]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/message/fusion/mptscsih.c
[SCSI] fusion: FC rport code fixes
[linux-2.6-omap-h63xx.git] / drivers / message / fusion / mptscsih.c
index 4330ed0cedaaaafbc2a435b73c1b42b4aadc43d9..56c3d1f78f0500f8ec250d4fc2551500d6110f82 100644 (file)
@@ -150,28 +150,27 @@ static int        mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 tar
 int            mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 int            mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
-static void    mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-static void    mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
-static void    mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
+static void    mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen);
+static void    mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56);
 static void    mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
-static void    mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
+static void    mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
 static int     mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
 static int     mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
 int            mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int     mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
-static int     mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
-
-static struct work_struct   mptscsih_persistTask;
+static void    mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
+static void    mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
+static int     mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 static int     mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
 static void    mptscsih_domainValidation(void *hd);
-static int     mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
 static void    mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
 static int     mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
 static void    mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
 static void    mptscsih_fillbuf(char *buffer, int size, int index, int width);
 static void    mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
+static void    mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
 #endif
 
 void           mptscsih_remove(struct pci_dev *);
@@ -627,7 +626,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
                        "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
                        "resid=%d bufflen=%d xfer_cnt=%d\n",
-                       ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+                       ioc->id, sc->device->id, sc->device->lun,
                        status, scsi_state, scsi_status, sc->resid,
                        sc->request_bufflen, xfer_cnt));
 
@@ -641,7 +640,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                    pScsiReply->ResponseInfo) {
                        printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
                        "FCP_ResponseInfo=%08xh\n",
-                       ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+                       ioc->id, sc->device->id, sc->device->lun,
                        le32_to_cpu(pScsiReply->ResponseInfo));
                }
 
@@ -677,8 +676,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        sc->result = DID_RESET << 16;
 
                        /* GEM Workaround. */
-                       if (ioc->bus_type == SCSI)
-                               mptscsih_no_negotiate(hd, sc->device->id);
+                       if (ioc->bus_type == SPI)
+                               mptscsih_no_negotiate(hd, sc);
                        break;
 
                case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
@@ -892,16 +891,16 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
  *             when a lun is disable by mid-layer.
  *             Do NOT access the referenced scsi_cmnd structure or
  *             members. Will cause either a paging or NULL ptr error.
- *     @hd: Pointer to a SCSI HOST structure
- *     @target: target id
- *     @lun: lun
+ *             (BUT, BUT, BUT, the code does reference it! - mdr)
+ *      @hd: Pointer to a SCSI HOST structure
+ *     @vdevice: per device private data
  *
  *     Returns: None.
  *
  *     Called from slave_destroy.
  */
 static void
-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
+mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 {
        SCSIIORequest_t *mf = NULL;
        int              ii;
@@ -909,7 +908,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
        struct scsi_cmnd *sc;
 
        dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-                       target, lun, max));
+                       vdevice->target_id, vdevice->lun, max));
 
        for (ii=0; ii < max; ii++) {
                if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -919,7 +918,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
                        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)target)) || (mf->LUN[1] != ((u8) lun)))
+                       if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
                                continue;
 
                        /* Cleanup
@@ -993,8 +992,10 @@ mptscsih_remove(struct pci_dev *pdev)
        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
        struct Scsi_Host        *host = ioc->sh;
        MPT_SCSI_HOST           *hd;
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
        int                     count;
        unsigned long           flags;
+#endif 
        int sz1;
 
        if(!host) {
@@ -1075,11 +1076,6 @@ mptscsih_shutdown(struct pci_dev *pdev)
 
        hd = (MPT_SCSI_HOST *)host->hostdata;
 
-       /* Flush the cache of this adapter
-        */
-       if(hd != NULL)
-               mptscsih_synchronize_cache(hd, 0);
-
 }
 
 #ifdef CONFIG_PM
@@ -1286,7 +1282,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        MPT_SCSI_HOST           *hd;
        MPT_FRAME_HDR           *mf;
        SCSIIORequest_t         *pScsiReq;
-       VirtDevice              *pTarget = SCpnt->device->hostdata;
+       VirtDevice              *vdev = SCpnt->device->hostdata;
        int      lun;
        u32      datalen;
        u32      scsictl;
@@ -1341,8 +1337,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        /* Default to untagged. Once a target structure has been allocated,
         * use the Inquiry data to determine if device supports tagged.
         */
-       if (pTarget
-           && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+       if (vdev
+           && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
            && (SCpnt->device->tagged_supported)) {
                scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
        } else {
@@ -1351,8 +1347,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
        /* Use the above information to set up the message frame
         */
-       pScsiReq->TargetID = (u8) pTarget->target_id;
-       pScsiReq->Bus = pTarget->bus_id;
+       pScsiReq->TargetID = (u8) vdev->target_id;
+       pScsiReq->Bus = vdev->bus_id;
        pScsiReq->ChainOffset = 0;
        pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
        pScsiReq->CDBLength = SCpnt->cmd_len;
@@ -1403,8 +1399,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        SCpnt->host_scribble = NULL;
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       if (hd->ioc->bus_type == SCSI) {
-               int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];
+       if (hd->ioc->bus_type == SPI) {
+               int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id];
                int issueCmd = 1;
 
                if (dvStatus || hd->ioc->spi_data.forceDv) {
@@ -1437,7 +1433,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
                        /* Set the DV flags.
                         */
                        if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
-                               mptscsih_set_dvflags(hd, pScsiReq);
+                               mptscsih_set_dvflags(hd, SCpnt);
 
                        if (!issueCmd)
                                goto fail;
@@ -1741,6 +1737,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        u32              ctx2abort;
        int              scpnt_idx;
        int              retval;
+       VirtDevice       *vdev;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
@@ -1790,8 +1787,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        hd->abortSCpnt = SCpnt;
 
+       vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-               SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
+               vdev->bus_id, vdev->target_id, vdev->lun,
                ctx2abort, 2 /* 2 second timeout */);
 
        printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
@@ -1822,6 +1820,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
        int              retval;
+       VirtDevice       *vdev;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
@@ -1839,8 +1838,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
               hd->ioc->name, SCpnt);
        scsi_print_command(SCpnt);
 
+       vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-               SCpnt->device->channel, SCpnt->device->id,
+               vdev->bus_id, vdev->target_id,
                0, 0, 5 /* 5 second timeout */);
 
        printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1871,6 +1871,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
        int              retval;
+       VirtDevice       *vdev;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
@@ -1888,8 +1889,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
        if (hd->timeouts < -1)
                hd->timeouts++;
 
+       vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-               SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */);
+               vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
 
        printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
                hd->ioc->name,
@@ -2148,54 +2150,73 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
        return 0;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     OS entry point to allow host driver to alloc memory
+ *     for each scsi target. Called once per device the bus scan.
+ *     Return non-zero if allocation fails.
+ */
+int
+mptscsih_target_alloc(struct scsi_target *starget)
+{
+       VirtTarget              *vtarget;
+
+       vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+       if (!vtarget)
+               return -ENOMEM;
+       starget->hostdata = vtarget;
+       return 0;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     OS entry point to allow host driver to alloc memory
  *     for each scsi device. Called once per device the bus scan.
  *     Return non-zero if allocation fails.
- *     Init memory once per id (not LUN).
  */
 int
-mptscsih_slave_alloc(struct scsi_device *device)
+mptscsih_slave_alloc(struct scsi_device *sdev)
 {
-       struct Scsi_Host        *host = device->host;
+       struct Scsi_Host        *host = sdev->host;
        MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       VirtTarget              *vtarget;
        VirtDevice              *vdev;
-       uint                    target = device->id;
-
-       if (hd == NULL)
-               return -ENODEV;
+       struct scsi_target      *starget;
 
-       if ((vdev = hd->Targets[target]) != NULL)
-               goto out;
-
-       vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
        if (!vdev) {
                printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
                                hd->ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
 
-       memset(vdev, 0, sizeof(VirtDevice));
-       vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
        vdev->ioc_id = hd->ioc->id;
-       vdev->target_id = device->id;
-       vdev->bus_id = device->channel;
-       vdev->raidVolume = 0;
-       hd->Targets[device->id] = vdev;
-       if (hd->ioc->bus_type == SCSI) {
-               if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
-                       vdev->raidVolume = 1;
-                       ddvtprintk((KERN_INFO
-                           "RAID Volume @ id %d\n", device->id));
+       vdev->target_id = sdev->id;
+       vdev->bus_id = sdev->channel;
+       vdev->lun = sdev->lun;
+       sdev->hostdata = vdev;
+
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+       vdev->vtarget = vtarget;
+
+       if (vtarget->num_luns == 0) {
+               hd->Targets[sdev->id] = vtarget;
+               vtarget->ioc_id = hd->ioc->id;
+               vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+               vtarget->target_id = sdev->id;
+               vtarget->bus_id = sdev->channel;
+               if (hd->ioc->bus_type == SPI) {
+                       if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
+                               vtarget->raidVolume = 1;
+                               ddvtprintk((KERN_INFO
+                                   "RAID Volume @ id %d\n", sdev->id));
+                       }
+               } else {
+                       vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
                }
-       } else {
-               vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
        }
-
- out:
-       vdev->num_luns++;
-       device->hostdata = vdev;
+       vtarget->num_luns++;
        return 0;
 }
 
@@ -2204,40 +2225,52 @@ mptscsih_slave_alloc(struct scsi_device *device)
  *     Called if no device present or device being unloaded
  */
 void
-mptscsih_slave_destroy(struct scsi_device *device)
+mptscsih_target_destroy(struct scsi_target *starget)
 {
-       struct Scsi_Host        *host = device->host;
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
-       VirtDevice              *vdev;
-       uint                    target = device->id;
-       uint                    lun = device->lun;
-
-       if (hd == NULL)
-               return;
-
-       mptscsih_search_running_cmds(hd, target, lun);
-
-       vdev = hd->Targets[target];
-       vdev->luns[0] &= ~(1 << lun);
-       if (--vdev->num_luns)
-               return;
-
-       kfree(hd->Targets[target]);
-       hd->Targets[target] = NULL;
-
-       if (hd->ioc->bus_type == SCSI) {
-               if (mptscsih_is_phys_disk(hd->ioc, target)) {
-                       hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
-               } else {
-                       hd->ioc->spi_data.dvStatus[target] =
-                               MPT_SCSICFG_NEGOTIATE;
+       if (starget->hostdata)
+               kfree(starget->hostdata);
+       starget->hostdata = NULL;
+}
 
-                       if (!hd->negoNvram) {
-                               hd->ioc->spi_data.dvStatus[target] |=
-                                       MPT_SCSICFG_DV_NOT_DONE;
+/*
+ *     OS entry point to allow for host driver to free allocated memory
+ *     Called if no device present or device being unloaded
+ */
+void
+mptscsih_slave_destroy(struct scsi_device *sdev)
+{
+       struct Scsi_Host        *host = sdev->host;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       VirtTarget              *vtarget;
+       VirtDevice              *vdevice;
+       struct scsi_target      *starget;
+
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+       vdevice = sdev->hostdata;
+
+       mptscsih_search_running_cmds(hd, vdevice);
+       vtarget->luns[0] &= ~(1 << vdevice->lun);
+       vtarget->num_luns--;
+       if (vtarget->num_luns == 0) {
+               mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
+               if (hd->ioc->bus_type == SPI) {
+                       if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
+                               hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+                       } else {
+                               hd->ioc->spi_data.dvStatus[vtarget->target_id] =
+                                       MPT_SCSICFG_NEGOTIATE;
+                               if (!hd->negoNvram) {
+                                       hd->ioc->spi_data.dvStatus[vtarget->target_id] |=
+                                               MPT_SCSICFG_DV_NOT_DONE;
+                               }
                        }
                }
+               hd->Targets[sdev->id] = NULL;
        }
+       mptscsih_synchronize_cache(hd, vdevice);
+       kfree(vdevice);
+       sdev->hostdata = NULL;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2251,22 +2284,21 @@ mptscsih_slave_destroy(struct scsi_device *device)
 int
 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
-       VirtDevice *pTarget;
-       int     max_depth;
-       int     tagged;
-
-       if (hd == NULL)
-               return 0;
-       if (!(pTarget = hd->Targets[sdev->id]))
-               return 0;
-
-       if (hd->ioc->bus_type == SCSI) {
-               if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-                       if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+       VirtTarget              *vtarget;
+       struct scsi_target      *starget;
+       int                     max_depth;
+       int                     tagged;
+
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+
+       if (hd->ioc->bus_type == SPI) {
+               if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
+                       if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
                                max_depth = 1;
-                       else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
-                                (pTarget->minSyncFactor <= MPT_ULTRA160 ))
+                       else if (((vtarget->inq_data[0] & 0x1f) == 0x00) &&
+                                (vtarget->minSyncFactor <= MPT_ULTRA160 ))
                                max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
                        else
                                max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
@@ -2295,64 +2327,58 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
  *     Return non-zero if fails.
  */
 int
-mptscsih_slave_configure(struct scsi_device *device)
+mptscsih_slave_configure(struct scsi_device *sdev)
 {
-       struct Scsi_Host        *sh = device->host;
-       VirtDevice              *pTarget;
+       struct Scsi_Host        *sh = sdev->host;
+       VirtTarget              *vtarget;
+       VirtDevice              *vdevice;
+       struct scsi_target      *starget;
        MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
+       int                     indexed_lun, lun_index;
 
-       if ((hd == NULL) || (hd->Targets == NULL)) {
-               return 0;
-       }
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+       vdevice = sdev->hostdata;
 
        dsprintk((MYIOC_s_INFO_FMT
                "device @ %p, id=%d, LUN=%d, channel=%d\n",
-               hd->ioc->name, device, device->id, device->lun, device->channel));
-       dsprintk((MYIOC_s_INFO_FMT
-               "sdtr %d wdtr %d ppr %d inq length=%d\n",
-               hd->ioc->name, device->sdtr, device->wdtr,
-               device->ppr, device->inquiry_len));
-
-       if (device->id > sh->max_id) {
+               hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+       if (hd->ioc->bus_type == SPI)
+               dsprintk((MYIOC_s_INFO_FMT
+                   "sdtr %d wdtr %d ppr %d inq length=%d\n",
+                   hd->ioc->name, sdev->sdtr, sdev->wdtr,
+                   sdev->ppr, sdev->inquiry_len));
+
+       if (sdev->id > sh->max_id) {
                /* error case, should never happen */
-               scsi_adjust_queue_depth(device, 0, 1);
-               goto slave_configure_exit;
-       }
-
-       pTarget = hd->Targets[device->id];
-
-       if (pTarget == NULL) {
-               /* Driver doesn't know about this device.
-                * Kernel may generate a "Dummy Lun 0" which
-                * may become a real Lun if a
-                * "scsi add-single-device" command is executed
-                * while the driver is active (hot-plug a
-                * device).  LSI Raid controllers need
-                * queue_depth set to DEV_HIGH for this reason.
-                */
-               scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
-                       MPT_SCSI_CMD_PER_DEV_HIGH);
+               scsi_adjust_queue_depth(sdev, 0, 1);
                goto slave_configure_exit;
        }
 
-       mptscsih_initTarget(hd, device->channel, device->id, device->lun,
-               device->inquiry, device->inquiry_len );
-       mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
+       vdevice->configured_lun=1;
+       lun_index = (vdevice->lun >> 5);  /* 32 luns per lun_index */
+       indexed_lun = (vdevice->lun % 32);
+       vtarget->luns[lun_index] |= (1 << indexed_lun);
+       mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry,
+           sdev->inquiry_len );
+       mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
        dsprintk((MYIOC_s_INFO_FMT
                "Queue depth=%d, tflags=%x\n",
-               hd->ioc->name, device->queue_depth, pTarget->tflags));
+               hd->ioc->name, sdev->queue_depth, vtarget->tflags));
 
-       dsprintk((MYIOC_s_INFO_FMT
-               "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
-               hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
+       if (hd->ioc->bus_type == SPI)
+               dsprintk((MYIOC_s_INFO_FMT
+                   "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
+                   hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+                   vtarget->minSyncFactor));
 
 slave_configure_exit:
 
        dsprintk((MYIOC_s_INFO_FMT
                "tagged %d, simple %d, ordered %d\n",
-               hd->ioc->name,device->tagged_supported, device->simple_tags,
-               device->ordered_tags));
+               hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
+               sdev->ordered_tags));
 
        return 0;
 }
@@ -2370,16 +2396,14 @@ slave_configure_exit:
 static void
 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
 {
-       VirtDevice      *target;
+       VirtDevice      *vdev;
        SCSIIORequest_t *pReq;
        u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
-       int              index;
 
        /* Get target structure
         */
        pReq = (SCSIIORequest_t *) mf;
-       index = (int) pReq->TargetID;
-       target = hd->Targets[index];
+       vdev = sc->device->hostdata;
 
        if (sense_count) {
                u8 *sense_data;
@@ -2393,7 +2417,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
                /* Log SMART data (asc = 0x5D, non-IM case only) if required.
                 */
                if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
-                       if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
+                       if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
                                int idx;
                                MPT_ADAPTER *ioc = hd->ioc;
 
@@ -2403,7 +2427,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
 
                                ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
                                        (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
-                                       (pReq->Bus << 8) || pReq->TargetID;
+                                       (sc->device->channel << 8) || sc->device->id;
 
                                ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
 
@@ -2503,9 +2527,9 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                /* 2. Chain Buffer initialization
                 */
 
-               /* 4. Renegotiate to all devices, if SCSI
+               /* 4. Renegotiate to all devices, if SPI
                 */
-               if (ioc->bus_type == SCSI) {
+               if (ioc->bus_type == SPI) {
                        dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
                        mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
                }
@@ -2532,13 +2556,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                        hd->cmdPtr = NULL;
                }
 
-               /* 7. Set flag to force DV and re-read IOC Page 3
+               /* 7. SPI: Set flag to force DV and re-read IOC Page 3
                 */
-               if (ioc->bus_type == SCSI) {
+               if (ioc->bus_type == SPI) {
                        ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
                        ddvtprintk(("Set reload IOC Pg3 Flag\n"));
                }
 
+               /* 7. FC: Rescan for blocked rports which might have returned.
+                */
+               else if (ioc->bus_type == FC) {
+                       int work_count;
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+                       work_count = ++ioc->fc_rescan_work_count;
+                       spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+                       if (work_count == 1)
+                               schedule_work(&ioc->fc_rescan_work);
+               }
                dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
        }
@@ -2546,22 +2582,14 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        return 1;               /* currently means nothing really */
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* work queue thread to clear the persitency table */
-static void
-mptscsih_sas_persist_clear_table(void * arg)
-{
-       MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
-
-       mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 int
 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
        MPT_SCSI_HOST *hd;
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+       int work_count;
+       unsigned long flags;
 
        devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
@@ -2576,18 +2604,25 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                break;
        case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
        case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
-               if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
+               if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
                        hd->soft_resets++;
                break;
        case MPI_EVENT_LOGOUT:                          /* 09 */
                /* FIXME! */
                break;
 
+       case MPI_EVENT_RESCAN:                          /* 06 */
+               spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+               work_count = ++ioc->fc_rescan_work_count;
+               spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+               if (work_count == 1)
+                       schedule_work(&ioc->fc_rescan_work);
+               break;
+
                /*
                 *  CHECKME! Don't think we need to do
                 *  anything for these, but...
                 */
-       case MPI_EVENT_RESCAN:                          /* 06 */
        case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
        case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
                /*
@@ -2597,11 +2632,11 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 
        case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
        {
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
                pMpiEventDataRaid_t pRaidEventData =
                    (pMpiEventDataRaid_t) pEvReply->Data;
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
                /* Domain Validation Needed */
-               if (ioc->bus_type == SCSI &&
+               if (ioc->bus_type == SPI &&
                    pRaidEventData->ReasonCode ==
                    MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
                        mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
@@ -2609,13 +2644,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                break;
        }
 
-       /* Persistent table is full. */
-       case MPI_EVENT_PERSISTENT_TABLE_FULL:
-               INIT_WORK(&mptscsih_persistTask,
-                   mptscsih_sas_persist_clear_table,(void *)ioc);
-               schedule_work(&mptscsih_persistTask);
-               break;
-
        case MPI_EVENT_NONE:                            /* 00 */
        case MPI_EVENT_LOG_DATA:                        /* 01 */
        case MPI_EVENT_STATE_CHANGE:                    /* 02 */
@@ -2632,8 +2660,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 /*
  *     mptscsih_initTarget - Target, LUN alloc/free functionality.
  *     @hd: Pointer to MPT_SCSI_HOST structure
- *     @bus_id: Bus number (?)
- *     @target_id: SCSI target id
+ *     @vtarget: per target private data
  *     @lun: SCSI LUN id
  *     @data: Pointer to data
  *     @dlen: Number of INQUIRY bytes
@@ -2646,15 +2673,14 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
  *
  */
 static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
+mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
 {
-       int             indexed_lun, lun_index;
-       VirtDevice      *vdev;
        SpiCfgData      *pSpi;
        char            data_56;
+       int             inq_len;
 
        dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
-                       hd->ioc->name, bus_id, target_id, lun, hd));
+               hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
 
        /*
         * If the peripheral qualifier filter is enabled then if the target reports a 0x1
@@ -2674,75 +2700,68 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
        if (data[0] & 0xe0)
                return;
 
-       if ((vdev = hd->Targets[target_id]) == NULL) {
+       if (vtarget == NULL)
                return;
-       }
 
-       lun_index = (lun >> 5);  /* 32 luns per lun_index */
-       indexed_lun = (lun % 32);
-       vdev->luns[lun_index] |= (1 << indexed_lun);
-
-       if (hd->ioc->bus_type == SCSI) {
-               if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
-                       /* Treat all Processors as SAF-TE if
-                        * command line option is set */
-                       vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-                       mptscsih_writeIOCPage4(hd, target_id, bus_id);
-               }else if ((data[0] == TYPE_PROCESSOR) &&
-                       !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
-                       if ( dlen > 49 ) {
-                               vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-                               if ( data[44] == 'S' &&
-                                    data[45] == 'A' &&
-                                    data[46] == 'F' &&
-                                    data[47] == '-' &&
-                                    data[48] == 'T' &&
-                                    data[49] == 'E' ) {
-                                       vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-                                       mptscsih_writeIOCPage4(hd, target_id, bus_id);
-                               }
+       if (data)
+               vtarget->type = data[0];
+
+       if (hd->ioc->bus_type != SPI)
+               return;
+
+       if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+               /* Treat all Processors as SAF-TE if
+                * command line option is set */
+               vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+               mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
+       }else if ((data[0] == TYPE_PROCESSOR) &&
+               !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+               if ( dlen > 49 ) {
+                       vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+                       if ( data[44] == 'S' &&
+                            data[45] == 'A' &&
+                            data[46] == 'F' &&
+                            data[47] == '-' &&
+                            data[48] == 'T' &&
+                            data[49] == 'E' ) {
+                               vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+                               mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
                        }
                }
-               if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-                       if ( dlen > 8 ) {
-                               memcpy (vdev->inq_data, data, 8);
-                       } else {
-                               memcpy (vdev->inq_data, data, dlen);
-                       }
+       }
+       if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+               inq_len = dlen < 8 ? dlen : 8;
+               memcpy (vtarget->inq_data, data, inq_len);
+               /* If have not done DV, set the DV flag.
+                */
+               pSpi = &hd->ioc->spi_data;
+               if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
+                       if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE)
+                               pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV;
+               }
+               vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
 
-                       /* If have not done DV, set the DV flag.
+               data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
+               if (dlen > 56) {
+                       if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+                       /* Update the target capabilities
                         */
-                       pSpi = &hd->ioc->spi_data;
-                       if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
-                               if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
-                                       pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
-                       }
-
-                       vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-
-                       data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
-                       if (dlen > 56) {
-                               if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-                               /* Update the target capabilities
-                                */
-                                       data_56 = data[56];
-                                       vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
-                               }
+                               data_56 = data[56];
+                               vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
                        }
-                       mptscsih_setTargetNegoParms(hd, vdev, data_56);
-               } else {
-                       /* Initial Inquiry may not request enough data bytes to
-                        * obtain byte 57.  DV will; if target doesn't return
-                        * at least 57 bytes, data[56] will be zero. */
-                       if (dlen > 56) {
-                               if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-                               /* Update the target capabilities
-                                */
-                                       data_56 = data[56];
-                                       vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
-                                       mptscsih_setTargetNegoParms(hd, vdev, data_56);
-                               }
+               }
+               mptscsih_setTargetNegoParms(hd, vtarget, data_56);
+       } else {
+               /* Initial Inquiry may not request enough data bytes to
+                * obtain byte 57.  DV will; if target doesn't return
+                * at least 57 bytes, data[56] will be zero. */
+               if (dlen > 56) {
+                       if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+                       /* Update the target capabilities
+                        */
+                               data_56 = data[56];
+                               vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
+                               mptscsih_setTargetNegoParms(hd, vtarget, data_56);
                        }
                }
        }
@@ -2755,12 +2774,12 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
  *
  */
 static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
 {
        SpiCfgData *pspi_data = &hd->ioc->spi_data;
        int  id = (int) target->target_id;
        int  nvram;
-       VirtDevice      *vdev;
+       VirtTarget      *vtarget;
        int ii;
        u8 width = MPT_NARROW;
        u8 factor = MPT_ASYNC;
@@ -2905,9 +2924,9 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 
                        ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
                        for (ii = 0; ii < id; ii++) {
-                               if ( (vdev = hd->Targets[ii]) ) {
-                                       vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-                                       mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
+                               if ( (vtarget = hd->Targets[ii]) ) {
+                                       vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+                                       mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
                                }
                        }
                }
@@ -2925,106 +2944,18 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
        }
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
- * Else set the NEED_DV flag after Read Capacity Issued (disks)
- * or Mode Sense (cdroms).
- *
- * Tapes, initTarget will set this flag on completion of Inquiry command.
- * Called only if DV_NOT_DONE flag is set
- */
-static void
-mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
-{
-       MPT_ADAPTER     *ioc = hd->ioc;
-       u8 cmd;
-       SpiCfgData      *pSpi;
-
-       ddvtprintk((MYIOC_s_NOTE_FMT
-               " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
-               hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
-
-       if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
-               return;
-
-       cmd = pReq->CDB[0];
-
-       if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
-               pSpi = &ioc->spi_data;
-               if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
-                       /* Set NEED_DV for all hidden disks
-                        */
-                       Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
-                       int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
-                       while (numPDisk) {
-                               pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
-                               ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
-                               pPDisk++;
-                               numPDisk--;
-                       }
-               }
-               pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
-               ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
-       }
-}
-
-/* mptscsih_raid_set_dv_flags()
- *
- * New or replaced disk. Set DV flag and schedule DV.
- */
-static void
-mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
-{
-       MPT_ADAPTER     *ioc = hd->ioc;
-       SpiCfgData      *pSpi = &ioc->spi_data;
-       Ioc3PhysDisk_t  *pPDisk;
-       int              numPDisk;
-
-       if (hd->negoNvram != 0)
-               return;
-
-       ddvtprintk(("DV requested for phys disk id %d\n", id));
-       if (ioc->raid_data.pIocPg3) {
-               pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
-               numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-               while (numPDisk) {
-                       if (id == pPDisk->PhysDiskNum) {
-                               pSpi->dvStatus[pPDisk->PhysDiskID] =
-                                   (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
-                               pSpi->forceDv = MPT_SCSICFG_NEED_DV;
-                               ddvtprintk(("NEED_DV set for phys disk id %d\n",
-                                   pPDisk->PhysDiskID));
-                               break;
-                       }
-                       pPDisk++;
-                       numPDisk--;
-               }
-
-               if (numPDisk == 0) {
-                       /* The physical disk that needs DV was not found
-                        * in the stored IOC Page 3. The driver must reload
-                        * this page. DV routine will set the NEED_DV flag for
-                        * all phys disks that have DV_NOT_DONE set.
-                        */
-                       pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
-                       ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
-               }
-       }
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  * If no Target, bus reset on 1st I/O. Set the flag to
  * prevent any future negotiations to this device.
  */
 static void
-mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
 {
+       VirtDevice      *vdev;
 
-       if ((hd->Targets) && (hd->Targets[target_id] == NULL))
-               hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
-
+       if ((vdev = sc->device->hostdata) != NULL)
+               hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
        return;
 }
 
@@ -3100,7 +3031,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
        MPT_ADAPTER             *ioc = hd->ioc;
        Config_t                *pReq;
        SCSIDevicePage1_t       *pData;
-       VirtDevice              *pTarget=NULL;
+       VirtTarget              *vtarget=NULL;
        MPT_FRAME_HDR           *mf;
        dma_addr_t               dataDma;
        u16                      req_idx;
@@ -3180,11 +3111,11 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
                /* If id is not a raid volume, get the updated
                 * transmission settings from the target structure.
                 */
-               if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-                       width = pTarget->maxWidth;
-                       factor = pTarget->minSyncFactor;
-                       offset = pTarget->maxOffset;
-                       negoFlags = pTarget->negoFlags;
+               if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) {
+                       width = vtarget->maxWidth;
+                       factor = vtarget->minSyncFactor;
+                       offset = vtarget->maxOffset;
+                       negoFlags = vtarget->negoFlags;
                }
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
@@ -3904,149 +3835,137 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
- *     @hd: Pointer to MPT_SCSI_HOST structure
- *     @portnum: IOC port number
+ *     mptscsih_negotiate_to_asyn_narrow - Restore devices to default state
+ *     @hd: Pointer to a SCSI HOST structure
+ *     @vtarget: per device private data
  *
  *     Uses the ISR, but with special processing.
  *     MUST be single-threaded.
  *
- *     Return: 0 on completion
  */
-static int
-mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
+static void
+mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
 {
        MPT_ADAPTER             *ioc= hd->ioc;
-       VirtDevice              *pTarget;
-       SCSIDevicePage1_t       *pcfg1Data = NULL;
-       INTERNAL_CMD             iocmd;
+       SCSIDevicePage1_t       *pcfg1Data;
        CONFIGPARMS              cfg;
-       dma_addr_t               cfg1_dma_addr = -1;
-       ConfigPageHeader_t       header1;
-       int                      bus = 0;
-       int                      id = 0;
-       int                      lun;
-       int                      indexed_lun, lun_index;
-       int                      hostId = ioc->pfacts[portnum].PortSCSIID;
-       int                      max_id;
-       int                      requested, configuration, data;
-       int                      doConfig = 0;
+       dma_addr_t               cfg1_dma_addr;
+       ConfigPageHeader_t       header;
+       int                      id;
+       int                      requested, configuration, data,i;
        u8                       flags, factor;
 
-       max_id = ioc->sh->max_id - 1;
-
-       /* Following parameters will not change
-        * in this routine.
-        */
-       iocmd.cmd = SYNCHRONIZE_CACHE;
-       iocmd.flags = 0;
-       iocmd.physDiskNum = -1;
-       iocmd.data = NULL;
-       iocmd.data_dma = -1;
-       iocmd.size = 0;
-       iocmd.rsvd = iocmd.rsvd2 = 0;
-
-       /* No SCSI hosts
-        */
-       if (hd->Targets == NULL)
-               return 0;
-
-       /* Skip the host
-        */
-       if (id == hostId)
-               id++;
-
-       /* Write SDP1 for all SCSI devices
-        * Alloc memory and set up config buffer
-        */
-       if (ioc->bus_type == SCSI) {
-               if (ioc->spi_data.sdp1length > 0) {
-                       pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
-                                        ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
-
-                       if (pcfg1Data != NULL) {
-                               doConfig = 1;
-                               header1.PageVersion = ioc->spi_data.sdp1version;
-                               header1.PageLength = ioc->spi_data.sdp1length;
-                               header1.PageNumber = 1;
-                               header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-                               cfg.cfghdr.hdr = &header1;
-                               cfg.physAddr = cfg1_dma_addr;
-                               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-                               cfg.dir = 1;
-                               cfg.timeout = 0;
-                       }
-               }
-       }
+       if (ioc->bus_type != SPI)
+               return;
 
-       /* loop through all devices on this port
-        */
-       while (bus < MPT_MAX_BUS) {
-               iocmd.bus = bus;
-               iocmd.id = id;
-               pTarget = hd->Targets[(int)id];
+       if (!ioc->spi_data.sdp1length)
+               return;
 
-               if (doConfig) {
+       pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
+                ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
 
-                       /* Set the negotiation flags */
-                       if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-                               flags = pTarget->negoFlags;
-                       } else {
-                               flags = hd->ioc->spi_data.noQas;
-                               if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                                       data = hd->ioc->spi_data.nvram[id];
+       if (pcfg1Data == NULL)
+               return;
 
-                                       if (data & MPT_NVRAM_WIDE_DISABLE)
-                                               flags |= MPT_TARGET_NO_NEGO_WIDE;
+       header.PageVersion = ioc->spi_data.sdp1version;
+       header.PageLength = ioc->spi_data.sdp1length;
+       header.PageNumber = 1;
+       header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+       cfg.cfghdr.hdr = &header;
+       cfg.physAddr = cfg1_dma_addr;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+       cfg.dir = 1;
+       cfg.timeout = 0;
 
-                                       factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
-                                       if ((factor == 0) || (factor == MPT_ASYNC))
-                                               flags |= MPT_TARGET_NO_NEGO_SYNC;
-                               }
+       if (vtarget->raidVolume && ioc->raid_data.pIocPg3) {
+               for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+                       id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID;
+                       flags = hd->ioc->spi_data.noQas;
+                       if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+                               data = hd->ioc->spi_data.nvram[id];
+                               if (data & MPT_NVRAM_WIDE_DISABLE)
+                                       flags |= MPT_TARGET_NO_NEGO_WIDE;
+                               factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+                               if ((factor == 0) || (factor == MPT_ASYNC))
+                                       flags |= MPT_TARGET_NO_NEGO_SYNC;
                        }
-
-                       /* Force to async, narrow */
                        mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
-                                       &configuration, flags);
+                               &configuration, flags);
                        dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
                                "offset=0 negoFlags=%x request=%x config=%x\n",
                                id, flags, requested, configuration));
                        pcfg1Data->RequestedParameters = cpu_to_le32(requested);
                        pcfg1Data->Reserved = 0;
                        pcfg1Data->Configuration = cpu_to_le32(configuration);
-                       cfg.pageAddr = (bus<<8) | id;
+                       cfg.pageAddr = (vtarget->bus_id<<8) | id;
                        mpt_config(hd->ioc, &cfg);
                }
+       } else {
+               flags = vtarget->negoFlags;
+               mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
+                               &configuration, flags);
+               dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+                       "offset=0 negoFlags=%x request=%x config=%x\n",
+                       vtarget->target_id, flags, requested, configuration));
+               pcfg1Data->RequestedParameters = cpu_to_le32(requested);
+               pcfg1Data->Reserved = 0;
+               pcfg1Data->Configuration = cpu_to_le32(configuration);
+               cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id;
+               mpt_config(hd->ioc, &cfg);
+       }
 
-               /* If target Ptr NULL or if this target is NOT a disk, skip.
-                */
-               if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){
-                       for (lun=0; lun <= MPT_LAST_LUN; lun++) {
-                               /* If LUN present, issue the command
-                                */
-                               lun_index = (lun >> 5);  /* 32 luns per lun_index */
-                               indexed_lun = (lun % 32);
-                               if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
-                                       iocmd.lun = lun;
-                                       (void) mptscsih_do_cmd(hd, &iocmd);
-                               }
-                       }
-               }
+       if (pcfg1Data)
+               pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+}
 
-               /* get next relevant device */
-               id++;
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
+ *     @hd: Pointer to a SCSI HOST structure
+ *     @vtarget: per device private data
+ *     @lun: lun
+ *
+ *     Uses the ISR, but with special processing.
+ *     MUST be single-threaded.
+ *
+ */
+static void
+mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
+{
+       INTERNAL_CMD             iocmd;
 
-               if (id == hostId)
-                       id++;
+       /* Following parameters will not change
+        * in this routine.
+        */
+       iocmd.cmd = SYNCHRONIZE_CACHE;
+       iocmd.flags = 0;
+       iocmd.physDiskNum = -1;
+       iocmd.data = NULL;
+       iocmd.data_dma = -1;
+       iocmd.size = 0;
+       iocmd.rsvd = iocmd.rsvd2 = 0;
+       iocmd.bus = vdevice->bus_id;
+       iocmd.id = vdevice->target_id;
+       iocmd.lun = (u8)vdevice->lun;
 
-               if (id > max_id) {
-                       id = 0;
-                       bus++;
-               }
-       }
+       if ((vdevice->vtarget->type & TYPE_DISK) &&
+           (vdevice->configured_lun))
+               mptscsih_do_cmd(hd, &iocmd);
+}
+
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+static int
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+{
+       int i;
+
+       if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+               return 0;
 
-       if (pcfg1Data) {
-               pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+               if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+                       return 1;
        }
 
        return 0;
@@ -4101,8 +4020,8 @@ mptscsih_domainValidation(void *arg)
 
                        msleep(250);
 
-                       /* DV only to SCSI adapters */
-                       if (ioc->bus_type != SCSI)
+                       /* DV only to SPI adapters */
+                       if (ioc->bus_type != SPI)
                                continue;
 
                        /* Make sure everything looks ok */
@@ -4162,6 +4081,12 @@ mptscsih_domainValidation(void *arg)
                                                }
                                        }
 
+                                       if(mpt_alt_ioc_wait(hd->ioc)!=0) {
+                                               ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
+                                                   hd->ioc->name));
+                                               continue;
+                                       }
+
                                        if (mptscsih_doDv(hd, 0, id) == 1) {
                                                /* Untagged device was busy, try again
                                                 */
@@ -4173,6 +4098,10 @@ mptscsih_domainValidation(void *arg)
                                                hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
                                        }
 
+                                       spin_lock(&hd->ioc->initializing_hba_lock);
+                                       hd->ioc->initializing_hba_lock_flag=0;
+                                       spin_unlock(&hd->ioc->initializing_hba_lock);
+
                                        if (isPhysDisk) {
                                                for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
                                                        if (hd->ioc->raid_data.isRaid & (1 << ii)) {
@@ -4195,32 +4124,12 @@ mptscsih_domainValidation(void *arg)
        return;
 }
 
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-static int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
-{
-       int i;
-
-       if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
-               return 0;
-
-       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-               if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-                       return 1;
-       }
-
-       return 0;
-}
-
 /* Write SDP1 if no QAS has been enabled
  */
 static void
 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 {
-       VirtDevice *pTarget;
+       VirtTarget *vtarget;
        int ii;
 
        if (hd->Targets == NULL)
@@ -4233,11 +4142,11 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
                if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
                        continue;
 
-               pTarget = hd->Targets[ii];
+               vtarget = hd->Targets[ii];
 
-               if ((pTarget != NULL) && (!pTarget->raidVolume)) {
-                       if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
-                               pTarget->negoFlags |= hd->ioc->spi_data.noQas;
+               if ((vtarget != NULL) && (!vtarget->raidVolume)) {
+                       if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
+                               vtarget->negoFlags |= hd->ioc->spi_data.noQas;
                                dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
                                mptscsih_writeSDP1(hd, 0, ii, 0);
                        }
@@ -4277,7 +4186,7 @@ static int
 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 {
        MPT_ADAPTER             *ioc = hd->ioc;
-       VirtDevice              *pTarget;
+       VirtTarget              *vtarget;
        SCSIDevicePage1_t       *pcfg1Data;
        SCSIDevicePage0_t       *pcfg0Data;
        u8                      *pbuf1;
@@ -4348,12 +4257,12 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
        iocmd.physDiskNum = -1;
        iocmd.rsvd = iocmd.rsvd2 = 0;
 
-       pTarget = hd->Targets[id];
+       vtarget = hd->Targets[id];
 
        /* Use tagged commands if possible.
         */
-       if (pTarget) {
-               if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+       if (vtarget) {
+               if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
                        iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
                else {
                        if (hd->ioc->facts.FWVersion.Word < 0x01000600)
@@ -4569,7 +4478,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                /* Reset the size for disks
                 */
                inq0 = (*pbuf1) & 0x1F;
-               if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
+               if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
                        sz = 0x40;
                        iocmd.size = sz;
                }
@@ -4579,8 +4488,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                 */
                if (inq0 == TYPE_PROCESSOR) {
                        mptscsih_initTarget(hd,
-                               bus,
-                               id,
+                               vtarget,
                                lun,
                                pbuf1,
                                sz);
@@ -4594,22 +4502,22 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                        goto target_done;
 
                if (sz == 0x40) {
-                       if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
-                               && (pTarget->minSyncFactor > 0x09)) {
+                       if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
+                               && (vtarget->minSyncFactor > 0x09)) {
                                if ((pbuf1[56] & 0x04) == 0)
                                        ;
                                else if ((pbuf1[56] & 0x01) == 1) {
-                                       pTarget->minSyncFactor =
+                                       vtarget->minSyncFactor =
                                            nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
                                } else {
-                                       pTarget->minSyncFactor =
+                                       vtarget->minSyncFactor =
                                            nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
                                }
 
-                               dv.max.factor = pTarget->minSyncFactor;
+                               dv.max.factor = vtarget->minSyncFactor;
 
                                if ((pbuf1[56] & 0x02) == 0) {
-                                       pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+                                       vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
                                        hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
                                        ddvprintk((MYIOC_s_NOTE_FMT
                                            "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
@@ -4692,8 +4600,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
                                                    "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
                                                hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
                                                mptscsih_initTarget(hd,
-                                                       bus,
-                                                       id,
+                                                       vtarget,
                                                        lun,
                                                        pbuf1,
                                                        sz);
@@ -5194,7 +5101,7 @@ target_done:
 static void
 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 {
-       VirtDevice              *pTarget;
+       VirtTarget              *vtarget;
        SCSIDevicePage0_t       *pPage0;
        SCSIDevicePage1_t       *pPage1;
        int                     val = 0, data, configuration;
@@ -5214,11 +5121,11 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
                 * already throttled back.
                 */
                negoFlags = hd->ioc->spi_data.noQas;
-               if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
-                       width = pTarget->maxWidth;
-                       offset = pTarget->maxOffset;
-                       factor = pTarget->minSyncFactor;
-                       negoFlags |= pTarget->negoFlags;
+               if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
+                       width = vtarget->maxWidth;
+                       offset = vtarget->maxOffset;
+                       factor = vtarget->minSyncFactor;
+                       negoFlags |= vtarget->negoFlags;
                } else {
                        if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
                                data = hd->ioc->spi_data.nvram[id];
@@ -5420,11 +5327,11 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
                 * or overwrite nvram (phys disks only).
                 */
 
-               if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
-                       pTarget->maxWidth = dv->now.width;
-                       pTarget->maxOffset = dv->now.offset;
-                       pTarget->minSyncFactor = dv->now.factor;
-                       pTarget->negoFlags = dv->now.flags;
+               if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
+                       vtarget->maxWidth = dv->now.width;
+                       vtarget->maxOffset = dv->now.offset;
+                       vtarget->minSyncFactor = dv->now.factor;
+                       vtarget->negoFlags = dv->now.flags;
                } else {
                        /* Preserv all flags, use
                         * read-modify-write algorithm
@@ -5578,6 +5485,94 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width)
                break;
        }
 }
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
+ * Else set the NEED_DV flag after Read Capacity Issued (disks)
+ * or Mode Sense (cdroms).
+ *
+ * Tapes, initTarget will set this flag on completion of Inquiry command.
+ * Called only if DV_NOT_DONE flag is set
+ */
+static void
+mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
+{
+       MPT_ADAPTER     *ioc = hd->ioc;
+       u8 cmd;
+       SpiCfgData      *pSpi;
+
+       ddvtprintk((MYIOC_s_NOTE_FMT
+               " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
+               hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
+
+       if ((sc->device->lun != 0) || (hd->negoNvram != 0))
+               return;
+
+       cmd = sc->cmnd[0];
+
+       if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
+               pSpi = &ioc->spi_data;
+               if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
+                       /* Set NEED_DV for all hidden disks
+                        */
+                       Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+                       int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+
+                       while (numPDisk) {
+                               pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
+                               ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
+                               pPDisk++;
+                               numPDisk--;
+                       }
+               }
+               pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
+               ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
+       }
+}
+
+/* mptscsih_raid_set_dv_flags()
+ *
+ * New or replaced disk. Set DV flag and schedule DV.
+ */
+static void
+mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
+{
+       MPT_ADAPTER     *ioc = hd->ioc;
+       SpiCfgData      *pSpi = &ioc->spi_data;
+       Ioc3PhysDisk_t  *pPDisk;
+       int              numPDisk;
+
+       if (hd->negoNvram != 0)
+               return;
+
+       ddvtprintk(("DV requested for phys disk id %d\n", id));
+       if (ioc->raid_data.pIocPg3) {
+               pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+               numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+               while (numPDisk) {
+                       if (id == pPDisk->PhysDiskNum) {
+                               pSpi->dvStatus[pPDisk->PhysDiskID] =
+                                   (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
+                               pSpi->forceDv = MPT_SCSICFG_NEED_DV;
+                               ddvtprintk(("NEED_DV set for phys disk id %d\n",
+                                   pPDisk->PhysDiskID));
+                               break;
+                       }
+                       pPDisk++;
+                       numPDisk--;
+               }
+
+               if (numPDisk == 0) {
+                       /* The physical disk that needs DV was not found
+                        * in the stored IOC Page 3. The driver must reload
+                        * this page. DV routine will set the NEED_DV flag for
+                        * all phys disks that have DV_NOT_DONE set.
+                        */
+                       pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
+                       ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
+               }
+       }
+}
 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
 
 EXPORT_SYMBOL(mptscsih_remove);
@@ -5589,7 +5584,9 @@ EXPORT_SYMBOL(mptscsih_resume);
 EXPORT_SYMBOL(mptscsih_proc_info);
 EXPORT_SYMBOL(mptscsih_info);
 EXPORT_SYMBOL(mptscsih_qcmd);
+EXPORT_SYMBOL(mptscsih_target_alloc);
 EXPORT_SYMBOL(mptscsih_slave_alloc);
+EXPORT_SYMBOL(mptscsih_target_destroy);
 EXPORT_SYMBOL(mptscsih_slave_destroy);
 EXPORT_SYMBOL(mptscsih_slave_configure);
 EXPORT_SYMBOL(mptscsih_abort);