summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt3sas
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-21 19:50:15 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-21 19:50:15 +0200
commit10fd71780f7d155f4e35fecfad0ebd4a725a244b (patch)
treeb88976120fd8f620669ed239842ea26ecc2c5e52 /drivers/scsi/mpt3sas
parentMerge tag 'for-5.4/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/g... (diff)
parentscsi: hisi_sas: Fix the conflict between device gone and host reset (diff)
downloadlinux-10fd71780f7d155f4e35fecfad0ebd4a725a244b.tar.xz
linux-10fd71780f7d155f4e35fecfad0ebd4a725a244b.zip
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This is mostly update of the usual drivers: qla2xxx, ufs, smartpqi, lpfc, hisi_sas, qedf, mpt3sas; plus a whole load of minor updates. The only core change this time around is the addition of request batching for virtio. Since batching requires an additional flag to use, it should be invisible to the rest of the drivers" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (264 commits) scsi: hisi_sas: Fix the conflict between device gone and host reset scsi: hisi_sas: Add BIST support for phy loopback scsi: hisi_sas: Add hisi_sas_debugfs_alloc() to centralise allocation scsi: hisi_sas: Remove some unused function arguments scsi: hisi_sas: Remove redundant work declaration scsi: hisi_sas: Remove hisi_sas_hw.slot_complete scsi: hisi_sas: Assign NCQ tag for all NCQ commands scsi: hisi_sas: Update all the registers after suspend and resume scsi: hisi_sas: Retry 3 times TMF IO for SAS disks when init device scsi: hisi_sas: Remove sleep after issue phy reset if sas_smp_phy_control() fails scsi: hisi_sas: Directly return when running I_T_nexus reset if phy disabled scsi: hisi_sas: Use true/false as input parameter of sas_phy_reset() scsi: hisi_sas: add debugfs auto-trigger for internal abort time out scsi: virtio_scsi: unplug LUNs when events missed scsi: scsi_dh_rdac: zero cdb in send_mode_select() scsi: fcoe: fix null-ptr-deref Read in fc_release_transport scsi: ufs-hisi: use devm_platform_ioremap_resource() to simplify code scsi: ufshcd: use devm_platform_ioremap_resource() to simplify code scsi: hisi_sas: use devm_platform_ioremap_resource() to simplify code scsi: ufs: Use kmemdup in ufshcd_read_string_desc() ...
Diffstat (limited to 'drivers/scsi/mpt3sas')
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2.h5
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h10
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_image.h39
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_pci.h13
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_tool.h13
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c175
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h30
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c178
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c196
9 files changed, 543 insertions, 116 deletions
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
index 7efd17a3c25b..18b1e31b5eb8 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2.h
@@ -9,7 +9,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.53
+ * mpi2.h Version: 02.00.54
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@@ -121,6 +121,7 @@
* 08-15-18 02.00.52 Bumped MPI2_HEADER_VERSION_UNIT.
* 08-28-18 02.00.53 Bumped MPI2_HEADER_VERSION_UNIT.
* Added MPI2_IOCSTATUS_FAILURE
+ * 12-17-18 02.00.54 Bumped MPI2_HEADER_VERSION_UNIT
* --------------------------------------------------------------------------
*/
@@ -161,7 +162,7 @@
/* Unit and Dev versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x35)
+#define MPI2_HEADER_VERSION_UNIT (0x36)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index 167d79d145ca..3a6871aecada 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -7,7 +7,7 @@
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.46
+ * mpi2_cnfg.h Version: 02.00.47
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@@ -244,6 +244,11 @@
* Added DMDReport Delay Time defines to
* PCIeIOUnitPage1
* --------------------------------------------------------------------------
+ * 08-02-18 02.00.44 Added Slotx2, Slotx4 to ManPage 7.
+ * 08-15-18 02.00.45 Added ProductSpecific field at end of IOC Page 1
+ * 08-28-18 02.00.46 Added NVMs Write Cache flag to IOUnitPage1
+ * Added DMDReport Delay Time defines to PCIeIOUnitPage1
+ * 12-17-18 02.00.47 Swap locations of Slotx2 and Slotx4 in ManPage 7.
*/
#ifndef MPI2_CNFG_H
@@ -810,7 +815,8 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
U8 Location; /*0x14 */
U8 ReceptacleID; /*0x15 */
U16 Slot; /*0x16 */
- U32 Reserved2; /*0x18 */
+ U16 Slotx2; /*0x18 */
+ U16 Slotx4; /*0x1A */
} MPI2_MANPAGE7_CONNECTOR_INFO,
*PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
Mpi2ManPage7ConnectorInfo_t,
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_image.h b/drivers/scsi/mpt3sas/mpi/mpi2_image.h
index 4959585f029d..a3f677853098 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_image.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_image.h
@@ -5,7 +5,7 @@
* Name: mpi2_image.h
* Description: Contains definitions for firmware and other component images
* Creation Date: 04/02/2018
- * Version: 02.06.03
+ * Version: 02.06.04
*
*
* Version History
@@ -17,6 +17,8 @@
* 08-14-18 02.06.01 Corrected define for MPI26_IMAGE_HEADER_SIGNATURE0_MPI26
* 08-28-18 02.06.02 Added MPI2_EXT_IMAGE_TYPE_RDE
* 09-07-18 02.06.03 Added MPI26_EVENT_PCIE_TOPO_PI_16_LANES
+ * 12-17-18 02.06.04 Addd MPI2_EXT_IMAGE_TYPE_PBLP
+ * Shorten some defines to be compatible with DOS
*/
#ifndef MPI2_IMAGE_H
#define MPI2_IMAGE_H
@@ -200,17 +202,17 @@ typedef struct _MPI26_COMPONENT_IMAGE_HEADER {
#define MPI26_IMAGE_HEADER_SIGNATURE0_MPI26 (0xEB000042)
/**** Definitions for Signature1 field ****/
-#define MPI26_IMAGE_HEADER_SIGNATURE1_APPLICATION (0x20505041)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_CBB (0x20424243)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_MFG (0x2047464D)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_BIOS (0x534F4942)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_HIIM (0x4D494948)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_HIIA (0x41494948)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_CPLD (0x444C5043)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_SPD (0x20445053)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_NVDATA (0x5444564E)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_GAS_GAUGE (0x20534147)
-#define MPI26_IMAGE_HEADER_SIGNATURE1_PBLP (0x50424C50)
+#define MPI26_IMAGE_HEADER_SIG1_APPLICATION (0x20505041)
+#define MPI26_IMAGE_HEADER_SIG1_CBB (0x20424243)
+#define MPI26_IMAGE_HEADER_SIG1_MFG (0x2047464D)
+#define MPI26_IMAGE_HEADER_SIG1_BIOS (0x534F4942)
+#define MPI26_IMAGE_HEADER_SIG1_HIIM (0x4D494948)
+#define MPI26_IMAGE_HEADER_SIG1_HIIA (0x41494948)
+#define MPI26_IMAGE_HEADER_SIG1_CPLD (0x444C5043)
+#define MPI26_IMAGE_HEADER_SIG1_SPD (0x20445053)
+#define MPI26_IMAGE_HEADER_SIG1_NVDATA (0x5444564E)
+#define MPI26_IMAGE_HEADER_SIG1_GAS_GAUGE (0x20534147)
+#define MPI26_IMAGE_HEADER_SIG1_PBLP (0x504C4250)
/**** Definitions for Signature2 field ****/
#define MPI26_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546)
@@ -278,6 +280,7 @@ typedef struct _MPI2_EXT_IMAGE_HEADER {
#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08)
#define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09)
#define MPI2_EXT_IMAGE_TYPE_RDE (0x0A)
+#define MPI2_EXT_IMAGE_TYPE_PBLP (0x0B)
#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80)
#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF)
@@ -472,12 +475,12 @@ Mpi25EncryptedHashEntry_t, *pMpi25EncryptedHashEntry_t;
#define MPI25_HASH_ALGORITHM_UNUSED (0x00)
#define MPI25_HASH_ALGORITHM_SHA256 (0x01)
-#define MPI26_HASH_ALGORITHM_VERSION_MASK (0xE0)
-#define MPI26_HASH_ALGORITHM_VERSION_NONE (0x00)
-#define MPI26_HASH_ALGORITHM_VERSION_SHA1 (0x20)
-#define MPI26_HASH_ALGORITHM_VERSION_SHA2 (0x40)
-#define MPI26_HASH_ALGORITHM_VERSION_SHA3 (0x60)
-#define MPI26_HASH_ALGORITHM_SIZE_MASK (0x1F)
+#define MPI26_HASH_ALGORITHM_VER_MASK (0xE0)
+#define MPI26_HASH_ALGORITHM_VER_NONE (0x00)
+#define MPI26_HASH_ALGORITHM_VER_SHA1 (0x20)
+#define MPI26_HASH_ALGORITHM_VER_SHA2 (0x40)
+#define MPI26_HASH_ALGORITHM_VER_SHA3 (0x60)
+#define MPI26_HASH_ALGORITHM_SIZE_MASK (0x1F)
#define MPI26_HASH_ALGORITHM_SIZE_256 (0x01)
#define MPI26_HASH_ALGORITHM_SIZE_512 (0x02)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_pci.h b/drivers/scsi/mpt3sas/mpi/mpi2_pci.h
index 63a09509d7d1..bb7b79cfa558 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_pci.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_pci.h
@@ -6,7 +6,7 @@
* Title: MPI PCIe Attached Devices structures and definitions.
* Creation Date: October 9, 2012
*
- * mpi2_pci.h Version: 02.00.03
+ * mpi2_pci.h Version: 02.00.04
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@@ -24,6 +24,8 @@
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
* NVME Encapsulated Request.
* 07-22-18 02.00.03 Updted flags field for NVME Encapsulated req
+ * 12-17-18 02.00.04 Added MPI26_PCIE_DEVINFO_SCSI
+ * Shortten some defines to be compatible with DOS
* --------------------------------------------------------------------------
*/
@@ -41,7 +43,7 @@
#define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000)
#define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001)
#define MPI26_PCIE_DEVINFO_NVME (0x00000003)
-
+#define MPI26_PCIE_DEVINFO_SCSI (0x00000004)
/****************************************************************************
* NVMe Encapsulated message
@@ -75,10 +77,9 @@ typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST {
#define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000)
#define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010)
/*Error Response Address Space */
-#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR (0x000C)
-#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR_MASK (0x000C)
-#define MPI26_NVME_FLAGS_SYSTEM_RSP_ADDR (0x0000)
-#define MPI26_NVME_FLAGS_IOCCTL_RSP_ADDR (0x0008)
+#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_MASK (0x000C)
+#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_SYSTEM (0x0000)
+#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_IOCTL (0x0008)
/* Data Direction*/
#define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003)
#define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
index 3f966b6796b3..17ef7f63b938 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
@@ -7,7 +7,7 @@
* Title: MPI diagnostic tool structures and definitions
* Creation Date: March 26, 2007
*
- * mpi2_tool.h Version: 02.00.15
+ * mpi2_tool.h Version: 02.00.16
*
* Version History
* ---------------
@@ -40,6 +40,7 @@
* Tool Request Message.
* 07-22-18 02.00.15 Added defines for new TOOLBOX_PCIE_LANE_MARGINING tool.
* Added option for DeviceInfo field in ISTWI tool.
+ * 12-17-18 02.00.16 Shorten some defines to be compatible with DOS.
* --------------------------------------------------------------------------
*/
@@ -230,11 +231,11 @@ typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST {
#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07)
/*MPI26 TOOLBOX Request MsgFlags defines */
-#define MPI26_TOOLBOX_REQ_MSGFLAGS_ADDRESSING_MASK (0x01)
+#define MPI26_TOOL_ISTWI_MSGFLG_ADDR_MASK (0x01)
/*Request uses Man Page 43 device index addressing */
-#define MPI26_TOOLBOX_REQ_MSGFLAGS_ADDRESSING_DEVINDEX (0x00)
+#define MPI26_TOOL_ISTWI_MSGFLG_ADDR_INDEX (0x00)
/*Request uses Man Page 43 device info struct addressing */
-#define MPI26_TOOLBOX_REQ_MSGFLAGS_ADDRESSING_DEVINFO (0x01)
+#define MPI26_TOOL_ISTWI_MSGFLG_ADDR_INFO (0x01)
/*Toolbox ISTWI Read Write Tool reply message */
typedef struct _MPI2_TOOLBOX_ISTWI_REPLY {
@@ -403,7 +404,7 @@ Mpi2ToolboxTextDisplayRequest_t,
*/
/*Toolbox Backend Lane Margining Tool request message */
-typedef struct _MPI26_TOOLBOX_LANE_MARGINING_REQUEST {
+typedef struct _MPI26_TOOLBOX_LANE_MARGIN_REQUEST {
U8 Tool; /*0x00 */
U8 Reserved1; /*0x01 */
U8 ChainOffset; /*0x02 */
@@ -434,7 +435,7 @@ typedef struct _MPI26_TOOLBOX_LANE_MARGINING_REQUEST {
/*Toolbox Backend Lane Margining Tool reply message */
-typedef struct _MPI26_TOOLBOX_LANE_MARGINING_REPLY {
+typedef struct _MPI26_TOOLBOX_LANE_MARGIN_REPLY {
U8 Tool; /*0x00 */
U8 Reserved1; /*0x01 */
U8 MsgLength; /*0x02 */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 050c0f029ef9..fea3cb6a090b 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2260,6 +2260,11 @@ base_is_prp_possible(struct MPT3SAS_ADAPTER *ioc,
bool build_prp = true;
data_length = scsi_bufflen(scmd);
+ if (pcie_device &&
+ (mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info))) {
+ build_prp = false;
+ return build_prp;
+ }
/* If Datalenth is <= 16K and number of SGE’s entries are <= 2
* we built IEEE SGL
@@ -3178,6 +3183,37 @@ mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc)
}
}
+static int
+_base_diag_reset(struct MPT3SAS_ADAPTER *ioc);
+
+/**
+ * _base_check_for_fault_and_issue_reset - check if IOC is in fault state
+ * and if it is in fault state then issue diag reset.
+ * @ioc: per adapter object
+ *
+ * Returns: 0 for success, non-zero for failure.
+ */
+static int
+_base_check_for_fault_and_issue_reset(struct MPT3SAS_ADAPTER *ioc)
+{
+ u32 ioc_state;
+ int rc = -EFAULT;
+
+ dinitprintk(ioc, pr_info("%s\n", __func__));
+ if (ioc->pci_error_recovery)
+ return 0;
+ ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+ dhsprintk(ioc, pr_info("%s: ioc_state(0x%08x)\n", __func__, ioc_state));
+
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+ mpt3sas_base_fault_info(ioc, ioc_state &
+ MPI2_DOORBELL_DATA_MASK);
+ rc = _base_diag_reset(ioc);
+ }
+
+ return rc;
+}
+
/**
* mpt3sas_base_map_resources - map in controller resources (io/irq/memap)
* @ioc: per adapter object
@@ -3190,7 +3226,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
struct pci_dev *pdev = ioc->pdev;
u32 memap_sz;
u32 pio_sz;
- int i, r = 0;
+ int i, r = 0, rc;
u64 pio_chip = 0;
phys_addr_t chip_phys = 0;
struct adapter_reply_queue *reply_q;
@@ -3251,8 +3287,11 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
_base_mask_interrupts(ioc);
r = _base_get_ioc_facts(ioc);
- if (r)
- goto out_fail;
+ if (r) {
+ rc = _base_check_for_fault_and_issue_reset(ioc);
+ if (rc || (_base_get_ioc_facts(ioc)))
+ goto out_fail;
+ }
if (!ioc->rdpq_array_enable_assigned) {
ioc->rdpq_array_enable = ioc->rdpq_array_capable;
@@ -5037,6 +5076,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
_base_release_memory_pools(ioc);
goto retry_allocation;
}
+ memset(ioc->request, 0, sz);
if (retry_sz)
ioc_err(ioc, "request pool: dma_alloc_coherent succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), total(%d kb)\n",
@@ -5410,8 +5450,6 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout)
*
* Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
*/
-static int
-_base_diag_reset(struct MPT3SAS_ADAPTER *ioc);
static int
_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout)
@@ -5868,6 +5906,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
ioc->base_cmds.status = MPT3_CMD_PENDING;
request = mpt3sas_base_get_msg_frame(ioc, smid);
ioc->base_cmds.smid = smid;
+ memset(request, 0, ioc->request_sz);
memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
init_completion(&ioc->base_cmds.done);
ioc->put_smid_default(ioc, smid);
@@ -6686,7 +6725,7 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type)
static int
_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
{
- int r, i, index;
+ int r, i, index, rc;
unsigned long flags;
u32 reply_address;
u16 smid;
@@ -6789,8 +6828,19 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
skip_init_reply_post_free_queue:
r = _base_send_ioc_init(ioc);
- if (r)
- return r;
+ if (r) {
+ /*
+ * No need to check IOC state for fault state & issue
+ * diag reset during host reset. This check is need
+ * only during driver load time.
+ */
+ if (!ioc->is_driver_loading)
+ return r;
+
+ rc = _base_check_for_fault_and_issue_reset(ioc);
+ if (rc || (_base_send_ioc_init(ioc)))
+ return r;
+ }
/* initialize reply free host index */
ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
@@ -6882,7 +6932,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
int
mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
{
- int r, i;
+ int r, i, rc;
int cpu_id, last_cpu_id = 0;
dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__));
@@ -6926,8 +6976,11 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
pci_set_drvdata(ioc->pdev, ioc->shost);
r = _base_get_ioc_facts(ioc);
- if (r)
- goto out_free_resources;
+ if (r) {
+ rc = _base_check_for_fault_and_issue_reset(ioc);
+ if (rc || (_base_get_ioc_facts(ioc)))
+ goto out_free_resources;
+ }
switch (ioc->hba_mpi_version_belonged) {
case MPI2_VERSION:
@@ -6995,8 +7048,11 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
r = _base_get_port_facts(ioc, i);
- if (r)
- goto out_free_resources;
+ if (r) {
+ rc = _base_check_for_fault_and_issue_reset(ioc);
+ if (rc || (_base_get_port_facts(ioc, i)))
+ goto out_free_resources;
+ }
}
r = _base_allocate_memory_pools(ioc);
@@ -7118,6 +7174,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
if (r)
goto out_free_resources;
+ /*
+ * Copy current copy of IOCFacts in prev_fw_facts
+ * and it will be used during online firmware upgrade.
+ */
+ memcpy(&ioc->prev_fw_facts, &ioc->facts,
+ sizeof(struct mpt3sas_facts));
+
ioc->non_operational_loop = 0;
ioc->got_task_abort_from_ioctl = 0;
return 0;
@@ -7280,6 +7343,85 @@ mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
}
/**
+ * _base_check_ioc_facts_changes - Look for increase/decrease of IOCFacts
+ * attributes during online firmware upgrade and update the corresponding
+ * IOC variables accordingly.
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ */
+static int
+_base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc)
+{
+ u16 pd_handles_sz;
+ void *pd_handles = NULL, *blocking_handles = NULL;
+ void *pend_os_device_add = NULL, *device_remove_in_progress = NULL;
+ struct mpt3sas_facts *old_facts = &ioc->prev_fw_facts;
+
+ if (ioc->facts.MaxDevHandle > old_facts->MaxDevHandle) {
+ pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
+ if (ioc->facts.MaxDevHandle % 8)
+ pd_handles_sz++;
+
+ pd_handles = krealloc(ioc->pd_handles, pd_handles_sz,
+ GFP_KERNEL);
+ if (!pd_handles) {
+ ioc_info(ioc,
+ "Unable to allocate the memory for pd_handles of sz: %d\n",
+ pd_handles_sz);
+ return -ENOMEM;
+ }
+ memset(pd_handles + ioc->pd_handles_sz, 0,
+ (pd_handles_sz - ioc->pd_handles_sz));
+ ioc->pd_handles = pd_handles;
+
+ blocking_handles = krealloc(ioc->blocking_handles,
+ pd_handles_sz, GFP_KERNEL);
+ if (!blocking_handles) {
+ ioc_info(ioc,
+ "Unable to allocate the memory for "
+ "blocking_handles of sz: %d\n",
+ pd_handles_sz);
+ return -ENOMEM;
+ }
+ memset(blocking_handles + ioc->pd_handles_sz, 0,
+ (pd_handles_sz - ioc->pd_handles_sz));
+ ioc->blocking_handles = blocking_handles;
+ ioc->pd_handles_sz = pd_handles_sz;
+
+ pend_os_device_add = krealloc(ioc->pend_os_device_add,
+ pd_handles_sz, GFP_KERNEL);
+ if (!pend_os_device_add) {
+ ioc_info(ioc,
+ "Unable to allocate the memory for pend_os_device_add of sz: %d\n",
+ pd_handles_sz);
+ return -ENOMEM;
+ }
+ memset(pend_os_device_add + ioc->pend_os_device_add_sz, 0,
+ (pd_handles_sz - ioc->pend_os_device_add_sz));
+ ioc->pend_os_device_add = pend_os_device_add;
+ ioc->pend_os_device_add_sz = pd_handles_sz;
+
+ device_remove_in_progress = krealloc(
+ ioc->device_remove_in_progress, pd_handles_sz, GFP_KERNEL);
+ if (!device_remove_in_progress) {
+ ioc_info(ioc,
+ "Unable to allocate the memory for "
+ "device_remove_in_progress of sz: %d\n "
+ , pd_handles_sz);
+ return -ENOMEM;
+ }
+ memset(device_remove_in_progress +
+ ioc->device_remove_in_progress_sz, 0,
+ (pd_handles_sz - ioc->device_remove_in_progress_sz));
+ ioc->device_remove_in_progress = device_remove_in_progress;
+ ioc->device_remove_in_progress_sz = pd_handles_sz;
+ }
+
+ memcpy(&ioc->prev_fw_facts, &ioc->facts, sizeof(struct mpt3sas_facts));
+ return 0;
+}
+
+/**
* mpt3sas_base_hard_reset_handler - reset controller
* @ioc: Pointer to MPT_ADAPTER structure
* @type: FORCE_BIG_HAMMER or SOFT_RESET
@@ -7342,6 +7484,13 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
if (r)
goto out;
+ r = _base_check_ioc_facts_changes(ioc);
+ if (r) {
+ ioc_info(ioc,
+ "Some of the parameters got changed in this new firmware"
+ " image and it requires system reboot\n");
+ goto out;
+ }
if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable)
panic("%s: Issue occurred with flashing controller firmware."
"Please reboot the system and ensure that the correct"
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 6afbdb044310..faca0a5e71f8 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -76,8 +76,8 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "29.100.00.00"
-#define MPT3SAS_MAJOR_VERSION 29
+#define MPT3SAS_DRIVER_VERSION "31.100.00.00"
+#define MPT3SAS_MAJOR_VERSION 31
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@@ -583,6 +583,7 @@ static inline void sas_device_put(struct _sas_device *s)
* @enclosure_level: The level of device's enclosure from the controller
* @connector_name: ASCII value of the Connector's name
* @serial_number: pointer of serial number string allocated runtime
+ * @access_status: Device's Access Status
* @refcount: reference count for deletion
*/
struct _pcie_device {
@@ -604,6 +605,7 @@ struct _pcie_device {
u8 connector_name[4];
u8 *serial_number;
u8 reset_timeout;
+ u8 access_status;
struct kref refcount;
};
/**
@@ -1045,6 +1047,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
* @thresh_hold: Max number of reply descriptors processed
* before updating Host Index
+ * @drv_support_bitmap: driver's supported feature bit map
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
* @scsih_cb_idx: scsih internal commands
@@ -1066,6 +1069,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @event_log: event log pointer
* @event_masks: events that are masked
* @facts: static facts data
+ * @prev_fw_facts: previous fw facts data
* @pfacts: static port facts data
* @manu_pg0: static manufacturing page 0
* @manu_pg10: static manufacturing page 10
@@ -1227,6 +1231,8 @@ struct MPT3SAS_ADAPTER {
bool msix_load_balance;
u16 thresh_hold;
u8 high_iops_queues;
+ u32 drv_support_bitmap;
+ bool enable_sdev_max_qd;
/* internal commands, callback index */
u8 scsi_io_cb_idx;
@@ -1276,6 +1282,7 @@ struct MPT3SAS_ADAPTER {
/* static config pages */
struct mpt3sas_facts facts;
+ struct mpt3sas_facts prev_fw_facts;
struct mpt3sas_port_facts *pfacts;
Mpi2ManufacturingPage0_t manu_pg0;
struct Mpi2ManufacturingPage10_t manu_pg10;
@@ -1450,6 +1457,8 @@ struct MPT3SAS_ADAPTER {
GET_MSIX_INDEX get_msix_index_for_smlio;
};
+#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
+
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
@@ -1579,6 +1588,7 @@ struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
struct _raid_device *
mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle);
+void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
/* config shared API */
u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
@@ -1733,4 +1743,20 @@ mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
/* NCQ Prio Handling Check */
bool scsih_ncq_prio_supp(struct scsi_device *sdev);
+/**
+ * _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device
+ * @device_info: bitfield providing information about the device.
+ * Context: none
+ *
+ * Returns 1 if scsi device.
+ */
+static inline int
+mpt3sas_scsih_is_pcie_scsi_device(u32 device_info)
+{
+ if ((device_info &
+ MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE) == MPI26_PCIE_DEVINFO_SCSI)
+ return 1;
+ else
+ return 0;
+}
#endif /* MPT3SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index d4ecfbbe738c..7d696952b376 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -596,8 +596,16 @@ _ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg,
if (priv_data->sas_target->handle != handle)
continue;
st = scsi_cmd_priv(scmd);
- tm_request->TaskMID = cpu_to_le16(st->smid);
- found = 1;
+
+ /*
+ * If the given TaskMID from the user space is zero, then the
+ * first outstanding smid will be picked up. Otherwise,
+ * targeted smid will be the one.
+ */
+ if (!tm_request->TaskMID || tm_request->TaskMID == st->smid) {
+ tm_request->TaskMID = cpu_to_le16(st->smid);
+ found = 1;
+ }
}
if (!found) {
@@ -654,7 +662,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
size_t data_in_sz = 0;
long ret;
u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
- u8 tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
issue_reset = 0;
@@ -707,6 +714,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
ioc->ctl_cmds.status = MPT3_CMD_PENDING;
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
request = mpt3sas_base_get_msg_frame(ioc, smid);
+ memset(request, 0, ioc->request_sz);
memcpy(request, mpi_request, karg.data_sge_offset*4);
ioc->ctl_cmds.smid = smid;
data_out_sz = karg.data_out_size;
@@ -921,13 +929,37 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
Mpi2ToolboxCleanRequest_t *toolbox_request =
(Mpi2ToolboxCleanRequest_t *)mpi_request;
- if (toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) {
+ if ((toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL)
+ || (toolbox_request->Tool ==
+ MPI26_TOOLBOX_BACKEND_PCIE_LANE_MARGIN))
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
data_in_dma, data_in_sz);
- } else {
+ else if (toolbox_request->Tool ==
+ MPI2_TOOLBOX_MEMORY_MOVE_TOOL) {
+ Mpi2ToolboxMemMoveRequest_t *mem_move_request =
+ (Mpi2ToolboxMemMoveRequest_t *)request;
+ Mpi2SGESimple64_t tmp, *src = NULL, *dst = NULL;
+
+ ioc->build_sg_mpi(ioc, psge, data_out_dma,
+ data_out_sz, data_in_dma, data_in_sz);
+ if (data_out_sz && !data_in_sz) {
+ dst =
+ (Mpi2SGESimple64_t *)&mem_move_request->SGL;
+ src = (void *)dst + ioc->sge_size;
+
+ memcpy(&tmp, src, ioc->sge_size);
+ memcpy(src, dst, ioc->sge_size);
+ memcpy(dst, &tmp, ioc->sge_size);
+ }
+ if (ioc->logging_level & MPT_DEBUG_TM) {
+ ioc_info(ioc,
+ "Mpi2ToolboxMemMoveRequest_t request msg\n");
+ _debug_dump_mf(mem_move_request,
+ ioc->request_sz/4);
+ }
+ } else
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
- data_in_dma, data_in_sz);
- }
+ data_in_dma, data_in_sz);
ioc->put_smid_default(ioc, smid);
break;
}
@@ -1047,12 +1079,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
mpt3sas_halt_firmware(ioc);
pcie_device = mpt3sas_get_pdev_by_handle(ioc,
le16_to_cpu(mpi_request->FunctionDependent1));
- if (pcie_device && (!ioc->tm_custom_handling))
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(
+ pcie_device->device_info))))
mpt3sas_scsih_issue_locked_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1),
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
0, pcie_device->reset_timeout,
- tr_method);
+ MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE);
else
mpt3sas_scsih_issue_locked_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1),
@@ -3278,9 +3312,8 @@ diag_trigger_scsi_store(struct device *cdev,
ssize_t sz;
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
- sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count);
- memset(&ioc->diag_trigger_scsi, 0,
- sizeof(struct SL_WH_EVENT_TRIGGERS_T));
+ sz = min(sizeof(ioc->diag_trigger_scsi), count);
+ memset(&ioc->diag_trigger_scsi, 0, sizeof(ioc->diag_trigger_scsi));
memcpy(&ioc->diag_trigger_scsi, buf, sz);
if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES)
ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES;
@@ -3349,6 +3382,125 @@ static DEVICE_ATTR_RW(diag_trigger_mpi);
/*****************************************/
+/**
+ * drv_support_bitmap_show - driver supported feature bitmap
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+drv_support_bitmap_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", ioc->drv_support_bitmap);
+}
+static DEVICE_ATTR_RO(drv_support_bitmap);
+
+/**
+ * enable_sdev_max_qd_show - display whether sdev max qd is enabled/disabled
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs read/write shost attribute. This attribute is used to set the
+ * targets queue depth to HBA IO queue depth if this attribute is enabled.
+ */
+static ssize_t
+enable_sdev_max_qd_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ioc->enable_sdev_max_qd);
+}
+
+/**
+ * enable_sdev_max_qd_store - Enable/disable sdev max qd
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs read/write shost attribute. This attribute is used to set the
+ * targets queue depth to HBA IO queue depth if this attribute is enabled.
+ * If this attribute is disabled then targets will have corresponding default
+ * queue depth.
+ */
+static ssize_t
+enable_sdev_max_qd_store(struct device *cdev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct MPT3SAS_DEVICE *sas_device_priv_data;
+ struct MPT3SAS_TARGET *sas_target_priv_data;
+ int val = 0;
+ struct scsi_device *sdev;
+ struct _raid_device *raid_device;
+ int qdepth;
+
+ if (kstrtoint(buf, 0, &val) != 0)
+ return -EINVAL;
+
+ switch (val) {
+ case 0:
+ ioc->enable_sdev_max_qd = 0;
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ sas_target_priv_data = sas_device_priv_data->sas_target;
+ if (!sas_target_priv_data)
+ continue;
+
+ if (sas_target_priv_data->flags &
+ MPT_TARGET_FLAGS_VOLUME) {
+ raid_device =
+ mpt3sas_raid_device_find_by_handle(ioc,
+ sas_target_priv_data->handle);
+
+ switch (raid_device->volume_type) {
+ case MPI2_RAID_VOL_TYPE_RAID0:
+ if (raid_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SSP_TARGET)
+ qdepth =
+ MPT3SAS_SAS_QUEUE_DEPTH;
+ else
+ qdepth =
+ MPT3SAS_SATA_QUEUE_DEPTH;
+ break;
+ case MPI2_RAID_VOL_TYPE_RAID1E:
+ case MPI2_RAID_VOL_TYPE_RAID1:
+ case MPI2_RAID_VOL_TYPE_RAID10:
+ case MPI2_RAID_VOL_TYPE_UNKNOWN:
+ default:
+ qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
+ }
+ } else if (sas_target_priv_data->flags &
+ MPT_TARGET_FLAGS_PCIE_DEVICE)
+ qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
+ else
+ qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
+
+ mpt3sas_scsih_change_queue_depth(sdev, qdepth);
+ }
+ break;
+ case 1:
+ ioc->enable_sdev_max_qd = 1;
+ shost_for_each_device(sdev, ioc->shost)
+ mpt3sas_scsih_change_queue_depth(sdev,
+ shost->can_queue);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return strlen(buf);
+}
+static DEVICE_ATTR_RW(enable_sdev_max_qd);
+
struct device_attribute *mpt3sas_host_attrs[] = {
&dev_attr_version_fw,
&dev_attr_version_bios,
@@ -3374,7 +3526,9 @@ struct device_attribute *mpt3sas_host_attrs[] = {
&dev_attr_diag_trigger_event,
&dev_attr_diag_trigger_scsi,
&dev_attr_diag_trigger_mpi,
+ &dev_attr_drv_support_bitmap,
&dev_attr_BRM_status,
+ &dev_attr_enable_sdev_max_qd,
NULL,
};
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 717ba0845a2a..d0c2f8d6f2a2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -155,6 +155,10 @@ static int prot_mask = -1;
module_param(prot_mask, int, 0444);
MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
+static bool enable_sdev_max_qd;
+module_param(enable_sdev_max_qd, bool, 0444);
+MODULE_PARM_DESC(enable_sdev_max_qd,
+ "Enable sdev max qd as can_queue, def=disabled(0)");
/* raid transport support */
static struct raid_template *mpt3sas_raid_template;
@@ -1152,6 +1156,11 @@ _scsih_pcie_device_add(struct MPT3SAS_ADAPTER *ioc,
list_add_tail(&pcie_device->list, &ioc->pcie_device_list);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
+ if (pcie_device->access_status ==
+ MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED) {
+ clear_bit(pcie_device->handle, ioc->pend_os_device_add);
+ return;
+ }
if (scsi_add_device(ioc->shost, PCIE_CHANNEL, pcie_device->id, 0)) {
_scsih_pcie_device_remove(ioc, pcie_device);
} else if (!pcie_device->starget) {
@@ -1196,7 +1205,9 @@ _scsih_pcie_device_init_add(struct MPT3SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
pcie_device_get(pcie_device);
list_add_tail(&pcie_device->list, &ioc->pcie_device_init_list);
- _scsih_determine_boot_device(ioc, pcie_device, PCIE_CHANNEL);
+ if (pcie_device->access_status !=
+ MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED)
+ _scsih_determine_boot_device(ioc, pcie_device, PCIE_CHANNEL);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
}
/**
@@ -1433,17 +1444,20 @@ _scsih_is_end_device(u32 device_info)
}
/**
- * _scsih_is_nvme_device - determines if device is an nvme device
+ * _scsih_is_nvme_pciescsi_device - determines if
+ * device is an pcie nvme/scsi device
* @device_info: bitfield providing information about the device.
* Context: none
*
- * Return: 1 if nvme device.
+ * Returns 1 if device is pcie device type nvme/scsi.
*/
static int
-_scsih_is_nvme_device(u32 device_info)
+_scsih_is_nvme_pciescsi_device(u32 device_info)
{
- if ((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE)
- == MPI26_PCIE_DEVINFO_NVME)
+ if (((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE)
+ == MPI26_PCIE_DEVINFO_NVME) ||
+ ((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE)
+ == MPI26_PCIE_DEVINFO_SCSI))
return 1;
else
return 0;
@@ -1509,7 +1523,13 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
max_depth = shost->can_queue;
- /* limit max device queue for SATA to 32 */
+ /*
+ * limit max device queue for SATA to 32 if enable_sdev_max_qd
+ * is disabled.
+ */
+ if (ioc->enable_sdev_max_qd)
+ goto not_sata;
+
sas_device_priv_data = sdev->hostdata;
if (!sas_device_priv_data)
goto not_sata;
@@ -1539,6 +1559,25 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
}
/**
+ * mpt3sas_scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ *
+ * Returns nothing.
+ */
+void
+mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+ struct Scsi_Host *shost = sdev->host;
+ struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+ if (ioc->enable_sdev_max_qd)
+ qdepth = shost->can_queue;
+
+ scsih_change_queue_depth(sdev, qdepth);
+}
+
+/**
* scsih_target_alloc - target add routine
* @starget: scsi target struct
*
@@ -2296,7 +2335,7 @@ scsih_slave_configure(struct scsi_device *sdev)
MPT3SAS_RAID_MAX_SECTORS);
}
- scsih_change_queue_depth(sdev, qdepth);
+ mpt3sas_scsih_change_queue_depth(sdev, qdepth);
/* raid transport support */
if (!ioc->is_warpdrive)
@@ -2360,7 +2399,7 @@ scsih_slave_configure(struct scsi_device *sdev)
pcie_device_put(pcie_device);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
- scsih_change_queue_depth(sdev, qdepth);
+ mpt3sas_scsih_change_queue_depth(sdev, qdepth);
/* Enable QUEUE_FLAG_NOMERGES flag, so that IOs won't be
** merged and can eliminate holes created during merging
** operation.
@@ -2420,7 +2459,7 @@ scsih_slave_configure(struct scsi_device *sdev)
_scsih_display_sata_capabilities(ioc, handle, sdev);
- scsih_change_queue_depth(sdev, qdepth);
+ mpt3sas_scsih_change_queue_depth(sdev, qdepth);
if (ssp_target) {
sas_read_port_mode_page(sdev);
@@ -2872,7 +2911,8 @@ scsih_abort(struct scsi_cmnd *scmd)
handle = sas_device_priv_data->sas_target->handle;
pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle);
- if (pcie_device && (!ioc->tm_custom_handling))
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info))))
timeout = ioc->nvme_abort_timeout;
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
@@ -2943,11 +2983,13 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle);
- if (pcie_device && (!ioc->tm_custom_handling)) {
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) {
tr_timeout = pcie_device->reset_timeout;
tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
} else
tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0,
tr_timeout, tr_method);
@@ -3020,7 +3062,8 @@ scsih_target_reset(struct scsi_cmnd *scmd)
pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle);
- if (pcie_device && (!ioc->tm_custom_handling)) {
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) {
tr_timeout = pcie_device->reset_timeout;
tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
} else
@@ -3598,7 +3641,9 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
sas_address = pcie_device->wwid;
}
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
- if (pcie_device && (!ioc->tm_custom_handling))
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(
+ pcie_device->device_info))))
tr_method =
MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
else
@@ -4654,11 +4699,8 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
* since we're lockless at this point
*/
do {
- if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
- scmd->result = SAM_STAT_BUSY;
- scmd->scsi_done(scmd);
- return 0;
- }
+ if (test_bit(0, &sas_device_priv_data->ata_command_pending))
+ return SCSI_MLQUEUE_DEVICE_BUSY;
} while (_scsih_set_satl_pending(scmd, true));
if (scmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -6456,24 +6498,17 @@ _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
/**
* _scsih_sas_device_status_change_event - handle device status change
* @ioc: per adapter object
- * @fw_event: The fw_event_work object
+ * @event_data: The fw event
* Context: user.
*/
static void
_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
+ Mpi2EventDataSasDeviceStatusChange_t *event_data)
{
struct MPT3SAS_TARGET *target_priv_data;
struct _sas_device *sas_device;
u64 sas_address;
unsigned long flags;
- Mpi2EventDataSasDeviceStatusChange_t *event_data =
- (Mpi2EventDataSasDeviceStatusChange_t *)
- fw_event->event_data;
-
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
- _scsih_sas_device_status_change_event_debug(ioc,
- event_data);
/* In MPI Revision K (0xC), the internal device reset complete was
* implemented, so avoid setting tm_busy flag for older firmware.
@@ -6505,6 +6540,12 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
else
target_priv_data->tm_busy = 0;
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ ioc_info(ioc,
+ "%s tm_busy flag for handle(0x%04x)\n",
+ (target_priv_data->tm_busy == 1) ? "Enable" : "Disable",
+ target_priv_data->handle);
+
out:
if (sas_device)
sas_device_put(sas_device);
@@ -6539,6 +6580,11 @@ _scsih_check_pcie_access_status(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
break;
case MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED:
desc = "PCIe device blocked";
+ ioc_info(ioc,
+ "Device with Access Status (%s): wwid(0x%016llx), "
+ "handle(0x%04x)\n ll only be added to the internal list",
+ desc, (u64)wwid, handle);
+ rc = 0;
break;
case MPI26_PCIEDEV0_ASTATUS_MEMORY_SPACE_ACCESS_FAILED:
desc = "PCIe device mem space access failed";
@@ -6643,7 +6689,8 @@ _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc,
pcie_device->enclosure_level,
pcie_device->connector_name);
- if (pcie_device->starget)
+ if (pcie_device->starget && (pcie_device->access_status !=
+ MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED))
scsi_remove_target(&pcie_device->starget->dev);
dewtprintk(ioc,
ioc_info(ioc, "%s: exit: handle(0x%04x), wwid(0x%016llx)\n",
@@ -6694,7 +6741,7 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
/* check if this is end device */
device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
- if (!(_scsih_is_nvme_device(device_info)))
+ if (!(_scsih_is_nvme_pciescsi_device(device_info)))
return;
wwid = le64_to_cpu(pcie_device_pg0.WWID);
@@ -6709,6 +6756,7 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
if (unlikely(pcie_device->handle != handle)) {
starget = pcie_device->starget;
sas_target_priv_data = starget->hostdata;
+ pcie_device->access_status = pcie_device_pg0.AccessStatus;
starget_printk(KERN_INFO, starget,
"handle changed from(0x%04x) to (0x%04x)!!!\n",
pcie_device->handle, handle);
@@ -6803,7 +6851,8 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
pcie_device_pg0.AccessStatus))
return 0;
- if (!(_scsih_is_nvme_device(le32_to_cpu(pcie_device_pg0.DeviceInfo))))
+ if (!(_scsih_is_nvme_pciescsi_device(le32_to_cpu
+ (pcie_device_pg0.DeviceInfo))))
return 0;
pcie_device = mpt3sas_get_pdev_by_wwid(ioc, wwid);
@@ -6813,6 +6862,31 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
return 0;
}
+ /* PCIe Device Page 2 contains read-only information about a
+ * specific NVMe device; therefore, this page is only
+ * valid for NVMe devices and skip for pcie devices of type scsi.
+ */
+ if (!(mpt3sas_scsih_is_pcie_scsi_device(
+ le32_to_cpu(pcie_device_pg0.DeviceInfo)))) {
+ if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply,
+ &pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+ handle)) {
+ ioc_err(ioc,
+ "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ return 0;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ ioc_err(ioc,
+ "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ return 0;
+ }
+ }
+
pcie_device = kzalloc(sizeof(struct _pcie_device), GFP_KERNEL);
if (!pcie_device) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -6824,6 +6898,7 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
pcie_device->id = ioc->pcie_target_id++;
pcie_device->channel = PCIE_CHANNEL;
pcie_device->handle = handle;
+ pcie_device->access_status = pcie_device_pg0.AccessStatus;
pcie_device->device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
pcie_device->wwid = wwid;
pcie_device->port_num = pcie_device_pg0.PortNum;
@@ -6855,27 +6930,16 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID);
}
/* TODO -- Add device name once FW supports it */
- if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply,
- &pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)) {
- ioc_err(ioc, "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- kfree(pcie_device);
- return 0;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- ioc_err(ioc, "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- kfree(pcie_device);
- return 0;
- }
- pcie_device->nvme_mdts =
- le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize);
- if (pcie_device_pg2.ControllerResetTO)
- pcie_device->reset_timeout =
- pcie_device_pg2.ControllerResetTO;
- else
+ if (!(mpt3sas_scsih_is_pcie_scsi_device(
+ le32_to_cpu(pcie_device_pg0.DeviceInfo)))) {
+ pcie_device->nvme_mdts =
+ le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize);
+ if (pcie_device_pg2.ControllerResetTO)
+ pcie_device->reset_timeout =
+ pcie_device_pg2.ControllerResetTO;
+ else
+ pcie_device->reset_timeout = 30;
+ } else
pcie_device->reset_timeout = 30;
if (ioc->wait_for_discovery_to_complete)
@@ -8507,6 +8571,8 @@ _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc,
if ((pcie_device->wwid == le64_to_cpu(pcie_device_pg0->WWID))
&& (pcie_device->slot == le16_to_cpu(
pcie_device_pg0->Slot))) {
+ pcie_device->access_status =
+ pcie_device_pg0->AccessStatus;
pcie_device->responding = 1;
starget = pcie_device->starget;
if (starget && starget->hostdata) {
@@ -8594,7 +8660,7 @@ _scsih_search_responding_pcie_devices(struct MPT3SAS_ADAPTER *ioc)
}
handle = le16_to_cpu(pcie_device_pg0.DevHandle);
device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
- if (!(_scsih_is_nvme_device(device_info)))
+ if (!(_scsih_is_nvme_pciescsi_device(device_info)))
continue;
_scsih_mark_responding_pcie_device(ioc, &pcie_device_pg0);
}
@@ -9175,7 +9241,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
break;
}
handle = le16_to_cpu(pcie_device_pg0.DevHandle);
- if (!(_scsih_is_nvme_device(
+ if (!(_scsih_is_nvme_pciescsi_device(
le32_to_cpu(pcie_device_pg0.DeviceInfo))))
continue;
pcie_device = mpt3sas_get_pdev_by_wwid(ioc,
@@ -9308,7 +9374,10 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
_scsih_sas_topology_change_event(ioc, fw_event);
break;
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
- _scsih_sas_device_status_change_event(ioc, fw_event);
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ _scsih_sas_device_status_change_event_debug(ioc,
+ (Mpi2EventDataSasDeviceStatusChange_t *)
+ fw_event->event_data);
break;
case MPI2_EVENT_SAS_DISCOVERY:
_scsih_sas_discovery_event(ioc, fw_event);
@@ -9481,6 +9550,10 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
break;
}
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ _scsih_sas_device_status_change_event(ioc,
+ (Mpi2EventDataSasDeviceStatusChange_t *)
+ mpi_reply->EventData);
+ break;
case MPI2_EVENT_IR_OPERATION_STATUS:
case MPI2_EVENT_SAS_DISCOVERY:
case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
@@ -10039,6 +10112,12 @@ _scsih_probe_pcie(struct MPT3SAS_ADAPTER *ioc)
pcie_device_put(pcie_device);
continue;
}
+ if (pcie_device->access_status ==
+ MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED) {
+ pcie_device_make_active(ioc, pcie_device);
+ pcie_device_put(pcie_device);
+ continue;
+ }
rc = scsi_add_device(ioc->shost, PCIE_CHANNEL,
pcie_device->id, 0);
if (rc) {
@@ -10453,6 +10532,13 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
ioc->logging_level = logging_level;
ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
+ /*
+ * Enable MEMORY MOVE support flag.
+ */
+ ioc->drv_support_bitmap |= MPT_DRV_SUPPORT_BITMAP_MEMMOVE;
+
+ ioc->enable_sdev_max_qd = enable_sdev_max_qd;
+
/* misc semaphores and spin locks */
mutex_init(&ioc->reset_in_progress_mutex);
/* initializing pci_access_mutex lock */