Merge ../linux-2.6
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>
Tue, 21 Mar 2006 19:05:45 +0000 (13:05 -0600)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Tue, 21 Mar 2006 19:05:45 +0000 (13:05 -0600)
113 files changed:
MAINTAINERS
drivers/base/bus.c
drivers/block/cciss.c
drivers/message/fusion/Kconfig
drivers/message/fusion/Makefile
drivers/message/fusion/lsi/mpi_log_sas.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/message/i2o/exec-osm.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/53c700.c
drivers/scsi/FlashPoint.c
drivers/scsi/NCR_D700.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aha152x.c
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic7xxx_core.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/ch.c
drivers/scsi/dmx3191d.c
drivers/scsi/hosts.c
drivers/scsi/ibmmca.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/jazz_esp.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_disc.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_scsi.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/ncr53c8xx.c
drivers/scsi/ncr53c8xx.h
drivers/scsi/osst.c
drivers/scsi/osst.h
drivers/scsi/qla2xxx/Kconfig
drivers/scsi/qla2xxx/Makefile
drivers/scsi/qla2xxx/ql2300.c
drivers/scsi/qla2xxx/ql2300_fw.c
drivers/scsi/qla2xxx/ql2322.c
drivers/scsi/qla2xxx/ql2322_fw.c
drivers/scsi/qla2xxx/ql2400.c
drivers/scsi/qla2xxx/ql2400_fw.c
drivers/scsi/qla2xxx/ql6312.c [deleted file]
drivers/scsi/qla2xxx/ql6312_fw.c [deleted file]
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_devtbl.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sgiwd93.c
drivers/scsi/sim710.c
drivers/scsi/sr.c
drivers/scsi/st.c
drivers/scsi/sym53c8xx_2/sym_hipd.c
drivers/scsi/wd33c93.c
include/linux/device.h
include/linux/pci_ids.h
include/linux/workqueue.h
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_device.h
include/scsi/scsi_host.h
include/scsi/scsi_transport.h
include/scsi/scsi_transport_sas.h
include/scsi/scsi_transport_spi.h
kernel/workqueue.c

index 7a1cbda8a2fe1f41e8affe1e88f4c138069ab6f3..b0dc75a5e74e2c6749fce0f5418fc69eb261a3f7 100644 (file)
@@ -2141,7 +2141,7 @@ S:        Maintained
 
 QLOGIC QLA2XXX FC-SCSI DRIVER
 P:     Andrew Vasquez
-M:     andrew.vasquez@qlogic.com
+M:     linux-driver@qlogic.com
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 
index c3141565d59d503250fce52deddbd4df74ffe9ac..48718b7f4fa01737326174f42a775cdabbcc81a8 100644 (file)
@@ -536,6 +536,28 @@ void bus_rescan_devices(struct bus_type * bus)
        bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
 }
 
+/**
+ * device_reprobe - remove driver for a device and probe for a new driver
+ * @dev: the device to reprobe
+ *
+ * This function detaches the attached driver (if any) for the given
+ * device and restarts the driver probing process.  It is intended
+ * to use if probing criteria changed during a devices lifetime and
+ * driver attachment should change accordingly.
+ */
+void device_reprobe(struct device *dev)
+{
+       if (dev->driver) {
+               if (dev->parent)        /* Needed for USB */
+                       down(&dev->parent->sem);
+               device_release_driver(dev);
+               if (dev->parent)
+                       up(&dev->parent->sem);
+       }
+
+       bus_rescan_devices_helper(dev, NULL);
+}
+EXPORT_SYMBOL_GPL(device_reprobe);
 
 struct bus_type * get_bus(struct bus_type * bus)
 {
index 0d65394707dbd5653057cfe1dbca6c94fdd98c47..b9c786ee6fad21fee1aa32db38369cfc37bd2266 100644 (file)
@@ -3251,8 +3251,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 
 clean4:
 #ifdef CONFIG_CISS_SCSI_TAPE
-       if(hba[i]->scsi_rejects.complete)
-               kfree(hba[i]->scsi_rejects.complete);
+       kfree(hba[i]->scsi_rejects.complete);
 #endif
        kfree(hba[i]->cmd_pool_bits);
        if(hba[i]->cmd_pool)
index e67cf15e9c3961af697067c4007e78ffd359da4b..bbc229852881e133affea9a4984a6ce806f1f622 100644 (file)
@@ -9,6 +9,7 @@ config FUSION_SPI
        tristate "Fusion MPT ScsiHost drivers for SPI"
        depends on PCI && SCSI
        select FUSION
+       select SCSI_SPI_ATTRS
        ---help---
          SCSI HOST support for a parallel SCSI host adapters.
 
index 33ace373241cb4b80997b60bb52b29dc46c87f8b..51740b346224b35fd80d79ad7e56882647d4a18b 100644 (file)
@@ -4,6 +4,7 @@
 #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
 #EXTRA_CFLAGS += -DMPT_DEBUG_SG
 #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS
+#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS
 #EXTRA_CFLAGS += -DMPT_DEBUG_INIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
index 9259d1ad6e6e579b47ac61908abfd99c8caa6c09..a9c14ad132ce1a2dda6b965acf20211c2a0b6e9c 100644 (file)
@@ -3,38 +3,11 @@
  *                                                                         *
  *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
  *                                                                         *
- *  This file is confidential and a trade secret of LSI Logic.  The        *
- *  receipt of or possession of this file does not convey any rights to    *
- *  reproduce or disclose its contents or to manufacture, use, or sell     *
- *  anything it may describe, in whole, or in part, without the specific   *
- *  written consent of LSI Logic Corporation.                              *
+ * Description                                                             *
+ * ------------                                                            *
+ * This include file contains SAS firmware interface IOC Log Info codes    *
  *                                                                         *
- ***************************************************************************
- *
- *           Name:  iopiIocLogInfo.h
- *          Title:  SAS Firmware IOP Interface IOC Log Info Definitions
- *     Programmer:  Guy Kendall
- *  Creation Date:  September 24, 2003
- *
- *  Version History
- *  ---------------
- *
- *  Last Updated
- *  -------------
- *  Version         %version: 22 %
- *  Date Updated    %date_modified: %
- *  Programmer      %created_by: nperucca %
- *
- *  Date      Who   Description
- *  --------  ---   -------------------------------------------------------
- *  09/24/03  GWK   Initial version
- *
- *
- * Description
- * ------------
- * This include file contains SAS firmware interface IOC Log Info codes
- *
- *-------------------------------------------------------------------------
+ *-------------------------------------------------------------------------*
  */
 
 #ifndef IOPI_IOCLOGINFO_H_INCLUDED
@@ -57,6 +30,8 @@
 #define IOC_LOGINFO_ORIGINATOR_PL                       (0x01000000)
 #define IOC_LOGINFO_ORIGINATOR_IR                       (0x02000000)
 
+#define IOC_LOGINFO_ORIGINATOR_MASK                     (0x0F000000)
+
 /****************************************************************************/
 /* LOGINFO_CODE defines                                                     */
 /****************************************************************************/
 #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT    (0x00030700) /* Default Page not found */
 #define IOP_LOGINFO_CODE_TASK_TERMINATED                (0x00050000)
 
+#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R    (0x00060001) /* Read Action not supported for SEP msg */
+#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */
+
+#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED       (0x00070001)
+#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED  (0x00070002)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO       (0x00070003)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO     (0x00070004)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
 
 /****************************************************************************/
 /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL            */
 /****************************************************************************/
 #define PL_LOGINFO_CODE_OPEN_FAILURE                        (0x00010000)
+#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT      (0x00010001)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION        (0x00010011)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY      (0x00010018)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION      (0x00010019)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT            (0X0001001A)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED        (0x0001001B)
+#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED              (0x0001001C)
 #define PL_LOGINFO_CODE_INVALID_SGL                         (0x00020000)
 #define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH       (0x00030000)
 #define PL_LOGINFO_CODE_FRAME_XFER_ERROR                    (0x00040000)
@@ -97,6 +88,7 @@
 #define PL_LOGINFO_CODE_SATA_LINK_DOWN                      (0x000D0000)
 #define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS           (0x000E0000)
 #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED           (0x000F0001) /* PL not yet initialized, can't do config page req. */
 #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x000F0100) /* Invalid Page Type */
 #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS        (0x000F0200) /* Invalid Number of Phys */
 #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP         (0x000F0300) /* Case Not Handled */
 #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY             (0x000F0600) /* Invalid Phy */
 #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER        (0x000F0700) /* No Owner Found */
 #define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT            (0x00100000)
-#define PL_LOGINFO_CODE_RESET                               (0x00110000)
-#define PL_LOGINFO_CODE_ABORT                               (0x00120000)
+#define PL_LOGINFO_CODE_RESET                               (0x00110000) /* See Sub-Codes below */
+#define PL_LOGINFO_CODE_ABORT                               (0x00120000) /* See Sub-Codes below */
 #define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                 (0x00130000)
 #define PL_LOGINFO_CODE_IO_EXECUTED                         (0x00140000)
+#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER       (0x00150000)
+#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT                    (0x00160000)
 #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                    (0x00000100)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT    (0x00000101)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT        (0x0000011A) /* Open Reject (Retry) Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED    (0x0000011B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED          (0x0000011C) /* Arbitration Wait Timer Maxed */
+
+#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET                (0x00000120)
+#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER                 (0x00000130)  /* Leave lower nibble (1-f) reserved. */
+#define PL_LOGINFO_SUB_CODE_PORT_LAYER                      (0x00000140)  /* Leave lower nibble (1-f) reserved. */
+
+
 #define PL_LOGINFO_SUB_CODE_INVALID_SGL                     (0x00000200)
 #define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH   (0x00000300)
 #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                (0x00000400)
 #define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR       (0x00000C00)
 #define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                  (0x00000D00)
 #define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS       (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET      (0x00000E01)
+#define PL_LOGINFO_SUB_CODE_SECOND_OPEN                     (0x00000F00)
 #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT        (0x00001000)
 
 
 #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE         (0x00200000) /* Can't get SMP Frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR            (0x00200001) /* Error occured on SMP Read */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR           (0x00200002) /* Error occured on SMP Write */
-#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL     (0x00200004) /* Encl Mgmt services not available for this WWID */
-#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED   (0x00200005) /* Address Mode not suppored */
-#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM              (0x00200006) /* Invalid Slot Number in SEP Msg */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT         (0x00200007) /* SGPIO not present/enabled */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR            (0x00200010) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR           (0x00200020) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL     (0x00200040) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED   (0x00200050) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM              (0x00200060) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT         (0x00200070) /* SGPIO not present/enabled */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED       (0x00200080) /* GPIO not configured */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR          (0x00200090) /* GPIO can't allocate a frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR    (0x002000A0) /* GPIO failed config page request */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR     (0x002000B0) /* Can't get frame for SES command */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR              (0x002000C0) /* I/O execution error */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED     (0x002000D0) /* SEP I/O retries exhausted */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR     (0x002000E0) /* Can't get frame for SMP command */
 
 #define PL_LOGINFO_DA_SEP_NOT_PRESENT                       (0x00200100) /* SEP not present when msg received */
 #define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR               (0x00200101) /* Can only accept 1 msg at a time */
 #define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE          (0x00200102) /* ISTWI interrupt recvd. while IDLE */
 #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE          (0x00200103) /* SEP NACK'd, it is busy */
-#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM             (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1         (0x00200105) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2         (0x00200106) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP           (0x00200107) /* SEP returned bad chksum after STOP */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA   (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
+#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK               (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM             (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                      (0x00200106) /* SEP stopped while transfering data */
+#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                (0x00200107) /* SEP stopped while transfering sense data */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1         (0x00200108) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2         (0x00200109) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP           (0x0020010A) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA   (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND               (0x0020010C) /* SEP doesn't support CDB opcode */
 
 
 /****************************************************************************/
index 642a61b6d0a4ebd3a89732c002a071dc633156ce..266414ca2814e935b1d589f4c68aa7eed49c028e 100644 (file)
@@ -180,6 +180,7 @@ static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 static void    mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void    mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void    mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static int     mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 
 /* module entry point */
 static int  __init    fusion_init  (void);
@@ -428,7 +429,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
                if (results != evHandlers) {
                        /* CHECKME! Any special handling needed here? */
-                       devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
+                       devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
                                        ioc->name, evHandlers, results));
                }
 
@@ -438,10 +439,10 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                 */
                if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
                        freereq = 0;
-                       devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+                       devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
                                ioc->name, pEvReply));
                } else {
-                       devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+                       devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
                                ioc->name, pEvReply));
                }
 
@@ -1120,65 +1121,6 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
        return -1;
 }
 
-int
-mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
-{
-       int loop_count = 30 * 4;  /* Wait 30 seconds */
-       int status = -1; /* -1 means failed to get board READY */
-
-       do {
-               spin_lock(&ioc->initializing_hba_lock);
-               if (ioc->initializing_hba_lock_flag == 0) {
-                       ioc->initializing_hba_lock_flag=1;
-                       spin_unlock(&ioc->initializing_hba_lock);
-                       status = 0;
-                       break;
-               }
-               spin_unlock(&ioc->initializing_hba_lock);
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(HZ/4);
-       } while (--loop_count);
-
-       return status;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
- *     @ioc: Pointer to MPT adapter structure
- *     @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
- *
- *     This routine performs all the steps necessary to bring the IOC
- *     to a OPERATIONAL state.
- *
- *      Special Note: This function was added with spin lock's so as to allow
- *      the dv(domain validation) work thread to succeed on the other channel
- *      that maybe occuring at the same time when this function is called.
- *      Without this lock, the dv would fail when message frames were
- *      requested during hba bringup on the alternate ioc.
- */
-static int
-mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
-{
-       int r;
-
-       if(ioc->alt_ioc) {
-               if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
-                       return r;
-       }
-
-       r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
-           CAN_SLEEP);
-
-       if(ioc->alt_ioc) {
-               spin_lock(&ioc->alt_ioc->initializing_hba_lock);
-               ioc->alt_ioc->initializing_hba_lock_flag=0;
-               spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
-       }
-
-return r;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_attach - Install a PCI intelligent MPT adapter.
@@ -1482,7 +1424,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
         */
        mpt_detect_bound_ports(ioc, pdev);
 
-       if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
+       if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
+           CAN_SLEEP)) != 0){
                printk(KERN_WARNING MYNAM
                  ": WARNING - %s did not initialize properly! (%d)\n",
                  ioc->name, r);
@@ -1629,7 +1572,6 @@ mpt_resume(struct pci_dev *pdev)
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
        u32 device_state = pdev->current_state;
        int recovery_state;
-       int ii;
 
        printk(MYIOC_s_INFO_FMT
        "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
@@ -1643,14 +1585,6 @@ mpt_resume(struct pci_dev *pdev)
        CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
        ioc->active = 1;
 
-       /* F/W not running */
-       if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
-               /* enable domain validation flags */
-               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                       ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
-               }
-       }
-
        printk(MYIOC_s_INFO_FMT
                "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
                ioc->name,
@@ -4938,7 +4872,7 @@ done_and_free:
        return rc;
 }
 
-int
+static int
 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 {
        IOCPage3_t              *pIoc3;
@@ -5146,13 +5080,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
 
        evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
        if (evnp == NULL) {
-               devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+               devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
                                ioc->name));
                return 0;
        }
        memset(evnp, 0, sizeof(*evnp));
 
-       devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
+       devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
 
        evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
        evnp->ChainOffset = 0;
@@ -5907,24 +5841,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
                break;
        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
        {
+               char buf[50];
+               u8 id = (u8)(evData0);
                u8 ReasonCode = (u8)(evData0 >> 16);
                switch (ReasonCode) {
                case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
-                       ds = "SAS Device Status Change: Added";
+                       sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
                        break;
                case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
-                       ds = "SAS Device Status Change: Deleted";
+                       sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
                        break;
                case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-                       ds = "SAS Device Status Change: SMART Data";
+                       sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
                        break;
                case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
-                       ds = "SAS Device Status Change: No Persistancy Added";
+                       sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
                        break;
                default:
-                       ds = "SAS Device Status Change: Unknown";
+                       sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
                break;
                }
+               ds = buf;
                break;
        }
        case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@@ -5940,11 +5877,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
                ds = "Persistent Table Full";
                break;
        case MPI_EVENT_SAS_PHY_LINK_STATUS:
-               ds = "SAS PHY Link Status";
+       {
+               char buf[50];
+               u8 LinkRates = (u8)(evData0 >> 8);
+               u8 PhyNumber = (u8)(evData0);
+               LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
+                       MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
+               switch (LinkRates) {
+               case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                          " Rate Unknown",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                          " Phy Disabled",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                          " Failed Speed Nego",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                          " Sata OOB Completed",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                          " Rate 1.5 Gbps",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                          " Rate 3.0 Gpbs",PhyNumber);
+                       break;
+               default:
+                       sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
+                       break;
+               }
+               ds = buf;
                break;
+       }
        case MPI_EVENT_SAS_DISCOVERY_ERROR:
                ds = "SAS Discovery Error";
                break;
+       case MPI_EVENT_IR_RESYNC_UPDATE:
+       {
+               u8 resync_complete = (u8)(evData0 >> 16);
+               char buf[40];
+               sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
+               ds = buf;
+               break;
+       }
+       case MPI_EVENT_IR2:
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
+                       ds = "IR2: LD State Changed";
+                       break;
+               case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
+                       ds = "IR2: PD State Changed";
+                       break;
+               case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
+                       ds = "IR2: Bad Block Table Full";
+                       break;
+               case MPI_EVENT_IR2_RC_PD_INSERTED:
+                       ds = "IR2: PD Inserted";
+                       break;
+               case MPI_EVENT_IR2_RC_PD_REMOVED:
+                       ds = "IR2: PD Removed";
+                       break;
+               case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
+                       ds = "IR2: Foreign CFG Detected";
+                       break;
+               case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
+                       ds = "IR2: Rebuild Medium Error";
+                       break;
+               default:
+                       ds = "IR2";
+               break;
+               }
+               break;
+       }
+       case MPI_EVENT_SAS_DISCOVERY:
+       {
+               if (evData0)
+                       ds = "SAS Discovery: Start";
+               else
+                       ds = "SAS Discovery: Stop";
+               break;
+       }
+       case MPI_EVENT_LOG_ENTRY_ADDED:
+               ds = "SAS Log Entry Added";
+               break;
 
        /*
         *  MPT base "custom" events may be added here...
@@ -5989,12 +6012,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        }
 
        EventDescriptionStr(event, evData0, evStr);
-       devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
+       devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
                        ioc->name,
-                       evStr,
-                       event));
+                       event,
+                       evStr));
 
-#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
+#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
        printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
        for (ii = 0; ii < evDataLen; ii++)
                printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
@@ -6053,7 +6076,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
         */
        for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
                if (MptEvHandlers[ii]) {
-                       devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
+                       devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
                                        ioc->name, ii));
                        r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
                        handlers++;
@@ -6065,10 +6088,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
         *  If needed, send (a single) EventAck.
         */
        if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
-               devtprintk((MYIOC_s_WARN_FMT
+               devtverboseprintk((MYIOC_s_WARN_FMT
                        "EventAck required\n",ioc->name));
                if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
-                       devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+                       devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
                                        ioc->name, ii));
                }
        }
@@ -6205,8 +6228,8 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
                "Abort",                                        /* 12h */
                "IO Not Yet Executed",                          /* 13h */
                "IO Executed",                                  /* 14h */
-               NULL,                                           /* 15h */
-               NULL,                                           /* 16h */
+               "Persistant Reservation Out Not Affiliation Owner", /* 15h */
+               "Open Transmit DMA Abort",                      /* 16h */
                NULL,                                           /* 17h */
                NULL,                                           /* 18h */
                NULL,                                           /* 19h */
@@ -6431,11 +6454,9 @@ EXPORT_SYMBOL(mpt_stm_index);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_config);
 EXPORT_SYMBOL(mpt_findImVolumes);
-EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
-EXPORT_SYMBOL(mpt_alt_ioc_wait);
 EXPORT_SYMBOL(mptbase_GetFcPortPage0);
 
 
index 723d543009530262d3f2bdbe68ea3486108856f5..be7e8501b53c1d4243691625003cd690c0b75932 100644 (file)
@@ -76,8 +76,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.03.07"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.07"
+#define MPT_LINUX_VERSION_COMMON       "3.03.08"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.08"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS
  *     VirtDevice - FC LUN device or SCSI target device
  */
 typedef struct _VirtTarget {
+       struct scsi_target      *starget;
        u8                       tflags;
        u8                       ioc_id;
        u8                       target_id;
@@ -343,14 +344,10 @@ typedef struct _VirtTarget {
        u8                       type;          /* byte 0 of Inquiry data */
        u32                      num_luns;
        u32                      luns[8];               /* Max LUNs is 256 */
-       u8                       inq_data[8];
 } VirtTarget;
 
 typedef struct _VirtDevice {
-       VirtTarget              *vtarget;
-       u8                       ioc_id;
-       u8                       bus_id;
-       u8                       target_id;
+       VirtTarget              *vtarget;
        u8                       configured_lun;
        u32                      lun;
 } VirtDevice;
@@ -364,6 +361,7 @@ typedef struct _VirtDevice {
 #define MPT_TARGET_FLAGS_Q_YES         0x08
 #define MPT_TARGET_FLAGS_VALID_56      0x10
 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
+#define MPT_TARGET_FLAGS_RAID_COMPONENT        0x40
 
 /*
  *     /proc/mpt interface
@@ -447,13 +445,6 @@ typedef struct _mpt_ioctl_events {
  *     Substructure to store SCSI specific configuration page data
  */
                                                /* dvStatus defines: */
-#define MPT_SCSICFG_NEGOTIATE          0x01    /* Negotiate on next IO */
-#define MPT_SCSICFG_NEED_DV            0x02    /* Schedule DV */
-#define MPT_SCSICFG_DV_PENDING         0x04    /* DV on this physical id pending */
-#define MPT_SCSICFG_DV_NOT_DONE                0x08    /* DV has not been performed */
-#define MPT_SCSICFG_BLK_NEGO           0x10    /* WriteSDP1 with WDTR and SDTR disabled */
-#define MPT_SCSICFG_RELOAD_IOC_PG3     0x20    /* IOC Pg 3 data is obsolete */
-                                               /* Args passed to writeSDP1: */
 #define MPT_SCSICFG_USE_NVRAM          0x01    /* WriteSDP1 using NVRAM */
 #define MPT_SCSICFG_ALL_IDS            0x02    /* WriteSDP1 to all IDS */
 /* #define MPT_SCSICFG_BLK_NEGO                0x10       WriteSDP1 with WDTR and SDTR disabled */
@@ -464,7 +455,6 @@ typedef     struct _SpiCfgData {
        IOCPage4_t      *pIocPg4;               /* SEP devices addressing */
        dma_addr_t       IocPg4_dma;            /* Phys Addr of IOCPage4 data */
        int              IocPg4Sz;              /* IOCPage4 size */
-       u8               dvStatus[MPT_MAX_SCSI_DEVICES];
        u8               minSyncFactor;         /* 0xFF if async */
        u8               maxSyncOffset;         /* 0 if async */
        u8               maxBusWidth;           /* 0 if narrow, 1 if wide */
@@ -474,13 +464,11 @@ typedef   struct _SpiCfgData {
        u8               sdp0version;           /* SDP0 version */
        u8               sdp0length;            /* SDP0 length  */
        u8               dvScheduled;           /* 1 if scheduled */
-       u8               forceDv;               /* 1 to force DV scheduling */
        u8               noQas;                 /* Disable QAS for this adapter */
        u8               Saf_Te;                /* 1 to force all Processors as
                                                 * SAF-TE if Inquiry data length
                                                 * is too short to check for SAF-TE
                                                 */
-       u8               mpt_dv;                /* command line option: enhanced=1, basic=0 */
        u8               bus_reset;             /* 1 to allow bus reset */
        u8               rsvd[1];
 }SpiCfgData;
@@ -631,6 +619,10 @@ typedef struct _MPT_ADAPTER
        struct net_device       *netdev;
        struct list_head         sas_topology;
        struct mutex             sas_topology_mutex;
+       struct mutex             sas_discovery_mutex;
+       u8                       sas_discovery_runtime;
+       u8                       sas_discovery_ignore_events;
+       int                      sas_index; /* index refrencing */
        MPT_SAS_MGMT             sas_mgmt;
        int                      num_ports;
        struct work_struct       mptscsih_persistTask;
@@ -728,12 +720,18 @@ typedef struct _mpt_sge {
 #define dhsprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_EVENTS
+#if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS)
 #define devtprintk(x)  printk x
 #else
 #define devtprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_VERBOSE_EVENTS
+#define devtverboseprintk(x)  printk x
+#else
+#define devtverboseprintk(x)
+#endif
+
 #ifdef MPT_DEBUG_RESET
 #define drsprintk(x)  printk x
 #else
@@ -1030,10 +1028,8 @@ extern int        mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
 extern void     mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
 extern void     mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int      mpt_findImVolumes(MPT_ADAPTER *ioc);
-extern int      mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 extern int      mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 extern int      mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
-extern int      mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
 
 /*
  *  Public data decl's...
index 9b64e07400da464606d1153fce1f6c20f1eb7d4d..b4967bb8a7d64521b23207520fa22702fbce034d 100644 (file)
@@ -140,7 +140,7 @@ static int  mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
  * Event Handler function
  */
 static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
-struct fasync_struct *async_queue=NULL;
+static struct fasync_struct *async_queue=NULL;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -497,7 +497,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
         if (event == 0x21 ) {
                ioc->aen_event_read_flag=1;
                dctlprintk(("Raised SIGIO to application\n"));
-               devtprintk(("Raised SIGIO to application\n"));
+               devtverboseprintk(("Raised SIGIO to application\n"));
                kill_fasync(&async_queue, SIGIO, POLL_IN);
                return 1;
         }
@@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
                ioc->aen_event_read_flag=1;
                dctlprintk(("Raised SIGIO to application\n"));
-               devtprintk(("Raised SIGIO to application\n"));
+               devtverboseprintk(("Raised SIGIO to application\n"));
                kill_fasync(&async_queue, SIGIO, POLL_IN);
        }
        return 1;
@@ -2968,7 +2968,7 @@ static int __init mptctl_init(void)
        }
 
        if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
-               devtprintk((KERN_INFO MYNAM
+               devtverboseprintk((KERN_INFO MYNAM
                  ": Registered for IOC event notifications\n"));
        }
 
index c3a3499bce2ae8c3ece665ce11f98b6027a1cd83..b343f2a68b1c755ceff84c70aaa774f8eff3576f 100644 (file)
@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
 
 static struct scsi_transport_template *mptfc_transport_template = NULL;
 
-struct fc_function_template mptfc_transport_functions = {
+static struct fc_function_template mptfc_transport_functions = {
        .dd_fcrport_size = 8,
        .show_host_node_name = 1,
        .show_host_port_name = 1,
@@ -348,24 +348,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
        return 0;
 }
 
-static void
-mptfc_remap_sdev(struct scsi_device *sdev, void *arg)
-{
-       VirtDevice              *vdev;
-       VirtTarget              *vtarget;
-       struct scsi_target      *starget;
-
-       starget = scsi_target(sdev);
-       if (starget->hostdata == arg) {
-               vtarget = arg;
-               vdev = sdev->hostdata;
-               if (vdev) {
-                       vdev->bus_id = vtarget->bus_id;
-                       vdev->target_id = vtarget->target_id;
-               }
-       }
-}
-
 static void
 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 {
@@ -423,8 +405,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                                if (vtarget) {
                                        vtarget->target_id = pg0->CurrentTargetID;
                                        vtarget->bus_id = pg0->CurrentBus;
-                                       starget_for_each_device(ri->starget,
-                                               vtarget,mptfc_remap_sdev);
                                }
                                ri->remap_needed = 0;
                        }
@@ -432,7 +412,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                                "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
                                "rport tid %d, tmo %d\n",
                                        ioc->name,
-                                       oc->sh->host_no,
+                                       ioc->sh->host_no,
                                        pg0->PortIdentifier,
                                        pg0->WWNN,
                                        pg0->WWPN,
@@ -514,7 +494,7 @@ mptfc_target_alloc(struct scsi_target *starget)
  *     Return non-zero if allocation fails.
  *     Init memory once per LUN.
  */
-int
+static int
 mptfc_slave_alloc(struct scsi_device *sdev)
 {
        MPT_SCSI_HOST           *hd;
@@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev)
        }
 
        vdev->vtarget = vtarget;
-       vdev->ioc_id = hd->ioc->id;
        vdev->lun = sdev->lun;
-       vdev->target_id = vtarget->target_id;
-       vdev->bus_id = vtarget->bus_id;
 
        spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
 
        vtarget->num_luns++;
 
+#ifdef DMPT_DEBUG_FC
+        {
+       struct mptfc_rport_info *ri;
+       ri = *((struct mptfc_rport_info **)rport->dd_data);
        dfcprintk ((MYIOC_s_INFO_FMT
                "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
                "CurrentTargetID %d, %x %llx %llx\n",
-               ioc->name,
+               hd->ioc->name,
                sdev->host->host_no,
                vtarget->num_luns,
                sdev->id, ri->pg0.CurrentTargetID,
                ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
+       }
+#endif
 
        return 0;
 }
@@ -941,7 +924,7 @@ mptfc_init(void)
        mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
 
        if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
-               devtprintk((KERN_INFO MYNAM
+               devtverboseprintk((KERN_INFO MYNAM
                  ": Registered for IOC event notifications\n"));
        }
 
index 73f59528212ae3aa92590eb6058457999afb3776..314c3a27585d8cc686a01243f930fe7489f6a2ed 100644 (file)
@@ -1152,10 +1152,7 @@ mpt_lan_receive_post_reply(struct net_device *dev,
                                priv->mpt_rxfidx_tail,
                                MPT_LAN_MAX_BUCKETS_OUT);
 
-               panic("Damn it Jim! I'm a doctor, not a programmer! "
-                               "Oh, wait a sec, I am a programmer. "
-                               "And, who's Jim?!?!\n"
-                               "Arrgghh! We've done it again!\n");
+               return -1;
        }
 
        if (remaining == 0)
index 2512d0e6155ede3b55f1996b13fe69b6b78eda0a..010d4a39269b8c55dc39eab53516f4a68636f44c 100644 (file)
@@ -104,6 +104,13 @@ struct mptsas_hotplug_event {
        u16                     handle;
        u16                     parent_handle;
        u8                      phy_id;
+       u8                      phys_disk_num;
+       u8                      phys_disk_num_valid;
+};
+
+struct mptsas_discovery_event {
+       struct work_struct      work;
+       MPT_ADAPTER             *ioc;
 };
 
 /*
@@ -117,6 +124,8 @@ struct mptsas_hotplug_event {
 struct mptsas_devinfo {
        u16     handle;         /* unique id to address this device */
        u16     handle_parent;  /* unique id to address parent device */
+       u16     handle_enclosure; /* enclosure identifier of the enclosure */
+       u16     slot;           /* physical slot in enclosure */
        u8      phy_id;         /* phy number of parent device */
        u8      port_id;        /* sas physical port this device
                                   is assoc'd with */
@@ -137,6 +146,7 @@ struct mptsas_phyinfo {
        struct mptsas_devinfo attached; /* point to attached device info */
        struct sas_phy *phy;
        struct sas_rphy *rphy;
+       struct scsi_target *starget;
 };
 
 struct mptsas_portinfo {
@@ -146,6 +156,17 @@ struct mptsas_portinfo {
        struct mptsas_phyinfo *phy_info;
 };
 
+struct mptsas_enclosure {
+       u64     enclosure_logical_id;   /* The WWN for the enclosure */
+       u16     enclosure_handle;       /* unique id to address this */
+       u16     flags;                  /* details enclosure management */
+       u16     num_slot;               /* num slots */
+       u16     start_slot;             /* first slot */
+       u8      start_id;               /* starting logical target id */
+       u8      start_channel;          /* starting logical channel id */
+       u8      sep_id;                 /* SEP device logical target id */
+       u8      sep_channel;            /* SEP channel logical channel id */
+};
 
 #ifdef SASDEBUG
 static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -205,6 +226,7 @@ static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
 
        printk("---- SAS DEVICE PAGE 0 ---------\n");
        printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
+       printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
        printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
        printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
        printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
@@ -243,6 +265,111 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
 #define mptsas_print_expander_pg1(pg1)         do { } while (0)
 #endif
 
+static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
+{
+       struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+       return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+}
+
+static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
+{
+       struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+       return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+}
+
+/*
+ * mptsas_find_portinfo_by_handle
+ *
+ * This function should be called with the sas_topology_mutex already held
+ */
+static struct mptsas_portinfo *
+mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+       struct mptsas_portinfo *port_info, *rc=NULL;
+       int i;
+
+       list_for_each_entry(port_info, &ioc->sas_topology, list)
+               for (i = 0; i < port_info->num_phys; i++)
+                       if (port_info->phy_info[i].identify.handle == handle) {
+                               rc = port_info;
+                               goto out;
+                       }
+ out:
+       return rc;
+}
+
+static int
+mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
+               u32 form, u32 form_specific)
+{
+       ConfigExtendedPageHeader_t hdr;
+       CONFIGPARMS cfg;
+       SasEnclosurePage0_t *buffer;
+       dma_addr_t dma_handle;
+       int error;
+       __le64 le_identifier;
+
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
+       hdr.PageNumber = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
+
+       cfg.cfghdr.ehdr = &hdr;
+       cfg.physAddr = -1;
+       cfg.pageAddr = form + form_specific;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.dir = 0;    /* read */
+       cfg.timeout = 10;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out;
+       if (!hdr.ExtPageLength) {
+               error = -ENXIO;
+               goto out;
+       }
+
+       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                       &dma_handle);
+       if (!buffer) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       cfg.physAddr = dma_handle;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+       error = mpt_config(ioc, &cfg);
+       if (error)
+               goto out_free_consistent;
+
+       /* save config data */
+       memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
+       enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
+       enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
+       enclosure->flags = le16_to_cpu(buffer->Flags);
+       enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
+       enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
+       enclosure->start_id = buffer->StartTargetID;
+       enclosure->start_channel = buffer->StartBus;
+       enclosure->sep_id = buffer->SEPTargetID;
+       enclosure->sep_channel = buffer->SEPBus;
+
+ out_free_consistent:
+       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+                           buffer, dma_handle);
+ out:
+       return error;
+}
+
+static int
+mptsas_slave_configure(struct scsi_device *sdev)
+{
+       sas_read_port_mode_page(sdev);
+
+       return mptscsih_slave_configure(sdev);
+}
 
 /*
  * This is pretty ugly.  We will be able to seriously clean it up
@@ -259,6 +386,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
        VirtTarget              *vtarget;
        VirtDevice              *vdev;
        struct scsi_target      *starget;
+       u32                     target_id;
        int i;
 
        vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
@@ -267,10 +395,10 @@ mptsas_slave_alloc(struct scsi_device *sdev)
                                hd->ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
-       vdev->ioc_id = hd->ioc->id;
        sdev->hostdata = vdev;
        starget = scsi_target(sdev);
        vtarget = starget->hostdata;
+       vtarget->ioc_id = hd->ioc->id;
        vdev->vtarget = vtarget;
        if (vtarget->num_luns == 0) {
                vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
@@ -281,8 +409,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
          RAID volumes placed beyond the last expected port.
        */
        if (sdev->channel == hd->ioc->num_ports) {
-               vdev->target_id = sdev->id;
-               vdev->bus_id = 0;
+               target_id = sdev->id;
+               vtarget->bus_id = 0;
                vdev->lun = 0;
                goto out;
        }
@@ -293,11 +421,21 @@ mptsas_slave_alloc(struct scsi_device *sdev)
                for (i = 0; i < p->num_phys; i++) {
                        if (p->phy_info[i].attached.sas_address ==
                                        rphy->identify.sas_address) {
-                               vdev->target_id =
-                                       p->phy_info[i].attached.id;
-                               vdev->bus_id = p->phy_info[i].attached.channel;
+                               target_id = p->phy_info[i].attached.id;
+                               vtarget->bus_id = p->phy_info[i].attached.channel;
                                vdev->lun = sdev->lun;
-       mutex_unlock(&hd->ioc->sas_topology_mutex);
+                               p->phy_info[i].starget = sdev->sdev_target;
+                               /*
+                                * Exposing hidden disk (RAID)
+                                */
+                               if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
+                                       target_id = mptscsih_raid_id_to_num(hd,
+                                                       target_id);
+                                       vdev->vtarget->tflags |=
+                                           MPT_TARGET_FLAGS_RAID_COMPONENT;
+                                       sdev->no_uld_attach = 1;
+                               }
+                               mutex_unlock(&hd->ioc->sas_topology_mutex);
                                goto out;
                        }
                }
@@ -308,9 +446,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
        return -ENXIO;
 
  out:
-       vtarget->ioc_id = vdev->ioc_id;
-       vtarget->target_id = vdev->target_id;
-       vtarget->bus_id = vdev->bus_id;
+       vtarget->target_id = target_id;
        vtarget->num_luns++;
        return 0;
 }
@@ -320,32 +456,8 @@ mptsas_slave_destroy(struct scsi_device *sdev)
 {
        struct Scsi_Host *host = sdev->host;
        MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
-       struct sas_rphy *rphy;
-       struct mptsas_portinfo *p;
-       int i;
        VirtDevice *vdev;
 
-       /*
-        * Handle hotplug removal case.
-        * We need to clear out attached data structure.
-        */
-       rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
-
-       mutex_lock(&hd->ioc->sas_topology_mutex);
-       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
-               for (i = 0; i < p->num_phys; i++) {
-                       if (p->phy_info[i].attached.sas_address ==
-                                       rphy->identify.sas_address) {
-                               memset(&p->phy_info[i].attached, 0,
-                                   sizeof(struct mptsas_devinfo));
-                               p->phy_info[i].rphy = NULL;
-                               goto out;
-                       }
-               }
-       }
-
- out:
-       mutex_unlock(&hd->ioc->sas_topology_mutex);
        /*
         * Issue target reset to flush firmware outstanding commands.
         */
@@ -353,8 +465,8 @@ mptsas_slave_destroy(struct scsi_device *sdev)
        if (vdev->configured_lun){
                if (mptscsih_TMHandler(hd,
                     MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-                    vdev->bus_id,
-                    vdev->target_id,
+                    vdev->vtarget->bus_id,
+                    vdev->vtarget->target_id,
                     0, 0, 5 /* 5 second timeout */)
                     < 0){
 
@@ -364,7 +476,7 @@ mptsas_slave_destroy(struct scsi_device *sdev)
                        printk(MYIOC_s_WARN_FMT
                       "Error processing TaskMgmt id=%d TARGET_RESET\n",
                                hd->ioc->name,
-                               vdev->target_id);
+                               vdev->vtarget->target_id);
 
                        hd->tmPending = 0;
                        hd->tmState = TM_STATE_NONE;
@@ -382,7 +494,7 @@ static struct scsi_host_template mptsas_driver_template = {
        .queuecommand                   = mptscsih_qcmd,
        .target_alloc                   = mptscsih_target_alloc,
        .slave_alloc                    = mptsas_slave_alloc,
-       .slave_configure                = mptscsih_slave_configure,
+       .slave_configure                = mptsas_slave_configure,
        .target_destroy                 = mptscsih_target_destroy,
        .slave_destroy                  = mptsas_slave_destroy,
        .change_queue_depth             = mptscsih_change_queue_depth,
@@ -399,12 +511,6 @@ static struct scsi_host_template mptsas_driver_template = {
        .use_clustering                 = ENABLE_CLUSTERING,
 };
 
-static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
-{
-       struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
-       return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
-}
-
 static int mptsas_get_linkerrors(struct sas_phy *phy)
 {
        MPT_ADAPTER *ioc = phy_to_ioc(phy);
@@ -546,8 +652,67 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
        return error;
 }
 
+static int
+mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
+{
+       MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
+       int i, error;
+       struct mptsas_portinfo *p;
+       struct mptsas_enclosure enclosure_info;
+       u64 enclosure_handle;
+
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry(p, &ioc->sas_topology, list) {
+               for (i = 0; i < p->num_phys; i++) {
+                       if (p->phy_info[i].attached.sas_address ==
+                           rphy->identify.sas_address) {
+                               enclosure_handle = p->phy_info[i].
+                                       attached.handle_enclosure;
+                               goto found_info;
+                       }
+               }
+       }
+       mutex_unlock(&ioc->sas_topology_mutex);
+       return -ENXIO;
+
+ found_info:
+       mutex_unlock(&ioc->sas_topology_mutex);
+       memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
+       error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
+                       (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
+                        MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
+       if (!error)
+               *identifier = enclosure_info.enclosure_logical_id;
+       return error;
+}
+
+static int
+mptsas_get_bay_identifier(struct sas_rphy *rphy)
+{
+       MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
+       struct mptsas_portinfo *p;
+       int i, rc;
+
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry(p, &ioc->sas_topology, list) {
+               for (i = 0; i < p->num_phys; i++) {
+                       if (p->phy_info[i].attached.sas_address ==
+                           rphy->identify.sas_address) {
+                               rc = p->phy_info[i].attached.slot;
+                               goto out;
+                       }
+               }
+       }
+       rc = -ENXIO;
+ out:
+       mutex_unlock(&ioc->sas_topology_mutex);
+       return rc;
+}
+
 static struct sas_function_template mptsas_transport_functions = {
        .get_linkerrors         = mptsas_get_linkerrors,
+       .get_enclosure_identifier = mptsas_get_enclosure_identifier,
+       .get_bay_identifier     = mptsas_get_bay_identifier,
        .phy_reset              = mptsas_phy_reset,
 };
 
@@ -607,6 +772,9 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                goto out_free_consistent;
        }
 
+       if (port_info->num_phys)
+               port_info->handle =
+                   le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
        for (i = 0; i < port_info->num_phys; i++) {
                mptsas_print_phy_data(&buffer->PhyData[i]);
                port_info->phy_info[i].phy_id = i;
@@ -713,6 +881,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
        cfg.dir = 0;    /* read */
        cfg.timeout = 10;
 
+       memset(device_info, 0, sizeof(struct mptsas_devinfo));
        error = mpt_config(ioc, &cfg);
        if (error)
                goto out;
@@ -739,6 +908,9 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
 
        device_info->handle = le16_to_cpu(buffer->DevHandle);
        device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
+       device_info->handle_enclosure =
+           le16_to_cpu(buffer->EnclosureHandle);
+       device_info->slot = le16_to_cpu(buffer->Slot);
        device_info->phy_id = buffer->PhyNum;
        device_info->port_id = buffer->PhysicalPort;
        device_info->id = buffer->TargetID;
@@ -780,6 +952,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
        cfg.dir = 0;    /* read */
        cfg.timeout = 10;
 
+       memset(port_info, 0, sizeof(struct mptsas_portinfo));
        error = mpt_config(ioc, &cfg);
        if (error)
                goto out;
@@ -880,7 +1053,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
        phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
        phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
 
-
  out_free_consistent:
        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
                            buffer, dma_handle);
@@ -970,12 +1142,19 @@ mptsas_parse_device_info(struct sas_identify *identify,
 static int mptsas_probe_one_phy(struct device *dev,
                struct mptsas_phyinfo *phy_info, int index, int local)
 {
+       MPT_ADAPTER *ioc;
        struct sas_phy *phy;
        int error;
 
-       phy = sas_phy_alloc(dev, index);
-       if (!phy)
-               return -ENOMEM;
+       if (!dev)
+               return -ENODEV;
+
+       if (!phy_info->phy) {
+               phy = sas_phy_alloc(dev, index);
+               if (!phy)
+                       return -ENOMEM;
+       } else
+               phy = phy_info->phy;
 
        phy->port_identifier = phy_info->port_id;
        mptsas_parse_device_info(&phy->identify, &phy_info->identify);
@@ -1061,24 +1240,54 @@ static int mptsas_probe_one_phy(struct device *dev,
                break;
        }
 
-       if (local)
-               phy->local_attached = 1;
+       if (!phy_info->phy) {
 
-       error = sas_phy_add(phy);
-       if (error) {
-               sas_phy_free(phy);
-               return error;
+               if (local)
+                       phy->local_attached = 1;
+
+               error = sas_phy_add(phy);
+               if (error) {
+                       sas_phy_free(phy);
+                       return error;
+               }
+               phy_info->phy = phy;
        }
-       phy_info->phy = phy;
 
-       if (phy_info->attached.handle) {
+       if ((phy_info->attached.handle) &&
+           (!phy_info->rphy)) {
+
                struct sas_rphy *rphy;
+               struct sas_identify identify;
+
+               ioc = phy_to_ioc(phy_info->phy);
 
-               rphy = sas_rphy_alloc(phy);
+               /*
+                * Let the hotplug_work thread handle processing
+                * the adding/removing of devices that occur
+                * after start of day.
+                */
+               if (ioc->sas_discovery_runtime &&
+                       mptsas_is_end_device(&phy_info->attached))
+                       return 0;
+
+               mptsas_parse_device_info(&identify, &phy_info->attached);
+               switch (identify.device_type) {
+               case SAS_END_DEVICE:
+                       rphy = sas_end_device_alloc(phy);
+                       break;
+               case SAS_EDGE_EXPANDER_DEVICE:
+               case SAS_FANOUT_EXPANDER_DEVICE:
+                       rphy = sas_expander_alloc(phy, identify.device_type);
+                       break;
+               default:
+                       rphy = NULL;
+                       break;
+               }
                if (!rphy)
                        return 0; /* non-fatal: an rphy can be added later */
 
-               mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+               rphy->identify = identify;
+
                error = sas_rphy_add(rphy);
                if (error) {
                        sas_rphy_free(rphy);
@@ -1092,24 +1301,37 @@ static int mptsas_probe_one_phy(struct device *dev,
 }
 
 static int
-mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
+mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
 {
-       struct mptsas_portinfo *port_info;
+       struct mptsas_portinfo *port_info, *hba;
        u32 handle = 0xFFFF;
        int error = -ENOMEM, i;
 
-       port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
-       if (!port_info)
+       hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
+       if (! hba)
                goto out;
 
-       error = mptsas_sas_io_unit_pg0(ioc, port_info);
+       error = mptsas_sas_io_unit_pg0(ioc, hba);
        if (error)
                goto out_free_port_info;
 
-       ioc->num_ports = port_info->num_phys;
        mutex_lock(&ioc->sas_topology_mutex);
-       list_add_tail(&port_info->list, &ioc->sas_topology);
+       port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
+       if (!port_info) {
+               port_info = hba;
+               list_add_tail(&port_info->list, &ioc->sas_topology);
+       } else {
+               port_info->handle = hba->handle;
+               for (i = 0; i < hba->num_phys; i++)
+                       port_info->phy_info[i].negotiated_link_rate =
+                               hba->phy_info[i].negotiated_link_rate;
+               if (hba->phy_info)
+                       kfree(hba->phy_info);
+               kfree(hba);
+               hba = NULL;
+       }
        mutex_unlock(&ioc->sas_topology_mutex);
+       ioc->num_ports = port_info->num_phys;
 
        for (i = 0; i < port_info->num_phys; i++) {
                mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
@@ -1132,38 +1354,49 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
                }
 
                mptsas_probe_one_phy(&ioc->sh->shost_gendev,
-                                    &port_info->phy_info[i], *index, 1);
-               (*index)++;
+                   &port_info->phy_info[i], ioc->sas_index, 1);
+               ioc->sas_index++;
        }
 
        return 0;
 
  out_free_port_info:
-       kfree(port_info);
+       if (hba)
+               kfree(hba);
  out:
        return error;
 }
 
 static int
-mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
+mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
 {
-       struct mptsas_portinfo *port_info, *p;
+       struct mptsas_portinfo *port_info, *p, *ex;
        int error = -ENOMEM, i, j;
 
-       port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
-       if (!port_info)
+       ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
+       if (!ex)
                goto out;
 
-       error = mptsas_sas_expander_pg0(ioc, port_info,
+       error = mptsas_sas_expander_pg0(ioc, ex,
                (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
                 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
        if (error)
                goto out_free_port_info;
 
-       *handle = port_info->handle;
+       *handle = ex->handle;
 
        mutex_lock(&ioc->sas_topology_mutex);
-       list_add_tail(&port_info->list, &ioc->sas_topology);
+       port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
+       if (!port_info) {
+               port_info = ex;
+               list_add_tail(&port_info->list, &ioc->sas_topology);
+       } else {
+               port_info->handle = ex->handle;
+               if (ex->phy_info)
+                       kfree(ex->phy_info);
+               kfree(ex);
+               ex = NULL;
+       }
        mutex_unlock(&ioc->sas_topology_mutex);
 
        for (i = 0; i < port_info->num_phys; i++) {
@@ -1189,6 +1422,8 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
                                (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
                                 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
                                port_info->phy_info[i].attached.handle);
+                       port_info->phy_info[i].attached.phy_id =
+                           port_info->phy_info[i].phy_id;
                }
 
                /*
@@ -1208,27 +1443,137 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
                mutex_unlock(&ioc->sas_topology_mutex);
 
                mptsas_probe_one_phy(parent, &port_info->phy_info[i],
-                                    *index, 0);
-               (*index)++;
+                   ioc->sas_index, 0);
+               ioc->sas_index++;
        }
 
        return 0;
 
  out_free_port_info:
-       kfree(port_info);
+       if (ex) {
+               if (ex->phy_info)
+                       kfree(ex->phy_info);
+               kfree(ex);
+       }
  out:
        return error;
 }
 
+/*
+ * mptsas_delete_expander_phys
+ *
+ *
+ * This will traverse topology, and remove expanders
+ * that are no longer present
+ */
+static void
+mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
+{
+       struct mptsas_portinfo buffer;
+       struct mptsas_portinfo *port_info, *n, *parent;
+       int i;
+
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
+
+               if (port_info->phy_info &&
+                   (!(port_info->phy_info[0].identify.device_info &
+                   MPI_SAS_DEVICE_INFO_SMP_TARGET)))
+                       continue;
+
+               if (mptsas_sas_expander_pg0(ioc, &buffer,
+                    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
+                    MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
+
+                       /*
+                        * Obtain the port_info instance to the parent port
+                        */
+                       parent = mptsas_find_portinfo_by_handle(ioc,
+                           port_info->phy_info[0].identify.handle_parent);
+
+                       if (!parent)
+                               goto next_port;
+
+                       /*
+                        * Delete rphys in the parent that point
+                        * to this expander.  The transport layer will
+                        * cleanup all the children.
+                        */
+                       for (i = 0; i < parent->num_phys; i++) {
+                               if ((!parent->phy_info[i].rphy) ||
+                                   (parent->phy_info[i].attached.sas_address !=
+                                  port_info->phy_info[i].identify.sas_address))
+                                       continue;
+                               sas_rphy_delete(parent->phy_info[i].rphy);
+                               memset(&parent->phy_info[i].attached, 0,
+                                   sizeof(struct mptsas_devinfo));
+                               parent->phy_info[i].rphy = NULL;
+                               parent->phy_info[i].starget = NULL;
+                       }
+ next_port:
+                       list_del(&port_info->list);
+                       if (port_info->phy_info)
+                               kfree(port_info->phy_info);
+                       kfree(port_info);
+               }
+               /*
+               * Free this memory allocated from inside
+               * mptsas_sas_expander_pg0
+               */
+               if (buffer.phy_info)
+                       kfree(buffer.phy_info);
+       }
+       mutex_unlock(&ioc->sas_topology_mutex);
+}
+
+/*
+ * Start of day discovery
+ */
 static void
 mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 {
        u32 handle = 0xFFFF;
-       int index = 0;
+       int i;
+
+       mutex_lock(&ioc->sas_discovery_mutex);
+       mptsas_probe_hba_phys(ioc);
+       while (!mptsas_probe_expander_phys(ioc, &handle))
+               ;
+       /*
+         Reporting RAID volumes.
+       */
+       if (!ioc->raid_data.pIocPg2)
+               goto out;
+       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+               goto out;
+       for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+               scsi_add_device(ioc->sh, ioc->num_ports,
+                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
+       }
+ out:
+       mutex_unlock(&ioc->sas_discovery_mutex);
+}
+
+/*
+ * Work queue thread to handle Runtime discovery
+ * Mere purpose is the hot add/delete of expanders
+ */
+static void
+mptscsih_discovery_work(void * arg)
+{
+       struct mptsas_discovery_event *ev = arg;
+       MPT_ADAPTER *ioc = ev->ioc;
+       u32 handle = 0xFFFF;
 
-       mptsas_probe_hba_phys(ioc, &index);
-       while (!mptsas_probe_expander_phys(ioc, &handle, &index))
+       mutex_lock(&ioc->sas_discovery_mutex);
+       ioc->sas_discovery_runtime=1;
+       mptsas_delete_expander_phys(ioc);
+       mptsas_probe_hba_phys(ioc);
+       while (!mptsas_probe_expander_phys(ioc, &handle))
                ;
+       kfree(ev);
+       ioc->sas_discovery_runtime=0;
+       mutex_unlock(&ioc->sas_discovery_mutex);
 }
 
 static struct mptsas_phyinfo *
@@ -1246,10 +1591,8 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
                (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
                 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
                parent_handle);
-       if (error) {
-               printk("mptsas: failed to retrieve device page\n");
+       if (error)
                return NULL;
-       }
 
        /*
         * The phy_info structures are never deallocated during lifetime of
@@ -1296,6 +1639,35 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
        return phy_info;
 }
 
+/*
+ * 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);
+}
+
+static void
+mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
+{
+       sdev->no_uld_attach = data ? 1 : 0;
+       scsi_device_reprobe(sdev);
+}
+
+static void
+mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
+{
+       starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
+                       mptsas_reprobe_lun);
+}
+
+
+/*
+ * Work queue thread to handle SAS hotplug events
+ */
 static void
 mptsas_hotplug_work(void *arg)
 {
@@ -1304,16 +1676,39 @@ mptsas_hotplug_work(void *arg)
        struct mptsas_phyinfo *phy_info;
        struct sas_rphy *rphy;
        struct scsi_device *sdev;
+       struct sas_identify identify;
        char *ds = NULL;
        struct mptsas_devinfo sas_device;
+       VirtTarget *vtarget;
+
+       mutex_lock(&ioc->sas_discovery_mutex);
 
        switch (ev->event_type) {
        case MPTSAS_DEL_DEVICE:
 
                phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
-               if (!phy_info) {
-                       printk("mptsas: remove event for non-existant PHY.\n");
+
+               /*
+                * Sanity checks, for non-existing phys and remote rphys.
+                */
+               if (!phy_info)
                        break;
+               if (!phy_info->rphy)
+                       break;
+               if (phy_info->starget) {
+                       vtarget = phy_info->starget->hostdata;
+
+                       if (!vtarget)
+                               break;
+                       /*
+                        * Handling  RAID components
+                        */
+                       if (ev->phys_disk_num_valid) {
+                               vtarget->target_id = ev->phys_disk_num;
+                               vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+                               mptsas_reprobe_target(vtarget->starget, 1);
+                               break;
+                       }
                }
 
                if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
@@ -1327,55 +1722,74 @@ mptsas_hotplug_work(void *arg)
                       "removing %s device, channel %d, id %d, phy %d\n",
                       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
 
-               if (phy_info->rphy) {
-                       sas_rphy_delete(phy_info->rphy);
-                       phy_info->rphy = NULL;
-               }
+               sas_rphy_delete(phy_info->rphy);
+               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+               phy_info->rphy = NULL;
+               phy_info->starget = NULL;
                break;
        case MPTSAS_ADD_DEVICE:
 
                /*
-                * When there is no sas address,
-                * RAID volumes are being deleted,
-                * and hidden phy disk are being added.
-                * We don't know the SAS data yet,
-                * so lookup sas device page to get
-                * pertaining info
+                * Refresh sas device pg0 data
                 */
-               if (!ev->sas_address) {
-                       if (mptsas_sas_device_pg0(ioc,
-                           &sas_device, ev->id,
-                           (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
-                            MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
-                               break;
-                       ev->handle = sas_device.handle;
-                       ev->parent_handle = sas_device.handle_parent;
-                       ev->channel = sas_device.channel;
-                       ev->phy_id = sas_device.phy_id;
-                       ev->sas_address = sas_device.sas_address;
-                       ev->device_info = sas_device.device_info;
-               }
+               if (mptsas_sas_device_pg0(ioc, &sas_device,
+                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
+                       break;
 
                phy_info = mptsas_find_phyinfo_by_parent(ioc,
-                               ev->parent_handle, ev->phy_id);
+                               sas_device.handle_parent, sas_device.phy_id);
+
                if (!phy_info) {
-                       printk("mptsas: add event for non-existant PHY.\n");
-                       break;
+                       u32 handle = 0xFFFF;
+
+                       /*
+                       * Its possible when an expander has been hot added
+                       * containing attached devices, the sas firmware
+                       * may send a RC_ADDED event prior to the
+                       * DISCOVERY STOP event. If that occurs, our
+                       * view of the topology in the driver in respect to this
+                       * expander might of not been setup, and we hit this
+                       * condition.
+                       * Therefore, this code kicks off discovery to
+                       * refresh the data.
+                       * Then again, we check whether the parent phy has
+                       * been created.
+                       */
+                       ioc->sas_discovery_runtime=1;
+                       mptsas_delete_expander_phys(ioc);
+                       mptsas_probe_hba_phys(ioc);
+                       while (!mptsas_probe_expander_phys(ioc, &handle))
+                               ;
+                       ioc->sas_discovery_runtime=0;
+
+                       phy_info = mptsas_find_phyinfo_by_parent(ioc,
+                               sas_device.handle_parent, sas_device.phy_id);
+                       if (!phy_info)
+                               break;
                }
 
-               if (phy_info->rphy) {
-                       printk("mptsas: trying to add existing device.\n");
+               if (phy_info->starget) {
+                       vtarget = phy_info->starget->hostdata;
+
+                       if (!vtarget)
+                               break;
+                       /*
+                        * Handling  RAID components
+                        */
+                       if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+                               vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+                               vtarget->target_id = ev->id;
+                               mptsas_reprobe_target(phy_info->starget, 0);
+                       }
                        break;
                }
 
-               /* fill attached info */
-               phy_info->attached.handle = ev->handle;
-               phy_info->attached.phy_id = ev->phy_id;
-               phy_info->attached.port_id = phy_info->identify.port_id;
-               phy_info->attached.id = ev->id;
-               phy_info->attached.channel = ev->channel;
-               phy_info->attached.sas_address = ev->sas_address;
-               phy_info->attached.device_info = ev->device_info;
+               if (phy_info->rphy)
+                       break;
+
+               memcpy(&phy_info->attached, &sas_device,
+                   sizeof(struct mptsas_devinfo));
 
                if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
                        ds = "ssp";
@@ -1388,13 +1802,23 @@ mptsas_hotplug_work(void *arg)
                       "attaching %s device, channel %d, id %d, phy %d\n",
                       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
 
-
-               rphy = sas_rphy_alloc(phy_info->phy);
+               mptsas_parse_device_info(&identify, &phy_info->attached);
+               switch (identify.device_type) {
+               case SAS_END_DEVICE:
+                       rphy = sas_end_device_alloc(phy_info->phy);
+                       break;
+               case SAS_EDGE_EXPANDER_DEVICE:
+               case SAS_FANOUT_EXPANDER_DEVICE:
+                       rphy = sas_expander_alloc(phy_info->phy, identify.device_type);
+                       break;
+               default:
+                       rphy = NULL;
+                       break;
+               }
                if (!rphy)
                        break; /* non-fatal: an rphy can be added later */
 
-               rphy->scsi_target_id = phy_info->attached.id;
-               mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+               rphy->identify = identify;
                if (sas_rphy_add(rphy)) {
                        sas_rphy_free(rphy);
                        break;
@@ -1413,7 +1837,7 @@ mptsas_hotplug_work(void *arg)
                        break;
                }
                printk(MYIOC_s_INFO_FMT
-                      "attaching device, channel %d, id %d\n",
+                      "attaching raid volume, channel %d, id %d\n",
                       ioc->name, ioc->num_ports, ev->id);
                scsi_add_device(ioc->sh,
                        ioc->num_ports,
@@ -1430,7 +1854,7 @@ mptsas_hotplug_work(void *arg)
                if (!sdev)
                        break;
                printk(MYIOC_s_INFO_FMT
-                      "removing device, channel %d, id %d\n",
+                      "removing raid volume, channel %d, id %d\n",
                       ioc->name, ioc->num_ports, ev->id);
                scsi_remove_device(sdev);
                scsi_device_put(sdev);
@@ -1439,6 +1863,7 @@ mptsas_hotplug_work(void *arg)
        }
 
        kfree(ev);
+       mutex_unlock(&ioc->sas_discovery_mutex);
 }
 
 static void
@@ -1455,35 +1880,51 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
              MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
                return;
 
-       if ((sas_event_data->ReasonCode &
-            (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
-             MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
-               return;
+       switch (sas_event_data->ReasonCode) {
+       case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+       case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+               ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+               if (!ev) {
+                       printk(KERN_WARNING "mptsas: lost hotplug event\n");
+                       break;
+               }
 
-       ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
-       if (!ev) {
-               printk(KERN_WARNING "mptsas: lost hotplug event\n");
-               return;
+               INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+               ev->ioc = ioc;
+               ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+               ev->parent_handle =
+                   le16_to_cpu(sas_event_data->ParentDevHandle);
+               ev->channel = sas_event_data->Bus;
+               ev->id = sas_event_data->TargetID;
+               ev->phy_id = sas_event_data->PhyNum;
+               memcpy(&sas_address, &sas_event_data->SASAddress,
+                   sizeof(__le64));
+               ev->sas_address = le64_to_cpu(sas_address);
+               ev->device_info = device_info;
+
+               if (sas_event_data->ReasonCode &
+                   MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
+                       ev->event_type = MPTSAS_ADD_DEVICE;
+               else
+                       ev->event_type = MPTSAS_DEL_DEVICE;
+               schedule_work(&ev->work);
+               break;
+       case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+       /*
+        * Persistent table is full.
+        */
+               INIT_WORK(&ioc->mptscsih_persistTask,
+                   mptscsih_sas_persist_clear_table,
+                   (void *)ioc);
+               schedule_work(&ioc->mptscsih_persistTask);
+               break;
+       case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+       /* TODO */
+       case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+       /* TODO */
+       default:
+               break;
        }
-
-
-       INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
-       ev->ioc = ioc;
-       ev->handle = le16_to_cpu(sas_event_data->DevHandle);
-       ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
-       ev->channel = sas_event_data->Bus;
-       ev->id = sas_event_data->TargetID;
-       ev->phy_id = sas_event_data->PhyNum;
-       memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
-       ev->sas_address = le64_to_cpu(sas_address);
-       ev->device_info = device_info;
-
-       if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
-               ev->event_type = MPTSAS_ADD_DEVICE;
-       else
-               ev->event_type = MPTSAS_DEL_DEVICE;
-
-       schedule_work(&ev->work);
 }
 
 static void
@@ -1512,6 +1953,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
                ev->event_type = MPTSAS_ADD_DEVICE;
                break;
        case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+               ioc->raid_data.isRaid = 1;
+               ev->phys_disk_num_valid = 1;
+               ev->phys_disk_num = raid_event_data->PhysDiskNum;
                ev->event_type = MPTSAS_DEL_DEVICE;
                break;
        case MPI_EVENT_RAID_RC_VOLUME_DELETED:
@@ -1533,15 +1977,31 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
        schedule_work(&ev->work);
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* work queue thread to clear the persitency table */
 static void
-mptscsih_sas_persist_clear_table(void * arg)
+mptscsih_send_discovery(MPT_ADAPTER *ioc,
+       EVENT_DATA_SAS_DISCOVERY *discovery_data)
 {
-       MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+       struct mptsas_discovery_event *ev;
+
+       /*
+        * DiscoveryStatus
+        *
+        * This flag will be non-zero when firmware
+        * kicks off discovery, and return to zero
+        * once its completed.
+        */
+       if (discovery_data->DiscoveryStatus)
+               return;
+
+       ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+       if (!ev)
+               return;
+       memset(ev,0,sizeof(struct mptsas_discovery_event));
+       INIT_WORK(&ev->work, mptscsih_discovery_work, ev);
+       ev->ioc = ioc;
+       schedule_work(&ev->work);
+};
 
-       mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
-}
 
 static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
@@ -1552,6 +2012,17 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
        if (!ioc->sh)
                goto out;
 
+       /*
+        * sas_discovery_ignore_events
+        *
+        * This flag is to prevent anymore processing of
+        * sas events once mptsas_remove function is called.
+        */
+       if (ioc->sas_discovery_ignore_events) {
+               rc = mptscsih_event_process(ioc, reply);
+               goto out;
+       }
+
        switch (event) {
        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
                mptscsih_send_sas_event(ioc,
@@ -1567,6 +2038,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
                    (void *)ioc);
                schedule_work(&ioc->mptscsih_persistTask);
                break;
+        case MPI_EVENT_SAS_DISCOVERY:
+               mptscsih_send_discovery(ioc,
+                       (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
+               break;
        default:
                rc = mptscsih_event_process(ioc, reply);
                break;
@@ -1668,7 +2143,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        INIT_LIST_HEAD(&ioc->sas_topology);
        mutex_init(&ioc->sas_topology_mutex);
-
+       mutex_init(&ioc->sas_discovery_mutex);
        mutex_init(&ioc->sas_mgmt.mutex);
        init_completion(&ioc->sas_mgmt.done);
 
@@ -1781,20 +2256,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        mptsas_scan_sas_topology(ioc);
 
-       /*
-         Reporting RAID volumes.
-       */
-       if (!ioc->raid_data.pIocPg2)
-               return 0;
-       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
-               return 0;
-       for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
-               scsi_add_device(sh,
-                       ioc->num_ports,
-                       ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
-                       0);
-       }
-
        return 0;
 
 out_mptsas_probe:
@@ -1808,11 +2269,14 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
        struct mptsas_portinfo *p, *n;
 
+       ioc->sas_discovery_ignore_events=1;
        sas_remove_host(ioc->sh);
 
        mutex_lock(&ioc->sas_topology_mutex);
        list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
                list_del(&p->list);
+               if (p->phy_info)
+                       kfree(p->phy_info);
                kfree(p);
        }
        mutex_unlock(&ioc->sas_topology_mutex);
@@ -1867,7 +2331,7 @@ mptsas_init(void)
        mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
 
        if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
-               devtprintk((KERN_INFO MYNAM
+               devtverboseprintk((KERN_INFO MYNAM
                  ": Registered for IOC event notifications\n"));
        }
 
index 4fee6befc93d0e900fa66fae4e837ef8ac054b51..3729062db3177a2fd6c57c992a6d0c9b09bb1fa2 100644 (file)
@@ -114,21 +114,6 @@ typedef struct _internal_cmd {
        u8              rsvd;
 } INTERNAL_CMD;
 
-typedef struct _negoparms {
-       u8 width;
-       u8 offset;
-       u8 factor;
-       u8 flags;
-} NEGOPARMS;
-
-typedef struct _dv_parameters {
-       NEGOPARMS        max;
-       NEGOPARMS        now;
-       u8               cmd;
-       u8               id;
-       u16              pad1;
-} DVPARAMETERS;
-
 /*
  *  Other private/forward protos...
  */
@@ -149,28 +134,12 @@ 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, 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, struct scsi_cmnd *sc);
-static int     mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
+static void    mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
+static void    mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
 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 void    mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
-static void    mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
-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 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 *);
 void           mptscsih_shutdown(struct pci_dev *);
@@ -181,16 +150,6 @@ int                mptscsih_resume(struct pci_dev *pdev);
 
 #define SNS_LEN(scp)   sizeof((scp)->sense_buffer)
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*
- * Domain Validation task structure
- */
-static DEFINE_SPINLOCK(dvtaskQ_lock);
-static int dvtaskQ_active = 0;
-static int dvtaskQ_release = 0;
-static struct work_struct      dvTaskQ_task;
-#endif
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_add_sge - Place a simple SGE at address pAddr.
@@ -687,9 +646,6 @@ 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 == SPI)
-                               mptscsih_no_negotiate(hd, sc);
                        break;
 
                case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
@@ -931,7 +887,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
                        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->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
+                       if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
                                continue;
 
                        /* Cleanup
@@ -1005,10 +961,6 @@ 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) {
@@ -1021,25 +973,6 @@ mptscsih_remove(struct pci_dev *pdev)
        if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
                return;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       /* Check DV thread active */
-       count = 10 * HZ;
-       spin_lock_irqsave(&dvtaskQ_lock, flags);
-       if (dvtaskQ_active) {
-               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-               while(dvtaskQ_active && --count)
-                       schedule_timeout_interruptible(1);
-       } else {
-               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-       }
-       if (!count)
-               printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-       else
-               printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
-#endif
-#endif
-
        mptscsih_shutdown(pdev);
 
        sz1=0;
@@ -1127,21 +1060,6 @@ mptscsih_resume(struct pci_dev *pdev)
        if(!hd)
                return 0;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       {
-       unsigned long lflags;
-       spin_lock_irqsave(&dvtaskQ_lock, lflags);
-       if (!dvtaskQ_active) {
-               dvtaskQ_active = 1;
-               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-               INIT_WORK(&dvTaskQ_task,
-                 mptscsih_domainValidation, (void *) hd);
-               schedule_work(&dvTaskQ_task);
-       } else {
-               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-       }
-       }
-#endif
        return 0;
 }
 
@@ -1317,6 +1235,14 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
                return SCSI_MLQUEUE_HOST_BUSY;
        }
 
+       if ((hd->ioc->bus_type == SPI) &&
+           vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
+           mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
+               SCpnt->result = DID_NO_CONNECT << 16;
+               done(SCpnt);
+               return 0;
+       }
+
        /*
         *  Put together a MPT SCSI request...
         */
@@ -1360,10 +1286,13 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
        /* Use the above information to set up the message frame
         */
-       pScsiReq->TargetID = (u8) vdev->target_id;
-       pScsiReq->Bus = vdev->bus_id;
+       pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
+       pScsiReq->Bus = vdev->vtarget->bus_id;
        pScsiReq->ChainOffset = 0;
-       pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
+       if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
+               pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
+       else
+               pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
        pScsiReq->CDBLength = SCpnt->cmd_len;
        pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
        pScsiReq->Reserved = 0;
@@ -1411,49 +1340,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        hd->ScsiLookup[my_idx] = SCpnt;
        SCpnt->host_scribble = NULL;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       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) {
-
-                       if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
-                               (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
-                               unsigned long lflags;
-                               /* Schedule DV if necessary */
-                               spin_lock_irqsave(&dvtaskQ_lock, lflags);
-                               if (!dvtaskQ_active) {
-                                       dvtaskQ_active = 1;
-                                       spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-                                       INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
-
-                                       schedule_work(&dvTaskQ_task);
-                               } else {
-                                       spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-                               }
-                               hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
-                       }
-
-                       /* Trying to do DV to this target, extend timeout.
-                        * Wait to issue until flag is clear
-                        */
-                       if (dvStatus & MPT_SCSICFG_DV_PENDING) {
-                               mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
-                               issueCmd = 0;
-                       }
-
-                       /* Set the DV flags.
-                        */
-                       if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
-                               mptscsih_set_dvflags(hd, SCpnt);
-
-                       if (!issueCmd)
-                               goto fail;
-               }
-       }
-#endif
-
        mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
        dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
                        hd->ioc->name, SCpnt, mf, my_idx));
@@ -1816,7 +1702,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-               vdev->bus_id, vdev->target_id, vdev->lun,
+               vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
                ctx2abort, mptscsih_get_tm_timeout(ioc));
 
        printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
@@ -1867,7 +1753,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 
        vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-               vdev->bus_id, vdev->target_id,
+               vdev->vtarget->bus_id, vdev->vtarget->target_id,
                0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
        printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1918,7 +1804,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 
        vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-               vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+               vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
        printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
                hd->ioc->name,
@@ -2218,6 +2104,42 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
        return 0;
 }
 
+/* Search IOC page 3 to determine if this is hidden physical disk
+ *
+ */
+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;
+}
+EXPORT_SYMBOL(mptscsih_is_phys_disk);
+
+int
+mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
+{
+       int i;
+
+       if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
+               return -ENXIO;
+
+       for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+               if (physdiskid ==
+                   hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+                       return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+       }
+
+       return -ENXIO;
+}
+EXPORT_SYMBOL(mptscsih_raid_id_to_num);
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     OS entry point to allow host driver to alloc memory
@@ -2233,6 +2155,7 @@ mptscsih_target_alloc(struct scsi_target *starget)
        if (!vtarget)
                return -ENOMEM;
        starget->hostdata = vtarget;
+       vtarget->starget = starget;
        return 0;
 }
 
@@ -2258,14 +2181,12 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
                return -ENOMEM;
        }
 
-       vdev->ioc_id = hd->ioc->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) {
@@ -2274,14 +2195,11 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
                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
+               if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
+                   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;
                }
        }
        vtarget->num_luns++;
@@ -2321,19 +2239,6 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
        vtarget->luns[0] &= ~(1 << vdevice->lun);
        vtarget->num_luns--;
        if (vtarget->num_luns == 0) {
-               mptscsih_negotiate_to_asyn_narrow(hd, vdevice);
-               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);
@@ -2362,18 +2267,13 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
        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 (((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;
-               } else {
-                       /* error case - No Inq. Data */
+               if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
                        max_depth = 1;
-               }
+               else if (sdev->type == TYPE_DISK &&
+                        vtarget->minSyncFactor <= MPT_ULTRA160)
+                       max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+               else
+                       max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
        } else
                max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
 
@@ -2427,8 +2327,7 @@ mptscsih_slave_configure(struct scsi_device *sdev)
        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_initTarget(hd, vtarget, sdev);
        mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
        dsprintk((MYIOC_s_INFO_FMT
@@ -2597,10 +2496,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
                /* 4. Renegotiate to all devices, if SPI
                 */
-               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);
-               }
 
                /* 5. Enable new commands to be posted
                 */
@@ -2624,13 +2519,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                        hd->cmdPtr = NULL;
                }
 
-               /* 7. SPI: Set flag to force DV and re-read IOC Page 3
-                */
-               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) {
@@ -2659,7 +2547,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        int work_count;
        unsigned long flags;
 
-       devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+       devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
 
        if (ioc->sh == NULL ||
@@ -2699,18 +2587,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                break;
 
        case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
-       {
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-               pMpiEventDataRaid_t pRaidEventData =
-                   (pMpiEventDataRaid_t) pEvReply->Data;
-               /* Domain Validation Needed */
-               if (ioc->bus_type == SPI &&
-                   pRaidEventData->ReasonCode ==
-                   MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
-                       mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
-#endif
                break;
-       }
 
        case MPI_EVENT_NONE:                            /* 00 */
        case MPI_EVENT_LOG_DATA:                        /* 01 */
@@ -2729,9 +2606,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
  *     mptscsih_initTarget - Target, LUN alloc/free functionality.
  *     @hd: Pointer to MPT_SCSI_HOST structure
  *     @vtarget: per target private data
- *     @lun: SCSI LUN id
- *     @data: Pointer to data
- *     @dlen: Number of INQUIRY bytes
+ *     @sdev: SCSI device
  *
  *     NOTE: It's only SAFE to call this routine if data points to
  *     sane & valid STANDARD INQUIRY data!
@@ -2741,98 +2616,46 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
  *
  */
 static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
+mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
+                   struct scsi_device *sdev)
 {
-       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, vtarget->bus_id, vtarget->target_id, lun, hd));
 
-       /*
-        * If the peripheral qualifier filter is enabled then if the target reports a 0x1
-        * (i.e. The targer is capable of supporting the specified peripheral device type
-        * on this logical unit; however, the physical device is not currently connected
-        * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
-        * capable of supporting a physical device on this logical unit). This is to work
-        * around a bug in th emid-layer in some distributions in which the mid-layer will
-        * continue to try to communicate to the LUN and evntually create a dummy LUN.
-       */
-       if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
-               data[0] |= 0x40;
-
        /* Is LUN supported? If so, upper 2 bits will be 0
        * in first byte of inquiry data.
        */
-       if (data[0] & 0xe0)
+       if (sdev->inq_periph_qual != 0)
                return;
 
        if (vtarget == NULL)
                return;
 
-       if (data)
-               vtarget->type = data[0];
+       vtarget->type = sdev->type;
 
        if (hd->ioc->bus_type != SPI)
                return;
 
-       if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+       if ((sdev->type == 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) &&
+       }else if ((sdev->type == 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' ) {
+               if (sdev->inquiry_len > 49 ) {
+                       if (sdev->inquiry[44] == 'S' &&
+                           sdev->inquiry[45] == 'A' &&
+                           sdev->inquiry[46] == 'F' &&
+                           sdev->inquiry[47] == '-' &&
+                           sdev->inquiry[48] == 'T' &&
+                           sdev->inquiry[49] == 'E' ) {
                                vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
                                mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
                        }
                }
        }
-       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;
-
-               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
-                        */
-                               data_56 = data[56];
-                               vtarget->tflags |= MPT_TARGET_FLAGS_VALID_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);
-                       }
-               }
-       }
+       mptscsih_setTargetNegoParms(hd, vtarget, sdev);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2842,66 +2665,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data,
  *
  */
 static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
+                           struct scsi_device *sdev)
 {
        SpiCfgData *pspi_data = &hd->ioc->spi_data;
        int  id = (int) target->target_id;
        int  nvram;
-       VirtTarget      *vtarget;
-       int ii;
        u8 width = MPT_NARROW;
        u8 factor = MPT_ASYNC;
        u8 offset = 0;
-       u8 version, nfactor;
+       u8 nfactor;
        u8 noQas = 1;
 
        target->negoFlags = pspi_data->noQas;
 
-       /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
-        * support. If available, default QAS to off and allow enabling.
-        * If not available, default QAS to on, turn off for non-disks.
-        */
+       /* noQas == 0 => device supports QAS. */
 
-       /* Set flags based on Inquiry data
-        */
-       version = target->inq_data[2] & 0x07;
-       if (version < 2) {
+       if (sdev->scsi_level < SCSI_2) {
                width = 0;
                factor = MPT_ULTRA2;
                offset = pspi_data->maxSyncOffset;
                target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
        } else {
-               if (target->inq_data[7] & 0x20) {
+               if (scsi_device_wide(sdev)) {
                        width = 1;
                }
 
-               if (target->inq_data[7] & 0x10) {
+               if (scsi_device_sync(sdev)) {
                        factor = pspi_data->minSyncFactor;
-                       if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
-                               /* bits 2 & 3 show Clocking support */
-                               if ((byte56 & 0x0C) == 0)
+                       if (!scsi_device_dt(sdev))
                                        factor = MPT_ULTRA2;
+                       else {
+                               if (!scsi_device_ius(sdev) &&
+                                   !scsi_device_qas(sdev))
+                                       factor = MPT_ULTRA160;
                                else {
-                                       if ((byte56 & 0x03) == 0)
-                                               factor = MPT_ULTRA160;
-                                       else {
-                                               factor = MPT_ULTRA320;
-                                               if (byte56 & 0x02)
-                                               {
-                                                       ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
-                                                       noQas = 0;
-                                               }
-                                               if (target->inq_data[0] == TYPE_TAPE) {
-                                                       if (byte56 & 0x01)
-                                                               target->negoFlags |= MPT_TAPE_NEGO_IDP;
-                                               }
+                                       factor = MPT_ULTRA320;
+                                       if (scsi_device_qas(sdev)) {
+                                               ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+                                               noQas = 0;
                                        }
+                                       if (sdev->type == TYPE_TAPE &&
+                                           scsi_device_ius(sdev))
+                                               target->negoFlags |= MPT_TAPE_NEGO_IDP;
                                }
-                       } else {
-                               ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
-                               noQas = 0;
                        }
-
                        offset = pspi_data->maxSyncOffset;
 
                        /* If RAID, never disable QAS
@@ -2919,7 +2727,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
                }
        }
 
-       if ( (target->inq_data[7] & 0x02) == 0) {
+       if (!sdev->tagged_supported) {
                target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
        }
 
@@ -2977,305 +2785,23 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
        if ( factor > MPT_ULTRA320 )
                noQas = 0;
 
-       /* GEM, processor WORKAROUND
-        */
-       if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
-               target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-               pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
-       } else {
-               if (noQas && (pspi_data->noQas == 0)) {
-                       pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
-                       target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
-                       /* Disable QAS in a mixed configuration case
-                       */
-
-                       ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
-                       for (ii = 0; ii < id; ii++) {
-                               if ( (vtarget = hd->Targets[ii]) ) {
-                                       vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-                                       mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
-                               }
-                       }
-               }
-       }
+       if (noQas && (pspi_data->noQas == 0)) {
+               pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+               target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+               /* Disable QAS in a mixed configuration case
+                */
 
-       /* Write SDP1 on this I/O to this target */
-       if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
-               ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
-               mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
-               pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
-       } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
-               ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
-               mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
-               pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+               ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, 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, struct scsi_cmnd *sc)
-{
-       VirtDevice      *vdev;
-
-       if ((vdev = sc->device->hostdata) != NULL)
-               hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
-       return;
-}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  SCSI Config Page functionality ...
  */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
- *     based on width, factor and offset parameters.
- *     @width: bus width
- *     @factor: sync factor
- *     @offset: sync offset
- *     @requestedPtr: pointer to requested values (updated)
- *     @configurationPtr: pointer to configuration values (updated)
- *     @flags: flags to block WDTR or SDTR negotiation
- *
- *     Return: None.
- *
- *     Remark: Called by writeSDP1 and _dv_params
- */
-static void
-mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
-{
-       u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
-       u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
-
-       *configurationPtr = 0;
-       *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
-       *requestedPtr |= (offset << 16) | (factor << 8);
-
-       if (width && offset && !nowide && !nosync) {
-               if (factor < MPT_ULTRA160) {
-                       *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
-                       if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
-                               *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
-                       if (flags & MPT_TAPE_NEGO_IDP)
-                               *requestedPtr |= 0x08000000;
-               } else if (factor < MPT_ULTRA2) {
-                       *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
-               }
-       }
-
-       if (nowide)
-               *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
-
-       if (nosync)
-               *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
-
-       return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_writeSDP1  - write SCSI Device Page 1
- *     @hd: Pointer to a SCSI Host Strucutre
- *     @portnum: IOC port number
- *     @target_id: writeSDP1 for single ID
- *     @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
- *
- *     Return: -EFAULT if read of config page header fails
- *             or 0 if success.
- *
- *     Remark: If a target has been found, the settings from the
- *             target structure are used, else the device is set
- *             to async/narrow.
- *
- *     Remark: Called during init and after a FW reload.
- *     Remark: We do not wait for a return, write pages sequentially.
- */
-static int
-mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
-{
-       MPT_ADAPTER             *ioc = hd->ioc;
-       Config_t                *pReq;
-       SCSIDevicePage1_t       *pData;
-       VirtTarget              *vtarget=NULL;
-       MPT_FRAME_HDR           *mf;
-       dma_addr_t               dataDma;
-       u16                      req_idx;
-       u32                      frameOffset;
-       u32                      requested, configuration, flagsLength;
-       int                      ii, nvram;
-       int                      id = 0, maxid = 0;
-       u8                       width;
-       u8                       factor;
-       u8                       offset;
-       u8                       bus = 0;
-       u8                       negoFlags;
-       u8                       maxwidth, maxoffset, maxfactor;
-
-       if (ioc->spi_data.sdp1length == 0)
-               return 0;
-
-       if (flags & MPT_SCSICFG_ALL_IDS) {
-               id = 0;
-               maxid = ioc->sh->max_id - 1;
-       } else if (ioc->sh) {
-               id = target_id;
-               maxid = min_t(int, id, ioc->sh->max_id - 1);
-       }
-
-       for (; id <= maxid; id++) {
-
-               if (id == ioc->pfacts[portnum].PortSCSIID)
-                       continue;
-
-               /* Use NVRAM to get adapter and target maximums
-                * Data over-riden by target structure information, if present
-                */
-               maxwidth = ioc->spi_data.maxBusWidth;
-               maxoffset = ioc->spi_data.maxSyncOffset;
-               maxfactor = ioc->spi_data.minSyncFactor;
-               if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                       nvram = ioc->spi_data.nvram[id];
-
-                       if (maxwidth)
-                               maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
-                       if (maxoffset > 0) {
-                               maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-                               if (maxfactor == 0) {
-                                       /* Key for async */
-                                       maxfactor = MPT_ASYNC;
-                                       maxoffset = 0;
-                               } else if (maxfactor < ioc->spi_data.minSyncFactor) {
-                                       maxfactor = ioc->spi_data.minSyncFactor;
-                               }
-                       } else
-                               maxfactor = MPT_ASYNC;
-               }
-
-               /* Set the negotiation flags.
-                */
-               negoFlags = ioc->spi_data.noQas;
-               if (!maxwidth)
-                       negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-               if (!maxoffset)
-                       negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-
-               if (flags & MPT_SCSICFG_USE_NVRAM) {
-                       width = maxwidth;
-                       factor = maxfactor;
-                       offset = maxoffset;
-               } else {
-                       width = 0;
-                       factor = MPT_ASYNC;
-                       offset = 0;
-                       //negoFlags = 0;
-                       //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
-               }
-
-               /* If id is not a raid volume, get the updated
-                * transmission settings from the target structure.
-                */
-               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
-               /* Force to async and narrow if DV has not been executed
-                * for this ID
-                */
-               if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
-                       width = 0;
-                       factor = MPT_ASYNC;
-                       offset = 0;
-               }
-#endif
-
-               if (flags & MPT_SCSICFG_BLK_NEGO)
-                       negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
-
-               mptscsih_setDevicePage1Flags(width, factor, offset,
-                                       &requested, &configuration, negoFlags);
-               dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
-                       target_id, width, factor, offset, negoFlags, requested, configuration));
-
-               /* Get a MF for this command.
-                */
-               if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
-                       dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
-                               ioc->name));
-                       return -EAGAIN;
-               }
-
-               ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
-                       hd->ioc->name, mf, id, requested, configuration));
-
-
-               /* Set the request and the data pointers.
-                * Request takes: 36 bytes (32 bit SGE)
-                * SCSI Device Page 1 requires 16 bytes
-                * 40 + 16 <= size of SCSI IO Request = 56 bytes
-                * and MF size >= 64 bytes.
-                * Place data at end of MF.
-                */
-               pReq = (Config_t *)mf;
-
-               req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-               frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
-
-               pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
-               dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
-
-               /* Complete the request frame (same for all requests).
-                */
-               pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-               pReq->Reserved = 0;
-               pReq->ChainOffset = 0;
-               pReq->Function = MPI_FUNCTION_CONFIG;
-               pReq->ExtPageLength = 0;
-               pReq->ExtPageType = 0;
-               pReq->MsgFlags = 0;
-               for (ii=0; ii < 8; ii++) {
-                       pReq->Reserved2[ii] = 0;
-               }
-               pReq->Header.PageVersion = ioc->spi_data.sdp1version;
-               pReq->Header.PageLength = ioc->spi_data.sdp1length;
-               pReq->Header.PageNumber = 1;
-               pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-               pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
-
-               /* Add a SGE to the config request.
-                */
-               flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
-
-               mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
-
-               /* Set up the common data portion
-                */
-               pData->Header.PageVersion = pReq->Header.PageVersion;
-               pData->Header.PageLength = pReq->Header.PageLength;
-               pData->Header.PageNumber = pReq->Header.PageNumber;
-               pData->Header.PageType = pReq->Header.PageType;
-               pData->RequestedParameters = cpu_to_le32(requested);
-               pData->Reserved = 0;
-               pData->Configuration = cpu_to_le32(configuration);
-
-               dprintk((MYIOC_s_INFO_FMT
-                       "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
-                               ioc->name, id, (id | (bus<<8)),
-                               requested, configuration));
-
-               mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
-       }
-
-       return 0;
-}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*     mptscsih_writeIOCPage4  - write IOC Page 4
@@ -3465,6 +2991,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                        completionCode = MPT_SCANDV_GOOD;
                                else
                                        completionCode = MPT_SCANDV_SOME_ERROR;
+                               memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
 
                        } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
                                u8              *sense_data;
@@ -3578,78 +3105,6 @@ mptscsih_timer_expired(unsigned long data)
        return;
 }
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_do_raid - Format and Issue a RAID volume request message.
- *     @hd: Pointer to scsi host structure
- *     @action: What do be done.
- *     @id: Logical target id.
- *     @bus: Target locations bus.
- *
- *     Returns: < 0 on a fatal error
- *             0 on success
- *
- *     Remark: Wait to return until reply processed by the ISR.
- */
-static int
-mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
-{
-       MpiRaidActionRequest_t  *pReq;
-       MPT_FRAME_HDR           *mf;
-       int                     in_isr;
-
-       in_isr = in_interrupt();
-       if (in_isr) {
-               dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
-                                       hd->ioc->name));
-               return -EPERM;
-       }
-
-       /* Get and Populate a free Frame
-        */
-       if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
-               ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
-                                       hd->ioc->name));
-               return -EAGAIN;
-       }
-       pReq = (MpiRaidActionRequest_t *)mf;
-       pReq->Action = action;
-       pReq->Reserved1 = 0;
-       pReq->ChainOffset = 0;
-       pReq->Function = MPI_FUNCTION_RAID_ACTION;
-       pReq->VolumeID = io->id;
-       pReq->VolumeBus = io->bus;
-       pReq->PhysDiskNum = io->physDiskNum;
-       pReq->MsgFlags = 0;
-       pReq->Reserved2 = 0;
-       pReq->ActionDataWord = 0; /* Reserved for this action */
-       //pReq->ActionDataSGE = 0;
-
-       mpt_add_sge((char *)&pReq->ActionDataSGE,
-               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
-
-       ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
-                       hd->ioc->name, action, io->id));
-
-       hd->pLocal = NULL;
-       hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
-       hd->scandv_wait_done = 0;
-
-       /* Save cmd pointer, for resource free if timeout or
-        * FW reload occurs
-        */
-       hd->cmdPtr = mf;
-
-       add_timer(&hd->timer);
-       mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
-       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
-
-       if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
-               return -1;
-
-       return 0;
-}
-#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -3901,93 +3356,6 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        return rc;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     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.
- *
- */
-static void
-mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
-{
-       VirtTarget              *vtarget = vdevice->vtarget;
-       MPT_ADAPTER             *ioc= hd->ioc;
-       SCSIDevicePage1_t       *pcfg1Data;
-       CONFIGPARMS              cfg;
-       dma_addr_t               cfg1_dma_addr;
-       ConfigPageHeader_t       header;
-       int                      id;
-       int                      requested, configuration, data,i;
-       u8                       flags, factor;
-
-       if ((ioc->bus_type != SPI) ||
-               (!vdevice->configured_lun))
-               return;
-
-       if (!ioc->spi_data.sdp1length)
-               return;
-
-       pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
-                ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
-
-       if (pcfg1Data == NULL)
-               return;
-
-       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;
-
-       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;
-                       }
-                       mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
-                               &configuration, flags);
-                       dnegoprintk(("nego asyn narrow: 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 = (vtarget->bus_id<<8) | id;
-                       mpt_config(hd->ioc, &cfg);
-               }
-       } else {
-               flags = vtarget->negoFlags;
-               mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
-                               &configuration, flags);
-               dnegoprintk(("nego asyn narrow: 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 (pcfg1Data)
-               pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
@@ -4014,1637 +3382,15 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
        iocmd.data_dma = -1;
        iocmd.size = 0;
        iocmd.rsvd = iocmd.rsvd2 = 0;
-       iocmd.bus = vdevice->bus_id;
-       iocmd.id = vdevice->target_id;
+       iocmd.bus = vdevice->vtarget->bus_id;
+       iocmd.id = vdevice->vtarget->target_id;
        iocmd.lun = (u8)vdevice->lun;
 
-       if ((vdevice->vtarget->type & TYPE_DISK) &&
+       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;
-
-       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-               if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-                       return 1;
-       }
-
-       return 0;
-}
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_domainValidation - Top level handler for domain validation.
- *     @hd: Pointer to MPT_SCSI_HOST structure.
- *
- *     Uses the ISR, but with special processing.
- *     Called from schedule, should not be in interrupt mode.
- *     While thread alive, do dv for all devices needing dv
- *
- *     Return: None.
- */
-static void
-mptscsih_domainValidation(void *arg)
-{
-       MPT_SCSI_HOST           *hd;
-       MPT_ADAPTER             *ioc;
-       unsigned long            flags;
-       int                      id, maxid, dvStatus, did;
-       int                      ii, isPhysDisk;
-
-       spin_lock_irqsave(&dvtaskQ_lock, flags);
-       dvtaskQ_active = 1;
-       if (dvtaskQ_release) {
-               dvtaskQ_active = 0;
-               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-       /* For this ioc, loop through all devices and do dv to each device.
-        * When complete with this ioc, search through the ioc list, and
-        * for each scsi ioc found, do dv for all devices. Exit when no
-        * device needs dv.
-        */
-       did = 1;
-       while (did) {
-               did = 0;
-               list_for_each_entry(ioc, &ioc_list, list) {
-                       spin_lock_irqsave(&dvtaskQ_lock, flags);
-                       if (dvtaskQ_release) {
-                               dvtaskQ_active = 0;
-                               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-                               return;
-                       }
-                       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-                       msleep(250);
-
-                       /* DV only to SPI adapters */
-                       if (ioc->bus_type != SPI)
-                               continue;
-
-                       /* Make sure everything looks ok */
-                       if (ioc->sh == NULL)
-                               continue;
-
-                       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-                       if (hd == NULL)
-                               continue;
-
-                       if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
-                               mpt_read_ioc_pg_3(ioc);
-                               if (ioc->raid_data.pIocPg3) {
-                                       Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
-                                       int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
-                                       while (numPDisk) {
-                                               if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
-                                                       ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
-
-                                               pPDisk++;
-                                               numPDisk--;
-                                       }
-                               }
-                               ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
-                       }
-
-                       maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
-
-                       for (id = 0; id < maxid; id++) {
-                               spin_lock_irqsave(&dvtaskQ_lock, flags);
-                               if (dvtaskQ_release) {
-                                       dvtaskQ_active = 0;
-                                       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-                                       return;
-                               }
-                               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-                               dvStatus = hd->ioc->spi_data.dvStatus[id];
-
-                               if (dvStatus & MPT_SCSICFG_NEED_DV) {
-                                       did++;
-                                       hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
-                                       hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
-
-                                       msleep(250);
-
-                                       /* If hidden phys disk, block IO's to all
-                                        *      raid volumes
-                                        * else, process normally
-                                        */
-                                       isPhysDisk = mptscsih_is_phys_disk(ioc, id);
-                                       if (isPhysDisk) {
-                                               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                                                       if (hd->ioc->raid_data.isRaid & (1 << ii)) {
-                                                               hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
-                                                       }
-                                               }
-                                       }
-
-                                       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
-                                                */
-                                               hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
-                                               hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
-                                       } else {
-                                               /* DV is complete. Clear flags.
-                                                */
-                                               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)) {
-                                                               hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
-                                                       }
-                                               }
-                                       }
-
-                                       if (hd->ioc->spi_data.noQas)
-                                               mptscsih_qas_check(hd, id);
-                               }
-                       }
-               }
-       }
-
-       spin_lock_irqsave(&dvtaskQ_lock, flags);
-       dvtaskQ_active = 0;
-       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-       return;
-}
-
-/* Write SDP1 if no QAS has been enabled
- */
-static void
-mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
-{
-       VirtTarget *vtarget;
-       int ii;
-
-       if (hd->Targets == NULL)
-               return;
-
-       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-               if (ii == id)
-                       continue;
-
-               if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
-                       continue;
-
-               vtarget = hd->Targets[ii];
-
-               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);
-                       }
-               } else {
-                       if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
-                               dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
-                               mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
-                       }
-               }
-       }
-       return;
-}
-
-
-
-#define MPT_GET_NVRAM_VALS     0x01
-#define MPT_UPDATE_MAX         0x02
-#define MPT_SET_MAX            0x04
-#define MPT_SET_MIN            0x08
-#define MPT_FALLBACK           0x10
-#define MPT_SAVE               0x20
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_doDv - Perform domain validation to a target.
- *     @hd: Pointer to MPT_SCSI_HOST structure.
- *     @portnum: IOC port number.
- *     @target: Physical ID of this target
- *
- *     Uses the ISR, but with special processing.
- *     MUST be single-threaded.
- *     Test will exit if target is at async & narrow.
- *
- *     Return: None.
- */
-static int
-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
-{
-       MPT_ADAPTER             *ioc = hd->ioc;
-       VirtTarget              *vtarget;
-       SCSIDevicePage1_t       *pcfg1Data;
-       SCSIDevicePage0_t       *pcfg0Data;
-       u8                      *pbuf1;
-       u8                      *pbuf2;
-       u8                      *pDvBuf;
-       dma_addr_t               dvbuf_dma = -1;
-       dma_addr_t               buf1_dma = -1;
-       dma_addr_t               buf2_dma = -1;
-       dma_addr_t               cfg1_dma_addr = -1;
-       dma_addr_t               cfg0_dma_addr = -1;
-       ConfigPageHeader_t       header1;
-       ConfigPageHeader_t       header0;
-       DVPARAMETERS             dv;
-       INTERNAL_CMD             iocmd;
-       CONFIGPARMS              cfg;
-       int                      dv_alloc = 0;
-       int                      rc, sz = 0;
-       int                      bufsize = 0;
-       int                      dataBufSize = 0;
-       int                      echoBufSize = 0;
-       int                      notDone;
-       int                      patt;
-       int                      repeat;
-       int                      retcode = 0;
-       int                      nfactor =  MPT_ULTRA320;
-       char                     firstPass = 1;
-       char                     doFallback = 0;
-       char                     readPage0;
-       char                     bus, lun;
-       char                     inq0 = 0;
-
-       if (ioc->spi_data.sdp1length == 0)
-               return 0;
-
-       if (ioc->spi_data.sdp0length == 0)
-               return 0;
-
-       /* If multiple buses are used, require that the initiator
-        * id be the same on all buses.
-        */
-       if (id == ioc->pfacts[0].PortSCSIID)
-               return 0;
-
-       lun = 0;
-       bus = (u8) bus_number;
-       ddvtprintk((MYIOC_s_NOTE_FMT
-                       "DV started: bus=%d, id=%d dv @ %p\n",
-                       ioc->name, bus, id, &dv));
-
-       /* Prep DV structure
-        */
-       memset (&dv, 0, sizeof(DVPARAMETERS));
-       dv.id = id;
-
-       /* Populate tmax with the current maximum
-        * transfer parameters for this target.
-        * Exit if narrow and async.
-        */
-       dv.cmd = MPT_GET_NVRAM_VALS;
-       mptscsih_dv_parms(hd, &dv, NULL);
-
-       /* Prep SCSI IO structure
-        */
-       iocmd.id = id;
-       iocmd.bus = bus;
-       iocmd.lun = lun;
-       iocmd.flags = 0;
-       iocmd.physDiskNum = -1;
-       iocmd.rsvd = iocmd.rsvd2 = 0;
-
-       vtarget = hd->Targets[id];
-
-       /* Use tagged commands if possible.
-        */
-       if (vtarget) {
-               if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
-                       iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
-               else {
-                       if (hd->ioc->facts.FWVersion.Word < 0x01000600)
-                               return 0;
-
-                       if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
-                               (hd->ioc->facts.FWVersion.Word < 0x01010B00))
-                               return 0;
-               }
-       }
-
-       /* Prep cfg structure
-        */
-       cfg.pageAddr = (bus<<8) | id;
-       cfg.cfghdr.hdr = NULL;
-
-       /* Prep SDP0 header
-        */
-       header0.PageVersion = ioc->spi_data.sdp0version;
-       header0.PageLength = ioc->spi_data.sdp0length;
-       header0.PageNumber = 0;
-       header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
-       /* Prep SDP1 header
-        */
-       header1.PageVersion = ioc->spi_data.sdp1version;
-       header1.PageLength = ioc->spi_data.sdp1length;
-       header1.PageNumber = 1;
-       header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
-       if (header0.PageLength & 1)
-               dv_alloc = (header0.PageLength * 4) + 4;
-
-       dv_alloc +=  (2048 + (header1.PageLength * 4));
-
-       pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
-       if (pDvBuf == NULL)
-               return 0;
-
-       sz = 0;
-       pbuf1 = (u8 *)pDvBuf;
-       buf1_dma = dvbuf_dma;
-       sz +=1024;
-
-       pbuf2 = (u8 *) (pDvBuf + sz);
-       buf2_dma = dvbuf_dma + sz;
-       sz +=1024;
-
-       pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
-       cfg0_dma_addr = dvbuf_dma + sz;
-       sz += header0.PageLength * 4;
-
-       /* 8-byte alignment
-        */
-       if (header0.PageLength & 1)
-               sz += 4;
-
-       pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
-       cfg1_dma_addr = dvbuf_dma + sz;
-
-       /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
-        */
-       {
-               SpiCfgData *pspi_data = &hd->ioc->spi_data;
-               if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                       /* Set the factor from nvram */
-                       nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
-                       if (nfactor < pspi_data->minSyncFactor )
-                               nfactor = pspi_data->minSyncFactor;
-
-                       if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
-                               (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
-
-                               ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
-                                       ioc->name, bus, id, lun));
-
-                               dv.cmd = MPT_SET_MAX;
-                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-                               cfg.cfghdr.hdr = &header1;
-
-                               /* Save the final negotiated settings to
-                                * SCSI device page 1.
-                                */
-                               cfg.physAddr = cfg1_dma_addr;
-                               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-                               cfg.dir = 1;
-                               mpt_config(hd->ioc, &cfg);
-                               goto target_done;
-                       }
-               }
-       }
-
-       /* Finish iocmd inititialization - hidden or visible disk? */
-       if (ioc->raid_data.pIocPg3) {
-               /* Search IOC page 3 for matching id
-                */
-               Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
-               int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
-               while (numPDisk) {
-                       if (pPDisk->PhysDiskID == id) {
-                               /* match */
-                               iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
-                               iocmd.physDiskNum = pPDisk->PhysDiskNum;
-
-                               /* Quiesce the IM
-                                */
-                               if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
-                                       ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
-                                       goto target_done;
-                               }
-                               break;
-                       }
-                       pPDisk++;
-                       numPDisk--;
-               }
-       }
-
-       /* RAID Volume ID's may double for a physical device. If RAID but
-        * not a physical ID as well, skip DV.
-        */
-       if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
-               goto target_done;
-
-
-       /* Basic Test.
-        * Async & Narrow - Inquiry
-        * Async & Narrow - Inquiry
-        * Maximum transfer rate - Inquiry
-        * Compare buffers:
-        *      If compare, test complete.
-        *      If miscompare and first pass, repeat
-        *      If miscompare and not first pass, fall back and repeat
-        */
-       hd->pLocal = NULL;
-       readPage0 = 0;
-       sz = SCSI_MAX_INQUIRY_BYTES;
-       rc = MPT_SCANDV_GOOD;
-       while (1) {
-               ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
-               retcode = 0;
-               dv.cmd = MPT_SET_MIN;
-               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-               cfg.cfghdr.hdr = &header1;
-               cfg.physAddr = cfg1_dma_addr;
-               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-               cfg.dir = 1;
-               if (mpt_config(hd->ioc, &cfg) != 0)
-                       goto target_done;
-
-               /* Wide - narrow - wide workaround case
-                */
-               if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
-                       /* Send an untagged command to reset disk Qs corrupted
-                        * when a parity error occurs on a Request Sense.
-                        */
-                       if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
-                               ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
-                               (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
-
-                               iocmd.cmd = REQUEST_SENSE;
-                               iocmd.data_dma = buf1_dma;
-                               iocmd.data = pbuf1;
-                               iocmd.size = 0x12;
-                               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                                       goto target_done;
-                               else {
-                                       if (hd->pLocal == NULL)
-                                               goto target_done;
-                                       rc = hd->pLocal->completion;
-                                       if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
-                                               dv.max.width = 0;
-                                               doFallback = 0;
-                                       } else
-                                               goto target_done;
-                               }
-                       } else
-                               goto target_done;
-               }
-
-               iocmd.cmd = INQUIRY;
-               iocmd.data_dma = buf1_dma;
-               iocmd.data = pbuf1;
-               iocmd.size = sz;
-               memset(pbuf1, 0x00, sz);
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else {
-                       if (hd->pLocal == NULL)
-                               goto target_done;
-                       rc = hd->pLocal->completion;
-                       if (rc == MPT_SCANDV_GOOD) {
-                               if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
-                                       if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
-                                               retcode = 1;
-                                       else
-                                               retcode = 0;
-
-                                       goto target_done;
-                               }
-                       } else if  (rc == MPT_SCANDV_SENSE) {
-                               ;
-                       } else {
-                               /* If first command doesn't complete
-                                * with a good status or with a check condition,
-                                * exit.
-                                */
-                               goto target_done;
-                       }
-               }
-
-               /* Reset the size for disks
-                */
-               inq0 = (*pbuf1) & 0x1F;
-               if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
-                       sz = 0x40;
-                       iocmd.size = sz;
-               }
-
-               /* Another GEM workaround. Check peripheral device type,
-                * if PROCESSOR, quit DV.
-                */
-               if (inq0 == TYPE_PROCESSOR) {
-                       mptscsih_initTarget(hd,
-                               vtarget,
-                               lun,
-                               pbuf1,
-                               sz);
-                       goto target_done;
-               }
-
-               if (inq0 > 0x08)
-                       goto target_done;
-
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-
-               if (sz == 0x40) {
-                       if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
-                               && (vtarget->minSyncFactor > 0x09)) {
-                               if ((pbuf1[56] & 0x04) == 0)
-                                       ;
-                               else if ((pbuf1[56] & 0x01) == 1) {
-                                       vtarget->minSyncFactor =
-                                           nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
-                               } else {
-                                       vtarget->minSyncFactor =
-                                           nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
-                               }
-
-                               dv.max.factor = vtarget->minSyncFactor;
-
-                               if ((pbuf1[56] & 0x02) == 0) {
-                                       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",
-                                           ioc->name, id, pbuf1[56]));
-                               }
-                       }
-               }
-
-               if (doFallback)
-                       dv.cmd = MPT_FALLBACK;
-               else
-                       dv.cmd = MPT_SET_MAX;
-
-               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-               if (mpt_config(hd->ioc, &cfg) != 0)
-                       goto target_done;
-
-               if ((!dv.now.width) && (!dv.now.offset))
-                       goto target_done;
-
-               iocmd.cmd = INQUIRY;
-               iocmd.data_dma = buf2_dma;
-               iocmd.data = pbuf2;
-               iocmd.size = sz;
-               memset(pbuf2, 0x00, sz);
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else if (hd->pLocal == NULL)
-                       goto target_done;
-               else {
-                       /* Save the return code.
-                        * If this is the first pass,
-                        * read SCSI Device Page 0
-                        * and update the target max parameters.
-                        */
-                       rc = hd->pLocal->completion;
-                       doFallback = 0;
-                       if (rc == MPT_SCANDV_GOOD) {
-                               if (!readPage0) {
-                                       u32 sdp0_info;
-                                       u32 sdp0_nego;
-
-                                       cfg.cfghdr.hdr = &header0;
-                                       cfg.physAddr = cfg0_dma_addr;
-                                       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-                                       cfg.dir = 0;
-
-                                       if (mpt_config(hd->ioc, &cfg) != 0)
-                                               goto target_done;
-
-                                       sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
-                                       sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
-
-                                       /* Quantum and Fujitsu workarounds.
-                                        * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
-                                        * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
-                                        * Resetart with a request for U160.
-                                        */
-                                       if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
-                                                       doFallback = 1;
-                                       } else {
-                                               dv.cmd = MPT_UPDATE_MAX;
-                                               mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
-                                               /* Update the SCSI device page 1 area
-                                                */
-                                               pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
-                                               readPage0 = 1;
-                                       }
-                               }
-
-                               /* Quantum workaround. Restart this test will the fallback
-                                * flag set.
-                                */
-                               if (doFallback == 0) {
-                                       if (memcmp(pbuf1, pbuf2, sz) != 0) {
-                                               if (!firstPass)
-                                                       doFallback = 1;
-                                       } else {
-                                               ddvprintk((MYIOC_s_NOTE_FMT
-                                                   "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,
-                                                       vtarget,
-                                                       lun,
-                                                       pbuf1,
-                                                       sz);
-                                               break;  /* test complete */
-                                       }
-                               }
-
-
-                       } else if (rc == MPT_SCANDV_ISSUE_SENSE)
-                               doFallback = 1; /* set fallback flag */
-                       else if ((rc == MPT_SCANDV_DID_RESET) ||
-                                (rc == MPT_SCANDV_SENSE) ||
-                                (rc == MPT_SCANDV_FALLBACK))
-                               doFallback = 1; /* set fallback flag */
-                       else
-                               goto target_done;
-
-                       firstPass = 0;
-               }
-       }
-       ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
-
-       if (ioc->spi_data.mpt_dv == 0)
-               goto target_done;
-
-       inq0 = (*pbuf1) & 0x1F;
-
-       /* Continue only for disks
-        */
-       if (inq0 != 0)
-               goto target_done;
-
-       if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
-               goto target_done;
-
-       /* Start the Enhanced Test.
-        * 0) issue TUR to clear out check conditions
-        * 1) read capacity of echo (regular) buffer
-        * 2) reserve device
-        * 3) do write-read-compare data pattern test
-        * 4) release
-        * 5) update nego parms to target struct
-        */
-       cfg.cfghdr.hdr = &header1;
-       cfg.physAddr = cfg1_dma_addr;
-       cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-       cfg.dir = 1;
-
-       iocmd.cmd = TEST_UNIT_READY;
-       iocmd.data_dma = -1;
-       iocmd.data = NULL;
-       iocmd.size = 0;
-       notDone = 1;
-       while (notDone) {
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-
-               if (hd->pLocal == NULL)
-                       goto target_done;
-
-               rc = hd->pLocal->completion;
-               if (rc == MPT_SCANDV_GOOD)
-                       notDone = 0;
-               else if (rc == MPT_SCANDV_SENSE) {
-                       u8 skey = hd->pLocal->sense[2] & 0x0F;
-                       u8 asc = hd->pLocal->sense[12];
-                       u8 ascq = hd->pLocal->sense[13];
-                       ddvprintk((MYIOC_s_INFO_FMT
-                               "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-                               ioc->name, skey, asc, ascq));
-
-                       if (skey == UNIT_ATTENTION)
-                               notDone++; /* repeat */
-                       else if ((skey == NOT_READY) &&
-                                       (asc == 0x04)&&(ascq == 0x01)) {
-                               /* wait then repeat */
-                               mdelay (2000);
-                               notDone++;
-                       } else if ((skey == NOT_READY) && (asc == 0x3A)) {
-                               /* no medium, try read test anyway */
-                               notDone = 0;
-                       } else {
-                               /* All other errors are fatal.
-                                */
-                               ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
-                                               ioc->name));
-                               goto target_done;
-                       }
-               } else
-                       goto target_done;
-       }
-
-       iocmd.cmd = READ_BUFFER;
-       iocmd.data_dma = buf1_dma;
-       iocmd.data = pbuf1;
-       iocmd.size = 4;
-       iocmd.flags |= MPT_ICFLAG_BUF_CAP;
-
-       dataBufSize = 0;
-       echoBufSize = 0;
-       for (patt = 0; patt < 2; patt++) {
-               if (patt == 0)
-                       iocmd.flags |= MPT_ICFLAG_ECHO;
-               else
-                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-
-               notDone = 1;
-               while (notDone) {
-                       bufsize = 0;
-
-                       /* If not ready after 8 trials,
-                        * give up on this device.
-                        */
-                       if (notDone > 8)
-                               goto target_done;
-
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-                       else if (hd->pLocal == NULL)
-                               goto target_done;
-                       else {
-                               rc = hd->pLocal->completion;
-                               ddvprintk(("ReadBuffer Comp Code %d", rc));
-                               ddvprintk(("  buff: %0x %0x %0x %0x\n",
-                                       pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
-
-                               if (rc == MPT_SCANDV_GOOD) {
-                                       notDone = 0;
-                                       if (iocmd.flags & MPT_ICFLAG_ECHO) {
-                                               bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
-                                               if (pbuf1[0] & 0x01)
-                                                       iocmd.flags |= MPT_ICFLAG_EBOS;
-                                       } else {
-                                               bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
-                                       }
-                               } else if (rc == MPT_SCANDV_SENSE) {
-                                       u8 skey = hd->pLocal->sense[2] & 0x0F;
-                                       u8 asc = hd->pLocal->sense[12];
-                                       u8 ascq = hd->pLocal->sense[13];
-                                       ddvprintk((MYIOC_s_INFO_FMT
-                                               "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-                                               ioc->name, skey, asc, ascq));
-                                       if (skey == ILLEGAL_REQUEST) {
-                                               notDone = 0;
-                                       } else if (skey == UNIT_ATTENTION) {
-                                               notDone++; /* repeat */
-                                       } else if ((skey == NOT_READY) &&
-                                               (asc == 0x04)&&(ascq == 0x01)) {
-                                               /* wait then repeat */
-                                               mdelay (2000);
-                                               notDone++;
-                                       } else {
-                                               /* All other errors are fatal.
-                                                */
-                                               ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
-                                                       ioc->name));
-                                               goto target_done;
-                                       }
-                               } else {
-                                       /* All other errors are fatal
-                                        */
-                                       goto target_done;
-                               }
-                       }
-               }
-
-               if (iocmd.flags & MPT_ICFLAG_ECHO)
-                       echoBufSize = bufsize;
-               else
-                       dataBufSize = bufsize;
-       }
-       sz = 0;
-       iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
-
-       /* Use echo buffers if possible,
-        * Exit if both buffers are 0.
-        */
-       if (echoBufSize > 0) {
-               iocmd.flags |= MPT_ICFLAG_ECHO;
-               if (dataBufSize > 0)
-                       bufsize = min(echoBufSize, dataBufSize);
-               else
-                       bufsize = echoBufSize;
-       } else if (dataBufSize == 0)
-               goto target_done;
-
-       ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
-               (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
-
-       /* Data buffers for write-read-compare test max 1K.
-        */
-       sz = min(bufsize, 1024);
-
-       /* --- loop ----
-        * On first pass, always issue a reserve.
-        * On additional loops, only if a reset has occurred.
-        * iocmd.flags indicates if echo or regular buffer
-        */
-       for (patt = 0; patt < 4; patt++) {
-               ddvprintk(("Pattern %d\n", patt));
-               if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
-                       iocmd.cmd = TEST_UNIT_READY;
-                       iocmd.data_dma = -1;
-                       iocmd.data = NULL;
-                       iocmd.size = 0;
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-
-                       iocmd.cmd = RELEASE;
-                       iocmd.data_dma = -1;
-                       iocmd.data = NULL;
-                       iocmd.size = 0;
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-                       else if (hd->pLocal == NULL)
-                               goto target_done;
-                       else {
-                               rc = hd->pLocal->completion;
-                               ddvprintk(("Release rc %d\n", rc));
-                               if (rc == MPT_SCANDV_GOOD)
-                                       iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-                               else
-                                       goto target_done;
-                       }
-                       iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-               }
-               iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
-
-               if (iocmd.flags & MPT_ICFLAG_EBOS)
-                       goto skip_Reserve;
-
-               repeat = 5;
-               while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
-                       iocmd.cmd = RESERVE;
-                       iocmd.data_dma = -1;
-                       iocmd.data = NULL;
-                       iocmd.size = 0;
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-                       else if (hd->pLocal == NULL)
-                               goto target_done;
-                       else {
-                               rc = hd->pLocal->completion;
-                               if (rc == MPT_SCANDV_GOOD) {
-                                       iocmd.flags |= MPT_ICFLAG_RESERVED;
-                               } else if (rc == MPT_SCANDV_SENSE) {
-                                       /* Wait if coming ready
-                                        */
-                                       u8 skey = hd->pLocal->sense[2] & 0x0F;
-                                       u8 asc = hd->pLocal->sense[12];
-                                       u8 ascq = hd->pLocal->sense[13];
-                                       ddvprintk((MYIOC_s_INFO_FMT
-                                               "DV: Reserve Failed: ", ioc->name));
-                                       ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-                                                       skey, asc, ascq));
-
-                                       if ((skey == NOT_READY) && (asc == 0x04)&&
-                                                                       (ascq == 0x01)) {
-                                               /* wait then repeat */
-                                               mdelay (2000);
-                                               notDone++;
-                                       } else {
-                                               ddvprintk((MYIOC_s_INFO_FMT
-                                                       "DV: Reserved Failed.", ioc->name));
-                                               goto target_done;
-                                       }
-                               } else {
-                                       ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
-                                                        ioc->name));
-                                       goto target_done;
-                               }
-                       }
-               }
-
-skip_Reserve:
-               mptscsih_fillbuf(pbuf1, sz, patt, 1);
-               iocmd.cmd = WRITE_BUFFER;
-               iocmd.data_dma = buf1_dma;
-               iocmd.data = pbuf1;
-               iocmd.size = sz;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else if (hd->pLocal == NULL)
-                       goto target_done;
-               else {
-                       rc = hd->pLocal->completion;
-                       if (rc == MPT_SCANDV_GOOD)
-                               ;               /* Issue read buffer */
-                       else if (rc == MPT_SCANDV_DID_RESET) {
-                               /* If using echo buffers, reset to data buffers.
-                                * Else do Fallback and restart
-                                * this test (re-issue reserve
-                                * because of bus reset).
-                                */
-                               if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
-                                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-                               } else {
-                                       dv.cmd = MPT_FALLBACK;
-                                       mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-                                       if (mpt_config(hd->ioc, &cfg) != 0)
-                                               goto target_done;
-
-                                       if ((!dv.now.width) && (!dv.now.offset))
-                                               goto target_done;
-                               }
-
-                               iocmd.flags |= MPT_ICFLAG_DID_RESET;
-                               patt = -1;
-                               continue;
-                       } else if (rc == MPT_SCANDV_SENSE) {
-                               /* Restart data test if UA, else quit.
-                                */
-                               u8 skey = hd->pLocal->sense[2] & 0x0F;
-                               ddvprintk((MYIOC_s_INFO_FMT
-                                       "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
-                                       hd->pLocal->sense[12], hd->pLocal->sense[13]));
-                               if (skey == UNIT_ATTENTION) {
-                                       patt = -1;
-                                       continue;
-                               } else if (skey == ILLEGAL_REQUEST) {
-                                       if (iocmd.flags & MPT_ICFLAG_ECHO) {
-                                               if (dataBufSize >= bufsize) {
-                                                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-                                                       patt = -1;
-                                                       continue;
-                                               }
-                                       }
-                                       goto target_done;
-                               }
-                               else
-                                       goto target_done;
-                       } else {
-                               /* fatal error */
-                               goto target_done;
-                       }
-               }
-
-               iocmd.cmd = READ_BUFFER;
-               iocmd.data_dma = buf2_dma;
-               iocmd.data = pbuf2;
-               iocmd.size = sz;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else if (hd->pLocal == NULL)
-                       goto target_done;
-               else {
-                       rc = hd->pLocal->completion;
-                       if (rc == MPT_SCANDV_GOOD) {
-                                /* If buffers compare,
-                                 * go to next pattern,
-                                 * else, do a fallback and restart
-                                 * data transfer test.
-                                 */
-                               if (memcmp (pbuf1, pbuf2, sz) == 0) {
-                                       ; /* goto next pattern */
-                               } else {
-                                       /* Miscompare with Echo buffer, go to data buffer,
-                                        * if that buffer exists.
-                                        * Miscompare with Data buffer, check first 4 bytes,
-                                        * some devices return capacity. Exit in this case.
-                                        */
-                                       if (iocmd.flags & MPT_ICFLAG_ECHO) {
-                                               if (dataBufSize >= bufsize)
-                                                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-                                               else
-                                                       goto target_done;
-                                       } else {
-                                               if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
-                                                       /* Argh. Device returning wrong data.
-                                                        * Quit DV for this device.
-                                                        */
-                                                       goto target_done;
-                                               }
-
-                                               /* Had an actual miscompare. Slow down.*/
-                                               dv.cmd = MPT_FALLBACK;
-                                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-                                               if (mpt_config(hd->ioc, &cfg) != 0)
-                                                       goto target_done;
-
-                                               if ((!dv.now.width) && (!dv.now.offset))
-                                                       goto target_done;
-                                       }
-
-                                       patt = -1;
-                                       continue;
-                               }
-                       } else if (rc == MPT_SCANDV_DID_RESET) {
-                               /* Do Fallback and restart
-                                * this test (re-issue reserve
-                                * because of bus reset).
-                                */
-                               dv.cmd = MPT_FALLBACK;
-                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-                               if (mpt_config(hd->ioc, &cfg) != 0)
-                                        goto target_done;
-
-                               if ((!dv.now.width) && (!dv.now.offset))
-                                       goto target_done;
-
-                               iocmd.flags |= MPT_ICFLAG_DID_RESET;
-                               patt = -1;
-                               continue;
-                       } else if (rc == MPT_SCANDV_SENSE) {
-                               /* Restart data test if UA, else quit.
-                                */
-                               u8 skey = hd->pLocal->sense[2] & 0x0F;
-                               ddvprintk((MYIOC_s_INFO_FMT
-                                       "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
-                                       hd->pLocal->sense[12], hd->pLocal->sense[13]));
-                               if (skey == UNIT_ATTENTION) {
-                                       patt = -1;
-                                       continue;
-                               }
-                               else
-                                       goto target_done;
-                       } else {
-                               /* fatal error */
-                               goto target_done;
-                       }
-               }
-
-       } /* --- end of patt loop ---- */
-
-target_done:
-       if (iocmd.flags & MPT_ICFLAG_RESERVED) {
-               iocmd.cmd = RELEASE;
-               iocmd.data_dma = -1;
-               iocmd.data = NULL;
-               iocmd.size = 0;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
-                                       ioc->name, id);
-               else if (hd->pLocal) {
-                       if (hd->pLocal->completion == MPT_SCANDV_GOOD)
-                               iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-               } else {
-                       printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
-                                               ioc->name, id);
-               }
-       }
-
-
-       /* Set if cfg1_dma_addr contents is valid
-        */
-       if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
-               /* If disk, not U320, disable QAS
-                */
-               if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
-                       hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
-                       ddvprintk((MYIOC_s_NOTE_FMT
-                           "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
-               }
-
-               dv.cmd = MPT_SAVE;
-               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-               /* Double writes to SDP1 can cause problems,
-                * skip save of the final negotiated settings to
-                * SCSI device page 1.
-                *
-               cfg.cfghdr.hdr = &header1;
-               cfg.physAddr = cfg1_dma_addr;
-               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-               cfg.dir = 1;
-               mpt_config(hd->ioc, &cfg);
-                */
-       }
-
-       /* If this is a RAID Passthrough, enable internal IOs
-        */
-       if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
-               if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
-                       ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
-       }
-
-       /* Done with the DV scan of the current target
-        */
-       if (pDvBuf)
-               pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
-
-       ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
-                       ioc->name, id));
-
-       return retcode;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_dv_parms - perform a variety of operations on the
- *     parameters used for negotiation.
- *     @hd: Pointer to a SCSI host.
- *     @dv: Pointer to a structure that contains the maximum and current
- *             negotiated parameters.
- */
-static void
-mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
-{
-       VirtTarget              *vtarget;
-       SCSIDevicePage0_t       *pPage0;
-       SCSIDevicePage1_t       *pPage1;
-       int                     val = 0, data, configuration;
-       u8                      width = 0;
-       u8                      offset = 0;
-       u8                      factor = 0;
-       u8                      negoFlags = 0;
-       u8                      cmd = dv->cmd;
-       u8                      id = dv->id;
-
-       switch (cmd) {
-       case MPT_GET_NVRAM_VALS:
-               ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
-                                                        hd->ioc->name));
-               /* Get the NVRAM values and save in tmax
-                * If not an LVD bus, the adapter minSyncFactor has been
-                * already throttled back.
-                */
-               negoFlags = hd->ioc->spi_data.noQas;
-               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];
-                               width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-                               if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
-                                       factor = MPT_ASYNC;
-                               else {
-                                       factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
-                                       if ((factor == 0) || (factor == MPT_ASYNC)){
-                                               factor = MPT_ASYNC;
-                                               offset = 0;
-                                       }
-                               }
-                       } else {
-                               width = MPT_NARROW;
-                               offset = 0;
-                               factor = MPT_ASYNC;
-                       }
-
-                       /* Set the negotiation flags */
-                       if (!width)
-                               negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-                       if (!offset)
-                               negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-               }
-
-               /* limit by adapter capabilities */
-               width = min(width, hd->ioc->spi_data.maxBusWidth);
-               offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
-               factor = max(factor, hd->ioc->spi_data.minSyncFactor);
-
-               /* Check Consistency */
-               if (offset && (factor < MPT_ULTRA2) && !width)
-                       factor = MPT_ULTRA2;
-
-               dv->max.width = width;
-               dv->max.offset = offset;
-               dv->max.factor = factor;
-               dv->max.flags = negoFlags;
-               ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
-                               id, width, factor, offset, negoFlags));
-               break;
-
-       case MPT_UPDATE_MAX:
-               ddvprintk((MYIOC_s_NOTE_FMT
-                       "Updating with SDP0 Data: ", hd->ioc->name));
-               /* Update tmax values with those from Device Page 0.*/
-               pPage0 = (SCSIDevicePage0_t *) pPage;
-               if (pPage0) {
-                       val = le32_to_cpu(pPage0->NegotiatedParameters);
-                       dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
-                       dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
-                       dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
-               }
-
-               dv->now.width = dv->max.width;
-               dv->now.offset = dv->max.offset;
-               dv->now.factor = dv->max.factor;
-               ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
-                               id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
-               break;
-
-       case MPT_SET_MAX:
-               ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
-                                                               hd->ioc->name));
-               /* Set current to the max values. Update the config page.*/
-               dv->now.width = dv->max.width;
-               dv->now.offset = dv->max.offset;
-               dv->now.factor = dv->max.factor;
-               dv->now.flags = dv->max.flags;
-
-               pPage1 = (SCSIDevicePage1_t *)pPage;
-               if (pPage1) {
-                       mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
-                               dv->now.offset, &val, &configuration, dv->now.flags);
-                       dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
-                               id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
-                       pPage1->RequestedParameters = cpu_to_le32(val);
-                       pPage1->Reserved = 0;
-                       pPage1->Configuration = cpu_to_le32(configuration);
-               }
-
-               ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
-                               id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
-               break;
-
-       case MPT_SET_MIN:
-               ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
-                                                               hd->ioc->name));
-               /* Set page to asynchronous and narrow
-                * Do not update now, breaks fallback routine. */
-               width = MPT_NARROW;
-               offset = 0;
-               factor = MPT_ASYNC;
-               negoFlags = dv->max.flags;
-
-               pPage1 = (SCSIDevicePage1_t *)pPage;
-               if (pPage1) {
-                       mptscsih_setDevicePage1Flags (width, factor,
-                               offset, &val, &configuration, negoFlags);
-                       dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
-                               id, width, factor, offset, negoFlags, val, configuration));
-                       pPage1->RequestedParameters = cpu_to_le32(val);
-                       pPage1->Reserved = 0;
-                       pPage1->Configuration = cpu_to_le32(configuration);
-               }
-               ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
-                               id, width, factor, offset, val, configuration, negoFlags));
-               break;
-
-       case MPT_FALLBACK:
-               ddvprintk((MYIOC_s_NOTE_FMT
-                       "Fallback: Start: offset %d, factor %x, width %d \n",
-                               hd->ioc->name, dv->now.offset,
-                               dv->now.factor, dv->now.width));
-               width = dv->now.width;
-               offset = dv->now.offset;
-               factor = dv->now.factor;
-               if ((offset) && (dv->max.width)) {
-                       if (factor < MPT_ULTRA160)
-                               factor = MPT_ULTRA160;
-                       else if (factor < MPT_ULTRA2) {
-                               factor = MPT_ULTRA2;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_ULTRA2) && width) {
-                               factor = MPT_ULTRA2;
-                               width = MPT_NARROW;
-                       } else if (factor < MPT_ULTRA) {
-                               factor = MPT_ULTRA;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_ULTRA) && width) {
-                               width = MPT_NARROW;
-                       } else if (factor < MPT_FAST) {
-                               factor = MPT_FAST;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_FAST) && width) {
-                               factor = MPT_FAST;
-                               width = MPT_NARROW;
-                       } else if (factor < MPT_SCSI) {
-                               factor = MPT_SCSI;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_SCSI) && width) {
-                               factor = MPT_SCSI;
-                               width = MPT_NARROW;
-                       } else {
-                               factor = MPT_ASYNC;
-                               offset = 0;
-                       }
-
-               } else if (offset) {
-                       width = MPT_NARROW;
-                       if (factor < MPT_ULTRA)
-                               factor = MPT_ULTRA;
-                       else if (factor < MPT_FAST)
-                               factor = MPT_FAST;
-                       else if (factor < MPT_SCSI)
-                               factor = MPT_SCSI;
-                       else {
-                               factor = MPT_ASYNC;
-                               offset = 0;
-                       }
-
-               } else {
-                       width = MPT_NARROW;
-                       factor = MPT_ASYNC;
-               }
-               dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
-               dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
-
-               dv->now.width = width;
-               dv->now.offset = offset;
-               dv->now.factor = factor;
-               dv->now.flags = dv->max.flags;
-
-               pPage1 = (SCSIDevicePage1_t *)pPage;
-               if (pPage1) {
-                       mptscsih_setDevicePage1Flags (width, factor, offset, &val,
-                                               &configuration, dv->now.flags);
-                       dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
-                            id, width, offset, factor, dv->now.flags, val, configuration));
-
-                       pPage1->RequestedParameters = cpu_to_le32(val);
-                       pPage1->Reserved = 0;
-                       pPage1->Configuration = cpu_to_le32(configuration);
-               }
-
-               ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
-                            id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
-               break;
-
-       case MPT_SAVE:
-               ddvprintk((MYIOC_s_NOTE_FMT
-                       "Saving to Target structure: ", hd->ioc->name));
-               ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
-                            id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
-
-               /* Save these values to target structures
-                * or overwrite nvram (phys disks only).
-                */
-
-               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
-                        */
-                       if (hd->ioc->spi_data.nvram) {
-                               data = hd->ioc->spi_data.nvram[id];
-
-                               if (dv->now.width)
-                                       data &= ~MPT_NVRAM_WIDE_DISABLE;
-                               else
-                                       data |= MPT_NVRAM_WIDE_DISABLE;
-
-                               if (!dv->now.offset)
-                                       factor = MPT_ASYNC;
-
-                               data &= ~MPT_NVRAM_SYNC_MASK;
-                               data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
-
-                               hd->ioc->spi_data.nvram[id] = data;
-                       }
-               }
-               break;
-       }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_fillbuf - fill a buffer with a special data pattern
- *             cleanup. For bus scan only.
- *
- *     @buffer: Pointer to data buffer to be filled.
- *     @size: Number of bytes to fill
- *     @index: Pattern index
- *     @width: bus width, 0 (8 bits) or 1 (16 bits)
- */
-static void
-mptscsih_fillbuf(char *buffer, int size, int index, int width)
-{
-       char *ptr = buffer;
-       int ii;
-       char byte;
-       short val;
-
-       switch (index) {
-       case 0:
-
-               if (width) {
-                       /* Pattern:  0000 FFFF 0000 FFFF
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x02)
-                                       *ptr = 0xFF;
-                               else
-                                       *ptr = 0x00;
-                       }
-               } else {
-                       /* Pattern:  00 FF 00 FF
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x01)
-                                       *ptr = 0xFF;
-                               else
-                                       *ptr = 0x00;
-                       }
-               }
-               break;
-
-       case 1:
-               if (width) {
-                       /* Pattern:  5555 AAAA 5555 AAAA 5555
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x02)
-                                       *ptr = 0xAA;
-                               else
-                                       *ptr = 0x55;
-                       }
-               } else {
-                       /* Pattern:  55 AA 55 AA 55
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x01)
-                                       *ptr = 0xAA;
-                               else
-                                       *ptr = 0x55;
-                       }
-               }
-               break;
-
-       case 2:
-               /* Pattern:  00 01 02 03 04 05
-                * ... FE FF 00 01..
-                */
-               for (ii=0; ii < size; ii++, ptr++)
-                       *ptr = (char) ii;
-               break;
-
-       case 3:
-               if (width) {
-                       /* Wide Pattern:  FFFE 0001 FFFD 0002
-                        * ...  4000 DFFF 8000 EFFF
-                        */
-                       byte = 0;
-                       for (ii=0; ii < size/2; ii++) {
-                               /* Create the base pattern
-                                */
-                               val = (1 << byte);
-                               /* every 64 (0x40) bytes flip the pattern
-                                * since we fill 2 bytes / iteration,
-                                * test for ii = 0x20
-                                */
-                               if (ii & 0x20)
-                                       val = ~(val);
-
-                               if (ii & 0x01) {
-                                       *ptr = (char)( (val & 0xFF00) >> 8);
-                                       ptr++;
-                                       *ptr = (char)(val & 0xFF);
-                                       byte++;
-                                       byte &= 0x0F;
-                               } else {
-                                       val = ~val;
-                                       *ptr = (char)( (val & 0xFF00) >> 8);
-                                       ptr++;
-                                       *ptr = (char)(val & 0xFF);
-                               }
-
-                               ptr++;
-                       }
-               } else {
-                       /* Narrow Pattern:  FE 01 FD 02 FB 04
-                        * .. 7F 80 01 FE 02 FD ...  80 7F
-                        */
-                       byte = 0;
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               /* Base pattern - first 32 bytes
-                                */
-                               if (ii & 0x01) {
-                                       *ptr = (1 << byte);
-                                       byte++;
-                                       byte &= 0x07;
-                               } else {
-                                       *ptr = (char) (~(1 << byte));
-                               }
-
-                               /* Flip the pattern every 32 bytes
-                                */
-                               if (ii & 0x20)
-                                       *ptr = ~(*ptr);
-                       }
-               }
-               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);
 EXPORT_SYMBOL(mptscsih_shutdown);
 #ifdef CONFIG_PM
index 44b248d51ea3174ff33d34024ac50b43e6bec672..14a5b6c2e2bdeb4ea60f8e992ec516641d167a29 100644 (file)
 
 #define MPT_SCSI_MAX_SECTORS    8192
 
-/* To disable domain validation, uncomment the
- * following line. No effect for FC devices.
- * For SCSI devices, driver will negotiate to
- * NVRAM settings (if available) or to maximum adapter
- * capabilities.
- */
-
-#define MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-
-
 /* SCSI driver setup structure. Settings can be overridden
  * by command line options.
  */
@@ -109,3 +99,5 @@ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
 extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
+extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
index f148dfa39117edb097bb5f481dcb9c8bad05bd60..09c745b19cc8443a3f86f93737d7f29d2bdba098 100644 (file)
 #include <linux/reboot.h>      /* notifier code */
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/raid_class.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
 
 /* Command line args */
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
-module_param(mpt_dv, int, 0);
-MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
-
-static int mpt_width = MPTSCSIH_MAX_WIDTH;
-module_param(mpt_width, int, 0);
-MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
-
-static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
-module_param(mpt_factor, ushort, 0);
-MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
-#endif
-
 static int mpt_saf_te = MPTSCSIH_SAF_TE;
 module_param(mpt_saf_te, int, 0);
 MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1  (default=MPTSCSIH_SAF_TE=0)");
@@ -98,10 +87,308 @@ static int mpt_pq_filter = 0;
 module_param(mpt_pq_filter, int, 0);
 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
 
+static void mptspi_write_offset(struct scsi_target *, int);
+static void mptspi_write_width(struct scsi_target *, int);
+static int mptspi_write_spi_device_pg1(struct scsi_target *,
+                                      struct _CONFIG_PAGE_SCSI_DEVICE_1 *);
+
+static struct scsi_transport_template *mptspi_transport_template = NULL;
+
 static int     mptspiDoneCtx = -1;
 static int     mptspiTaskCtx = -1;
 static int     mptspiInternalCtx = -1; /* Used only for internal commands */
 
+static int mptspi_target_alloc(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       int ret;
+
+       if (hd == NULL)
+               return -ENODEV;
+
+       ret = mptscsih_target_alloc(starget);
+       if (ret)
+               return ret;
+
+       /* if we're a device on virtual channel 1 and we're not part
+        * of an array, just return here (otherwise the setup below
+        * may actually affect a real physical device on channel 0 */
+       if (starget->channel == 1 &&
+           mptscsih_raid_id_to_num(hd, starget->id) < 0)
+               return 0;
+
+       if (hd->ioc->spi_data.nvram &&
+           hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
+               u32 nvram = hd->ioc->spi_data.nvram[starget->id];
+               spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+               spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+       } else {
+               spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
+               spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
+       }
+       spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
+
+       spi_offset(starget) = 0;
+       mptspi_write_width(starget, 0);
+
+       return 0;
+}
+
+static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
+                            struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
+{
+       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       struct _MPT_ADAPTER *ioc = hd->ioc;
+       struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
+       dma_addr_t pg0_dma;
+       int size;
+       struct _x_config_parms cfg;
+       struct _CONFIG_PAGE_HEADER hdr;
+       int err = -EBUSY;
+
+       /* No SPI parameters for RAID devices */
+       if (starget->channel == 0 &&
+           (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+               return -1;
+
+       size = ioc->spi_data.sdp0length * 4;
+       /*
+       if (ioc->spi_data.sdp0length & 1)
+               size += size + 4;
+       size += 2048;
+       */
+
+       pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
+       if (pg0 == NULL) {
+               starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
+               return -EINVAL;
+       }
+
+       memset(&hdr, 0, sizeof(hdr));
+
+       hdr.PageVersion = ioc->spi_data.sdp0version;
+       hdr.PageLength = ioc->spi_data.sdp0length;
+       hdr.PageNumber = 0;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+       memset(&cfg, 0, sizeof(cfg));
+
+       cfg.cfghdr.hdr = &hdr;
+       cfg.physAddr = pg0_dma;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+       cfg.dir = 0;
+       cfg.pageAddr = starget->id;
+
+       if (mpt_config(ioc, &cfg)) {
+               starget_printk(KERN_ERR, starget, "mpt_config failed\n");
+               goto out_free;
+       }
+       err = 0;
+       memcpy(pass_pg0, pg0, size);
+
+ out_free:
+       dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
+       return err;
+}
+
+static u32 mptspi_getRP(struct scsi_target *starget)
+{
+       u32 nego = 0;
+
+       nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
+       nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
+       nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
+       nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
+       nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
+       nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
+       nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
+       nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
+
+       nego |= (spi_period(starget) <<  MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
+       nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
+       nego |= spi_width(starget) ?  MPI_SCSIDEVPAGE1_RP_WIDE : 0;
+
+       return nego;
+}
+
+static void mptspi_read_parameters(struct scsi_target *starget)
+{
+       int nego;
+       struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
+
+       mptspi_read_spi_device_pg0(starget, &pg0);
+
+       nego = le32_to_cpu(pg0.NegotiatedParameters);
+
+       spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
+       spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
+       spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
+       spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
+       spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
+       spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
+       spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
+       spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
+       spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
+       spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
+       spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
+}
+
+static int
+mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
+{
+       MpiRaidActionRequest_t  *pReq;
+       MPT_FRAME_HDR           *mf;
+
+       /* Get and Populate a free Frame
+        */
+       if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
+               ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
+                                       hd->ioc->name));
+               return -EAGAIN;
+       }
+       pReq = (MpiRaidActionRequest_t *)mf;
+       if (quiesce)
+               pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
+       else
+               pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
+       pReq->Reserved1 = 0;
+       pReq->ChainOffset = 0;
+       pReq->Function = MPI_FUNCTION_RAID_ACTION;
+       pReq->VolumeID = disk;
+       pReq->VolumeBus = 0;
+       pReq->PhysDiskNum = 0;
+       pReq->MsgFlags = 0;
+       pReq->Reserved2 = 0;
+       pReq->ActionDataWord = 0; /* Reserved for this action */
+
+       mpt_add_sge((char *)&pReq->ActionDataSGE,
+               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
+
+       ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
+                       hd->ioc->name, action, io->id));
+
+       hd->pLocal = NULL;
+       hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
+       hd->scandv_wait_done = 0;
+
+       /* Save cmd pointer, for resource free if timeout or
+        * FW reload occurs
+        */
+       hd->cmdPtr = mf;
+
+       add_timer(&hd->timer);
+       mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
+
+       if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
+               return -1;
+
+       return 0;
+}
+
+static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
+                            struct scsi_device *sdev)
+{
+       VirtTarget *vtarget = scsi_target(sdev)->hostdata;
+
+       /* no DV on RAID devices */
+       if (sdev->channel == 0 &&
+           (hd->ioc->raid_data.isRaid & (1 << sdev->id)))
+               return;
+
+       /* If this is a piece of a RAID, then quiesce first */
+       if (sdev->channel == 1 &&
+           mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) {
+               starget_printk(KERN_ERR, scsi_target(sdev),
+                              "Integrated RAID quiesce failed\n");
+               return;
+       }
+
+       spi_dv_device(sdev);
+
+       if (sdev->channel == 1 &&
+           mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0)
+               starget_printk(KERN_ERR, scsi_target(sdev),
+                              "Integrated RAID resume failed\n");
+
+       mptspi_read_parameters(sdev->sdev_target);
+       spi_display_xfer_agreement(sdev->sdev_target);
+       mptspi_read_parameters(sdev->sdev_target);
+}
+
+static int mptspi_slave_alloc(struct scsi_device *sdev)
+{
+       int ret;
+       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+       /* gcc doesn't see that all uses of this variable occur within
+        * the if() statements, so stop it from whining */
+       int physdisknum = 0;
+
+       if (sdev->channel == 1) {
+               physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
+
+               if (physdisknum < 0)
+                       return physdisknum;
+       }
+
+       ret = mptscsih_slave_alloc(sdev);
+
+       if (ret)
+               return ret;
+
+       if (sdev->channel == 1) {
+               VirtDevice *vdev = sdev->hostdata;
+               sdev->no_uld_attach = 1;
+               vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+               /* The real channel for this device is zero */
+               vdev->vtarget->bus_id = 0;
+               /* The actual physdisknum (for RAID passthrough) */
+               vdev->vtarget->target_id = physdisknum;
+       }
+
+       return 0;
+}
+
+static int mptspi_slave_configure(struct scsi_device *sdev)
+{
+       int ret = mptscsih_slave_configure(sdev);
+       struct _MPT_SCSI_HOST *hd =
+               (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+
+       if (ret)
+               return ret;
+
+       if ((sdev->channel == 1 ||
+            !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
+           !spi_initial_dv(sdev->sdev_target))
+               mptspi_dv_device(hd, sdev);
+
+       return 0;
+}
+
+static void mptspi_slave_destroy(struct scsi_device *sdev)
+{
+       struct scsi_target *starget = scsi_target(sdev);
+       VirtTarget *vtarget = starget->hostdata;
+       VirtDevice *vdevice = sdev->hostdata;
+
+       /* Will this be the last lun on a non-raid device? */
+       if (vtarget->num_luns == 1 && vdevice->configured_lun) {
+               struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+
+               /* Async Narrow */
+               pg1.RequestedParameters = 0;
+               pg1.Reserved = 0;
+               pg1.Configuration = 0;
+
+               mptspi_write_spi_device_pg1(starget, &pg1);
+       }
+
+       mptscsih_slave_destroy(sdev);
+}
+
 static struct scsi_host_template mptspi_driver_template = {
        .module                         = THIS_MODULE,
        .proc_name                      = "mptspi",
@@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = {
        .name                           = "MPT SPI Host",
        .info                           = mptscsih_info,
        .queuecommand                   = mptscsih_qcmd,
-       .target_alloc                   = mptscsih_target_alloc,
-       .slave_alloc                    = mptscsih_slave_alloc,
-       .slave_configure                = mptscsih_slave_configure,
+       .target_alloc                   = mptspi_target_alloc,
+       .slave_alloc                    = mptspi_slave_alloc,
+       .slave_configure                = mptspi_slave_configure,
        .target_destroy                 = mptscsih_target_destroy,
-       .slave_destroy                  = mptscsih_slave_destroy,
+       .slave_destroy                  = mptspi_slave_destroy,
        .change_queue_depth             = mptscsih_change_queue_depth,
        .eh_abort_handler               = mptscsih_abort,
        .eh_device_reset_handler        = mptscsih_dev_reset,
@@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = {
        .use_clustering                 = ENABLE_CLUSTERING,
 };
 
+static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
+                              struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
+{
+       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       struct _MPT_ADAPTER *ioc = hd->ioc;
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
+       dma_addr_t pg1_dma;
+       int size;
+       struct _x_config_parms cfg;
+       struct _CONFIG_PAGE_HEADER hdr;
+       int err = -EBUSY;
+
+       /* don't allow updating nego parameters on RAID devices */
+       if (starget->channel == 0 &&
+           (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+               return -1;
+
+       size = ioc->spi_data.sdp1length * 4;
+
+       pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
+       if (pg1 == NULL) {
+               starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
+               return -EINVAL;
+       }
+
+       memset(&hdr, 0, sizeof(hdr));
+
+       hdr.PageVersion = ioc->spi_data.sdp1version;
+       hdr.PageLength = ioc->spi_data.sdp1length;
+       hdr.PageNumber = 1;
+       hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+       memset(&cfg, 0, sizeof(cfg));
+
+       cfg.cfghdr.hdr = &hdr;
+       cfg.physAddr = pg1_dma;
+       cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+       cfg.dir = 1;
+       cfg.pageAddr = starget->id;
+
+       memcpy(pg1, pass_pg1, size);
+
+       pg1->Header.PageVersion = hdr.PageVersion;
+       pg1->Header.PageLength = hdr.PageLength;
+       pg1->Header.PageNumber = hdr.PageNumber;
+       pg1->Header.PageType = hdr.PageType;
+
+       if (mpt_config(ioc, &cfg)) {
+               starget_printk(KERN_ERR, starget, "mpt_config failed\n");
+               goto out_free;
+       }
+       err = 0;
+
+ out_free:
+       dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
+       return err;
+}
+
+static void mptspi_write_offset(struct scsi_target *starget, int offset)
+{
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       u32 nego;
+
+       if (offset < 0)
+               offset = 0;
+
+       if (offset > 255)
+               offset = 255;
+
+       if (spi_offset(starget) == -1)
+               mptspi_read_parameters(starget);
+
+       spi_offset(starget) = offset;
+
+       nego = mptspi_getRP(starget);
+
+       pg1.RequestedParameters = cpu_to_le32(nego);
+       pg1.Reserved = 0;
+       pg1.Configuration = 0;
+
+       mptspi_write_spi_device_pg1(starget, &pg1);
+}
+
+static void mptspi_write_period(struct scsi_target *starget, int period)
+{
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       u32 nego;
+
+       if (period < 8)
+               period = 8;
+
+       if (period > 255)
+               period = 255;
+
+       if (spi_period(starget) == -1)
+               mptspi_read_parameters(starget);
+
+       if (period == 8) {
+               spi_iu(starget) = 1;
+               spi_dt(starget) = 1;
+       } else if (period == 9) {
+               spi_dt(starget) = 1;
+       }
+
+       spi_period(starget) = period;
+
+       nego = mptspi_getRP(starget);
+
+       pg1.RequestedParameters = cpu_to_le32(nego);
+       pg1.Reserved = 0;
+       pg1.Configuration = 0;
+
+       mptspi_write_spi_device_pg1(starget, &pg1);
+}
+
+static void mptspi_write_dt(struct scsi_target *starget, int dt)
+{
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       u32 nego;
+
+       if (spi_period(starget) == -1)
+               mptspi_read_parameters(starget);
+
+       if (!dt && spi_period(starget) < 10)
+               spi_period(starget) = 10;
+
+       spi_dt(starget) = dt;
+
+       nego = mptspi_getRP(starget);
+
+
+       pg1.RequestedParameters = cpu_to_le32(nego);
+       pg1.Reserved = 0;
+       pg1.Configuration = 0;
+
+       mptspi_write_spi_device_pg1(starget, &pg1);
+}
+
+static void mptspi_write_iu(struct scsi_target *starget, int iu)
+{
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       u32 nego;
+
+       if (spi_period(starget) == -1)
+               mptspi_read_parameters(starget);
+
+       if (!iu && spi_period(starget) < 9)
+               spi_period(starget) = 9;
+
+       spi_iu(starget) = iu;
+
+       nego = mptspi_getRP(starget);
+
+       pg1.RequestedParameters = cpu_to_le32(nego);
+       pg1.Reserved = 0;
+       pg1.Configuration = 0;
+
+       mptspi_write_spi_device_pg1(starget, &pg1);
+}
+
+#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm)                             \
+static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
+{                                                                      \
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;                          \
+       u32 nego;                                                       \
+                                                                       \
+       spi_##parm(starget) = parm;                                     \
+                                                                       \
+       nego = mptspi_getRP(starget);                                   \
+                                                                       \
+       pg1.RequestedParameters = cpu_to_le32(nego);                    \
+       pg1.Reserved = 0;                                               \
+       pg1.Configuration = 0;                                          \
+                                                                       \
+       mptspi_write_spi_device_pg1(starget, &pg1);                             \
+}
+
+MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
+MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
+MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
+MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
+MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
+
+static void mptspi_write_qas(struct scsi_target *starget, int qas)
+{
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       VirtTarget *vtarget = starget->hostdata;
+       u32 nego;
+
+       if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
+           hd->ioc->spi_data.noQas)
+               spi_qas(starget) = 0;
+       else
+               spi_qas(starget) = qas;
+
+       nego = mptspi_getRP(starget);
+
+       pg1.RequestedParameters = cpu_to_le32(nego);
+       pg1.Reserved = 0;
+       pg1.Configuration = 0;
+
+       mptspi_write_spi_device_pg1(starget, &pg1);
+}
+
+static void mptspi_write_width(struct scsi_target *starget, int width)
+{
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       u32 nego;
+
+       if (!width) {
+               spi_dt(starget) = 0;
+               if (spi_period(starget) < 10)
+                       spi_period(starget) = 10;
+       }
+
+       spi_width(starget) = width;
+
+       nego = mptspi_getRP(starget);
+
+       pg1.RequestedParameters = cpu_to_le32(nego);
+       pg1.Reserved = 0;
+       pg1.Configuration = 0;
+
+       mptspi_write_spi_device_pg1(starget, &pg1);
+}
+
+struct work_queue_wrapper {
+       struct work_struct      work;
+       struct _MPT_SCSI_HOST   *hd;
+       int                     disk;
+};
+
+static void mpt_work_wrapper(void *data)
+{
+       struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+       struct _MPT_SCSI_HOST *hd = wqw->hd;
+       struct Scsi_Host *shost = hd->ioc->sh;
+       struct scsi_device *sdev;
+       int disk = wqw->disk;
+       struct _CONFIG_PAGE_IOC_3 *pg3;
+
+       kfree(wqw);
+
+       mpt_findImVolumes(hd->ioc);
+       pg3 = hd->ioc->raid_data.pIocPg3;
+       if (!pg3)
+               return;
+
+       shost_for_each_device(sdev,shost) {
+               struct scsi_target *starget = scsi_target(sdev);
+               VirtTarget *vtarget = starget->hostdata;
+
+               /* only want to search RAID components */
+               if (sdev->channel != 1)
+                       continue;
+
+               /* The target_id is the raid PhysDiskNum, even if
+                * starget->id is the actual target address */
+               if(vtarget->target_id != disk)
+                       continue;
+
+               starget_printk(KERN_INFO, vtarget->starget,
+                              "Integrated RAID requests DV of new device\n");
+               mptspi_dv_device(hd, sdev);
+       }
+       shost_printk(KERN_INFO, shost,
+                    "Integrated RAID detects new device %d\n", disk);
+       scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
+}
+
+
+static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
+{
+       struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+
+       if (!wqw) {
+               shost_printk(KERN_ERR, hd->ioc->sh,
+                            "Failed to act on RAID event for physical disk %d\n",
+                          disk);
+               return;
+       }
+       INIT_WORK(&wqw->work, mpt_work_wrapper, wqw);
+       wqw->hd = hd;
+       wqw->disk = disk;
+
+       schedule_work(&wqw->work);
+}
+
+static int
+mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+       u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+
+       if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {
+               int reason
+                       = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
+
+               if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+                       int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
+                       mpt_dv_raid(hd, disk);
+               }
+       }
+       return mptscsih_event_process(ioc, pEvReply);
+}
+
+static int
+mptspi_deny_binding(struct scsi_target *starget)
+{
+       struct _MPT_SCSI_HOST *hd =
+               (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
+       return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
+               starget->channel == 0) ? 1 : 0;
+}
+
+static struct spi_function_template mptspi_transport_functions = {
+       .get_offset     = mptspi_read_parameters,
+       .set_offset     = mptspi_write_offset,
+       .show_offset    = 1,
+       .get_period     = mptspi_read_parameters,
+       .set_period     = mptspi_write_period,
+       .show_period    = 1,
+       .get_width      = mptspi_read_parameters,
+       .set_width      = mptspi_write_width,
+       .show_width     = 1,
+       .get_iu         = mptspi_read_parameters,
+       .set_iu         = mptspi_write_iu,
+       .show_iu        = 1,
+       .get_dt         = mptspi_read_parameters,
+       .set_dt         = mptspi_write_dt,
+       .show_dt        = 1,
+       .get_qas        = mptspi_read_parameters,
+       .set_qas        = mptspi_write_qas,
+       .show_qas       = 1,
+       .get_wr_flow    = mptspi_read_parameters,
+       .set_wr_flow    = mptspi_write_wr_flow,
+       .show_wr_flow   = 1,
+       .get_rd_strm    = mptspi_read_parameters,
+       .set_rd_strm    = mptspi_write_rd_strm,
+       .show_rd_strm   = 1,
+       .get_rti        = mptspi_read_parameters,
+       .set_rti        = mptspi_write_rti,
+       .show_rti       = 1,
+       .get_pcomp_en   = mptspi_read_parameters,
+       .set_pcomp_en   = mptspi_write_pcomp_en,
+       .show_pcomp_en  = 1,
+       .get_hold_mcs   = mptspi_read_parameters,
+       .set_hold_mcs   = mptspi_write_hold_mcs,
+       .show_hold_mcs  = 1,
+       .deny_binding   = mptspi_deny_binding,
+};
 
 /****************************************************************************
  * Supported hardware
@@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        sh->max_id = MPT_MAX_SCSI_DEVICES;
 
        sh->max_lun = MPT_LAST_LUN + 1;
-       sh->max_channel = 0;
+       /*
+        * If RAID Firmware Detected, setup virtual channel
+        */
+       if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+           > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+               sh->max_channel = 1;
+       else
+               sh->max_channel = 0;
        sh->this_id = ioc->pfacts[0].PortSCSIID;
 
        /* Required entry.
@@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
         * indicates a device exists.
         * max_id = 1 + maximum id (hosts.h)
         */
-       hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+       hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
+                             sizeof(void *), GFP_ATOMIC);
        if (!hd->Targets) {
                error = -ENOMEM;
                goto out_mptspi_probe;
@@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->spi_data.Saf_Te = mpt_saf_te;
        hd->mpt_pq_filter = mpt_pq_filter;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       if (ioc->spi_data.maxBusWidth > mpt_width)
-               ioc->spi_data.maxBusWidth = mpt_width;
-       if (ioc->spi_data.minSyncFactor < mpt_factor)
-               ioc->spi_data.minSyncFactor = mpt_factor;
-       if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
-               ioc->spi_data.maxSyncOffset = 0;
-       }
-       ioc->spi_data.mpt_dv = mpt_dv;
-       hd->negoNvram = 0;
-
-       ddvprintk((MYIOC_s_INFO_FMT
-               "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
-               ioc->name,
-               mpt_dv,
-               mpt_width,
-               mpt_factor,
-               mpt_saf_te,
-               mpt_pq_filter));
-#else
        hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
        ddvprintk((MYIOC_s_INFO_FMT
                "saf_te %x mpt_pq_filter %x\n",
                ioc->name,
                mpt_saf_te,
                mpt_pq_filter));
-#endif
-
-       ioc->spi_data.forceDv = 0;
        ioc->spi_data.noQas = 0;
 
-       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
-               ioc->spi_data.dvStatus[ii] =
-                 MPT_SCSICFG_NEGOTIATE;
-
-       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
-               ioc->spi_data.dvStatus[ii] |=
-                 MPT_SCSICFG_DV_NOT_DONE;
-
        init_waitqueue_head(&hd->scandv_waitq);
        hd->scandv_wait_done = 0;
        hd->last_queue_full = 0;
 
+       /* Some versions of the firmware don't support page 0; without
+        * that we can't get the parameters */
+       if (hd->ioc->spi_data.sdp0length != 0)
+               sh->transportt = mptspi_transport_template;
+
        error = scsi_add_host (sh, &ioc->pcidev->dev);
        if(error) {
                dprintk((KERN_ERR MYNAM
@@ -423,15 +1046,18 @@ static struct pci_driver mptspi_driver = {
 static int __init
 mptspi_init(void)
 {
-
        show_mptmod_ver(my_NAME, my_VERSION);
 
+       mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
+       if (!mptspi_transport_template)
+               return -ENODEV;
+
        mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
        mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
        mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
 
-       if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
-               devtprintk((KERN_INFO MYNAM
+       if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
+               devtverboseprintk((KERN_INFO MYNAM
                  ": Registered for IOC event notifications\n"));
        }
 
@@ -465,6 +1091,7 @@ mptspi_exit(void)
        mpt_deregister(mptspiInternalCtx);
        mpt_deregister(mptspiTaskCtx);
        mpt_deregister(mptspiDoneCtx);
+       spi_release_transport(mptspi_transport_template);
 }
 
 module_init(mptspi_init);
index 9bb9859f6dfead429b0bec069c5c150d15e5056e..5ea133c59afb3e7ab2788c2d68c1512723ddf5c6 100644 (file)
@@ -57,6 +57,13 @@ struct i2o_exec_wait {
        struct list_head list;  /* node in global wait list */
 };
 
+/* Work struct needed to handle LCT NOTIFY replies */
+struct i2o_exec_lct_notify_work {
+       struct work_struct work;        /* work struct */
+       struct i2o_controller *c;       /* controller on which the LCT NOTIFY
+                                          was received */
+};
+
 /* Exec OSM class handling definition */
 static struct i2o_class_id i2o_exec_class_id[] = {
        {I2O_CLASS_EXECUTIVE},
@@ -355,9 +362,12 @@ static int i2o_exec_remove(struct device *dev)
  *     new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
  *     again, otherwise send LCT NOTIFY to get informed on next LCT change.
  */
-static void i2o_exec_lct_modified(struct i2o_controller *c)
+static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work)
 {
        u32 change_ind = 0;
+       struct i2o_controller *c = work->c;
+
+       kfree(work);
 
        if (i2o_device_parse_lct(c) != -EAGAIN)
                change_ind = c->lct->change_ind + 1;
@@ -410,7 +420,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
                return i2o_msg_post_wait_complete(c, m, msg, context);
 
        if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
-               struct work_struct *work;
+               struct i2o_exec_lct_notify_work *work;
 
                pr_debug("%s: LCT notify received\n", c->name);
 
@@ -418,8 +428,11 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
                if (!work)
                        return -ENOMEM;
 
-               INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c);
-               queue_work(i2o_exec_driver.event_queue, work);
+               work->c = c;
+
+               INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified,
+                         work);
+               queue_work(i2o_exec_driver.event_queue, &work->work);
                return 1;
        }
 
index d9152d02088c81bb4c498360d5ed7232f10718dd..0ab26d01877b1c985e9119006679bd7f21194054 100644 (file)
@@