ocfs2: Move buckets up into ocfs2_add_new_xattr_cluster().
[safe/jmp/linux-2.6] / drivers / scsi / qla4xxx / ql4_isr.c
index 35b9e36..799120f 100644 (file)
@@ -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,
@@ -148,7 +139,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
                              ha->host_no, cmd->device->channel,
                              cmd->device->id, cmd->device->lun));
 
-               cmd->result = DID_BUS_BUSY << 16;
+               cmd->result = DID_TRANSPORT_DISRUPTED << 16;
 
                /*
                 * Mark device missing so that we won't continue to send
@@ -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 {
@@ -267,7 +243,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
                if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
                        qla4xxx_mark_device_missing(ha, ddb_entry);
 
-               cmd->result = DID_BUS_BUSY << 16;
+               cmd->result = DID_TRANSPORT_DISRUPTED << 16;
                break;
 
        case SCS_QUEUE_FULL:
@@ -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);
-
 }