qla4xxx: added support for abort task management command
Subsystems (2)
PATCH 8/12 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 | 49 +++++++++++++++++ drivers/scsi/qla4xxx/ql4_os.c | 112 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 163 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 +49 -0
55 lines not on this page · raw message
drivers/scsi/qla4xxx/ql4_os.c +112 -0
130 lines not on this page · raw message
Signature · 3 lines
1.6.0.2 ----- End forwarded message -----
Quoted 137 lines · Ravi Anand
From: Vikas Chaudhary<[email protected]>
Handles SCSI aborts.
Signed-off-by Karen Higgins<[email protected]>Signed-off-by Vikas Chaudhary<[email protected]>Signed-off-by Ravi Anand<[email protected]>--- 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(-)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 0x001Edrivers/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 +49
-0@@ -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 drivers/scsi/qla4xxx/ql4_os.c +17
-0@@ -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;
drivers/scsi/qla4xxx/ql4_os.c static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, · line 1608
Quoted 10 lines
drivers/scsi/qla4xxx/ql4_os.c +10
-0+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 ; + }
Are you hitting this null scsi cmd case?
Quoted 11 lines
drivers/scsi/qla4xxx/ql4_os.c +11
-0+ + 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));
drivers/scsi/qla4xxx/ql4_os.c static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, · line 1629
Quoted 10 lines
drivers/scsi/qla4xxx/ql4_os.c +10
-0+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;
You do not need this do you? You never really use it. It seems to only be used to print a refcount that is never used.
drivers/scsi/qla4xxx/ql4_os.c static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, · line 1640
Quoted 11 lines
drivers/scsi/qla4xxx/ql4_os.c +11
-0+ +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 ; + }
If the adapter went down, do you need to abort commands? If the adapter goes down does it fail all the running commands, or do you still need to do a an abort to clean them up in firmware?
Or if the adapter goes down does it fail the running sessions, which would fail the commands if doing erl0. And in that case we would not need to abort them.
drivers/scsi/qla4xxx/ql4_os.c static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
Quoted 4 lines
drivers/scsi/qla4xxx/ql4_os.c +4
-0+ +/* Check active list for command */ +spin_lock_irqsave (&ha->hardware_lock, flags); +for (i =1 ; i<MAX_SRBS ; i++) {
Why loop? Can't you grab the hardware lock then check if tcmd->SCp.ptr and cmd->host_scribble is set? If it is then it should be your srb in the host_scribble right?