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 35b9e36a0e8..4a154beb0d3 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -6,6 +6,9 @@ */ #include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" /** * qla2x00_process_completed_request() - Process a Fast Post response. @@ -90,9 +93,29 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; } - if (sts_entry->iscsiFlags & - (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER)) - cmd->resid = residual; + if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { + cmd->result = DID_ERROR << 16; + break; + } + + if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) { + scsi_set_resid(cmd, residual); + if (!scsi_status && ((scsi_bufflen(cmd) - residual) < + cmd->underflow)) { + + cmd->result = DID_ERROR << 16; + + DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " + "Mid-layer Data underrun0, " + "xferlen = 0x%x, " + "residual = 0x%x\n", ha->host_no, + cmd->device->channel, + cmd->device->id, + cmd->device->lun, __func__, + scsi_bufflen(cmd), residual)); + break; + } + } cmd->result = DID_OK << 16 | scsi_status; @@ -161,7 +184,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, case SCS_DATA_UNDERRUN: case SCS_DATA_OVERRUN: - if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { + if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) || + (sts_entry->completionStatus == SCS_DATA_OVERRUN)) { DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, " "residual = 0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, @@ -171,21 +195,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; } - if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) { - /* - * Firmware detected a SCSI transport underrun - * condition - */ - cmd->resid = residual; - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status " - "detected, xferlen = 0x%x, residual = " - "0x%x\n", - ha->host_no, cmd->device->channel, - cmd->device->id, - cmd->device->lun, __func__, - cmd->request_bufflen, - residual)); - } + scsi_set_resid(cmd, residual); /* * If there is scsi_status, it takes precedense over @@ -227,7 +237,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) { cmd->result = DID_BUS_BUSY << 16; - } else if ((cmd->request_bufflen - residual) < + } else if ((scsi_bufflen(cmd) - residual) < cmd->underflow) { /* * Handle mid-layer underflow??? @@ -242,13 +252,13 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, * will return DID_ERROR. */ DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " - "Mid-layer Data underrun, " - "xferlen = 0x%x, " - "residual = 0x%x\n", ha->host_no, - cmd->device->channel, - cmd->device->id, - cmd->device->lun, __func__, - cmd->request_bufflen, residual)); + "Mid-layer Data underrun1, " + "xferlen = 0x%x, " + "residual = 0x%x\n", ha->host_no, + cmd->device->channel, + cmd->device->id, + cmd->device->lun, __func__, + scsi_bufflen(cmd), residual)); cmd->result = DID_ERROR << 16; } else { @@ -417,6 +427,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, uint32_t mbox_status) { int i; + uint32_t mbox_stat2, mbox_stat3; if ((mbox_status == MBOX_STS_BUSY) || (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || @@ -437,6 +448,12 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { /* Immediately process the AENs that don't require much work. * Only queue the database_changed AENs */ + if (ha->aen_log.count < MAX_AEN_ENTRIES) { + for (i = 0; i < MBOX_AEN_REG_COUNT; i++) + ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] = + readl(&ha->reg->mailbox[i]); + ha->aen_log.count++; + } switch (mbox_status) { case MBOX_ASTS_SYSTEM_ERROR: /* Log Mailbox registers */ @@ -493,6 +510,16 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, mbox_status)); break; + case MBOX_ASTS_IP_ADDR_STATE_CHANGED: + mbox_stat2 = readl(&ha->reg->mailbox[2]); + mbox_stat3 = readl(&ha->reg->mailbox[3]); + + if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) + set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); + else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) + set_bit(DPC_RESET_HA, &ha->dpc_flags); + break; + case MBOX_ASTS_MAC_ADDRESS_CHANGED: case MBOX_ASTS_DNS: /* No action */ @@ -518,11 +545,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, /* Queue AEN information and process it in the DPC * routine */ if (ha->aen_q_count > 0) { - /* advance pointer */ - if (ha->aen_in == (MAX_AEN_ENTRIES - 1)) - ha->aen_in = 0; - else - ha->aen_in++; /* decrement available counter */ ha->aen_q_count--; @@ -542,6 +564,10 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, ha->aen_q[ha->aen_in].mbox_sts[2], ha->aen_q[ha->aen_in].mbox_sts[3], ha->aen_q[ha->aen_in]. mbox_sts[4])); + /* advance pointer */ + ha->aen_in++; + if (ha->aen_in == MAX_AEN_ENTRIES) + ha->aen_in = 0; /* The DPC routine will process the aen */ set_bit(DPC_AEN, &ha->dpc_flags); @@ -724,25 +750,24 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) spin_lock_irqsave(&ha->hardware_lock, flags); while (ha->aen_out != ha->aen_in) { - /* Advance pointers for next entry */ - if (ha->aen_out == (MAX_AEN_ENTRIES - 1)) - ha->aen_out = 0; - else - ha->aen_out++; - - ha->aen_q_count++; aen = &ha->aen_q[ha->aen_out]; - /* copy aen information to local structure */ for (i = 0; i < MBOX_AEN_REG_COUNT; i++) mbox_sts[i] = aen->mbox_sts[i]; + ha->aen_q_count++; + ha->aen_out++; + + if (ha->aen_out == MAX_AEN_ENTRIES) + ha->aen_out = 0; + spin_unlock_irqrestore(&ha->hardware_lock, flags); - DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x " - "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out, - mbox_sts[0], mbox_sts[2], mbox_sts[3], - mbox_sts[1], mbox_sts[4])); + DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x" + " mbx3=0x%08x mbx4=0x%08x\n", ha->host_no, + (ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)), + mbox_sts[0], mbox_sts[1], mbox_sts[2], + mbox_sts[3], mbox_sts[4])); switch (mbox_sts[0]) { case MBOX_ASTS_DATABASE_CHANGED: @@ -792,6 +817,5 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) spin_lock_irqsave(&ha->hardware_lock, flags); } spin_unlock_irqrestore(&ha->hardware_lock, flags); - } |