aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_isr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_isr.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c114
1 files changed, 69 insertions, 45 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 35b9e36a0e8d..4a154beb0d39 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -6,6 +6,9 @@
6 */ 6 */
7 7
8#include "ql4_def.h" 8#include "ql4_def.h"
9#include "ql4_glbl.h"
10#include "ql4_dbg.h"
11#include "ql4_inline.h"
9 12
10/** 13/**
11 * qla2x00_process_completed_request() - Process a Fast Post response. 14 * qla2x00_process_completed_request() - Process a Fast Post response.
@@ -90,9 +93,29 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
90 break; 93 break;
91 } 94 }
92 95
93 if (sts_entry->iscsiFlags & 96 if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
94 (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER)) 97 cmd->result = DID_ERROR << 16;
95 cmd->resid = residual; 98 break;
99 }
100
101 if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
102 scsi_set_resid(cmd, residual);
103 if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
104 cmd->underflow)) {
105
106 cmd->result = DID_ERROR << 16;
107
108 DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
109 "Mid-layer Data underrun0, "
110 "xferlen = 0x%x, "
111 "residual = 0x%x\n", ha->host_no,
112 cmd->device->channel,
113 cmd->device->id,
114 cmd->device->lun, __func__,
115 scsi_bufflen(cmd), residual));
116 break;
117 }
118 }
96 119
97 cmd->result = DID_OK << 16 | scsi_status; 120 cmd->result = DID_OK << 16 | scsi_status;
98 121
@@ -161,7 +184,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
161 184
162 case SCS_DATA_UNDERRUN: 185 case SCS_DATA_UNDERRUN:
163 case SCS_DATA_OVERRUN: 186 case SCS_DATA_OVERRUN:
164 if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { 187 if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) ||
188 (sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
165 DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, " 189 DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, "
166 "residual = 0x%x\n", ha->host_no, 190 "residual = 0x%x\n", ha->host_no,
167 cmd->device->channel, cmd->device->id, 191 cmd->device->channel, cmd->device->id,
@@ -171,21 +195,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
171 break; 195 break;
172 } 196 }
173 197
174 if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) { 198 scsi_set_resid(cmd, residual);
175 /*
176 * Firmware detected a SCSI transport underrun
177 * condition
178 */
179 cmd->resid = residual;
180 DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status "
181 "detected, xferlen = 0x%x, residual = "
182 "0x%x\n",
183 ha->host_no, cmd->device->channel,
184 cmd->device->id,
185 cmd->device->lun, __func__,
186 cmd->request_bufflen,
187 residual));
188 }
189 199
190 /* 200 /*
191 * If there is scsi_status, it takes precedense over 201 * If there is scsi_status, it takes precedense over
@@ -227,7 +237,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
227 if ((sts_entry->iscsiFlags & 237 if ((sts_entry->iscsiFlags &
228 ISCSI_FLAG_RESIDUAL_UNDER) == 0) { 238 ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
229 cmd->result = DID_BUS_BUSY << 16; 239 cmd->result = DID_BUS_BUSY << 16;
230 } else if ((cmd->request_bufflen - residual) < 240 } else if ((scsi_bufflen(cmd) - residual) <
231 cmd->underflow) { 241 cmd->underflow) {
232 /* 242 /*
233 * Handle mid-layer underflow??? 243 * Handle mid-layer underflow???
@@ -242,13 +252,13 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
242 * will return DID_ERROR. 252 * will return DID_ERROR.
243 */ 253 */
244 DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " 254 DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
245 "Mid-layer Data underrun, " 255 "Mid-layer Data underrun1, "
246 "xferlen = 0x%x, " 256 "xferlen = 0x%x, "
247 "residual = 0x%x\n", ha->host_no, 257 "residual = 0x%x\n", ha->host_no,
248 cmd->device->channel, 258 cmd->device->channel,
249 cmd->device->id, 259 cmd->device->id,
250 cmd->device->lun, __func__, 260 cmd->device->lun, __func__,
251 cmd->request_bufflen, residual)); 261 scsi_bufflen(cmd), residual));
252 262
253 cmd->result = DID_ERROR << 16; 263 cmd->result = DID_ERROR << 16;
254 } else { 264 } else {
@@ -417,6 +427,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
417 uint32_t mbox_status) 427 uint32_t mbox_status)
418{ 428{
419 int i; 429 int i;
430 uint32_t mbox_stat2, mbox_stat3;
420 431
421 if ((mbox_status == MBOX_STS_BUSY) || 432 if ((mbox_status == MBOX_STS_BUSY) ||
422 (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || 433 (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
@@ -437,6 +448,12 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
437 } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { 448 } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
438 /* Immediately process the AENs that don't require much work. 449 /* Immediately process the AENs that don't require much work.
439 * Only queue the database_changed AENs */ 450 * Only queue the database_changed AENs */
451 if (ha->aen_log.count < MAX_AEN_ENTRIES) {
452 for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
453 ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
454 readl(&ha->reg->mailbox[i]);
455 ha->aen_log.count++;
456 }
440 switch (mbox_status) { 457 switch (mbox_status) {
441 case MBOX_ASTS_SYSTEM_ERROR: 458 case MBOX_ASTS_SYSTEM_ERROR:
442 /* Log Mailbox registers */ 459 /* Log Mailbox registers */
@@ -493,6 +510,16 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
493 mbox_status)); 510 mbox_status));
494 break; 511 break;
495 512
513 case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
514 mbox_stat2 = readl(&ha->reg->mailbox[2]);
515 mbox_stat3 = readl(&ha->reg->mailbox[3]);
516
517 if ((mbox_stat3 == 5) && (mbox_stat2 == 3))
518 set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
519 else if ((mbox_stat3 == 2) && (mbox_stat2 == 5))
520 set_bit(DPC_RESET_HA, &ha->dpc_flags);
521 break;
522
496 case MBOX_ASTS_MAC_ADDRESS_CHANGED: 523 case MBOX_ASTS_MAC_ADDRESS_CHANGED:
497 case MBOX_ASTS_DNS: 524 case MBOX_ASTS_DNS:
498 /* No action */ 525 /* No action */
@@ -518,11 +545,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
518 /* Queue AEN information and process it in the DPC 545 /* Queue AEN information and process it in the DPC
519 * routine */ 546 * routine */
520 if (ha->aen_q_count > 0) { 547 if (ha->aen_q_count > 0) {
521 /* advance pointer */
522 if (ha->aen_in == (MAX_AEN_ENTRIES - 1))
523 ha->aen_in = 0;
524 else
525 ha->aen_in++;
526 548
527 /* decrement available counter */ 549 /* decrement available counter */
528 ha->aen_q_count--; 550 ha->aen_q_count--;
@@ -542,6 +564,10 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
542 ha->aen_q[ha->aen_in].mbox_sts[2], 564 ha->aen_q[ha->aen_in].mbox_sts[2],
543 ha->aen_q[ha->aen_in].mbox_sts[3], 565 ha->aen_q[ha->aen_in].mbox_sts[3],
544 ha->aen_q[ha->aen_in]. mbox_sts[4])); 566 ha->aen_q[ha->aen_in]. mbox_sts[4]));
567 /* advance pointer */
568 ha->aen_in++;
569 if (ha->aen_in == MAX_AEN_ENTRIES)
570 ha->aen_in = 0;
545 571
546 /* The DPC routine will process the aen */ 572 /* The DPC routine will process the aen */
547 set_bit(DPC_AEN, &ha->dpc_flags); 573 set_bit(DPC_AEN, &ha->dpc_flags);
@@ -724,25 +750,24 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
724 750
725 spin_lock_irqsave(&ha->hardware_lock, flags); 751 spin_lock_irqsave(&ha->hardware_lock, flags);
726 while (ha->aen_out != ha->aen_in) { 752 while (ha->aen_out != ha->aen_in) {
727 /* Advance pointers for next entry */
728 if (ha->aen_out == (MAX_AEN_ENTRIES - 1))
729 ha->aen_out = 0;
730 else
731 ha->aen_out++;
732
733 ha->aen_q_count++;
734 aen = &ha->aen_q[ha->aen_out]; 753 aen = &ha->aen_q[ha->aen_out];
735
736 /* copy aen information to local structure */ 754 /* copy aen information to local structure */
737 for (i = 0; i < MBOX_AEN_REG_COUNT; i++) 755 for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
738 mbox_sts[i] = aen->mbox_sts[i]; 756 mbox_sts[i] = aen->mbox_sts[i];
739 757
758 ha->aen_q_count++;
759 ha->aen_out++;
760
761 if (ha->aen_out == MAX_AEN_ENTRIES)
762 ha->aen_out = 0;
763
740 spin_unlock_irqrestore(&ha->hardware_lock, flags); 764 spin_unlock_irqrestore(&ha->hardware_lock, flags);
741 765
742 DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x " 766 DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
743 "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out, 767 " mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
744 mbox_sts[0], mbox_sts[2], mbox_sts[3], 768 (ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
745 mbox_sts[1], mbox_sts[4])); 769 mbox_sts[0], mbox_sts[1], mbox_sts[2],
770 mbox_sts[3], mbox_sts[4]));
746 771
747 switch (mbox_sts[0]) { 772 switch (mbox_sts[0]) {
748 case MBOX_ASTS_DATABASE_CHANGED: 773 case MBOX_ASTS_DATABASE_CHANGED:
@@ -792,6 +817,5 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
792 spin_lock_irqsave(&ha->hardware_lock, flags); 817 spin_lock_irqsave(&ha->hardware_lock, flags);
793 } 818 }
794 spin_unlock_irqrestore(&ha->hardware_lock, flags); 819 spin_unlock_irqrestore(&ha->hardware_lock, flags);
795
796} 820}
797 821