Commit b00ee7d7 authored by Chad Dupuis's avatar Chad Dupuis Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Unload hangs after issuing BSG commands to vport.



BSG code path increments ref count in the send path, but does not
decrement in the return path leading to hang during unload of the
driver.

Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarSaurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 619d5a0d
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ void
qla2x00_bsg_sp_free(void *data, void *ptr)
{
	srb_t *sp = (srb_t *)ptr;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
	struct scsi_qla_host *vha = sp->fcport->vha;
	struct fc_bsg_job *bsg_job = sp->u.bsg_job;
	struct qla_hw_data *ha = vha->hw;

@@ -40,7 +40,7 @@ qla2x00_bsg_sp_free(void *data, void *ptr)
	if (sp->type == SRB_CT_CMD ||
	    sp->type == SRB_ELS_CMD_HST)
		kfree(sp->fcport);
	mempool_free(sp, vha->hw->srb_mempool);
	qla2x00_rel_sp(vha, sp);
}

int
@@ -368,7 +368,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
	if (rval != QLA_SUCCESS) {
		ql_log(ql_log_warn, vha, 0x700e,
		    "qla2x00_start_sp failed = %d\n", rval);
		mempool_free(sp, ha->srb_mempool);
		qla2x00_rel_sp(vha, sp);
		rval = -EIO;
		goto done_unmap_sg;
	}
@@ -515,7 +515,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
	if (rval != QLA_SUCCESS) {
		ql_log(ql_log_warn, vha, 0x7017,
		    "qla2x00_start_sp failed=%d.\n", rval);
		mempool_free(sp, ha->srb_mempool);
		qla2x00_rel_sp(vha, sp);
		rval = -EIO;
		goto done_free_fcport;
	}
@@ -1995,6 +1995,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
	if (bsg_job->request->msgcode == FC_BSG_HST_CT)
		kfree(sp->fcport);
	mempool_free(sp, ha->srb_mempool);
	qla2x00_rel_sp(vha, sp);
	return 0;
}
+1 −3
Original line number Diff line number Diff line
@@ -70,9 +70,7 @@ qla2x00_sp_free(void *data, void *ptr)
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;

	del_timer(&iocb->timer);
	mempool_free(sp, vha->hw->srb_mempool);

	QLA_VHA_MARK_NOT_BUSY(vha);
	qla2x00_rel_sp(vha, sp);
}

/* Asynchronous Login/Logout Routines -------------------------------------- */
+7 −0
Original line number Diff line number Diff line
@@ -197,6 +197,13 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
	return sp;
}

static inline void
qla2x00_rel_sp(scsi_qla_host_t *vha, srb_t *sp)
{
	mempool_free(sp, vha->hw->srb_mempool);
	QLA_VHA_MARK_NOT_BUSY(vha);
}

static inline void
qla2x00_init_timer(srb_t *sp, unsigned long tmo)
{
+2 −2
Original line number Diff line number Diff line
@@ -630,7 +630,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr)
	}

	CMD_SP(cmd) = NULL;
	mempool_free(sp, ha->srb_mempool);
	qla2x00_rel_sp(sp->fcport->vha, sp);
}

static void
@@ -718,7 +718,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
		goto qc24_target_busy;
	}

	sp = qla2x00_get_sp(base_vha, fcport, GFP_ATOMIC);
	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
	if (!sp) {
		set_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags);
		goto qc24_host_busy;