qla4xxx: added support for abort task management command
Subsystems (2)
PATCH 10/11 qla4xxx: added support for abort task management command
From: Vikas Chaudhary <[email protected]>
Handles SCSI aborts.
--- drivers/scsi/qla4xxx/ql4_fw.h | 1 + drivers/scsi/qla4xxx/ql4_glbl.h | 1 + drivers/scsi/qla4xxx/ql4_mbx.c | 45 ++++++++++++ drivers/scsi/qla4xxx/ql4_os.c | 147 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+), 0 deletions(-)
drivers/scsi/qla4xxx/ql4_fw.h +1 -0
@@ -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
drivers/scsi/qla4xxx/ql4_glbl.h +1 -0
@@ -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,
drivers/scsi/qla4xxx/ql4_mbx.c +45 -0
51 lines not on this page · raw message
drivers/scsi/qla4xxx/ql4_os.c +147 -0
165 lines not on this page · raw message
Signature · 1 line
1.6.0.2
Quoted 35 lines · Ravi Anand
/**
+ *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.
+ **/drivers/scsi/qla4xxx/ql4_os.c +27
-0+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 =SUCCESS ; +unsigned int channel; +unsigned int id; +unsigned int lun; +unsigned long serial; +unsigned long flags =0 ; +int i =0 ; +int got_ref =0 ; +unsigned long wait_online; + +if (cmd ==NULL ) { +DEBUG2 (printk ("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;
drivers/scsi/qla4xxx/ql4_os.c static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, · line 1658
Quoted 10 lines
drivers/scsi/qla4xxx/ql4_os.c +10
-0+ +if (!ddb_entry) { +DEBUG2 (printk ("scsi%ld: ABORT - NULL ddb entry.\n" , ha->host_no)); +return FAILED ; + } + +if (!cmd->SCp.ptr) { +DEBUG2 (printk ("scsi%ld: ABORT - cmd already completed.\n" , + ha->host_no)); +return ret;
Not a big deal, but a couple lines above you keep switching between using ret or SUCCESS/FAILED. In the cmd == NULL check you use SUCESS. Here is use ret, but ret is never changed. Not a big deal, but harder to read, because we have to double check if we missed ret getting changed since we keep switching back and forth using it.
Quoted 53 lines
drivers/scsi/qla4xxx/ql4_os.c +53
-0+ } + + + + 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 ("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 ("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)); + +/* Get a reference to the sp and drop the lock.*/ +sp_get (srb); + got_ref++; + +spin_unlock_irqrestore (&ha->hardware_lock, flags); + +/* +* If device is not online wait for 10 sec for device to come online, +* else return error and do not issue abort task. +*/ +if (atomic_read (&ddb_entry->state) !=DDB_STATE_ONLINE ) { + wait_online = jiffies + (DEVICE_ONLINE_TOV *HZ ); +while (time_before (jiffies, wait_online)) { +set_current_state (TASK_INTERRUPTIBLE ); +schedule_timeout (HZ ); +if (atomic_read (&ddb_entry->state) ==DDB_STATE_ONLINE )
drivers/scsi/qla4xxx/ql4_os.c static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, · line 1721
Quoted 10 lines
drivers/scsi/qla4xxx/ql4_os.c +10
-0+break ; + } +if (atomic_read (&ddb_entry->state) !=DDB_STATE_ONLINE ) { +DEBUG2 (printk ("scsi%ld:%d: %s: Unable to abort task." +"Device is not online.\n" , ha->host_no + , cmd->device->channel, __func__)); + +return FAILED ; + } + }
Does the abort command for your card do a abort task tmf and do some firmware cleanup?
If the session is went down, and it is now back up, do you have to send a abort to the firmware? In other places, like for a ddb changed or link down handling, you do not do that.
For iscsi in erl0, the tasks are wiped out when you relogin, so if you went from ddb state non online to online, there is no point in sending the tmf to the target since the relogin had the same clearing effects.
If you need to send this to clear up some firmware stuff, then it seems like you have a bug in the other paths when the session does offline (it does not like we are sending a abort to the card there).
If you do not need to send a abort for firmware cleanup, and if doing erl0, then it is fastest to just escalate to the target reset callout for this case. We can wait just once there instead of waiting 10 secs * num_commands.
Quoted 4 lines · Mike Christie
If you do not need to send a abort for firmware cleanup, and if doing erl0, then it is fastest to just escalate to the target reset callout for this case. We can wait just once there instead of waiting 10 secs *
num_commands.
Oh yeah, you want to wait in the target reset handler for the session to come back or for qla4xxx_recovery_timedout to be called.