Merge remote-tracking branch 'scsi-queue/core-for-3.17' into for-next
authorJames Bottomley <JBottomley@Parallels.com>
Wed, 6 Aug 2014 17:26:47 +0000 (10:26 -0700)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 6 Aug 2014 17:26:47 +0000 (10:26 -0700)
71 files changed:
MAINTAINERS
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptsas.h
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/scsi/3w-xxxx.h
drivers/scsi/Kconfig
drivers/scsi/NCR53c406a.c
drivers/scsi/aic7xxx/aic7770_osm.c
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/bfa/bfa_fcs.c
drivers/scsi/bfa/bfa_ioc.h
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
drivers/scsi/bnx2fc/Kconfig
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_constants.h
drivers/scsi/bnx2fc/bnx2fc_debug.c
drivers/scsi/bnx2fc/bnx2fc_debug.h
drivers/scsi/bnx2fc/bnx2fc_els.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c
drivers/scsi/bnx2i/57xx_iscsi_constants.h
drivers/scsi/bnx2i/57xx_iscsi_hsi.h
drivers/scsi/bnx2i/Kconfig
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/bnx2i/bnx2i_sysfs.c
drivers/scsi/fnic/fnic_isr.c
drivers/scsi/hpsa.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/isci/init.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/pas16.c
drivers/scsi/pm8001/pm8001_ctl.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qlogicfas.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/storvsc_drv.c
drivers/scsi/ufs/ufs.h
drivers/scsi/ufs/ufshcd-pci.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshci.h
drivers/scsi/virtio_scsi.c
drivers/scsi/vmw_pvscsi.c
include/scsi/scsi_transport_fc.h

index 61a8f486306b700749dce48b58ff63c856b3a5eb..1262d3cdaf3df40152d5405ee46f29904c0a03f5 100644 (file)
@@ -1987,13 +1987,13 @@ S:      Supported
 F:     drivers/net/wireless/brcm80211/
 
 BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
-M:     Eddie Wai <eddie.wai@broadcom.com>
+M:     QLogic-Storage-Upstream@qlogic.com
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/bnx2fc/
 
 BROADCOM BNX2I 1/10 GIGABIT iSCSI DRIVER
-M:     Eddie Wai <eddie.wai@broadcom.com>
+M:     QLogic-Storage-Upstream@qlogic.com
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/bnx2i/
index ebc0af7d769c01699aa8077b4231a5f61fc86ec2..a896d948b79ee12b36f82c3d04c6c3ec34d9d1b0 100644 (file)
@@ -649,12 +649,10 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
        case MPI_FUNCTION_CONFIG:
        case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
                ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
-               if (reply) {
-                       ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
-                       memcpy(ioc->mptbase_cmds.reply, reply,
-                           min(MPT_DEFAULT_FRAME_SIZE,
-                               4 * reply->u.reply.MsgLength));
-               }
+               ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+               memcpy(ioc->mptbase_cmds.reply, reply,
+                   min(MPT_DEFAULT_FRAME_SIZE,
+                       4 * reply->u.reply.MsgLength));
                if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
                        ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
                        complete(&ioc->mptbase_cmds.done);
@@ -1408,8 +1406,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
  *     in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
  *
  **/
-static void
-mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
+static const char*
+mpt_get_product_name(u16 vendor, u16 device, u8 revision)
 {
        char *product_str = NULL;
 
@@ -1635,8 +1633,7 @@ mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
        }
 
  out:
-       if (product_str)
-               sprintf(prod_name, "%s", product_str);
+       return product_str;
 }
 
 /**
@@ -1887,8 +1884,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
            ioc->name, &ioc->facts, &ioc->pfacts[0]));
 
-       mpt_get_product_name(pdev->vendor, pdev->device, pdev->revision,
-                            ioc->prod_name);
+       ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device,
+                                             pdev->revision);
 
        switch (pdev->device)
        {
@@ -7007,7 +7004,7 @@ EXPORT_SYMBOL(mpt_halt_firmware);
  *     IOC doesn't reply to any outstanding request. This will transfer IOC
  *     to READY state.
  **/
-int
+static int
 mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 {
        int              rc;
index f37ea6fdc6ae8f4187cb230635b7327df345c266..8f14090b8b7151a66f43e23345c9bd5c280d1aa5 100644 (file)
@@ -605,7 +605,7 @@ typedef struct _MPT_ADAPTER
        int                      id;            /* Unique adapter id N {0,1,2,...} */
        int                      pci_irq;       /* This irq           */
        char                     name[MPT_NAME_LENGTH]; /* "iocN"             */
-       char                     prod_name[MPT_NAME_LENGTH];    /* "LSIFC9x9"         */
+       const char               *prod_name;    /* "LSIFC9x9"         */
 #ifdef CONFIG_FUSION_LOGGING
        /* used in mpt_display_event_info */
        char                     evStr[EVENT_DESCR_STR_SZ];
index 8a050e8856881ada1094954c5ce04f9584ed36e7..b0a892a2bf1b535ac4b155c92dbca0bacaad990a 100644 (file)
@@ -1261,19 +1261,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        else
                return -EFAULT;
 
-       karg = kmalloc(data_size, GFP_KERNEL);
-       if (karg == NULL) {
-               printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
-                               __FILE__, __LINE__);
-               return -ENOMEM;
-       }
-
-       if (copy_from_user(karg, uarg, data_size)) {
-               printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - "
-                       "Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
-                               __FILE__, __LINE__, uarg);
-               kfree(karg);
-               return -EFAULT;
+       karg = memdup_user(uarg, data_size);
+       if (IS_ERR(karg)) {
+               printk(KERN_ERR MYNAM "%s@%d::mpt_ioctl_iocinfo() - memdup_user returned error [%ld]\n",
+                               __FILE__, __LINE__, PTR_ERR(karg));
+               return PTR_ERR(karg);
        }
 
        if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
index bf2a2cef562bed6bdfe71a8945f308d0bb2bb478..d8bf84aef602d0f959641aea2e501f213837fca3 100644 (file)
@@ -525,8 +525,7 @@ mptfc_target_destroy(struct scsi_target *starget)
                if (ri) /* better be! */
                        ri->starget = NULL;
        }
-       if (starget->hostdata)
-               kfree(starget->hostdata);
+       kfree(starget->hostdata);
        starget->hostdata = NULL;
 }
 
index d636dbe172a3cf4a34cfc8b00cedd4f96582c6ea..0707fa2c701b543ef597d4797e77b8272c658ca4 100644 (file)
@@ -990,11 +990,10 @@ mptsas_queue_device_delete(MPT_ADAPTER *ioc,
        MpiEventDataSasDeviceStatusChange_t *sas_event_data)
 {
        struct fw_event_work *fw_event;
-       int sz;
 
-       sz = offsetof(struct fw_event_work, event_data) +
-           sizeof(MpiEventDataSasDeviceStatusChange_t);
-       fw_event = kzalloc(sz, GFP_ATOMIC);
+       fw_event = kzalloc(sizeof(*fw_event) +
+                          sizeof(MpiEventDataSasDeviceStatusChange_t),
+                          GFP_ATOMIC);
        if (!fw_event) {
                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
                    ioc->name, __func__, __LINE__);
@@ -1011,10 +1010,8 @@ static void
 mptsas_queue_rescan(MPT_ADAPTER *ioc)
 {
        struct fw_event_work *fw_event;
-       int sz;
 
-       sz = offsetof(struct fw_event_work, event_data);
-       fw_event = kzalloc(sz, GFP_ATOMIC);
+       fw_event = kzalloc(sizeof(*fw_event), GFP_ATOMIC);
        if (!fw_event) {
                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
                    ioc->name, __func__, __LINE__);
@@ -1206,27 +1203,28 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
            "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
 
        pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
-       if (pScsiTmReply) {
-               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                   "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
-                   "\ttask_type = 0x%02X, iocstatus = 0x%04X "
-                   "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
-                   "term_cmnds = %d\n", ioc->name,
-                   pScsiTmReply->Bus, pScsiTmReply->TargetID,
-                   pScsiTmReply->TaskType,
-                   le16_to_cpu(pScsiTmReply->IOCStatus),
-                   le32_to_cpu(pScsiTmReply->IOCLogInfo),
-                   pScsiTmReply->ResponseCode,
-                   le32_to_cpu(pScsiTmReply->TerminationCount)));
-
-               if (pScsiTmReply->ResponseCode)
-                       mptscsih_taskmgmt_response_code(ioc,
-                       pScsiTmReply->ResponseCode);
-       }
-
-       if (pScsiTmReply && (pScsiTmReply->TaskType ==
+       if (!pScsiTmReply)
+               return 0;
+
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
+           "\ttask_type = 0x%02X, iocstatus = 0x%04X "
+           "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
+           "term_cmnds = %d\n", ioc->name,
+           pScsiTmReply->Bus, pScsiTmReply->TargetID,
+           pScsiTmReply->TaskType,
+           le16_to_cpu(pScsiTmReply->IOCStatus),
+           le32_to_cpu(pScsiTmReply->IOCLogInfo),
+           pScsiTmReply->ResponseCode,
+           le32_to_cpu(pScsiTmReply->TerminationCount)));
+
+       if (pScsiTmReply->ResponseCode)
+               mptscsih_taskmgmt_response_code(ioc,
+               pScsiTmReply->ResponseCode);
+
+       if (pScsiTmReply->TaskType ==
            MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
-            MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
+            MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {
                ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
                ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
                memcpy(ioc->taskmgmt_cmds.reply, mr,
@@ -1575,7 +1573,7 @@ mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
        mptsas_port_delete(ioc, phy_info->port_details);
 }
 
-struct mptsas_phyinfo *
+static struct mptsas_phyinfo *
 mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
        struct mptsas_devinfo *sas_device)
 {
@@ -3648,7 +3646,7 @@ mptsas_send_expander_event(struct fw_event_work *fw_event)
  * @handle:
  *
  */
-struct mptsas_portinfo *
+static struct mptsas_portinfo *
 mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
 {
        struct mptsas_portinfo buffer, *port_info;
@@ -3856,10 +3854,8 @@ retry_page:
                        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
                                        sas_info->sas_address);
 
-                       if (phy_info) {
-                               mptsas_del_end_device(ioc, phy_info);
-                               goto redo_device_scan;
-                       }
+                       mptsas_del_end_device(ioc, phy_info);
+                       goto redo_device_scan;
                } else
                        mptsas_volume_delete(ioc, sas_info->fw.id);
        }
@@ -3870,9 +3866,8 @@ retry_page:
  redo_expander_scan:
        list_for_each_entry(port_info, &ioc->sas_topology, list) {
 
-               if (port_info->phy_info &&
-                   (!(port_info->phy_info[0].identify.device_info &
-                   MPI_SAS_DEVICE_INFO_SMP_TARGET)))
+               if (!(port_info->phy_info[0].identify.device_info &
+                   MPI_SAS_DEVICE_INFO_SMP_TARGET))
                        continue;
                found_expander = 0;
                handle = 0xFFFF;
@@ -4983,7 +4978,7 @@ static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 {
        u32 event = le32_to_cpu(reply->Event);
-       int sz, event_data_sz;
+       int event_data_sz;
        struct fw_event_work *fw_event;
        unsigned long delay;
 
@@ -5093,8 +5088,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 
        event_data_sz = ((reply->MsgLength * 4) -
            offsetof(EventNotificationReply_t, Data));
-       sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
-       fw_event = kzalloc(sz, GFP_ATOMIC);
+       fw_event = kzalloc(sizeof(*fw_event) + event_data_sz, GFP_ATOMIC);
        if (!fw_event) {
                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
                 __func__, __LINE__);
@@ -5321,7 +5315,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        return error;
 }
 
-void
+static void
 mptsas_shutdown(struct pci_dev *pdev)
 {
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
index 57e86ab77661361bf1dcedc9bc73ee352a54b46f..c396483d36245b6ac2683629f43eb1089614eada 100644 (file)
@@ -110,7 +110,7 @@ struct fw_event_work {
        MPT_ADAPTER     *ioc;
        u32                     event;
        u8                      retries;
-       u8                      __attribute__((aligned(4))) event_data[1];
+       char                    event_data[0] __aligned(4);
 };
 
 struct mptsas_discovery_event {
index 39e566803089bb2b685dc6eb4ea918e0c620ed26..e7dcb25833697e05a8d00742eac640dfd338f71d 100644 (file)
@@ -1271,15 +1271,13 @@ mptscsih_info(struct Scsi_Host *SChost)
 
        h = shost_priv(SChost);
 
-       if (h) {
-               if (h->info_kbuf == NULL)
-                       if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
-                               return h->info_kbuf;
-               h->info_kbuf[0] = '\0';
-
-               mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
-               h->info_kbuf[size-1] = '\0';
-       }
+       if (h->info_kbuf == NULL)
+               if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+                       return h->info_kbuf;
+       h->info_kbuf[0] = '\0';
+
+       mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+       h->info_kbuf[size-1] = '\0';
 
        return h->info_kbuf;
 }
@@ -1368,8 +1366,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt)
        /* Default to untagged. Once a target structure has been allocated,
         * use the Inquiry data to determine if device supports tagged.
         */
-       if (vdevice
-           && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+       if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
            && (SCpnt->device->tagged_supported)) {
                scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
                if (SCpnt->request && SCpnt->request->ioprio) {
index 49d11338294bbe31e6e07c1e14aded1670ab733a..787933d43d3217954eb95364fbea3cff9a7870dd 100644 (file)
@@ -461,8 +461,7 @@ static int mptspi_target_alloc(struct scsi_target *starget)
 static void
 mptspi_target_destroy(struct scsi_target *starget)
 {
-       if (starget->hostdata)
-               kfree(starget->hostdata);
+       kfree(starget->hostdata);
        starget->hostdata = NULL;
 }
 
@@ -620,7 +619,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
        spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
 }
 
-int
+static int
 mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
 {
        MPT_ADAPTER     *ioc = hd->ioc;
index 49dcf03c631a52f971170d6ee029083a69edab34..29b0b84ed69e888b1939c57dde7e60589506e992 100644 (file)
@@ -392,6 +392,8 @@ typedef struct TAG_TW_Passthru
        unsigned char padding[12];
 } TW_Passthru;
 
+#pragma pack()
+
 typedef struct TAG_TW_Device_Extension {
        u32                     base_addr;
        unsigned long           *alignment_virtual_address[TW_Q_LENGTH];
@@ -430,6 +432,4 @@ typedef struct TAG_TW_Device_Extension {
        wait_queue_head_t       ioctl_wqueue;
 } TW_Device_Extension;
 
-#pragma pack()
-
 #endif /* _3W_XXXX_H */
index 7b07e287e2ceb890a36ef88d8e3bdf422c3fb7b1..18a3358eb1d47c9f8cd6acd9e62816691afbff66 100644 (file)
@@ -493,7 +493,7 @@ config SCSI_DPT_I2O
 
 config SCSI_ADVANSYS
        tristate "AdvanSys SCSI support"
-       depends on SCSI && VIRT_TO_BUS
+       depends on SCSI && VIRT_TO_BUS && !ARM
        depends on ISA || EISA || PCI
        help
          This is a driver for all SCSI host adapters manufactured by
index 10c3374d759fc23b7b85d42d2374c6fdd1fb04bd..42c7161474f7b31ca4622f4ffe91ca4da333fb1e 100644 (file)
@@ -595,7 +595,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost)
 {
        if (shost->irq)
                free_irq(shost->irq, NULL);
-#ifdef USE_DMA
+#if USE_DMA
        if (shost->dma_channel != 0xff)
                free_dma(shost->dma_channel);
 #endif
index 0cb8ef64b5ce794ae720b73ecdc8849faa14421d..3d401d02c01955bc02304fe4f761993e73eaad46 100644 (file)
@@ -85,10 +85,9 @@ aic7770_probe(struct device *dev)
        int     error;
 
        sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
-       name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+       name = kstrdup(buf, GFP_ATOMIC);
        if (name == NULL)
                return (ENOMEM);
-       strcpy(name, buf);
        ahc = ahc_alloc(&aic7xxx_driver_template, name);
        if (ahc == NULL)
                return (ENOMEM);
index 3c85873b14b902ae128ec9a4626fa8220ab56218..8466aa784ec1aab828af2399fa80b3792e0d6290 100644 (file)
@@ -178,10 +178,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ahd_get_pci_bus(pci),
                ahd_get_pci_slot(pci),
                ahd_get_pci_function(pci));
-       name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+       name = kstrdup(buf, GFP_ATOMIC);
        if (name == NULL)
                return (-ENOMEM);
-       strcpy(name, buf);
        ahd = ahd_alloc(NULL, name);
        if (ahd == NULL)
                return (-ENOMEM);
index ee05e8410754be8c6ae86479d9d2c56b88f0800f..0fc14dac7070ce6bab629c08a2998638fc26553e 100644 (file)
@@ -225,10 +225,9 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ahc_get_pci_bus(pci),
                ahc_get_pci_slot(pci),
                ahc_get_pci_function(pci));
-       name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+       name = kstrdup(buf, GFP_ATOMIC);
        if (name == NULL)
                return (-ENOMEM);
-       strcpy(name, buf);
        ahc = ahc_alloc(NULL, name);
        if (ahc == NULL)
                return (-ENOMEM);
index fd284ff36ecf28fb05581619b1c8ca0e34eac018..86162811812de3d1b6e3102db45bcbc277041fd2 100644 (file)
@@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
        stats->r2t_pdus = conn->r2t_pdus_cnt;
        stats->digest_err = 0;
        stats->timeout_err = 0;
-       stats->custom_length = 0;
+       stats->custom_length = 1;
        strcpy(stats->custom[0].desc, "eh_abort_cnt");
        stats->custom[0].value = conn->eh_abort_cnt;
 }
index 07934b0b9ee100a47b5ac3961b0473759da4257c..a3e56487616c2b5ea37c25010fd6c9d58d12da19 100644 (file)
@@ -1015,7 +1015,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                if (if_info->dhcp_state) {
                        beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
                                    "BG_%d : DHCP Already Enabled\n");
-                       return 0;
+                       goto exit;
                }
                /* The ip_param->len is 1 in DHCP case. Setting
                   proper IP len as this it is used while
@@ -1033,7 +1033,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                                sizeof(*reldhcp));
 
                        if (rc)
-                               return rc;
+                               goto exit;
 
                        reldhcp = nonemb_cmd.va;
                        reldhcp->interface_hndl = phba->interface_handle;
@@ -1044,7 +1044,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                                beiscsi_log(phba, KERN_WARNING,
                                            BEISCSI_LOG_CONFIG,
                                            "BG_%d : Failed to Delete existing dhcp\n");
-                               return rc;
+                               goto exit;
                        }
                }
        }
@@ -1054,7 +1054,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
                                           IP_ACTION_DEL);
                if (rc)
-                       return rc;
+                       goto exit;
        }
 
        /* Delete the Gateway settings if mode change is to DHCP */
@@ -1064,7 +1064,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                if (rc) {
                        beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
                                    "BG_%d : Failed to Get Gateway Addr\n");
-                       return rc;
+                       goto exit;
                }
 
                if (gtway_addr_set.ip_addr.addr[0]) {
@@ -1076,7 +1076,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                                beiscsi_log(phba, KERN_WARNING,
                                            BEISCSI_LOG_CONFIG,
                                            "BG_%d : Failed to clear Gateway Addr Set\n");
-                               return rc;
+                               goto exit;
                        }
                }
        }
@@ -1087,7 +1087,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                        OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
                        sizeof(*dhcpreq));
                if (rc)
-                       return rc;
+                       goto exit;
 
                dhcpreq = nonemb_cmd.va;
                dhcpreq->flags = BLOCKING;
@@ -1095,12 +1095,14 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
                dhcpreq->interface_hndl = phba->interface_handle;
                dhcpreq->ip_type = BE2_DHCP_V4;
 
-               return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+               rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
        } else {
-               return mgmt_static_ip_modify(phba, if_info, ip_param,
+               rc = mgmt_static_ip_modify(phba, if_info, ip_param,
                                             subnet_param, IP_ACTION_ADD);
        }
 
+exit:
+       kfree(if_info);
        return rc;
 }
 
index a3ab5cce4208b4bb924f3ebff7a97a83886f4efe..0f19455951ec37a4d165e9b0bcc03b5c77f9db50 100644 (file)
@@ -81,7 +81,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
        bfa->fcs = BFA_TRUE;
        fcbuild_init();
 
-       for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
                mod = &fcs_modules[i];
                if (mod->attach)
                        mod->attach(fcs);
@@ -97,7 +97,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs)
        int     i;
        struct bfa_fcs_mod_s  *mod;
 
-       for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
                mod = &fcs_modules[i];
                if (mod->modinit)
                        mod->modinit(fcs);
@@ -184,7 +184,7 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
 
        bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
 
-       nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+       nmods = ARRAY_SIZE(fcs_modules);
 
        for (i = 0; i < nmods; i++) {
 
index 2e28392c2fb6e53c8998f5b33b13363385361eed..a38aafa030b35256ede14da888f421d27dc4166d 100644 (file)
@@ -72,7 +72,7 @@ struct bfa_sge_s {
 } while (0)
 
 #define bfa_swap_words(_x)  (  \
-       ((_x) << 32) | ((_x) >> 32))
+       ((u64)(_x) << 32) | ((u64)(_x) >> 32))
 
 #ifdef __BIG_ENDIAN
 #define bfa_sge_to_be(_x)
index 7593b7c1d3367e81a5a323cf5feb7805e1846620..e90a3742f09d9b9b19fea19bfb3e7d1285e8ca99 100644 (file)
@@ -1219,7 +1219,7 @@ bfad_install_msix_handler(struct bfad_s *bfad)
 int
 bfad_setup_intr(struct bfad_s *bfad)
 {
-       int error = 0;
+       int error;
        u32 mask = 0, i, num_bit = 0, max_bit = 0;
        struct msix_entry msix_entries[MAX_MSIX_ENTRY];
        struct pci_dev *pdev = bfad->pcidev;
@@ -1234,34 +1234,24 @@ bfad_setup_intr(struct bfad_s *bfad)
        if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) ||
           (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {
 
-               error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
-               if (error) {
-                       /* In CT1 & CT2, try to allocate just one vector */
-                       if (bfa_asic_id_ctc(pdev->device)) {
-                               printk(KERN_WARNING "bfa %s: trying one msix "
-                                      "vector failed to allocate %d[%d]\n",
-                                      bfad->pci_name, bfad->nvec, error);
-                               bfad->nvec = 1;
-                               error = pci_enable_msix(bfad->pcidev,
-                                               msix_entries, bfad->nvec);
-                       }
+               error = pci_enable_msix_exact(bfad->pcidev,
+                                             msix_entries, bfad->nvec);
+               /* In CT1 & CT2, try to allocate just one vector */
+               if (error == -ENOSPC && bfa_asic_id_ctc(pdev->device)) {
+                       printk(KERN_WARNING "bfa %s: trying one msix "
+                              "vector failed to allocate %d[%d]\n",
+                              bfad->pci_name, bfad->nvec, error);
+                       bfad->nvec = 1;
+                       error = pci_enable_msix_exact(bfad->pcidev,
+                                                     msix_entries, 1);
+               }
 
-                       /*
-                        * Only error number of vector is available.
-                        * We don't have a mechanism to map multiple
-                        * interrupts into one vector, so even if we
-                        * can try to request less vectors, we don't
-                        * know how to associate interrupt events to
-                        *  vectors. Linux doesn't duplicate vectors
-                        * in the MSIX table for this case.
-                        */
-                       if (error) {
-                               printk(KERN_WARNING "bfad%d: "
-                                      "pci_enable_msix failed (%d), "
-                                      "use line based.\n",
-                                       bfad->inst_no, error);
-                               goto line_based;
-                       }
+               if (error) {
+                       printk(KERN_WARNING "bfad%d: "
+                              "pci_enable_msix_exact failed (%d), "
+                              "use line based.\n",
+                               bfad->inst_no, error);
+                       goto line_based;
                }
 
                /* Disable INTX in MSI-X mode */
@@ -1281,20 +1271,18 @@ bfad_setup_intr(struct bfad_s *bfad)
 
                bfad->bfad_flags |= BFAD_MSIX_ON;
 
-               return error;
+               return 0;
        }
 
 line_based:
-       error = 0;
-       if (request_irq
-           (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
-            BFAD_DRIVER_NAME, bfad) != 0) {
-               /* Enable interrupt handler failed */
-               return 1;
-       }
+       error = request_irq(bfad->pcidev->irq, (irq_handler_t)bfad_intx,
+                           BFAD_IRQ_FLAGS, BFAD_DRIVER_NAME, bfad);
+       if (error)
+               return error;
+
        bfad->bfad_flags |= BFAD_INTX_ON;
 
-       return error;
+       return 0;
 }
 
 void
index 8994fb857ee9e6693a1d01e4998cf1b4e544004e..023b9d42ad9a229ebca4876de4336e25d611f59d 100644 (file)
@@ -26,7 +26,6 @@ int
 bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
 {
        struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
-       int     rc = 0;
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -34,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
        if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
                iocmd->status = BFA_STATUS_OK;
-               return rc;
+               return 0;
        }
 
        init_completion(&bfad->enable_comp);
@@ -43,21 +42,20 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        wait_for_completion(&bfad->enable_comp);
 
-       return rc;
+       return 0;
 }
 
 int
 bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
 {
        struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
-       int     rc = 0;
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
                iocmd->status = BFA_STATUS_OK;
-               return rc;
+               return 0;
        }
 
        if (bfad->disable_active) {
@@ -74,7 +72,7 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
        bfad->disable_active = BFA_FALSE;
        iocmd->status = BFA_STATUS_OK;
 
-       return rc;
+       return 0;
 }
 
 static int
@@ -3270,13 +3268,13 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
        /* Allocate dma coherent memory */
        buf_info = buf_base;
        buf_info->size = payload_len;
-       buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
-                                       &buf_info->phys, GFP_KERNEL);
+       buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev,
+                                            buf_info->size, &buf_info->phys,
+                                            GFP_KERNEL);
        if (!buf_info->virt)
                goto out_free_mem;
 
        /* copy the linear bsg buffer to buf_info */
-       memset(buf_info->virt, 0, buf_info->size);
        memcpy(buf_info->virt, payload_kbuf, buf_info->size);
 
        /*
index e1f1e3448f982faf5f7886aeef3604790052ae6b..fe2106c91c08585049da46972d53f8089dc2469f 100644 (file)
@@ -1,3 +1,16 @@
+/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
 #ifndef __57XX_FCOE_HSI_LINUX_LE__
 #define __57XX_FCOE_HSI_LINUX_LE__
 
index cfcad8bde7cf3b1da88b8ceeeb7bac987a3726ac..f245d543d7b1405f060fcd90491382e37739d24b 100644 (file)
@@ -1,5 +1,5 @@
 config SCSI_BNX2X_FCOE
-       tristate "Broadcom NetXtreme II FCoE support"
+       tristate "QLogic NetXtreme II FCoE support"
        depends on PCI
        select NETDEVICES
        select ETHERNET
@@ -8,5 +8,5 @@ config SCSI_BNX2X_FCOE
        select LIBFCOE
        select CNIC
        ---help---
-       This driver supports FCoE offload for the Broadcom NetXtreme II
+       This driver supports FCoE offload for the QLogic NetXtreme II
        devices.
index 6a976657b475dedb8bcca75cd7242839b33f6f72..1346e052e03cc1311792b8a4c9bf3c85565748a6 100644 (file)
@@ -1,8 +1,7 @@
-#ifndef _BNX2FC_H_
-#define _BNX2FC_H_
-/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -11,6 +10,8 @@
  * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
  */
 
+#ifndef _BNX2FC_H_
+#define _BNX2FC_H_
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
index dad9924abbbb61d32cd0efc80f7fe33f24f1a285..e147cc7ee36c5d454de7967f0eabbee7abaf7187 100644 (file)
@@ -1,3 +1,16 @@
+/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
 #ifndef __BNX2FC_CONSTANTS_H_
 #define __BNX2FC_CONSTANTS_H_
 
index 0cbee1b23ee23c3c79c73dca6e9ba8aba80fd118..d055df01faa5b3c18442e09a0806234459b0673e 100644 (file)
@@ -1,3 +1,16 @@
+/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
 #include "bnx2fc.h"
 
 void BNX2FC_IO_DBG(const struct bnx2fc_cmd *io_req, const char *fmt, ...)
index 4808ff99621f263985a81b7f0b859439cd9ae5af..2b9006774f377241565f36137dde0de616697376 100644 (file)
@@ -1,3 +1,16 @@
+/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
 #ifndef __BNX2FC_DEBUG__
 #define __BNX2FC_DEBUG__
 
index b1c9a4f8caee852f2cbf16b3735a7f7d912bb014..ca75c7ca25590cdb15ae562bd9bd87cd28fcce9b 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver.
  * This file contains helper routines that handle ELS requests
  * and responses.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 785d0d71781ee25b6a19aa796b38f7c8691bb8da..79e5c94107a9cc44fe8269f55ab72e8150005e0b 100644 (file)
@@ -1,9 +1,10 @@
-/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver.
  * This file contains the code that interacts with libfc, libfcoe,
  * cnic modules to create FCoE instances, send/receive non-offloaded
  * FIP/FCoE packets, listen to link events etc.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,12 +27,12 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
 
 
 static char version[] =
-               "Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+               "QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \
                " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
 MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -692,7 +693,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
        if (!lport->vport)
                fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
        snprintf(fc_host_symbolic_name(lport->host), 256,
-                "%s (Broadcom %s) v%s over %s",
+                "%s (QLogic %s) v%s over %s",
                BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION,
                interface->netdev->name);
 
@@ -2775,7 +2776,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = {
  */
 static struct scsi_host_template bnx2fc_shost_template = {
        .module                 = THIS_MODULE,
-       .name                   = "Broadcom Offload FCoE Initiator",
+       .name                   = "QLogic Offload FCoE Initiator",
        .queuecommand           = bnx2fc_queuecommand,
        .eh_abort_handler       = bnx2fc_eh_abort,        /* abts */
        .eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
index 512aed3ae4f1c70ba856908e444890f945be784f..c6688d72a846fa61d37324217d924d3f19848f48 100644 (file)
@@ -1,8 +1,9 @@
-/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver.
  * This file contains the code that low level functions that interact
  * with 57712 FCoE firmware.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index e0bb209f3af14a5a28d443b08bfafd9d2741dde3..4c5891e6603874a2de0eb8bd7a137f597977934a 100644 (file)
@@ -1,7 +1,8 @@
-/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver.
  * IO manager and SCSI IO processing.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 6870cf6781d970d1b314f0b452bde14402a5e8ac..c66c708412a6a34a8d0cf3f281641b4a594707c1 100644 (file)
@@ -1,8 +1,9 @@
-/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 3d33767f2f2ca0d715c81dc36759e37d4517df07..917534109a50c67d1fd1ef8a091d059276767fa8 100644 (file)
@@ -1,13 +1,15 @@
-/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
+/* 57xx_iscsi_constants.h: QLogic NetXtreme II iSCSI HSI
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 #ifndef __57XX_ISCSI_CONSTANTS_H_
 #define __57XX_ISCSI_CONSTANTS_H_
index 7052a839b0eae5eccdd81e33b0eee16d82b51438..19b3a97dbacd0b386f74bd2e6e0e1c8cdfaf7cad 100644 (file)
@@ -1,13 +1,15 @@
-/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
+/* 57xx_iscsi_hsi.h: QLogic NetXtreme II iSCSI HSI.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 #ifndef __57XX_ISCSI_HSI_LINUX_LE__
 #define __57XX_ISCSI_HSI_LINUX_LE__
index 01cff1894b6d75bef7f28a310de3de5a0ad48135..44ce54e536e54c4e3c2ef02a2bdd471d6b9c5e32 100644 (file)
@@ -1,5 +1,5 @@
 config SCSI_BNX2_ISCSI
-       tristate "Broadcom NetXtreme II iSCSI support"
+       tristate "QLogic NetXtreme II iSCSI support"
        depends on NET
        depends on PCI
        select SCSI_ISCSI_ATTRS
@@ -8,5 +8,5 @@ config SCSI_BNX2_ISCSI
        select NET_VENDOR_BROADCOM
        select CNIC
        ---help---
-       This driver supports iSCSI offload for the Broadcom NetXtreme II
+       This driver supports iSCSI offload for the QLogic NetXtreme II
        devices.
index c73bbcb63c02049b1147b98829d8a3e4b4c8ebf5..ed7f3228e2349c0e9e1097063429cd18c35d2098 100644 (file)
@@ -1,15 +1,17 @@
-/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i.h: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #ifndef _BNX2I_H_
index d6d491c2f00463c4f3d9f32a900e7b96cc9803b3..fb072cc5e9fdb53f92f318d265313095cd8979e1 100644 (file)
@@ -1,15 +1,17 @@
-/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i_hwi.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include <linux/gfp.h>
index 80c03b452d61960cbe3df5d198fc409e7c49a9e9..c8b410c24cf03215a588e41557b3eaf7faa46c13 100644 (file)
@@ -1,15 +1,17 @@
-/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include "bnx2i.h"
@@ -18,18 +20,18 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME                "bnx2i"
-#define DRV_MODULE_VERSION     "2.7.6.2"
-#define DRV_MODULE_RELDATE     "Jun 06, 2013"
+#define DRV_MODULE_VERSION     "2.7.10.1"
+#define DRV_MODULE_RELDATE     "Jul 16, 2014"
 
 static char version[] =
-               "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
+               "QLogic NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
                " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
 MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
              "Eddie Wai <eddie.wai@broadcom.com>");
 
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/57710/57711/57712"
                   "/57800/57810/57840 iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
index 166543f7ef55d232bfd238bd8cf55db0ed337576..40e22497d2498a4452ed211bcd08372d59c7b909 100644 (file)
@@ -1,16 +1,18 @@
 /*
- * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
+ * bnx2i_iscsi.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include <linux/slab.h>
@@ -1643,12 +1645,11 @@ static void bnx2i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
        stats->r2t_pdus = conn->r2t_pdus_cnt;
        stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
        stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
-       stats->custom_length = 3;
-       strcpy(stats->custom[2].desc, "eh_abort_cnt");
-       stats->custom[2].value = conn->eh_abort_cnt;
        stats->digest_err = 0;
        stats->timeout_err = 0;
-       stats->custom_length = 0;
+       strcpy(stats->custom[0].desc, "eh_abort_cnt");
+       stats->custom[0].value = conn->eh_abort_cnt;
+       stats->custom_length = 1;
 }
 
 
@@ -2249,7 +2250,7 @@ static umode_t bnx2i_attr_is_visible(int param_type, int param)
  */
 static struct scsi_host_template bnx2i_host_template = {
        .module                 = THIS_MODULE,
-       .name                   = "Broadcom Offload iSCSI Initiator",
+       .name                   = "QLogic Offload iSCSI Initiator",
        .proc_name              = "bnx2i",
        .queuecommand           = iscsi_queuecommand,
        .eh_abort_handler       = iscsi_eh_abort,
index a0a3d9fe61fe944a4e108c17c6e578c4fcc7f68f..6d56fd60cb2b2a4f2ec514581cf29cb88110c24f 100644 (file)
@@ -1,13 +1,15 @@
-/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i_sysfs.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2004 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include "bnx2i.h"
index 7d9b54ae7f62f826f503fb8a72870cb1a093321f..a0dd1b67a467ff4f5b704e2f05d876aea6852294 100644 (file)
@@ -257,8 +257,8 @@ int fnic_set_intr_mode(struct fnic *fnic)
            fnic->raw_wq_count >= m &&
            fnic->wq_copy_count >= o &&
            fnic->cq_count >= n + m + o) {
-               if (!pci_enable_msix(fnic->pdev, fnic->msix_entry,
-                                   n + m + o + 1)) {
+               if (!pci_enable_msix_exact(fnic->pdev, fnic->msix_entry,
+                                          n + m + o + 1)) {
                        fnic->rq_count = n;
                        fnic->raw_wq_count = m;
                        fnic->wq_copy_count = o;
index a59e1e022e3716cb13caf2de2e0a9d82636ad20f..8545d1826725bde1aee310f2f4c1469aa11e4c12 100644 (file)
@@ -1708,7 +1708,14 @@ static void complete_scsi_command(struct CommandList *cp)
 
        cmd->result |= ei->ScsiStatus;
 
-       /* copy the sense data whether we need to or not. */
+       scsi_set_resid(cmd, ei->ResidualCnt);
+       if (ei->CommandStatus == 0) {
+               cmd_free(h, cp);
+               cmd->scsi_done(cmd);
+               return;
+       }
+
+       /* copy the sense data */
        if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo))
                sense_data_size = SCSI_SENSE_BUFFERSIZE;
        else
@@ -1717,13 +1724,6 @@ static void complete_scsi_command(struct CommandList *cp)
                sense_data_size = ei->SenseLen;
 
        memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size);
-       scsi_set_resid(cmd, ei->ResidualCnt);
-
-       if (ei->CommandStatus == 0) {
-               cmd_free(h, cp);
-               cmd->scsi_done(cmd);
-               return;
-       }
 
        /* For I/O accelerator commands, copy over some fields to the normal
         * CISS header used below for error handling.
@@ -3686,6 +3686,8 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
                        (((u64) cmd->cmnd[2]) << 8) |
                        cmd->cmnd[3];
                block_cnt = cmd->cmnd[4];
+               if (block_cnt == 0)
+                       block_cnt = 256;
                break;
        case WRITE_10:
                is_write = 1;
@@ -3734,7 +3736,6 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
        default:
                return IO_ACCEL_INELIGIBLE; /* process via normal I/O path */
        }
-       BUG_ON(block_cnt == 0);
        last_block = first_block + block_cnt - 1;
 
        /* check for write to non-RAID-0 */
@@ -5092,7 +5093,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
                }
                if (ioc->Request.Type.Direction & XFER_WRITE) {
                        if (copy_from_user(buff[sg_used], data_ptr, sz)) {
-                               status = -ENOMEM;
+                               status = -EFAULT;
                                goto cleanup1;
                        }
                } else
@@ -6365,9 +6366,9 @@ static inline void hpsa_set_driver_support_bits(struct ctlr_info *h)
 {
        u32 driver_support;
 
-#ifdef CONFIG_X86
-       /* Need to enable prefetch in the SCSI core for 6400 in x86 */
        driver_support = readl(&(h->cfgtable->driver_support));
+       /* Need to enable prefetch in the SCSI core for 6400 in x86 */
+#ifdef CONFIG_X86
        driver_support |= ENABLE_SCSI_PREFETCH;
 #endif
        driver_support |= ENABLE_UNIT_ATTN;
@@ -6913,8 +6914,12 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
                d = list_entry(this, struct offline_device_entry,
                                offline_list);
                spin_unlock_irqrestore(&h->offline_device_lock, flags);
-               if (!hpsa_volume_offline(h, d->scsi3addr))
+               if (!hpsa_volume_offline(h, d->scsi3addr)) {
+                       spin_lock_irqsave(&h->offline_device_lock, flags);
+                       list_del(&d->offline_list);
+                       spin_unlock_irqrestore(&h->offline_device_lock, flags);
                        return 1;
+               }
                spin_lock_irqsave(&h->offline_device_lock, flags);
        }
        spin_unlock_irqrestore(&h->offline_device_lock, flags);
@@ -6995,8 +7000,10 @@ reinit_after_soft_reset:
 
        /* Allocate and clear per-cpu variable lockup_detected */
        h->lockup_detected = alloc_percpu(u32);
-       if (!h->lockup_detected)
+       if (!h->lockup_detected) {
+               rc = -ENOMEM;
                goto clean1;
+       }
        set_lockup_detected_for_all_cpus(h, 0);
 
        rc = hpsa_pci_init(h);
index 6eb47b683569c1161551bf84444732126b8812ac..598c42cba5a86ab939f8a81ade1057dd8eb512f7 100644 (file)
@@ -166,13 +166,13 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)
        switch (entry->fmt) {
        case IBMVFC_CMD_FORMAT:
                entry->op_code = vfc_cmd->iu.cdb[0];
-               entry->scsi_id = vfc_cmd->tgt_scsi_id;
+               entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
                entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
                entry->tmf_flags = vfc_cmd->iu.tmf_flags;
-               entry->u.start.xfer_len = vfc_cmd->iu.xfer_len;
+               entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len);
                break;
        case IBMVFC_MAD_FORMAT:
-               entry->op_code = mad->opcode;
+               entry->op_code = be32_to_cpu(mad->opcode);
                break;
        default:
                break;
@@ -199,18 +199,18 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)
        switch (entry->fmt) {
        case IBMVFC_CMD_FORMAT:
                entry->op_code = vfc_cmd->iu.cdb[0];
-               entry->scsi_id = vfc_cmd->tgt_scsi_id;
+               entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
                entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
                entry->tmf_flags = vfc_cmd->iu.tmf_flags;
-               entry->u.end.status = vfc_cmd->status;
-               entry->u.end.error = vfc_cmd->error;
+               entry->u.end.status = be16_to_cpu(vfc_cmd->status);
+               entry->u.end.error = be16_to_cpu(vfc_cmd->error);
                entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags;
                entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code;
                entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status;
                break;
        case IBMVFC_MAD_FORMAT:
-               entry->op_code = mad->opcode;
-               entry->u.end.status = mad->status;
+               entry->op_code = be32_to_cpu(mad->opcode);
+               entry->u.end.status = be16_to_cpu(mad->status);
                break;
        default:
                break;
@@ -270,14 +270,14 @@ static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd)
 {
        int err;
        struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
-       int fc_rsp_len = rsp->fcp_rsp_len;
+       int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
 
        if ((rsp->flags & FCP_RSP_LEN_VALID) &&
            ((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) ||
             rsp->data.info.rsp_code))
                return DID_ERROR << 16;
 
-       err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
+       err = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
        if (err >= 0)
                return rsp->scsi_status | (cmd_status[err].result << 16);
        return rsp->scsi_status | (DID_ERROR << 16);
@@ -807,7 +807,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
                evt->cmnd->result = (error_code << 16);
                evt->done = ibmvfc_scsi_eh_done;
        } else
-               evt->xfer_iu->mad_common.status = IBMVFC_MAD_DRIVER_FAILED;
+               evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED);
 
        list_del(&evt->queue);
        del_timer(&evt->timer);
@@ -955,7 +955,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost)
 
        spin_lock_irqsave(shost->host_lock, flags);
        if (vhost->state == IBMVFC_ACTIVE) {
-               switch (vhost->login_buf->resp.link_speed / 100) {
+               switch (be64_to_cpu(vhost->login_buf->resp.link_speed) / 100) {
                case 1:
                        fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
                        break;
@@ -976,7 +976,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost)
                        break;
                default:
                        ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n",
-                                  vhost->login_buf->resp.link_speed / 100);
+                                  be64_to_cpu(vhost->login_buf->resp.link_speed) / 100);
                        fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
                        break;
                }
@@ -1171,21 +1171,21 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
 
        memset(login_info, 0, sizeof(*login_info));
 
-       login_info->ostype = IBMVFC_OS_LINUX;
-       login_info->max_dma_len = IBMVFC_MAX_SECTORS << 9;
-       login_info->max_payload = sizeof(struct ibmvfc_fcp_cmd_iu);
-       login_info->max_response = sizeof(struct ibmvfc_fcp_rsp);
-       login_info->partition_num = vhost->partition_number;
-       login_info->vfc_frame_version = 1;
-       login_info->fcp_version = 3;
-       login_info->flags = IBMVFC_FLUSH_ON_HALT;
+       login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX);
+       login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9);
+       login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu));
+       login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp));
+       login_info->partition_num = cpu_to_be32(vhost->partition_number);
+       login_info->vfc_frame_version = cpu_to_be32(1);
+       login_info->fcp_version = cpu_to_be16(3);
+       login_info->flags = cpu_to_be16(IBMVFC_FLUSH_ON_HALT);
        if (vhost->client_migrated)
-               login_info->flags |= IBMVFC_CLIENT_MIGRATED;
+               login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED);
 
-       login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
-       login_info->capabilities = IBMVFC_CAN_MIGRATE;
-       login_info->async.va = vhost->async_crq.msg_token;
-       login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
+       login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ);
+       login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE);
+       login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
+       login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs));
        strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
        strncpy(login_info->device_name,
                dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
@@ -1225,7 +1225,7 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
                struct ibmvfc_event *evt = &pool->events[i];
                atomic_set(&evt->free, 1);
                evt->crq.valid = 0x80;
-               evt->crq.ioba = pool->iu_token + (sizeof(*evt->xfer_iu) * i);
+               evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i));
                evt->xfer_iu = pool->iu_storage + i;
                evt->vhost = vhost;
                evt->ext_list = NULL;
@@ -1310,8 +1310,8 @@ static void ibmvfc_map_sg_list(struct scsi_cmnd *scmd, int nseg,
        struct scatterlist *sg;
 
        scsi_for_each_sg(scmd, sg, nseg, i) {
-               md[i].va = sg_dma_address(sg);
-               md[i].len = sg_dma_len(sg);
+               md[i].va = cpu_to_be64(sg_dma_address(sg));
+               md[i].len = cpu_to_be32(sg_dma_len(sg));
                md[i].key = 0;
        }
 }
@@ -1337,7 +1337,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
 
        sg_mapped = scsi_dma_map(scmd);
        if (!sg_mapped) {
-               vfc_cmd->flags |= IBMVFC_NO_MEM_DESC;
+               vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC);
                return 0;
        } else if (unlikely(sg_mapped < 0)) {
                if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
@@ -1346,10 +1346,10 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
        }
 
        if (scmd->sc_data_direction == DMA_TO_DEVICE) {
-               vfc_cmd->flags |= IBMVFC_WRITE;
+               vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE);
                vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA;
        } else {
-               vfc_cmd->flags |= IBMVFC_READ;
+               vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ);
                vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA;
        }
 
@@ -1358,7 +1358,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
                return 0;
        }
 
-       vfc_cmd->flags |= IBMVFC_SCATTERLIST;
+       vfc_cmd->flags |= cpu_to_be16(IBMVFC_SCATTERLIST);
 
        if (!evt->ext_list) {
                evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC,
@@ -1374,8 +1374,8 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
 
        ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list);
 
-       data->va = evt->ext_list_token;
-       data->len = sg_mapped * sizeof(struct srp_direct_buf);
+       data->va = cpu_to_be64(evt->ext_list_token);
+       data->len = cpu_to_be32(sg_mapped * sizeof(struct srp_direct_buf));
        data->key = 0;
        return 0;
 }
@@ -1404,15 +1404,15 @@ static void ibmvfc_timeout(struct ibmvfc_event *evt)
 static int ibmvfc_send_event(struct ibmvfc_event *evt,
                             struct ibmvfc_host *vhost, unsigned long timeout)
 {
-       u64 *crq_as_u64 = (u64 *) &evt->crq;
+       __be64 *crq_as_u64 = (__be64 *) &evt->crq;
        int rc;
 
        /* Copy the IU into the transfer area */
        *evt->xfer_iu = evt->iu;
        if (evt->crq.format == IBMVFC_CMD_FORMAT)
-               evt->xfer_iu->cmd.tag = (u64)evt;
+               evt->xfer_iu->cmd.tag = cpu_to_be64((u64)evt);
        else if (evt->crq.format == IBMVFC_MAD_FORMAT)
-               evt->xfer_iu->mad_common.tag = (u64)evt;
+               evt->xfer_iu->mad_common.tag = cpu_to_be64((u64)evt);
        else
                BUG();
 
@@ -1428,7 +1428,8 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
 
        mb();
 
-       if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) {
+       if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
+                                 be64_to_cpu(crq_as_u64[1])))) {
                list_del(&evt->queue);
                del_timer(&evt->timer);
 
@@ -1451,7 +1452,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
                        evt->cmnd->result = DID_ERROR << 16;
                        evt->done = ibmvfc_scsi_eh_done;
                } else
-                       evt->xfer_iu->mad_common.status = IBMVFC_MAD_CRQ_ERROR;
+                       evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR);
 
                evt->done(evt);
        } else
@@ -1472,7 +1473,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
        struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
        struct scsi_cmnd *cmnd = evt->cmnd;
        const char *err = unknown_error;
-       int index = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
+       int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
        int logerr = 0;
        int rsp_code = 0;
 
@@ -1526,13 +1527,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
        struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
        struct scsi_cmnd *cmnd = evt->cmnd;
        u32 rsp_len = 0;
-       u32 sense_len = rsp->fcp_sense_len;
+       u32 sense_len = be32_to_cpu(rsp->fcp_sense_len);
 
        if (cmnd) {
-               if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID)
-                       scsi_set_resid(cmnd, vfc_cmd->adapter_resid);
+               if (be16_to_cpu(vfc_cmd->response_flags) & IBMVFC_ADAPTER_RESID_VALID)
+                       scsi_set_resid(cmnd, be32_to_cpu(vfc_cmd->adapter_resid));
                else if (rsp->flags & FCP_RESID_UNDER)
-                       scsi_set_resid(cmnd, rsp->fcp_resid);
+                       scsi_set_resid(cmnd, be32_to_cpu(rsp->fcp_resid));
                else
                        scsi_set_resid(cmnd, 0);
 
@@ -1540,12 +1541,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
                        cmnd->result = ibmvfc_get_err_result(vfc_cmd);
 
                        if (rsp->flags & FCP_RSP_LEN_VALID)
-                               rsp_len = rsp->fcp_rsp_len;
+                               rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
                        if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE)
                                sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
                        if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
                                memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
-                       if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED))
+                       if ((be16_to_cpu(vfc_cmd->status) & IBMVFC_VIOS_FAILURE) &&
+                           (be16_to_cpu(vfc_cmd->error) == IBMVFC_PLOGI_REQUIRED))
                                ibmvfc_relogin(cmnd->device);
 
                        if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER)))
@@ -1630,19 +1632,19 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
        cmnd->scsi_done = done;
        vfc_cmd = &evt->iu.cmd;
        memset(vfc_cmd, 0, sizeof(*vfc_cmd));
-       vfc_cmd->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
-       vfc_cmd->resp.len = sizeof(vfc_cmd->rsp);
-       vfc_cmd->frame_type = IBMVFC_SCSI_FCP_TYPE;
-       vfc_cmd->payload_len = sizeof(vfc_cmd->iu);
-       vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
-       vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
-       vfc_cmd->tgt_scsi_id = rport->port_id;
-       vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
+       vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+       vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp));
+       vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+       vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu));
+       vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp));
+       vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata);
+       vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id);
+       vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd));
        int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
        memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
 
        if (scsi_populate_tag_msg(cmnd, tag)) {
-               vfc_cmd->task_tag = tag[1];
+               vfc_cmd->task_tag = cpu_to_be64(tag[1]);
                switch (tag[0]) {
                case MSG_SIMPLE_TAG:
                        vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
@@ -1732,12 +1734,12 @@ static int ibmvfc_bsg_timeout(struct fc_bsg_job *job)
 
        tmf = &evt->iu.tmf;
        memset(tmf, 0, sizeof(*tmf));
-       tmf->common.version = 1;
-       tmf->common.opcode = IBMVFC_TMF_MAD;
-       tmf->common.length = sizeof(*tmf);
-       tmf->scsi_id = port_id;
-       tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
-       tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY;
+       tmf->common.version = cpu_to_be32(1);
+       tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+       tmf->common.length = cpu_to_be16(sizeof(*tmf));
+       tmf->scsi_id = cpu_to_be64(port_id);
+       tmf->cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY);
+       tmf->my_cancel_key = cpu_to_be32(IBMVFC_INTERNAL_CANCEL_KEY);
        rc = ibmvfc_send_event(evt, vhost, default_timeout);
 
        if (rc != 0) {
@@ -1789,10 +1791,10 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id)
        ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
        plogi = &evt->iu.plogi;
        memset(plogi, 0, sizeof(*plogi));
-       plogi->common.version = 1;
-       plogi->common.opcode = IBMVFC_PORT_LOGIN;
-       plogi->common.length = sizeof(*plogi);
-       plogi->scsi_id = port_id;
+       plogi->common.version = cpu_to_be32(1);
+       plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN);
+       plogi->common.length = cpu_to_be16(sizeof(*plogi));
+       plogi->scsi_id = cpu_to_be64(port_id);
        evt->sync_iu = &rsp_iu;
        init_completion(&evt->comp);
 
@@ -1904,26 +1906,26 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job)
        mad = &evt->iu.passthru;
 
        memset(mad, 0, sizeof(*mad));
-       mad->common.version = 1;
-       mad->common.opcode = IBMVFC_PASSTHRU;
-       mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
-
-       mad->cmd_ioba.va = (u64)evt->crq.ioba +
-               offsetof(struct ibmvfc_passthru_mad, iu);
-       mad->cmd_ioba.len = sizeof(mad->iu);
-
-       mad->iu.cmd_len = job->request_payload.payload_len;
-       mad->iu.rsp_len = job->reply_payload.payload_len;
-       mad->iu.flags = fc_flags;
-       mad->iu.cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
-
-       mad->iu.cmd.va = sg_dma_address(job->request_payload.sg_list);
-       mad->iu.cmd.len = sg_dma_len(job->request_payload.sg_list);
-       mad->iu.rsp.va = sg_dma_address(job->reply_payload.sg_list);
-       mad->iu.rsp.len = sg_dma_len(job->reply_payload.sg_list);
-       mad->iu.scsi_id = port_id;
-       mad->iu.tag = (u64)evt;
-       rsp_len = mad->iu.rsp.len;
+       mad->common.version = cpu_to_be32(1);
+       mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU);
+       mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu));
+
+       mad->cmd_ioba.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) +
+               offsetof(struct ibmvfc_passthru_mad, iu));
+       mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu));
+
+       mad->iu.cmd_len = cpu_to_be32(job->request_payload.payload_len);
+       mad->iu.rsp_len = cpu_to_be32(job->reply_payload.payload_len);
+       mad->iu.flags = cpu_to_be32(fc_flags);
+       mad->iu.cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY);
+
+       mad->iu.cmd.va = cpu_to_be64(sg_dma_address(job->request_payload.sg_list));
+       mad->iu.cmd.len = cpu_to_be32(sg_dma_len(job->request_payload.sg_list));
+       mad->iu.rsp.va = cpu_to_be64(sg_dma_address(job->reply_payload.sg_list));
+       mad->iu.rsp.len = cpu_to_be32(sg_dma_len(job->reply_payload.sg_list));
+       mad->iu.scsi_id = cpu_to_be64(port_id);
+       mad->iu.tag = cpu_to_be64((u64)evt);
+       rsp_len = be32_to_cpu(mad->iu.rsp.len);
 
        evt->sync_iu = &rsp_iu;
        init_completion(&evt->comp);
@@ -1986,15 +1988,15 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
 
                tmf = &evt->iu.cmd;
                memset(tmf, 0, sizeof(*tmf));
-               tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
-               tmf->resp.len = sizeof(tmf->rsp);
-               tmf->frame_type = IBMVFC_SCSI_FCP_TYPE;
-               tmf->payload_len = sizeof(tmf->iu);
-               tmf->resp_len = sizeof(tmf->rsp);
-               tmf->cancel_key = (unsigned long)sdev->hostdata;
-               tmf->tgt_scsi_id = rport->port_id;
+               tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+               tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp));
+               tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+               tmf->payload_len = cpu_to_be32(sizeof(tmf->iu));
+               tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp));
+               tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+               tmf->tgt_scsi_id = cpu_to_be64(rport->port_id);
                int_to_scsilun(sdev->lun, &tmf->iu.lun);
-               tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF);
+               tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
                tmf->iu.tmf_flags = type;
                evt->sync_iu = &rsp_iu;
 
@@ -2020,8 +2022,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
                        rsp_code = fc_rsp->data.info.rsp_code;
 
                sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) "
-                           "flags: %x fcp_rsp: %x, scsi_status: %x\n",
-                           desc, ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error),
+                           "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc,
+                           ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
                            rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
                            fc_rsp->scsi_status);
                rsp_rc = -EIO;
@@ -2185,19 +2187,19 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
 
                tmf = &evt->iu.tmf;
                memset(tmf, 0, sizeof(*tmf));
-               tmf->common.version = 1;
-               tmf->common.opcode = IBMVFC_TMF_MAD;
-               tmf->common.length = sizeof(*tmf);
-               tmf->scsi_id = rport->port_id;
+               tmf->common.version = cpu_to_be32(1);
+               tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+               tmf->common.length = cpu_to_be16(sizeof(*tmf));
+               tmf->scsi_id = cpu_to_be64(rport->port_id);
                int_to_scsilun(sdev->lun, &tmf->lun);
-               if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS))
+               if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS))
                        type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
                if (vhost->state == IBMVFC_ACTIVE)
-                       tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+                       tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID));
                else
-                       tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID);
-               tmf->cancel_key = (unsigned long)sdev->hostdata;
-               tmf->my_cancel_key = (unsigned long)starget->hostdata;
+                       tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID));
+               tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+               tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata);
 
                evt->sync_iu = &rsp;
                init_completion(&evt->comp);
@@ -2217,7 +2219,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
        sdev_printk(KERN_INFO, sdev, "Cancelling outstanding commands.\n");
 
        wait_for_completion(&evt->comp);
-       status = rsp.mad_common.status;
+       status = be16_to_cpu(rsp.mad_common.status);
        spin_lock_irqsave(vhost->host->host_lock, flags);
        ibmvfc_free_event(evt);
        spin_unlock_irqrestore(vhost->host->host_lock, flags);
@@ -2252,7 +2254,7 @@ static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key)
        unsigned long cancel_key = (unsigned long)key;
 
        if (evt->crq.format == IBMVFC_CMD_FORMAT &&
-           evt->iu.cmd.cancel_key == cancel_key)
+           be32_to_cpu(evt->iu.cmd.cancel_key) == cancel_key)
                return 1;
        return 0;
 }
@@ -2316,15 +2318,15 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
 
                tmf = &evt->iu.cmd;
                memset(tmf, 0, sizeof(*tmf));
-               tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
-               tmf->resp.len = sizeof(tmf->rsp);
-               tmf->frame_type = IBMVFC_SCSI_FCP_TYPE;
-               tmf->payload_len = sizeof(tmf->iu);
-               tmf->resp_len = sizeof(tmf->rsp);
-               tmf->cancel_key = (unsigned long)sdev->hostdata;
-               tmf->tgt_scsi_id = rport->port_id;
+               tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+               tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp));
+               tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+               tmf->payload_len = cpu_to_be32(sizeof(tmf->iu));
+               tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp));
+               tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+               tmf->tgt_scsi_id = cpu_to_be64(rport->port_id);
                int_to_scsilun(sdev->lun, &tmf->iu.lun);
-               tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF);
+               tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
                tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET;
                evt->sync_iu = &rsp_iu;
 
@@ -2380,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
 
                sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) "
                            "flags: %x fcp_rsp: %x, scsi_status: %x\n",
-                           ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error),
+                           ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
                            rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
                            fc_rsp->scsi_status);
                rsp_rc = -EIO;
@@ -2641,14 +2643,14 @@ static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state)
 static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
                                struct ibmvfc_host *vhost)
 {
-       const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event);
+       const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(be64_to_cpu(crq->event));
        struct ibmvfc_target *tgt;
 
        ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
                   " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
                   ibmvfc_get_link_state(crq->link_state));
 
-       switch (crq->event) {
+       switch (be64_to_cpu(crq->event)) {
        case IBMVFC_AE_RESUME:
                switch (crq->link_state) {
                case IBMVFC_AE_LS_LINK_DOWN:
@@ -2691,15 +2693,15 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
                list_for_each_entry(tgt, &vhost->targets, queue) {
                        if (!crq->scsi_id && !crq->wwpn && !crq->node_name)
                                break;
-                       if (crq->scsi_id && tgt->scsi_id != crq->scsi_id)
+                       if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) != crq->scsi_id)
                                continue;
-                       if (crq->wwpn && tgt->ids.port_name != crq->wwpn)
+                       if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) != crq->wwpn)
                                continue;
-                       if (crq->node_name && tgt->ids.node_name != crq->node_name)
+                       if (crq->node_name && cpu_to_be64(tgt->ids.node_name) != crq->node_name)
                                continue;
-                       if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO)
+                       if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO)
                                tgt->logo_rcvd = 1;
-                       if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) {
+                       if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) {
                                ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
                                ibmvfc_reinit_host(vhost);
                        }
@@ -2730,7 +2732,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
 static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
 {
        long rc;
-       struct ibmvfc_event *evt = (struct ibmvfc_event *)crq->ioba;
+       struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba);
 
        switch (crq->valid) {
        case IBMVFC_CRQ_INIT_RSP:
@@ -3336,7 +3338,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
        struct ibmvfc_host *vhost = evt->vhost;
        struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli;
        struct ibmvfc_prli_svc_parms *parms = &rsp->parms;
-       u32 status = rsp->common.status;
+       u32 status = be16_to_cpu(rsp->common.status);
        int index, level = IBMVFC_DEFAULT_LOG_LEVEL;
 
        vhost->discovery_threads--;
@@ -3347,14 +3349,14 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
                        parms->type, parms->flags, parms->service_parms);
 
                if (parms->type == IBMVFC_SCSI_FCP_TYPE) {
-                       index = ibmvfc_get_prli_rsp(parms->flags);
+                       index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags));
                        if (prli_rsp[index].logged_in) {
-                               if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) {
+                               if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) {
                                        tgt->need_login = 0;
                                        tgt->ids.roles = 0;
-                                       if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC)
+                                       if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_TARGET_FUNC)
                                                tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
-                                       if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
+                                       if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_INITIATOR_FUNC)
                                                tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
                                        tgt->add_rport = 1;
                                } else
@@ -3373,17 +3375,18 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
                break;
        case IBMVFC_MAD_FAILED:
        default:
-               if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED)
+               if ((be16_to_cpu(rsp->status) & IBMVFC_VIOS_FAILURE) &&
+                    be16_to_cpu(rsp->error) == IBMVFC_PLOGI_REQUIRED)
                        level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
                else if (tgt->logo_rcvd)
                        level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
-               else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+               else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
                        level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
                else
                        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
                tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
-                       ibmvfc_get_cmd_error(rsp->status, rsp->error),
+                       ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
                        rsp->status, rsp->error, status);
                break;
        };
@@ -3414,14 +3417,14 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
        evt->tgt = tgt;
        prli = &evt->iu.prli;
        memset(prli, 0, sizeof(*prli));
-       prli->common.version = 1;
-       prli->common.opcode = IBMVFC_PROCESS_LOGIN;
-       prli->common.length = sizeof(*prli);
-       prli->scsi_id = tgt->scsi_id;
+       prli->common.version = cpu_to_be32(1);
+       prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN);
+       prli->common.length = cpu_to_be16(sizeof(*prli));
+       prli->scsi_id = cpu_to_be64(tgt->scsi_id);
 
        prli->parms.type = IBMVFC_SCSI_FCP_TYPE;
-       prli->parms.flags = IBMVFC_PRLI_EST_IMG_PAIR;
-       prli->parms.service_parms = IBMVFC_PRLI_INITIATOR_FUNC;
+       prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR);
+       prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC);
 
        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
        if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3442,7 +3445,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
        struct ibmvfc_target *tgt = evt->tgt;
        struct ibmvfc_host *vhost = evt->vhost;
        struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi;
-       u32 status = rsp->common.status;
+       u32 status = be16_to_cpu(rsp->common.status);
        int level = IBMVFC_DEFAULT_LOG_LEVEL;
 
        vhost->discovery_threads--;
@@ -3472,15 +3475,15 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
                break;
        case IBMVFC_MAD_FAILED:
        default:
-               if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+               if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
                        level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
                else
                        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
                tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-                       ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
-                       ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
-                       ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status);
+                       ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error,
+                       ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type,
+                       ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status);
                break;
        };
 
@@ -3512,10 +3515,10 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt)
        evt->tgt = tgt;
        plogi = &evt->iu.plogi;
        memset(plogi, 0, sizeof(*plogi));
-       plogi->common.version = 1;
-       plogi->common.opcode = IBMVFC_PORT_LOGIN;
-       plogi->common.length = sizeof(*plogi);
-       plogi->scsi_id = tgt->scsi_id;
+       plogi->common.version = cpu_to_be32(1);
+       plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN);
+       plogi->common.length = cpu_to_be16(sizeof(*plogi));
+       plogi->scsi_id = cpu_to_be64(tgt->scsi_id);
 
        if (ibmvfc_send_event(evt, vhost, default_timeout)) {
                vhost->discovery_threads--;
@@ -3535,7 +3538,7 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt)
        struct ibmvfc_target *tgt = evt->tgt;
        struct ibmvfc_host *vhost = evt->vhost;
        struct ibmvfc_implicit_logout *rsp = &evt->xfer_iu->implicit_logout;
-       u32 status = rsp->common.status;
+       u32 status = be16_to_cpu(rsp->common.status);
 
        vhost->discovery_threads--;
        ibmvfc_free_event(evt);
@@ -3585,10 +3588,10 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
        evt->tgt = tgt;
        mad = &evt->iu.implicit_logout;
        memset(mad, 0, sizeof(*mad));
-       mad->common.version = 1;
-       mad->common.opcode = IBMVFC_IMPLICIT_LOGOUT;
-       mad->common.length = sizeof(*mad);
-       mad->old_scsi_id = tgt->scsi_id;
+       mad->common.version = cpu_to_be32(1);
+       mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT);
+       mad->common.length = cpu_to_be16(sizeof(*mad));
+       mad->old_scsi_id = cpu_to_be64(tgt->scsi_id);
 
        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
        if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3616,7 +3619,7 @@ static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad,
        if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
                   sizeof(tgt->ids.node_name)))
                return 1;
-       if (mad->fc_iu.response[6] != tgt->scsi_id)
+       if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id)
                return 1;
        return 0;
 }
@@ -3631,7 +3634,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
        struct ibmvfc_target *tgt = evt->tgt;
        struct ibmvfc_host *vhost = evt->vhost;
        struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
-       u32 status = mad->common.status;
+       u32 status = be16_to_cpu(mad->common.status);
        u8 fc_reason, fc_explain;
 
        vhost->discovery_threads--;
@@ -3649,10 +3652,10 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
        case IBMVFC_MAD_FAILED:
        default:
                ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
-               fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
-               fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
+               fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16;
+               fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8;
                tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-                        ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error),
+                        ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)),
                         mad->iu.status, mad->iu.error,
                         ibmvfc_get_fc_type(fc_reason), fc_reason,
                         ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
@@ -3674,22 +3677,22 @@ static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
        struct ibmvfc_passthru_mad *mad = &evt->iu.passthru;
 
        memset(mad, 0, sizeof(*mad));
-       mad->common.version = 1;
-       mad->common.opcode = IBMVFC_PASSTHRU;
-       mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
-       mad->cmd_ioba.va = (u64)evt->crq.ioba +
-               offsetof(struct ibmvfc_passthru_mad, iu);
-       mad->cmd_ioba.len = sizeof(mad->iu);
-       mad->iu.cmd_len = sizeof(mad->fc_iu.payload);
-       mad->iu.rsp_len = sizeof(mad->fc_iu.response);
-       mad->iu.cmd.va = (u64)evt->crq.ioba +
+       mad->common.version = cpu_to_be32(1);
+       mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU);
+       mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu));
+       mad->cmd_ioba.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
+               offsetof(struct ibmvfc_passthru_mad, iu));
+       mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu));
+       mad->iu.cmd_len = cpu_to_be32(sizeof(mad->fc_iu.payload));
+       mad->iu.rsp_len = cpu_to_be32(sizeof(mad->fc_iu.response));
+       mad->iu.cmd.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
                offsetof(struct ibmvfc_passthru_mad, fc_iu) +
-               offsetof(struct ibmvfc_passthru_fc_iu, payload);
-       mad->iu.cmd.len = sizeof(mad->fc_iu.payload);
-       mad->iu.rsp.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_fc_iu, payload));
+       mad->iu.cmd.len = cpu_to_be32(sizeof(mad->fc_iu.payload));
+       mad->iu.rsp.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
                offsetof(struct ibmvfc_passthru_mad, fc_iu) +
-               offsetof(struct ibmvfc_passthru_fc_iu, response);
-       mad->iu.rsp.len = sizeof(mad->fc_iu.response);
+               offsetof(struct ibmvfc_passthru_fc_iu, response));
+       mad->iu.rsp.len = cpu_to_be32(sizeof(mad->fc_iu.response));
 }
 
 /**
@@ -3748,11 +3751,11 @@ static void ibmvfc_adisc_timeout(struct ibmvfc_target *tgt)
        evt->tgt = tgt;
        tmf = &evt->iu.tmf;
        memset(tmf, 0, sizeof(*tmf));
-       tmf->common.version = 1;
-       tmf->common.opcode = IBMVFC_TMF_MAD;
-       tmf->common.length = sizeof(*tmf);
-       tmf->scsi_id = tgt->scsi_id;
-       tmf->cancel_key = tgt->cancel_key;
+       tmf->common.version = cpu_to_be32(1);
+       tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+       tmf->common.length = cpu_to_be16(sizeof(*tmf));
+       tmf->scsi_id = cpu_to_be64(tgt->scsi_id);
+       tmf->cancel_key = cpu_to_be32(tgt->cancel_key);
 
        rc = ibmvfc_send_event(evt, vhost, default_timeout);
 
@@ -3794,16 +3797,16 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
 
        ibmvfc_init_passthru(evt);
        mad = &evt->iu.passthru;
-       mad->iu.flags = IBMVFC_FC_ELS;
-       mad->iu.scsi_id = tgt->scsi_id;
-       mad->iu.cancel_key = tgt->cancel_key;
+       mad->iu.flags = cpu_to_be32(IBMVFC_FC_ELS);
+       mad->iu.scsi_id = cpu_to_be64(tgt->scsi_id);
+       mad->iu.cancel_key = cpu_to_be32(tgt->cancel_key);
 
-       mad->fc_iu.payload[0] = IBMVFC_ADISC;
+       mad->fc_iu.payload[0] = cpu_to_be32(IBMVFC_ADISC);
        memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
               sizeof(vhost->login_buf->resp.port_name));
        memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name,
               sizeof(vhost->login_buf->resp.node_name));
-       mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
+       mad->fc_iu.payload[6] = cpu_to_be32(be64_to_cpu(vhost->login_buf->resp.scsi_id) & 0x00ffffff);
 
        if (timer_pending(&tgt->timer))
                mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ));
@@ -3834,7 +3837,7 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
        struct ibmvfc_target *tgt = evt->tgt;
        struct ibmvfc_host *vhost = evt->vhost;
        struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt;
-       u32 status = rsp->common.status;
+       u32 status = be16_to_cpu(rsp->common.status);
        int level = IBMVFC_DEFAULT_LOG_LEVEL;
 
        vhost->discovery_threads--;
@@ -3842,8 +3845,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
        switch (status) {
        case IBMVFC_MAD_SUCCESS:
                tgt_dbg(tgt, "Query Target succeeded\n");
-               tgt->new_scsi_id = rsp->scsi_id;
-               if (rsp->scsi_id != tgt->scsi_id)
+               tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id);
+               if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id)
                        ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
                else
                        ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
@@ -3855,19 +3858,20 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
                break;
        case IBMVFC_MAD_FAILED:
        default:
-               if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
-                   rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ &&
-                   rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG)
+               if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
+                   be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ &&
+                   be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG)
                        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
-               else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+               else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
                        level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target);
                else
                        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
                tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-                       ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
-                       ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
-                       ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status);
+                       ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+                       rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)),
+                       rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)),
+                       rsp->fc_explain, status);
                break;
        };
 
@@ -3897,10 +3901,10 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt)
        ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT);
        query_tgt = &evt->iu.query_tgt;
        memset(query_tgt, 0, sizeof(*query_tgt));
-       query_tgt->common.version = 1;
-       query_tgt->common.opcode = IBMVFC_QUERY_TARGET;
-       query_tgt->common.length = sizeof(*query_tgt);
-       query_tgt->wwpn = tgt->ids.port_name;
+       query_tgt->common.version = cpu_to_be32(1);
+       query_tgt->common.opcode = cpu_to_be32(IBMVFC_QUERY_TARGET);
+       query_tgt->common.length = cpu_to_be16(sizeof(*query_tgt));
+       query_tgt->wwpn = cpu_to_be64(tgt->ids.port_name);
 
        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
        if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3971,7 +3975,8 @@ static int ibmvfc_alloc_targets(struct ibmvfc_host *vhost)
 
        for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++)
                rc = ibmvfc_alloc_target(vhost,
-                                        vhost->disc_buf->scsi_id[i] & IBMVFC_DISC_TGT_SCSI_ID_MASK);
+                                        be32_to_cpu(vhost->disc_buf->scsi_id[i]) &
+                                        IBMVFC_DISC_TGT_SCSI_ID_MASK);
 
        return rc;
 }
@@ -3985,19 +3990,20 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
 {
        struct ibmvfc_host *vhost = evt->vhost;
        struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets;
-       u32 mad_status = rsp->common.status;
+       u32 mad_status = be16_to_cpu(rsp->common.status);
        int level = IBMVFC_DEFAULT_LOG_LEVEL;
 
        switch (mad_status) {
        case IBMVFC_MAD_SUCCESS:
                ibmvfc_dbg(vhost, "Discover Targets succeeded\n");
-               vhost->num_targets = rsp->num_written;
+               vhost->num_targets = be32_to_cpu(rsp->num_written);
                ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS);
                break;
        case IBMVFC_MAD_FAILED:
                level += ibmvfc_retry_host_init(vhost);
                ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n",
-                          ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
+                          ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+                          rsp->status, rsp->error);
                break;
        case IBMVFC_MAD_DRIVER_FAILED:
                break;
@@ -4024,12 +4030,12 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
        ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT);
        mad = &evt->iu.discover_targets;
        memset(mad, 0, sizeof(*mad));
-       mad->common.version = 1;
-       mad->common.opcode = IBMVFC_DISC_TARGETS;
-       mad->common.length = sizeof(*mad);
-       mad->bufflen = vhost->disc_buf_sz;
-       mad->buffer.va = vhost->disc_buf_dma;
-       mad->buffer.len = vhost->disc_buf_sz;
+       mad->common.version = cpu_to_be32(1);
+       mad->common.opcode = cpu_to_be32(IBMVFC_DISC_TARGETS);
+       mad->common.length = cpu_to_be16(sizeof(*mad));
+       mad->bufflen = cpu_to_be32(vhost->disc_buf_sz);
+       mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma);
+       mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz);
        ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
 
        if (!ibmvfc_send_event(evt, vhost, default_timeout))
@@ -4046,7 +4052,7 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
 static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
 {
        struct ibmvfc_host *vhost = evt->vhost;
-       u32 mad_status = evt->xfer_iu->npiv_login.common.status;
+       u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_login.common.status);
        struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp;
        unsigned int npiv_max_sectors;
        int level = IBMVFC_DEFAULT_LOG_LEVEL;
@@ -4056,12 +4062,13 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
                ibmvfc_free_event(evt);
                break;
        case IBMVFC_MAD_FAILED:
-               if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+               if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
                        level += ibmvfc_retry_host_init(vhost);
                else
                        ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
                ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n",
-                          ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
+                          ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+                                               rsp->status, rsp->error);
                ibmvfc_free_event(evt);
                return;
        case IBMVFC_MAD_CRQ_ERROR:
@@ -4078,7 +4085,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
 
        vhost->client_migrated = 0;
 
-       if (!(rsp->flags & IBMVFC_NATIVE_FC)) {
+       if (!(be32_to_cpu(rsp->flags) & IBMVFC_NATIVE_FC)) {
                dev_err(vhost->dev, "Virtual adapter does not support FC. %x\n",
                        rsp->flags);
                ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
@@ -4086,7 +4093,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
                return;
        }
 
-       if (rsp->max_cmds <= IBMVFC_NUM_INTERNAL_REQ) {
+       if (be32_to_cpu(rsp->max_cmds) <= IBMVFC_NUM_INTERNAL_REQ) {
                dev_err(vhost->dev, "Virtual adapter supported queue depth too small: %d\n",
                        rsp->max_cmds);
                ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
@@ -4095,27 +4102,27 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
        }
 
        vhost->logged_in = 1;
-       npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS);
+       npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS);
        dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n",
                 rsp->partition_name, rsp->device_name, rsp->port_loc_code,
                 rsp->drc_name, npiv_max_sectors);
 
-       fc_host_fabric_name(vhost->host) = rsp->node_name;
-       fc_host_node_name(vhost->host) = rsp->node_name;
-       fc_host_port_name(vhost->host) = rsp->port_name;
-       fc_host_port_id(vhost->host) = rsp->scsi_id;
+       fc_host_fabric_name(vhost->host) = be64_to_cpu(rsp->node_name);
+       fc_host_node_name(vhost->host) = be64_to_cpu(rsp->node_name);
+       fc_host_port_name(vhost->host) = be64_to_cpu(rsp->port_name);
+       fc_host_port_id(vhost->host) = be64_to_cpu(rsp->scsi_id);
        fc_host_port_type(vhost->host) = FC_PORTTYPE_NPIV;
        fc_host_supported_classes(vhost->host) = 0;
-       if (rsp->service_parms.class1_parms[0] & 0x80000000)
+       if (be32_to_cpu(rsp->service_parms.class1_parms[0]) & 0x80000000)
                fc_host_supported_classes(vhost->host) |= FC_COS_CLASS1;
-       if (rsp->service_parms.class2_parms[0] & 0x80000000)
+       if (be32_to_cpu(rsp->service_parms.class2_parms[0]) & 0x80000000)
                fc_host_supported_classes(vhost->host) |= FC_COS_CLASS2;
-       if (rsp->service_parms.class3_parms[0] & 0x80000000)
+       if (be32_to_cpu(rsp->service_parms.class3_parms[0]) & 0x80000000)
                fc_host_supported_classes(vhost->host) |= FC_COS_CLASS3;
        fc_host_maxframe_size(vhost->host) =
-               rsp->service_parms.common.bb_rcv_sz & 0x0fff;
+               be16_to_cpu(rsp->service_parms.common.bb_rcv_sz) & 0x0fff;
 
-       vhost->host->can_queue = rsp->max_cmds - IBMVFC_NUM_INTERNAL_REQ;
+       vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ;
        vhost->host->max_sectors = npiv_max_sectors;
        ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
        wake_up(&vhost->work_wait_q);
@@ -4138,11 +4145,11 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
        memcpy(vhost->login_buf, &vhost->login_info, sizeof(vhost->login_info));
        mad = &evt->iu.npiv_login;
        memset(mad, 0, sizeof(struct ibmvfc_npiv_login_mad));
-       mad->common.version = 1;
-       mad->common.opcode = IBMVFC_NPIV_LOGIN;
-       mad->common.length = sizeof(struct ibmvfc_npiv_login_mad);
-       mad->buffer.va = vhost->login_buf_dma;
-       mad->buffer.len = sizeof(*vhost->login_buf);
+       mad->common.version = cpu_to_be32(1);
+       mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGIN);
+       mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_login_mad));
+       mad->buffer.va = cpu_to_be64(vhost->login_buf_dma);
+       mad->buffer.len = cpu_to_be32(sizeof(*vhost->login_buf));
 
        ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
 
@@ -4160,7 +4167,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
 static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt)
 {
        struct ibmvfc_host *vhost = evt->vhost;
-       u32 mad_status = evt->xfer_iu->npiv_logout.common.status;
+       u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_logout.common.status);
 
        ibmvfc_free_event(evt);
 
@@ -4199,9 +4206,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost)
 
        mad = &evt->iu.npiv_logout;
        memset(mad, 0, sizeof(*mad));
-       mad->common.version = 1;
-       mad->common.opcode = IBMVFC_NPIV_LOGOUT;
-       mad->common.length = sizeof(struct ibmvfc_npiv_logout_mad);
+       mad->common.version = cpu_to_be32(1);
+       mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGOUT);
+       mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_logout_mad));
 
        ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO_WAIT);
 
@@ -4343,14 +4350,14 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
        if (rport) {
                tgt_dbg(tgt, "rport add succeeded\n");
                tgt->rport = rport;
-               rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
+               rport->maxframe_size = be16_to_cpu(tgt->service_parms.common.bb_rcv_sz) & 0x0fff;
                rport->supported_classes = 0;
                tgt->target_id = rport->scsi_target_id;
-               if (tgt->service_parms.class1_parms[0] & 0x80000000)
+               if (be32_to_cpu(tgt->service_parms.class1_parms[0]) & 0x80000000)
                        rport->supported_classes |= FC_COS_CLASS1;
-               if (tgt->service_parms.class2_parms[0] & 0x80000000)
+               if (be32_to_cpu(tgt->service_parms.class2_parms[0]) & 0x80000000)
                        rport->supported_classes |= FC_COS_CLASS2;
-               if (tgt->service_parms.class3_parms[0] & 0x80000000)
+               if (be32_to_cpu(tgt->service_parms.class3_parms[0]) & 0x80000000)
                        rport->supported_classes |= FC_COS_CLASS3;
                if (rport->rqst_q)
                        blk_queue_max_segments(rport->rqst_q, 1);
index 017a5290e8c12ba5d27c89a390c4ed6490e05000..8fae03215a85d2d26920146617cbfc68c8a845ed 100644 (file)
@@ -135,12 +135,12 @@ enum ibmvfc_mad_types {
 };
 
 struct ibmvfc_mad_common {
-       u32 version;
-       u32 reserved;
-       u32 opcode;
-       u16 status;
-       u16 length;
-       u64 tag;
+       __be32 version;
+       __be32 reserved;
+       __be32 opcode;
+       __be16 status;
+       __be16 length;
+       __be64 tag;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_npiv_login_mad {
@@ -155,76 +155,76 @@ struct ibmvfc_npiv_logout_mad {
 #define IBMVFC_MAX_NAME 256
 
 struct ibmvfc_npiv_login {
-       u32 ostype;
+       __be32 ostype;
 #define IBMVFC_OS_LINUX        0x02
-       u32 pad;
-       u64 max_dma_len;
-       u32 max_payload;
-       u32 max_response;
-       u32 partition_num;
-       u32 vfc_frame_version;
-       u16 fcp_version;
-       u16 flags;
+       __be32 pad;
+       __be64 max_dma_len;
+       __be32 max_payload;
+       __be32 max_response;
+       __be32 partition_num;
+       __be32 vfc_frame_version;
+       __be16 fcp_version;
+       __be16 flags;
 #define IBMVFC_CLIENT_MIGRATED 0x01
 #define IBMVFC_FLUSH_ON_HALT           0x02
-       u32 max_cmds;
-       u64 capabilities;
+       __be32 max_cmds;
+       __be64 capabilities;
 #define IBMVFC_CAN_MIGRATE             0x01
-       u64 node_name;
+       __be64 node_name;
        struct srp_direct_buf async;
        u8 partition_name[IBMVFC_MAX_NAME];
        u8 device_name[IBMVFC_MAX_NAME];
        u8 drc_name[IBMVFC_MAX_NAME];
-       u64 reserved2[2];
+       __be64 reserved2[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_common_svc_parms {
-       u16 fcph_version;
-       u16 b2b_credit;
-       u16 features;
-       u16 bb_rcv_sz; /* upper nibble is BB_SC_N */
-       u32 ratov;
-       u32 edtov;
+       __be16 fcph_version;
+       __be16 b2b_credit;
+       __be16 features;
+       __be16 bb_rcv_sz; /* upper nibble is BB_SC_N */
+       __be32 ratov;
+       __be32 edtov;
 }__attribute__((packed, aligned (4)));
 
 struct ibmvfc_service_parms {
        struct ibmvfc_common_svc_parms common;
        u8 port_name[8];
        u8 node_name[8];
-       u32 class1_parms[4];
-       u32 class2_parms[4];
-       u32 class3_parms[4];
-       u32 obsolete[4];
-       u32 vendor_version[4];
-       u32 services_avail[2];
-       u32 ext_len;
-       u32 reserved[30];
-       u32 clk_sync_qos[2];
+       __be32 class1_parms[4];
+       __be32 class2_parms[4];
+       __be32 class3_parms[4];
+       __be32 obsolete[4];
+       __be32 vendor_version[4];
+       __be32 services_avail[2];
+       __be32 ext_len;
+       __be32 reserved[30];
+       __be32 clk_sync_qos[2];
 }__attribute__((packed, aligned (4)));
 
 struct ibmvfc_npiv_login_resp {
-       u32 version;
-       u16 status;
-       u16 error;
-       u32 flags;
+       __be32 version;
+       __be16 status;
+       __be16 error;
+       __be32 flags;
 #define IBMVFC_NATIVE_FC               0x01
-       u32 reserved;
-       u64 capabilities;
+       __be32 reserved;
+       __be64 capabilities;
 #define IBMVFC_CAN_FLUSH_ON_HALT       0x08
 #define IBMVFC_CAN_SUPPRESS_ABTS       0x10
-       u32 max_cmds;
-       u32 scsi_id_sz;
-       u64 max_dma_len;
-       u64 scsi_id;
-       u64 port_name;
-       u64 node_name;
-       u64 link_speed;
+       __be32 max_cmds;
+       __be32 scsi_id_sz;
+       __be64 max_dma_len;
+       __be64 scsi_id;
+       __be64 port_name;
+       __be64 node_name;
+       __be64 link_speed;
        u8 partition_name[IBMVFC_MAX_NAME];
        u8 device_name[IBMVFC_MAX_NAME];
        u8 port_loc_code[IBMVFC_MAX_NAME];
        u8 drc_name[IBMVFC_MAX_NAME];
        struct ibmvfc_service_parms service_parms;
-       u64 reserved2;
+       __be64 reserved2;
 }__attribute__((packed, aligned (8)));
 
 union ibmvfc_npiv_login_data {
@@ -233,20 +233,20 @@ union ibmvfc_npiv_login_data {
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_discover_targets_buf {
-       u32 scsi_id[1];
+       __be32 scsi_id[1];
 #define IBMVFC_DISC_TGT_SCSI_ID_MASK   0x00ffffff
 };
 
 struct ibmvfc_discover_targets {
        struct ibmvfc_mad_common common;
        struct srp_direct_buf buffer;
-       u32 flags;
-       u16 status;
-       u16 error;
-       u32 bufflen;
-       u32 num_avail;
-       u32 num_written;
-       u64 reserved[2];
+       __be32 flags;
+       __be16 status;
+       __be16 error;
+       __be32 bufflen;
+       __be32 num_avail;
+       __be32 num_written;
+       __be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 enum ibmvfc_fc_reason {
@@ -278,32 +278,32 @@ enum ibmvfc_gs_explain {
 
 struct ibmvfc_port_login {
        struct ibmvfc_mad_common common;
-       u64 scsi_id;
-       u16 reserved;
-       u16 fc_service_class;
-       u32 blksz;
-       u32 hdr_per_blk;
-       u16 status;
-       u16 error;              /* also fc_reason */
-       u16 fc_explain;
-       u16 fc_type;
-       u32 reserved2;
+       __be64 scsi_id;
+       __be16 reserved;
+       __be16 fc_service_class;
+       __be32 blksz;
+       __be32 hdr_per_blk;
+       __be16 status;
+       __be16 error;           /* also fc_reason */
+       __be16 fc_explain;
+       __be16 fc_type;
+       __be32 reserved2;
        struct ibmvfc_service_parms service_parms;
        struct ibmvfc_service_parms service_parms_change;
-       u64 reserved3[2];
+       __be64 reserved3[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_prli_svc_parms {
        u8 type;
 #define IBMVFC_SCSI_FCP_TYPE           0x08
        u8 type_ext;
-       u16 flags;
+       __be16 flags;
 #define IBMVFC_PRLI_ORIG_PA_VALID                      0x8000
 #define IBMVFC_PRLI_RESP_PA_VALID                      0x4000
 #define IBMVFC_PRLI_EST_IMG_PAIR                       0x2000
-       u32 orig_pa;
-       u32 resp_pa;
-       u32 service_parms;
+       __be32 orig_pa;
+       __be32 resp_pa;
+       __be32 service_parms;
 #define IBMVFC_PRLI_TASK_RETRY                 0x00000200
 #define IBMVFC_PRLI_RETRY                              0x00000100
 #define IBMVFC_PRLI_DATA_OVERLAY                       0x00000040
@@ -315,47 +315,47 @@ struct ibmvfc_prli_svc_parms {
 
 struct ibmvfc_process_login {
        struct ibmvfc_mad_common common;
-       u64 scsi_id;
+       __be64 scsi_id;
        struct ibmvfc_prli_svc_parms parms;
        u8 reserved[48];
-       u16 status;
-       u16 error;                      /* also fc_reason */
-       u32 reserved2;
-       u64 reserved3[2];
+       __be16 status;
+       __be16 error;                   /* also fc_reason */
+       __be32 reserved2;
+       __be64 reserved3[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_query_tgt {
        struct ibmvfc_mad_common common;
-       u64 wwpn;
-       u64 scsi_id;
-       u16 status;
-       u16 error;
-       u16 fc_explain;
-       u16 fc_type;
-       u64 reserved[2];
+       __be64 wwpn;
+       __be64 scsi_id;
+       __be16 status;
+       __be16 error;
+       __be16 fc_explain;
+       __be16 fc_type;
+       __be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_implicit_logout {
        struct ibmvfc_mad_common common;
-       u64 old_scsi_id;
-       u64 reserved[2];
+       __be64 old_scsi_id;
+       __be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_tmf {
        struct ibmvfc_mad_common common;
-       u64 scsi_id;
+       __be64 scsi_id;
        struct scsi_lun lun;
-       u32 flags;
+       __be32 flags;
 #define IBMVFC_TMF_ABORT_TASK          0x02
 #define IBMVFC_TMF_ABORT_TASK_SET      0x04
 #define IBMVFC_TMF_LUN_RESET           0x10
 #define IBMVFC_TMF_TGT_RESET           0x20
 #define IBMVFC_TMF_LUA_VALID           0x40
 #define IBMVFC_TMF_SUPPRESS_ABTS       0x80
-       u32 cancel_key;
-       u32 my_cancel_key;
-       u32 pad;
-       u64 reserved[2];
+       __be32 cancel_key;
+       __be32 my_cancel_key;
+       __be32 pad;
+       __be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 enum ibmvfc_fcp_rsp_info_codes {
@@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes {
 };
 
 struct ibmvfc_fcp_rsp_info {
-       u16 reserved;
+       __be16 reserved;
        u8 rsp_code;
        u8 reserved2[4];
 }__attribute__((packed, aligned (2)));
@@ -388,13 +388,13 @@ union ibmvfc_fcp_rsp_data {
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_fcp_rsp {
-       u64 reserved;
-       u16 retry_delay_timer;
+       __be64 reserved;
+       __be16 retry_delay_timer;
        u8 flags;
        u8 scsi_status;
-       u32 fcp_resid;
-       u32 fcp_sense_len;
-       u32 fcp_rsp_len;
+       __be32 fcp_resid;
+       __be32 fcp_sense_len;
+       __be32 fcp_rsp_len;
        union ibmvfc_fcp_rsp_data data;
 }__attribute__((packed, aligned (8)));
 
@@ -429,58 +429,58 @@ struct ibmvfc_fcp_cmd_iu {
 #define IBMVFC_RDDATA          0x02
 #define IBMVFC_WRDATA          0x01
        u8 cdb[IBMVFC_MAX_CDB_LEN];
-       u32 xfer_len;
+       __be32 xfer_len;
 }__attribute__((packed, aligned (4)));
 
 struct ibmvfc_cmd {
-       u64 task_tag;
-       u32 frame_type;
-       u32 payload_len;
-       u32 resp_len;
-       u32 adapter_resid;
-       u16 status;
-       u16 error;
-       u16 flags;
-       u16 response_flags;
+       __be64 task_tag;
+       __be32 frame_type;
+       __be32 payload_len;
+       __be32 resp_len;
+       __be32 adapter_resid;
+       __be16 status;
+       __be16 error;
+       __be16 flags;
+       __be16 response_flags;
 #define IBMVFC_ADAPTER_RESID_VALID     0x01
-       u32 cancel_key;
-       u32 exchange_id;
+       __be32 cancel_key;
+       __be32 exchange_id;
        struct srp_direct_buf ext_func;
        struct srp_direct_buf ioba;
        struct srp_direct_buf resp;
-       u64 correlation;
-       u64 tgt_scsi_id;
-       u64 tag;
-       u64 reserved3[2];
+       __be64 correlation;
+       __be64 tgt_scsi_id;
+       __be64 tag;
+       __be64 reserved3[2];
        struct ibmvfc_fcp_cmd_iu iu;
        struct ibmvfc_fcp_rsp rsp;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_passthru_fc_iu {
-       u32 payload[7];
+       __be32 payload[7];
 #define IBMVFC_ADISC   0x52000000
-       u32 response[7];
+       __be32 response[7];
 };
 
 struct ibmvfc_passthru_iu {
-       u64 task_tag;
-       u32 cmd_len;
-       u32 rsp_len;
-       u16 status;
-       u16 error;
-       u32 flags;
+       __be64 task_tag;
+       __be32 cmd_len;
+       __be32 rsp_len;
+       __be16 status;
+       __be16 error;
+       __be32 flags;
 #define IBMVFC_FC_ELS          0x01
 #define IBMVFC_FC_CT_IU                0x02
-       u32 cancel_key;
+       __be32 cancel_key;
 #define IBMVFC_PASSTHRU_CANCEL_KEY     0x80000000
 #define IBMVFC_INTERNAL_CANCEL_KEY     0x80000001
-       u32 reserved;
+       __be32 reserved;
        struct srp_direct_buf cmd;
        struct srp_direct_buf rsp;
-       u64 correlation;
-       u64 scsi_id;
-       u64 tag;
-       u64 reserved2[2];
+       __be64 correlation;
+       __be64 scsi_id;
+       __be64 tag;
+       __be64 reserved2[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_passthru_mad {
@@ -552,7 +552,7 @@ struct ibmvfc_crq {
        volatile u8 valid;
        volatile u8 format;
        u8 reserved[6];
-       volatile u64 ioba;
+       volatile __be64 ioba;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_crq_queue {
@@ -572,12 +572,12 @@ struct ibmvfc_async_crq {
        volatile u8 valid;
        u8 link_state;
        u8 pad[2];
-       u32 pad2;
-       volatile u64 event;
-       volatile u64 scsi_id;
-       volatile u64 wwpn;
-       volatile u64 node_name;
-       u64 reserved;
+       __be32 pad2;
+       volatile __be64 event;
+       volatile __be64 scsi_id;
+       volatile __be64 wwpn;
+       volatile __be64 node_name;
+       __be64 reserved;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_async_crq_queue {
index 695b34e9154e2bec2ec8493e3111f099840ed739..4198e45ea941edb856bbb25e7254dca102e2ec94 100644 (file)
@@ -356,7 +356,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
        for (i = 0; i < num_msix; i++)
                pci_info->msix_entries[i].entry = i;
 
-       err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix);
+       err = pci_enable_msix_exact(pdev, pci_info->msix_entries, num_msix);
        if (err)
                goto intx;
 
index 06f9a5b79e66d226c8c2e447b924f7d2ed554aa6..a5769a9960ac0be0154bfa542144205f9e7408e9 100644 (file)
@@ -8242,7 +8242,7 @@ lpfc_sli_enable_msix(struct lpfc_hba *phba)
        if (rc) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0420 PCI enable MSI-X failed (%d)\n", rc);
-               goto msi_fail_out;
+               goto vec_fail_out;
        }
        for (i = 0; i < LPFC_MSIX_VECTORS; i++)
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
@@ -8320,6 +8320,8 @@ irq_fail_out:
 msi_fail_out:
        /* Unconfigure MSI-X capability structure */
        pci_disable_msix(phba->pcidev);
+
+vec_fail_out:
        return rc;
 }
 
@@ -8812,7 +8814,7 @@ enable_msix_vectors:
        } else if (rc) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0484 PCI enable MSI-X failed (%d)\n", rc);
-               goto msi_fail_out;
+               goto vec_fail_out;
        }
 
        /* Log MSI-X vector assignment */
@@ -8875,9 +8877,10 @@ cfg_fail_out:
                         &phba->sli4_hba.fcp_eq_hdl[index]);
        }
 
-msi_fail_out:
        /* Unconfigure MSI-X capability structure */
        pci_disable_msix(phba->pcidev);
+
+vec_fail_out:
        return rc;
 }
 
index 8b88118e20e6cb0bcb0e1145761908b49da01be9..2f262be890c556bea4b4a3a84e15c93968dc0505 100644 (file)
@@ -277,7 +277,7 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
        ioc->fault_reset_work_q = NULL;
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
        if (wq) {
-               if (!cancel_delayed_work(&ioc->fault_reset_work))
+               if (!cancel_delayed_work_sync(&ioc->fault_reset_work))
                        flush_workqueue(wq);
                destroy_workqueue(wq);
        }
@@ -1332,53 +1332,35 @@ _base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector)
 static void
 _base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc)
 {
-       struct adapter_reply_queue *reply_q;
-       int cpu_id;
-       int cpu_grouping, loop, grouping, grouping_mod;
+       unsigned int cpu, nr_cpus, nr_msix, index = 0;
 
        if (!_base_is_controller_msix_enabled(ioc))
                return;
 
        memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
-       /* when there are more cpus than available msix vectors,
-        * then group cpus togeather on same irq
-        */
-       if (ioc->cpu_count > ioc->msix_vector_count) {
-               grouping = ioc->cpu_count / ioc->msix_vector_count;
-               grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
-               if (grouping < 2 || (grouping == 2 && !grouping_mod))
-                       cpu_grouping = 2;
-               else if (grouping < 4 || (grouping == 4 && !grouping_mod))
-                       cpu_grouping = 4;
-               else if (grouping < 8 || (grouping == 8 && !grouping_mod))
-                       cpu_grouping = 8;
-               else
-                       cpu_grouping = 16;
-       } else
-               cpu_grouping = 0;
-
-       loop = 0;
-       reply_q = list_entry(ioc->reply_queue_list.next,
-            struct adapter_reply_queue, list);
-       for_each_online_cpu(cpu_id) {
-               if (!cpu_grouping) {
-                       ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
-                       reply_q = list_entry(reply_q->list.next,
-                           struct adapter_reply_queue, list);
-               } else {
-                       if (loop < cpu_grouping) {
-                               ioc->cpu_msix_table[cpu_id] =
-                                       reply_q->msix_index;
-                               loop++;
-                       } else {
-                               reply_q = list_entry(reply_q->list.next,
-                                   struct adapter_reply_queue, list);
-                               ioc->cpu_msix_table[cpu_id] =
-                                       reply_q->msix_index;
-                               loop = 1;
-                       }
+
+       nr_cpus = num_online_cpus();
+       nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
+                                              ioc->facts.MaxMSIxVectors);
+       if (!nr_msix)
+               return;
+
+       cpu = cpumask_first(cpu_online_mask);
+
+       do {
+               unsigned int i, group = nr_cpus / nr_msix;
+
+               if (index < nr_cpus % nr_msix)
+                       group++;
+
+               for (i = 0 ; i < group ; i++) {
+                       ioc->cpu_msix_table[cpu] = index;
+                       cpu = cpumask_next(cpu, cpu_online_mask);
                }
-       }
+
+               index++;
+
+       } while (cpu < nr_cpus);
 }
 
 /**
@@ -4295,12 +4277,13 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
                goto out_free_resources;
 
        if (ioc->is_warpdrive) {
-               ioc->reply_post_host_index[0] =
-                   (resource_size_t *)&ioc->chip->ReplyPostHostIndex;
+               ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
+                   &ioc->chip->ReplyPostHostIndex;
 
                for (i = 1; i < ioc->cpu_msix_table_sz; i++)
-                       ioc->reply_post_host_index[i] = (resource_size_t *)
-                       ((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+                       ioc->reply_post_host_index[i] =
+                       (resource_size_t __iomem *)
+                       ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
                        * 4)));
        }
 
index fd3b998c75b1cfa37ede0887f3725d13567ba7c9..0ac5815a7f911c0cfdd41806fde0dd0ec252ddc7 100644 (file)
@@ -837,7 +837,7 @@ struct MPT2SAS_ADAPTER {
        u8              msix_enable;
        u16             msix_vector_count;
        u8              *cpu_msix_table;
-       resource_size_t **reply_post_host_index;
+       resource_size_t __iomem **reply_post_host_index;
        u16             cpu_msix_table_sz;
        u32             ioc_reset_count;
        MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
index 5055f925d2cd772e97502479dea9eb1c67faf46c..dd461015813f8450bc53a2c2d9581548ec7cef00 100644 (file)
@@ -173,7 +173,7 @@ struct fw_event_work {
        u8                      VP_ID;
        u8                      ignore;
        u16                     event;
-       void                    *event_data;
+       char                    event_data[0] __aligned(4);
 };
 
 /* raid transport support */
@@ -1292,7 +1292,8 @@ _scsih_target_alloc(struct scsi_target *starget)
        unsigned long flags;
        struct sas_rphy *rphy;
 
-       sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
+       sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
+                                      GFP_KERNEL);
        if (!sas_target_priv_data)
                return -ENOMEM;
 
@@ -1406,7 +1407,8 @@ _scsih_slave_alloc(struct scsi_device *sdev)
        struct _sas_device *sas_device;
        unsigned long flags;
 
-       sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
+       sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
+                                      GFP_KERNEL);
        if (!sas_device_priv_data)
                return -ENOMEM;
 
@@ -2832,7 +2834,6 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
 
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
        list_del(&fw_event->list);
-       kfree(fw_event->event_data);
        kfree(fw_event);
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
@@ -2899,11 +2900,10 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
                return;
 
        list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
-               if (cancel_delayed_work(&fw_event->delayed_work)) {
+               if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
                        _scsih_fw_event_free(ioc, fw_event);
                        continue;
                }
-               fw_event->cancel_pending_work = 1;
        }
 }
 
@@ -3518,7 +3518,8 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
                if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
                    fw_event->ignore)
                        continue;
-               local_event_data = fw_event->event_data;
+               local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
+                       fw_event->event_data;
                if (local_event_data->ExpStatus ==
                    MPI2_EVENT_SAS_TOPO_ES_ADDED ||
                    local_event_data->ExpStatus ==
@@ -5502,7 +5503,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
        u64 sas_address;
        unsigned long flags;
        u8 link_rate, prev_link_rate;
-       Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
+       Mpi2EventDataSasTopologyChangeList_t *event_data =
+               (Mpi2EventDataSasTopologyChangeList_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5697,7 +5700,8 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
        u64 sas_address;
        unsigned long flags;
        Mpi2EventDataSasDeviceStatusChange_t *event_data =
-           fw_event->event_data;
+               (Mpi2EventDataSasDeviceStatusChange_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5792,6 +5796,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
 #ifdef CONFIG_SCSI_MPT2SAS_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
 }
@@ -5816,7 +5821,9 @@ _scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc,
        u32 termination_count;
        u32 query_count;
        Mpi2SCSITaskManagementReply_t *mpi_reply;
-       Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
+       Mpi2EventDataSasBroadcastPrimitive_t *event_data =
+               (Mpi2EventDataSasBroadcastPrimitive_t *)
+               fw_event->event_data;
        u16 ioc_status;
        unsigned long flags;
        int r;
@@ -5967,7 +5974,9 @@ static void
 _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
     struct fw_event_work *fw_event)
 {
-       Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
+       Mpi2EventDataSasDiscovery_t *event_data =
+               (Mpi2EventDataSasDiscovery_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
@@ -6355,7 +6364,9 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
        Mpi2EventIrConfigElement_t *element;
        int i;
        u8 foreign_config;
-       Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrConfigChangeList_t *event_data =
+               (Mpi2EventDataIrConfigChangeList_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -6423,7 +6434,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
        u16 handle;
        u32 state;
        int rc;
-       Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrVolume_t *event_data =
+               (Mpi2EventDataIrVolume_t *)
+               fw_event->event_data;
 
        if (ioc->shost_recovery)
                return;
@@ -6507,7 +6520,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
        Mpi2ConfigReply_t mpi_reply;
        Mpi2SasDevicePage0_t sas_device_pg0;
        u32 ioc_status;
-       Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrPhysicalDisk_t *event_data =
+               (Mpi2EventDataIrPhysicalDisk_t *)
+               fw_event->event_data;
        u64 sas_address;
 
        if (ioc->shost_recovery)
@@ -6630,7 +6645,9 @@ static void
 _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
     struct fw_event_work *fw_event)
 {
-       Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrOperationStatus_t *event_data =
+               (Mpi2EventDataIrOperationStatus_t *)
+               fw_event->event_data;
        static struct _raid_device *raid_device;
        unsigned long flags;
        u16 handle;
@@ -7401,7 +7418,7 @@ _firmware_event_work(struct work_struct *work)
        struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
 
        /* the queue is being flushed so ignore this event */
-       if (ioc->remove_host || fw_event->cancel_pending_work ||
+       if (ioc->remove_host ||
            ioc->pci_error_recovery) {
                _scsih_fw_event_free(ioc, fw_event);
                return;
@@ -7590,23 +7607,15 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
                return;
        }
 
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
-       if (!fw_event) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
        sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
-       fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
-       if (!fw_event->event_data) {
+       fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
+       if (!fw_event) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
-               kfree(fw_event);
                return;
        }
 
-       memcpy(fw_event->event_data, mpi_reply->EventData,
-           sz);
+       memcpy(fw_event->event_data, mpi_reply->EventData, sz);
        fw_event->ioc = ioc;
        fw_event->VF_ID = mpi_reply->VF_ID;
        fw_event->VP_ID = mpi_reply->VP_ID;
@@ -7857,9 +7866,9 @@ _scsih_remove(struct pci_dev *pdev)
        }
 
        sas_remove_host(shost);
+       scsi_remove_host(shost);
        mpt2sas_base_detach(ioc);
        list_del(&ioc->list);
-       scsi_remove_host(shost);
        scsi_host_put(shost);
 }
 
@@ -8200,13 +8209,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                }
        }
 
-       if ((scsi_add_host(shost, &pdev->dev))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               list_del(&ioc->list);
-               goto out_add_shost_fail;
-       }
-
        /* register EEDP capabilities with SCSI layer */
        if (prot_mask)
                scsi_host_set_prot(shost, prot_mask);
@@ -8248,16 +8250,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                }
        } else
                ioc->hide_drives = 0;
+
+       if ((scsi_add_host(shost, &pdev->dev))) {
+               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_add_shost_fail;
+       }
+
        scsi_scan_host(shost);
 
        return 0;
 
+ out_add_shost_fail:
+       mpt2sas_base_detach(ioc);
  out_attach_fail:
        destroy_workqueue(ioc->firmware_event_thread);
  out_thread_fail:
        list_del(&ioc->list);
-       scsi_remove_host(shost);
- out_add_shost_fail:
        scsi_host_put(shost);
        return -ENODEV;
 }
index 0cf4f7000f94db8439fb99490ddeaa26f86d0fdd..93ce2b2baa41f0ce3c4509906978ba6e1afc0432 100644 (file)
@@ -266,7 +266,7 @@ mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc)
        ioc->fault_reset_work_q = NULL;
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
        if (wq) {
-               if (!cancel_delayed_work(&ioc->fault_reset_work))
+               if (!cancel_delayed_work_sync(&ioc->fault_reset_work))
                        flush_workqueue(wq);
                destroy_workqueue(wq);
        }
@@ -1624,66 +1624,35 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
 static void
 _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
 {
-       struct adapter_reply_queue *reply_q;
-       int cpu_id;
-       int cpu_grouping, loop, grouping, grouping_mod;
-       int reply_queue;
+       unsigned int cpu, nr_cpus, nr_msix, index = 0;
 
        if (!_base_is_controller_msix_enabled(ioc))
                return;
 
        memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
 
-       /* NUMA Hardware bug workaround - drop to less reply queues */
-       if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) {
-               ioc->reply_queue_count = ioc->facts.MaxMSIxVectors;
-               reply_queue = 0;
-               list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-                       reply_q->msix_index = reply_queue;
-                       if (++reply_queue == ioc->reply_queue_count)
-                               reply_queue = 0;
-               }
-       }
+       nr_cpus = num_online_cpus();
+       nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
+                                              ioc->facts.MaxMSIxVectors);
+       if (!nr_msix)
+               return;
 
-       /* when there are more cpus than available msix vectors,
-        * then group cpus togeather on same irq
-        */
-       if (ioc->cpu_count > ioc->msix_vector_count) {
-               grouping = ioc->cpu_count / ioc->msix_vector_count;
-               grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
-               if (grouping < 2 || (grouping == 2 && !grouping_mod))
-                       cpu_grouping = 2;
-               else if (grouping < 4 || (grouping == 4 && !grouping_mod))
-                       cpu_grouping = 4;
-               else if (grouping < 8 || (grouping == 8 && !grouping_mod))
-                       cpu_grouping = 8;
-               else
-                       cpu_grouping = 16;
-       } else
-               cpu_grouping = 0;
-
-       loop = 0;
-       reply_q = list_entry(ioc->reply_queue_list.next,
-            struct adapter_reply_queue, list);
-       for_each_online_cpu(cpu_id) {
-               if (!cpu_grouping) {
-                       ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
-                       reply_q = list_entry(reply_q->list.next,
-                           struct adapter_reply_queue, list);
-               } else {
-                       if (loop < cpu_grouping) {
-                               ioc->cpu_msix_table[cpu_id] =
-                                   reply_q->msix_index;
-                               loop++;
-                       } else {
-                               reply_q = list_entry(reply_q->list.next,
-                                   struct adapter_reply_queue, list);
-                               ioc->cpu_msix_table[cpu_id] =
-                                   reply_q->msix_index;
-                               loop = 1;
-                       }
+       cpu = cpumask_first(cpu_online_mask);
+
+       do {
+               unsigned int i, group = nr_cpus / nr_msix;
+
+               if (index < nr_cpus % nr_msix)
+                       group++;
+
+               for (i = 0 ; i < group ; i++) {
+                       ioc->cpu_msix_table[cpu] = index;
+                       cpu = cpumask_next(cpu, cpu_online_mask);
                }
-       }
+
+               index++;
+
+       } while (cpu < nr_cpus);
 }
 
 /**
index 0274ac3c533b00c3f8d0a1a5c2884a07a9489053..7cf48c5c15a761074cb344d51d5afef442895b18 100644 (file)
@@ -190,7 +190,7 @@ struct fw_event_work {
        u8                      VP_ID;
        u8                      ignore;
        u16                     event;
-       void                    *event_data;
+       char                    event_data[0] __aligned(4);
 };
 
 /* raid transport support */
@@ -1163,7 +1163,8 @@ _scsih_target_alloc(struct scsi_target *starget)
        unsigned long flags;
        struct sas_rphy *rphy;
 
-       sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
+       sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
+                                      GFP_KERNEL);
        if (!sas_target_priv_data)
                return -ENOMEM;
 
@@ -1277,7 +1278,8 @@ _scsih_slave_alloc(struct scsi_device *sdev)
        struct _sas_device *sas_device;
        unsigned long flags;
 
-       sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
+       sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
+                                      GFP_KERNEL);
        if (!sas_device_priv_data)
                return -ENOMEM;
 
@@ -2490,7 +2492,6 @@ _scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
 
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
        list_del(&fw_event->list);
-       kfree(fw_event->event_data);
        kfree(fw_event);
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
@@ -2511,12 +2512,10 @@ mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
 
        if (ioc->is_driver_loading)
                return;
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data),
+                          GFP_ATOMIC);
        if (!fw_event)
                return;
-       fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC);
-       if (!fw_event->event_data)
-               return;
        fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
        fw_event->ioc = ioc;
        memcpy(fw_event->event_data, event_data, sizeof(*event_data));
@@ -2582,11 +2581,10 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
                return;
 
        list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
-               if (cancel_delayed_work(&fw_event->delayed_work)) {
+               if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
                        _scsih_fw_event_free(ioc, fw_event);
                        continue;
                }
-               fw_event->cancel_pending_work = 1;
        }
 }
 
@@ -3211,7 +3209,8 @@ _scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
                if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
                    fw_event->ignore)
                        continue;
-               local_event_data = fw_event->event_data;
+               local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
+                                  fw_event->event_data;
                if (local_event_data->ExpStatus ==
                    MPI2_EVENT_SAS_TOPO_ES_ADDED ||
                    local_event_data->ExpStatus ==
@@ -5043,7 +5042,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
        u64 sas_address;
        unsigned long flags;
        u8 link_rate, prev_link_rate;
-       Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
+       Mpi2EventDataSasTopologyChangeList_t *event_data =
+               (Mpi2EventDataSasTopologyChangeList_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5241,7 +5242,8 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
        u64 sas_address;
        unsigned long flags;
        Mpi2EventDataSasDeviceStatusChange_t *event_data =
-           fw_event->event_data;
+               (Mpi2EventDataSasDeviceStatusChange_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5337,6 +5339,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
 #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
 }
@@ -5361,7 +5364,9 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
        u32 termination_count;
        u32 query_count;
        Mpi2SCSITaskManagementReply_t *mpi_reply;
-       Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
+       Mpi2EventDataSasBroadcastPrimitive_t *event_data =
+               (Mpi2EventDataSasBroadcastPrimitive_t *)
+               fw_event->event_data;
        u16 ioc_status;
        unsigned long flags;
        int r;
@@ -5513,7 +5518,8 @@ static void
 _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
        struct fw_event_work *fw_event)
 {
-       Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
+       Mpi2EventDataSasDiscovery_t *event_data =
+               (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
@@ -5999,7 +6005,9 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
        Mpi2EventIrConfigElement_t *element;
        int i;
        u8 foreign_config;
-       Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrConfigChangeList_t *event_data =
+               (Mpi2EventDataIrConfigChangeList_t *)
+               fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -6069,7 +6077,8 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
        u16 handle;
        u32 state;
        int rc;
-       Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrVolume_t *event_data =
+               (Mpi2EventDataIrVolume_t *) fw_event->event_data;
 
        if (ioc->shost_recovery)
                return;
@@ -6152,7 +6161,8 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
        Mpi2ConfigReply_t mpi_reply;
        Mpi2SasDevicePage0_t sas_device_pg0;
        u32 ioc_status;
-       Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrPhysicalDisk_t *event_data =
+               (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data;
        u64 sas_address;
 
        if (ioc->shost_recovery)
@@ -6272,7 +6282,9 @@ static void
 _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
        struct fw_event_work *fw_event)
 {
-       Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
+       Mpi2EventDataIrOperationStatus_t *event_data =
+               (Mpi2EventDataIrOperationStatus_t *)
+               fw_event->event_data;
        static struct _raid_device *raid_device;
        unsigned long flags;
        u16 handle;
@@ -7026,7 +7038,7 @@ static void
 _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
 {
        /* the queue is being flushed so ignore this event */
-       if (ioc->remove_host || fw_event->cancel_pending_work ||
+       if (ioc->remove_host ||
            ioc->pci_error_recovery) {
                _scsih_fw_event_free(ioc, fw_event);
                return;
@@ -7034,7 +7046,9 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
 
        switch (fw_event->event) {
        case MPT3SAS_PROCESS_TRIGGER_DIAG:
-               mpt3sas_process_trigger_data(ioc, fw_event->event_data);
+               mpt3sas_process_trigger_data(ioc,
+                       (struct SL_WH_TRIGGERS_EVENT_DATA_T *)
+                       fw_event->event_data);
                break;
        case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
                while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
@@ -7192,18 +7206,11 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
                return 1;
        }
 
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
-       if (!fw_event) {
-               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return 1;
-       }
        sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
-       fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
-       if (!fw_event->event_data) {
+       fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
+       if (!fw_event) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
-               kfree(fw_event);
                return 1;
        }
 
@@ -7431,9 +7438,9 @@ static void _scsih_remove(struct pci_dev *pdev)
        }
 
        sas_remove_host(shost);
+       scsi_remove_host(shost);
        mpt3sas_base_detach(ioc);
        list_del(&ioc->list);
-       scsi_remove_host(shost);
        scsi_host_put(shost);
 }
 
@@ -7801,13 +7808,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                }
        }
 
-       if ((scsi_add_host(shost, &pdev->dev))) {
-               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               list_del(&ioc->list);
-               goto out_add_shost_fail;
-       }
-
        /* register EEDP capabilities with SCSI layer */
        if (prot_mask > 0)
                scsi_host_set_prot(shost, prot_mask);
@@ -7835,15 +7835,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                    ioc->name, __FILE__, __LINE__, __func__);
                goto out_attach_fail;
        }
+       if ((scsi_add_host(shost, &pdev->dev))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               list_del(&ioc->list);
+               goto out_add_shost_fail;
+       }
+
        scsi_scan_host(shost);
        return 0;
-
+out_add_shost_fail:
+       mpt3sas_base_detach(ioc);
  out_attach_fail:
        destroy_workqueue(ioc->firmware_event_thread);
  out_thread_fail:
        list_del(&ioc->list);
-       scsi_remove_host(shost);
- out_add_shost_fail:
        scsi_host_put(shost);
        return -ENODEV;
 }
index 0d78a4d5576c33869ceed04f931a00b34b231323..80bacb5dc1d4170aeb4fa1d8c6a786ced42433ba 100644 (file)
@@ -607,8 +607,6 @@ static int pas16_release(struct Scsi_Host *shost)
        if (shost->irq)
                free_irq(shost->irq, shost);
        NCR5380_exit(shost);
-       if (shost->dma_channel != 0xff)
-               free_dma(shost->dma_channel);
        if (shost->io_port && shost->n_io_port)
                release_region(shost->io_port, shost->n_io_port);
        scsi_unregister(shost);
index a368d77b8d4100dbe267da5f9f419e0a2dbaa68f..d3a08aea09487e955d51b394b300826183b5c296 100644 (file)
@@ -397,7 +397,10 @@ static ssize_t pm8001_ctl_bios_version_show(struct device *cdev,
        payload.func_specific = kzalloc(4096, GFP_KERNEL);
        if (!payload.func_specific)
                return -ENOMEM;
-       PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+       if (PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload)) {
+               kfree(payload.func_specific);
+               return -ENOMEM;
+       }
        wait_for_completion(&completion);
        virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr;
        for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT;
@@ -614,11 +617,11 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
 
                pm8001_ha->nvmd_completion = &completion;
                ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload);
+               if (ret)
+                       break;
                wait_for_completion(&completion);
-               if (ret || (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS)) {
+               if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) {
                        ret = fwControl->retcode;
-                       kfree(ioctlbuffer);
-                       ioctlbuffer = NULL;
                        break;
                }
        }
index a97be015e52e5785c64b570fb5b38095713734fe..173831016f5f6d3093959d934e0fe598f19b6ffa 100644 (file)
@@ -1346,7 +1346,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
                &pMessage) < 0) {
                PM8001_IO_DBG(pm8001_ha,
                        pm8001_printk("No free mpi buffer\n"));
-               return -1;
+               return -ENOMEM;
        }
        BUG_ON(!payload);
        /*Copy to the payload*/
@@ -1751,6 +1751,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
        task_abort.tag = cpu_to_le32(ccb_tag);
 
        ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+       if (ret)
+               pm8001_tag_free(pm8001_ha, ccb_tag);
 
 }
 
@@ -1778,6 +1780,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 
        res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
        if (res) {
+               sas_free_task(task);
                PM8001_FAIL_DBG(pm8001_ha,
                        pm8001_printk("cannot allocate tag !!!\n"));
                return;
@@ -1788,14 +1791,14 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
        */
        dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
        if (!dev) {
+               sas_free_task(task);
+               pm8001_tag_free(pm8001_ha, ccb_tag);
                PM8001_FAIL_DBG(pm8001_ha,
                        pm8001_printk("Domain device cannot be allocated\n"));
-               sas_free_task(task);
                return;
-       } else {
-               task->dev = dev;
-               task->dev->lldd_dev = pm8001_ha_dev;
        }
+       task->dev = dev;
+       task->dev->lldd_dev = pm8001_ha_dev;
 
        ccb = &pm8001_ha->ccb_info[ccb_tag];
        ccb->device = pm8001_ha_dev;
@@ -1821,7 +1824,11 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
        memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
        res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
-
+       if (res) {
+               sas_free_task(task);
+               pm8001_tag_free(pm8001_ha, ccb_tag);
+               kfree(dev);
+       }
 }
 
 /**
@@ -3100,7 +3107,7 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
        complete(pm8001_dev->setds_completion);
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
-       pm8001_ccb_free(pm8001_ha, tag);
+       pm8001_tag_free(pm8001_ha, tag);
 }
 
 void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3119,13 +3126,12 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        }
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
-       pm8001_ccb_free(pm8001_ha, tag);
+       pm8001_tag_free(pm8001_ha, tag);
 }
 
 void
 pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
-       struct fw_control_ex    *fw_control_context;
        struct get_nvm_data_resp *pPayload =
                (struct get_nvm_data_resp *)(piomb + 4);
        u32 tag = le32_to_cpu(pPayload->tag);
@@ -3134,7 +3140,6 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        u32 ir_tds_bn_dps_das_nvm =
                le32_to_cpu(pPayload->ir_tda_bn_dps_das_nvm);
        void *virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr;
-       fw_control_context = ccb->fw_control_context;
 
        PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Get nvm data complete!\n"));
        if ((dlen_status & NVMD_STAT) != 0) {
@@ -3175,13 +3180,11 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        pm8001_printk("Get NVMD success, IR=0, dataLen=%d\n",
                        (dlen_status & NVMD_LEN) >> 24));
        }
-       memcpy(fw_control_context->usrAddr,
-               pm8001_ha->memoryMap.region[NVMD].virt_ptr,
-               fw_control_context->len);
-       complete(pm8001_ha->nvmd_completion);
+       kfree(ccb->fw_control_context);
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
-       pm8001_ccb_free(pm8001_ha, tag);
+       pm8001_tag_free(pm8001_ha, tag);
+       complete(pm8001_ha->nvmd_completion);
 }
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3588,7 +3591,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        complete(pm8001_dev->dcompletion);
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
-       pm8001_ccb_free(pm8001_ha, htag);
+       pm8001_tag_free(pm8001_ha, htag);
        return 0;
 }
 
@@ -3617,15 +3620,11 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
                void *piomb)
 {
        u32 status;
-       struct fw_control_ex    fw_control_context;
        struct fw_flash_Update_resp *ppayload =
                (struct fw_flash_Update_resp *)(piomb + 4);
        u32 tag = le32_to_cpu(ppayload->tag);
        struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
        status = le32_to_cpu(ppayload->status);
-       memcpy(&fw_control_context,
-               ccb->fw_control_context,
-               sizeof(fw_control_context));
        switch (status) {
        case FLASH_UPDATE_COMPLETE_PENDING_REBOOT:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3668,11 +3667,11 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
                        pm8001_printk("No matched status = %d\n", status));
                break;
        }
-       ccb->fw_control_context->fw_control->retcode = status;
-       complete(pm8001_ha->nvmd_completion);
+       kfree(ccb->fw_control_context);
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
-       pm8001_ccb_free(pm8001_ha, tag);
+       pm8001_tag_free(pm8001_ha, tag);
+       complete(pm8001_ha->nvmd_completion);
        return 0;
 }
 
@@ -4257,7 +4256,11 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
        smp_cmd.long_smp_req.long_resp_size =
                cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
        build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
-       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
+                                       (u32 *)&smp_cmd, 0);
+       if (rc)
+               goto err_out_2;
+
        return 0;
 
 err_out_2:
@@ -4398,7 +4401,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 
        /* Check for read log for failed drive and return */
        if (sata_cmd.sata_fis.command == 0x2f) {
-               if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
+               if (((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
                        (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
                        (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
                        struct task_status_struct *ts;
@@ -4789,6 +4792,10 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
                break;
        }
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+       if (rc) {
+               kfree(fw_control_context);
+               pm8001_tag_free(pm8001_ha, tag);
+       }
        return rc;
 }
 
@@ -4869,6 +4876,10 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
                break;
        }
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+       if (rc) {
+               kfree(fw_control_context);
+               pm8001_tag_free(pm8001_ha, tag);
+       }
        return rc;
 }
 
@@ -5061,7 +5072,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
        memset(&payload, 0, sizeof(payload));
        rc = pm8001_tag_alloc(pm8001_ha, &tag);
        if (rc)
-               return -1;
+               return -ENOMEM;
        ccb = &pm8001_ha->ccb_info[tag];
        ccb->ccb_tag = tag;
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -5070,6 +5081,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
        payload.sata_hol_tmo = cpu_to_le32(80);
        payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
        return rc;
 
 }
index e90c89f1d480e702db91728981636b896f08ea94..e49623a897a733d778ca24f8f80a49db16b4aa31 100644 (file)
@@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
 {
        int i;
        spin_lock_init(&pm8001_ha->lock);
+       spin_lock_init(&pm8001_ha->bitmap_lock);
        PM8001_INIT_DBG(pm8001_ha,
                pm8001_printk("pm8001_alloc: PHY:%x\n",
                                pm8001_ha->chip->n_phy));
@@ -621,6 +622,8 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
        DECLARE_COMPLETION_ONSTACK(completion);
        struct pm8001_ioctl_payload payload;
        u16 deviceid;
+       int rc;
+
        pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
        pm8001_ha->nvmd_completion = &completion;
 
@@ -638,7 +641,16 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
        }
        payload.offset = 0;
        payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
-       PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+       if (!payload.func_specific) {
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n"));
+               return;
+       }
+       rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+       if (rc) {
+               kfree(payload.func_specific);
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n"));
+               return;
+       }
        wait_for_completion(&completion);
 
        for (i = 0, j = 0; i <= 7; i++, j++) {
@@ -661,6 +673,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
                        pm8001_printk("phy %d sas_addr = %016llx\n", i,
                        pm8001_ha->phy[i].dev_sas_addr));
        }
+       kfree(payload.func_specific);
 #else
        for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
                pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL;
@@ -684,6 +697,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
        /*OPTION ROM FLASH read for the SPC cards */
        DECLARE_COMPLETION_ONSTACK(completion);
        struct pm8001_ioctl_payload payload;
+       int rc;
 
        pm8001_ha->nvmd_completion = &completion;
        /* SAS ADDRESS read from flash / EEPROM */
@@ -694,7 +708,12 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
        if (!payload.func_specific)
                return -ENOMEM;
        /* Read phy setting values from flash */
-       PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+       rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+       if (rc) {
+               kfree(payload.func_specific);
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n"));
+               return -ENOMEM;
+       }
        wait_for_completion(&completion);
        pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific);
        kfree(payload.func_specific);
@@ -744,9 +763,10 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
                        pm8001_ha->irq_vector[i].irq_id = i;
                        pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
 
-                       if (request_irq(pm8001_ha->msix_entries[i].vector,
+                       rc = request_irq(pm8001_ha->msix_entries[i].vector,
                                pm8001_interrupt_handler_msix, flag,
-                               intr_drvname[i], &(pm8001_ha->irq_vector[i]))) {
+                               intr_drvname[i], &(pm8001_ha->irq_vector[i]));
+                       if (rc) {
                                for (j = 0; j < i; j++)
                                        free_irq(
                                        pm8001_ha->msix_entries[j].vector,
@@ -964,6 +984,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        int  i, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
+       sas_suspend_ha(sha);
        flush_workqueue(pm8001_wq);
        scsi_block_requests(pm8001_ha->shost);
        if (!pdev->pm_cap) {
@@ -1013,6 +1034,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        int rc;
        u8 i = 0, j;
        u32 device_state;
+       DECLARE_COMPLETION_ONSTACK(completion);
        pm8001_ha = sha->lldd_ha;
        device_state = pdev->current_state;
 
@@ -1033,7 +1055,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        rc = pci_go_44(pdev);
        if (rc)
                goto err_out_disable;
-
+       sas_prep_resume_ha(sha);
        /* chip soft rst only for spc */
        if (pm8001_ha->chip_id == chip_8001) {
                PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
@@ -1065,7 +1087,13 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
                for (i = 1; i < pm8001_ha->number_of_intr; i++)
                        PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
        }
-       scsi_unblock_requests(pm8001_ha->shost);
+       pm8001_ha->flags = PM8001F_RUN_TIME;
+       for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+               pm8001_ha->phy[i].enable_completion = &completion;
+               PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
+               wait_for_completion(&completion);
+       }
+       sas_resume_ha(sha);
        return 0;
 
 err_out_disable:
index 8a44bc92bc786abe1076c58c34c5d0c5d9e20ae8..34cea82917722fbe9ad0a295f31d37638d7cf308 100644 (file)
@@ -58,25 +58,14 @@ static int pm8001_find_tag(struct sas_task *task, u32 *tag)
 }
 
 /**
-  * pm8001_tag_clear - clear the tags bitmap
+  * pm8001_tag_free - free the no more needed tag
   * @pm8001_ha: our hba struct
   * @tag: the found tag associated with the task
   */
-static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag)
-{
-       void *bitmap = pm8001_ha->tags;
-       clear_bit(tag, bitmap);
-}
-
 void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
-{
-       pm8001_tag_clear(pm8001_ha, tag);
-}
-
-static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag)
 {
        void *bitmap = pm8001_ha->tags;
-       set_bit(tag, bitmap);
+       clear_bit(tag, bitmap);
 }
 
 /**
@@ -86,14 +75,18 @@ static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag)
   */
 inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
 {
-       unsigned int index, tag;
+       unsigned int tag;
        void *bitmap = pm8001_ha->tags;
+       unsigned long flags;
 
-       index = find_first_zero_bit(bitmap, pm8001_ha->tags_num);
-       tag = index;
-       if (tag >= pm8001_ha->tags_num)
+       spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags);
+       tag = find_first_zero_bit(bitmap, pm8001_ha->tags_num);
+       if (tag >= pm8001_ha->tags_num) {
+               spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
                return -SAS_QUEUE_FULL;
-       pm8001_tag_set(pm8001_ha, tag);
+       }
+       set_bit(tag, bitmap);
+       spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
        *tag_out = tag;
        return 0;
 }
@@ -102,7 +95,7 @@ void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha)
 {
        int i;
        for (i = 0; i < pm8001_ha->tags_num; ++i)
-               pm8001_tag_clear(pm8001_ha, i);
+               pm8001_tag_free(pm8001_ha, i);
 }
 
  /**
@@ -501,11 +494,6 @@ int pm8001_queue_command(struct sas_task *task, const int num,
        return pm8001_task_exec(task, num, gfp_flags, 0, NULL);
 }
 
-void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx)
-{
-       pm8001_tag_clear(pm8001_ha, ccb_idx);
-}
-
 /**
   * pm8001_ccb_task_free - free the sg for ssp and smp command, free the ccb.
   * @pm8001_ha: our hba card information
@@ -542,7 +530,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
        ccb->open_retry = 0;
-       pm8001_ccb_free(pm8001_ha, ccb_idx);
+       pm8001_tag_free(pm8001_ha, ccb_idx);
 }
 
  /**
index 1ee06f21803b5b76c8a1e5b41d9551e4fdfc227c..f6b2ac59dae4f66dd99c1455cf7674e6113eb5bc 100644 (file)
@@ -475,6 +475,7 @@ struct pm8001_hba_info {
        struct list_head        list;
        unsigned long           flags;
        spinlock_t              lock;/* host-wide lock */
+       spinlock_t              bitmap_lock;
        struct pci_dev          *pdev;/* our device */
        struct device           *dev;
        struct pm8001_hba_memspace io_mem[6];
@@ -616,7 +617,6 @@ extern struct workqueue_struct *pm8001_wq;
 int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out);
 void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha);
 u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag);
-void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx);
 void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
        struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx);
 int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
index d70587f961845c2a868f4fd596ef1a624c5d8a30..b06443a0db2dc269e412eb61e414e6ce6f45358f 100644 (file)
@@ -856,6 +856,8 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
        payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
 
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
        return rc;
 
 }
@@ -936,6 +938,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
                         sizeof(SASProtocolTimerConfig_t));
 
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
 
        return rc;
 }
@@ -948,7 +952,7 @@ static int
 pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
 {
        u32 scratch3_value;
-       int ret;
+       int ret = -1;
 
        /* Read encryption status from SCRATCH PAD 3 */
        scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
@@ -982,7 +986,7 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
                pm8001_ha->encrypt_info.status = 0xFFFFFFFF;
                pm8001_ha->encrypt_info.cipher_mode = 0;
                pm8001_ha->encrypt_info.sec_mode = 0;
-               return 0;
+               ret = 0;
        } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
                                SCRATCH_PAD3_ENC_DIS_ERR) {
                pm8001_ha->encrypt_info.status =
@@ -1004,7 +1008,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
                        scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
                        pm8001_ha->encrypt_info.sec_mode,
                        pm8001_ha->encrypt_info.status));
-               ret = -1;
        } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
                                 SCRATCH_PAD3_ENC_ENA_ERR) {
 
@@ -1028,7 +1031,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
                        scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
                        pm8001_ha->encrypt_info.sec_mode,
                        pm8001_ha->encrypt_info.status));
-               ret = -1;
        }
        return ret;
 }
@@ -1059,6 +1061,8 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
                                        KEK_MGMT_SUBOP_KEYCARDUPDATE);
 
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
 
        return rc;
 }
@@ -1383,8 +1387,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
        task->task_done = pm8001_task_done;
 
        res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-       if (res)
+       if (res) {
+               sas_free_task(task);
                return;
+       }
 
        ccb = &pm8001_ha->ccb_info[ccb_tag];
        ccb->device = pm8001_ha_dev;
@@ -1399,7 +1405,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
        task_abort.tag = cpu_to_le32(ccb_tag);
 
        ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
-
+       if (ret) {
+               sas_free_task(task);
+               pm8001_tag_free(pm8001_ha, ccb_tag);
+       }
 }
 
 static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
@@ -1426,6 +1435,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 
        res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
        if (res) {
+               sas_free_task(task);
                PM8001_FAIL_DBG(pm8001_ha,
                        pm8001_printk("cannot allocate tag !!!\n"));
                return;
@@ -1436,15 +1446,16 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
        */
        dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
        if (!dev) {
+               sas_free_task(task);
+               pm8001_tag_free(pm8001_ha, ccb_tag);
                PM8001_FAIL_DBG(pm8001_ha,
                        pm8001_printk("Domain device cannot be allocated\n"));
-               sas_free_task(task);
                return;
-       } else {
-               task->dev = dev;
-               task->dev->lldd_dev = pm8001_ha_dev;
        }
 
+       task->dev = dev;
+       task->dev->lldd_dev = pm8001_ha_dev;
+
        ccb = &pm8001_ha->ccb_info[ccb_tag];
        ccb->device = pm8001_ha_dev;
        ccb->ccb_tag = ccb_tag;
@@ -1469,7 +1480,11 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
        memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
        res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
-
+       if (res) {
+               sas_free_task(task);
+               pm8001_tag_free(pm8001_ha, ccb_tag);
+               kfree(dev);
+       }
 }
 
 /**
@@ -3815,7 +3830,10 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 
        build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
                                &smp_cmd, pm8001_ha->smp_exp_mode, length);
-       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
+                                       (u32 *)&smp_cmd, 0);
+       if (rc)
+               goto err_out_2;
        return 0;
 
 err_out_2:
@@ -4406,6 +4424,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
                SAS_ADDR_SIZE);
 
        rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
 
        return rc;
 }
@@ -4484,7 +4504,9 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
                payload.reserved[j] =  cpu_to_le32(*((u32 *)buf + i));
                j++;
        }
-       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
 }
 
 void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
index e2184412617d8d0ccce3527dceacfb351fc5b45a..46990f4ceb4097be3acbb98f8235994be33bd475 100644 (file)
@@ -1526,8 +1526,8 @@ try_fce:
                            FCE_SIZE, ha->fce, ha->fce_dma);
 
                /* Allocate memory for Fibre Channel Event Buffer. */
-               tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
-                   GFP_KERNEL);
+               tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+                                        GFP_KERNEL);
                if (!tc) {
                        ql_log(ql_log_warn, vha, 0x00be,
                            "Unable to allocate (%d KB) for FCE.\n",
@@ -1535,7 +1535,6 @@ try_fce:
                        goto try_eft;
                }
 
-               memset(tc, 0, FCE_SIZE);
                rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
                    ha->fce_mb, &ha->fce_bufs);
                if (rval) {
@@ -1560,8 +1559,8 @@ try_eft:
                            EFT_SIZE, ha->eft, ha->eft_dma);
 
                /* Allocate memory for Extended Trace Buffer. */
-               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-                   GFP_KERNEL);
+               tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+                                        GFP_KERNEL);
                if (!tc) {
                        ql_log(ql_log_warn, vha, 0x00c1,
                            "Unable to allocate (%d KB) for EFT.\n",
@@ -1569,7 +1568,6 @@ try_eft:
                        goto cont_alloc;
                }
 
-               memset(tc, 0, EFT_SIZE);
                rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
                if (rval) {
                        ql_log(ql_log_warn, vha, 0x00c2,
index 13d628b56ff790473d2088759fba4d8a32b7cd1e..a22bb1b40ce2a12d344b741524ee75cee2668d58 100644 (file)
@@ -171,8 +171,6 @@ static int qlogicfas_release(struct Scsi_Host *shost)
                qlogicfas408_disable_ints(priv);        
                free_irq(shost->irq, shost);
        }
-       if (shost->dma_channel != 0xff)
-               free_dma(shost->dma_channel);
        if (shost->io_port && shost->n_io_port)
                release_region(shost->io_port, shost->n_io_port);
        scsi_host_put(shost);
index 6ed43fd19a22a5f01e21996d02c2939ab737161e..d19c0e3c7f481c7fa9ad814fe72cc7b7a9ae6715 100644 (file)
 #include <linux/scatterlist.h>
 #include <linux/blkdev.h>
 #include <linux/crc-t10dif.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/atomic.h>
+#include <linux/hrtimer.h>
 
 #include <net/checksum.h>
 
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_dbg.h>
 
 #include "sd.h"
 #include "scsi_logging.h"
 
-#define SCSI_DEBUG_VERSION "1.82"
-static const char * scsi_debug_version_date = "20100324";
+#define SCSI_DEBUG_VERSION "1.84"
+static const char *scsi_debug_version_date = "20140706";
+
+#define MY_NAME "scsi_debug"
 
 /* Additional Sense Code (ASC) */
 #define NO_ADDITIONAL_SENSE 0x0
@@ -72,7 +79,11 @@ static const char * scsi_debug_version_date = "20100324";
 #define INVALID_COMMAND_OPCODE 0x20
 #define INVALID_FIELD_IN_CDB 0x24
 #define INVALID_FIELD_IN_PARAM_LIST 0x26
-#define POWERON_RESET 0x29
+#define UA_RESET_ASC 0x29
+#define UA_CHANGED_ASC 0x2a
+#define POWER_ON_RESET_ASCQ 0x0
+#define BUS_RESET_ASCQ 0x2     /* scsi bus reset occurred */
+#define MODE_CHANGED_ASCQ 0x1  /* mode parameters changed */
 #define SAVING_PARAMS_UNSUP 0x39
 #define TRANSPORT_PROBLEM 0x4b
 #define THRESHOLD_EXCEEDED 0x5d
@@ -81,7 +92,6 @@ static const char * scsi_debug_version_date = "20100324";
 /* Additional Sense Code Qualifier (ASCQ) */
 #define ACK_NAK_TO 0x3
 
-#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 
 /* Default values for driver parameters */
 #define DEF_NUM_HOST   1
@@ -91,7 +101,7 @@ static const char * scsi_debug_version_date = "20100324";
  * (id 0) containing 1 logical unit (lun 0). That is 1 device.
  */
 #define DEF_ATO 1
-#define DEF_DELAY   1
+#define DEF_DELAY   1          /* if > 0 unit is a jiffy */
 #define DEF_DEV_SIZE_MB   8
 #define DEF_DIF 0
 #define DEF_DIX 0
@@ -99,11 +109,13 @@ static const char * scsi_debug_version_date = "20100324";
 #define DEF_EVERY_NTH   0
 #define DEF_FAKE_RW    0
 #define DEF_GUARD 0
+#define DEF_HOST_LOCK 0
 #define DEF_LBPU 0
 #define DEF_LBPWS 0
 #define DEF_LBPWS10 0
 #define DEF_LBPRZ 1
 #define DEF_LOWEST_ALIGNED 0
+#define DEF_NDELAY   0         /* if > 0 unit is a nanosecond */
 #define DEF_NO_LUN_0   0
 #define DEF_NUM_PARTS   0
 #define DEF_OPTS   0
@@ -113,6 +125,7 @@ static const char * scsi_debug_version_date = "20100324";
 #define DEF_REMOVABLE false
 #define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
 #define DEF_SECTOR_SIZE 512
+#define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 #define DEF_UNMAP_ALIGNMENT 0
 #define DEF_UNMAP_GRANULARITY 1
 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
@@ -120,6 +133,7 @@ static const char * scsi_debug_version_date = "20100324";
 #define DEF_VIRTUAL_GB   0
 #define DEF_VPD_USE_HOSTNO 1
 #define DEF_WRITESAME_LENGTH 0xFFFF
+#define DELAY_OVERRIDDEN -9999
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -130,7 +144,14 @@ static const char * scsi_debug_version_date = "20100324";
 #define SCSI_DEBUG_OPT_DIF_ERR   32
 #define SCSI_DEBUG_OPT_DIX_ERR   64
 #define SCSI_DEBUG_OPT_MAC_TIMEOUT  128
-#define SCSI_DEBUG_OPT_SHORT_TRANSFER  256
+#define SCSI_DEBUG_OPT_SHORT_TRANSFER  0x100
+#define SCSI_DEBUG_OPT_Q_NOISE 0x200
+#define SCSI_DEBUG_OPT_ALL_TSF 0x400
+#define SCSI_DEBUG_OPT_RARE_TSF        0x800
+#define SCSI_DEBUG_OPT_N_WCE   0x1000
+#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
+#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
+#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
 /* When "every_nth" > 0 then modulo "every_nth" commands:
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
@@ -148,6 +169,19 @@ static const char * scsi_debug_version_date = "20100324";
  * writing a new value (other than -1 or 1) to every_nth via sysfs).
  */
 
+/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
+ * priority order. In the subset implemented here lower numbers have higher
+ * priority. The UA numbers should be a sequence starting from 0 with
+ * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
+#define SDEBUG_UA_POR 0                /* Power on, reset, or bus device reset */
+#define SDEBUG_UA_BUS_RESET 1
+#define SDEBUG_UA_MODE_CHANGED 2
+#define SDEBUG_NUM_UAS 3
+
+/* for check_readiness() */
+#define UAS_ONLY 1
+#define UAS_TUR 0
+
 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
 #define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
@@ -158,9 +192,19 @@ static const char * scsi_debug_version_date = "20100324";
 #define SAM2_LUN_ADDRESS_METHOD 0
 #define SAM2_WLUN_REPORT_LUNS 0xc101
 
-/* Can queue up to this number of commands. Typically commands that
- * that have a non-zero delay are queued. */
-#define SCSI_DEBUG_CANQUEUE  255
+/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
+ * (for response) at one time. Can be reduced by max_queue option. Command
+ * responses are not queued when delay=0 and ndelay=0. The per-device
+ * DEF_CMD_PER_LUN can be changed via sysfs:
+ * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
+ * SCSI_DEBUG_CANQUEUE. */
+#define SCSI_DEBUG_CANQUEUE_WORDS  9   /* a WORD is bits in a long */
+#define SCSI_DEBUG_CANQUEUE  (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
+#define DEF_CMD_PER_LUN  255
+
+#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
+#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
+#endif
 
 static int scsi_debug_add_host = DEF_NUM_HOST;
 static int scsi_debug_ato = DEF_ATO;
@@ -175,6 +219,8 @@ static unsigned int scsi_debug_guard = DEF_GUARD;
 static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int scsi_debug_max_luns = DEF_MAX_LUNS;
 static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
+static atomic_t retired_max_queue;     /* if > 0 then was prior max_queue */
+static int scsi_debug_ndelay = DEF_NDELAY;
 static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
 static int scsi_debug_no_uld = 0;
 static int scsi_debug_num_parts = DEF_NUM_PARTS;
@@ -198,8 +244,11 @@ static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
 static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
 static bool scsi_debug_removable = DEF_REMOVABLE;
 static bool scsi_debug_clustering;
+static bool scsi_debug_host_lock = DEF_HOST_LOCK;
 
-static int scsi_debug_cmnd_count = 0;
+static atomic_t sdebug_cmnd_count;
+static atomic_t sdebug_completions;
+static atomic_t sdebug_a_tsf;          /* counter of 'almost' TSFs */
 
 #define DEV_READONLY(TGT)      (0)
 
@@ -214,24 +263,23 @@ static int sdebug_sectors_per;            /* sectors per cylinder */
 
 #define SDEBUG_MAX_PARTS 4
 
-#define SDEBUG_SENSE_LEN 32
-
 #define SCSI_DEBUG_MAX_CMD_LEN 32
 
 static unsigned int scsi_debug_lbp(void)
 {
-       return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10;
+       return ((0 == scsi_debug_fake_rw) &&
+               (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
 }
 
 struct sdebug_dev_info {
        struct list_head dev_list;
-       unsigned char sense_buff[SDEBUG_SENSE_LEN];     /* weak nexus */
        unsigned int channel;
        unsigned int target;
        u64 lun;
        struct sdebug_host_info *sdbg_host;
        u64 wlun;
-       char reset;
+       unsigned long uas_bm[1];
+       atomic_t num_in_q;
        char stopped;
        char used;
 };
@@ -249,26 +297,33 @@ struct sdebug_host_info {
 static LIST_HEAD(sdebug_host_list);
 static DEFINE_SPINLOCK(sdebug_host_list_lock);
 
-typedef void (* done_funct_t) (struct scsi_cmnd *);
+
+struct sdebug_hrtimer {                /* ... is derived from hrtimer */
+       struct hrtimer hrt;     /* must be first element */
+       int qa_indx;
+};
 
 struct sdebug_queued_cmd {
-       int in_use;
-       struct timer_list cmnd_timer;
-       done_funct_t done_funct;
+       /* in_use flagged by a bit in queued_in_use_bm[] */
+       struct timer_list *cmnd_timerp;
+       struct tasklet_struct *tletp;
+       struct sdebug_hrtimer *sd_hrtp;
        struct scsi_cmnd * a_cmnd;
-       int scsi_result;
 };
 static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
+static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
+
 
 static unsigned char * fake_storep;    /* ramdisk storage */
 static struct sd_dif_tuple *dif_storep;        /* protection info */
 static void *map_storep;               /* provisioning map */
 
 static unsigned long map_size;
-static int num_aborts = 0;
-static int num_dev_resets = 0;
-static int num_bus_resets = 0;
-static int num_host_resets = 0;
+static int num_aborts;
+static int num_dev_resets;
+static int num_target_resets;
+static int num_bus_resets;
+static int num_host_resets;
 static int dix_writes;
 static int dix_reads;
 static int dif_errors;
@@ -276,7 +331,8 @@ static int dif_errors;
 static DEFINE_SPINLOCK(queued_arr_lock);
 static DEFINE_RWLOCK(atomic_rw);
 
-static char sdebug_proc_name[] = "scsi_debug";
+static char sdebug_proc_name[] = MY_NAME;
+static const char *my_name = MY_NAME;
 
 static struct bus_type pseudo_lld_bus;
 
@@ -291,6 +347,12 @@ static const int check_condition_result =
 static const int illegal_condition_result =
        (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
 
+static const int device_qfull_result =
+       (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
+
+static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
+                                    0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
+                                    0, 0, 0, 0};
 static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
                                    0, 0, 0x2, 0x4b};
 static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
@@ -332,19 +394,24 @@ static void sdebug_max_tgts_luns(void)
        spin_unlock(&sdebug_host_list_lock);
 }
 
-static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
-                           int asc, int asq)
+static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
 {
        unsigned char *sbuff;
 
-       sbuff = devip->sense_buff;
-       memset(sbuff, 0, SDEBUG_SENSE_LEN);
+       sbuff = scp->sense_buffer;
+       if (!sbuff) {
+               sdev_printk(KERN_ERR, scp->device,
+                           "%s: sense_buffer is NULL\n", __func__);
+               return;
+       }
+       memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
 
        scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
 
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
-                     "[0x%x,0x%x,0x%x]\n", key, asc, asq);
+               sdev_printk(KERN_INFO, scp->device,
+                           "%s:  [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
+                           my_name, key, asc, asq);
 }
 
 static void get_data_transfer_info(unsigned char *cmd,
@@ -409,29 +476,71 @@ static void get_data_transfer_info(unsigned char *cmd,
 static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
-               printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd);
+               if (0x1261 == cmd)
+                       sdev_printk(KERN_INFO, dev,
+                                   "%s: BLKFLSBUF [0x1261]\n", __func__);
+               else if (0x5331 == cmd)
+                       sdev_printk(KERN_INFO, dev,
+                                   "%s: CDROM_GET_CAPABILITY [0x5331]\n",
+                                   __func__);
+               else
+                       sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
+                                   __func__, cmd);
        }
        return -EINVAL;
        /* return -ENOTTY; // correct return but upsets fdisk */
 }
 
-static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
                           struct sdebug_dev_info * devip)
 {
-       if (devip->reset) {
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Reporting Unit "
-                              "attention: power on reset\n");
-               devip->reset = 0;
-               mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
+       int k;
+       bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
+
+       k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
+       if (k != SDEBUG_NUM_UAS) {
+               const char *cp = NULL;
+
+               switch (k) {
+               case SDEBUG_UA_POR:
+                       mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+                                       UA_RESET_ASC, POWER_ON_RESET_ASCQ);
+                       if (debug)
+                               cp = "power on reset";
+                       break;
+               case SDEBUG_UA_BUS_RESET:
+                       mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+                                       UA_RESET_ASC, BUS_RESET_ASCQ);
+                       if (debug)
+                               cp = "bus reset";
+                       break;
+               case SDEBUG_UA_MODE_CHANGED:
+                       mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+                                       UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
+                       if (debug)
+                               cp = "mode parameters changed";
+                       break;
+               default:
+                       pr_warn("%s: unexpected unit attention code=%d\n",
+                               __func__, k);
+                       if (debug)
+                               cp = "unknown";
+                       break;
+               }
+               clear_bit(k, devip->uas_bm);
+               if (debug)
+                       sdev_printk(KERN_INFO, SCpnt->device,
+                                  "%s reports: Unit attention: %s\n",
+                                  my_name, cp);
                return check_condition_result;
        }
-       if ((0 == reset_only) && devip->stopped) {
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Reporting Not "
-                              "ready: initializing command required\n");
-               mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,
+       if ((UAS_TUR == uas_only) && devip->stopped) {
+               mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
                                0x2);
+               if (debug)
+                       sdev_printk(KERN_INFO, SCpnt->device,
+                                   "%s reports: Not ready: %s\n", my_name,
+                                   "initializing command required");
                return check_condition_result;
        }
        return 0;
@@ -471,8 +580,9 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
 
 static const char * inq_vendor_id = "Linux   ";
 static const char * inq_product_id = "scsi_debug      ";
-static const char * inq_product_rev = "0004";
+static const char *inq_product_rev = "0184";   /* version less '.' */
 
+/* Device identification VPD page. Returns number of bytes placed in arr */
 static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
                           int target_dev_id, int dev_id_num,
                           const char * dev_id_str,
@@ -573,12 +683,14 @@ static unsigned char vpd84_data[] = {
     0x22,0x22,0x22,0x0,0xbb,0x2,
 };
 
+/*  Software interface identification VPD page */
 static int inquiry_evpd_84(unsigned char * arr)
 {
        memcpy(arr, vpd84_data, sizeof(vpd84_data));
        return sizeof(vpd84_data);
 }
 
+/* Management network addresses VPD page */
 static int inquiry_evpd_85(unsigned char * arr)
 {
        int num = 0;
@@ -713,6 +825,7 @@ static unsigned char vpd89_data[] = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
 };
 
+/* ATA Information VPD page */
 static int inquiry_evpd_89(unsigned char * arr)
 {
        memcpy(arr, vpd89_data, sizeof(vpd89_data));
@@ -720,7 +833,6 @@ static int inquiry_evpd_89(unsigned char * arr)
 }
 
 
-/* Block limits VPD page (SBC-3) */
 static unsigned char vpdb0_data[] = {
        /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -728,6 +840,7 @@ static unsigned char vpdb0_data[] = {
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 };
 
+/* Block limits VPD page (SBC-3) */
 static int inquiry_evpd_b0(unsigned char * arr)
 {
        unsigned int gran;
@@ -811,7 +924,7 @@ static int inquiry_evpd_b2(unsigned char *arr)
 #define SDEBUG_LONG_INQ_SZ 96
 #define SDEBUG_MAX_INQ_ARR_SZ 584
 
-static int resp_inquiry(struct scsi_cmnd * scp, int target,
+static int resp_inquiry(struct scsi_cmnd *scp, int target,
                        struct sdebug_dev_info * devip)
 {
        unsigned char pq_pdt;
@@ -831,7 +944,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
                pq_pdt = (scsi_debug_ptype & 0x1f);
        arr[0] = pq_pdt;
        if (0x2 & cmd[1]) {  /* CMDDT bit set */
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                kfree(arr);
                return check_condition_result;
@@ -917,7 +1030,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
                        arr[3] = inquiry_evpd_b2(&arr[4]);
                } else {
                        /* Illegal request, invalid field in cdb */
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        kfree(arr);
                        return check_condition_result;
@@ -963,15 +1076,13 @@ static int resp_requests(struct scsi_cmnd * scp,
 {
        unsigned char * sbuff;
        unsigned char *cmd = (unsigned char *)scp->cmnd;
-       unsigned char arr[SDEBUG_SENSE_LEN];
+       unsigned char arr[SCSI_SENSE_BUFFERSIZE];
        int want_dsense;
        int len = 18;
 
        memset(arr, 0, sizeof(arr));
-       if (devip->reset == 1)
-               mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
        want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
-       sbuff = devip->sense_buff;
+       sbuff = scp->sense_buffer;
        if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
                if (want_dsense) {
                        arr[0] = 0x72;
@@ -986,7 +1097,7 @@ static int resp_requests(struct scsi_cmnd * scp,
                        arr[13] = 0xff;         /* TEST set and MRIE==6 */
                }
        } else {
-               memcpy(arr, sbuff, SDEBUG_SENSE_LEN);
+               memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
                if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
                        /* DESC bit set and sense_buff in fixed format */
                        memset(arr, 0, sizeof(arr));
@@ -997,7 +1108,7 @@ static int resp_requests(struct scsi_cmnd * scp,
                        len = 8;
                }
        }
-       mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
+       mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
        return fill_from_dev_buffer(scp, arr, len);
 }
 
@@ -1007,11 +1118,12 @@ static int resp_start_stop(struct scsi_cmnd * scp,
        unsigned char *cmd = (unsigned char *)scp->cmnd;
        int power_cond, errsts, start;
 
-       if ((errsts = check_readiness(scp, 1, devip)))
+       errsts = check_readiness(scp, UAS_ONLY, devip);
+       if (errsts)
                return errsts;
        power_cond = (cmd[4] & 0xf0) >> 4;
        if (power_cond) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
        }
@@ -1038,7 +1150,8 @@ static int resp_readcap(struct scsi_cmnd * scp,
        unsigned int capac;
        int errsts;
 
-       if ((errsts = check_readiness(scp, 1, devip)))
+       errsts = check_readiness(scp, UAS_ONLY, devip);
+       if (errsts)
                return errsts;
        /* following just in case virtual_gb changed */
        sdebug_capacity = get_sdebug_capacity();
@@ -1069,7 +1182,8 @@ static int resp_readcap16(struct scsi_cmnd * scp,
        unsigned long long capac;
        int errsts, k, alloc_len;
 
-       if ((errsts = check_readiness(scp, 1, devip)))
+       errsts = check_readiness(scp, UAS_ONLY, devip);
+       if (errsts)
                return errsts;
        alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
                     + cmd[13]);
@@ -1230,12 +1344,18 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target)
 
 static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 {      /* Caching page for mode_sense */
-       unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
+       unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+       unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
                0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,     0, 0, 0, 0};
 
+       if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
+               caching_pg[2] &= ~0x4;  /* set WCE=0 (default WCE=1) */
        memcpy(p, caching_pg, sizeof(caching_pg));
        if (1 == pcontrol)
-               memset(p + 2, 0, sizeof(caching_pg) - 2);
+               memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
+       else if (2 == pcontrol)
+               memcpy(p, d_caching_pg, sizeof(d_caching_pg));
        return sizeof(caching_pg);
 }
 
@@ -1350,7 +1470,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
        unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
        unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-       if ((errsts = check_readiness(scp, 1, devip)))
+       errsts = check_readiness(scp, UAS_ONLY, devip);
+       if (errsts)
                return errsts;
        dbd = !!(cmd[1] & 0x8);
        pcontrol = (cmd[2] & 0xc0) >> 6;
@@ -1365,8 +1486,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
        alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
        memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
        if (0x3 == pcontrol) {  /* Saving values not supported */
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP,
-                               0);
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
                return check_condition_result;
        }
        target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
@@ -1422,7 +1542,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
 
        if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
                /* TODO: Control Extension page */
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
        }
@@ -1449,7 +1569,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                break;
        case 0x19:      /* if spc==1 then sas phy, control+discover */
                if ((subpcode > 0x2) && (subpcode < 0xff)) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        return check_condition_result;
                }
@@ -1482,14 +1602,14 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                        }
                        len += resp_iec_m_pg(ap + len, pcontrol, target);
                } else {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        return check_condition_result;
                 }
                offset += len;
                break;
        default:
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
        }
@@ -1512,14 +1632,15 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
        unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
        unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-       if ((errsts = check_readiness(scp, 1, devip)))
+       errsts = check_readiness(scp, UAS_ONLY, devip);
+       if (errsts)
                return errsts;
        memset(arr, 0, sizeof(arr));
        pf = cmd[1] & 0x10;
        sp = cmd[1] & 0x1;
        param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
        if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                INVALID_FIELD_IN_CDB, 0);
                return check_condition_result;
        }
@@ -1528,12 +1649,13 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
                 return (DID_ERROR << 16);
         else if ((res < param_len) &&
                  (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-                printk(KERN_INFO "scsi_debug: mode_select: cdb indicated=%d, "
-                       " IO sent=%d bytes\n", param_len, res);
+               sdev_printk(KERN_INFO, scp->device,
+                           "%s: cdb indicated=%d, IO sent=%d bytes\n",
+                           __func__, param_len, res);
        md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
        bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
        if (md_len > 2) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                INVALID_FIELD_IN_PARAM_LIST, 0);
                return check_condition_result;
        }
@@ -1541,7 +1663,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
        mpage = arr[off] & 0x3f;
        ps = !!(arr[off] & 0x80);
        if (ps) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                INVALID_FIELD_IN_PARAM_LIST, 0);
                return check_condition_result;
        }
@@ -1549,32 +1671,42 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
        pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
                       (arr[off + 1] + 2);
        if ((pg_len + off) > param_len) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                PARAMETER_LIST_LENGTH_ERR, 0);
                return check_condition_result;
        }
        switch (mpage) {
+       case 0x8:      /* Caching Mode page */
+               if (caching_pg[1] == arr[off + 1]) {
+                       memcpy(caching_pg + 2, arr + off + 2,
+                              sizeof(caching_pg) - 2);
+                       goto set_mode_changed_ua;
+               }
+               break;
        case 0xa:      /* Control Mode page */
                if (ctrl_m_pg[1] == arr[off + 1]) {
                        memcpy(ctrl_m_pg + 2, arr + off + 2,
                               sizeof(ctrl_m_pg) - 2);
                        scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
-                       return 0;
+                       goto set_mode_changed_ua;
                }
                break;
        case 0x1c:      /* Informational Exceptions Mode page */
                if (iec_m_pg[1] == arr[off + 1]) {
                        memcpy(iec_m_pg + 2, arr + off + 2,
                               sizeof(iec_m_pg) - 2);
-                       return 0;
+                       goto set_mode_changed_ua;
                }
                break;
        default:
                break;
        }
-       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+       mk_sense_buffer(scp, ILLEGAL_REQUEST,
                        INVALID_FIELD_IN_PARAM_LIST, 0);
        return check_condition_result;
+set_mode_changed_ua:
+       set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
+       return 0;
 }
 
 static int resp_temp_l_pg(unsigned char * arr)
@@ -1609,13 +1741,14 @@ static int resp_log_sense(struct scsi_cmnd * scp,
        unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
        unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-       if ((errsts = check_readiness(scp, 1, devip)))
+       errsts = check_readiness(scp, UAS_ONLY, devip);
+       if (errsts)
                return errsts;
        memset(arr, 0, sizeof(arr));
        ppc = cmd[1] & 0x2;
        sp = cmd[1] & 0x1;
        if (ppc || sp) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                INVALID_FIELD_IN_CDB, 0);
                return check_condition_result;
        }
@@ -1640,7 +1773,7 @@ static int resp_log_sense(struct scsi_cmnd * scp,
                        arr[3] = resp_ie_l_pg(arr + 4);
                        break;
                default:
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        return check_condition_result;
                }
@@ -1673,12 +1806,12 @@ static int resp_log_sense(struct scsi_cmnd * scp,
                        arr[3] = n - 4;
                        break;
                default:
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        return check_condition_result;
                }
        } else {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST,
                                INVALID_FIELD_IN_CDB, 0);
                return check_condition_result;
        }
@@ -1687,16 +1820,16 @@ static int resp_log_sense(struct scsi_cmnd * scp,
                    min(len, SDEBUG_MAX_INQ_ARR_SZ));
 }
 
-static int check_device_access_params(struct sdebug_dev_info *devi,
+static int check_device_access_params(struct scsi_cmnd *scp,
                                      unsigned long long lba, unsigned int num)
 {
        if (lba + num > sdebug_capacity) {
-               mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
                return check_condition_result;
        }
        /* transfer length excessive (tie in to block limits VPD page) */
        if (num > sdebug_store_sectors) {
-               mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
                return check_condition_result;
        }
        return 0;
@@ -1704,7 +1837,6 @@ static int check_device_access_params(struct sdebug_dev_info *devi,
 
 /* Returns number of bytes copied or -1 if error. */
 static int do_device_access(struct scsi_cmnd *scmd,
-                           struct sdebug_dev_info *devi,
                            unsigned long long lba, unsigned int num, int write)
 {
        int ret;
@@ -1861,13 +1993,12 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
 }
 
 static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
-                    unsigned int num, struct sdebug_dev_info *devip,
-                    u32 ei_lba)
+                    unsigned int num, u32 ei_lba)
 {
        unsigned long iflags;
        int ret;
 
-       ret = check_device_access_params(devip, lba, num);
+       ret = check_device_access_params(SCpnt, lba, num);
        if (ret)
                return ret;
 
@@ -1875,16 +2006,16 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
            (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
            ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
                /* claim unrecoverable read error */
-               mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
+               mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
                /* set info field and valid bit for fixed descriptor */
-               if (0x70 == (devip->sense_buff[0] & 0x7f)) {
-                       devip->sense_buff[0] |= 0x80;   /* Valid bit */
+               if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) {
+                       SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */
                        ret = (lba < OPT_MEDIUM_ERR_ADDR)
                              ? OPT_MEDIUM_ERR_ADDR : (int)lba;
-                       devip->sense_buff[3] = (ret >> 24) & 0xff;
-                       devip->sense_buff[4] = (ret >> 16) & 0xff;
-                       devip->sense_buff[5] = (ret >> 8) & 0xff;
-                       devip->sense_buff[6] = ret & 0xff;
+                       SCpnt->sense_buffer[3] = (ret >> 24) & 0xff;
+                       SCpnt->sense_buffer[4] = (ret >> 16) & 0xff;
+                       SCpnt->sense_buffer[5] = (ret >> 8) & 0xff;
+                       SCpnt->sense_buffer[6] = ret & 0xff;
                }
                scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
                return check_condition_result;
@@ -1898,12 +2029,12 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
 
                if (prot_ret) {
                        read_unlock_irqrestore(&atomic_rw, iflags);
-                       mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
+                       mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret);
                        return illegal_condition_result;
                }
        }
 
-       ret = do_device_access(SCpnt, devip, lba, num, 0);
+       ret = do_device_access(SCpnt, lba, num, 0);
        read_unlock_irqrestore(&atomic_rw, iflags);
        if (ret == -1)
                return DID_ERROR << 16;
@@ -1915,22 +2046,23 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
 
 void dump_sector(unsigned char *buf, int len)
 {
-       int i, j;
-
-       printk(KERN_ERR ">>> Sector Dump <<<\n");
+       int i, j, n;
 
+       pr_err(">>> Sector Dump <<<\n");
        for (i = 0 ; i < len ; i += 16) {
-               printk(KERN_ERR "%04d: ", i);
+               char b[128];
 
-               for (j = 0 ; j < 16 ; j++) {
+               for (j = 0, n = 0; j < 16; j++) {
                        unsigned char c = buf[i+j];
+
                        if (c >= 0x20 && c < 0x7e)
-                               printk(" %c ", buf[i+j]);
+                               n += scnprintf(b + n, sizeof(b) - n,
+                                              " %c ", buf[i+j]);
                        else
-                               printk("%02x ", buf[i+j]);
+                               n += scnprintf(b + n, sizeof(b) - n,
+                                              "%02x ", buf[i+j]);
                }
-
-               printk("\n");
+               pr_err("%04d: %s\n", i, b);
        }
 }
 
@@ -2092,13 +2224,12 @@ static void unmap_region(sector_t lba, unsigned int len)
 }
 
 static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
-                     unsigned int num, struct sdebug_dev_info *devip,
-                     u32 ei_lba)
+                     unsigned int num, u32 ei_lba)
 {
        unsigned long iflags;
        int ret;
 
-       ret = check_device_access_params(devip, lba, num);
+       ret = check_device_access_params(SCpnt, lba, num);
        if (ret)
                return ret;
 
@@ -2110,12 +2241,13 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
 
                if (prot_ret) {
                        write_unlock_irqrestore(&atomic_rw, iflags);
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10,
+                                       prot_ret);
                        return illegal_condition_result;
                }
        }
 
-       ret = do_device_access(SCpnt, devip, lba, num, 1);
+       ret = do_device_access(SCpnt, lba, num, 1);
        if (scsi_debug_lbp())
                map_region(lba, num);
        write_unlock_irqrestore(&atomic_rw, iflags);
@@ -2123,26 +2255,26 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
                return (DID_ERROR << 16);
        else if ((ret < (num * scsi_debug_sector_size)) &&
                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-               printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
-                      " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
+               sdev_printk(KERN_INFO, SCpnt->device,
+                           "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
+                           my_name, num * scsi_debug_sector_size, ret);
 
        return 0;
 }
 
 static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
-                     unsigned int num, struct sdebug_dev_info *devip,
-                          u32 ei_lba, unsigned int unmap)
+                     unsigned int num, u32 ei_lba, unsigned int unmap)
 {
        unsigned long iflags;
        unsigned long long i;
        int ret;
 
-       ret = check_device_access_params(devip, lba, num);
+       ret = check_device_access_params(scmd, lba, num);
        if (ret)
                return ret;
 
        if (num > scsi_debug_write_same_length) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+               mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
        }
@@ -2164,8 +2296,10 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
                return (DID_ERROR << 16);
        } else if ((ret < (num * scsi_debug_sector_size)) &&
                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-               printk(KERN_INFO "scsi_debug: write same: cdb indicated=%u, "
-                      " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
+               sdev_printk(KERN_INFO, scmd->device,
+                           "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
+                           my_name, "write same",
+                           num * scsi_debug_sector_size, ret);
 
        /* Copy first sector to remaining blocks */
        for (i = 1 ; i < num ; i++)
@@ -2195,7 +2329,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
        int ret;
        unsigned long iflags;
 
-       ret = check_readiness(scmd, 1, devip);
+       ret = check_readiness(scmd, UAS_ONLY, devip);
        if (ret)
                return ret;
 
@@ -2221,7 +2355,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
                unsigned long long lba = get_unaligned_be64(&desc[i].lba);
                unsigned int num = get_unaligned_be32(&desc[i].blocks);
 
-               ret = check_device_access_params(devip, lba, num);
+               ret = check_device_access_params(scmd, lba, num);
                if (ret)
                        goto out;
 
@@ -2247,7 +2381,7 @@ static int resp_get_lba_status(struct scsi_cmnd * scmd,
        unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN];
        int ret;
 
-       ret = check_readiness(scmd, 1, devip);
+       ret = check_readiness(scmd, UAS_ONLY, devip);
        if (ret)
                return ret;
 
@@ -2257,7 +2391,7 @@ static int resp_get_lba_status(struct scsi_cmnd * scmd,
        if (alloc_len < 24)
                return 0;
 
-       ret = check_device_access_params(devip, lba, 1);
+       ret = check_device_access_params(scmd, lba, 1);
        if (ret)
                return ret;
 
@@ -2288,7 +2422,7 @@ static int resp_report_luns(struct scsi_cmnd * scp,
 
        alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
        if ((alloc_len < 4) || (select_report > 2)) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
        }
@@ -2342,7 +2476,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
        /* better not to use temporary buffer. */
        buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
        if (!buf) {
-               mk_sense_buffer(devip, NOT_READY,
+               mk_sense_buffer(scp, NOT_READY,
                                LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
                return check_condition_result;
        }
@@ -2366,34 +2500,125 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
        return 0;
 }
 
-/* When timer goes off this function is called. */
-static void timer_intr_handler(unsigned long indx)
+/* When timer or tasklet goes off this function is called. */
+static void sdebug_q_cmd_complete(unsigned long indx)
 {
-       struct sdebug_queued_cmd * sqcp;
+       int qa_indx;
+       int retiring = 0;
        unsigned long iflags;
+       struct sdebug_queued_cmd *sqcp;
+       struct scsi_cmnd *scp;
+       struct sdebug_dev_info *devip;
 
-       if (indx >= scsi_debug_max_queue) {
-               printk(KERN_ERR "scsi_debug:timer_intr_handler: indx too "
-                      "large\n");
+       atomic_inc(&sdebug_completions);
+       qa_indx = indx;
+       if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
+               pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
                return;
        }
        spin_lock_irqsave(&queued_arr_lock, iflags);
-       sqcp = &queued_arr[(int)indx];
-       if (! sqcp->in_use) {
-               printk(KERN_ERR "scsi_debug:timer_intr_handler: Unexpected "
-                      "interrupt\n");
+       sqcp = &queued_arr[qa_indx];
+       scp = sqcp->a_cmnd;
+       if (NULL == scp) {
+               spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               pr_err("%s: scp is NULL\n", __func__);
+               return;
+       }
+       devip = (struct sdebug_dev_info *)scp->device->hostdata;
+       if (devip)
+               atomic_dec(&devip->num_in_q);
+       else
+               pr_err("%s: devip=NULL\n", __func__);
+       if (atomic_read(&retired_max_queue) > 0)
+               retiring = 1;
+
+       sqcp->a_cmnd = NULL;
+       if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
                spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               pr_err("%s: Unexpected completion\n", __func__);
                return;
        }
-       sqcp->in_use = 0;
-       if (sqcp->done_funct) {
-               sqcp->a_cmnd->result = sqcp->scsi_result;
-               sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
+
+       if (unlikely(retiring)) {       /* user has reduced max_queue */
+               int k, retval;
+
+               retval = atomic_read(&retired_max_queue);
+               if (qa_indx >= retval) {
+                       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+                       pr_err("%s: index %d too large\n", __func__, retval);
+                       return;
+               }
+               k = find_last_bit(queued_in_use_bm, retval);
+               if ((k < scsi_debug_max_queue) || (k == retval))
+                       atomic_set(&retired_max_queue, 0);
+               else
+                       atomic_set(&retired_max_queue, k + 1);
        }
-       sqcp->done_funct = NULL;
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
+       scp->scsi_done(scp); /* callback to mid level */
 }
 
+/* When high resolution timer goes off this function is called. */
+static enum hrtimer_restart
+sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
+{
+       int qa_indx;
+       int retiring = 0;
+       unsigned long iflags;
+       struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
+       struct sdebug_queued_cmd *sqcp;
+       struct scsi_cmnd *scp;
+       struct sdebug_dev_info *devip;
+
+       atomic_inc(&sdebug_completions);
+       qa_indx = sd_hrtp->qa_indx;
+       if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
+               pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
+               goto the_end;
+       }
+       spin_lock_irqsave(&queued_arr_lock, iflags);
+       sqcp = &queued_arr[qa_indx];
+       scp = sqcp->a_cmnd;
+       if (NULL == scp) {
+               spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               pr_err("%s: scp is NULL\n", __func__);
+               goto the_end;
+       }
+       devip = (struct sdebug_dev_info *)scp->device->hostdata;
+       if (devip)
+               atomic_dec(&devip->num_in_q);
+       else
+               pr_err("%s: devip=NULL\n", __func__);
+       if (atomic_read(&retired_max_queue) > 0)
+               retiring = 1;
+
+       sqcp->a_cmnd = NULL;
+       if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
+               spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               pr_err("%s: Unexpected completion\n", __func__);
+               goto the_end;
+       }
+
+       if (unlikely(retiring)) {       /* user has reduced max_queue */
+               int k, retval;
+
+               retval = atomic_read(&retired_max_queue);
+               if (qa_indx >= retval) {
+                       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+                       pr_err("%s: index %d too large\n", __func__, retval);
+                       goto the_end;
+               }
+               k = find_last_bit(queued_in_use_bm, retval);
+               if ((k < scsi_debug_max_queue) || (k == retval))
+                       atomic_set(&retired_max_queue, 0);
+               else
+                       atomic_set(&retired_max_queue, k + 1);
+       }
+       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+       scp->scsi_done(scp); /* callback to mid level */
+the_end:
+       return HRTIMER_NORESTART;
+}
 
 static struct sdebug_dev_info *
 sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
@@ -2419,7 +2644,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
                return devip;
        sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
        if (!sdbg_host) {
-                printk(KERN_ERR "Host info NULL\n");
+               pr_err("%s: Host info NULL\n", __func__);
                return NULL;
         }
        list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
@@ -2445,15 +2670,9 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
        open_devip->target = sdev->id;
        open_devip->lun = sdev->lun;
        open_devip->sdbg_host = sdbg_host;
-       open_devip->reset = 1;
+       atomic_set(&open_devip->num_in_q, 0);
+       set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
        open_devip->used = 1;
-       memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
-       if (scsi_debug_dsense)
-               open_devip->sense_buff[0] = 0x72;
-       else {
-               open_devip->sense_buff[0] = 0x70;
-               open_devip->sense_buff[7] = 0xa;
-       }
        if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
                open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
 
@@ -2482,9 +2701,10 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp)
        if (NULL == devip)
                return 1;       /* no resources, will be marked offline */
        sdp->hostdata = devip;
+       sdp->tagged_supported = 1;
        if (sdp->host->cmd_per_lun)
-               scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
-                                       sdp->host->cmd_per_lun);
+               scsi_adjust_queue_depth(sdp, DEF_TAGGED_QUEUING,
+                                       DEF_CMD_PER_LUN);
        blk_queue_max_segment_size(sdp->request_queue, -1U);
        if (scsi_debug_no_uld)
                sdp->no_uld_attach = 1;
@@ -2506,150 +2726,230 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp)
        }
 }
 
-/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
+/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
 static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 {
        unsigned long iflags;
-       int k;
+       int k, qmax, r_qmax;
        struct sdebug_queued_cmd *sqcp;
+       struct sdebug_dev_info *devip;
 
        spin_lock_irqsave(&queued_arr_lock, iflags);
-       for (k = 0; k < scsi_debug_max_queue; ++k) {
-               sqcp = &queued_arr[k];
-               if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
-                       del_timer_sync(&sqcp->cmnd_timer);
-                       sqcp->in_use = 0;
-                       sqcp->a_cmnd = NULL;
-                       break;
+       qmax = scsi_debug_max_queue;
+       r_qmax = atomic_read(&retired_max_queue);
+       if (r_qmax > qmax)
+               qmax = r_qmax;
+       for (k = 0; k < qmax; ++k) {
+               if (test_bit(k, queued_in_use_bm)) {
+                       sqcp = &queued_arr[k];
+                       if (cmnd == sqcp->a_cmnd) {
+                               if (scsi_debug_ndelay > 0) {
+                                       if (sqcp->sd_hrtp)
+                                               hrtimer_cancel(
+                                                       &sqcp->sd_hrtp->hrt);
+                               } else if (scsi_debug_delay > 0) {
+                                       if (sqcp->cmnd_timerp)
+                                               del_timer_sync(
+                                                       sqcp->cmnd_timerp);
+                               } else if (scsi_debug_delay < 0) {
+                                       if (sqcp->tletp)
+                                               tasklet_kill(sqcp->tletp);
+                               }
+                               __clear_bit(k, queued_in_use_bm);
+                               devip = (struct sdebug_dev_info *)
+                                       cmnd->device->hostdata;
+                               if (devip)
+                                       atomic_dec(&devip->num_in_q);
+                               sqcp->a_cmnd = NULL;
+                               break;
+                       }
                }
        }
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
-       return (k < scsi_debug_max_queue) ? 1 : 0;
+       return (k < qmax) ? 1 : 0;
 }
 
-/* Deletes (stops) timers of all queued commands */
+/* Deletes (stops) timers or tasklets of all queued commands */
 static void stop_all_queued(void)
 {
        unsigned long iflags;
        int k;
        struct sdebug_queued_cmd *sqcp;
+       struct sdebug_dev_info *devip;
 
        spin_lock_irqsave(&queued_arr_lock, iflags);
-       for (k = 0; k < scsi_debug_max_queue; ++k) {
-               sqcp = &queued_arr[k];
-               if (sqcp->in_use && sqcp->a_cmnd) {
-                       del_timer_sync(&sqcp->cmnd_timer);
-                       sqcp->in_use = 0;
-                       sqcp->a_cmnd = NULL;
+       for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+               if (test_bit(k, queued_in_use_bm)) {
+                       sqcp = &queued_arr[k];
+                       if (sqcp->a_cmnd) {
+                               if (scsi_debug_ndelay > 0) {
+                                       if (sqcp->sd_hrtp)
+                                               hrtimer_cancel(
+                                                       &sqcp->sd_hrtp->hrt);
+                               } else if (scsi_debug_delay > 0) {
+                                       if (sqcp->cmnd_timerp)
+                                               del_timer_sync(
+                                                       sqcp->cmnd_timerp);
+                               } else if (scsi_debug_delay < 0) {
+                                       if (sqcp->tletp)
+                                               tasklet_kill(sqcp->tletp);
+                               }
+                               __clear_bit(k, queued_in_use_bm);
+                               devip = (struct sdebug_dev_info *)
+                                       sqcp->a_cmnd->device->hostdata;
+                               if (devip)
+                                       atomic_dec(&devip->num_in_q);
+                               sqcp->a_cmnd = NULL;
+                       }
                }
        }
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
+/* Free queued command memory on heap */
+static void free_all_queued(void)
 {
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: abort\n");
-       ++num_aborts;
-       stop_queued_cmnd(SCpnt);
-       return SUCCESS;
+       unsigned long iflags;
+       int k;
+       struct sdebug_queued_cmd *sqcp;
+
+       spin_lock_irqsave(&queued_arr_lock, iflags);
+       for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+               sqcp = &queued_arr[k];
+               kfree(sqcp->cmnd_timerp);
+               sqcp->cmnd_timerp = NULL;
+               kfree(sqcp->tletp);
+               sqcp->tletp = NULL;
+               kfree(sqcp->sd_hrtp);
+               sqcp->sd_hrtp = NULL;
+       }
+       spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int scsi_debug_biosparam(struct scsi_device *sdev,
-               struct block_device * bdev, sector_t capacity, int *info)
+static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
 {
-       int res;
-       unsigned char *buf;
-
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: biosparam\n");
-       buf = scsi_bios_ptable(bdev);
-       if (buf) {
-               res = scsi_partsize(buf, capacity,
-                                   &info[2], &info[0], &info[1]);
-               kfree(buf);
-               if (! res)
-                       return res;
-       }
-       info[0] = sdebug_heads;
-       info[1] = sdebug_sectors_per;
-       info[2] = sdebug_cylinders_per;
-       return 0;
+       ++num_aborts;
+       if (SCpnt) {
+               if (SCpnt->device &&
+                   (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
+                       sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
+                                   __func__);
+               stop_queued_cmnd(SCpnt);
+       }
+       return SUCCESS;
 }
 
 static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
 {
        struct sdebug_dev_info * devip;
 
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: device_reset\n");
        ++num_dev_resets;
-       if (SCpnt) {
-               devip = devInfoReg(SCpnt->device);
+       if (SCpnt && SCpnt->device) {
+               struct scsi_device *sdp = SCpnt->device;
+
+               if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+                       sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+               devip = devInfoReg(sdp);
                if (devip)
-                       devip->reset = 1;
+                       set_bit(SDEBUG_UA_POR, devip->uas_bm);
+       }
+       return SUCCESS;
+}
+
+static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
+{
+       struct sdebug_host_info *sdbg_host;
+       struct sdebug_dev_info *devip;
+       struct scsi_device *sdp;
+       struct Scsi_Host *hp;
+       int k = 0;
+
+       ++num_target_resets;
+       if (!SCpnt)
+               goto lie;
+       sdp = SCpnt->device;
+       if (!sdp)
+               goto lie;
+       if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+               sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+       hp = sdp->host;
+       if (!hp)
+               goto lie;
+       sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
+       if (sdbg_host) {
+               list_for_each_entry(devip,
+                                   &sdbg_host->dev_info_list,
+                                   dev_list)
+                       if (devip->target == sdp->id) {
+                               set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
+                               ++k;
+                       }
        }
+       if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+               sdev_printk(KERN_INFO, sdp,
+                           "%s: %d device(s) found in target\n", __func__, k);
+lie:
        return SUCCESS;
 }
 
 static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
 {
        struct sdebug_host_info *sdbg_host;
-        struct sdebug_dev_info * dev_info;
+       struct sdebug_dev_info *devip;
         struct scsi_device * sdp;
         struct Scsi_Host * hp;
+       int k = 0;
 
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: bus_reset\n");
        ++num_bus_resets;
-       if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+       if (!(SCpnt && SCpnt->device))
+               goto lie;
+       sdp = SCpnt->device;
+       if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+               sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+       hp = sdp->host;
+       if (hp) {
                sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
                if (sdbg_host) {
-                       list_for_each_entry(dev_info,
+                       list_for_each_entry(devip,
                                             &sdbg_host->dev_info_list,
-                                            dev_list)
-                               dev_info->reset = 1;
+                                           dev_list) {
+                               set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
+                               ++k;
+                       }
                }
        }
+       if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+               sdev_printk(KERN_INFO, sdp,
+                           "%s: %d device(s) found in host\n", __func__, k);
+lie:
        return SUCCESS;
 }
 
 static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
 {
        struct sdebug_host_info * sdbg_host;
-        struct sdebug_dev_info * dev_info;
+       struct sdebug_dev_info *devip;
+       int k = 0;
 
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: host_reset\n");
        ++num_host_resets;
+       if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
+               sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
         spin_lock(&sdebug_host_list_lock);
         list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
-                list_for_each_entry(dev_info, &sdbg_host->dev_info_list,
-                                    dev_list)
-                        dev_info->reset = 1;
+               list_for_each_entry(devip, &sdbg_host->dev_info_list,
+                                   dev_list) {
+                       set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
+                       ++k;
+               }
         }
         spin_unlock(&sdebug_host_list_lock);
        stop_all_queued();
+       if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+               sdev_printk(KERN_INFO, SCpnt->device,
+                           "%s: %d device(s) found\n", __func__, k);
        return SUCCESS;
 }
 
-/* Initializes timers in queued array */
-static void __init init_all_queued(void)
-{
-       unsigned long iflags;
-       int k;
-       struct sdebug_queued_cmd * sqcp;
-
-       spin_lock_irqsave(&queued_arr_lock, iflags);
-       for (k = 0; k < scsi_debug_max_queue; ++k) {
-               sqcp = &queued_arr[k];
-               init_timer(&sqcp->cmnd_timer);
-               sqcp->in_use = 0;
-               sqcp->a_cmnd = NULL;
-       }
-       spin_unlock_irqrestore(&queued_arr_lock, iflags);
-}
-
 static void __init sdebug_build_parts(unsigned char *ramp,
                                      unsigned long store_size)
 {
@@ -2663,8 +2963,8 @@ static void __init sdebug_build_parts(unsigned char *ramp,
                return;
        if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
                scsi_debug_num_parts = SDEBUG_MAX_PARTS;
-               printk(KERN_WARNING "scsi_debug:build_parts: reducing "
-                                   "partitions to %d\n", SDEBUG_MAX_PARTS);
+               pr_warn("%s: reducing partitions to %d\n", __func__,
+                       SDEBUG_MAX_PARTS);
        }
        num_sectors = (int)sdebug_store_sectors;
        sectors_per_part = (num_sectors - sdebug_sectors_per)
@@ -2701,62 +3001,130 @@ static void __init sdebug_build_parts(unsigned char *ramp,
        }
 }
 
-static int schedule_resp(struct scsi_cmnd * cmnd,
-                        struct sdebug_dev_info * devip,
-                        done_funct_t done, int scsi_result, int delta_jiff)
+static int
+schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
+             int scsi_result, int delta_jiff)
 {
-       if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) {
-               if (scsi_result) {
-                       struct scsi_device * sdp = cmnd->device;
+       unsigned long iflags;
+       int k, num_in_q, tsf, qdepth, inject;
+       struct sdebug_queued_cmd *sqcp = NULL;
+       struct scsi_device *sdp = cmnd->device;
+
+       if (NULL == cmnd || NULL == devip) {
+               pr_warn("%s: called with NULL cmnd or devip pointer\n",
+                       __func__);
+               /* no particularly good error to report back */
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+       if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+               sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
+                           __func__, scsi_result);
+       if (delta_jiff == 0) {
+               /* using same thread to call back mid-layer */
+               cmnd->result = scsi_result;
+               cmnd->scsi_done(cmnd);
+               return 0;
+       }
 
-                       printk(KERN_INFO "scsi_debug:    <%u %u %u %llu> "
-                              "non-zero result=0x%x\n", sdp->host->host_no,
-                              sdp->channel, sdp->id, sdp->lun, scsi_result);
+       /* deferred response cases */
+       spin_lock_irqsave(&queued_arr_lock, iflags);
+       num_in_q = atomic_read(&devip->num_in_q);
+       qdepth = cmnd->device->queue_depth;
+       k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
+       tsf = 0;
+       inject = 0;
+       if ((qdepth > 0) && (num_in_q >= qdepth))
+               tsf = 1;
+       else if ((scsi_debug_every_nth != 0) &&
+                (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts)) {
+               if ((num_in_q == (qdepth - 1)) &&
+                   (atomic_inc_return(&sdebug_a_tsf) >=
+                    abs(scsi_debug_every_nth))) {
+                       atomic_set(&sdebug_a_tsf, 0);
+                       inject = 1;
+                       tsf = 1;
                }
        }
-       if (cmnd && devip) {
-               /* simulate autosense by this driver */
-               if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
-                       memcpy(cmnd->sense_buffer, devip->sense_buff,
-                              (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
-                              SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
-       }
-       if (delta_jiff <= 0) {
-               if (cmnd)
-                       cmnd->result = scsi_result;
-               if (done)
-                       done(cmnd);
-               return 0;
-       } else {
-               unsigned long iflags;
-               int k;
-               struct sdebug_queued_cmd * sqcp = NULL;
 
-               spin_lock_irqsave(&queued_arr_lock, iflags);
-               for (k = 0; k < scsi_debug_max_queue; ++k) {
-                       sqcp = &queued_arr[k];
-                       if (! sqcp->in_use)
-                               break;
+       /* if (tsf) simulate device reporting SCSI status of TASK SET FULL.
+        * Might override existing CHECK CONDITION. */
+       if (tsf)
+               scsi_result = device_qfull_result;
+       if (k >= scsi_debug_max_queue) {
+               if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
+                       tsf = 1;
+               spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
+                       sdev_printk(KERN_INFO, sdp,
+                                   "%s: num_in_q=%d, bypass q, %s%s\n",
+                                   __func__, num_in_q,
+                                   (inject ? "<inject> " : ""),
+                                   (tsf ?  "status: TASK SET FULL" :
+                                           "report: host busy"));
+               if (tsf) {
+                       /* queued_arr full so respond in same thread */
+                       cmnd->result = scsi_result;
+                       cmnd->scsi_done(cmnd);
+                       /* As scsi_done() is called "inline" must return 0 */
+                       return 0;
+               } else
+                       return SCSI_MLQUEUE_HOST_BUSY;
+       }
+       __set_bit(k, queued_in_use_bm);
+       atomic_inc(&devip->num_in_q);
+       sqcp = &queued_arr[k];
+       sqcp->a_cmnd = cmnd;
+       cmnd->result = scsi_result;
+       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+       if (delta_jiff > 0) {
+               if (NULL == sqcp->cmnd_timerp) {
+                       sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
+                                                   GFP_ATOMIC);
+                       if (NULL == sqcp->cmnd_timerp)
+                               return SCSI_MLQUEUE_HOST_BUSY;
+                       init_timer(sqcp->cmnd_timerp);
                }
-               if (k >= scsi_debug_max_queue) {
-                       spin_unlock_irqrestore(&queued_arr_lock, iflags);
-                       printk(KERN_WARNING "scsi_debug: can_queue exceeded\n");
-                       return 1;       /* report busy to mid level */
+               sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
+               sqcp->cmnd_timerp->data = k;
+               sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
+               add_timer(sqcp->cmnd_timerp);
+       } else if (scsi_debug_ndelay > 0) {
+               ktime_t kt = ktime_set(0, scsi_debug_ndelay);
+               struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
+
+               if (NULL == sd_hp) {
+                       sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
+                       if (NULL == sd_hp)
+                               return SCSI_MLQUEUE_HOST_BUSY;
+                       sqcp->sd_hrtp = sd_hp;
+                       hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
+                                    HRTIMER_MODE_REL);
+                       sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
+                       sd_hp->qa_indx = k;
                }
-               sqcp->in_use = 1;
-               sqcp->a_cmnd = cmnd;
-               sqcp->scsi_result = scsi_result;
-               sqcp->done_funct = done;
-               sqcp->cmnd_timer.function = timer_intr_handler;
-               sqcp->cmnd_timer.data = k;
-               sqcp->cmnd_timer.expires = jiffies + delta_jiff;
-               add_timer(&sqcp->cmnd_timer);
-               spin_unlock_irqrestore(&queued_arr_lock, iflags);
-               if (cmnd)
-                       cmnd->result = 0;
-               return 0;
+               hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
+       } else {        /* delay < 0 */
+               if (NULL == sqcp->tletp) {
+                       sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
+                                             GFP_ATOMIC);
+                       if (NULL == sqcp->tletp)
+                               return SCSI_MLQUEUE_HOST_BUSY;
+                       tasklet_init(sqcp->tletp,
+                                    sdebug_q_cmd_complete, k);
+               }
+               if (-1 == delta_jiff)
+                       tasklet_hi_schedule(sqcp->tletp);
+               else
+                       tasklet_schedule(sqcp->tletp);
        }
+       if (tsf && (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts))
+               sdev_printk(KERN_INFO, sdp,
+                           "%s: num_in_q=%d +1, %s%s\n", __func__,
+                           num_in_q, (inject ? "<inject> " : ""),
+                           "status: TASK SET FULL");
+       return 0;
 }
+
 /* Note: The following macros create attribute files in the
    /sys/module/scsi_debug/parameters directory. Unfortunately this
    driver is unaware of a change and cannot trigger auxiliary actions
@@ -2774,6 +3142,7 @@ module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
 module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
 module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
 module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
+module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
 module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
 module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
 module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
@@ -2781,6 +3150,7 @@ module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
 module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
 module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
 module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
+module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
 module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
 module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
 module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
@@ -2810,7 +3180,7 @@ MODULE_VERSION(SCSI_DEBUG_VERSION);
 MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
 MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
 MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
-MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
+MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
 MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
 MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
@@ -2818,13 +3188,15 @@ MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
 MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
 MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
+MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
 MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
 MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
 MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
 MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
 MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
 MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
-MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))");
+MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
+MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
 MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
@@ -2855,9 +3227,7 @@ static const char * scsi_debug_info(struct Scsi_Host * shp)
        return sdebug_info;
 }
 
-/* scsi_debug_proc_info
- * Used if the driver currently has no own support for /proc/scsi
- */
+/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
 static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
        char arr[16];
@@ -2872,27 +3242,49 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int lengt
                return -EINVAL;
        scsi_debug_opts = opts;
        if (scsi_debug_every_nth != 0)
-               scsi_debug_cmnd_count = 0;
+               atomic_set(&sdebug_cmnd_count, 0);
        return length;
 }
 
+/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
+ * same for each scsi_debug host (if more than one). Some of the counters
+ * output are not atomics so might be inaccurate in a busy system. */
 static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-       seq_printf(m, "scsi_debug adapter driver, version "
-           "%s [%s]\n"
-           "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
-           "every_nth=%d(curr:%d)\n"
-           "delay=%d, max_luns=%d, scsi_level=%d\n"
-           "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
-           "number of aborts=%d, device_reset=%d, bus_resets=%d, "
-           "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n",
-           SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts,
-           scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
-           scsi_debug_cmnd_count, scsi_debug_delay,
-           scsi_debug_max_luns, scsi_debug_scsi_level,
-           scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
-           sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
-           num_host_resets, dix_reads, dix_writes, dif_errors);
+       int f, l;
+       char b[32];
+
+       if (scsi_debug_every_nth > 0)
+               snprintf(b, sizeof(b), " (curr:%d)",
+                        ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
+                               atomic_read(&sdebug_a_tsf) :
+                               atomic_read(&sdebug_cmnd_count)));
+       else
+               b[0] = '\0';
+
+       seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
+               "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
+               "every_nth=%d%s\n"
+               "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
+               "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
+               "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
+               "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
+               "usec_in_jiffy=%lu\n",
+               SCSI_DEBUG_VERSION, scsi_debug_version_date,
+               scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
+               scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
+               scsi_debug_max_luns, atomic_read(&sdebug_completions),
+               scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
+               sdebug_sectors_per, num_aborts, num_dev_resets,
+               num_target_resets, num_bus_resets, num_host_resets,
+               dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
+
+       f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
+       if (f != scsi_debug_max_queue) {
+               l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
+               seq_printf(m, "   %s BUSY: first,last bits set: %d,%d\n",
+                          "queued_in_use_bm", f, l);
+       }
        return 0;
 }
 
@@ -2900,23 +3292,69 @@ static ssize_t delay_show(struct device_driver *ddp, char *buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
 }
-
+/* Returns -EBUSY if delay is being changed and commands are queued */
 static ssize_t delay_store(struct device_driver *ddp, const char *buf,
                           size_t count)
 {
-        int delay;
-       char work[20];
-
-        if (1 == sscanf(buf, "%10s", work)) {
-               if ((1 == sscanf(work, "%d", &delay)) && (delay >= 0)) {
-                       scsi_debug_delay = delay;
-                       return count;
+       int delay, res;
+
+       if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
+               res = count;
+               if (scsi_debug_delay != delay) {
+                       unsigned long iflags;
+                       int k;
+
+                       spin_lock_irqsave(&queued_arr_lock, iflags);
+                       k = find_first_bit(queued_in_use_bm,
+                                          scsi_debug_max_queue);
+                       if (k != scsi_debug_max_queue)
+                               res = -EBUSY;   /* have queued commands */
+                       else {
+                               scsi_debug_delay = delay;
+                               scsi_debug_ndelay = 0;
+                       }
+                       spin_unlock_irqrestore(&queued_arr_lock, iflags);
                }
+               return res;
        }
        return -EINVAL;
 }
 static DRIVER_ATTR_RW(delay);
 
+static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
+}
+/* Returns -EBUSY if ndelay is being changed and commands are queued */
+/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
+static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
+                          size_t count)
+{
+       unsigned long iflags;
+       int ndelay, res, k;
+
+       if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
+           (ndelay >= 0) && (ndelay < 1000000000)) {
+               res = count;
+               if (scsi_debug_ndelay != ndelay) {
+                       spin_lock_irqsave(&queued_arr_lock, iflags);
+                       k = find_first_bit(queued_in_use_bm,
+                                          scsi_debug_max_queue);
+                       if (k != scsi_debug_max_queue)
+                               res = -EBUSY;   /* have queued commands */
+                       else {
+                               scsi_debug_ndelay = ndelay;
+                               scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
+                                                         : DEF_DELAY;
+                       }
+                       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               }
+               return res;
+       }
+       return -EINVAL;
+}
+static DRIVER_ATTR_RW(ndelay);
+
 static ssize_t opts_show(struct device_driver *ddp, char *buf)
 {
         return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
@@ -2940,7 +3378,8 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
        return -EINVAL;
 opts_done:
        scsi_debug_opts = opts;
-       scsi_debug_cmnd_count = 0;
+       atomic_set(&sdebug_cmnd_count, 0);
+       atomic_set(&sdebug_a_tsf, 0);
        return count;
 }
 static DRIVER_ATTR_RW(opts);
@@ -2989,7 +3428,24 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
         int n;
 
        if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-               scsi_debug_fake_rw = n;
+               n = (n > 0);
+               scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
+               if (scsi_debug_fake_rw != n) {
+                       if ((0 == n) && (NULL == fake_storep)) {
+                               unsigned long sz =
+                                       (unsigned long)scsi_debug_dev_size_mb *
+                                       1048576;
+
+                               fake_storep = vmalloc(sz);
+                               if (NULL == fake_storep) {
+                                       pr_err("%s: out of memory, 9\n",
+                                              __func__);
+                                       return -ENOMEM;
+                               }
+                               memset(fake_storep, 0, sz);
+                       }
+                       scsi_debug_fake_rw = n;
+               }
                return count;
        }
        return -EINVAL;
@@ -3054,7 +3510,7 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
 
        if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
                scsi_debug_every_nth = nth;
-               scsi_debug_cmnd_count = 0;
+               atomic_set(&sdebug_cmnd_count, 0);
                return count;
        }
        return -EINVAL;
@@ -3083,14 +3539,26 @@ static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
 }
+/* N.B. max_queue can be changed while there are queued commands. In flight
+ * commands beyond the new max_queue will be completed. */
 static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
                               size_t count)
 {
-        int n;
+       unsigned long iflags;
+       int n, k;
 
        if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
            (n <= SCSI_DEBUG_CANQUEUE)) {
+               spin_lock_irqsave(&queued_arr_lock, iflags);
+               k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
                scsi_debug_max_queue = n;
+               if (SCSI_DEBUG_CANQUEUE == k)
+                       atomic_set(&retired_max_queue, 0);
+               else if (k >= n)
+                       atomic_set(&retired_max_queue, k + 1);
+               else
+                       atomic_set(&retired_max_queue, 0);
+               spin_unlock_irqrestore(&queued_arr_lock, iflags);
                return count;
        }
        return -EINVAL;
@@ -3235,6 +3703,40 @@ static ssize_t removable_store(struct device_driver *ddp, const char *buf,
 }
 static DRIVER_ATTR_RW(removable);
 
+static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
+}
+/* Returns -EBUSY if host_lock is being changed and commands are queued */
+static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
+                              size_t count)
+{
+       int n, res;
+
+       if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+               bool new_host_lock = (n > 0);
+
+               res = count;
+               if (new_host_lock != scsi_debug_host_lock) {
+                       unsigned long iflags;
+                       int k;
+
+                       spin_lock_irqsave(&queued_arr_lock, iflags);
+                       k = find_first_bit(queued_in_use_bm,
+                                          scsi_debug_max_queue);
+                       if (k != scsi_debug_max_queue)
+                               res = -EBUSY;   /* have queued commands */
+                       else
+                               scsi_debug_host_lock = new_host_lock;
+                       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               }
+               return res;
+       }
+       return -EINVAL;
+}
+static DRIVER_ATTR_RW(host_lock);
+
+
 /* Note: The following array creates attribute files in the
    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
    files (over those found in the /sys/module/scsi_debug/parameters
@@ -3267,6 +3769,8 @@ static struct attribute *sdebug_drv_attrs[] = {
        &driver_attr_ato.attr,
        &driver_attr_map.attr,
        &driver_attr_removable.attr,
+       &driver_attr_host_lock.attr,
+       &driver_attr_ndelay.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(sdebug_drv);
@@ -3280,6 +3784,17 @@ static int __init scsi_debug_init(void)
        int k;
        int ret;
 
+       atomic_set(&sdebug_cmnd_count, 0);
+       atomic_set(&sdebug_completions, 0);
+       atomic_set(&retired_max_queue, 0);
+
+       if (scsi_debug_ndelay >= 1000000000) {
+               pr_warn("%s: ndelay must be less than 1 second, ignored\n",
+                       __func__);
+               scsi_debug_ndelay = 0;
+       } else if (scsi_debug_ndelay > 0)
+               scsi_debug_delay = DELAY_OVERRIDDEN;
+
        switch (scsi_debug_sector_size) {
        case  512:
        case 1024:
@@ -3287,7 +3802,7 @@ static int __init scsi_debug_init(void)
        case 4096:
                break;
        default:
-               printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n",
+               pr_err("%s: invalid sector_size %d\n", __func__,
                       scsi_debug_sector_size);
                return -EINVAL;
        }
@@ -3301,28 +3816,28 @@ static int __init scsi_debug_init(void)
                break;
 
        default:
-               printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n");
+               pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__);
                return -EINVAL;
        }
 
        if (scsi_debug_guard > 1) {
-               printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n");
+               pr_err("%s: guard must be 0 or 1\n", __func__);
                return -EINVAL;
        }
 
        if (scsi_debug_ato > 1) {
-               printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n");
+               pr_err("%s: ato must be 0 or 1\n", __func__);
                return -EINVAL;
        }
 
        if (scsi_debug_physblk_exp > 15) {
-               printk(KERN_ERR "scsi_debug_init: invalid physblk_exp %u\n",
+               pr_err("%s: invalid physblk_exp %u\n", __func__,
                       scsi_debug_physblk_exp);
                return -EINVAL;
        }
 
        if (scsi_debug_lowest_aligned > 0x3fff) {
-               printk(KERN_ERR "scsi_debug_init: lowest_aligned too big: %u\n",
+               pr_err("%s: lowest_aligned too big: %u\n", __func__,
                       scsi_debug_lowest_aligned);
                return -EINVAL;
        }
@@ -3350,14 +3865,16 @@ static int __init scsi_debug_init(void)
                               (sdebug_sectors_per * sdebug_heads);
        }
 
-       fake_storep = vmalloc(sz);
-       if (NULL == fake_storep) {
-               printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
-               return -ENOMEM;
+       if (0 == scsi_debug_fake_rw) {
+               fake_storep = vmalloc(sz);
+               if (NULL == fake_storep) {
+                       pr_err("%s: out of memory, 1\n", __func__);
+                       return -ENOMEM;
+               }
+               memset(fake_storep, 0, sz);
+               if (scsi_debug_num_parts > 0)
+                       sdebug_build_parts(fake_storep, sz);
        }
-       memset(fake_storep, 0, sz);
-       if (scsi_debug_num_parts > 0)
-               sdebug_build_parts(fake_storep, sz);
 
        if (scsi_debug_dix) {
                int dif_size;
@@ -3365,11 +3882,11 @@ static int __init scsi_debug_init(void)
                dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
                dif_storep = vmalloc(dif_size);
 
-               printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n",
-                      dif_size, dif_storep);
+               pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size,
+                       dif_storep);
 
                if (dif_storep == NULL) {
-                       printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n");
+                       pr_err("%s: out of mem. (DIX)\n", __func__);
                        ret = -ENOMEM;
                        goto free_vm;
                }
@@ -3391,8 +3908,7 @@ static int __init scsi_debug_init(void)
                if (scsi_debug_unmap_alignment &&
                    scsi_debug_unmap_granularity <=
                    scsi_debug_unmap_alignment) {
-                       printk(KERN_ERR
-                              "%s: ERR: unmap_granularity <= unmap_alignment\n",
+                       pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n",
                               __func__);
                        return -EINVAL;
                }
@@ -3400,11 +3916,10 @@ static int __init scsi_debug_init(void)
                map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
                map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
 
-               printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
-                      map_size);
+               pr_info("%s: %lu provisioning blocks\n", __func__, map_size);
 
                if (map_storep == NULL) {
-                       printk(KERN_ERR "scsi_debug_init: out of mem. (MAP)\n");
+                       pr_err("%s: out of mem. (MAP)\n", __func__);
                        ret = -ENOMEM;
                        goto free_vm;
                }
@@ -3418,39 +3933,35 @@ static int __init scsi_debug_init(void)
 
        pseudo_primary = root_device_register("pseudo_0");
        if (IS_ERR(pseudo_primary)) {
-               printk(KERN_WARNING "scsi_debug: root_device_register() error\n");
+               pr_warn("%s: root_device_register() error\n", __func__);
                ret = PTR_ERR(pseudo_primary);
                goto free_vm;
        }
        ret = bus_register(&pseudo_lld_bus);
        if (ret < 0) {
-               printk(KERN_WARNING "scsi_debug: bus_register error: %d\n",
-                       ret);
+               pr_warn("%s: bus_register error: %d\n", __func__, ret);
                goto dev_unreg;
        }
        ret = driver_register(&sdebug_driverfs_driver);
        if (ret < 0) {
-               printk(KERN_WARNING "scsi_debug: driver_register error: %d\n",
-                       ret);
+               pr_warn("%s: driver_register error: %d\n", __func__, ret);
                goto bus_unreg;
        }
 
-       init_all_queued();
-
        host_to_add = scsi_debug_add_host;
         scsi_debug_add_host = 0;
 
         for (k = 0; k < host_to_add; k++) {
                 if (sdebug_add_adapter()) {
-                        printk(KERN_ERR "scsi_debug_init: "
-                               "sdebug_add_adapter failed k=%d\n", k);
+                       pr_err("%s: sdebug_add_adapter failed k=%d\n",
+                               __func__, k);
                         break;
                 }
         }
 
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
-               printk(KERN_INFO "scsi_debug_init: built %d host(s)\n",
-                      scsi_debug_add_host);
+               pr_info("%s: built %d host(s)\n", __func__,
+                       scsi_debug_add_host);
        }
        return 0;
 
@@ -3473,6 +3984,7 @@ static void __exit scsi_debug_exit(void)
        int k = scsi_debug_add_host;
 
        stop_all_queued();
+       free_all_queued();
        for (; k; k--)
                sdebug_remove_adapter();
        driver_unregister(&sdebug_driverfs_driver);
@@ -3570,8 +4082,8 @@ static void sdebug_remove_adapter(void)
         --scsi_debug_add_host;
 }
 
-static
-int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
+static int
+scsi_debug_queuecommand(struct scsi_cmnd *SCpnt)
 {
        unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
        int len, k;
@@ -3590,32 +4102,34 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
        int unmap = 0;
 
        scsi_set_resid(SCpnt, 0);
-       if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
-               printk(KERN_INFO "scsi_debug: cmd ");
-               for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
-                       printk("%02x ", (int)cmd[k]);
-               printk("\n");
-       }
-
-       if (target == SCpnt->device->host->hostt->this_id) {
-               printk(KERN_INFO "scsi_debug: initiator's id used as "
-                      "target!\n");
-               return schedule_resp(SCpnt, NULL, done,
-                                    DID_NO_CONNECT << 16, 0);
+       if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) &&
+           !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts) && cmd) {
+               char b[120];
+               int n;
+
+               len = SCpnt->cmd_len;
+               if (len > 32)
+                       strcpy(b, "too long, over 32 bytes");
+               else {
+                       for (k = 0, n = 0; k < len; ++k)
+                               n += scnprintf(b + n, sizeof(b) - n, "%02x ",
+                                              (unsigned int)cmd[k]);
+               }
+               sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name,
+                           b);
        }
 
        if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
            (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
-               return schedule_resp(SCpnt, NULL, done,
-                                    DID_NO_CONNECT << 16, 0);
+               return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
        devip = devInfoReg(SCpnt->device);
        if (NULL == devip)
-               return schedule_resp(SCpnt, NULL, done,
-                                    DID_NO_CONNECT << 16, 0);
+               return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
 
        if ((scsi_debug_every_nth != 0) &&
-           (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
-               scsi_debug_cmnd_count = 0;
+           (atomic_inc_return(&sdebug_cmnd_count) >=
+            abs(scsi_debug_every_nth))) {
+               atomic_set(&sdebug_cmnd_count, 0);
                if (scsi_debug_every_nth < -1)
                        scsi_debug_every_nth = -1;
                if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
@@ -3646,11 +4160,10 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
                        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                                printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
                                       "not supported for wlun\n", *cmd);
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_OPCODE, 0);
                        errsts = check_condition_result;
-                       return schedule_resp(SCpnt, devip, done, errsts,
-                                            0);
+                       return schedule_resp(SCpnt, devip, errsts, 0);
                }
        }
 
@@ -3668,7 +4181,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
                errsts = resp_start_stop(SCpnt, devip);
                break;
        case ALLOW_MEDIUM_REMOVAL:
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                if (errsts)
                        break;
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
@@ -3676,23 +4189,23 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
                               cmd[4] ? "inhibited" : "enabled");
                break;
        case SEND_DIAGNOSTIC:     /* mandatory */
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                break;
        case TEST_UNIT_READY:     /* mandatory */
-               delay_override = 1;
-               errsts = check_readiness(SCpnt, 0, devip);
+               /* delay_override = 1; */
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                break;
        case RESERVE:
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                break;
        case RESERVE_10:
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                break;
        case RELEASE:
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                break;
        case RELEASE_10:
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                break;
        case READ_CAPACITY:
                errsts = resp_readcap(SCpnt, devip);
@@ -3703,20 +4216,20 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
                else if (cmd[1] == SAI_GET_LBA_STATUS) {
 
                        if (scsi_debug_lbp() == 0) {
-                               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                                INVALID_COMMAND_OPCODE, 0);
                                errsts = check_condition_result;
                        } else
                                errsts = resp_get_lba_status(SCpnt, devip);
                } else {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_OPCODE, 0);
                        errsts = check_condition_result;
                }
                break;
        case MAINTENANCE_IN:
                if (MI_REPORT_TARGET_PGS != cmd[1]) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_OPCODE, 0);
                        errsts = check_condition_result;
                        break;
@@ -3729,7 +4242,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
                /* READ{10,12,16} and DIF Type 2 are natural enemies */
                if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
                    cmd[1] & 0xe0) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_COMMAND_OPCODE, 0);
                        errsts = check_condition_result;
                        break;
@@ -3743,7 +4256,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
                /* fall through */
        case READ_6:
 read:
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                if (errsts)
                        break;
                if (scsi_debug_fake_rw)
@@ -3753,20 +4266,21 @@ read:
                if (inj_short)
                        num /= 2;
 
-               errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
+               errsts = resp_read(SCpnt, lba, num, ei_lba);
                if (inj_recovered && (0 == errsts)) {
-                       mk_sense_buffer(devip, RECOVERED_ERROR,
+                       mk_sense_buffer(SCpnt, RECOVERED_ERROR,
                                        THRESHOLD_EXCEEDED, 0);
                        errsts = check_condition_result;
                } else if (inj_transport && (0 == errsts)) {
-                       mk_sense_buffer(devip, ABORTED_COMMAND,
+                       mk_sense_buffer(SCpnt, ABORTED_COMMAND,
                                        TRANSPORT_PROBLEM, ACK_NAK_TO);
                        errsts = check_condition_result;
                } else if (inj_dif && (0 == errsts)) {
-                       mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
+                       /* Logical block guard check failed */
+                       mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
                        errsts = illegal_condition_result;
                } else if (inj_dix && (0 == errsts)) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
                        errsts = illegal_condition_result;
                }
                break;
@@ -3775,7 +4289,7 @@ read:
                errsts = resp_report_luns(SCpnt, devip);
                break;
        case VERIFY:            /* 10 byte SBC-2 command */
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                break;
        case WRITE_16:
        case WRITE_12:
@@ -3783,7 +4297,7 @@ read:
                /* WRITE{10,12,16} and DIF Type 2 are natural enemies */
                if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
                    cmd[1] & 0xe0) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_COMMAND_OPCODE, 0);
                        errsts = check_condition_result;
                        break;
@@ -3797,22 +4311,22 @@ read:
                /* fall through */
        case WRITE_6:
 write:
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                if (errsts)
                        break;
                if (scsi_debug_fake_rw)
                        break;
                get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-               errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
+               errsts = resp_write(SCpnt, lba, num, ei_lba);
                if (inj_recovered && (0 == errsts)) {
-                       mk_sense_buffer(devip, RECOVERED_ERROR,
+                       mk_sense_buffer(SCpnt, RECOVERED_ERROR,
                                        THRESHOLD_EXCEEDED, 0);
                        errsts = check_condition_result;
                } else if (inj_dif && (0 == errsts)) {
-                       mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
+                       mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
                        errsts = illegal_condition_result;
                } else if (inj_dix && (0 == errsts)) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
                        errsts = illegal_condition_result;
                }
                break;
@@ -3821,7 +4335,7 @@ write:
                if (cmd[1] & 0x8) {
                        if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
                            (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
-                               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                                INVALID_FIELD_IN_CDB, 0);
                                errsts = check_condition_result;
                        } else
@@ -3829,19 +4343,23 @@ write:
                }
                if (errsts)
                        break;
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                if (errsts)
                        break;
+               if (scsi_debug_fake_rw)
+                       break;
                get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-               errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap);
+               errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap);
                break;
        case UNMAP:
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                if (errsts)
                        break;
+               if (scsi_debug_fake_rw)
+                       break;
 
                if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_COMMAND_OPCODE, 0);
                        errsts = check_condition_result;
                } else
@@ -3862,29 +4380,29 @@ write:
                break;
        case SYNCHRONIZE_CACHE:
                delay_override = 1;
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                break;
        case WRITE_BUFFER:
-               errsts = check_readiness(SCpnt, 1, devip);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                break;
        case XDWRITEREAD_10:
                if (!scsi_bidi_cmnd(SCpnt)) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        errsts = check_condition_result;
                        break;
                }
 
-               errsts = check_readiness(SCpnt, 0, devip);
+               errsts = check_readiness(SCpnt, UAS_TUR, devip);
                if (errsts)
                        break;
                if (scsi_debug_fake_rw)
                        break;
                get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-               errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
+               errsts = resp_read(SCpnt, lba, num, ei_lba);
                if (errsts)
                        break;
-               errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
+               errsts = resp_write(SCpnt, lba, num, ei_lba);
                if (errsts)
                        break;
                errsts = resp_xdwriteread(SCpnt, lba, num, devip);
@@ -3907,27 +4425,138 @@ write:
                        }
                }
 
-               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
                                INVALID_FIELD_IN_CDB, 0);
                errsts = check_condition_result;
                break;
-
+       case 0x85:
+               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                       sdev_printk(KERN_INFO, SCpnt->device,
+                       "%s: ATA PASS-THROUGH(16) not supported\n", my_name);
+               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
+                               INVALID_OPCODE, 0);
+               errsts = check_condition_result;
+               break;
        default:
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
-                              "supported\n", *cmd);
-               errsts = check_readiness(SCpnt, 1, devip);
+                       sdev_printk(KERN_INFO, SCpnt->device,
+                                   "%s: Opcode: 0x%x not supported\n",
+                                   my_name, *cmd);
+               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
                if (errsts)
                        break;  /* Unit attention takes precedence */
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
+               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
                errsts = check_condition_result;
                break;
        }
-       return schedule_resp(SCpnt, devip, done, errsts,
+       return schedule_resp(SCpnt, devip, errsts,
                             (delay_override ? 0 : scsi_debug_delay));
 }
 
-static DEF_SCSI_QCMD(scsi_debug_queuecommand)
+static int
+sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+{
+       if (scsi_debug_host_lock) {
+               unsigned long iflags;
+               int rc;
+
+               spin_lock_irqsave(shost->host_lock, iflags);
+               rc = scsi_debug_queuecommand(cmd);
+               spin_unlock_irqrestore(shost->host_lock, iflags);
+               return rc;
+       } else
+               return scsi_debug_queuecommand(cmd);
+}
+
+static int
+sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason)
+{
+       int num_in_q = 0;
+       int bad = 0;
+       unsigned long iflags;
+       struct sdebug_dev_info *devip;
+
+       spin_lock_irqsave(&queued_arr_lock, iflags);
+       devip = (struct sdebug_dev_info *)sdev->hostdata;
+       if (NULL == devip) {
+               spin_unlock_irqrestore(&queued_arr_lock, iflags);
+               return  -ENODEV;
+       }
+       num_in_q = atomic_read(&devip->num_in_q);
+       spin_unlock_irqrestore(&queued_arr_lock, iflags);
+       if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) {
+               if (qdepth < 1)
+                       qdepth = 1;
+               /* allow to exceed max host queued_arr elements for testing */
+               if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
+                       qdepth = SCSI_DEBUG_CANQUEUE + 10;
+               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+       } else if (reason == SCSI_QDEPTH_QFULL)
+               scsi_track_queue_full(sdev, qdepth);
+       else
+               bad = 1;
+       if (bad)
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: unknown reason=0x%x\n", __func__, reason);
+       if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
+               if (SCSI_QDEPTH_QFULL == reason)
+                       sdev_printk(KERN_INFO, sdev,
+                           "%s: -> %d, num_in_q=%d, reason: queue full\n",
+                                   __func__, qdepth, num_in_q);
+               else {
+                       const char *cp;
+
+                       switch (reason) {
+                       case SCSI_QDEPTH_DEFAULT:
+                               cp = "default (sysfs ?)";
+                               break;
+                       case SCSI_QDEPTH_RAMP_UP:
+                               cp = "ramp up";
+                               break;
+                       default:
+                               cp = "unknown";
+                               break;
+                       }
+                       sdev_printk(KERN_INFO, sdev,
+                                   "%s: qdepth=%d, num_in_q=%d, reason: %s\n",
+                                   __func__, qdepth, num_in_q, cp);
+               }
+       }
+       return sdev->queue_depth;
+}
+
+static int
+sdebug_change_qtype(struct scsi_device *sdev, int qtype)
+{
+       if (sdev->tagged_supported) {
+               scsi_set_tag_type(sdev, qtype);
+               if (qtype)
+                       scsi_activate_tcq(sdev, sdev->queue_depth);
+               else
+                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
+       } else
+               qtype = 0;
+       if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
+               const char *cp;
+
+               switch (qtype) {
+               case 0:
+                       cp = "untagged";
+                       break;
+               case MSG_SIMPLE_TAG:
+                       cp = "simple tags";
+                       break;
+               case MSG_ORDERED_TAG:
+                       cp = "ordered tags";
+                       break;
+               default:
+                       cp = "unknown";
+                       break;
+               }
+               sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp);
+       }
+       return qtype;
+}
 
 static struct scsi_host_template sdebug_driver_template = {
        .show_info =            scsi_debug_show_info,
@@ -3939,16 +4568,18 @@ static struct scsi_host_template sdebug_driver_template = {
        .slave_configure =      scsi_debug_slave_configure,
        .slave_destroy =        scsi_debug_slave_destroy,
        .ioctl =                scsi_debug_ioctl,
-       .queuecommand =         scsi_debug_queuecommand,
+       .queuecommand =         sdebug_queuecommand_lock_or_not,
+       .change_queue_depth =   sdebug_change_qdepth,
+       .change_queue_type =    sdebug_change_qtype,
        .eh_abort_handler =     scsi_debug_abort,
-       .eh_bus_reset_handler = scsi_debug_bus_reset,
        .eh_device_reset_handler = scsi_debug_device_reset,
+       .eh_target_reset_handler = scsi_debug_target_reset,
+       .eh_bus_reset_handler = scsi_debug_bus_reset,
        .eh_host_reset_handler = scsi_debug_host_reset,
-       .bios_param =           scsi_debug_biosparam,
        .can_queue =            SCSI_DEBUG_CANQUEUE,
        .this_id =              7,
        .sg_tablesize =         SCSI_MAX_SG_CHAIN_SEGMENTS,
-       .cmd_per_lun =          16,
+       .cmd_per_lun =          DEF_CMD_PER_LUN,
        .max_sectors =          -1U,
        .use_clustering =       DISABLE_CLUSTERING,
        .module =               THIS_MODULE,
@@ -4033,8 +4664,7 @@ static int sdebug_driver_probe(struct device * dev)
         } else
                scsi_scan_host(hpnt);
 
-
-        return error;
+       return error;
 }
 
 static int sdebug_driver_remove(struct device * dev)
index 4b0f167e8c214d78a8d4f5a60ca72f213b6174ba..5d6f348eb3d8590361327d21dc9ddb2eddf49d8e 100644 (file)
@@ -261,6 +261,10 @@ static const struct {
        { FC_PORTSPEED_8GBIT,           "8 Gbit" },
        { FC_PORTSPEED_16GBIT,          "16 Gbit" },
        { FC_PORTSPEED_32GBIT,          "32 Gbit" },
+       { FC_PORTSPEED_20GBIT,          "20 Gbit" },
+       { FC_PORTSPEED_40GBIT,          "40 Gbit" },
+       { FC_PORTSPEED_50GBIT,          "50 Gbit" },
+       { FC_PORTSPEED_100GBIT,         "100 Gbit" },
        { FC_PORTSPEED_NOT_NEGOTIATED,  "Not Negotiated" },
 };
 fc_bitfield_name_search(port_speed, fc_port_speed_names)
index 126bf260500f8411c9a7585895eee3959f1c6ccd..b481e62a12cc96945a937972f5c12ebaca488819 100644 (file)
@@ -3059,7 +3059,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
                evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
                evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
                evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
-               buf = (char *) ((char *)evchap + sizeof(*evchap));
+               buf = (char *)evchap + sizeof(*evchap);
                memset(buf, 0, chap_buf_size);
 
                err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
@@ -3463,7 +3463,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
                evhost_stats->type = nlh->nlmsg_type;
                evhost_stats->u.get_host_stats.host_no =
                                        ev->u.get_host_stats.host_no;
-               buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats));
+               buf = (char *)evhost_stats + sizeof(*evhost_stats);
                memset(buf, 0, host_stats_size);
 
                err = transport->get_host_stats(shost, buf, host_stats_size);
index 9969fa1ef7c4ef09ac4fc72c942c5ef72703ae49..fecac5d03fddd141d785455b556b84eec0b9dc0f 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/hyperv.h>
 #include <linux/mempool.h>
+#include <linux/blkdev.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -326,21 +327,23 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
  */
 static int storvsc_timeout = 180;
 
+static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
+
 #define STORVSC_MAX_IO_REQUESTS                                200
 
 static void storvsc_on_channel_callback(void *context);
 
-/*
- * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
- * reality, the path/target is not used (ie always set to 0) so our
- * scsi host adapter essentially has 1 bus with 1 target that contains
- * up to 256 luns.
- */
-#define STORVSC_MAX_LUNS_PER_TARGET                    64
-#define STORVSC_MAX_TARGETS                            1
-#define STORVSC_MAX_CHANNELS                           1
+#define STORVSC_MAX_LUNS_PER_TARGET                    255
+#define STORVSC_MAX_TARGETS                            2
+#define STORVSC_MAX_CHANNELS                           8
 
+#define STORVSC_FC_MAX_LUNS_PER_TARGET                 255
+#define STORVSC_FC_MAX_TARGETS                         128
+#define STORVSC_FC_MAX_CHANNELS                                8
 
+#define STORVSC_IDE_MAX_LUNS_PER_TARGET                        64
+#define STORVSC_IDE_MAX_TARGETS                                1
+#define STORVSC_IDE_MAX_CHANNELS                       1
 
 struct storvsc_cmd_request {
        struct list_head entry;
@@ -1017,6 +1020,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
                case ATA_12:
                        set_host_byte(scmnd, DID_PASSTHROUGH);
                        break;
+               /*
+                * On Some Windows hosts TEST_UNIT_READY command can return
+                * SRB_STATUS_ERROR, let the upper level code deal with it
+                * based on the sense information.
+                */
+               case TEST_UNIT_READY:
+                       break;
                default:
                        set_host_byte(scmnd, DID_TARGET_FAILURE);
                }
@@ -1441,6 +1451,14 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
 
        sdevice->no_write_same = 1;
 
+       /*
+        * Add blist flags to permit the reading of the VPD pages even when
+        * the target may claim SPC-2 compliance. MSFT targets currently
+        * claim SPC-2 compliance while they implement post SPC-2 features.
+        * With this patch we can correctly handle WRITE_SAME_16 issues.
+        */
+       sdevice->sdev_bflags |= msft_blist_flags;
+
        return 0;
 }
 
@@ -1518,6 +1536,16 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
        return SUCCESS;
 }
 
+/*
+ * The host guarantees to respond to each command, although I/O latencies might
+ * be unbounded on Azure.  Reset the timer unconditionally to give the host a
+ * chance to perform EH.
+ */
+static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
+{
+       return BLK_EH_RESET_TIMER;
+}
+
 static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
 {
        bool allowed = true;
@@ -1553,9 +1581,19 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        struct vmscsi_request *vm_srb;
        struct stor_mem_pools *memp = scmnd->device->hostdata;
 
-       if (!storvsc_scsi_cmd_ok(scmnd)) {
-               scmnd->scsi_done(scmnd);
-               return 0;
+       if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
+               /*
+                * On legacy hosts filter unimplemented commands.
+                * Future hosts are expected to correctly handle
+                * unsupported commands. Furthermore, it is
+                * possible that some of the currently
+                * unsupported commands maybe supported in
+                * future versions of the host.
+                */
+               if (!storvsc_scsi_cmd_ok(scmnd)) {
+                       scmnd->scsi_done(scmnd);
+                       return 0;
+               }
        }
 
        request_size = sizeof(struct storvsc_cmd_request);
@@ -1580,26 +1618,24 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        vm_srb = &cmd_request->vstor_packet.vm_srb;
        vm_srb->win8_extension.time_out_value = 60;
 
+       vm_srb->win8_extension.srb_flags |=
+               (SRB_FLAGS_QUEUE_ACTION_ENABLE |
+               SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
 
        /* Build the SRB */
        switch (scmnd->sc_data_direction) {
        case DMA_TO_DEVICE:
                vm_srb->data_in = WRITE_TYPE;
                vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT;
-               vm_srb->win8_extension.srb_flags |=
-                       (SRB_FLAGS_QUEUE_ACTION_ENABLE |
-                       SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
                break;
        case DMA_FROM_DEVICE:
                vm_srb->data_in = READ_TYPE;
                vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN;
-               vm_srb->win8_extension.srb_flags |=
-                       (SRB_FLAGS_QUEUE_ACTION_ENABLE |
-                       SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
                break;
        default:
                vm_srb->data_in = UNKNOWN_TYPE;
-               vm_srb->win8_extension.srb_flags = 0;
+               vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN |
+                                                    SRB_FLAGS_DATA_OUT);
                break;
        }
 
@@ -1687,11 +1723,11 @@ static struct scsi_host_template scsi_driver = {
        .bios_param =           storvsc_get_chs,
        .queuecommand =         storvsc_queuecommand,
        .eh_host_reset_handler =        storvsc_host_reset_handler,
+       .eh_timed_out =         storvsc_eh_timed_out,
        .slave_alloc =          storvsc_device_alloc,
        .slave_destroy =        storvsc_device_destroy,
        .slave_configure =      storvsc_device_configure,
-       .cmd_per_lun =          1,
-       /* 64 max_queue * 1 target */
+       .cmd_per_lun =          255,
        .can_queue =            STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
        .this_id =              -1,
        /* no use setting to 0 since ll_blk_rw reset it to 1 */
@@ -1743,19 +1779,25 @@ static int storvsc_probe(struct hv_device *device,
         * set state to properly communicate with the host.
         */
 
-       if (vmbus_proto_version == VERSION_WIN8) {
-               sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
-               vmscsi_size_delta = 0;
-               vmstor_current_major = VMSTOR_WIN8_MAJOR;
-               vmstor_current_minor = VMSTOR_WIN8_MINOR;
-       } else {
+       switch (vmbus_proto_version) {
+       case VERSION_WS2008:
+       case VERSION_WIN7:
                sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
                vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
                vmstor_current_major = VMSTOR_WIN7_MAJOR;
                vmstor_current_minor = VMSTOR_WIN7_MINOR;
+               break;
+       default:
+               sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
+               vmscsi_size_delta = 0;
+               vmstor_current_major = VMSTOR_WIN8_MAJOR;
+               vmstor_current_minor = VMSTOR_WIN8_MINOR;
+               break;
        }
 
-
+       if (dev_id->driver_data == SFC_GUID)
+               scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
+                                        STORVSC_FC_MAX_TARGETS);
        host = scsi_host_alloc(&scsi_driver,
                               sizeof(struct hv_host_device));
        if (!host)
@@ -1789,12 +1831,25 @@ static int storvsc_probe(struct hv_device *device,
        host_dev->path = stor_device->path_id;
        host_dev->target = stor_device->target_id;
 
-       /* max # of devices per target */
-       host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
-       /* max # of targets per channel */
-       host->max_id = STORVSC_MAX_TARGETS;
-       /* max # of channels */
-       host->max_channel = STORVSC_MAX_CHANNELS - 1;
+       switch (dev_id->driver_data) {
+       case SFC_GUID:
+               host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET;
+               host->max_id = STORVSC_FC_MAX_TARGETS;
+               host->max_channel = STORVSC_FC_MAX_CHANNELS - 1;
+               break;
+
+       case SCSI_GUID:
+               host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
+               host->max_id = STORVSC_MAX_TARGETS;
+               host->max_channel = STORVSC_MAX_CHANNELS - 1;
+               break;
+
+       default:
+               host->max_lun = STORVSC_IDE_MAX_LUNS_PER_TARGET;
+               host->max_id = STORVSC_IDE_MAX_TARGETS;
+               host->max_channel = STORVSC_IDE_MAX_CHANNELS - 1;
+               break;
+       }
        /* max cmd length */
        host->max_cmd_len = STORVSC_MAX_CMD_LEN;
 
index f42d1cee652aaec50dbfa9bcd7dd7848ab99191e..fafcf5e354c6d1043ff8c91a678de15c402465b8 100644 (file)
@@ -41,7 +41,8 @@
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
-#define QUERY_DESC_MAX_SIZE       256
+#define QUERY_DESC_MAX_SIZE       255
+#define QUERY_DESC_MIN_SIZE       2
 #define QUERY_OSF_SIZE            (GENERAL_UPIU_REQUEST_SIZE - \
                                        (sizeof(struct utp_upiu_header)))
 
@@ -117,6 +118,41 @@ enum attr_idn {
        QUERY_ATTR_IDN_EE_STATUS        = 0x0E,
 };
 
+/* Descriptor idn for Query requests */
+enum desc_idn {
+       QUERY_DESC_IDN_DEVICE           = 0x0,
+       QUERY_DESC_IDN_CONFIGURAION     = 0x1,
+       QUERY_DESC_IDN_UNIT             = 0x2,
+       QUERY_DESC_IDN_RFU_0            = 0x3,
+       QUERY_DESC_IDN_INTERCONNECT     = 0x4,
+       QUERY_DESC_IDN_STRING           = 0x5,
+       QUERY_DESC_IDN_RFU_1            = 0x6,
+       QUERY_DESC_IDN_GEOMETRY         = 0x7,
+       QUERY_DESC_IDN_POWER            = 0x8,
+       QUERY_DESC_IDN_RFU_2            = 0x9,
+};
+
+#define UNIT_DESC_MAX_SIZE       0x22
+/* Unit descriptor parameters offsets in bytes*/
+enum unit_desc_param {
+       UNIT_DESC_PARAM_LEN                     = 0x0,
+       UNIT_DESC_PARAM_TYPE                    = 0x1,
+       UNIT_DESC_PARAM_UNIT_INDEX              = 0x2,
+       UNIT_DESC_PARAM_LU_ENABLE               = 0x3,
+       UNIT_DESC_PARAM_BOOT_LUN_ID             = 0x4,
+       UNIT_DESC_PARAM_LU_WR_PROTECT           = 0x5,
+       UNIT_DESC_PARAM_LU_Q_DEPTH              = 0x6,
+       UNIT_DESC_PARAM_MEM_TYPE                = 0x8,
+       UNIT_DESC_PARAM_DATA_RELIABILITY        = 0x9,
+       UNIT_DESC_PARAM_LOGICAL_BLK_SIZE        = 0xA,
+       UNIT_DESC_PARAM_LOGICAL_BLK_COUNT       = 0xB,
+       UNIT_DESC_PARAM_ERASE_BLK_SIZE          = 0x13,
+       UNIT_DESC_PARAM_PROVISIONING_TYPE       = 0x17,
+       UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT        = 0x18,
+       UNIT_DESC_PARAM_CTX_CAPABILITIES        = 0x20,
+       UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1      = 0x22,
+};
+
 /* Exception event mask values */
 enum {
        MASK_EE_STATUS          = 0xFFFF,
index 8b9531204c2bb7ee570fb3d504a59803765a4ba6..c007a7a69c28c0e29b1ac999f3c5b320c32a7c0d 100644 (file)
@@ -134,26 +134,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
        ufshcd_remove(hba);
 }
 
-/**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- *                      addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct pci_dev *pdev)
-{
-       int err;
-
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
-               && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
-               return 0;
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-       return err;
-}
-
 /**
  * ufshcd_pci_probe - probe routine of the driver
  * @pdev: pointer to PCI device handle
@@ -184,12 +164,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        mmio_base = pcim_iomap_table(pdev)[0];
 
-       err = ufshcd_set_dma_mask(pdev);
-       if (err) {
-               dev_err(&pdev->dev, "set dma mask failed\n");
-               return err;
-       }
-
        err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
        if (err) {
                dev_err(&pdev->dev, "Initialization failed\n");
index 0c2877251251d9e7a4a94e0e654d3c9e50a40609..ba27215b8034460c8578fdd14295623ebc047e1b 100644 (file)
@@ -110,6 +110,8 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba);
 static void ufshcd_async_scan(void *data, async_cookie_t cookie);
 static int ufshcd_reset_and_restore(struct ufs_hba *hba);
 static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
+static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
+                                       struct scsi_device *sdev);
 
 /*
  * ufshcd_wait_for_register - wait for register value to change
@@ -446,30 +448,35 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
  * @lrb - pointer to local reference block
  */
 static
-void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 {
        struct ufs_query_res *query_res = &hba->dev_cmd.query.response;
 
-       /* Get the UPIU response */
-       query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >>
-                       UPIU_RSP_CODE_OFFSET;
-
        memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr, QUERY_OSF_SIZE);
 
-
        /* Get the descriptor */
        if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) {
-               u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr +
+               u8 *descp = (u8 *)lrbp->ucd_rsp_ptr +
                                GENERAL_UPIU_REQUEST_SIZE;
-               u16 len;
+               u16 resp_len;
+               u16 buf_len;
 
                /* data segment length */
-               len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
+               resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
                                                MASK_QUERY_DATA_SEG_LEN;
-
-               memcpy(hba->dev_cmd.query.descriptor, descp,
-                               min_t(u16, len, QUERY_DESC_MAX_SIZE));
+               buf_len = be16_to_cpu(
+                               hba->dev_cmd.query.request.upiu_req.length);
+               if (likely(buf_len >= resp_len)) {
+                       memcpy(hba->dev_cmd.query.descriptor, descp, resp_len);
+               } else {
+                       dev_warn(hba->dev,
+                               "%s: Response size is bigger than buffer",
+                               __func__);
+                       return -EINVAL;
+               }
        }
+
+       return 0;
 }
 
 /**
@@ -797,11 +804,9 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
                        QUERY_OSF_SIZE);
 
        /* Copy the Descriptor */
-       if ((len > 0) && (query->request.upiu_req.opcode ==
-                                       UPIU_QUERY_OPCODE_WRITE_DESC)) {
-               memcpy(descp, query->descriptor,
-                               min_t(u16, len, QUERY_DESC_MAX_SIZE));
-       }
+       if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
+               memcpy(descp, query->descriptor, len);
+
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
@@ -980,6 +985,17 @@ ufshcd_clear_cmd(struct ufs_hba *hba, int tag)
        return err;
 }
 
+static int
+ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+       struct ufs_query_res *query_res = &hba->dev_cmd.query.response;
+
+       /* Get the UPIU response */
+       query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >>
+                               UPIU_RSP_CODE_OFFSET;
+       return query_res->response;
+}
+
 /**
  * ufshcd_dev_cmd_completion() - handles device management command responses
  * @hba: per adapter instance
@@ -1002,7 +1018,9 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
                }
                break;
        case UPIU_TRANSACTION_QUERY_RSP:
-               ufshcd_copy_query_response(hba, lrbp);
+               err = ufshcd_check_query_response(hba, lrbp);
+               if (!err)
+                       err = ufshcd_copy_query_response(hba, lrbp);
                break;
        case UPIU_TRANSACTION_REJECT_UPIU:
                /* TODO: handle Reject UPIU Response */
@@ -1133,6 +1151,30 @@ out_put_tag:
        return err;
 }
 
+/**
+ * ufshcd_init_query() - init the query response and request parameters
+ * @hba: per-adapter instance
+ * @request: address of the request pointer to be initialized
+ * @response: address of the response pointer to be initialized
+ * @opcode: operation to perform
+ * @idn: flag idn to access
+ * @index: LU number to access
+ * @selector: query/flag/descriptor further identification
+ */
+static inline void ufshcd_init_query(struct ufs_hba *hba,
+               struct ufs_query_req **request, struct ufs_query_res **response,
+               enum query_opcode opcode, u8 idn, u8 index, u8 selector)
+{
+       *request = &hba->dev_cmd.query.request;
+       *response = &hba->dev_cmd.query.response;
+       memset(*request, 0, sizeof(struct ufs_query_req));
+       memset(*response, 0, sizeof(struct ufs_query_res));
+       (*request)->upiu_req.opcode = opcode;
+       (*request)->upiu_req.idn = idn;
+       (*request)->upiu_req.index = index;
+       (*request)->upiu_req.selector = selector;
+}
+
 /**
  * ufshcd_query_flag() - API function for sending flag query requests
  * hba: per-adapter instance
@@ -1145,17 +1187,15 @@ out_put_tag:
 static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
                        enum flag_idn idn, bool *flag_res)
 {
-       struct ufs_query_req *request;
-       struct ufs_query_res *response;
-       int err;
+       struct ufs_query_req *request = NULL;
+       struct ufs_query_res *response = NULL;
+       int err, index = 0, selector = 0;
 
        BUG_ON(!hba);
 
        mutex_lock(&hba->dev_cmd.lock);
-       request = &hba->dev_cmd.query.request;
-       response = &hba->dev_cmd.query.response;
-       memset(request, 0, sizeof(struct ufs_query_req));
-       memset(response, 0, sizeof(struct ufs_query_res));
+       ufshcd_init_query(hba, &request, &response, opcode, idn, index,
+                       selector);
 
        switch (opcode) {
        case UPIU_QUERY_OPCODE_SET_FLAG:
@@ -1180,12 +1220,8 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
                err = -EINVAL;
                goto out_unlock;
        }
-       request->upiu_req.opcode = opcode;
-       request->upiu_req.idn = idn;
 
-       /* Send query request */
-       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
-                       QUERY_REQ_TIMEOUT);
+       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
 
        if (err) {
                dev_err(hba->dev,
@@ -1217,8 +1253,8 @@ out_unlock:
 static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
                        enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
 {
-       struct ufs_query_req *request;
-       struct ufs_query_res *response;
+       struct ufs_query_req *request = NULL;
+       struct ufs_query_res *response = NULL;
        int err;
 
        BUG_ON(!hba);
@@ -1231,10 +1267,8 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
        }
 
        mutex_lock(&hba->dev_cmd.lock);
-       request = &hba->dev_cmd.query.request;
-       response = &hba->dev_cmd.query.response;
-       memset(request, 0, sizeof(struct ufs_query_req));
-       memset(response, 0, sizeof(struct ufs_query_res));
+       ufshcd_init_query(hba, &request, &response, opcode, idn, index,
+                       selector);
 
        switch (opcode) {
        case UPIU_QUERY_OPCODE_WRITE_ATTR:
@@ -1251,14 +1285,7 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
                goto out_unlock;
        }
 
-       request->upiu_req.opcode = opcode;
-       request->upiu_req.idn = idn;
-       request->upiu_req.index = index;
-       request->upiu_req.selector = selector;
-
-       /* Send query request */
-       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
-                                               QUERY_REQ_TIMEOUT);
+       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
 
        if (err) {
                dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n",
@@ -1274,6 +1301,82 @@ out:
        return err;
 }
 
+/**
+ * ufshcd_query_descriptor - API function for sending descriptor requests
+ * hba: per-adapter instance
+ * opcode: attribute opcode
+ * idn: attribute idn to access
+ * index: index field
+ * selector: selector field
+ * desc_buf: the buffer that contains the descriptor
+ * buf_len: length parameter passed to the device
+ *
+ * Returns 0 for success, non-zero in case of failure.
+ * The buf_len parameter will contain, on return, the length parameter
+ * received on the response.
+ */
+static int ufshcd_query_descriptor(struct ufs_hba *hba,
+                       enum query_opcode opcode, enum desc_idn idn, u8 index,
+                       u8 selector, u8 *desc_buf, int *buf_len)
+{
+       struct ufs_query_req *request = NULL;
+       struct ufs_query_res *response = NULL;
+       int err;
+
+       BUG_ON(!hba);
+
+       if (!desc_buf) {
+               dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n",
+                               __func__, opcode);
+               err = -EINVAL;
+               goto out;
+       }
+
+       if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) {
+               dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n",
+                               __func__, *buf_len);
+               err = -EINVAL;
+               goto out;
+       }
+
+       mutex_lock(&hba->dev_cmd.lock);
+       ufshcd_init_query(hba, &request, &response, opcode, idn, index,
+                       selector);
+       hba->dev_cmd.query.descriptor = desc_buf;
+       request->upiu_req.length = cpu_to_be16(*buf_len);
+
+       switch (opcode) {
+       case UPIU_QUERY_OPCODE_WRITE_DESC:
+               request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
+               break;
+       case UPIU_QUERY_OPCODE_READ_DESC:
+               request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
+               break;
+       default:
+               dev_err(hba->dev,
+                               "%s: Expected query descriptor opcode but got = 0x%.2x\n",
+                               __func__, opcode);
+               err = -EINVAL;
+               goto out_unlock;
+       }
+
+       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+       if (err) {
+               dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n",
+                               __func__, opcode, idn, err);
+               goto out_unlock;
+       }
+
+       hba->dev_cmd.query.descriptor = NULL;
+       *buf_len = be16_to_cpu(response->upiu_res.length);
+
+out_unlock:
+       mutex_unlock(&hba->dev_cmd.lock);
+out:
+       return err;
+}
+
 /**
  * ufshcd_memory_alloc - allocate memory for host memory space data structures
  * @hba: per adapter instance
@@ -1878,6 +1981,7 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
 static int ufshcd_slave_alloc(struct scsi_device *sdev)
 {
        struct ufs_hba *hba;
+       int lun_qdepth;
 
        hba = shost_priv(sdev->host);
        sdev->tagged_supported = 1;
@@ -1889,14 +1993,68 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
        /* allow SCSI layer to restart the device in case of errors */
        sdev->allow_restart = 1;
 
-       /*
-        * Inform SCSI Midlayer that the LUN queue depth is same as the
-        * controller queue depth. If a LUN queue depth is less than the
-        * controller queue depth and if the LUN reports
-        * SAM_STAT_TASK_SET_FULL, the LUN queue depth will be adjusted
-        * with scsi_adjust_queue_depth.
-        */
-       scsi_activate_tcq(sdev, hba->nutrs);
+       /* REPORT SUPPORTED OPERATION CODES is not supported */
+       sdev->no_report_opcodes = 1;
+
+       lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev);
+       if (lun_qdepth <= 0)
+               /* eventually, we can figure out the real queue depth */
+               lun_qdepth = hba->nutrs;
+       else
+               lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
+
+       dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
+                       __func__, lun_qdepth);
+       scsi_activate_tcq(sdev, lun_qdepth);
+
+       return 0;
+}
+
+/**
+ * ufshcd_change_queue_depth - change queue depth
+ * @sdev: pointer to SCSI device
+ * @depth: required depth to set
+ * @reason: reason for changing the depth
+ *
+ * Change queue depth according to the reason and make sure
+ * the max. limits are not crossed.
+ */
+static int ufshcd_change_queue_depth(struct scsi_device *sdev,
+               int depth, int reason)
+{
+       struct ufs_hba *hba = shost_priv(sdev->host);
+
+       if (depth > hba->nutrs)
+               depth = hba->nutrs;
+
+       switch (reason) {
+       case SCSI_QDEPTH_DEFAULT:
+       case SCSI_QDEPTH_RAMP_UP:
+               if (!sdev->tagged_supported)
+                       depth = 1;
+               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+               break;
+       case SCSI_QDEPTH_QFULL:
+               scsi_track_queue_full(sdev, depth);
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return depth;
+}
+
+/**
+ * ufshcd_slave_configure - adjust SCSI device configurations
+ * @sdev: pointer to SCSI device
+ */
+static int ufshcd_slave_configure(struct scsi_device *sdev)
+{
+       struct request_queue *q = sdev->request_queue;
+
+       blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
+       blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX);
+
        return 0;
 }
 
@@ -1952,42 +2110,6 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
        return ocs_value;
 }
 
-/**
- * ufshcd_adjust_lun_qdepth - Update LUN queue depth if device responds with
- *                           SAM_STAT_TASK_SET_FULL SCSI command status.
- * @cmd: pointer to SCSI command
- */
-static void ufshcd_adjust_lun_qdepth(struct scsi_cmnd *cmd)
-{
-       struct ufs_hba *hba;
-       int i;
-       int lun_qdepth = 0;
-
-       hba = shost_priv(cmd->device->host);
-
-       /*
-        * LUN queue depth can be obtained by counting outstanding commands
-        * on the LUN.
-        */
-       for (i = 0; i < hba->nutrs; i++) {
-               if (test_bit(i, &hba->outstanding_reqs)) {
-
-                       /*
-                        * Check if the outstanding command belongs
-                        * to the LUN which reported SAM_STAT_TASK_SET_FULL.
-                        */
-                       if (cmd->device->lun == hba->lrb[i].lun)
-                               lun_qdepth++;
-               }
-       }
-
-       /*
-        * LUN queue depth will be total outstanding commands, except the
-        * command for which the LUN reported SAM_STAT_TASK_SET_FULL.
-        */
-       scsi_adjust_queue_depth(cmd->device, MSG_SIMPLE_TAG, lun_qdepth - 1);
-}
-
 /**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrb: pointer to local reference block of completed command
@@ -2009,12 +2131,6 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status)
                          scsi_status;
                break;
        case SAM_STAT_TASK_SET_FULL:
-               /*
-                * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue
-                * depth needs to be adjusted to the exact number of
-                * outstanding commands the LUN can handle at any given time.
-                */
-               ufshcd_adjust_lun_qdepth(lrbp->cmd);
        case SAM_STAT_BUSY:
        case SAM_STAT_TASK_ABORTED:
                ufshcd_copy_sense_data(lrbp);
@@ -2134,47 +2250,42 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
        u32 tr_doorbell;
        int result;
        int index;
-       bool int_aggr_reset = false;
+
+       /* Resetting interrupt aggregation counters first and reading the
+        * DOOR_BELL afterward allows us to handle all the completed requests.
+        * In order to prevent other interrupts starvation the DB is read once
+        * after reset. The down side of this solution is the possibility of
+        * false interrupt if device completes another request after resetting
+        * aggregation and before reading the DB.
+        */
+       ufshcd_reset_intr_aggr(hba);
 
        tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
        completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
 
-       for (index = 0; index < hba->nutrs; index++) {
-               if (test_bit(index, &completed_reqs)) {
-                       lrbp = &hba->lrb[index];
-                       cmd = lrbp->cmd;
-                       /*
-                        * Don't skip resetting interrupt aggregation counters
-                        * if a regular command is present.
-                        */
-                       int_aggr_reset |= !lrbp->intr_cmd;
-
-                       if (cmd) {
-                               result = ufshcd_transfer_rsp_status(hba, lrbp);
-                               scsi_dma_unmap(cmd);
-                               cmd->result = result;
-                               /* Mark completed command as NULL in LRB */
-                               lrbp->cmd = NULL;
-                               clear_bit_unlock(index, &hba->lrb_in_use);
-                               /* Do not touch lrbp after scsi done */
-                               cmd->scsi_done(cmd);
-                       } else if (lrbp->command_type ==
-                                       UTP_CMD_TYPE_DEV_MANAGE) {
-                               if (hba->dev_cmd.complete)
-                                       complete(hba->dev_cmd.complete);
-                       }
-               } /* end of if */
-       } /* end of for */
+       for_each_set_bit(index, &completed_reqs, hba->nutrs) {
+               lrbp = &hba->lrb[index];
+               cmd = lrbp->cmd;
+               if (cmd) {
+                       result = ufshcd_transfer_rsp_status(hba, lrbp);
+                       scsi_dma_unmap(cmd);
+                       cmd->result = result;
+                       /* Mark completed command as NULL in LRB */
+                       lrbp->cmd = NULL;
+                       clear_bit_unlock(index, &hba->lrb_in_use);
+                       /* Do not touch lrbp after scsi done */
+                       cmd->scsi_done(cmd);
+               } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
+                       if (hba->dev_cmd.complete)
+                               complete(hba->dev_cmd.complete);
+               }
+       }
 
        /* clear corresponding bits of completed commands */
        hba->outstanding_reqs ^= completed_reqs;
 
        /* we might have free'd some tags above */
        wake_up(&hba->dev_cmd.tag_wq);
-
-       /* Reset interrupt aggregation counters */
-       if (int_aggr_reset)
-               ufshcd_reset_intr_aggr(hba);
 }
 
 /**
@@ -2779,6 +2890,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
        int poll_cnt;
        u8 resp = 0xF;
        struct ufshcd_lrb *lrbp;
+       u32 reg;
 
        host = cmd->device->host;
        hba = shost_priv(host);
@@ -2788,6 +2900,13 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
        if (!(test_bit(tag, &hba->outstanding_reqs)))
                goto out;
 
+       reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+       if (!(reg & (1 << tag))) {
+               dev_err(hba->dev,
+               "%s: cmd was completed, but without a notifying intr, tag = %d",
+               __func__, tag);
+       }
+
        lrbp = &hba->lrb[tag];
        for (poll_cnt = 100; poll_cnt; poll_cnt--) {
                err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
@@ -2796,8 +2915,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
                        /* cmd pending in the device */
                        break;
                } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
-                       u32 reg;
-
                        /*
                         * cmd not pending in the device, check if it is
                         * in transition.
@@ -2970,6 +3087,38 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
        return err;
 }
 
+/**
+ * ufshcd_read_sdev_qdepth - read the lun command queue depth
+ * @hba: Pointer to adapter instance
+ * @sdev: pointer to SCSI device
+ *
+ * Return in case of success the lun's queue depth else error.
+ */
+static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
+                               struct scsi_device *sdev)
+{
+       int ret;
+       int buff_len = UNIT_DESC_MAX_SIZE;
+       u8 desc_buf[UNIT_DESC_MAX_SIZE];
+
+       ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
+                       QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len);
+
+       if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) {
+               dev_err(hba->dev,
+                       "%s:Failed reading unit descriptor. len = %d ret = %d"
+                       , __func__, buff_len, ret);
+               if (!ret)
+                       ret = -EINVAL;
+
+               goto out;
+       }
+
+       ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF;
+out:
+       return ret;
+}
+
 /**
  * ufshcd_async_scan - asynchronous execution for link startup
  * @data: data pointer to pass to this function
@@ -3012,7 +3161,9 @@ static struct scsi_host_template ufshcd_driver_template = {
        .proc_name              = UFSHCD,
        .queuecommand           = ufshcd_queuecommand,
        .slave_alloc            = ufshcd_slave_alloc,
+       .slave_configure        = ufshcd_slave_configure,
        .slave_destroy          = ufshcd_slave_destroy,
+       .change_queue_depth     = ufshcd_change_queue_depth,
        .eh_abort_handler       = ufshcd_abort,
        .eh_device_reset_handler = ufshcd_eh_device_reset_handler,
        .eh_host_reset_handler   = ufshcd_eh_host_reset_handler,
@@ -3109,6 +3260,22 @@ void ufshcd_remove(struct ufs_hba *hba)
 }
 EXPORT_SYMBOL_GPL(ufshcd_remove);
 
+/**
+ * ufshcd_set_dma_mask - Set dma mask based on the controller
+ *                      addressing capability
+ * @hba: per adapter instance
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_set_dma_mask(struct ufs_hba *hba)
+{
+       if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
+               if (!dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(64)))
+                       return 0;
+       }
+       return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32));
+}
+
 /**
  * ufshcd_init - Driver initialization routine
  * @dev: pointer to device handle
@@ -3160,6 +3327,12 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
        /* Get Interrupt bit mask per version */
        hba->intr_mask = ufshcd_get_intr_mask(hba);
 
+       err = ufshcd_set_dma_mask(hba);
+       if (err) {
+               dev_err(hba->dev, "set dma mask failed\n");
+               goto out_disable;
+       }
+
        /* Allocate memory for host memory space */
        err = ufshcd_memory_alloc(hba);
        if (err) {
index 9abc7e32b43d93350a710f757f651ad3a586248e..e1b844bc94607b302ff70100729b9fa83d7ae5fc 100644 (file)
@@ -296,6 +296,11 @@ enum {
        MASK_OCS                        = 0x0F,
 };
 
+/* The maximum length of the data byte count field in the PRDT is 256KB */
+#define PRDT_DATA_BYTE_COUNT_MAX       (256 * 1024)
+/* The granularity of the data byte count field in the PRDT is 32-bit */
+#define PRDT_DATA_BYTE_COUNT_PAD       4
+
 /**
  * struct ufshcd_sg_entry - UFSHCI PRD Entry
  * @base_addr: Lower 32bit physical address DW-0
index 308256b5e4cb07d1e3a839848aeb679aff5c8d6f..eee1bc0b506efe64359d7096cbcb0384edb9255b 100644 (file)
@@ -27,6 +27,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_tcq.h>
+#include <linux/seqlock.h>
 
 #define VIRTIO_SCSI_MEMPOOL_SZ 64
 #define VIRTIO_SCSI_EVENT_LEN 8
@@ -75,18 +77,16 @@ struct virtio_scsi_vq {
  * queue, and also lets the driver optimize the IRQ affinity for the virtqueues
  * (each virtqueue's affinity is set to the CPU that "owns" the queue).
  *
- * tgt_lock is held to serialize reading and writing req_vq. Reading req_vq
- * could be done locklessly, but we do not do it yet.
+ * tgt_seq is held to serialize reading and writing req_vq.
  *
  * Decrements of reqs are never concurrent with writes of req_vq: before the
  * decrement reqs will be != 0; after the decrement the virtqueue completion
  * routine will not use the req_vq so it can be changed by a new request.
- * Thus they can happen outside the tgt_lock, provided of course we make reqs
+ * Thus they can happen outside the tgt_seq, provided of course we make reqs
  * an atomic_t.
  */
 struct virtio_scsi_target_state {
-       /* This spinlock never held at the same time as vq_lock. */
-       spinlock_t tgt_lock;
+       seqcount_t tgt_seq;
 
        /* Count of outstanding requests. */
        atomic_t reqs;
@@ -559,19 +559,33 @@ static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi,
        unsigned long flags;
        u32 queue_num;
 
-       spin_lock_irqsave(&tgt->tgt_lock, flags);
+       local_irq_save(flags);
+       if (atomic_inc_return(&tgt->reqs) > 1) {
+               unsigned long seq;
+
+               do {
+                       seq = read_seqcount_begin(&tgt->tgt_seq);
+                       vq = tgt->req_vq;
+               } while (read_seqcount_retry(&tgt->tgt_seq, seq));
+       } else {
+               /* no writes can be concurrent because of atomic_t */
+               write_seqcount_begin(&tgt->tgt_seq);
+
+               /* keep previous req_vq if a reader just arrived */
+               if (unlikely(atomic_read(&tgt->reqs) > 1)) {
+                       vq = tgt->req_vq;
+                       goto unlock;
+               }
 
-       if (atomic_inc_return(&tgt->reqs) > 1)
-               vq = tgt->req_vq;
-       else {
                queue_num = smp_processor_id();
                while (unlikely(queue_num >= vscsi->num_queues))
                        queue_num -= vscsi->num_queues;
-
                tgt->req_vq = vq = &vscsi->req_vqs[queue_num];
+ unlock:
+               write_seqcount_end(&tgt->tgt_seq);
        }
+       local_irq_restore(flags);
 
-       spin_unlock_irqrestore(&tgt->tgt_lock, flags);
        return vq;
 }
 
@@ -641,6 +655,36 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc)
        return virtscsi_tmf(vscsi, cmd);
 }
 
+/**
+ * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth
+ * @sdev:      Virtscsi target whose queue depth to change
+ * @qdepth:    New queue depth
+ * @reason:    Reason for the queue depth change.
+ */
+static int virtscsi_change_queue_depth(struct scsi_device *sdev,
+                                      int qdepth,
+                                      int reason)
+{
+       struct Scsi_Host *shost = sdev->host;
+       int max_depth = shost->cmd_per_lun;
+
+       switch (reason) {
+       case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */
+               scsi_track_queue_full(sdev, qdepth);
+               break;
+       case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */
+       case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */
+               scsi_adjust_queue_depth(sdev,
+                                       scsi_get_tag_type(sdev),
+                                       min(max_depth, qdepth));
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return sdev->queue_depth;
+}
+
 static int virtscsi_abort(struct scsi_cmnd *sc)
 {
        struct virtio_scsi *vscsi = shost_priv(sc->device->host);
@@ -667,14 +711,17 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
 
 static int virtscsi_target_alloc(struct scsi_target *starget)
 {
+       struct Scsi_Host *sh = dev_to_shost(starget->dev.parent);
+       struct virtio_scsi *vscsi = shost_priv(sh);
+
        struct virtio_scsi_target_state *tgt =
                                kmalloc(sizeof(*tgt), GFP_KERNEL);
        if (!tgt)
                return -ENOMEM;
 
-       spin_lock_init(&tgt->tgt_lock);
+       seqcount_init(&tgt->tgt_seq);
        atomic_set(&tgt->reqs, 0);
-       tgt->req_vq = NULL;
+       tgt->req_vq = &vscsi->req_vqs[0];
 
        starget->hostdata = tgt;
        return 0;
@@ -693,6 +740,7 @@ static struct scsi_host_template virtscsi_host_template_single = {
        .this_id = -1,
        .cmd_size = sizeof(struct virtio_scsi_cmd),
        .queuecommand = virtscsi_queuecommand_single,
+       .change_queue_depth = virtscsi_change_queue_depth,
        .eh_abort_handler = virtscsi_abort,
        .eh_device_reset_handler = virtscsi_device_reset,
 
@@ -710,6 +758,7 @@ static struct scsi_host_template virtscsi_host_template_multi = {
        .this_id = -1,
        .cmd_size = sizeof(struct virtio_scsi_cmd),
        .queuecommand = virtscsi_queuecommand_multi,
+       .change_queue_depth = virtscsi_change_queue_depth,
        .eh_abort_handler = virtscsi_abort,
        .eh_device_reset_handler = virtscsi_device_reset,
 
index c88e1468aad723c454395474aec6ae567a9c1419..598f65efaaec0e725851301959d138deda7cfaa1 100644 (file)
@@ -1194,7 +1194,7 @@ static int pvscsi_setup_msix(const struct pvscsi_adapter *adapter,
        struct msix_entry entry = { 0, PVSCSI_VECTOR_COMPLETION };
        int ret;
 
-       ret = pci_enable_msix(adapter->dev, &entry, 1);
+       ret = pci_enable_msix_exact(adapter->dev, &entry, 1);
        if (ret)
                return ret;
 
index 8c79980dc8f2827072deea5b981dddc1e5b07ae4..007a0bc01b74a0a8779d759db6c091fa05f42404 100644 (file)
@@ -131,6 +131,10 @@ enum fc_vport_state {
 #define FC_PORTSPEED_8GBIT             0x10
 #define FC_PORTSPEED_16GBIT            0x20
 #define FC_PORTSPEED_32GBIT            0x40
+#define FC_PORTSPEED_20GBIT            0x80
+#define FC_PORTSPEED_40GBIT            0x100
+#define FC_PORTSPEED_50GBIT            0x200
+#define FC_PORTSPEED_100GBIT           0x400
 #define FC_PORTSPEED_NOT_NEGOTIATED    (1 << 15) /* Speed not established */
 
 /*