Skip to content

Commit 09a0f71

Browse files
Vikas ChaudharyJames Bottomley
authored andcommitted
[SCSI] qla4xxx: added support for abort task management command
* Handles SCSI command aborts. * Serialization srb between error handler and command completion path. Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Signed-off-by: Ravi Anand <ravi.anand@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
1 parent 5369887 commit 09a0f71

File tree

6 files changed

+124
-9
lines changed

6 files changed

+124
-9
lines changed

drivers/scsi/qla4xxx/ql4_def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ struct srb {
172172

173173
struct scsi_cmnd *cmd; /* (4) SCSI command block */
174174
dma_addr_t dma_handle; /* (4) for unmap of single transfers */
175-
atomic_t ref_count; /* reference count for this srb */
175+
struct kref srb_ref; /* reference count for this srb */
176176
uint32_t fw_ddb_index;
177177
uint8_t err_id; /* error id */
178178
#define SRB_ERR_PORT 1 /* Request failed because "port down" */

drivers/scsi/qla4xxx/ql4_fw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ union external_hw_config_reg {
215215
/* Mailbox command definitions */
216216
#define MBOX_CMD_ABOUT_FW 0x0009
217217
#define MBOX_CMD_PING 0x000B
218+
#define MBOX_CMD_ABORT_TASK 0x0015
218219
#define MBOX_CMD_LUN_RESET 0x0016
219220
#define MBOX_CMD_TARGET_WARM_RESET 0x0017
220221
#define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E

drivers/scsi/qla4xxx/ql4_glbl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen);
2525
int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha);
2626
int qla4xxx_relogin_device(struct scsi_qla_host * ha,
2727
struct ddb_entry * ddb_entry);
28+
int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb);
2829
int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
2930
int lun);
3031
int qla4xxx_reset_target(struct scsi_qla_host * ha,
@@ -65,7 +66,7 @@ void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
6566
int qla4xxx_init_rings(struct scsi_qla_host * ha);
6667
struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
6768
uint32_t index);
68-
void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
69+
void qla4xxx_srb_compl(struct kref *ref);
6970
int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
7071
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
7172
uint32_t state, uint32_t conn_error);

drivers/scsi/qla4xxx/ql4_isr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ qla4xxx_status_cont_entry(struct scsi_qla_host *ha,
9797

9898
/* Place command on done queue. */
9999
if (srb->req_sense_len == 0) {
100-
qla4xxx_srb_compl(ha, srb);
100+
kref_put(&srb->srb_ref, qla4xxx_srb_compl);
101101
ha->status_srb = NULL;
102102
}
103103
}
@@ -329,7 +329,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
329329
/* complete the request, if not waiting for status_continuation pkt */
330330
srb->cc_stat = sts_entry->completionStatus;
331331
if (ha->status_srb == NULL)
332-
qla4xxx_srb_compl(ha, srb);
332+
kref_put(&srb->srb_ref, qla4xxx_srb_compl);
333333
}
334334

335335
/**
@@ -393,7 +393,7 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
393393
/* ETRY normally by sending it back with
394394
* DID_BUS_BUSY */
395395
srb->cmd->result = DID_BUS_BUSY << 16;
396-
qla4xxx_srb_compl(ha, srb);
396+
kref_put(&srb->srb_ref, qla4xxx_srb_compl);
397397
break;
398398

399399
case ET_CONTINUE:

drivers/scsi/qla4xxx/ql4_mbx.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,59 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
761761
event_log_dma);
762762
}
763763

764+
/**
765+
* qla4xxx_abort_task - issues Abort Task
766+
* @ha: Pointer to host adapter structure.
767+
* @srb: Pointer to srb entry
768+
*
769+
* This routine performs a LUN RESET on the specified target/lun.
770+
* The caller must ensure that the ddb_entry and lun_entry pointers
771+
* are valid before calling this routine.
772+
**/
773+
int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
774+
{
775+
uint32_t mbox_cmd[MBOX_REG_COUNT];
776+
uint32_t mbox_sts[MBOX_REG_COUNT];
777+
struct scsi_cmnd *cmd = srb->cmd;
778+
int status = QLA_SUCCESS;
779+
unsigned long flags = 0;
780+
uint32_t index;
781+
782+
/*
783+
* Send abort task command to ISP, so that the ISP will return
784+
* request with ABORT status
785+
*/
786+
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
787+
memset(&mbox_sts, 0, sizeof(mbox_sts));
788+
789+
spin_lock_irqsave(&ha->hardware_lock, flags);
790+
index = (unsigned long)(unsigned char *)cmd->host_scribble;
791+
spin_unlock_irqrestore(&ha->hardware_lock, flags);
792+
793+
/* Firmware already posted completion on response queue */
794+
if (index == MAX_SRBS)
795+
return status;
796+
797+
mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
798+
mbox_cmd[1] = srb->fw_ddb_index;
799+
mbox_cmd[2] = index;
800+
/* Immediate Command Enable */
801+
mbox_cmd[5] = 0x01;
802+
803+
qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
804+
&mbox_sts[0]);
805+
if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
806+
status = QLA_ERROR;
807+
808+
DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: "
809+
"mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
810+
ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
811+
mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
812+
}
813+
814+
return status;
815+
}
816+
764817
/**
765818
* qla4xxx_reset_lun - issues LUN Reset
766819
* @ha: Pointer to host adapter structure.

drivers/scsi/qla4xxx/ql4_os.c

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
7474
*/
7575
static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
7676
void (*done) (struct scsi_cmnd *));
77+
static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
7778
static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
7879
static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
7980
static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
@@ -88,6 +89,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
8889
.proc_name = DRIVER_NAME,
8990
.queuecommand = qla4xxx_queuecommand,
9091

92+
.eh_abort_handler = qla4xxx_eh_abort,
9193
.eh_device_reset_handler = qla4xxx_eh_device_reset,
9294
.eh_target_reset_handler = qla4xxx_eh_target_reset,
9395
.eh_host_reset_handler = qla4xxx_eh_host_reset,
@@ -384,7 +386,7 @@ static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
384386
if (!srb)
385387
return srb;
386388

387-
atomic_set(&srb->ref_count, 1);
389+
kref_init(&srb->srb_ref);
388390
srb->ha = ha;
389391
srb->ddb = ddb_entry;
390392
srb->cmd = cmd;
@@ -406,9 +408,11 @@ static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)
406408
CMD_SP(cmd) = NULL;
407409
}
408410

409-
void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb)
411+
void qla4xxx_srb_compl(struct kref *ref)
410412
{
413+
struct srb *srb = container_of(ref, struct srb, srb_ref);
411414
struct scsi_cmnd *cmd = srb->cmd;
415+
struct scsi_qla_host *ha = srb->ha;
412416

413417
qla4xxx_srb_free_dma(ha, srb);
414418

@@ -887,7 +891,7 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha)
887891
srb = qla4xxx_del_from_active_array(ha, i);
888892
if (srb != NULL) {
889893
srb->cmd->result = DID_RESET << 16;
890-
qla4xxx_srb_compl(ha, srb);
894+
kref_put(&srb->srb_ref, qla4xxx_srb_compl);
891895
}
892896
}
893897
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1501,7 +1505,7 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t in
15011505

15021506
/**
15031507
* qla4xxx_eh_wait_on_command - waits for command to be returned by firmware
1504-
* @ha: actual ha whose done queue will contain the comd returned by firmware.
1508+
* @ha: Pointer to host adapter structure.
15051509
* @cmd: Scsi Command to wait on.
15061510
*
15071511
* This routine waits for the command to be returned by the Firmware
@@ -1584,6 +1588,62 @@ static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
15841588
return status;
15851589
}
15861590

1591+
/**
1592+
* qla4xxx_eh_abort - callback for abort task.
1593+
* @cmd: Pointer to Linux's SCSI command structure
1594+
*
1595+
* This routine is called by the Linux OS to abort the specified
1596+
* command.
1597+
**/
1598+
static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
1599+
{
1600+
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
1601+
unsigned int id = cmd->device->id;
1602+
unsigned int lun = cmd->device->lun;
1603+
unsigned long serial = cmd->serial_number;
1604+
struct srb *srb = NULL;
1605+
int ret = SUCCESS;
1606+
int wait = 0;
1607+
1608+
dev_info(&ha->pdev->dev,
1609+
"scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n",
1610+
ha->host_no, id, lun, cmd, serial);
1611+
1612+
srb = (struct srb *) CMD_SP(cmd);
1613+
1614+
if (!srb)
1615+
return SUCCESS;
1616+
1617+
kref_get(&srb->srb_ref);
1618+
1619+
if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
1620+
DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",
1621+
ha->host_no, id, lun));
1622+
ret = FAILED;
1623+
} else {
1624+
DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n",
1625+
ha->host_no, id, lun));
1626+
wait = 1;
1627+
}
1628+
1629+
kref_put(&srb->srb_ref, qla4xxx_srb_compl);
1630+
1631+
/* Wait for command to complete */
1632+
if (wait) {
1633+
if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
1634+
DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n",
1635+
ha->host_no, id, lun));
1636+
ret = FAILED;
1637+
}
1638+
}
1639+
1640+
dev_info(&ha->pdev->dev,
1641+
"scsi%ld:%d:%d: Abort command - %s\n",
1642+
ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed");
1643+
1644+
return ret;
1645+
}
1646+
15871647
/**
15881648
* qla4xxx_eh_device_reset - callback for target reset.
15891649
* @cmd: Pointer to Linux's SCSI command structure

0 commit comments

Comments
 (0)