diff options
author | David C Somayajulu <david.somayajulu@qlogic.com> | 2008-03-19 14:23:03 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-07 13:19:00 -0400 |
commit | 9d56291366cd6ab156be722e42cf487bef20f5fd (patch) | |
tree | d85fadb003a7ed4a3ac8380487423a2b6ce31bb2 /drivers/scsi | |
parent | af7a5647c03c18f5ea58033710ccb23d71727e0c (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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 3 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_iocb.c | 14 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 40 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 20 |
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); | |||
70 | int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, | 70 | int 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); |
72 | void qla4xxx_dump_buffer(void *b, uint32_t size); | 72 | void qla4xxx_dump_buffer(void *b, uint32_t size); |
73 | int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, | ||
74 | struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); | ||
73 | 75 | ||
74 | extern int ql4xextended_error_logging; | 76 | extern int ql4xextended_error_logging; |
75 | extern int ql4xdiscoverywait; | 77 | extern 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 | **/ |
69 | static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, | 69 | int 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 | **/ | ||
18 | static 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; |