From 9134211f7bed218bc01940fc24ebe8b4bc02b69b Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Fri, 4 Aug 2023 16:12:43 +0530 Subject: scsi: mpi3mr: Invoke soft reset upon TSU or event ack time out When a timestamp update or an event acknowledgment command times out, the driver invokes the soft reset handler to recover the controller while holding a mutex lock. The soft reset handler also tries to acquire the same mutex to send initialization commands to the controller which leads to a deadlock scenario. To resolve the issue the driver will check thestatus and if this indicates the controller is operational, the driver will issue a diagnostic fault reset and exit out of the command processing function. If the controller is already faulted or asynchronously reset, then the driver will just exit the command processing function. Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20230804104248.118924-2-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 5fa07d6ee5b8..11b78d4a87a0 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -2343,8 +2343,8 @@ static int mpi3mr_sync_timestamp(struct mpi3mr_ioc *mrioc) ioc_err(mrioc, "Issue IOUCTL time_stamp: command timed out\n"); mrioc->init_cmds.is_waiting = 0; if (!(mrioc->init_cmds.state & MPI3MR_CMD_RESET)) - mpi3mr_soft_reset_handler(mrioc, - MPI3MR_RESET_FROM_TSU_TIMEOUT, 1); + mpi3mr_check_rh_fault_ioc(mrioc, + MPI3MR_RESET_FROM_TSU_TIMEOUT); retval = -1; goto out_unlock; } @@ -3359,8 +3359,8 @@ int mpi3mr_process_event_ack(struct mpi3mr_ioc *mrioc, u8 event, if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { ioc_err(mrioc, "Issue EvtNotify: command timed out\n"); if (!(mrioc->init_cmds.state & MPI3MR_CMD_RESET)) - mpi3mr_soft_reset_handler(mrioc, - MPI3MR_RESET_FROM_EVTACK_TIMEOUT, 1); + mpi3mr_check_rh_fault_ioc(mrioc, + MPI3MR_RESET_FROM_EVTACK_TIMEOUT); retval = -1; goto out_unlock; } -- cgit From 6f81b1cfdf33533925dbbfab9923f67fb4a31858 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Fri, 4 Aug 2023 16:12:44 +0530 Subject: scsi: mpi3mr: Update MPI Headers to version 3.00.28 Updated MPI Headers to version 3.00.28. Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20230804104248.118924-3-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 2 +- drivers/scsi/mpi3mr/mpi/mpi30_ioc.h | 1 + drivers/scsi/mpi3mr/mpi/mpi30_transport.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index 2fc196499c89..35f81af40f51 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -1482,7 +1482,7 @@ struct mpi3_security_page0 { #define MPI3_SECURITY1_KEY_RECORD_MAX 1 #endif #ifndef MPI3_SECURITY1_PAD_MAX -#define MPI3_SECURITY1_PAD_MAX 1 +#define MPI3_SECURITY1_PAD_MAX 4 #endif union mpi3_security1_key_data { __le32 dword[128]; diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h index f5e9c2309ce6..1e4a60fc655f 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h @@ -600,6 +600,7 @@ struct mpi3_event_data_pcie_error_threshold { __le16 threshold_count; __le16 attached_dev_handle; __le16 reserved12; + __le32 reserved14; }; #define MPI3_EVENT_PCI_ERROR_RC_THRESHOLD_EXCEEDED (0x00) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h index 441cfc2c7f09..1e0a3dcaf723 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h @@ -18,7 +18,7 @@ union mpi3_version_union { #define MPI3_VERSION_MAJOR (3) #define MPI3_VERSION_MINOR (0) -#define MPI3_VERSION_UNIT (27) +#define MPI3_VERSION_UNIT (28) #define MPI3_VERSION_DEV (0) #define MPI3_DEVHANDLE_INVALID (0xffff) struct mpi3_sysif_oper_queue_indexes { -- cgit From d9adb81e67e9be51990a14389cd1762086b44985 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Fri, 4 Aug 2023 16:12:45 +0530 Subject: scsi: mpi3mr: Add support for more than 1MB I/O Enhance the driver to get the maximum data length per I/O request from IOC Facts data and report that to the upper layers. If the IOC facts data is not reported then a default I/O size of 1MB is reported to the OS. Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20230804104248.118924-4-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr.h | 8 ++++++-- drivers/scsi/mpi3mr/mpi3mr_fw.c | 29 ++++++++++++++++++++++++----- drivers/scsi/mpi3mr/mpi3mr_os.c | 24 ++++++++++++++++++++---- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 0afb687402e1..fd3619775739 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -66,11 +66,12 @@ extern atomic64_t event_counter; #define MPI3MR_NAME_LENGTH 32 #define IOCNAME "%s: " -#define MPI3MR_MAX_SECTORS 2048 +#define MPI3MR_DEFAULT_MAX_IO_SIZE (1 * 1024 * 1024) /* Definitions for internal SGL and Chain SGL buffers */ #define MPI3MR_PAGE_SIZE_4K 4096 -#define MPI3MR_SG_DEPTH (MPI3MR_PAGE_SIZE_4K / sizeof(struct mpi3_sge_common)) +#define MPI3MR_DEFAULT_SGL_ENTRIES 256 +#define MPI3MR_MAX_SGL_ENTRIES 2048 /* Definitions for MAX values for shost */ #define MPI3MR_MAX_CMDS_LUN 128 @@ -323,6 +324,7 @@ struct mpi3mr_ioc_facts { u16 max_perids; u16 max_pds; u16 max_sasexpanders; + u32 max_data_length; u16 max_sasinitiators; u16 max_enclosures; u16 max_pcie_switches; @@ -959,6 +961,7 @@ struct scmd_priv { * @stop_drv_processing: Stop all command processing * @device_refresh_on: Don't process the events until devices are refreshed * @max_host_ios: Maximum host I/O count + * @max_sgl_entries: Max SGL entries per I/O * @chain_buf_count: Chain buffer count * @chain_buf_pool: Chain buffer pool * @chain_sgl_list: Chain SGL list @@ -1129,6 +1132,7 @@ struct mpi3mr_ioc { u16 max_host_ios; spinlock_t tgtdev_lock; struct list_head tgtdev_list; + u16 max_sgl_entries; u32 chain_buf_count; struct dma_pool *chain_buf_pool; diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 11b78d4a87a0..f039f1d98647 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -1163,6 +1163,12 @@ mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) return -EPERM; } + if (mrioc->shost->max_sectors != (mrioc->facts.max_data_length / 512)) + ioc_err(mrioc, "Warning: The maximum data transfer length\n" + "\tchanged after reset: previous(%d), new(%d),\n" + "the driver cannot change this at run time\n", + mrioc->shost->max_sectors * 512, mrioc->facts.max_data_length); + if ((mrioc->sas_transport_enabled) && (mrioc->facts.ioc_capabilities & MPI3_IOCFACTS_CAPABILITY_MULTIPATH_ENABLED)) ioc_err(mrioc, @@ -2856,6 +2862,7 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, le16_to_cpu(facts_data->max_pcie_switches); mrioc->facts.max_sasexpanders = le16_to_cpu(facts_data->max_sas_expanders); + mrioc->facts.max_data_length = le16_to_cpu(facts_data->max_data_length); mrioc->facts.max_sasinitiators = le16_to_cpu(facts_data->max_sas_initiators); mrioc->facts.max_enclosures = le16_to_cpu(facts_data->max_enclosures); @@ -2893,13 +2900,18 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, mrioc->facts.io_throttle_high = le16_to_cpu(facts_data->io_throttle_high); + if (mrioc->facts.max_data_length == + MPI3_IOCFACTS_MAX_DATA_LENGTH_NOT_REPORTED) + mrioc->facts.max_data_length = MPI3MR_DEFAULT_MAX_IO_SIZE; + else + mrioc->facts.max_data_length *= MPI3MR_PAGE_SIZE_4K; /* Store in 512b block count */ if (mrioc->facts.io_throttle_data_length) mrioc->io_throttle_data_length = (mrioc->facts.io_throttle_data_length * 2 * 4); else /* set the length to 1MB + 1K to disable throttle */ - mrioc->io_throttle_data_length = MPI3MR_MAX_SECTORS + 2; + mrioc->io_throttle_data_length = (mrioc->facts.max_data_length / 512) + 2; mrioc->io_throttle_high = (mrioc->facts.io_throttle_high * 2 * 1024); mrioc->io_throttle_low = (mrioc->facts.io_throttle_low * 2 * 1024); @@ -2914,9 +2926,9 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, ioc_info(mrioc, "SGEModMask 0x%x SGEModVal 0x%x SGEModShift 0x%x ", mrioc->facts.sge_mod_mask, mrioc->facts.sge_mod_value, mrioc->facts.sge_mod_shift); - ioc_info(mrioc, "DMA mask %d InitialPE status 0x%x\n", + ioc_info(mrioc, "DMA mask %d InitialPE status 0x%x max_data_len (%d)\n", mrioc->facts.dma_mask, (facts_flags & - MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK)); + MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK), mrioc->facts.max_data_length); ioc_info(mrioc, "max_dev_per_throttle_group(%d), max_throttle_groups(%d)\n", mrioc->facts.max_dev_per_tg, mrioc->facts.max_io_throttle_group); @@ -3414,7 +3426,14 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_ioc *mrioc) if (!mrioc->chain_sgl_list) goto out_failed; - sz = MPI3MR_PAGE_SIZE_4K; + if (mrioc->max_sgl_entries > (mrioc->facts.max_data_length / + MPI3MR_PAGE_SIZE_4K)) + mrioc->max_sgl_entries = mrioc->facts.max_data_length / + MPI3MR_PAGE_SIZE_4K; + sz = mrioc->max_sgl_entries * sizeof(struct mpi3_sge_common); + ioc_info(mrioc, "number of sgl entries=%d chain buffer size=%dKB\n", + mrioc->max_sgl_entries, sz/1024); + mrioc->chain_buf_pool = dma_pool_create("chain_buf pool", &mrioc->pdev->dev, sz, 16, 0); if (!mrioc->chain_buf_pool) { @@ -3813,7 +3832,7 @@ retry_init: } mrioc->max_host_ios = mrioc->facts.max_reqs - MPI3MR_INTERNAL_CMDS_RESVD; - + mrioc->shost->max_sectors = mrioc->facts.max_data_length / 512; mrioc->num_io_throttle_group = mrioc->facts.max_io_throttle_group; atomic_set(&mrioc->pend_large_data_sz, 0); diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index d627355303d7..b19b624d0e97 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -33,6 +33,12 @@ static int logging_level; module_param(logging_level, int, 0); MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info (default=0)"); +static int max_sgl_entries = MPI3MR_DEFAULT_SGL_ENTRIES; +module_param(max_sgl_entries, int, 0444); +MODULE_PARM_DESC(max_sgl_entries, + "Preferred max number of SG entries to be used for a single I/O\n" + "The actual value will be determined by the driver\n" + "(Minimum=256, Maximum=2048, default=256)"); /* Forward declarations*/ static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, @@ -3413,7 +3419,7 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, scsi_bufflen(scmd)); return -ENOMEM; } - if (sges_left > MPI3MR_SG_DEPTH) { + if (sges_left > mrioc->max_sgl_entries) { sdev_printk(KERN_ERR, scmd->device, "scsi_dma_map returned unsupported sge count %d!\n", sges_left); @@ -4818,10 +4824,10 @@ static const struct scsi_host_template mpi3mr_driver_template = { .no_write_same = 1, .can_queue = 1, .this_id = -1, - .sg_tablesize = MPI3MR_SG_DEPTH, + .sg_tablesize = MPI3MR_DEFAULT_SGL_ENTRIES, /* max xfer supported is 1M (2K in 512 byte sized sectors) */ - .max_sectors = 2048, + .max_sectors = (MPI3MR_DEFAULT_MAX_IO_SIZE / 512), .cmd_per_lun = MPI3MR_MAX_CMDS_LUN, .max_segment_size = 0xffffffff, .track_queue_depth = 1, @@ -5004,6 +5010,16 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) mrioc->pdev = pdev; mrioc->stop_bsgs = 1; + mrioc->max_sgl_entries = max_sgl_entries; + if (max_sgl_entries > MPI3MR_MAX_SGL_ENTRIES) + mrioc->max_sgl_entries = MPI3MR_MAX_SGL_ENTRIES; + else if (max_sgl_entries < MPI3MR_DEFAULT_SGL_ENTRIES) + mrioc->max_sgl_entries = MPI3MR_DEFAULT_SGL_ENTRIES; + else { + mrioc->max_sgl_entries /= MPI3MR_DEFAULT_SGL_ENTRIES; + mrioc->max_sgl_entries *= MPI3MR_DEFAULT_SGL_ENTRIES; + } + /* init shost parameters */ shost->max_cmd_len = MPI3MR_MAX_CDB_LENGTH; shost->max_lun = -1; @@ -5068,7 +5084,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) shost->nr_maps = 3; shost->can_queue = mrioc->max_host_ios; - shost->sg_tablesize = MPI3MR_SG_DEPTH; + shost->sg_tablesize = mrioc->max_sgl_entries; shost->max_id = mrioc->facts.max_perids + 1; retval = scsi_add_host(shost, &pdev->dev); -- cgit From e7a8648e1ce2ddbc74ac69da83dcebbee0c7e1b8 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Fri, 4 Aug 2023 16:12:46 +0530 Subject: scsi: mpi3mr: WRITE SAME implementation Enhance driver to divert the WRITE SAME commands that are issued with UNMAP=1 and NDOB=1 and with the transfer length greater than the max WRITE SAME length specified by the firmware for the particular drive to the controller firmware. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202307280034.DXU5pTVV-lkp@intel.com/ Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20230804104248.118924-5-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr.h | 11 ++++ drivers/scsi/mpi3mr/mpi3mr_os.c | 118 ++++++++++++++++++++++++++++++++-------- 2 files changed, 105 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index fd3619775739..8b009ba26d88 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -207,6 +207,9 @@ extern atomic64_t event_counter; */ #define MPI3MR_MAX_APP_XFER_SECTORS (2048 + 512) +#define MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS 256 +#define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048 + /** * struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe * Encapsulated commands. @@ -678,6 +681,7 @@ enum mpi3mr_dev_state { * @io_unit_port: IO Unit port ID * @non_stl: Is this device not to be attached with SAS TL * @io_throttle_enabled: I/O throttling needed or not + * @wslen: Write same max length * @q_depth: Device specific Queue Depth * @wwid: World wide ID * @enclosure_logical_id: Enclosure logical identifier @@ -700,6 +704,7 @@ struct mpi3mr_tgt_dev { u8 io_unit_port; u8 non_stl; u8 io_throttle_enabled; + u16 wslen; u16 q_depth; u64 wwid; u64 enclosure_logical_id; @@ -753,6 +758,8 @@ static inline void mpi3mr_tgtdev_put(struct mpi3mr_tgt_dev *s) * @dev_removed: Device removed in the Firmware * @dev_removedelay: Device is waiting to be removed in FW * @dev_type: Device type + * @dev_nvme_dif: Device is NVMe DIF enabled + * @wslen: Write same max length * @io_throttle_enabled: I/O throttling needed or not * @io_divert: Flag indicates io divert is on or off for the dev * @throttle_group: Pointer to throttle group info @@ -769,6 +776,8 @@ struct mpi3mr_stgt_priv_data { u8 dev_removed; u8 dev_removedelay; u8 dev_type; + u8 dev_nvme_dif; + u16 wslen; u8 io_throttle_enabled; u8 io_divert; struct mpi3mr_throttle_group_info *throttle_group; @@ -784,12 +793,14 @@ struct mpi3mr_stgt_priv_data { * @ncq_prio_enable: NCQ priority enable for SATA device * @pend_count: Counter to track pending I/Os during error * handling + * @wslen: Write same max length */ struct mpi3mr_sdev_priv_data { struct mpi3mr_stgt_priv_data *tgt_priv_data; u32 lun_id; u8 ncq_prio_enable; u32 pend_count; + u16 wslen; }; /** diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index b19b624d0e97..fcf0888232e7 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -430,6 +430,7 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc) tgt_priv->io_throttle_enabled = 0; tgt_priv->io_divert = 0; tgt_priv->throttle_group = NULL; + tgt_priv->wslen = 0; if (tgtdev->host_exposed) atomic_set(&tgt_priv->block_io, 1); } @@ -1108,6 +1109,18 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, tgtdev->io_throttle_enabled = (flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0; + switch (flags & MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_MASK) { + case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_256_LB: + tgtdev->wslen = MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS; + break; + case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_2048_LB: + tgtdev->wslen = MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS; + break; + case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_NO_LIMIT: + default: + tgtdev->wslen = 0; + break; + } if (tgtdev->starget && tgtdev->starget->hostdata) { scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *) @@ -1119,6 +1132,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, tgtdev->io_throttle_enabled; if (is_added == true) atomic_set(&scsi_tgt_priv_data->block_io, 0); + scsi_tgt_priv_data->wslen = tgtdev->wslen; } switch (dev_pg0->access_status) { @@ -3939,6 +3953,48 @@ void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout) mpi3mr_get_fw_pending_ios(mrioc)); } +/** + * mpi3mr_setup_divert_ws - Setup Divert IO flag for write same + * @mrioc: Adapter instance reference + * @scmd: SCSI command reference + * @scsiio_req: MPI3 SCSI IO request + * @scsiio_flags: Pointer to MPI3 SCSI IO Flags + * @wslen: write same max length + * + * Gets values of unmap, ndob and number of blocks from write + * same scsi io and based on these values it sets divert IO flag + * and reason for diverting IO to firmware. + * + * Return: Nothing + */ +static inline void mpi3mr_setup_divert_ws(struct mpi3mr_ioc *mrioc, + struct scsi_cmnd *scmd, struct mpi3_scsi_io_request *scsiio_req, + u32 *scsiio_flags, u16 wslen) +{ + u8 unmap = 0, ndob = 0; + u8 opcode = scmd->cmnd[0]; + u32 num_blocks = 0; + u16 sa = (scmd->cmnd[8] << 8) | (scmd->cmnd[9]); + + if (opcode == WRITE_SAME_16) { + unmap = scmd->cmnd[1] & 0x08; + ndob = scmd->cmnd[1] & 0x01; + num_blocks = get_unaligned_be32(scmd->cmnd + 10); + } else if ((opcode == VARIABLE_LENGTH_CMD) && (sa == WRITE_SAME_32)) { + unmap = scmd->cmnd[10] & 0x08; + ndob = scmd->cmnd[10] & 0x01; + num_blocks = get_unaligned_be32(scmd->cmnd + 28); + } else + return; + + if ((unmap) && (ndob) && (num_blocks > wslen)) { + scsiio_req->msg_flags |= + MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE; + *scsiio_flags |= + MPI3_SCSIIO_FLAGS_DIVERT_REASON_WRITE_SAME_TOO_LARGE; + } +} + /** * mpi3mr_eh_host_reset - Host reset error handling callback * @scmd: SCSI command reference @@ -4436,7 +4492,6 @@ static int mpi3mr_target_alloc(struct scsi_target *starget) unsigned long flags; int retval = 0; struct sas_rphy *rphy = NULL; - bool update_stgt_priv_data = false; scsi_tgt_priv_data = kzalloc(sizeof(*scsi_tgt_priv_data), GFP_KERNEL); if (!scsi_tgt_priv_data) @@ -4445,39 +4500,50 @@ static int mpi3mr_target_alloc(struct scsi_target *starget) starget->hostdata = scsi_tgt_priv_data; spin_lock_irqsave(&mrioc->tgtdev_lock, flags); - if (starget->channel == mrioc->scsi_device_channel) { tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); - if (tgt_dev && !tgt_dev->is_hidden) - update_stgt_priv_data = true; - else + if (tgt_dev && !tgt_dev->is_hidden) { + scsi_tgt_priv_data->starget = starget; + scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle; + scsi_tgt_priv_data->perst_id = tgt_dev->perst_id; + scsi_tgt_priv_data->dev_type = tgt_dev->dev_type; + scsi_tgt_priv_data->tgt_dev = tgt_dev; + tgt_dev->starget = starget; + atomic_set(&scsi_tgt_priv_data->block_io, 0); + retval = 0; + if ((tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_PCIE) && + ((tgt_dev->dev_spec.pcie_inf.dev_info & + MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) == + MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) && + ((tgt_dev->dev_spec.pcie_inf.dev_info & + MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_MASK) != + MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_0)) + scsi_tgt_priv_data->dev_nvme_dif = 1; + scsi_tgt_priv_data->io_throttle_enabled = tgt_dev->io_throttle_enabled; + scsi_tgt_priv_data->wslen = tgt_dev->wslen; + if (tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_VD) + scsi_tgt_priv_data->throttle_group = tgt_dev->dev_spec.vd_inf.tg; + } else retval = -ENXIO; } else if (mrioc->sas_transport_enabled && !starget->channel) { rphy = dev_to_rphy(starget->dev.parent); tgt_dev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, rphy->identify.sas_address, rphy); if (tgt_dev && !tgt_dev->is_hidden && !tgt_dev->non_stl && - (tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA)) - update_stgt_priv_data = true; - else + (tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA)) { + scsi_tgt_priv_data->starget = starget; + scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle; + scsi_tgt_priv_data->perst_id = tgt_dev->perst_id; + scsi_tgt_priv_data->dev_type = tgt_dev->dev_type; + scsi_tgt_priv_data->tgt_dev = tgt_dev; + scsi_tgt_priv_data->io_throttle_enabled = tgt_dev->io_throttle_enabled; + scsi_tgt_priv_data->wslen = tgt_dev->wslen; + tgt_dev->starget = starget; + atomic_set(&scsi_tgt_priv_data->block_io, 0); + retval = 0; + } else retval = -ENXIO; } - - if (update_stgt_priv_data) { - scsi_tgt_priv_data->starget = starget; - scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle; - scsi_tgt_priv_data->perst_id = tgt_dev->perst_id; - scsi_tgt_priv_data->dev_type = tgt_dev->dev_type; - scsi_tgt_priv_data->tgt_dev = tgt_dev; - tgt_dev->starget = starget; - atomic_set(&scsi_tgt_priv_data->block_io, 0); - retval = 0; - scsi_tgt_priv_data->io_throttle_enabled = - tgt_dev->io_throttle_enabled; - if (tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_VD) - scsi_tgt_priv_data->throttle_group = - tgt_dev->dev_spec.vd_inf.tg; - } spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); return retval; @@ -4738,6 +4804,10 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost, mpi3mr_setup_eedp(mrioc, scmd, scsiio_req); + if (stgt_priv_data->wslen) + mpi3mr_setup_divert_ws(mrioc, scmd, scsiio_req, &scsiio_flags, + stgt_priv_data->wslen); + memcpy(scsiio_req->cdb.cdb32, scmd->cmnd, scmd->cmd_len); scsiio_req->data_length = cpu_to_le32(scsi_bufflen(scmd)); scsiio_req->dev_handle = cpu_to_le16(dev_handle); -- cgit From d9a5ab0ea98fdee77fcbfec27bb3976de9615377 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Fri, 4 Aug 2023 16:12:47 +0530 Subject: scsi: mpi3mr: Enhance handling of devices removed after controller reset Mark all of the devices that are exposed to the OS prior to a controller reset and not detected by the controller after the reset as removed devices and the I/Os to those devices are unblocked (and returned with DID_NO_CONNECT) prior to removing the devices one after the other. Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20230804104248.118924-6-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_os.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index fcf0888232e7..89ba015c5d7e 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -1041,6 +1041,19 @@ mpi3mr_update_sdev(struct scsi_device *sdev, void *data) void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc) { struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; + struct mpi3mr_stgt_priv_data *tgt_priv; + + dprint_reset(mrioc, "refresh target devices: check for removals\n"); + list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, + list) { + if ((tgtdev->dev_handle == MPI3MR_INVALID_DEV_HANDLE) && + tgtdev->host_exposed && tgtdev->starget && + tgtdev->starget->hostdata) { + tgt_priv = tgtdev->starget->hostdata; + tgt_priv->dev_removed = 1; + atomic_set(&tgt_priv->block_io, 0); + } + } list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, list) { -- cgit From 9a9068b2afa0b0bf559b66b374785d2fcb5b9b5e Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Fri, 4 Aug 2023 16:12:48 +0530 Subject: scsi: mpi3mr: Update driver version to 8.5.0.0.0 Update driver version to 8.5.0.0.0 Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20230804104248.118924-7-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 8b009ba26d88..ae98d15c30b1 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -55,8 +55,8 @@ extern struct list_head mrioc_list; extern int prot_mask; extern atomic64_t event_counter; -#define MPI3MR_DRIVER_VERSION "8.4.1.0.0" -#define MPI3MR_DRIVER_RELDATE "16-March-2023" +#define MPI3MR_DRIVER_VERSION "8.5.0.0.0" +#define MPI3MR_DRIVER_RELDATE "24-July-2023" #define MPI3MR_DRIVER_NAME "mpi3mr" #define MPI3MR_DRIVER_LICENSE "GPL" -- cgit