summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS4
-rw-r--r--drivers/message/fusion/mptbase.c23
-rw-r--r--drivers/message/fusion/mptbase.h2
-rw-r--r--drivers/message/fusion/mptctl.c18
-rw-r--r--drivers/message/fusion/mptfc.c3
-rw-r--r--drivers/message/fusion/mptsas.c74
-rw-r--r--drivers/message/fusion/mptsas.h2
-rw-r--r--drivers/message/fusion/mptscsih.c19
-rw-r--r--drivers/message/fusion/mptspi.c5
-rw-r--r--drivers/scsi/3w-xxxx.h4
-rw-r--r--drivers/scsi/Kconfig2
-rw-r--r--drivers/scsi/NCR53c406a.c2
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c3
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c3
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c2
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c20
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c6
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h2
-rw-r--r--drivers/scsi/bfa/bfad.c62
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c16
-rw-r--r--drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h13
-rw-r--r--drivers/scsi/bnx2fc/Kconfig4
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h7
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_constants.h13
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.c13
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.h13
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c11
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c3
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h6
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h6
-rw-r--r--drivers/scsi/bnx2i/Kconfig4
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h6
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c6
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c14
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c15
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c6
-rw-r--r--drivers/scsi/fnic/fnic_isr.c4
-rw-r--r--drivers/scsi/hpsa.c35
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c473
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h268
-rw-r--r--drivers/scsi/isci/init.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c9
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c75
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c83
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c75
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c88
-rw-r--r--drivers/scsi/pas16.c2
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c11
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c65
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c40
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c38
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h2
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c48
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c10
-rw-r--r--drivers/scsi/qlogicfas.c2
-rw-r--r--drivers/scsi/scsi_debug.c1464
-rw-r--r--drivers/scsi/scsi_transport_fc.c4
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c4
-rw-r--r--drivers/scsi/storvsc_drv.c123
-rw-r--r--drivers/scsi/ufs/ufs.h38
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c26
-rw-r--r--drivers/scsi/ufs/ufshcd.c427
-rw-r--r--drivers/scsi/ufs/ufshci.h5
-rw-r--r--drivers/scsi/virtio_scsi.c75
-rw-r--r--drivers/scsi/vmw_pvscsi.c2
-rw-r--r--include/scsi/scsi_transport_fc.h4
71 files changed, 2462 insertions, 1466 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 61a8f48..1262d3c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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/
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index ebc0af7..a896d94 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -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;
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index f37ea6f..8f14090 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -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];
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 8a050e8..b0a892a 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -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) ||
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index bf2a2ce..d8bf84a 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -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;
}
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index d636dbe..0707fa2 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -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);
diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h
index 57e86ab..c396483 100644
--- a/drivers/message/fusion/mptsas.h
+++ b/drivers/message/fusion/mptsas.h
@@ -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 {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 39e5668..e7dcb25 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -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) {
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 49d1133..787933d 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -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;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 49dcf03..29b0b84e 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -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 */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 7b07e28..18a3358 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -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
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 10c3374..42c7161 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -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
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index 0cb8ef6..3d401d0 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -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);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 3c85873..8466aa7 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -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);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index ee05e84..0fc14da 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -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);
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index fd284ff..8616281 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -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;
}
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 07934b0..a3e5648 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -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;
}
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index a3ab5cc..0f19455 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -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++) {
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 2e28392..a38aafa0 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -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)
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 7593b7c..e90a374 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -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
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 8994fb8..023b9d4 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -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);
/*
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index e1f1e34..fe2106c 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -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__
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
index cfcad8b..f245d54 100644
--- a/drivers/scsi/bnx2fc/Kconfig
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -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.
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 6a97665..1346e05 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -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>
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index dad9924..e147cc7 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -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_
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.c b/drivers/scsi/bnx2fc/bnx2fc_debug.c
index 0cbee1b..d055df0 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.c
@@ -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, ...)
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h
index 4808ff9..2b90067 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h
@@ -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__
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index b1c9a4f..ca75c7c 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 785d0d7..79e5c94 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -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 */
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 512aed3..c6688d7 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index e0bb209..4c5891e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index 6870cf6..c66c708 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -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
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 3d33767..9175341 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -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_
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index 7052a83..19b3a97 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -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__
diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig
index 01cff18..44ce54e 100644
--- a/drivers/scsi/bnx2i/Kconfig
+++ b/drivers/scsi/bnx2i/Kconfig
@@ -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.
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index c73bbcb..ed7f322 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -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_
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index d6d491c..fb072cc 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -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>
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 80c03b4..c8b410c 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -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);
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 166543f..40e2249 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -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,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index a0a3d9f..6d56fd6 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -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"
diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c
index 7d9b54a..a0dd1b6 100644
--- a/drivers/scsi/fnic/fnic_isr.c
+++ b/drivers/scsi/fnic/fnic_isr.c
@@ -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;
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a59e1e0..8545d18 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -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);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 6eb47b6..598c42c 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -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);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 017a529..8fae032 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -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 {
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 695b34e..4198e45 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -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;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 06f9a5b..a5769a9 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -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;
}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 8b88118..2f262be 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -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)));
}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index fd3b998..0ac5815 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -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;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 5055f92..dd46101 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -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;
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 0cf4f70..93ce2b2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -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);
}
/**
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 0274ac3..7cf48c5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -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;
}
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 0d78a4d..80bacb5 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -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);
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index a368d77..d3a08ae 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -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;
}
}
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a97be01..1738310 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -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;
}
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index e90c89f..e49623a 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -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:
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 8a44bc9..34cea82 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -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);
}
/**
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 1ee06f2..f6b2ac5 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -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,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index d70587f..b06443a 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -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,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e218441..46990f4 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -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,
diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
index 13d628b..a22bb1b 100644
--- a/drivers/scsi/qlogicfas.c
+++ b/drivers/scsi/qlogicfas.c
@@ -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);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6ed43fd..d19c0e3 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -42,6 +42,10 @@
#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>
@@ -53,13 +57,16 @@
#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)
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 4b0f167..5d6f348 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -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)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 126bf26..b481e62 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -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);
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 9969fa1..fecac5d0 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -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;
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f42d1ce..fafcf5e 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -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,
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 8b95312..c007a7a 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -135,26 +135,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
}
/**
- * 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
* @id: PCI device id
@@ -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");
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 0c28772..ba27215 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -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 */
@@ -1134,6 +1152,30 @@ out_put_tag:
}
/**
+ * 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
* query_opcode: flag query to perform
@@ -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",
@@ -1275,6 +1302,82 @@ out:
}
/**
+ * 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;
}
@@ -1953,42 +2111,6 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
}
/**
- * 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
* @scsi_status: SCSI command status
@@ -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.
@@ -2971,6 +3088,38 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
}
/**
+ * 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
* @cookie: cookie data
@@ -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,
@@ -3110,6 +3261,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
* @hba_handle: driver private 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) {
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 9abc7e3..e1b844b 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -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
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 308256b..eee1bc0 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -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,
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index c88e146..598f65e 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -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;
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 8c79980..007a0bc 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -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 */
/*
OpenPOWER on IntegriCloud