Commit b95b9452 authored by Sawan Chandak's avatar Sawan Chandak Committed by Martin K. Petersen

scsi: qla2xxx: Fix crash due to mismatch mumber of Q-pair creation for Multi queue

when driver is loaded with Multi Queue enabled, it was noticed that
there was one less queue pair created.

Following message would indicate this:

"No resources to create additional q pair."

The result of one less queue pair means that system can crash, if the
block mq layer thinks there is an extra hardware queue available, and
the driver will use a NULL ptr qpair in that instance.

Following stack trace is seen in one of the crash:

irq_create_affinity_masks+0x98/0x530
irq_create_affinity_masks+0x98/0x530
__pci_enable_msix+0x321/0x4e0
mutex_lock+0x12/0x40
pci_alloc_irq_vectors_affinity+0xb5/0x140
qla24xx_enable_msix+0x79/0x530 [qla2xxx]
qla2x00_request_irqs+0x61/0x2d0 [qla2xxx]
qla2x00_probe_one+0xc73/0x2390 [qla2xxx]
ida_simple_get+0x98/0x100
kernfs_next_descendant_post+0x40/0x50
local_pci_probe+0x45/0xa0
pci_device_probe+0xfc/0x140
driver_probe_device+0x2c5/0x470
__driver_attach+0xdd/0xe0
driver_probe_device+0x470/0x470
bus_for_each_dev+0x6c/0xc0
driver_attach+0x1e/0x20
bus_add_driver+0x45/0x270
driver_register+0x60/0xe0
__pci_register_driver+0x4c/0x50
qla2x00_module_init+0x1ce/0x21e [qla2xxx]

Cc: <stable@vger.kernel.org> # v4.10+
Signed-off-by: default avatarSawan Chandak <sawan.chandak@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 0ea88662
...@@ -3425,6 +3425,7 @@ struct qla_hw_data { ...@@ -3425,6 +3425,7 @@ struct qla_hw_data {
uint8_t max_req_queues; uint8_t max_req_queues;
uint8_t max_rsp_queues; uint8_t max_rsp_queues;
uint8_t max_qpairs; uint8_t max_qpairs;
uint8_t num_qpairs;
struct qla_qpair *base_qpair; struct qla_qpair *base_qpair;
struct qla_npiv_entry *npiv_info; struct qla_npiv_entry *npiv_info;
uint16_t nvram_npiv_size; uint16_t nvram_npiv_size;
......
...@@ -7543,12 +7543,13 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v ...@@ -7543,12 +7543,13 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
/* Assign available que pair id */ /* Assign available que pair id */
mutex_lock(&ha->mq_lock); mutex_lock(&ha->mq_lock);
qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs); qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs);
if (qpair_id >= ha->max_qpairs) { if (ha->num_qpairs >= ha->max_qpairs) {
mutex_unlock(&ha->mq_lock); mutex_unlock(&ha->mq_lock);
ql_log(ql_log_warn, vha, 0x0183, ql_log(ql_log_warn, vha, 0x0183,
"No resources to create additional q pair.\n"); "No resources to create additional q pair.\n");
goto fail_qid_map; goto fail_qid_map;
} }
ha->num_qpairs++;
set_bit(qpair_id, ha->qpair_qid_map); set_bit(qpair_id, ha->qpair_qid_map);
ha->queue_pair_map[qpair_id] = qpair; ha->queue_pair_map[qpair_id] = qpair;
qpair->id = qpair_id; qpair->id = qpair_id;
...@@ -7635,6 +7636,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v ...@@ -7635,6 +7636,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
fail_msix: fail_msix:
ha->queue_pair_map[qpair_id] = NULL; ha->queue_pair_map[qpair_id] = NULL;
clear_bit(qpair_id, ha->qpair_qid_map); clear_bit(qpair_id, ha->qpair_qid_map);
ha->num_qpairs--;
mutex_unlock(&ha->mq_lock); mutex_unlock(&ha->mq_lock);
fail_qid_map: fail_qid_map:
kfree(qpair); kfree(qpair);
...@@ -7660,6 +7662,7 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair) ...@@ -7660,6 +7662,7 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
mutex_lock(&ha->mq_lock); mutex_lock(&ha->mq_lock);
ha->queue_pair_map[qpair->id] = NULL; ha->queue_pair_map[qpair->id] = NULL;
clear_bit(qpair->id, ha->qpair_qid_map); clear_bit(qpair->id, ha->qpair_qid_map);
ha->num_qpairs--;
list_del(&qpair->qp_list_elem); list_del(&qpair->qp_list_elem);
if (list_empty(&vha->qp_list)) if (list_empty(&vha->qp_list))
vha->flags.qpairs_available = 0; vha->flags.qpairs_available = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment