All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ravi Anand <ravi.anand@qlogic.com>
To: James Bottomley <james.bottomley@suse.de>
Cc: Mike Christie <michaelc@cs.wisc.edu>,
	Linux-SCSI Mailing List <linux-scsi@vger.kernel.org>,
	Vikas Chaudhary <vikas.chaudhary@qlogic.com>,
	Karen Higgins <karen.higgins@qlogic.com>
Subject: [PATCH 08/12] qla4xxx: added support for abort task management command
Date: Tue, 6 Apr 2010 03:14:24 -0700	[thread overview]
Message-ID: <20100406101423.GO22922@linux-qf4p> (raw)

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

Handles SCSI aborts.

Signed-off-by: Karen Higgins <karen.higgins@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Ravi Anand <ravi.anand@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_fw.h   |    1 +
 drivers/scsi/qla4xxx/ql4_glbl.h |    1 +
 drivers/scsi/qla4xxx/ql4_mbx.c  |   49 +++++++++++++++++
 drivers/scsi/qla4xxx/ql4_os.c   |  112 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index dfe7b4d..855226e 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -215,6 +215,7 @@ union external_hw_config_reg {
 /*  Mailbox command definitions */
 #define MBOX_CMD_ABOUT_FW			0x0009
 #define MBOX_CMD_PING				0x000B
+#define MBOX_CMD_ABORT_TASK			0x0015
 #define MBOX_CMD_LUN_RESET			0x0016
 #define MBOX_CMD_TARGET_WARM_RESET		0x0017
 #define MBOX_CMD_GET_MANAGEMENT_DATA		0x001E
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 987658f..3c8f753 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -25,6 +25,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen);
 int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha);
 int qla4xxx_relogin_device(struct scsi_qla_host * ha,
 			   struct ddb_entry * ddb_entry);
+int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb);
 int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
 		      int lun);
 int qla4xxx_reset_target(struct scsi_qla_host * ha,
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 12e17a3..ad073a6 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -762,6 +762,55 @@ exit_get_event_log:
 }
 
 /**
+ * qla4xxx_abort_task - issues Abort Task
+ * @ha: Pointer to host adapter structure.
+ * @srb: Pointer to srb entry
+ *
+ * This routine performs a LUN RESET on the specified target/lun.
+ * The caller must ensure that the ddb_entry and lun_entry pointers
+ * are valid before calling this routine.
+ **/
+int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	struct scsi_cmnd *cmd = srb->cmd;
+	int status = QLA_SUCCESS;
+
+	DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: abort task issued\n",
+			ha->host_no, cmd->device->channel, cmd->device->id,
+			cmd->device->lun));
+
+	/*
+	 * Send abort task command to ISP, so that the ISP will return
+	 * request with ABORT status
+	 */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
+	mbox_cmd[1] = srb->fw_ddb_index;
+	mbox_cmd[2] = (unsigned long)(unsigned char *)cmd->host_scribble;
+	mbox_cmd[5] = 0x01;     /* Immediate Command Enable */
+
+	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
+				&mbox_sts[0]);
+	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
+		status = QLA_ERROR;
+
+		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d:%d: abort task "
+				"FAILED: ", ha->host_no, cmd->device->channel,
+				cmd->device->id, cmd->device->lun));
+		DEBUG2(printk(KERN_WARNING "mbx0=%04X, mb1=%04X, mb2=%04X,"
+				" mb3=%04X, mb4=%04X\n", mbox_sts[0],
+				mbox_sts[1], mbox_sts[2], mbox_sts[3],
+				mbox_sts[4]));
+	}
+
+	return status;
+}
+
+/**
  * qla4xxx_reset_lun - issues LUN Reset
  * @ha: Pointer to host adapter structure.
  * @db_entry: Pointer to device database entry
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index ca1d293..2ca5659 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -73,6 +73,7 @@ static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
  */
 static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 				void (*done) (struct scsi_cmnd *));
+static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
@@ -87,6 +88,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
 	.proc_name		= DRIVER_NAME,
 	.queuecommand		= qla4xxx_queuecommand,
 
+	.eh_abort_handler	= qla4xxx_eh_abort,
 	.eh_device_reset_handler = qla4xxx_eh_device_reset,
 	.eh_target_reset_handler = qla4xxx_eh_target_reset,
 	.eh_host_reset_handler	= qla4xxx_eh_host_reset,
@@ -1579,6 +1581,116 @@ static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
 }
 
 /**
+ * qla4xxx_eh_abort - callback for abort task.
+ * @cmd: Pointer to Linux's SCSI command structure
+ *
+ * This routine is called by the Linux OS to abort the specified
+ * command.
+ **/
+static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
+{
+	struct scsi_qla_host *ha;
+	struct srb *srb = NULL;
+	struct ddb_entry *ddb_entry;
+	struct scsi_cmnd *srb_cmd = NULL;
+	int ret = FAILED;
+	unsigned int channel;
+	unsigned int id;
+	unsigned int lun;
+	unsigned long serial;
+	unsigned long flags = 0;
+	int i = 0;
+
+	if (cmd == NULL) {
+		DEBUG2(printk(KERN_INFO "ABORT - **** SCSI mid-layer passing"
+				" in NULL cmd\n"));
+		return SUCCESS;
+	}
+
+	ha = to_qla_host(cmd->device->host);
+	ddb_entry = cmd->device->hostdata;
+	channel = cmd->device->channel;
+	id = cmd->device->id;
+	lun = cmd->device->lun;
+	serial = cmd->serial_number;
+
+	if (!ddb_entry) {
+		DEBUG2(printk(KERN_WARNING "scsi%ld: ABORT - NULL ddb entry.\n",
+				ha->host_no));
+		return FAILED;
+	}
+
+	if (!cmd->SCp.ptr) {
+		DEBUG2(printk(KERN_INFO "scsi%ld: ABORT - cmd already"
+				" completed.\n", ha->host_no));
+		return SUCCESS;
+	}
+
+	srb = (struct srb *) cmd->SCp.ptr;
+
+	dev_info(&ha->pdev->dev, "scsi%ld:%d:%d:%d: ABORT ISSUED "
+		 "cmd=%p, pid=%ld, ref=%d\n", ha->host_no, channel, id, lun,
+		 cmd, serial, atomic_read(&srb->ref_count));
+
+	if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
+		DEBUG2(printk(KERN_WARNING "scsi%ld:%d: %s: Unable to abort "
+				"task. Adapter DEAD.\n", ha->host_no,
+				cmd->device->channel, __func__));
+		return FAILED;
+	}
+
+	/* Check active list for command */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (i = 1; i < MAX_SRBS; i++) {
+		srb_cmd = scsi_host_find_tag(ha->host, i);
+		if (srb_cmd == NULL)
+			continue;
+
+		srb = (struct srb *)srb_cmd->host_scribble;
+		if (srb == NULL)
+			continue;
+
+		if (srb->cmd != cmd)
+			continue;
+
+		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d %s: aborting srb %p "
+				"from RISC. pid=%ld.\n", ha->host_no, channel,
+				id, lun, __func__, srb, serial));
+		DEBUG3(qla4xxx_print_scsi_cmd(cmd));
+
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
+			dev_info(&ha->pdev->dev,
+				"scsi%ld:%d:%d:%d: ABORT TASK - FAILED.\n",
+				ha->host_no, channel, id, lun);
+		} else {
+			dev_info(&ha->pdev->dev,
+				"scsi%ld:%d:%d:%d: ABORT TASK - mbx success.\n",
+				ha->host_no, channel, id, lun);
+		}
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		break;
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	/* Wait for command to complete */
+	if (qla4xxx_eh_wait_on_command(ha, cmd)) {
+		dev_info(&ha->pdev->dev,
+			 "scsi%ld:%d:%d:%d: ABORT SUCCEEDED - "
+			 "cmd returned back to OS.\n",
+			 ha->host_no, channel, id, lun);
+		ret = SUCCESS;
+	}
+
+	DEBUG2(printk("scsi%ld:%d:%d:%d: ABORT cmd=%p, pid=%ld, ref=%d, "
+		      "ret=%x\n", ha->host_no, channel, id, lun, cmd,
+		      serial, atomic_read(&srb->ref_count), ret));
+
+	return ret;
+}
+
+/**
  * qla4xxx_eh_device_reset - callback for target reset.
  * @cmd: Pointer to Linux's SCSI command structure
  *
-- 
1.6.0.2

----- End forwarded message -----

             reply	other threads:[~2010-04-06 10:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-06 10:14 Ravi Anand [this message]
2010-04-07  4:34 ` [PATCH 08/12] qla4xxx: added support for abort task management command Mike Christie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100406101423.GO22922@linux-qf4p \
    --to=ravi.anand@qlogic.com \
    --cc=james.bottomley@suse.de \
    --cc=karen.higgins@qlogic.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=michaelc@cs.wisc.edu \
    --cc=vikas.chaudhary@qlogic.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.