diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_isr.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 114 |
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 | ||