[SCSI] qla2xxx: Unload hangs after issuing BSG commands to vport.
authorChad Dupuis <chad.dupuis@qlogic.com>
Fri, 8 Feb 2013 06:57:50 +0000 (01:57 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 22 Feb 2013 12:35:40 +0000 (12:35 +0000)
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: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_os.c

index 525c339..79babab 100644 (file)
@@ -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 @@ done:
        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;
 }
index 97f2684..7568324 100644 (file)
@@ -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 -------------------------------------- */
index deb8618..130f6f3 100644 (file)
@@ -198,6 +198,13 @@ done:
 }
 
 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)
 {
        init_timer(&sp->u.iocb_cmd.timer);
index 9e3ae1d..33fb217 100644 (file)
@@ -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;