]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi: qla2xxx: Fix Target mode handling with Multiqueue changes.
authorQuinn Tran <quinn.tran@cavium.com>
Fri, 24 Feb 2017 16:33:44 +0000 (22:03 +0530)
committerDhaval Giani <dhaval.giani@oracle.com>
Thu, 9 Mar 2017 02:12:21 +0000 (21:12 -0500)
Orabug: 25477809

- Fix race condition between dpc_thread accessing Multiqueue resources
and qla2x00_remove_one thread trying to free resource.
- Fix out of order free for Multiqueue resources. Also, Multiqueue
interrupts needs a workqueue. Interrupt needed to stop before
the wq can be destroyed.

Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Somasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Dhaval Giani <dhaval.giani@oracle.com>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c

index dace70b3bbb8d4c8de19253cb94e07cc1e95f477..2362215d5a4b183c48d1c12320b404cc5f9e7541 100644 (file)
@@ -2722,7 +2722,8 @@ struct isp_operations {
 
 #define QLA_MSIX_DEFAULT               0x00
 #define QLA_MSIX_RSP_Q                 0x01
-#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q    0x02
+#define QLA_ATIO_VECTOR                0x02
+#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q    0x03
 
 #define QLA_MIDX_DEFAULT       0
 #define QLA_MIDX_RSP_Q         1
index 660ad03042421a60ca3d87b3b0e18bf4e8fa2b96..aab3c9707886d15cd7175ca1fd2230c44f4b7732 100644 (file)
@@ -6740,8 +6740,8 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha,
                qpair->id = qpair_id;
                qpair->vp_idx = vp_idx;
 
-               for (i = 0; i < ha->msix_count; i++) {
-                       msix = &ha->msix_entries[i + 2];
+               for (i = 2; i < ha->msix_count; i++) {
+                       msix = &ha->msix_entries[i];
                        if (msix->in_use)
                                continue;
                        qpair->msix = msix;
index fea638dc48349c4b3f6e6a94162b3ccf5003715c..e532700fe13bdb9fdbc50b2bed20ad07b5365f03 100644 (file)
@@ -2967,6 +2967,7 @@ struct qla_init_msix_entry {
 static struct qla_init_msix_entry msix_entries[] = {
        { "qla2xxx (default)", qla24xx_msix_default },
        { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
+       { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
        { "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q },
 };
 
@@ -2975,12 +2976,6 @@ static struct qla_init_msix_entry qla82xx_msix_entries[] = {
        { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
 };
 
-static struct qla_init_msix_entry qla83xx_msix_entries[] = {
-       { "qla2xxx (default)", qla24xx_msix_default },
-       { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
-       { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
-};
-
 static void
 qla24xx_disable_msix(struct qla_hw_data *ha)
 {
@@ -3008,7 +3003,6 @@ static int
 qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
 {
 #define MIN_MSIX_COUNT 2
-#define ATIO_VECTOR    2
        int i, ret;
        struct msix_entry *entries;
        struct qla_msix_entry *qentry;
@@ -3079,7 +3073,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
        }
 
        /* Enable MSI-X vectors for the base queue */
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < (QLA_MSIX_RSP_Q + 1); i++) {
                qentry = &ha->msix_entries[i];
                qentry->handle = rsp;
                rsp->msix = qentry;
@@ -3103,14 +3097,15 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
         * queue.
         */
        if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
-               qentry = &ha->msix_entries[ATIO_VECTOR];
+               qentry = &ha->msix_entries[QLA_ATIO_VECTOR];
                rsp->msix = qentry;
                qentry->handle = rsp;
                scnprintf(qentry->name, sizeof(qentry->name),
-                       qla83xx_msix_entries[ATIO_VECTOR].name);
+                       msix_entries[QLA_ATIO_VECTOR].name);
+               qentry->in_use = 1;
                ret = request_irq(qentry->vector,
-                       qla83xx_msix_entries[ATIO_VECTOR].handler,
-                       0, qla83xx_msix_entries[ATIO_VECTOR].name, rsp);
+                       msix_entries[QLA_ATIO_VECTOR].handler,
+                       0, msix_entries[QLA_ATIO_VECTOR].name, rsp);
                qentry->have_irq = 1;
 
                /* Register for CPU affinity notification. */
index 034c61c5bfe997b0027add03c995b1546c5a6f7b..2c88393de0c1b9ab08e11deb3a37a5d1c5714db5 100644 (file)
@@ -425,18 +425,31 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
        struct req_que *req;
        struct rsp_que *rsp;
        int cnt;
+       unsigned long flags;
 
+       spin_lock_irqsave(&ha->hardware_lock, flags);
        for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
                req = ha->req_q_map[cnt];
+                clear_bit(cnt, ha->req_qid_map);
+               ha->req_q_map[cnt] = NULL;
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
                qla2x00_free_req_que(ha, req);
+               spin_lock_irqsave(&ha->hardware_lock, flags);
        }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
        kfree(ha->req_q_map);
        ha->req_q_map = NULL;
 
+       spin_lock_irqsave(&ha->hardware_lock, flags);
        for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
                rsp = ha->rsp_q_map[cnt];
+                clear_bit(cnt, ha->req_qid_map);
+               ha->rsp_q_map[cnt] =  NULL;
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
                qla2x00_free_rsp_que(ha, rsp);
+               spin_lock_irqsave(&ha->hardware_lock, flags);
        }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
        kfree(ha->rsp_q_map);
        ha->rsp_q_map = NULL;
 }
@@ -1851,17 +1864,22 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
                pci_read_config_word(ha->pdev,
                    QLA_83XX_PCI_MSIX_CONTROL, &msix);
                ha->msix_count = msix + 1;
-               /* Max queues are bounded by available msix vectors */
-               /* queue 0 uses two msix vectors */
+               /*
+                * By default, driver uses at least two msix vectors
+                * (default & rspq)
+                */
                if (ql2xmqsupport) {
                        /* MB interrupt uses 1 vector */
                        ha->max_req_queues = ha->msix_count - 1;
                        ha->max_rsp_queues = ha->max_req_queues;
+
+                       /* ATIOQ needs 1 vector. That's 1 less QPair */
+                       if (QLA_TGT_MODE_ENABLED())
+                               ha->max_req_queues--;
+
                        /* Queue pairs is the max value minus
                         * the base queue pair */
                        ha->max_qpairs = ha->max_req_queues - 1;
-                       ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc010,
-                           "Max no of queues pairs: %d.\n", ha->max_qpairs);
                        ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0190,
                            "Max no of queues pairs: %d.\n", ha->max_qpairs);
                }
@@ -1873,6 +1891,8 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
 
 mqiobase_exit:
        ha->msix_count = ha->max_rsp_queues + 1;
+       if (QLA_TGT_MODE_ENABLED())
+               ha->msix_count++;
 
        qlt_83xx_iospace_config(ha);
 
@@ -3226,13 +3246,6 @@ qla2x00_delete_all_vps(struct qla_hw_data *ha, scsi_qla_host_t *base_vha)
 static void
 qla2x00_destroy_deferred_work(struct qla_hw_data *ha)
 {
-       /* Flush the work queue and remove it */
-       if (ha->wq) {
-               flush_workqueue(ha->wq);
-               destroy_workqueue(ha->wq);
-               ha->wq = NULL;
-       }
-
        /* Cancel all work and destroy DPC workqueues */
        if (ha->dpc_lp_wq) {
                cancel_work_sync(&ha->idc_aen);
@@ -3420,9 +3433,17 @@ qla2x00_free_device(scsi_qla_host_t *vha)
                ha->isp_ops->disable_intrs(ha);
        }
 
+       qla2x00_free_fcports(vha);
+
        qla2x00_free_irqs(vha);
 
-       qla2x00_free_fcports(vha);
+       /* Flush the work queue and remove it */
+       if (ha->wq) {
+               flush_workqueue(ha->wq);
+               destroy_workqueue(ha->wq);
+               ha->wq = NULL;
+       }
+
 
        qla2x00_mem_free(ha);
 
@@ -4994,8 +5015,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
 
        base_vha->flags.init_done = 0;
        qla25xx_delete_queues(base_vha);
-       qla2x00_free_irqs(base_vha);
        qla2x00_free_fcports(base_vha);
+       qla2x00_free_irqs(base_vha);
        qla2x00_mem_free(ha);
        qla82xx_md_free(base_vha);
        qla2x00_free_queues(ha);