X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla4xxx%2Fql4_isr.c;h=a91a57c57bffbd979d7fbc2c4b0c9b7880ef5ac4;hb=dd32f7effdd2f3f348ef91ca1649d78a0ab2b103;hp=35b9e36a0e8dbaa924a7391ae33c98765120ddef;hpb=ce35a81a71f405031ed6fd0d454d3aaa55dc8ed2;p=linux-2.6 diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 35b9e36a0e..a91a57c57b 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -6,28 +6,9 @@ */ #include "ql4_def.h" - -/** - * qla2x00_process_completed_request() - Process a Fast Post response. - * @ha: SCSI driver HA context - * @index: SRB index - **/ -static void qla4xxx_process_completed_request(struct scsi_qla_host *ha, - uint32_t index) -{ - struct srb *srb; - - srb = qla4xxx_del_from_active_array(ha, index); - if (srb) { - /* Save ISP completion status */ - srb->cmd->result = DID_OK << 16; - qla4xxx_srb_compl(ha, srb); - } else { - DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = " - "%d\n", ha->host_no, index)); - set_bit(DPC_RESET_HA, &ha->dpc_flags); - } -} +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" /** * qla4xxx_status_entry - processes status IOCBs @@ -44,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, uint32_t residual; uint16_t sensebytecnt; - if (sts_entry->completionStatus == SCS_COMPLETE && - sts_entry->scsiStatus == 0) { - qla4xxx_process_completed_request(ha, - le32_to_cpu(sts_entry-> - handle)); - return; - } - srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); if (!srb) { /* FIXMEdg: Don't we need to reset ISP in this case??? */ @@ -59,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, "handle 0x%x, sp=%p. This cmd may have already " "been completed.\n", ha->host_no, __func__, le32_to_cpu(sts_entry->handle), srb)); + dev_warn(&ha->pdev->dev, "%s invalid status entry:" + " handle=0x%0x\n", __func__, sts_entry->handle); + set_bit(DPC_RESET_HA, &ha->dpc_flags); return; } @@ -85,14 +61,30 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, scsi_status = sts_entry->scsiStatus; switch (sts_entry->completionStatus) { case SCS_COMPLETE: - if (scsi_status == 0) { - cmd->result = DID_OK << 16; + + if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { + cmd->result = DID_ERROR << 16; break; } - if (sts_entry->iscsiFlags & - (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER)) - cmd->resid = residual; + 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; @@ -100,15 +92,14 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; /* Copy Sense Data into sense buffer. */ - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt); if (sensebytecnt == 0) break; memcpy(cmd->sense_buffer, sts_entry->senseData, - min(sensebytecnt, - (uint16_t) sizeof(cmd->sense_buffer))); + min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE)); DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, " "ASC/ASCQ = %02x/%02x\n", ha->host_no, @@ -161,7 +152,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 +163,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 @@ -198,8 +176,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; /* Copy Sense Data into sense buffer. */ - memset(cmd->sense_buffer, 0, - sizeof(cmd->sense_buffer)); + memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt); @@ -207,8 +184,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; memcpy(cmd->sense_buffer, sts_entry->senseData, - min(sensebytecnt, - (uint16_t) sizeof(cmd->sense_buffer))); + min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE)); DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, " "ASC/ASCQ = %02x/%02x\n", ha->host_no, @@ -227,7 +203,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 +218,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 +393,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 +414,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 +476,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 +511,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 +530,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 +716,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 +783,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); - }