Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7459527 authored by Michael Hernandez's avatar Michael Hernandez Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Add multiple queue pair functionality.



Replaced existing multiple queue functionality with framework
that allows for the creation of pairs of request and response queues,
either at start of day or dynamically.

Queue pair creation depend on module parameter "ql2xmqsupport",
which need to be enabled to create queue pair.

Signed-off-by: default avatarSawan Chandak <sawan.chandak@cavium.com>
Signed-off-by: default avatarMichael Hernandez <michael.hernandez@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 4fa18345
Loading
Loading
Loading
Loading
+15 −21
Original line number Diff line number Diff line
@@ -1988,9 +1988,9 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
	scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
	scsi_qla_host_t *vha = NULL;
	struct qla_hw_data *ha = base_vha->hw;
	uint16_t options = 0;
	int	cnt;
	struct req_que *req = ha->req_q_map[0];
	struct qla_qpair *qpair;

	ret = qla24xx_vport_create_req_sanity_check(fc_vport);
	if (ret) {
@@ -2075,15 +2075,9 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
	qlt_vport_create(vha, ha);
	qla24xx_vport_disable(fc_vport, disable);

	if (ha->flags.cpu_affinity_enabled) {
		req = ha->req_q_map[1];
		ql_dbg(ql_dbg_multiq, vha, 0xc000,
		    "Request queue %p attached with "
		    "VP[%d], cpu affinity =%d\n",
		    req, vha->vp_idx, ha->flags.cpu_affinity_enabled);
		goto vport_queue;
	} else if (ql2xmaxqueues == 1 || !ha->npiv_info)
	if (!ql2xmqsupport || !ha->npiv_info)
		goto vport_queue;

	/* Create a request queue in QoS mode for the vport */
	for (cnt = 0; cnt < ha->nvram_npiv_size; cnt++) {
		if (memcmp(ha->npiv_info[cnt].port_name, vha->port_name, 8) == 0
@@ -2095,20 +2089,20 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
	}

	if (qos) {
		ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, 0,
			qos);
		if (!ret)
		qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx);
		if (!qpair)
			ql_log(ql_log_warn, vha, 0x7084,
			    "Can't create request queue for VP[%d]\n",
			    "Can't create qpair for VP[%d]\n",
			    vha->vp_idx);
		else {
			ql_dbg(ql_dbg_multiq, vha, 0xc001,
			    "Request Que:%d Q0s: %d) created for VP[%d]\n",
			    ret, qos, vha->vp_idx);
			    "Queue pair: %d Qos: %d) created for VP[%d]\n",
			    qpair->id, qos, vha->vp_idx);
			ql_dbg(ql_dbg_user, vha, 0x7085,
			    "Request Que:%d Q0s: %d) created for VP[%d]\n",
			    ret, qos, vha->vp_idx);
			req = ha->req_q_map[ret];
			    "Queue Pair: %d Qos: %d) created for VP[%d]\n",
			    qpair->id, qos, vha->vp_idx);
			req = qpair->req;
			vha->qpair = qpair;
		}
	}

@@ -2162,10 +2156,10 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
	clear_bit(vha->vp_idx, ha->vp_idx_map);
	mutex_unlock(&ha->vport_lock);

	if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
		if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
	if (vha->qpair->vp_idx == vha->vp_idx) {
		if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
			ql_log(ql_log_warn, vha, 0x7087,
			    "Queue delete failed.\n");
			    "Queue Pair delete failed.\n");
	}

	ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id);
+2 −2
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@
 * ----------------------------------------------------------------------
 * |             Level            |   Last Value Used  |     Holes	|
 * ----------------------------------------------------------------------
 * | Module Init and Probe        |       0x0191       | 0x0146         |
 * | Module Init and Probe        |       0x0193       | 0x0146         |
 * |                              |                    | 0x015b-0x0160	|
 * |                              |                    | 0x016e		|
 * | Mailbox commands             |       0x1199       | 0x1193		|
@@ -58,7 +58,7 @@
 * |                              |                    | 0xb13a,0xb142  |
 * |                              |                    | 0xb13c-0xb140  |
 * |                              |                    | 0xb149		|
 * | MultiQ                       |       0xc00c       |		|
 * | MultiQ                       |       0xc010       |		|
 * | Misc                         |       0xd301       | 0xd031-0xd0ff	|
 * |                              |                    | 0xd101-0xd1fe	|
 * |                              |                    | 0xd214-0xd2fe	|
+90 −15
Original line number Diff line number Diff line
@@ -401,6 +401,7 @@ typedef struct srb {
	uint16_t type;
	char *name;
	int iocbs;
	struct qla_qpair *qpair;
	union {
		struct srb_iocb iocb_cmd;
		struct bsg_job *bsg_job;
@@ -2719,6 +2720,7 @@ struct isp_operations {

	int (*get_flash_version) (struct scsi_qla_host *, void *);
	int (*start_scsi) (srb_t *);
	int (*start_scsi_mq) (srb_t *);
	int (*abort_isp) (struct scsi_qla_host *);
	int (*iospace_config)(struct qla_hw_data*);
	int (*initialize_adapter)(struct scsi_qla_host *);
@@ -2732,6 +2734,7 @@ struct isp_operations {

#define QLA_MSIX_DEFAULT		0x00
#define QLA_MSIX_RSP_Q			0x01
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q	0x02

#define QLA_MIDX_DEFAULT	0
#define QLA_MIDX_RSP_Q		1
@@ -2745,8 +2748,10 @@ struct scsi_qla_host;

struct qla_msix_entry {
	int have_irq;
	int in_use;
	uint32_t vector;
	uint16_t entry;
	char name[30];
	void *handle;
	struct irq_affinity_notify irq_notify;
	int cpuid;
@@ -2872,7 +2877,6 @@ struct rsp_que {
	struct qla_msix_entry *msix;
	struct req_que *req;
	srb_t *status_srb; /* status continuation entry */
	struct work_struct q_work;

	dma_addr_t  dma_fx00;
	response_t *ring_fx00;
@@ -2909,6 +2913,37 @@ struct req_que {
	uint8_t req_pkt[REQUEST_ENTRY_SIZE];
};

/*Queue pair data structure */
struct qla_qpair {
	spinlock_t qp_lock;
	atomic_t ref_count;
	/* distill these fields down to 'online=0/1'
	 * ha->flags.eeh_busy
	 * ha->flags.pci_channel_io_perm_failure
	 * base_vha->loop_state
	 */
	uint32_t online:1;
	/* move vha->flags.difdix_supported here */
	uint32_t difdix_supported:1;
	uint32_t delete_in_progress:1;

	uint16_t id;			/* qp number used with FW */
	uint16_t num_active_cmd;	/* cmds down at firmware */
	cpumask_t cpu_mask; /* CPU mask for cpu affinity operation */
	uint16_t vp_idx;		/* vport ID */

	mempool_t *srb_mempool;

	/* to do: New driver: move queues to here instead of pointers */
	struct req_que *req;
	struct rsp_que *rsp;
	struct atio_que *atio;
	struct qla_msix_entry *msix; /* point to &ha->msix_entries[x] */
	struct qla_hw_data *hw;
	struct work_struct q_work;
	struct list_head qp_list_elem; /* vha->qp_list */
};

/* Place holder for FW buffer parameters */
struct qlfc_fw {
	void *fw_buf;
@@ -3004,7 +3039,6 @@ struct qla_hw_data {
		uint32_t	chip_reset_done		:1;
		uint32_t	running_gold_fw		:1;
		uint32_t	eeh_busy		:1;
		uint32_t	cpu_affinity_enabled	:1;
		uint32_t	disable_msix_handshake	:1;
		uint32_t	fcp_prio_enabled	:1;
		uint32_t	isp82xx_fw_hung:1;
@@ -3061,10 +3095,15 @@ struct qla_hw_data {
	uint8_t         mqenable;
	struct req_que **req_q_map;
	struct rsp_que **rsp_q_map;
	struct qla_qpair **queue_pair_map;
	unsigned long req_qid_map[(QLA_MAX_QUEUES / 8) / sizeof(unsigned long)];
	unsigned long rsp_qid_map[(QLA_MAX_QUEUES / 8) / sizeof(unsigned long)];
	unsigned long qpair_qid_map[(QLA_MAX_QUEUES / 8)
		/ sizeof(unsigned long)];
	uint8_t 	max_req_queues;
	uint8_t 	max_rsp_queues;
	uint8_t		max_qpairs;
	struct qla_qpair *base_qpair;
	struct qla_npiv_entry *npiv_info;
	uint16_t	nvram_npiv_size;

@@ -3328,6 +3367,7 @@ struct qla_hw_data {

	struct mutex vport_lock;        /* Virtual port synchronization */
	spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */
	struct mutex mq_lock;        /* multi-queue synchronization */
	struct completion mbx_cmd_comp; /* Serialize mbx access */
	struct completion mbx_intr_comp;  /* Used for completion notification */
	struct completion dcbx_comp;	/* For set port config notification */
@@ -3608,6 +3648,7 @@ typedef struct scsi_qla_host {

		uint32_t	fw_tgt_reported:1;
		uint32_t	bbcr_enable:1;
		uint32_t	qpairs_available:1;
	} flags;

	atomic_t	loop_state;
@@ -3646,6 +3687,7 @@ typedef struct scsi_qla_host {
#define FX00_TARGET_SCAN	24
#define FX00_CRITEMP_RECOVERY	25
#define FX00_HOST_INFO_RESEND	26
#define QPAIR_ONLINE_CHECK_NEEDED	27

	unsigned long	pci_flags;
#define PFLG_DISCONNECTED	0	/* PCI device removed */
@@ -3704,10 +3746,13 @@ typedef struct scsi_qla_host {
	/* List of pending PLOGI acks, protected by hw lock */
	struct list_head	plogi_ack_list;

	struct list_head	qp_list;

	uint32_t	vp_abort_cnt;

	struct fc_vport	*fc_vport;	/* holds fc_vport * for each vport */
	uint16_t        vp_idx;		/* vport ID */
	struct qla_qpair *qpair;	/* base qpair */

	unsigned long		vp_flags;
#define VP_IDX_ACQUIRED		0	/* bit no 0 */
@@ -3763,6 +3808,23 @@ struct qla_tgt_vp_map {
	scsi_qla_host_t *vha;
};

struct qla2_sgx {
	dma_addr_t		dma_addr;	/* OUT */
	uint32_t		dma_len;	/* OUT */

	uint32_t		tot_bytes;	/* IN */
	struct scatterlist	*cur_sg;	/* IN */

	/* for book keeping, bzero on initial invocation */
	uint32_t		bytes_consumed;
	uint32_t		num_bytes;
	uint32_t		tot_partial;

	/* for debugging */
	uint32_t		num_sg;
	srb_t			*sp;
};

/*
 * Macros to help code, maintain, etc.
 */
@@ -3786,10 +3848,23 @@ struct qla_tgt_vp_map {
	}						\
} while (0)

#define QLA_VHA_MARK_NOT_BUSY(__vha) do {		     \
#define QLA_VHA_MARK_NOT_BUSY(__vha)			\
	atomic_dec(&__vha->vref_count);			\

#define QLA_QPAIR_MARK_BUSY(__qpair, __bail) do {	\
	atomic_inc(&__qpair->ref_count);		\
	mb();						\
	if (__qpair->delete_in_progress) {		\
		atomic_dec(&__qpair->ref_count);	\
		__bail = 1;				\
	} else {					\
	       __bail = 0;				\
	}						\
} while (0)

#define QLA_QPAIR_MARK_NOT_BUSY(__qpair)		\
	atomic_dec(&__qpair->ref_count);		\

/*
 * qla2x00 local function return status codes
 */
+23 −5
Original line number Diff line number Diff line
@@ -91,12 +91,17 @@ extern int
qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
extern int qla2x00_init_rings(scsi_qla_host_t *);
extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
	int, int);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);

/*
 * Global Data in qla_os.c source file.
 */
extern char qla2x00_version_str[];

extern struct kmem_cache *srb_cachep;

extern int ql2xlogintimeout;
extern int qlport_down_retry;
extern int ql2xplogiabsentdevice;
@@ -105,8 +110,7 @@ extern int ql2xfdmienable;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
extern int ql2xiidmaenable;
extern int ql2xmaxqueues;
extern int ql2xmultique_tag;
extern int ql2xmqsupport;
extern int ql2xfwloadbin;
extern int ql2xetsenable;
extern int ql2xshiftctondsd;
@@ -172,6 +176,9 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);

extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
extern void qla2x00_sp_compl(void *, void *, int);
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
extern void qla2xxx_qpair_sp_compl(void *, void *, int);

/*
 * Global Functions in qla_mid.c source file.
@@ -220,6 +227,8 @@ extern uint16_t qla2x00_calc_iocbs_32(uint16_t);
extern uint16_t qla2x00_calc_iocbs_64(uint16_t);
extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t);
extern void qla2x00_build_scsi_iocbs_64(srb_t *, cmd_entry_t *, uint16_t);
extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *,
	uint16_t, struct req_que *);
extern int qla2x00_start_scsi(srb_t *sp);
extern int qla24xx_start_scsi(srb_t *sp);
int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
@@ -227,6 +236,7 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
extern int qla2x00_start_sp(srb_t *);
extern int qla24xx_dif_start_scsi(srb_t *);
extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
extern int qla2xxx_dif_start_scsi_mq(srb_t *);
extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);

extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
@@ -237,7 +247,10 @@ extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
	uint32_t *, uint16_t, struct qla_tgt_cmd *);
extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
	uint32_t *, uint16_t, struct qla_tgt_cmd *);

extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
	struct cmd_type_crc_2 *, uint16_t, uint16_t, uint16_t);

/*
 * Global Function Prototypes in qla_mbx.c source file.
@@ -468,6 +481,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *, const char *, struct req_que *,
extern void
qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *,
	uint32_t);
extern irqreturn_t
qla2xxx_msix_rsp_q(int irq, void *dev_id);

/*
 * Global Function Prototypes in qla_sup.c source file.
@@ -603,15 +618,18 @@ extern int qla2x00_dfs_setup(scsi_qla_host_t *);
extern int qla2x00_dfs_remove(scsi_qla_host_t *);

/* Globa function prototypes for multi-q */
extern int qla25xx_request_irq(struct rsp_que *);
extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *,
	struct qla_msix_entry *, int);
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
	uint16_t, int, uint8_t);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
	uint16_t, int);
	uint16_t, struct qla_qpair *);

extern void qla2x00_init_response_q_entries(struct rsp_que *);
extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_delete_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_delete_queues(struct scsi_qla_host *);
extern uint16_t qla24xx_rd_req_reg(struct qla_hw_data *, uint16_t);
extern uint16_t qla25xx_rd_req_reg(struct qla_hw_data *, uint16_t);
+164 −9
Original line number Diff line number Diff line
@@ -1769,8 +1769,7 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
	if (req->outstanding_cmds)
		return QLA_SUCCESS;

	if (!IS_FWI2_CAPABLE(ha) || (ha->mqiobase &&
	    (ql2xmultique_tag || ql2xmaxqueues > 1)))
	if (!IS_FWI2_CAPABLE(ha))
		req->num_outstanding_cmds = DEFAULT_OUTSTANDING_COMMANDS;
	else {
		if (ha->cur_fw_xcb_count <= ha->cur_fw_iocb_count)
@@ -4248,9 +4247,6 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
	struct req_que *req;
	struct rsp_que *rsp;

	if (vha->hw->flags.cpu_affinity_enabled)
		req = vha->hw->req_q_map[0];
	else
	req = vha->req;
	rsp = req->rsp;

@@ -6040,10 +6036,10 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
		return -EINVAL;

	rval = qla2x00_fw_ready(base_vha);
	if (ha->flags.cpu_affinity_enabled)
		req = ha->req_q_map[0];
	if (vha->qpair)
		req = vha->qpair->req;
	else
		req = vha->req;
		req = ha->req_q_map[0];
	rsp = req->rsp;

	if (rval == QLA_SUCCESS) {
@@ -6725,3 +6721,162 @@ qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)

	return ret;
}

struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int vp_idx)
{
	int rsp_id = 0;
	int  req_id = 0;
	int i;
	struct qla_hw_data *ha = vha->hw;
	uint16_t qpair_id = 0;
	struct qla_qpair *qpair = NULL;
	struct qla_msix_entry *msix;

	if (!(ha->fw_attributes & BIT_6) || !ha->flags.msix_enabled) {
		ql_log(ql_log_warn, vha, 0x00181,
		    "FW/Driver is not multi-queue capable.\n");
		return NULL;
	}

	if (ql2xmqsupport) {
		qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL);
		if (qpair == NULL) {
			ql_log(ql_log_warn, vha, 0x0182,
			    "Failed to allocate memory for queue pair.\n");
			return NULL;
		}
		memset(qpair, 0, sizeof(struct qla_qpair));

		qpair->hw = vha->hw;

		/* Assign available que pair id */
		mutex_lock(&ha->mq_lock);
		qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs);
		if (qpair_id >= ha->max_qpairs) {
			mutex_unlock(&ha->mq_lock);
			ql_log(ql_log_warn, vha, 0x0183,
			    "No resources to create additional q pair.\n");
			goto fail_qid_map;
		}
		set_bit(qpair_id, ha->qpair_qid_map);
		ha->queue_pair_map[qpair_id] = qpair;
		qpair->id = qpair_id;
		qpair->vp_idx = vp_idx;

		for (i = 0; i < ha->msix_count; i++) {
			msix = &ha->msix_entries[i + 2];
			if (msix->in_use)
				continue;
			qpair->msix = msix;
			ql_log(ql_dbg_multiq, vha, 0xc00f,
			    "Vector %x selected for qpair\n", msix->vector);
			break;
		}
		if (!qpair->msix) {
			ql_log(ql_log_warn, vha, 0x0184,
			    "Out of MSI-X vectors!.\n");
			goto fail_msix;
		}

		qpair->msix->in_use = 1;
		list_add_tail(&qpair->qp_list_elem, &vha->qp_list);

		mutex_unlock(&ha->mq_lock);

		/* Create response queue first */
		rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair);
		if (!rsp_id) {
			ql_log(ql_log_warn, vha, 0x0185,
			    "Failed to create response queue.\n");
			goto fail_rsp;
		}

		qpair->rsp = ha->rsp_q_map[rsp_id];

		/* Create request queue */
		req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos);
		if (!req_id) {
			ql_log(ql_log_warn, vha, 0x0186,
			    "Failed to create request queue.\n");
			goto fail_req;
		}

		qpair->req = ha->req_q_map[req_id];
		qpair->rsp->req = qpair->req;

		if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
			if (ha->fw_attributes & BIT_4)
				qpair->difdix_supported = 1;
		}

		qpair->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
		if (!qpair->srb_mempool) {
			ql_log(ql_log_warn, vha, 0x0191,
			    "Failed to create srb mempool for qpair %d\n",
			    qpair->id);
			goto fail_mempool;
		}

		/* Mark as online */
		qpair->online = 1;

		if (!vha->flags.qpairs_available)
			vha->flags.qpairs_available = 1;

		ql_dbg(ql_dbg_multiq, vha, 0xc00d,
		    "Request/Response queue pair created, id %d\n",
		    qpair->id);
		ql_dbg(ql_dbg_init, vha, 0x0187,
		    "Request/Response queue pair created, id %d\n",
		    qpair->id);
	}
	return qpair;

fail_mempool:
fail_req:
	qla25xx_delete_rsp_que(vha, qpair->rsp);
fail_rsp:
	mutex_lock(&ha->mq_lock);
	qpair->msix->in_use = 0;
	list_del(&qpair->qp_list_elem);
	if (list_empty(&vha->qp_list))
		vha->flags.qpairs_available = 0;
fail_msix:
	ha->queue_pair_map[qpair_id] = NULL;
	clear_bit(qpair_id, ha->qpair_qid_map);
	mutex_unlock(&ha->mq_lock);
fail_qid_map:
	kfree(qpair);
	return NULL;
}

int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
{
	int ret;
	struct qla_hw_data *ha = qpair->hw;

	qpair->delete_in_progress = 1;
	while (atomic_read(&qpair->ref_count))
		msleep(500);

	ret = qla25xx_delete_req_que(vha, qpair->req);
	if (ret != QLA_SUCCESS)
		goto fail;
	ret = qla25xx_delete_rsp_que(vha, qpair->rsp);
	if (ret != QLA_SUCCESS)
		goto fail;

	mutex_lock(&ha->mq_lock);
	ha->queue_pair_map[qpair->id] = NULL;
	clear_bit(qpair->id, ha->qpair_qid_map);
	list_del(&qpair->qp_list_elem);
	if (list_empty(&vha->qp_list))
		vha->flags.qpairs_available = 0;
	mempool_destroy(qpair->srb_mempool);
	kfree(qpair);
	mutex_unlock(&ha->mq_lock);

	return QLA_SUCCESS;
fail:
	return ret;
}
Loading