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

Commit ec7193e2 authored by Quinn Tran's avatar Quinn Tran Committed by Nicholas Bellinger
Browse files

qla2xxx: Fix delayed response to command for loop mode/direct connect.



Current driver wait for FW to be in the ready state before
processing in-coming commands. For Arbitrated Loop or
Point-to- Point (not switch), FW Ready state can take a while.
FW will transition to ready state after all Nports have been
logged in. In the mean time, certain initiators have completed
the login and starts IO. Driver needs to start processing all
queues if FW is already started.

Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 482c9dc7
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -3322,6 +3322,10 @@ struct qlt_hw_data {

#define LEAK_EXCHG_THRESH_HOLD_PERCENT 75	/* 75 percent */

#define QLA_EARLY_LINKUP(_ha) \
	((_ha->flags.n2n_ae || _ha->flags.lip_ae) && \
	 _ha->flags.fw_started && !_ha->flags.fw_init_done)

/*
 * Qlogic host adapter specific data structure.
*/
@@ -3371,9 +3375,11 @@ struct qla_hw_data {
		uint32_t	fawwpn_enabled:1;
		uint32_t	exlogins_enabled:1;
		uint32_t	exchoffld_enabled:1;
		/* 35 bits */

		uint32_t	lip_ae:1;
		uint32_t	n2n_ae:1;
		uint32_t	fw_started:1;
		uint32_t	fw_init_done:1;
	} flags;

	/* This spinlock is used to protect "io transactions", you must
@@ -3466,7 +3472,6 @@ struct qla_hw_data {
#define P2P_LOOP  3
	uint8_t		interrupts_on;
	uint32_t	isp_abort_cnt;

#define PCI_DEVICE_ID_QLOGIC_ISP2532    0x2532
#define PCI_DEVICE_ID_QLOGIC_ISP8432    0x8432
#define PCI_DEVICE_ID_QLOGIC_ISP8001	0x8001
@@ -3947,6 +3952,7 @@ typedef struct scsi_qla_host {
	struct list_head vp_fcports;	/* list of fcports */
	struct list_head work_list;
	spinlock_t work_lock;
	struct work_struct iocb_work;

	/* Commonly used flags and state information. */
	struct Scsi_Host *host;
+12 −0
Original line number Diff line number Diff line
@@ -3178,6 +3178,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
	} else {
		ql_dbg(ql_dbg_init, vha, 0x00d3,
		    "Init Firmware -- success.\n");
		ha->flags.fw_started = 1;
	}

	return (rval);
@@ -4000,6 +4001,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
			atomic_set(&vha->loop_state, LOOP_READY);
			ql_dbg(ql_dbg_disc, vha, 0x2069,
			    "LOOP READY.\n");
			ha->flags.fw_init_done = 1;

			/*
			 * Process any ATIO queue entries that came in
@@ -5491,6 +5493,11 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
	if (!(IS_P3P_TYPE(ha)))
		ha->isp_ops->reset_chip(vha);

	ha->flags.n2n_ae = 0;
	ha->flags.lip_ae = 0;
	ha->current_topology = 0;
	ha->flags.fw_started = 0;
	ha->flags.fw_init_done = 0;
	ha->chip_reset++;

	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@ -6767,6 +6774,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
		return;
	if (!ha->fw_major_version)
		return;
	if (!ha->flags.fw_started)
		return;

	ret = qla2x00_stop_firmware(vha);
	for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
@@ -6780,6 +6789,9 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
		    "Attempting retry of stop-firmware command.\n");
		ret = qla2x00_stop_firmware(vha);
	}

	ha->flags.fw_started = 0;
	ha->flags.fw_init_done = 0;
}

int
+13 −1
Original line number Diff line number Diff line
@@ -708,6 +708,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
		    "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);

		ha->isp_ops->fw_dump(vha, 1);
		ha->flags.fw_init_done = 0;
		ha->flags.fw_started = 0;

		if (IS_FWI2_CAPABLE(ha)) {
			if (mb[1] == 0 && mb[2] == 0) {
@@ -761,6 +763,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
		break;

	case MBA_LIP_OCCURRED:		/* Loop Initialization Procedure */
		ha->flags.lip_ae = 1;
		ha->flags.n2n_ae = 0;

		ql_dbg(ql_dbg_async, vha, 0x5009,
		    "LIP occurred (%x).\n", mb[1]);

@@ -797,6 +802,10 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
		break;

	case MBA_LOOP_DOWN:		/* Loop Down Event */
		ha->flags.n2n_ae = 0;
		ha->flags.lip_ae = 0;
		ha->current_topology = 0;

		mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
			? RD_REG_WORD(&reg24->mailbox4) : 0;
		mbx = (IS_P3P_TYPE(ha)) ? RD_REG_WORD(&reg82->mailbox_out[4])
@@ -866,6 +875,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)

	/* case MBA_DCBX_COMPLETE: */
	case MBA_POINT_TO_POINT:	/* Point-to-Point */
		ha->flags.lip_ae = 0;
		ha->flags.n2n_ae = 1;

		if (IS_QLA2100(ha))
			break;

@@ -2706,7 +2718,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
	struct sts_entry_24xx *pkt;
	struct qla_hw_data *ha = vha->hw;

	if (!vha->flags.online)
	if (!ha->flags.fw_started)
		return;

	while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
+3 −3
Original line number Diff line number Diff line
@@ -3638,11 +3638,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,

	if (rptid_entry->format == 0) {
		/* loop */
		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
		ql_dbg(ql_dbg_async, vha, 0x10b7,
		    "Format 0 : Number of VPs setup %d, number of "
		    "VPs acquired %d.\n", rptid_entry->vp_setup,
		    rptid_entry->vp_acquired);
		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8,
		ql_dbg(ql_dbg_async, vha, 0x10b8,
		    "Primary port id %02x%02x%02x.\n",
		    rptid_entry->port_id[2], rptid_entry->port_id[1],
		    rptid_entry->port_id[0]);
@@ -3651,7 +3651,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,

	} else if (rptid_entry->format == 1) {
		/* fabric */
		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9,
		ql_dbg(ql_dbg_async, vha, 0x10b9,
		    "Format 1: VP[%d] enabled - status %d - with "
		    "port id %02x%02x%02x.\n", rptid_entry->vp_idx,
			rptid_entry->vp_status,
+20 −1
Original line number Diff line number Diff line
@@ -2560,6 +2560,20 @@ qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
	return atomic_read(&vha->loop_state) == LOOP_READY;
}

static void qla2x00_iocb_work_fn(struct work_struct *work)
{
	struct scsi_qla_host *vha = container_of(work,
		struct scsi_qla_host, iocb_work);
	int cnt = 0;

	while (!list_empty(&vha->work_list)) {
		qla2x00_do_work(vha);
		cnt++;
		if (cnt > 10)
			break;
	}
}

/*
 * PCI driver interface
 */
@@ -3078,6 +3092,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
	 */
	qla2xxx_wake_dpc(base_vha);

	INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
	INIT_WORK(&ha->board_disable, qla2x00_disable_board_on_pci_error);

	if (IS_QLA8031(ha) || IS_MCTP_CAPABLE(ha)) {
@@ -4321,6 +4336,10 @@ qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
	spin_lock_irqsave(&vha->work_lock, flags);
	list_add_tail(&e->list, &vha->work_list);
	spin_unlock_irqrestore(&vha->work_lock, flags);

	if (QLA_EARLY_LINKUP(vha->hw))
		schedule_work(&vha->iocb_work);
	else
		qla2xxx_wake_dpc(vha);

	return QLA_SUCCESS;
Loading