[PATCH 2/2] qla2xxx: Kick target ATIO queue after qla2x00_abort_isp completion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch addresses an issue between the assignment of vha->flags.online = 1
to signal operational status in process context via qla2x00_do_dpc() ->
qla2x00_abort_isp() -> qla2x00_restart_isp(), and processing of individual
ATIO packets in interrupt context within qla_tgt_24xx_process_atio_queue().
This was causing qla_tgt_24xx_process_atio_queue() to explictly ignore
new packets with non-operational status before completion of qla2x00_restart_isp()
-> target mode operation transition, and more specifically ELS packets
that are expected to drive the re-creation of active qla_tgt_sess nexuses in
qla_target.c + tcm_qla2xxx code.

This v2 patch takes a different approach than v1, which originally tried to
allow ATIO ring processing in qla_tgt_24xx_process_atio_queue() during
qla2x00_abort_isp() reset operation.  This patch:

*) Keep !vha->flags.online check in qla_tgt_24xx_process_atio_queue() to
   prevent all ATIO ring processing during qla2x00_abort_isp() reset.
*) Prevent vha->flags.online = 1 from being set during qla2x00_abort_isp()
   and qla2x00_restart_isp() processing.
*) Set vha->flags.online = 1 upon the completion of qla2x00_abort_isp(),
   and make a direct call into qla_tgt_24xx_process_atio_queue() from
   qla2x00_do_dpc() process context to handle ATIO packets that have
   accumulated during qla2x00_abort_isp().
*) Add extra paranoid qla_tgt_mode_enabled_base_vha() checks around
   existing IS_NOPOLLING_TYPE() usage in qla2x00_mailbox_command(),
   qla24xx_disable_intrs() and qla24xx_reset_risc().  This allows
   target mode to run in legacy interrupt mode for mailbox commands
   during qla2x00_abort_isp() reset, and allows qla24xx_disable_intrs()
   to clear qla_hw_data->interrupts_on during reset.

This patch also depends upon 'Disable initial LIP' being cleared within
qla_tgt_24xx_config_nvram_stage1() for firmware_options_1:

	/* Enable initial LIP */
	nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9);

Enabling this bit to 'Disable initial LIP' ends up causing intermittent
reset hangs with target mode operation, eventually causing the port to
be taken offline.

Reported-by: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Reported-by: Patrick Lee <patrick@xxxxxxxxxxxxxxx>
Cc: Patrick Lee <patrick@xxxxxxxxxxxxxxx>
Cc: Andrew Vasquez <andrew.vasquez@xxxxxxxxxx>
Cc: Madhuranath Iyengar <mni@xxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxxxxxxxx>
---
 drivers/scsi/qla2xxx/qla_init.c   |   20 +++++++++++++++++---
 drivers/scsi/qla2xxx/qla_mbx.c    |    7 ++++---
 drivers/scsi/qla2xxx/qla_os.c     |    2 +-
 drivers/scsi/qla2xxx/qla_target.c |    8 +++++++-
 drivers/scsi/qla2xxx/qla_target.h |    8 ++++++++
 5 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index fca50d5..de8810d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1068,7 +1068,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
 
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-	if (IS_NOPOLLING_TYPE(ha))
+	if (IS_NOPOLLING_TYPE(ha) && !qla_tgt_mode_enabled_base_vha(ha))
 		ha->isp_ops->enable_intrs(ha);
 }
 
@@ -4133,7 +4133,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
 				vha->marker_needed = 1;
 			}
 
-			vha->flags.online = 1;
+			if (!qla_tgt_mode_enabled(vha))
+				vha->flags.online = 1;
 
 			qla_tgt_abort_isp(vha);
 
@@ -4229,6 +4230,17 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
 			}
 		}
 		spin_unlock_irqrestore(&ha->vport_slock, flags);
+		/*
+ 		 * For target mode, wait until the last moment to set the
+ 		 * online flag and kick the ATIO ring to process new packets
+ 		 * that have accumulated during qla2x00_abort_isp().
+ 		 */ 
+		if (qla_tgt_mode_enabled(vha)) {
+			spin_lock_irqsave(&ha->hardware_lock, flags);
+			vha->flags.online = 1;
+			qla_tgt_24xx_process_atio_queue(vha);
+			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+		}
 
 	} else {
 		qla_printk(KERN_INFO, ha,
@@ -4279,7 +4291,9 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
 			/* Issue a marker after FW becomes ready. */
 			qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
 
-			vha->flags.online = 1;
+			if (!qla_tgt_mode_enabled(vha))
+				vha->flags.online = 1;
+
 			/* Wait at most MAX_TARGET RSCNs for a stable link. */
 			wait_time = 256;
 			do {
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 087b2cc..3813306 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -148,7 +148,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
 	/* Wait for mbx cmd completion until timeout */
 
-	if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
+	if ((!abort_active && io_lock_on) ||
+	    (IS_NOPOLLING_TYPE(ha) && !qla_tgt_mode_enabled_base_vha(ha))) {
 		set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
 		if (IS_QLA82XX(ha)) {
@@ -278,8 +279,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
 	/* Clean up */
 	ha->mcp = NULL;
-
-	if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
+	if ((abort_active || !io_lock_on) &&
+	    (!IS_NOPOLLING_TYPE(ha) || qla_tgt_mode_enabled_base_vha(ha))) {
 		DEBUG11(printk("%s(%ld): checking for additional resp "
 		    "interrupt.\n", __func__, base_vha->host_no));
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2ab9564..0b61ca7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1486,7 +1486,7 @@ qla24xx_disable_intrs(struct qla_hw_data *ha)
 	unsigned long flags = 0;
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
-	if (IS_NOPOLLING_TYPE(ha))
+	if (IS_NOPOLLING_TYPE(ha) && !qla_tgt_mode_enabled_base_vha(ha))
 		return;
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	ha->interrupts_on = 0;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 757e971..f26b743 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -5328,7 +5328,13 @@ qla_tgt_24xx_process_atio_queue(struct scsi_qla_host *vha)
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 	atio_t *pkt;
 	int cnt, i;
-
+	/*
+ 	 * During qla2x00_abort_isp() we expect to hit this check in order
+ 	 * to prevent processing during reset.  Upon completion of reset,
+ 	 * qla2x00_abort_isp() will set vha->flags.online=1 and make a
+ 	 * direct call to qla_tgt_24xx_process_atio_queue() to kick off
+ 	 * ATIO ring processing from qla2x00_do_dpc() process context.
+ 	 */
 	if (!vha->flags.online)
 		return;
 
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 42d5479..e89a7e3 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -1023,6 +1023,14 @@ static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
 	return ha->host->active_mode & MODE_TARGET;
 }
 
+static inline bool qla_tgt_mode_enabled_base_vha(struct qla_hw_data *hw)
+{
+	if (!hw->qla_tgt || !hw->qla_tgt->vha)
+		return false;
+
+	return qla_tgt_mode_enabled(hw->qla_tgt->vha);
+}
+
 static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha)
 {
 	return ha->host->active_mode & MODE_INITIATOR;
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux