aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid C Somayajulu <david.somayajulu@qlogic.com>2008-03-19 14:23:03 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:00 -0400
commit9d56291366cd6ab156be722e42cf487bef20f5fd (patch)
treed85fadb003a7ed4a3ac8380487423a2b6ce31bb2
parentaf7a5647c03c18f5ea58033710ccb23d71727e0c (diff)
[SCSI] qla4xxx: fix scsi command completion, lun reset and target reset code
This patch contains the following: 1. when hba completion status is good, check for iscsi transport errors (underflow/overflow) prior to checking the scsi status 2. New firmware requires that one marker iocb be issued for each task management command. The patch issues marker iocb immediately following a LUN or Target reset. Signed-off-by: David C Somayajulu <david.somayajulu@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h3
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c14
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c40
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c20
5 files changed, 26 insertions, 53 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index ed8ee66a7da5..1b667a70cffa 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -678,7 +678,8 @@ struct qla4_marker_entry {
678 uint32_t system_defined; /* 04-07 */ 678 uint32_t system_defined; /* 04-07 */
679 uint16_t target; /* 08-09 */ 679 uint16_t target; /* 08-09 */
680 uint16_t modifier; /* 0A-0B */ 680 uint16_t modifier; /* 0A-0B */
681#define MM_LUN_RESET 0 681#define MM_LUN_RESET 0
682#define MM_TGT_WARM_RESET 1
682 683
683 uint16_t flags; /* 0C-0D */ 684 uint16_t flags; /* 0C-0D */
684 uint16_t reserved1; /* 0E-0F */ 685 uint16_t reserved1; /* 0E-0F */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index b403a17106c5..96ebfb021f6c 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -70,6 +70,8 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
70int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, 70int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
71 uint32_t fw_ddb_index, uint32_t state); 71 uint32_t fw_ddb_index, uint32_t state);
72void qla4xxx_dump_buffer(void *b, uint32_t size); 72void qla4xxx_dump_buffer(void *b, uint32_t size);
73int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
74 struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
73 75
74extern int ql4xextended_error_logging; 76extern int ql4xextended_error_logging;
75extern int ql4xdiscoverywait; 77extern int ql4xdiscoverywait;
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index e4461b5d767a..912a67494adf 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -66,8 +66,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
66 * 66 *
67 * This routine issues a marker IOCB. 67 * This routine issues a marker IOCB.
68 **/ 68 **/
69static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, 69int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
70 struct ddb_entry *ddb_entry, int lun) 70 struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod)
71{ 71{
72 struct qla4_marker_entry *marker_entry; 72 struct qla4_marker_entry *marker_entry;
73 unsigned long flags = 0; 73 unsigned long flags = 0;
@@ -87,7 +87,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
87 marker_entry->hdr.entryType = ET_MARKER; 87 marker_entry->hdr.entryType = ET_MARKER;
88 marker_entry->hdr.entryCount = 1; 88 marker_entry->hdr.entryCount = 1;
89 marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index); 89 marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
90 marker_entry->modifier = cpu_to_le16(MM_LUN_RESET); 90 marker_entry->modifier = cpu_to_le16(mrkr_mod);
91 int_to_scsilun(lun, &marker_entry->lun); 91 int_to_scsilun(lun, &marker_entry->lun);
92 wmb(); 92 wmb();
93 93
@@ -210,14 +210,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
210 /* Get real lun and adapter */ 210 /* Get real lun and adapter */
211 ddb_entry = srb->ddb; 211 ddb_entry = srb->ddb;
212 212
213 /* Send marker(s) if needed. */
214 if (ha->marker_needed == 1) {
215 if (qla4xxx_send_marker_iocb(ha, ddb_entry,
216 cmd->device->lun) != QLA_SUCCESS)
217 return QLA_ERROR;
218
219 ha->marker_needed = 0;
220 }
221 tot_dsds = 0; 213 tot_dsds = 0;
222 214
223 /* Acquire hardware specific lock */ 215 /* Acquire hardware specific lock */
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index fc84db4069f4..a91a57c57bff 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -11,28 +11,6 @@
11#include "ql4_inline.h" 11#include "ql4_inline.h"
12 12
13/** 13/**
14 * qla2x00_process_completed_request() - Process a Fast Post response.
15 * @ha: SCSI driver HA context
16 * @index: SRB index
17 **/
18static void qla4xxx_process_completed_request(struct scsi_qla_host *ha,
19 uint32_t index)
20{
21 struct srb *srb;
22
23 srb = qla4xxx_del_from_active_array(ha, index);
24 if (srb) {
25 /* Save ISP completion status */
26 srb->cmd->result = DID_OK << 16;
27 qla4xxx_srb_compl(ha, srb);
28 } else {
29 DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
30 "%d\n", ha->host_no, index));
31 set_bit(DPC_RESET_HA, &ha->dpc_flags);
32 }
33}
34
35/**
36 * qla4xxx_status_entry - processes status IOCBs 14 * qla4xxx_status_entry - processes status IOCBs
37 * @ha: Pointer to host adapter structure. 15 * @ha: Pointer to host adapter structure.
38 * @sts_entry: Pointer to status entry structure. 16 * @sts_entry: Pointer to status entry structure.
@@ -47,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
47 uint32_t residual; 25 uint32_t residual;
48 uint16_t sensebytecnt; 26 uint16_t sensebytecnt;
49 27
50 if (sts_entry->completionStatus == SCS_COMPLETE &&
51 sts_entry->scsiStatus == 0) {
52 qla4xxx_process_completed_request(ha,
53 le32_to_cpu(sts_entry->
54 handle));
55 return;
56 }
57
58 srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); 28 srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
59 if (!srb) { 29 if (!srb) {
60 /* FIXMEdg: Don't we need to reset ISP in this case??? */ 30 /* FIXMEdg: Don't we need to reset ISP in this case??? */
@@ -62,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
62 "handle 0x%x, sp=%p. This cmd may have already " 32 "handle 0x%x, sp=%p. This cmd may have already "
63 "been completed.\n", ha->host_no, __func__, 33 "been completed.\n", ha->host_no, __func__,
64 le32_to_cpu(sts_entry->handle), srb)); 34 le32_to_cpu(sts_entry->handle), srb));
35 dev_warn(&ha->pdev->dev, "%s invalid status entry:"
36 " handle=0x%0x\n", __func__, sts_entry->handle);
37 set_bit(DPC_RESET_HA, &ha->dpc_flags);
65 return; 38 return;
66 } 39 }
67 40
@@ -88,10 +61,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
88 scsi_status = sts_entry->scsiStatus; 61 scsi_status = sts_entry->scsiStatus;
89 switch (sts_entry->completionStatus) { 62 switch (sts_entry->completionStatus) {
90 case SCS_COMPLETE: 63 case SCS_COMPLETE:
91 if (scsi_status == 0) {
92 cmd->result = DID_OK << 16;
93 break;
94 }
95 64
96 if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { 65 if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
97 cmd->result = DID_ERROR << 16; 66 cmd->result = DID_ERROR << 16;
@@ -100,7 +69,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
100 69
101 if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) { 70 if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
102 scsi_set_resid(cmd, residual); 71 scsi_set_resid(cmd, residual);
103 if ((scsi_bufflen(cmd) - residual) < cmd->underflow) { 72 if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
73 cmd->underflow)) {
104 74
105 cmd->result = DID_ERROR << 16; 75 cmd->result = DID_ERROR << 16;
106 76
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 31e605caf0f1..0c786944d2c2 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1552,9 +1552,6 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
1552 goto eh_dev_reset_done; 1552 goto eh_dev_reset_done;
1553 } 1553 }
1554 1554
1555 /* Send marker. */
1556 ha->marker_needed = 1;
1557
1558 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), 1555 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
1559 cmd->device)) { 1556 cmd->device)) {
1560 dev_info(&ha->pdev->dev, 1557 dev_info(&ha->pdev->dev,
@@ -1563,6 +1560,11 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
1563 goto eh_dev_reset_done; 1560 goto eh_dev_reset_done;
1564 } 1561 }
1565 1562
1563 /* Send marker. */
1564 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
1565 MM_LUN_RESET) != QLA_SUCCESS)
1566 goto eh_dev_reset_done;
1567
1566 dev_info(&ha->pdev->dev, 1568 dev_info(&ha->pdev->dev,
1567 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", 1569 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
1568 ha->host_no, cmd->device->channel, cmd->device->id, 1570 ha->host_no, cmd->device->channel, cmd->device->id,
@@ -1606,9 +1608,6 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
1606 return FAILED; 1608 return FAILED;
1607 } 1609 }
1608 1610
1609 /* Send marker. */
1610 ha->marker_needed = 1;
1611
1612 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), 1611 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
1613 NULL)) { 1612 NULL)) {
1614 starget_printk(KERN_INFO, scsi_target(cmd->device), 1613 starget_printk(KERN_INFO, scsi_target(cmd->device),
@@ -1617,6 +1616,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
1617 return FAILED; 1616 return FAILED;
1618 } 1617 }
1619 1618
1619 /* Send marker. */
1620 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
1621 MM_TGT_WARM_RESET) != QLA_SUCCESS) {
1622 starget_printk(KERN_INFO, scsi_target(cmd->device),
1623 "WARM TARGET DEVICE RESET FAILED - "
1624 "marker iocb failed.\n");
1625 return FAILED;
1626 }
1627
1620 starget_printk(KERN_INFO, scsi_target(cmd->device), 1628 starget_printk(KERN_INFO, scsi_target(cmd->device),
1621 "WARM TARGET RESET SUCCEEDED.\n"); 1629 "WARM TARGET RESET SUCCEEDED.\n");
1622 return SUCCESS; 1630 return SUCCESS;