mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 12:20:52 +07:00
scsi: qla2xxx: Fix Target mode handling with Multiqueue changes.
- 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>
This commit is contained in:
parent
5601236b6f
commit
093df73771
@ -2734,7 +2734,8 @@ struct isp_operations {
|
|||||||
|
|
||||||
#define QLA_MSIX_DEFAULT 0x00
|
#define QLA_MSIX_DEFAULT 0x00
|
||||||
#define QLA_MSIX_RSP_Q 0x01
|
#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_DEFAULT 0
|
||||||
#define QLA_MIDX_RSP_Q 1
|
#define QLA_MIDX_RSP_Q 1
|
||||||
|
@ -6764,7 +6764,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
|
|||||||
qpair->vp_idx = vp_idx;
|
qpair->vp_idx = vp_idx;
|
||||||
|
|
||||||
for (i = 0; i < ha->msix_count; i++) {
|
for (i = 0; i < ha->msix_count; i++) {
|
||||||
msix = &ha->msix_entries[i + 2];
|
msix = &ha->msix_entries[i];
|
||||||
if (msix->in_use)
|
if (msix->in_use)
|
||||||
continue;
|
continue;
|
||||||
qpair->msix = msix;
|
qpair->msix = msix;
|
||||||
|
@ -3005,6 +3005,7 @@ struct qla_init_msix_entry {
|
|||||||
static struct qla_init_msix_entry msix_entries[] = {
|
static struct qla_init_msix_entry msix_entries[] = {
|
||||||
{ "qla2xxx (default)", qla24xx_msix_default },
|
{ "qla2xxx (default)", qla24xx_msix_default },
|
||||||
{ "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
|
{ "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
|
||||||
|
{ "qla2xxx (atio_q)", qla83xx_msix_atio_q },
|
||||||
{ "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q },
|
{ "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3013,17 +3014,10 @@ static struct qla_init_msix_entry qla82xx_msix_entries[] = {
|
|||||||
{ "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
|
{ "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 int
|
static int
|
||||||
qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
||||||
{
|
{
|
||||||
#define MIN_MSIX_COUNT 2
|
#define MIN_MSIX_COUNT 2
|
||||||
#define ATIO_VECTOR 2
|
|
||||||
int i, ret;
|
int i, ret;
|
||||||
struct qla_msix_entry *qentry;
|
struct qla_msix_entry *qentry;
|
||||||
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
|
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
|
||||||
@ -3080,7 +3074,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Enable MSI-X vectors for the base queue */
|
/* 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 = &ha->msix_entries[i];
|
||||||
qentry->handle = rsp;
|
qentry->handle = rsp;
|
||||||
rsp->msix = qentry;
|
rsp->msix = qentry;
|
||||||
@ -3097,6 +3091,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto msix_register_fail;
|
goto msix_register_fail;
|
||||||
qentry->have_irq = 1;
|
qentry->have_irq = 1;
|
||||||
|
qentry->in_use = 1;
|
||||||
|
|
||||||
/* Register for CPU affinity notification. */
|
/* Register for CPU affinity notification. */
|
||||||
irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
|
irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
|
||||||
@ -3116,14 +3111,15 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||||||
* queue.
|
* queue.
|
||||||
*/
|
*/
|
||||||
if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
|
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;
|
rsp->msix = qentry;
|
||||||
qentry->handle = rsp;
|
qentry->handle = rsp;
|
||||||
scnprintf(qentry->name, sizeof(qentry->name),
|
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,
|
ret = request_irq(qentry->vector,
|
||||||
qla83xx_msix_entries[ATIO_VECTOR].handler,
|
msix_entries[QLA_ATIO_VECTOR].handler,
|
||||||
0, qla83xx_msix_entries[ATIO_VECTOR].name, rsp);
|
0, msix_entries[QLA_ATIO_VECTOR].name, rsp);
|
||||||
qentry->have_irq = 1;
|
qentry->have_irq = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,24 +439,41 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
|
|||||||
struct req_que *req;
|
struct req_que *req;
|
||||||
struct rsp_que *rsp;
|
struct rsp_que *rsp;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
|
for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
|
||||||
if (!test_bit(cnt, ha->req_qid_map))
|
if (!test_bit(cnt, ha->req_qid_map))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
req = ha->req_q_map[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);
|
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);
|
kfree(ha->req_q_map);
|
||||||
ha->req_q_map = NULL;
|
ha->req_q_map = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
|
for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
|
||||||
if (!test_bit(cnt, ha->rsp_qid_map))
|
if (!test_bit(cnt, ha->rsp_qid_map))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rsp = ha->rsp_q_map[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);
|
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);
|
kfree(ha->rsp_q_map);
|
||||||
ha->rsp_q_map = NULL;
|
ha->rsp_q_map = NULL;
|
||||||
}
|
}
|
||||||
@ -1890,17 +1907,22 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
|
|||||||
pci_read_config_word(ha->pdev,
|
pci_read_config_word(ha->pdev,
|
||||||
QLA_83XX_PCI_MSIX_CONTROL, &msix);
|
QLA_83XX_PCI_MSIX_CONTROL, &msix);
|
||||||
ha->msix_count = msix + 1;
|
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) {
|
if (ql2xmqsupport) {
|
||||||
/* MB interrupt uses 1 vector */
|
/* MB interrupt uses 1 vector */
|
||||||
ha->max_req_queues = ha->msix_count - 1;
|
ha->max_req_queues = ha->msix_count - 1;
|
||||||
ha->max_rsp_queues = ha->max_req_queues;
|
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
|
/* Queue pairs is the max value minus
|
||||||
* the base queue pair */
|
* the base queue pair */
|
||||||
ha->max_qpairs = ha->max_req_queues - 1;
|
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,
|
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0190,
|
||||||
"Max no of queues pairs: %d.\n", ha->max_qpairs);
|
"Max no of queues pairs: %d.\n", ha->max_qpairs);
|
||||||
}
|
}
|
||||||
@ -1912,6 +1934,8 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
|
|||||||
|
|
||||||
mqiobase_exit:
|
mqiobase_exit:
|
||||||
ha->msix_count = ha->max_rsp_queues + 1;
|
ha->msix_count = ha->max_rsp_queues + 1;
|
||||||
|
if (QLA_TGT_MODE_ENABLED())
|
||||||
|
ha->msix_count++;
|
||||||
|
|
||||||
qlt_83xx_iospace_config(ha);
|
qlt_83xx_iospace_config(ha);
|
||||||
|
|
||||||
@ -2989,7 +3013,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
host->can_queue, base_vha->req,
|
host->can_queue, base_vha->req,
|
||||||
base_vha->mgmt_svr_loop_id, host->sg_tablesize);
|
base_vha->mgmt_svr_loop_id, host->sg_tablesize);
|
||||||
|
|
||||||
if (ha->mqenable) {
|
if (ha->mqenable && qla_ini_mode_enabled(base_vha)) {
|
||||||
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
|
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
|
||||||
/* Create start of day qpairs for Block MQ */
|
/* Create start of day qpairs for Block MQ */
|
||||||
if (shost_use_blk_mq(host)) {
|
if (shost_use_blk_mq(host)) {
|
||||||
@ -3263,13 +3287,6 @@ qla2x00_delete_all_vps(struct qla_hw_data *ha, scsi_qla_host_t *base_vha)
|
|||||||
static void
|
static void
|
||||||
qla2x00_destroy_deferred_work(struct qla_hw_data *ha)
|
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 */
|
/* Cancel all work and destroy DPC workqueues */
|
||||||
if (ha->dpc_lp_wq) {
|
if (ha->dpc_lp_wq) {
|
||||||
cancel_work_sync(&ha->idc_aen);
|
cancel_work_sync(&ha->idc_aen);
|
||||||
@ -3465,9 +3482,17 @@ qla2x00_free_device(scsi_qla_host_t *vha)
|
|||||||
ha->isp_ops->disable_intrs(ha);
|
ha->isp_ops->disable_intrs(ha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qla2x00_free_fcports(vha);
|
||||||
|
|
||||||
qla2x00_free_irqs(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);
|
qla2x00_mem_free(ha);
|
||||||
|
|
||||||
@ -5187,8 +5212,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
|
|||||||
|
|
||||||
base_vha->flags.init_done = 0;
|
base_vha->flags.init_done = 0;
|
||||||
qla25xx_delete_queues(base_vha);
|
qla25xx_delete_queues(base_vha);
|
||||||
qla2x00_free_irqs(base_vha);
|
|
||||||
qla2x00_free_fcports(base_vha);
|
qla2x00_free_fcports(base_vha);
|
||||||
|
qla2x00_free_irqs(base_vha);
|
||||||
qla2x00_mem_free(ha);
|
qla2x00_mem_free(ha);
|
||||||
qla82xx_md_free(base_vha);
|
qla82xx_md_free(base_vha);
|
||||||
qla2x00_free_queues(ha);
|
qla2x00_free_queues(ha);
|
||||||
|
Loading…
Reference in New Issue
Block a user