Browse Source

scsi: qla2xxx: Fix mailbox failure while deleting Queue pairs

In target mode driver, queue pairs are not created during driver load
time, instead they are created at the configuration time after chip
reset.  If a user tries to load/unload driver after queue pairs are
created, then there would be mailbox failure, while deleting queue
pairs.  Flag is added to check if queue pairs are created or not. Queue
pairs will be deleted only If they were created during target
configuration.

Signed-off-by: Sawan Chandak <sawan.chandak@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Sawan Chandak 8 years ago
parent
commit
d65237c7f0

+ 2 - 0
drivers/scsi/qla2xxx/qla_def.h

@@ -3997,6 +3997,8 @@ typedef struct scsi_qla_host {
 		uint32_t	fw_tgt_reported:1;
 		uint32_t	fw_tgt_reported:1;
 		uint32_t	bbcr_enable:1;
 		uint32_t	bbcr_enable:1;
 		uint32_t	qpairs_available:1;
 		uint32_t	qpairs_available:1;
+		uint32_t	qpairs_req_created:1;
+		uint32_t	qpairs_rsp_created:1;
 	} flags;
 	} flags;
 
 
 	atomic_t	loop_state;
 	atomic_t	loop_state;

+ 8 - 2
drivers/scsi/qla2xxx/qla_init.c

@@ -7719,9 +7719,12 @@ fail_qid_map:
 
 
 int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
 int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
 {
 {
-	int ret;
+	int ret = QLA_FUNCTION_FAILED;
 	struct qla_hw_data *ha = qpair->hw;
 	struct qla_hw_data *ha = qpair->hw;
 
 
+	if (!vha->flags.qpairs_req_created && !vha->flags.qpairs_rsp_created)
+		goto fail;
+
 	qpair->delete_in_progress = 1;
 	qpair->delete_in_progress = 1;
 	while (atomic_read(&qpair->ref_count))
 	while (atomic_read(&qpair->ref_count))
 		msleep(500);
 		msleep(500);
@@ -7738,8 +7741,11 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
 	clear_bit(qpair->id, ha->qpair_qid_map);
 	clear_bit(qpair->id, ha->qpair_qid_map);
 	ha->num_qpairs--;
 	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;
+		vha->flags.qpairs_req_created = 0;
+		vha->flags.qpairs_rsp_created = 0;
+	}
 	mempool_destroy(qpair->srb_mempool);
 	mempool_destroy(qpair->srb_mempool);
 	kfree(qpair);
 	kfree(qpair);
 	mutex_unlock(&ha->mq_lock);
 	mutex_unlock(&ha->mq_lock);

+ 4 - 0
drivers/scsi/qla2xxx/qla_mid.c

@@ -645,6 +645,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
 	int ret = 0;
 	int ret = 0;
 	struct req_que *req = NULL;
 	struct req_que *req = NULL;
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+	struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
 	uint16_t que_id = 0;
 	uint16_t que_id = 0;
 	device_reg_t *reg;
 	device_reg_t *reg;
 	uint32_t cnt;
 	uint32_t cnt;
@@ -741,6 +742,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
 			mutex_unlock(&ha->mq_lock);
 			mutex_unlock(&ha->mq_lock);
 			goto que_failed;
 			goto que_failed;
 		}
 		}
+		vha->flags.qpairs_req_created = 1;
 	}
 	}
 
 
 	return req->id;
 	return req->id;
@@ -772,6 +774,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
 	int ret = 0;
 	int ret = 0;
 	struct rsp_que *rsp = NULL;
 	struct rsp_que *rsp = NULL;
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+	struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
 	uint16_t que_id = 0;
 	uint16_t que_id = 0;
 	device_reg_t *reg;
 	device_reg_t *reg;
 
 
@@ -855,6 +858,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
 			mutex_unlock(&ha->mq_lock);
 			mutex_unlock(&ha->mq_lock);
 			goto que_failed;
 			goto que_failed;
 		}
 		}
+		vha->flags.qpairs_rsp_created = 1;
 	}
 	}
 	rsp->req = NULL;
 	rsp->req = NULL;
 
 

+ 1 - 0
drivers/scsi/qla2xxx/qla_os.c

@@ -384,6 +384,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
 	ha->base_qpair->rsp = rsp;
 	ha->base_qpair->rsp = rsp;
 	ha->base_qpair->vha = vha;
 	ha->base_qpair->vha = vha;
 	ha->base_qpair->qp_lock_ptr = &ha->hardware_lock;
 	ha->base_qpair->qp_lock_ptr = &ha->hardware_lock;
+	/* init qpair to this cpu. Will adjust at run time. */
 	ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q];
 	ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q];
 	INIT_LIST_HEAD(&ha->base_qpair->hints_list);
 	INIT_LIST_HEAD(&ha->base_qpair->hints_list);
 	qla_cpu_update(rsp->qpair, smp_processor_id());
 	qla_cpu_update(rsp->qpair, smp_processor_id());