mpt2sas, mpt3sas: Remove SCSI_MPTXSAS_LOGGING entry from Kconfig
[linux-2.6-block.git] / drivers / scsi / mpt3sas / mpt3sas_scsih.c
index 5a97e3286719d8150a6dbf24bcd062f2effa4373..a638920dbfb33f24e4ea3d2a51640f285f7a1120 100644 (file)
 
 #include "mpt3sas_base.h"
 
-MODULE_AUTHOR(MPT3SAS_AUTHOR);
-MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
-
 #define RAID_CHANNEL 1
 /* forward proto's */
 static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
@@ -75,11 +70,10 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 
 static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
 
-static void _scsih_scan_start(struct Scsi_Host *shost);
-static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
 
 /* global parameters */
 LIST_HEAD(mpt3sas_ioc_list);
+char    driver_name[MPT_NAME_LENGTH];
 
 /* local parameters */
 static u8 scsi_io_cb_idx = -1;
@@ -143,8 +137,7 @@ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
 
 
 /* raid transport support */
-
-static struct raid_template *mpt3sas_raid_template;
+struct raid_template *mpt3sas_raid_template;
 
 
 /**
@@ -194,9 +187,6 @@ struct fw_event_work {
        char                    event_data[0] __aligned(4);
 };
 
-/* raid transport support */
-static struct raid_template *mpt3sas_raid_template;
-
 /**
  * struct _scsi_io_transfer - scsi io transfer
  * @handle: sas device handle (assigned by firmware)
@@ -245,28 +235,6 @@ struct _scsi_io_transfer {
        u32     transfer_length;
 };
 
-/*
- * The pci device ids are defined in mpi/mpi2_cnfg.h.
- */
-static const struct pci_device_id scsih_pci_table[] = {
-       /* Fury ~ 3004 and 3008 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Invader ~ 3108 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
-               PCI_ANY_ID, PCI_ANY_ID },
-       {0}     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, scsih_pci_table);
-
 /**
  * _scsih_set_debug_level - global setting of ioc->logging_level.
  *
@@ -585,6 +553,22 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
 
        if (!sas_device)
                return;
+       pr_info(MPT3SAS_FMT
+           "removing handle(0x%04x), sas_addr(0x%016llx)\n",
+           ioc->name, sas_device->handle,
+           (unsigned long long) sas_device->sas_address);
+
+       if (sas_device->enclosure_handle != 0)
+               pr_info(MPT3SAS_FMT
+                  "removing enclosure logical id(0x%016llx), slot(%d)\n",
+                  ioc->name, (unsigned long long)
+                  sas_device->enclosure_logical_id, sas_device->slot);
+
+       if (sas_device->connector_name[0] != '\0')
+               pr_info(MPT3SAS_FMT
+                  "removing enclosure level(0x%04x), connector name( %s)\n",
+                  ioc->name, sas_device->enclosure_level,
+                  sas_device->connector_name);
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        list_del(&sas_device->list);
@@ -663,6 +647,18 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
                ioc->name, __func__, sas_device->handle,
                (unsigned long long)sas_device->sas_address));
 
+       if (sas_device->enclosure_handle != 0)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: enclosure logical id(0x%016llx), slot( %d)\n",
+                   ioc->name, __func__, (unsigned long long)
+                   sas_device->enclosure_logical_id, sas_device->slot));
+
+       if (sas_device->connector_name[0] != '\0')
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: enclosure level(0x%04x), connector name( %s)\n",
+                   ioc->name, __func__,
+                   sas_device->enclosure_level, sas_device->connector_name));
+
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        list_add_tail(&sas_device->list, &ioc->sas_device_list);
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -704,6 +700,18 @@ _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
                __func__, sas_device->handle,
                (unsigned long long)sas_device->sas_address));
 
+       if (sas_device->enclosure_handle != 0)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: enclosure logical id(0x%016llx), slot( %d)\n",
+                   ioc->name, __func__, (unsigned long long)
+                   sas_device->enclosure_logical_id, sas_device->slot));
+
+       if (sas_device->connector_name[0] != '\0')
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: enclosure level(0x%04x), connector name( %s)\n",
+                   ioc->name, __func__, sas_device->enclosure_level,
+                   sas_device->connector_name));
+
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
        _scsih_determine_boot_device(ioc, sas_device, 0);
@@ -1055,14 +1063,14 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
 }
 
 /**
- * _scsih_change_queue_depth - setting device queue depth
+ * scsih_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
  *
  * Returns queue depth.
  */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+int
+scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        struct Scsi_Host *shost = sdev->host;
        int max_depth;
@@ -1101,14 +1109,14 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 }
 
 /**
- * _scsih_target_alloc - target add routine
+ * scsih_target_alloc - target add routine
  * @starget: scsi target struct
  *
  * Returns 0 if ok. Any other return is assumed to be an error and
  * the device is ignored.
  */
-static int
-_scsih_target_alloc(struct scsi_target *starget)
+int
+scsih_target_alloc(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1166,13 +1174,13 @@ _scsih_target_alloc(struct scsi_target *starget)
 }
 
 /**
- * _scsih_target_destroy - target destroy routine
+ * scsih_target_destroy - target destroy routine
  * @starget: scsi target struct
  *
  * Returns nothing.
  */
-static void
-_scsih_target_destroy(struct scsi_target *starget)
+void
+scsih_target_destroy(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1215,14 +1223,14 @@ _scsih_target_destroy(struct scsi_target *starget)
 }
 
 /**
- * _scsih_slave_alloc - device add routine
+ * scsih_slave_alloc - device add routine
  * @sdev: scsi device struct
  *
  * Returns 0 if ok. Any other return is assumed to be an error and
  * the device is ignored.
  */
-static int
-_scsih_slave_alloc(struct scsi_device *sdev)
+int
+scsih_slave_alloc(struct scsi_device *sdev)
 {
        struct Scsi_Host *shost;
        struct MPT3SAS_ADAPTER *ioc;
@@ -1277,13 +1285,13 @@ _scsih_slave_alloc(struct scsi_device *sdev)
 }
 
 /**
- * _scsih_slave_destroy - device destroy routine
+ * scsih_slave_destroy - device destroy routine
  * @sdev: scsi device struct
  *
  * Returns nothing.
  */
-static void
-_scsih_slave_destroy(struct scsi_device *sdev)
+void
+scsih_slave_destroy(struct scsi_device *sdev)
 {
        struct MPT3SAS_TARGET *sas_target_priv_data;
        struct scsi_target *starget;
@@ -1369,11 +1377,11 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
  */
 
 /**
- * _scsih_is_raid - return boolean indicating device is raid volume
+ * scsih_is_raid - return boolean indicating device is raid volume
  * @dev the device struct object
  */
-static int
-_scsih_is_raid(struct device *dev)
+int
+scsih_is_raid(struct device *dev)
 {
        struct scsi_device *sdev = to_scsi_device(dev);
 
@@ -1381,11 +1389,11 @@ _scsih_is_raid(struct device *dev)
 }
 
 /**
- * _scsih_get_resync - get raid volume resync percent complete
+ * scsih_get_resync - get raid volume resync percent complete
  * @dev the device struct object
  */
-static void
-_scsih_get_resync(struct device *dev)
+void
+scsih_get_resync(struct device *dev)
 {
        struct scsi_device *sdev = to_scsi_device(dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
@@ -1430,11 +1438,11 @@ _scsih_get_resync(struct device *dev)
 }
 
 /**
- * _scsih_get_state - get raid volume level
+ * scsih_get_state - get raid volume level
  * @dev the device struct object
  */
-static void
-_scsih_get_state(struct device *dev)
+void
+scsih_get_state(struct device *dev)
 {
        struct scsi_device *sdev = to_scsi_device(dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
@@ -1612,14 +1620,14 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
 }
 
 /**
- * _scsih_slave_configure - device configure routine.
+ * scsih_slave_configure - device configure routine.
  * @sdev: scsi device struct
  *
  * Returns 0 if ok. Any other return is assumed to be an error and
  * the device is ignored.
  */
-static int
-_scsih_slave_configure(struct scsi_device *sdev)
+int
+scsih_slave_configure(struct scsi_device *sdev)
 {
        struct Scsi_Host *shost = sdev->host;
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1717,7 +1725,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                         raid_device->num_pds, ds);
 
 
-               _scsih_change_queue_depth(sdev, qdepth);
+               scsih_change_queue_depth(sdev, qdepth);
 
 /* raid transport support */
                _scsih_set_level(sdev, raid_device->volume_type);
@@ -1772,10 +1780,16 @@ _scsih_slave_configure(struct scsi_device *sdev)
            "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
            ds, handle, (unsigned long long)sas_device->sas_address,
            sas_device->phy, (unsigned long long)sas_device->device_name);
-       sdev_printk(KERN_INFO, sdev,
-               "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
-               ds, (unsigned long long)
-           sas_device->enclosure_logical_id, sas_device->slot);
+       if (sas_device->enclosure_handle != 0)
+               sdev_printk(KERN_INFO, sdev,
+                    "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
+                    ds, (unsigned long long)
+                    sas_device->enclosure_logical_id, sas_device->slot);
+       if (sas_device->connector_name[0] != '\0')
+               sdev_printk(KERN_INFO, sdev,
+                    "%s: enclosure level(0x%04x), connector name( %s)\n",
+                    ds, sas_device->enclosure_level,
+                    sas_device->connector_name);
 
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
@@ -1783,7 +1797,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                _scsih_display_sata_capabilities(ioc, handle, sdev);
 
 
-       _scsih_change_queue_depth(sdev, qdepth);
+       scsih_change_queue_depth(sdev, qdepth);
 
        if (ssp_target) {
                sas_read_port_mode_page(sdev);
@@ -1794,7 +1808,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
 }
 
 /**
- * _scsih_bios_param - fetch head, sector, cylinder info for a disk
+ * scsih_bios_param - fetch head, sector, cylinder info for a disk
  * @sdev: scsi device struct
  * @bdev: pointer to block device context
  * @capacity: device size (in 512 byte sectors)
@@ -1805,8 +1819,8 @@ _scsih_slave_configure(struct scsi_device *sdev)
  *
  * Return nothing.
  */
-static int
-_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+int
+scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
        sector_t capacity, int params[])
 {
        int             heads;
@@ -2189,23 +2203,30 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
                            sas_device->handle,
                            (unsigned long long)sas_device->sas_address,
                            sas_device->phy);
-                       starget_printk(KERN_INFO, starget,
-                           "enclosure_logical_id(0x%016llx), slot(%d)\n",
-                          (unsigned long long)sas_device->enclosure_logical_id,
-                           sas_device->slot);
+                       if (sas_device->enclosure_handle != 0)
+                               starget_printk(KERN_INFO, starget,
+                                "enclosure_logical_id(0x%016llx), slot(%d)\n",
+                                (unsigned long long)
+                                sas_device->enclosure_logical_id,
+                                sas_device->slot);
+                       if (sas_device->connector_name)
+                               starget_printk(KERN_INFO, starget,
+                               "enclosure level(0x%04x),connector name(%s)\n",
+                                sas_device->enclosure_level,
+                                sas_device->connector_name);
                }
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
 }
 
 /**
- * _scsih_abort - eh threads main abort routine
+ * scsih_abort - eh threads main abort routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_abort(struct scsi_cmnd *scmd)
+int
+scsih_abort(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -2258,13 +2279,13 @@ _scsih_abort(struct scsi_cmnd *scmd)
 }
 
 /**
- * _scsih_dev_reset - eh threads main device reset routine
+ * scsih_dev_reset - eh threads main device reset routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_dev_reset(struct scsi_cmnd *scmd)
+int
+scsih_dev_reset(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -2317,13 +2338,13 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
 }
 
 /**
- * _scsih_target_reset - eh threads main target reset routine
+ * scsih_target_reset - eh threads main target reset routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_target_reset(struct scsi_cmnd *scmd)
+int
+scsih_target_reset(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -2378,13 +2399,13 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
 
 
 /**
- * _scsih_host_reset - eh threads main host reset routine
+ * scsih_host_reset - eh threads main host reset routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_host_reset(struct scsi_cmnd *scmd)
+int
+scsih_host_reset(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        int r, retval;
@@ -2551,6 +2572,75 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
        }
 }
 
+/**
+ * _scsih_internal_device_block - block the sdev device
+ * @sdev: per device object
+ * @sas_device_priv_data : per device driver private data
+ *
+ * make sure device is blocked without error, if not
+ * print an error
+ */
+static void
+_scsih_internal_device_block(struct scsi_device *sdev,
+                       struct MPT3SAS_DEVICE *sas_device_priv_data)
+{
+       int r = 0;
+
+       sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n",
+           sas_device_priv_data->sas_target->handle);
+       sas_device_priv_data->block = 1;
+
+       r = scsi_internal_device_block(sdev);
+       if (r == -EINVAL)
+               sdev_printk(KERN_WARNING, sdev,
+                   "device_block failed with return(%d) for handle(0x%04x)\n",
+                   sas_device_priv_data->sas_target->handle, r);
+}
+
+/**
+ * _scsih_internal_device_unblock - unblock the sdev device
+ * @sdev: per device object
+ * @sas_device_priv_data : per device driver private data
+ * make sure device is unblocked without error, if not retry
+ * by blocking and then unblocking
+ */
+
+static void
+_scsih_internal_device_unblock(struct scsi_device *sdev,
+                       struct MPT3SAS_DEVICE *sas_device_priv_data)
+{
+       int r = 0;
+
+       sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, "
+           "handle(0x%04x)\n", sas_device_priv_data->sas_target->handle);
+       sas_device_priv_data->block = 0;
+       r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+       if (r == -EINVAL) {
+               /* The device has been set to SDEV_RUNNING by SD layer during
+                * device addition but the request queue is still stopped by
+                * our earlier block call. We need to perform a block again
+                * to get the device to SDEV_BLOCK and then to SDEV_RUNNING */
+
+               sdev_printk(KERN_WARNING, sdev,
+                   "device_unblock failed with return(%d) for handle(0x%04x) "
+                   "performing a block followed by an unblock\n",
+                   sas_device_priv_data->sas_target->handle, r);
+               sas_device_priv_data->block = 1;
+               r = scsi_internal_device_block(sdev);
+               if (r)
+                       sdev_printk(KERN_WARNING, sdev, "retried device_block "
+                           "failed with return(%d) for handle(0x%04x)\n",
+                           sas_device_priv_data->sas_target->handle, r);
+
+               sas_device_priv_data->block = 0;
+               r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+               if (r)
+                       sdev_printk(KERN_WARNING, sdev, "retried device_unblock"
+                           " failed with return(%d) for handle(0x%04x)\n",
+                           sas_device_priv_data->sas_target->handle, r);
+       }
+}
+
 /**
  * _scsih_ublock_io_all_device - unblock every device
  * @ioc: per adapter object
@@ -2570,11 +2660,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
                if (!sas_device_priv_data->block)
                        continue;
 
-               sas_device_priv_data->block = 0;
                dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
                        "device_running, handle(0x%04x)\n",
                    sas_device_priv_data->sas_target->handle));
-               scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+               _scsih_internal_device_unblock(sdev, sas_device_priv_data);
        }
 }
 
@@ -2599,10 +2688,9 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
                if (sas_device_priv_data->sas_target->sas_address
                    != sas_address)
                        continue;
-               if (sas_device_priv_data->block) {
-                       sas_device_priv_data->block = 0;
-                       scsi_internal_device_unblock(sdev, SDEV_RUNNING);
-               }
+               if (sas_device_priv_data->block)
+                       _scsih_internal_device_unblock(sdev,
+                               sas_device_priv_data);
        }
 }
 
@@ -2625,10 +2713,7 @@ _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
                        continue;
                if (sas_device_priv_data->block)
                        continue;
-               sas_device_priv_data->block = 1;
-               scsi_internal_device_block(sdev);
-               sdev_printk(KERN_INFO, sdev, "device_blocked, handle(0x%04x)\n",
-                   sas_device_priv_data->sas_target->handle);
+               _scsih_internal_device_block(sdev, sas_device_priv_data);
        }
 }
 
@@ -2644,6 +2729,11 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        struct scsi_device *sdev;
+       struct _sas_device *sas_device;
+
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (!sas_device)
+               return;
 
        shost_for_each_device(sdev, ioc->shost) {
                sas_device_priv_data = sdev->hostdata;
@@ -2653,10 +2743,9 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                        continue;
                if (sas_device_priv_data->block)
                        continue;
-               sas_device_priv_data->block = 1;
-               scsi_internal_device_block(sdev);
-               sdev_printk(KERN_INFO, sdev,
-                       "device_blocked, handle(0x%04x)\n", handle);
+               if (sas_device->pend_sas_rphy_add)
+                       continue;
+               _scsih_internal_device_block(sdev, sas_device_priv_data);
        }
 }
 
@@ -2806,6 +2895,18 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                        "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n",
                        ioc->name, handle,
                    (unsigned long long)sas_address));
+               if (sas_device->enclosure_handle != 0)
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                        "setting delete flag:enclosure logical id(0x%016llx),"
+                        " slot(%d)\n", ioc->name, (unsigned long long)
+                         sas_device->enclosure_logical_id,
+                         sas_device->slot));
+               if (sas_device->connector_name)
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                        "setting delete flag: enclosure level(0x%04x),"
+                        " connector name( %s)\n", ioc->name,
+                         sas_device->enclosure_level,
+                         sas_device->connector_name));
                _scsih_ublock_io_device(ioc, sas_address);
                sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
        }
@@ -3502,7 +3603,7 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
 
 
 /**
- * _scsih_qcmd - main scsi request entry point
+ * scsih_qcmd - main scsi request entry point
  * @scmd: pointer to scsi command object
  * @done: function pointer to be invoked on completion
  *
@@ -3512,8 +3613,8 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
  * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
  * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
  */
-static int
-_scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+int
+scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -3523,10 +3624,8 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
        u16 smid;
        u16 handle;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_SCSI)
                scsi_print_command(scmd);
-#endif
 
        sas_device_priv_data = scmd->device->hostdata;
        if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
@@ -3657,7 +3756,6 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
        }
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
  * @ioc: per adapter object
@@ -3821,10 +3919,19 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
                                "\tsas_address(0x%016llx), phy(%d)\n",
                                ioc->name, (unsigned long long)
                            sas_device->sas_address, sas_device->phy);
-                       pr_warn(MPT3SAS_FMT
-                           "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
-                           ioc->name, (unsigned long long)
-                           sas_device->enclosure_logical_id, sas_device->slot);
+                       if (sas_device->enclosure_handle != 0)
+                               pr_warn(MPT3SAS_FMT
+                                 "\tenclosure_logical_id(0x%016llx),"
+                                 "slot(%d)\n", ioc->name,
+                                 (unsigned long long)
+                                 sas_device->enclosure_logical_id,
+                                 sas_device->slot);
+                       if (sas_device->connector_name[0])
+                               pr_warn(MPT3SAS_FMT
+                                 "\tenclosure level(0x%04x),"
+                                 " connector name( %s)\n", ioc->name,
+                                 sas_device->enclosure_level,
+                                 sas_device->connector_name);
                }
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
@@ -3861,7 +3968,6 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
                _scsih_response_code(ioc, response_bytes[0]);
        }
 }
-#endif
 
 /**
  * _scsih_turn_on_pfa_led - illuminate PFA LED
@@ -3999,7 +4105,16 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
                return;
        }
-       starget_printk(KERN_WARNING, starget, "predicted fault\n");
+       if (sas_device->enclosure_handle != 0)
+               starget_printk(KERN_INFO, starget, "predicted fault, "
+                       "enclosure logical id(0x%016llx), slot(%d)\n",
+                       (unsigned long long)sas_device->enclosure_logical_id,
+                       sas_device->slot);
+       if (sas_device->connector_name[0] != '\0')
+               starget_printk(KERN_WARNING, starget, "predicted fault, "
+                       "enclosure level(0x%04x), connector name( %s)\n",
+                       sas_device->enclosure_level,
+                       sas_device->connector_name);
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
        if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
@@ -4119,8 +4234,13 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
                        _scsih_smart_predicted_fault(ioc,
                            le16_to_cpu(mpi_reply->DevHandle));
                mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
-       }
 
+               if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
+                    ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
+                    (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
+                    (scmd->sense_buffer[2] == HARDWARE_ERROR)))
+                       _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
+       }
        switch (ioc_status) {
        case MPI2_IOCSTATUS_BUSY:
        case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
@@ -4146,6 +4266,9 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
                                scmd->device->expecting_cc_ua = 1;
                        }
                        break;
+               } else if (log_info == VIRTUAL_IO_FAILED_RETRY) {
+                       scmd->result = DID_RESET << 16;
+                       break;
                }
                scmd->result = DID_SOFT_ERROR << 16;
                break;
@@ -4223,10 +4346,8 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
 
        }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
                _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
-#endif
 
  out:
 
@@ -4788,6 +4909,16 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
                        sas_device->handle, handle);
                sas_target_priv_data->handle = handle;
                sas_device->handle = handle;
+               if (sas_device_pg0.Flags &
+                    MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
+                       sas_device->enclosure_level =
+                               le16_to_cpu(sas_device_pg0.EnclosureLevel);
+                       memcpy(&sas_device->connector_name[0],
+                               &sas_device_pg0.ConnectorName[0], 4);
+               } else {
+                       sas_device->enclosure_level = 0;
+                       sas_device->connector_name[0] = '\0';
+               }
        }
 
        /* check if device is present */
@@ -4894,14 +5025,24 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
                    ioc->name, __FILE__, __LINE__, __func__);
        sas_device->enclosure_handle =
            le16_to_cpu(sas_device_pg0.EnclosureHandle);
-       sas_device->slot =
-           le16_to_cpu(sas_device_pg0.Slot);
+       if (sas_device->enclosure_handle != 0)
+               sas_device->slot =
+                   le16_to_cpu(sas_device_pg0.Slot);
        sas_device->device_info = device_info;
        sas_device->sas_address = sas_address;
        sas_device->phy = sas_device_pg0.PhyNum;
        sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
            MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
 
+       if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
+               sas_device->enclosure_level =
+                       le16_to_cpu(sas_device_pg0.EnclosureLevel);
+               memcpy(&sas_device->connector_name[0],
+                       &sas_device_pg0.ConnectorName[0], 4);
+       } else {
+               sas_device->enclosure_level = 0;
+               sas_device->connector_name[0] = '\0';
+       }
        /* get enclosure_logical_id */
        if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
           ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
@@ -4943,6 +5084,18 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
                ioc->name, __func__,
            sas_device->handle, (unsigned long long)
            sas_device->sas_address));
+       if (sas_device->enclosure_handle != 0)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n",
+                   ioc->name, __func__,
+                   (unsigned long long)sas_device->enclosure_logical_id,
+                   sas_device->slot));
+       if (sas_device->connector_name[0] != '\0')
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                 "%s: enter: enclosure level(0x%04x), connector name( %s)\n",
+                 ioc->name, __func__,
+                 sas_device->enclosure_level,
+                 sas_device->connector_name));
 
        if (sas_device->starget && sas_device->starget->hostdata) {
                sas_target_priv_data = sas_device->starget->hostdata;
@@ -4959,17 +5112,38 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
                "removing handle(0x%04x), sas_addr(0x%016llx)\n",
                ioc->name, sas_device->handle,
            (unsigned long long) sas_device->sas_address);
+       if (sas_device->enclosure_handle != 0)
+               pr_info(MPT3SAS_FMT
+                 "removing : enclosure logical id(0x%016llx), slot(%d)\n",
+                 ioc->name,
+                 (unsigned long long)sas_device->enclosure_logical_id,
+                 sas_device->slot);
+       if (sas_device->connector_name[0] != '\0')
+               pr_info(MPT3SAS_FMT
+                 "removing enclosure level(0x%04x), connector name( %s)\n",
+                 ioc->name, sas_device->enclosure_level,
+                 sas_device->connector_name);
 
        dewtprintk(ioc, pr_info(MPT3SAS_FMT
                "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
                ioc->name, __func__,
-           sas_device->handle, (unsigned long long)
-           sas_device->sas_address));
+               sas_device->handle, (unsigned long long)
+               sas_device->sas_address));
+       if (sas_device->enclosure_handle != 0)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n",
+                   ioc->name, __func__,
+                   (unsigned long long)sas_device->enclosure_logical_id,
+                   sas_device->slot));
+       if (sas_device->connector_name[0] != '\0')
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: exit: enclosure level(0x%04x), connector name(%s)\n",
+                   ioc->name, __func__, sas_device->enclosure_level,
+                   sas_device->connector_name));
 
        kfree(sas_device);
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_topology_change_event_debug - debug for topology event
  * @ioc: per adapter object
@@ -5047,7 +5221,6 @@ _scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
 
        }
 }
-#endif
 
 /**
  * _scsih_sas_topology_change_event - handle topology changes
@@ -5072,10 +5245,8 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
                (Mpi2EventDataSasTopologyChangeList_t *)
                fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_topology_change_event_debug(ioc, event_data);
-#endif
 
        if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
                return 0;
@@ -5181,7 +5352,6 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
        return 0;
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_device_status_change_event_debug - debug for device event
  * @event_data: event data payload
@@ -5249,7 +5419,6 @@ _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
                    event_data->ASC, event_data->ASCQ);
        pr_info("\n");
 }
-#endif
 
 /**
  * _scsih_sas_device_status_change_event - handle device status change
@@ -5271,11 +5440,9 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
                (Mpi2EventDataSasDeviceStatusChange_t *)
                fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_device_status_change_event_debug(ioc,
                     event_data);
-#endif
 
        /* In MPI Revision K (0xC), the internal device reset complete was
         * implemented, so avoid setting tm_busy flag for older firmware.
@@ -5313,7 +5480,6 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
  * event
@@ -5348,7 +5514,6 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
            (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
            le16_to_cpu(event_data->StartSlot));
 }
-#endif
 
 /**
  * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
@@ -5362,12 +5527,10 @@ static void
 _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
        struct fw_event_work *fw_event)
 {
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
                     (Mpi2EventDataSasEnclDevStatusChange_t *)
                     fw_event->event_data);
-#endif
 }
 
 /**
@@ -5547,17 +5710,15 @@ _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
        Mpi2EventDataSasDiscovery_t *event_data =
                (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
                pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
                    (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
                    "start" : "stop");
-       if (event_data->DiscoveryStatus)
-               pr_info("discovery_status(0x%08x)",
-                   le32_to_cpu(event_data->DiscoveryStatus));
-       pr_info("\n");
+               if (event_data->DiscoveryStatus)
+                       pr_info("discovery_status(0x%08x)",
+                           le32_to_cpu(event_data->DiscoveryStatus));
+               pr_info("\n");
        }
-#endif
 
        if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
            !ioc->sas_hba.num_phys) {
@@ -5934,7 +6095,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
        _scsih_add_device(ioc, handle, 0, 1);
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
  * @ioc: per adapter object
@@ -6014,7 +6174,6 @@ _scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
                    element->PhysDiskNum);
        }
 }
-#endif
 
 /**
  * _scsih_sas_ir_config_change_event - handle ir configuration change events
@@ -6035,12 +6194,9 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
                (Mpi2EventDataIrConfigChangeList_t *)
                fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_ir_config_change_event_debug(ioc, event_data);
 
-#endif
-
        foreign_config = (le32_to_cpu(event_data->Flags) &
            MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
 
@@ -6252,7 +6408,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
        }
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
  * @ioc: per adapter object
@@ -6294,7 +6449,6 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
            le16_to_cpu(event_data->VolDevHandle),
            event_data->PercentComplete);
 }
-#endif
 
 /**
  * _scsih_sas_ir_operation_status_event - handle RAID operation events
@@ -6315,11 +6469,9 @@ _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
        unsigned long flags;
        u16 handle;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_ir_operation_status_event_debug(ioc,
                     event_data);
-#endif
 
        /* code added for raid transport support */
        if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
@@ -6357,9 +6509,7 @@ _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
 /**
  * _scsih_mark_responding_sas_device - mark a sas_devices as responding
  * @ioc: per adapter object
- * @sas_address: sas address
- * @slot: enclosure slot id
- * @handle: device handle
+ * @sas_device_pg0: SAS Device page 0
  *
  * After host reset, find out whether devices are still responding.
  * Used in _scsih_remove_unresponsive_sas_devices.
@@ -6367,8 +6517,8 @@ _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
  * Return nothing.
  */
 static void
-_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
-       u16 slot, u16 handle)
+_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc,
+Mpi2SasDevicePage0_t *sas_device_pg0)
 {
        struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
        struct scsi_target *starget;
@@ -6377,8 +6527,8 @@ _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
-               if (sas_device->sas_address == sas_address &&
-                   sas_device->slot == slot) {
+               if ((sas_device->sas_address == sas_device_pg0->SASAddress) &&
+                       (sas_device->slot == sas_device_pg0->Slot)) {
                        sas_device->responding = 1;
                        starget = sas_device->starget;
                        if (starget && starget->hostdata) {
@@ -6387,22 +6537,40 @@ _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
                                sas_target_priv_data->deleted = 0;
                        } else
                                sas_target_priv_data = NULL;
-                       if (starget)
+                       if (starget) {
                                starget_printk(KERN_INFO, starget,
-                                   "handle(0x%04x), sas_addr(0x%016llx), "
-                                   "enclosure logical id(0x%016llx), "
-                                   "slot(%d)\n", handle,
-                                   (unsigned long long)sas_device->sas_address,
+                                   "handle(0x%04x), sas_addr(0x%016llx)\n",
+                                   sas_device_pg0->DevHandle,
                                    (unsigned long long)
-                                   sas_device->enclosure_logical_id,
-                                   sas_device->slot);
-                       if (sas_device->handle == handle)
+                                   sas_device->sas_address);
+
+                               if (sas_device->enclosure_handle != 0)
+                                       starget_printk(KERN_INFO, starget,
+                                        "enclosure logical id(0x%016llx),"
+                                        " slot(%d)\n",
+                                        (unsigned long long)
+                                        sas_device->enclosure_logical_id,
+                                        sas_device->slot);
+                       }
+                       if (sas_device_pg0->Flags &
+                             MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
+                               sas_device->enclosure_level =
+                                  le16_to_cpu(sas_device_pg0->EnclosureLevel);
+                               memcpy(&sas_device->connector_name[0],
+                                       &sas_device_pg0->ConnectorName[0], 4);
+                       } else {
+                               sas_device->enclosure_level = 0;
+                               sas_device->connector_name[0] = '\0';
+                       }
+
+                       if (sas_device->handle == sas_device_pg0->DevHandle)
                                goto out;
                        pr_info("\thandle changed from(0x%04x)!!!\n",
                            sas_device->handle);
-                       sas_device->handle = handle;
+                       sas_device->handle = sas_device_pg0->DevHandle;
                        if (sas_target_priv_data)
-                               sas_target_priv_data->handle = handle;
+                               sas_target_priv_data->handle =
+                                       sas_device_pg0->DevHandle;
                        goto out;
                }
        }
@@ -6441,13 +6609,15 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
                    MPI2_IOCSTATUS_MASK;
                if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
                        break;
-               handle = le16_to_cpu(sas_device_pg0.DevHandle);
+               handle = sas_device_pg0.DevHandle =
+                               le16_to_cpu(sas_device_pg0.DevHandle);
                device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
                if (!(_scsih_is_end_device(device_info)))
                        continue;
-               _scsih_mark_responding_sas_device(ioc,
-                   le64_to_cpu(sas_device_pg0.SASAddress),
-                   le16_to_cpu(sas_device_pg0.Slot), handle);
+               sas_device_pg0.SASAddress =
+                               le64_to_cpu(sas_device_pg0.SASAddress);
+               sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot);
+               _scsih_mark_responding_sas_device(ioc, &sas_device_pg0);
        }
 
  out:
@@ -7255,36 +7425,6 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
        return 1;
 }
 
-/* shost template */
-static struct scsi_host_template scsih_driver_template = {
-       .module                         = THIS_MODULE,
-       .name                           = "Fusion MPT SAS Host",
-       .proc_name                      = MPT3SAS_DRIVER_NAME,
-       .queuecommand                   = _scsih_qcmd,
-       .target_alloc                   = _scsih_target_alloc,
-       .slave_alloc                    = _scsih_slave_alloc,
-       .slave_configure                = _scsih_slave_configure,
-       .target_destroy                 = _scsih_target_destroy,
-       .slave_destroy                  = _scsih_slave_destroy,
-       .scan_finished                  = _scsih_scan_finished,
-       .scan_start                     = _scsih_scan_start,
-       .change_queue_depth             = _scsih_change_queue_depth,
-       .eh_abort_handler               = _scsih_abort,
-       .eh_device_reset_handler        = _scsih_dev_reset,
-       .eh_target_reset_handler        = _scsih_target_reset,
-       .eh_host_reset_handler          = _scsih_host_reset,
-       .bios_param                     = _scsih_bios_param,
-       .can_queue                      = 1,
-       .this_id                        = -1,
-       .sg_tablesize                   = MPT3SAS_SG_DEPTH,
-       .max_sectors                    = 32767,
-       .cmd_per_lun                    = 7,
-       .use_clustering                 = ENABLE_CLUSTERING,
-       .shost_attrs                    = mpt3sas_host_attrs,
-       .sdev_attrs                     = mpt3sas_dev_attrs,
-       .track_queue_depth              = 1,
-};
-
 /**
  * _scsih_expander_node_remove - removing expander device from list.
  * @ioc: per adapter object
@@ -7405,13 +7545,13 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
- * _scsih_remove - detach and remove add host
+ * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
  * Routine called when unloading the driver.
  * Return nothing.
  */
-static void _scsih_remove(struct pci_dev *pdev)
+void scsih_remove(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7477,13 +7617,13 @@ static void _scsih_remove(struct pci_dev *pdev)
 }
 
 /**
- * _scsih_shutdown - routine call during system shutdown
+ * scsih_shutdown - routine call during system shutdown
  * @pdev: PCI device struct
  *
  * Return nothing.
  */
-static void
-_scsih_shutdown(struct pci_dev *pdev)
+void
+scsih_shutdown(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7675,15 +7815,15 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
- * _scsih_scan_start - scsi lld callback for .scan_start
+ * scsih_scan_start - scsi lld callback for .scan_start
  * @shost: SCSI host pointer
  *
  * The shost has the ability to discover targets on its own instead
  * of scanning the entire bus.  In our implemention, we will kick off
  * firmware discovery.
  */
-static void
-_scsih_scan_start(struct Scsi_Host *shost)
+void
+scsih_scan_start(struct Scsi_Host *shost)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
        int rc;
@@ -7701,7 +7841,7 @@ _scsih_scan_start(struct Scsi_Host *shost)
 }
 
 /**
- * _scsih_scan_finished - scsi lld callback for .scan_finished
+ * scsih_scan_finished - scsi lld callback for .scan_finished
  * @shost: SCSI host pointer
  * @time: elapsed time of the scan in jiffies
  *
@@ -7709,8 +7849,8 @@ _scsih_scan_start(struct Scsi_Host *shost)
  * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
  * we wait for firmware discovery to complete, then return 1.
  */
-static int
-_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
+int
+scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
 
@@ -7754,25 +7894,52 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
        return 1;
 }
 
-/**
- * _scsih_probe - attach and add scsi host
+void
+_scsih_determine_hba_mpi_version(struct MPT3SAS_ADAPTER *ioc) {
+
+       switch (ioc->pdev->device) {
+       case MPI2_MFGPAGE_DEVID_SAS2004:
+       case MPI2_MFGPAGE_DEVID_SAS2008:
+       case MPI2_MFGPAGE_DEVID_SAS2108_1:
+       case MPI2_MFGPAGE_DEVID_SAS2108_2:
+       case MPI2_MFGPAGE_DEVID_SAS2108_3:
+       case MPI2_MFGPAGE_DEVID_SAS2116_1:
+       case MPI2_MFGPAGE_DEVID_SAS2116_2:
+       case MPI2_MFGPAGE_DEVID_SAS2208_1:
+       case MPI2_MFGPAGE_DEVID_SAS2208_2:
+       case MPI2_MFGPAGE_DEVID_SAS2208_3:
+       case MPI2_MFGPAGE_DEVID_SAS2208_4:
+       case MPI2_MFGPAGE_DEVID_SAS2208_5:
+       case MPI2_MFGPAGE_DEVID_SAS2208_6:
+       case MPI2_MFGPAGE_DEVID_SAS2308_1:
+       case MPI2_MFGPAGE_DEVID_SAS2308_2:
+       case MPI2_MFGPAGE_DEVID_SAS2308_3:
+               ioc->hba_mpi_version_belonged = MPI2_VERSION;
+               break;
+       case MPI25_MFGPAGE_DEVID_SAS3004:
+       case MPI25_MFGPAGE_DEVID_SAS3008:
+       case MPI25_MFGPAGE_DEVID_SAS3108_1:
+       case MPI25_MFGPAGE_DEVID_SAS3108_2:
+       case MPI25_MFGPAGE_DEVID_SAS3108_5:
+       case MPI25_MFGPAGE_DEVID_SAS3108_6:
+               ioc->hba_mpi_version_belonged = MPI25_VERSION;
+               break;
+       }
+}
+
+/**
+ * scsih_probe - attach and add scsi host
  * @pdev: PCI device struct
  * @id: pci device id
  *
  * Returns 0 success, anything else error.
  */
-static int
-_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int
+scsih_probe(struct pci_dev *pdev, struct Scsi_Host *shost)
 {
        struct MPT3SAS_ADAPTER *ioc;
-       struct Scsi_Host *shost;
        int rv;
 
-       shost = scsi_host_alloc(&scsih_driver_template,
-           sizeof(struct MPT3SAS_ADAPTER));
-       if (!shost)
-               return -ENODEV;
-
        /* init local params */
        ioc = shost_priv(shost);
        memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
@@ -7780,7 +7947,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        list_add_tail(&ioc->list, &mpt3sas_ioc_list);
        ioc->shost = shost;
        ioc->id = mpt_ids++;
-       sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id);
+
        ioc->pdev = pdev;
        ioc->scsi_io_cb_idx = scsi_io_cb_idx;
        ioc->tm_cb_idx = tm_cb_idx;
@@ -7815,6 +7982,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
        INIT_LIST_HEAD(&ioc->reply_queue_list);
 
+       _scsih_determine_hba_mpi_version(ioc);
+       sprintf(ioc->name, "%s_cm%d", driver_name, ioc->id);
+
        /* init shost parameters */
        shost->max_cmd_len = 32;
        shost->max_lun = max_lun;
@@ -7854,8 +8024,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        /* event thread */
        snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
            "fw_event%d", ioc->id);
-       ioc->firmware_event_thread = create_singlethread_workqueue(
-           ioc->firmware_event_name);
+       ioc->firmware_event_thread = alloc_ordered_workqueue(
+           ioc->firmware_event_name, WQ_MEM_RECLAIM);
        if (!ioc->firmware_event_thread) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
@@ -7891,14 +8061,14 @@ out_add_shost_fail:
 
 #ifdef CONFIG_PM
 /**
- * _scsih_suspend - power management suspend main entry point
+ * scsih_suspend - power management suspend main entry point
  * @pdev: PCI device struct
  * @state: PM state change to (usually PCI_D3)
  *
  * Returns 0 success, anything else error.
  */
-static int
-_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
+int
+scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7919,13 +8089,13 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 }
 
 /**
- * _scsih_resume - power management resume main entry point
+ * scsih_resume - power management resume main entry point
  * @pdev: PCI device struct
  *
  * Returns 0 success, anything else error.
  */
-static int
-_scsih_resume(struct pci_dev *pdev)
+int
+scsih_resume(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7952,7 +8122,7 @@ _scsih_resume(struct pci_dev *pdev)
 #endif /* CONFIG_PM */
 
 /**
- * _scsih_pci_error_detected - Called when a PCI error is detected.
+ * scsih_pci_error_detected - Called when a PCI error is detected.
  * @pdev: PCI device struct
  * @state: PCI channel state
  *
@@ -7961,8 +8131,8 @@ _scsih_resume(struct pci_dev *pdev)
  * Return value:
  *      PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
  */
-static pci_ers_result_t
-_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+pci_ers_result_t
+scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7991,15 +8161,15 @@ _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 }
 
 /**
- * _scsih_pci_slot_reset - Called when PCI slot has been reset.
+ * scsih_pci_slot_reset - Called when PCI slot has been reset.
  * @pdev: PCI device struct
  *
  * Description: This routine is called by the pci error recovery
  * code after the PCI slot has been reset, just before we
  * should resume normal operations.
  */
-static pci_ers_result_t
-_scsih_pci_slot_reset(struct pci_dev *pdev)
+pci_ers_result_t
+scsih_pci_slot_reset(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8028,15 +8198,15 @@ _scsih_pci_slot_reset(struct pci_dev *pdev)
 }
 
 /**
- * _scsih_pci_resume() - resume normal ops after PCI reset
+ * scsih_pci_resume() - resume normal ops after PCI reset
  * @pdev: pointer to PCI device
  *
  * Called when the error recovery driver tells us that its
  * OK to resume normal operation. Use completion to allow
  * halted scsi ops to resume.
  */
-static void
-_scsih_pci_resume(struct pci_dev *pdev)
+void
+scsih_pci_resume(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8049,11 +8219,11 @@ _scsih_pci_resume(struct pci_dev *pdev)
 }
 
 /**
- * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
+ * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
  * @pdev: pointer to PCI device
  */
-static pci_ers_result_t
-_scsih_pci_mmio_enabled(struct pci_dev *pdev)
+pci_ers_result_t
+scsih_pci_mmio_enabled(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8067,62 +8237,16 @@ _scsih_pci_mmio_enabled(struct pci_dev *pdev)
        return PCI_ERS_RESULT_NEED_RESET;
 }
 
-/* raid transport support */
-static struct raid_function_template mpt3sas_raid_functions = {
-       .cookie         = &scsih_driver_template,
-       .is_raid        = _scsih_is_raid,
-       .get_resync     = _scsih_get_resync,
-       .get_state      = _scsih_get_state,
-};
-
-static struct pci_error_handlers _scsih_err_handler = {
-       .error_detected = _scsih_pci_error_detected,
-       .mmio_enabled = _scsih_pci_mmio_enabled,
-       .slot_reset =   _scsih_pci_slot_reset,
-       .resume =       _scsih_pci_resume,
-};
-
-static struct pci_driver scsih_driver = {
-       .name           = MPT3SAS_DRIVER_NAME,
-       .id_table       = scsih_pci_table,
-       .probe          = _scsih_probe,
-       .remove         = _scsih_remove,
-       .shutdown       = _scsih_shutdown,
-       .err_handler    = &_scsih_err_handler,
-#ifdef CONFIG_PM
-       .suspend        = _scsih_suspend,
-       .resume         = _scsih_resume,
-#endif
-};
-
-
 /**
- * _scsih_init - main entry point for this driver.
+ * scsih_init - main entry point for this driver.
  *
  * Returns 0 success, anything else error.
  */
-static int __init
-_scsih_init(void)
+int
+scsih_init(void)
 {
-       int error;
-
        mpt_ids = 0;
 
-       pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
-           MPT3SAS_DRIVER_VERSION);
-
-       mpt3sas_transport_template =
-           sas_attach_transport(&mpt3sas_transport_functions);
-       if (!mpt3sas_transport_template)
-               return -ENODEV;
-
-/* raid transport support */
-       mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions);
-       if (!mpt3sas_raid_template) {
-               sas_release_transport(mpt3sas_transport_template);
-               return -ENODEV;
-       }
-
        mpt3sas_base_initialize_callback_handler();
 
         /* queuecommand callback hander */
@@ -8159,33 +8283,17 @@ _scsih_init(void)
        tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
            _scsih_sas_control_complete);
 
-       mpt3sas_ctl_init();
-
-       error = pci_register_driver(&scsih_driver);
-       if (error) {
-               /* raid transport support */
-               raid_class_release(mpt3sas_raid_template);
-               sas_release_transport(mpt3sas_transport_template);
-       }
-
-       return error;
+       return 0;
 }
 
 /**
- * _scsih_exit - exit point for this driver (when it is a module).
+ * scsih_exit - exit point for this driver (when it is a module).
  *
  * Returns 0 success, anything else error.
  */
-static void __exit
-_scsih_exit(void)
+void
+scsih_exit(void)
 {
-       pr_info("mpt3sas version %s unloading\n",
-           MPT3SAS_DRIVER_VERSION);
-
-       mpt3sas_ctl_exit();
-
-       pci_unregister_driver(&scsih_driver);
-
 
        mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
        mpt3sas_base_release_callback_handler(tm_cb_idx);
@@ -8204,6 +8312,3 @@ _scsih_exit(void)
        raid_class_release(mpt3sas_raid_template);
        sas_release_transport(mpt3sas_transport_template);
 }
-
-module_init(_scsih_init);
-module_exit(_scsih_exit);