From: Quinn Tran Date: Fri, 24 Feb 2017 16:33:44 +0000 (+0530) Subject: scsi: qla2xxx: Fix Target mode handling with Multiqueue changes. X-Git-Tag: v4.1.12-98.0.20170517_2143~42^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=5729c75713de3037132385f385a93c5b91f5b5f0;p=users%2Fjedix%2Flinux-maple.git scsi: qla2xxx: Fix Target mode handling with Multiqueue changes. 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 Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen Signed-off-by: Somasundaram Krishnasamy Reviewed-by: Martin K. Petersen Signed-off-by: Dhaval Giani --- diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index dace70b3bbb8..2362215d5a4b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -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 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 660ad0304242..aab3c9707886 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -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; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index fea638dc4834..e532700fe13b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -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. */ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 034c61c5bfe9..2c88393de0c1 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -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);