Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / drivers / message / fusion / mptscsih.c
index 30524dc..84fa271 100644 (file)
@@ -66,7 +66,6 @@
 
 #include "mptbase.h"
 #include "mptscsih.h"
-#include "lsi/mpi_log_sas.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #define my_NAME                "Fusion MPT SCSI Host driver"
@@ -128,7 +127,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
 static void    mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int     mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 static int     mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
-static int     SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
+static u32     SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
 
 static int     mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 
@@ -498,34 +497,6 @@ nextSGEset:
        return SUCCESS;
 } /* mptscsih_AddSGE() */
 
-static void
-mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
-    U32 SlotStatus)
-{
-       MPT_FRAME_HDR *mf;
-       SEPRequest_t     *SEPMsg;
-
-       if (ioc->bus_type == FC)
-               return;
-
-       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
-               dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
-                   ioc->name,__FUNCTION__));
-               return;
-       }
-
-       SEPMsg = (SEPRequest_t *)mf;
-       SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-       SEPMsg->Bus = vtarget->bus_id;
-       SEPMsg->TargetID = vtarget->target_id;
-       SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
-       SEPMsg->SlotStatus = SlotStatus;
-       devtverboseprintk((MYIOC_s_WARN_FMT
-           "Sending SEP cmd=%x id=%d bus=%d\n",
-           ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
-       mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -549,8 +520,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        SCSIIORequest_t *pScsiReq;
        SCSIIOReply_t   *pScsiReply;
        u16              req_idx, req_idx_MR;
-       VirtDevice       *vdev;
-       VirtTarget       *vtarget;
 
        hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
 
@@ -569,7 +538,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        }
 
        sc = hd->ScsiLookup[req_idx];
-       hd->ScsiLookup[req_idx] = NULL;
        if (sc == NULL) {
                MPIHeader_t *hdr = (MPIHeader_t *)mf;
 
@@ -585,12 +553,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                return 1;
        }
 
-       if ((unsigned char *)mf != sc->host_scribble) {
-               mptscsih_freeChainBuffers(ioc, req_idx);
-               return 1;
-       }
-
-       sc->host_scribble = NULL;
        sc->result = DID_OK << 16;              /* Set default reply as OK */
        pScsiReq = (SCSIIORequest_t *) mf;
        pScsiReply = (SCSIIOReply_t *) mr;
@@ -678,36 +640,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                        if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
                                hd->sel_timeout[pScsiReq->TargetID]++;
-
-                       vdev = sc->device->hostdata;
-                       if (!vdev)
-                               break;
-                       vtarget = vdev->vtarget;
-                       if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
-                               mptscsih_issue_sep_command(ioc, vtarget,
-                                   MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
-                               vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
-                       }
                        break;
 
-               case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
-                       if ( ioc->bus_type == SAS ) {
-                               u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
-                               if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
-                                       u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
-                                       log_info &=SAS_LOGINFO_MASK;
-                                       if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
-                                               sc->result = (DID_BUS_BUSY << 16);
-                                               break;
-                                       }
-                               }
-                       }
-
-                       /*
-                        * Allow non-SAS & non-NEXUS_LOSS to drop into below code
-                        */
-
                case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
+               case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
                case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
                        /* Linux handles an unsolicited DID_RESET better
                         * than an unsolicited DID_ABORT.
@@ -722,7 +658,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                sc->result=DID_SOFT_ERROR << 16;
                        else /* Sufficient data transfer occurred */
                                sc->result = (DID_OK << 16) | scsi_status;
-                       dreplyprintk((KERN_NOTICE
+                       dreplyprintk((KERN_NOTICE 
                            "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
                        break;
 
@@ -848,6 +784,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                sc->request_bufflen, sc->sc_data_direction);
        }
 
+       hd->ScsiLookup[req_idx] = NULL;
+
        sc->scsi_done(sc);              /* Issue the command callback */
 
        /* Free Chain buffers */
@@ -889,17 +827,9 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
                        dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
                                        mf, SCpnt));
 
-                       /* Free Chain buffers */
-                       mptscsih_freeChainBuffers(ioc, ii);
-
-                       /* Free Message frames */
-                       mpt_free_msg_frame(ioc, mf);
-
-                       if ((unsigned char *)mf != SCpnt->host_scribble)
-                               continue;
-
                        /* Set status, free OS resources (SG DMA buffers)
                         * Do OS callback
+                        * Free driver resources (chain, msg buffers)
                         */
                        if (SCpnt->use_sg) {
                                pci_unmap_sg(ioc->pcidev,
@@ -915,6 +845,12 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
                        SCpnt->result = DID_RESET << 16;
                        SCpnt->host_scribble = NULL;
 
+                       /* Free Chain buffers */
+                       mptscsih_freeChainBuffers(ioc, ii);
+
+                       /* Free Message frames */
+                       mpt_free_msg_frame(ioc, mf);
+
                        SCpnt->scsi_done(SCpnt);        /* Issue the command callback */
                }
        }
@@ -951,10 +887,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
                if ((sc = hd->ScsiLookup[ii]) != NULL) {
 
                        mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
-                       if (mf == NULL)
-                               continue;
+
                        dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
                                        hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
+
                        if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
                                continue;
 
@@ -963,8 +899,6 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
                        hd->ScsiLookup[ii] = NULL;
                        mptscsih_freeChainBuffers(hd->ioc, ii);
                        mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
-                       if ((unsigned char *)mf != sc->host_scribble)
-                               continue;
                        if (sc->use_sg) {
                                pci_unmap_sg(hd->ioc->pcidev,
                                (struct scatterlist *) sc->request_buffer,
@@ -1407,8 +1341,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
                        goto fail;
        }
 
-       SCpnt->host_scribble = (unsigned char *)mf;
        hd->ScsiLookup[my_idx] = SCpnt;
+       SCpnt->host_scribble = NULL;
 
        mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
        dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
@@ -1595,12 +1529,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
                rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
        }
 
-       /*
-        * Check IOCStatus from TM reply message
-        */
-        if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
-               rc = FAILED;
-
        dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
 
        return rc;
@@ -1726,7 +1654,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        int              scpnt_idx;
        int              retval;
        VirtDevice       *vdev;
-       ulong            sn = SCpnt->serial_number;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
@@ -1780,11 +1707,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
                ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
 
-       if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
-           SCpnt->serial_number == sn) {
-               retval = FAILED;
-       }
-
        printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
                hd->ioc->name,
                ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2000,7 +1922,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
                        break;
                }
                spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-               msleep(250);
+               msleep_interruptible(250);
        } while (--loop_count);
 
        return status;
@@ -2101,7 +2023,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
 
                iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-               hd->tm_iocstatus = iocstatus;
                dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
                        ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
                /* Error?  (anything non-zero?) */
@@ -2480,13 +2401,6 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
                                ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
 
                                ioc->eventContext++;
-                               if (hd->ioc->pcidev->vendor ==
-                                   PCI_VENDOR_ID_IBM) {
-                                       mptscsih_issue_sep_command(hd->ioc,
-                                           vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
-                                       vdev->vtarget->tflags |=
-                                           MPT_TARGET_FLAGS_LED_ON;
-                               }
                        }
                }
        } else {
@@ -2495,7 +2409,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
        }
 }
 
-static int
+static u32
 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
 {
        MPT_SCSI_HOST *hd;
@@ -2607,6 +2521,18 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                        hd->cmdPtr = NULL;
                }
 
+               /* 7. FC: Rescan for blocked rports which might have returned.
+                */
+               if (ioc->bus_type == FC) {
+                       spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+                       if (ioc->fc_rescan_work_q) {
+                               if (ioc->fc_rescan_work_count++ == 0) {
+                                       queue_work(ioc->fc_rescan_work_q,
+                                                  &ioc->fc_rescan_work);
+                               }
+                       }
+                       spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+               }
                dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
        }
@@ -2620,6 +2546,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
        MPT_SCSI_HOST *hd;
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+       unsigned long flags;
 
        devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
@@ -2642,6 +2569,14 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                break;
 
        case MPI_EVENT_RESCAN:                          /* 06 */
+               spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+               if (ioc->fc_rescan_work_q) {
+                       if (ioc->fc_rescan_work_count++ == 0) {
+                               queue_work(ioc->fc_rescan_work_q,
+                                          &ioc->fc_rescan_work);
+                       }
+               }
+               spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
                break;
 
                /*