[PATCH] scsi: 3ware: use pci_iounmap instead of iounmap
'base_addr' has been mapped using 'pci_iomap()'. It should be freed with the corresponding 'pci_iounmap()' instead of 'iomap()'. Signed-off-by: Christophe JAILLET --- drivers/scsi/3w-sas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index cf9f2a09b47d..231b04dd9076 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1692,7 +1692,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) pci_disable_msi(pdev); scsi_remove_host(host); out_iounmap: - iounmap(tw_dev->base_addr); + pci_iounmap(pdev, tw_dev->base_addr); out_release_mem_region: pci_release_regions(pdev); out_free_device_extension: @@ -1738,7 +1738,7 @@ static void twl_remove(struct pci_dev *pdev) pci_disable_msi(pdev); /* Free IO remapping */ - iounmap(tw_dev->base_addr); + pci_iounmap(pdev, tw_dev->base_addr); /* Free up the mem region */ pci_release_regions(pdev); -- 2.14.1
[PATCH 0/3] scsi: aacraid: Multi controller Kdump IOP reset handling
During Kdump aacraid controller IOP reset is invoked, IOP reset takes approx 40 seconds to bring the controller back up and running. with timeout of 120 seconds and anything more than 2 controllers will cause kdump to timeout. This patchset implements a new reset mechanism called DropIO, that induces the fw to drop any pending IO in the fw and making the reset process quicker. Raghava Aditya Renukunta (3): scsi: aacraid: Implement DropIO sync command scsi: aacraid: Preserve MSIX mode in the OMR register scsi: aacraid: Auto detect INTx or MSIx mode during sync cmd processing drivers/scsi/aacraid/aacraid.h | 5 + drivers/scsi/aacraid/src.c | 211 ++--- 2 files changed, 202 insertions(+), 14 deletions(-) -- 2.9.4
[PATCH 1/3] scsi: aacraid: Implement DropIO sync command
IOP_RESET takes longer time to complete, if controller is in a state where we can bring it back with init struct, controller DropIO sync command is implemented. - If controller is faulted perform standard IOP_RESET in aac_srcv_init. - If controller is not faulted get adapter properties and extended properties. - Update the sa_firmware variable and determine if DropIO request is supported. - Issue DropIO request, and get the number of outstanding commands. - If all commands are complete with success (CT_OK), consider IOP_RESET is complete. - If any commands timeout, Perform the IOP_RESET. Signed-off-by: Prasad B Munirathnam Signed-off-by: Raghava Aditya Renukunta --- drivers/scsi/aacraid/aacraid.h | 4 + drivers/scsi/aacraid/src.c | 167 +++-- 2 files changed, 163 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 3e8bfcf..784783b 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1528,6 +1528,7 @@ struct aac_bus_info_response { #define AAC_COMM_MESSAGE_TYPE3 5 #define AAC_EXTOPT_SA_FIRMWARE cpu_to_le32(1<<1) +#define AAC_EXTOPT_SOFT_RESET cpu_to_le32(1<<16) /* MSIX context */ struct aac_msix_ctx { @@ -1662,6 +1663,7 @@ struct aac_dev u8 raw_io_64; u8 printf_enabled; u8 in_reset; + u8 in_soft_reset; u8 msi; u8 sa_firmware; int management_fib_count; @@ -2502,6 +2504,7 @@ struct aac_hba_info { #define RCV_TEMP_READINGS 0x0025 #define GET_COMM_PREFERRED_SETTINGS0x0026 #define IOP_RESET_FW_FIB_DUMP 0x0034 +#define DROP_IO0x0035 #define IOP_RESET 0x1000 #define IOP_RESET_ALWAYS 0x1001 #define RE_INIT_ADAPTER0x00ee @@ -2537,6 +2540,7 @@ struct aac_hba_info { #defineFLASH_UPD_PENDING 0x2000 #defineFLASH_UPD_SUCCESS 0x4000 #defineFLASH_UPD_FAILED0x8000 +#defineINVALID_OMR 0x #defineFWUPD_TIMEOUT (5 * 60) /* diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 0c9361c..df98f37 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -255,7 +255,8 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, */ src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); - if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) { + if ((!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) && + !dev->in_soft_reset) { ok = 0; start = jiffies; @@ -988,6 +989,148 @@ int aac_src_init(struct aac_dev *dev) return -1; } +static int aac_src_wait_sync(struct aac_dev *dev, int *status) +{ + unsigned long start = jiffies; + unsigned long usecs = 0; + int delay = 5 * HZ; + int rc = 1; + + while (time_before(jiffies, start+delay)) { + /* +* Delay 5 microseconds to let Mon960 get info. +*/ + udelay(5); + + /* +* Mon960 will set doorbell0 bit when it has completed the +* command. +*/ + if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) { + /* +* Clear: the doorbell. +*/ + if (dev->msi_enabled) + aac_src_access_devreg(dev, AAC_CLEAR_SYNC_BIT); + else + src_writel(dev, MUnit.ODR_C, + OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); + rc = 0; + + break; + } + + /* +* Yield the processor in case we are slow +*/ + usecs = 1 * USEC_PER_MSEC; + usleep_range(usecs, usecs + 50); + } + /* +* Pull the synch status from Mailbox 0. +*/ + if (status && !rc) { + status[0] = readl(&dev->IndexRegs->Mailbox[0]); + status[1] = readl(&dev->IndexRegs->Mailbox[1]); + status[2] = readl(&dev->IndexRegs->Mailbox[2]); + status[3] = readl(&dev->IndexRegs->Mailbox[3]); + status[4] = readl(&dev->IndexRegs->Mailbox[4]); + } + + return rc; +} + +/** + * aac_src_soft_reset - perform soft reset to speed up + * access + * + * Assumptions: That the controller is in a state where we can + * bring it back to life with an init struct. We can only use + * fast
[PATCH 2/3] scsi: aacraid: Preserve MSIX mode in the OMR register
Preserve the current MSIX mode value in the OMR before rewriting the OMR to initiate the IOP or Soft Reset. Signed-off-by: Prasad B Munirathnam Signed-off-by: Raghava Aditya Renukunta --- drivers/scsi/aacraid/src.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index df98f37..b05c3cf 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -680,6 +680,25 @@ void aac_set_intx_mode(struct aac_dev *dev) } } +static void aac_clear_omr(struct aac_dev *dev) +{ + u32 omr_value = 0; + + omr_value = src_readl(dev, MUnit.OMR); + + /* +* Check for PCI Errors or Kernel Panic +*/ + if ((omr_value == INVALID_OMR) || (omr_value & KERNEL_PANIC)) + omr_value = 0; + + /* +* Preserve MSIX Value if any +*/ + src_writel(dev, MUnit.OMR, omr_value & AAC_INT_MODE_MSIX); + src_readl(dev, MUnit.OMR); +} + static void aac_dump_fw_fib_iop_reset(struct aac_dev *dev) { __le32 supported_options3; @@ -740,6 +759,8 @@ static void aac_send_iop_reset(struct aac_dev *dev) aac_set_intx_mode(dev); + aac_clear_omr(dev); + src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK); msleep(5000); @@ -749,6 +770,7 @@ static void aac_send_hardware_soft_reset(struct aac_dev *dev) { u_int32_t val; + aac_clear_omr(dev); val = readl(((char *)(dev->base) + IBW_SWR_OFFSET)); val |= 0x01; writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET)); -- 2.9.4
[PATCH 3/3] scsi: aacraid: Auto detect INTx or MSIx mode during sync cmd processing
During sync command processing if legacy INTx status indicates command is not completed, sample the MSIx register and check if it indicates command completion, set controller MSIx enabled flag. Signed-off-by: Prasad B Munirathnam Signed-off-by: Raghava Aditya Renukunta --- drivers/scsi/aacraid/aacraid.h | 1 + drivers/scsi/aacraid/src.c | 22 -- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 784783b..7834d09 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1231,6 +1231,7 @@ struct src_registers { #define SRC_ODR_SHIFT 12 #define SRC_IDR_SHIFT 9 +#define SRC_MSI_READ_MASK 0x1000 typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index b05c3cf..f9600b6 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -1399,13 +1399,23 @@ void aac_src_access_devreg(struct aac_dev *dev, int mode) static int aac_src_get_sync_status(struct aac_dev *dev) { + int msix_val = 0; + int legacy_val = 0; - int val; + msix_val = src_readl(dev, MUnit.ODR_MSI) & SRC_MSI_READ_MASK ? 1 : 0; - if (dev->msi_enabled) - val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0; - else - val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT; + if (!dev->msi_enabled) { + /* +* if Legacy int status indicates cmd is not complete +* sample MSIx register to see if it indiactes cmd complete, +* if yes set the controller in MSIx mode and consider cmd +* completed +*/ + legacy_val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT; + if (!(legacy_val & 1) && msix_val) + dev->msi_enabled = 1; + return legacy_val; + } - return val; + return msix_val; } -- 2.9.4
[GIT PULL] SCSI fixes for 4.15-rc8
One fix for SAS attached SATA CD-ROMs. It turns out that the libata handling of CD devices relies on the SCSI error handler, so disable async aborts (which don't start the error handler) for these devices. The patch is available here: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-fixes The short changelog is: Hannes Reinecke (1): scsi: libsas: Disable asynchronous aborts for SATA devices And the diffstat: drivers/scsi/libsas/sas_scsi_host.c | 17 +++-- 1 file changed, 15 insertions(+), 2 deletions(-) With full diff below. James --- diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 91795eb56206..eea94aa4091c 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -486,15 +486,28 @@ static int sas_queue_reset(struct domain_device *dev, int reset_type, int sas_eh_abort_handler(struct scsi_cmnd *cmd) { - int res; + int res = TMF_RESP_FUNC_FAILED; struct sas_task *task = TO_SAS_TASK(cmd); struct Scsi_Host *host = cmd->device->host; + struct domain_device *dev = cmd_to_domain_dev(cmd); struct sas_internal *i = to_sas_internal(host->transportt); + unsigned long flags; if (!i->dft->lldd_abort_task) return FAILED; - res = i->dft->lldd_abort_task(task); + spin_lock_irqsave(host->host_lock, flags); + /* We cannot do async aborts for SATA devices */ + if (dev_is_sata(dev) && !host->host_eh_scheduled) { + spin_unlock_irqrestore(host->host_lock, flags); + return FAILED; + } + spin_unlock_irqrestore(host->host_lock, flags); + + if (task) + res = i->dft->lldd_abort_task(task); + else + SAS_DPRINTK("no task to abort\n"); if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) return SUCCESS;
[PATCH 4/5] qla2xxx: Restore ZIO threshold setting
From: Darren Trapp Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_nvme.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index a8e81fc14c44..5ee447680ddd 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -464,11 +464,6 @@ static int qla2x00_start_nvme_mq(srb_t *sp) /* Set chip new ring index. */ WRT_REG_DWORD(req->req_q_in, req->ring_index); - /* Manage unprocessed RIO/ZIO commands in response queue. */ - if (vha->flags.process_response_queue && - rsp->ring_ptr->signature != RESPONSE_PROCESSED) - qla24xx_process_response_queue(vha, rsp); - queuing_error: spin_unlock_irqrestore(&qpair->qp_lock, flags); return rval; -- 2.12.0
[PATCH 2/5] qla2xxx: Set IIDMA and fcport state before qla_nvme_register_remote()
From: Darren Trapp Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index aececf664654..e7e51ac0bb46 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5106,13 +5106,14 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) fcport->deleted = 0; fcport->logout_on_delete = 1; + qla2x00_set_fcport_state(fcport, FCS_ONLINE); + qla2x00_iidma_fcport(vha, fcport); + if (fcport->fc4f_nvme) { qla_nvme_register_remote(vha, fcport); return; } - qla2x00_set_fcport_state(fcport, FCS_ONLINE); - qla2x00_iidma_fcport(vha, fcport); qla24xx_update_fcport_fcp_prio(vha, fcport); reg_port: -- 2.12.0
[PATCH 5/5] qla2xxx: Update driver version to 10.00.00.06-k
Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 549bef9afddd..0c55d7057280 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.05-k" +#define QLA2XXX_VERSION "10.00.00.06-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 0 -- 2.12.0
[PATCH 3/5] qla2xxx: Add changes for devloss timeout in driver
From: Darren Trapp Add support for error recovery within devloss timeout, now that FC-NVMe transport support devloss timeout. Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 1 + drivers/scsi/qla2xxx/qla_init.c | 8 +++ drivers/scsi/qla2xxx/qla_isr.c| 5 +- drivers/scsi/qla2xxx/qla_nvme.c | 142 +- drivers/scsi/qla2xxx/qla_nvme.h | 6 +- drivers/scsi/qla2xxx/qla_target.c | 13 ++-- drivers/scsi/qla2xxx/qla_target.h | 2 +- 7 files changed, 87 insertions(+), 90 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index be7d6824581a..56f78dce4d3c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2355,6 +2355,7 @@ typedef struct fc_port { #define NVME_PRLI_SP_DISCOVERY BIT_3 uint8_t nvme_flag; #define NVME_FLAG_REGISTERED 4 +#define NVME_FLAG_DELETING 2 struct fc_port *conflict; unsigned char logout_completed; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e7e51ac0bb46..5b6f3c53fdcf 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5516,6 +5516,14 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) break; } + if (fcport->fc4f_nvme) { + if (fcport->disc_state == DSC_DELETE_PEND) { + fcport->disc_state = DSC_GNL; + vha->fcport_count--; + fcport->login_succ = 0; + } + } + if (found) { spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); continue; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 14109d86c3f6..d1e7fd905f16 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1908,7 +1908,7 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } else { switch (le16_to_cpu(sts->comp_status)) { case CS_COMPLETE: - ret = 0; + ret = QLA_SUCCESS; break; case CS_ABORTED: @@ -1920,7 +1920,8 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) "NVME-%s ERR Handling - hdl=%x completion status(%x) resid=%x ox_id=%x\n", sp->name, sp->handle, sts->comp_status, le32_to_cpu(sts->residual_len), sts->ox_id); - fd->transferred_length = fd->payload_length; + fd->transferred_length = 0; + iocb->u.nvme.rsp_pyld_len = 0; ret = QLA_ABORTED; break; diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 162a523b985e..a8e81fc14c44 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -16,15 +16,13 @@ static void qla_nvme_unregister_remote_port(struct work_struct *); int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) { - struct nvme_rport *rport; + struct qla_nvme_rport *rport; + struct nvme_fc_port_info req; int ret; if (!IS_ENABLED(CONFIG_NVME_FC)) return 0; - if (fcport->nvme_flag & NVME_FLAG_REGISTERED) - return 0; - if (!vha->flags.nvme_enabled) { ql_log(ql_log_info, vha, 0x2100, "%s: Not registering target since Host NVME is not enabled\n", @@ -33,38 +31,35 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) } if (!(fcport->nvme_prli_service_param & - (NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY))) + (NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY)) || + (fcport->nvme_flag & NVME_FLAG_REGISTERED)) return 0; INIT_WORK(&fcport->nvme_del_work, qla_nvme_unregister_remote_port); - rport = kzalloc(sizeof(*rport), GFP_KERNEL); - if (!rport) { - ql_log(ql_log_warn, vha, 0x2101, - "%s: unable to alloc memory\n", __func__); - return -ENOMEM; - } - rport->req.port_name = wwn_to_u64(fcport->port_name); - rport->req.node_name = wwn_to_u64(fcport->node_name); - rport->req.port_role = 0; + memset(&req, 0, sizeof(struct nvme_fc_port_info)); + req.port_name = wwn_to_u64(fcport->port_name); + req.node_name = wwn_to_u64(fcport->node_name); + req.port_role = 0; + req.dev_loss_tmo = NVME_FC_DEV_LOSS_TMO; if (fcport->nvme_prli_service_param & NV
[PATCH 0/5] qla2xxx: Fixes for FC-NVMe erorr path.
Hi Christoph, This series has mostly cleanup and support for devloss timeout in qla2xxx driver for FC-NVMe protocol. Please consider this series for inclusion in 4.16 Thanks, Himanshu Darren Trapp (3): qla2xxx: Set IIDMA and fcport state before qla_nvme_register_remote() qla2xxx: Add changes for devloss timeout in driver qla2xxx: Restore ZIO threshold setting Himanshu Madhani (2): qla2xxx: Remove unneeded message and minor cleanup for FC-NVMe qla2xxx: Update driver version to 10.00.00.06-k drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_init.c| 13 ++- drivers/scsi/qla2xxx/qla_isr.c | 5 +- drivers/scsi/qla2xxx/qla_nvme.c| 158 +++-- drivers/scsi/qla2xxx/qla_nvme.h| 6 +- drivers/scsi/qla2xxx/qla_target.c | 13 +-- drivers/scsi/qla2xxx/qla_target.h | 2 +- drivers/scsi/qla2xxx/qla_version.h | 2 +- 8 files changed, 94 insertions(+), 106 deletions(-) -- 2.12.0
[PATCH 1/5] qla2xxx: Remove unneeded message and minor cleanup for FC-NVMe
Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_nvme.c | 11 +++ 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 6b33a1f24f56..162a523b985e 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -113,8 +113,6 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport, return 0; } - ql_log(ql_log_warn, vha, 0x, - "allocating q for idx=%x w/o cpu mask\n", qidx); qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true); if (qpair == NULL) { ql_log(ql_log_warn, vha, 0x2122, @@ -313,7 +311,6 @@ static int qla2x00_start_nvme_mq(srb_t *sp) uint16_tavail_dsds; uint32_t*cur_dsd; struct req_que *req = NULL; - struct rsp_que *rsp = NULL; struct scsi_qla_host *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair = sp->qpair; @@ -322,15 +319,13 @@ static int qla2x00_start_nvme_mq(srb_t *sp) struct nvmefc_fcp_req *fd = nvme->u.nvme.desc; uint32_trval = QLA_SUCCESS; + /* Setup qpair pointers */ + req = qpair->req; tot_dsds = fd->sg_cnt; /* Acquire qpair specific lock */ spin_lock_irqsave(&qpair->qp_lock, flags); - /* Setup qpair pointers */ - req = qpair->req; - rsp = qpair->rsp; - /* Check for room in outstanding command list. */ handle = req->current_outstanding_cmd; for (index = 1; index < req->num_outstanding_cmds; index++) { @@ -365,7 +360,7 @@ static int qla2x00_start_nvme_mq(srb_t *sp) struct nvme_fc_cmd_iu *cmd = fd->cmdaddr; if (cmd->sqe.common.opcode == nvme_admin_async_event) { nvme->u.nvme.aen_op = 1; - atomic_inc(&vha->hw->nvme_active_aen_cnt); + atomic_inc(&ha->nvme_active_aen_cnt); } } -- 2.12.0
Re: [PATCH 2/5] scsi: Add VENDOR_SPECIFIC sense code definitions
On Fri, 2018-01-19 at 16:11 +0100, Hannes Reinecke wrote: > Some older devices will return vendor specific sense codes, so > we should be adding a definition for it. > > Signed-off-by: Hannes Reinecke > --- > include/scsi/scsi_proto.h | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h > index 1df8efb0ee01..c36860111932 100644 > --- a/include/scsi/scsi_proto.h > +++ b/include/scsi/scsi_proto.h > @@ -236,6 +236,7 @@ struct scsi_varlen_cdb_hdr { > #define UNIT_ATTENTION 0x06 > #define DATA_PROTECT0x07 > #define BLANK_CHECK 0x08 > +#define VENDOR_SPECIFIC 0x09 > #define COPY_ABORTED0x0a > #define ABORTED_COMMAND 0x0b > #define VOLUME_OVERFLOW 0x0d Reviewed-by: Bart Van Assche
Re: [PATCH target-pending] iscsi-target: make sure to wake up sleeping login worker
Eric Dumazet wrote: > On Fri, 2018-01-19 at 14:36 +0100, Florian Westphal wrote: > > diff --git a/drivers/target/iscsi/iscsi_target_nego.c > > b/drivers/target/iscsi/iscsi_target_nego.c > > index b686e2ce9c0e..3723f8f419aa 100644 > > --- a/drivers/target/iscsi/iscsi_target_nego.c > > +++ b/drivers/target/iscsi/iscsi_target_nego.c > > @@ -432,6 +432,9 @@ static void iscsi_target_sk_data_ready(struct sock *sk) > > if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { > > write_unlock_bh(&sk->sk_callback_lock); > > pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p \n", > > conn); > > + if (WARN_ON(iscsi_target_sk_data_ready == > > conn->orig_data_ready)) > > + return; > > Is this WARN_ON() belonging to this fix ? > At least make it WARN_ON_ONCE() or pr_err_once() Nicholas, I don't know this code at all so it would be good if you could give advice here (omit all together, WARN_ON_ONCE, ...). Thanks!
Re: [PATCH target-pending] iscsi-target: make sure to wake up sleeping login worker
On Fri, 2018-01-19 at 14:36 +0100, Florian Westphal wrote: > Mike Christie reports: > Starting in 4.14 iscsi logins will fail around 50% of the time. > > Problem appears to be that iscsi_target_sk_data_ready() callback may > return without doing anything in case it finds the login work queue > is still blocked in sock_recvmsg(). > > Nicholas Bellinger says: > It would indicate users providing their own ->sk_data_ready() callback > must be responsible for waking up a kthread context blocked on > sock_recvmsg(..., MSG_WAITALL), when a second ->sk_data_ready() is > received before the first sock_recvmsg(..., MSG_WAITALL) completes. > > So, do this and invoke the original data_ready() callback -- in > case of tcp sockets this takes care of waking the thread. > > Disclaimer: I do not understand why this problem did not show up before > tcp prequeue removal. > > Reported-by: Mike Christie > Bisected-by: Mike Christie > Tested-by: Mike Christie > Diagnosed-by: Nicholas Bellinger > Fixes: e7942d0633c4 ("tcp: remove prequeue support") > Signed-off-by: Florian Westphal > --- > drivers/target/iscsi/iscsi_target_nego.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/target/iscsi/iscsi_target_nego.c > b/drivers/target/iscsi/iscsi_target_nego.c > index b686e2ce9c0e..3723f8f419aa 100644 > --- a/drivers/target/iscsi/iscsi_target_nego.c > +++ b/drivers/target/iscsi/iscsi_target_nego.c > @@ -432,6 +432,9 @@ static void iscsi_target_sk_data_ready(struct sock *sk) > if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { > write_unlock_bh(&sk->sk_callback_lock); > pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p \n", > conn); > + if (WARN_ON(iscsi_target_sk_data_ready == > conn->orig_data_ready)) > + return; Is this WARN_ON() belonging to this fix ? At least make it WARN_ON_ONCE() or pr_err_once() > + conn->orig_data_ready(sk); > return; > } >
[PATCH] mpt3sas: fix an out of bound write
cpu_msix_table is allocated to store online cpus, but pci_irq_get_affinity may return cpu_possible_mask which is then used to access cpu_msix_table. That causes bad user experience. Fix limits access to only online cpus, I've also added an additonal test to protect from an unlikely change in cpu_online_mask. Fixes: 1d55abc0e98a0bf35f3af80665aac564e3b30572 scsi: mpt3sas: switch to pci_alloc_irq_vectors Signed-off-by: Tomas Henzl --- drivers/scsi/mpt3sas/mpt3sas_base.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 13d6e4ec3..59a87ca32 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2410,8 +2410,11 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) continue; } - for_each_cpu(cpu, mask) + for_each_cpu_and(cpu, mask, cpu_online_mask) { + if (cpu >= ioc->cpu_msix_table_sz) + break; ioc->cpu_msix_table[cpu] = reply_q->msix_index; + } } return; } -- 2.14.3
[PATCH 2/5] scsi: Add VENDOR_SPECIFIC sense code definitions
Some older devices will return vendor specific sense codes, so we should be adding a definition for it. Signed-off-by: Hannes Reinecke --- include/scsi/scsi_proto.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index 1df8efb0ee01..c36860111932 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -236,6 +236,7 @@ struct scsi_varlen_cdb_hdr { #define UNIT_ATTENTION 0x06 #define DATA_PROTECT0x07 #define BLANK_CHECK 0x08 +#define VENDOR_SPECIFIC 0x09 #define COPY_ABORTED0x0a #define ABORTED_COMMAND 0x0b #define VOLUME_OVERFLOW 0x0d -- 2.12.3
[PATCH 1/5] raid_class: Add 'JBOD' RAID level
Not a real RAID level, but some HBAs support JBOD in addition to the 'classical' RAID levels. Signed-off-by: Hannes Reinecke --- drivers/scsi/raid_class.c | 1 + include/linux/raid_class.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 2c146b44d95f..ea88906d2cc5 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -157,6 +157,7 @@ static struct { { RAID_LEVEL_5, "raid5" }, { RAID_LEVEL_50, "raid50" }, { RAID_LEVEL_6, "raid6" }, + { RAID_LEVEL_JBOD, "jbod" }, }; static const char *raid_level_name(enum raid_level level) diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h index 31e1ff69efc8..ec8655514283 100644 --- a/include/linux/raid_class.h +++ b/include/linux/raid_class.h @@ -38,6 +38,7 @@ enum raid_level { RAID_LEVEL_5, RAID_LEVEL_50, RAID_LEVEL_6, + RAID_LEVEL_JBOD, }; struct raid_data { -- 2.12.3
[PATCHv2 0/5] Deprecate DAC960 driver
Hi all, as we're trying to get rid of the remaining request_fn drivers here's a patchset to move the DAC960 driver to the SCSI stack. As per request from hch I've split up the driver into two new SCSI drivers called 'myrb' and 'myrs'. The 'myrb' driver only supports the earlier (V1) firmware interface, which doesn't have a SCSI interface for the logical drives; for those I've added a (pretty rudimentary, admittedly) SCSI translation for them. The 'myrs' driver supports the newer (V2) firmware interface, which is SCSI based and doesn't need the translation layer. And the weird proc interface from DAC960 has been converted to sysfs attributes. Tested with eXtremeRAID 1100 (for V1 Firmware) and Mylex AcceleRAID 170 (for V2 Firmware). Changes to v1: - Split into two drivers - Improve scanning for V1 firmware interface Hannes Reinecke (5): raid_class: Add 'JBOD' RAID level scsi: Add VENDOR_SPECIFIC sense code definitions myrb: Add Mylex RAID controller (block interface) myrs: Add Mylex RAID controller (SCSI interface) drivers/block: Remove DAC960 driver Documentation/blockdev/README.DAC960 | 756 drivers/block/DAC960.c | 7244 -- drivers/block/DAC960.h | 4415 - drivers/block/Kconfig| 12 - drivers/block/Makefile |1 - drivers/scsi/Kconfig | 28 + drivers/scsi/Makefile|2 + drivers/scsi/myrb.c | 3249 +++ drivers/scsi/myrb.h | 1891 + drivers/scsi/myrs.c | 2947 ++ drivers/scsi/myrs.h | 2042 ++ drivers/scsi/raid_class.c|1 + include/linux/raid_class.h |1 + include/scsi/scsi_proto.h|1 + 14 files changed, 10162 insertions(+), 12428 deletions(-) delete mode 100644 Documentation/blockdev/README.DAC960 delete mode 100644 drivers/block/DAC960.c delete mode 100644 drivers/block/DAC960.h create mode 100644 drivers/scsi/myrb.c create mode 100644 drivers/scsi/myrb.h create mode 100644 drivers/scsi/myrs.c create mode 100644 drivers/scsi/myrs.h -- 2.12.3
[PATCH target-pending] iscsi-target: make sure to wake up sleeping login worker
Mike Christie reports: Starting in 4.14 iscsi logins will fail around 50% of the time. Problem appears to be that iscsi_target_sk_data_ready() callback may return without doing anything in case it finds the login work queue is still blocked in sock_recvmsg(). Nicholas Bellinger says: It would indicate users providing their own ->sk_data_ready() callback must be responsible for waking up a kthread context blocked on sock_recvmsg(..., MSG_WAITALL), when a second ->sk_data_ready() is received before the first sock_recvmsg(..., MSG_WAITALL) completes. So, do this and invoke the original data_ready() callback -- in case of tcp sockets this takes care of waking the thread. Disclaimer: I do not understand why this problem did not show up before tcp prequeue removal. Reported-by: Mike Christie Bisected-by: Mike Christie Tested-by: Mike Christie Diagnosed-by: Nicholas Bellinger Fixes: e7942d0633c4 ("tcp: remove prequeue support") Signed-off-by: Florian Westphal --- drivers/target/iscsi/iscsi_target_nego.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index b686e2ce9c0e..3723f8f419aa 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -432,6 +432,9 @@ static void iscsi_target_sk_data_ready(struct sock *sk) if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { write_unlock_bh(&sk->sk_callback_lock); pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p \n", conn); + if (WARN_ON(iscsi_target_sk_data_ready == conn->orig_data_ready)) + return; + conn->orig_data_ready(sk); return; } -- 2.13.6
[PATCH 3/6] mpt3sas: Introduce API's to get BAR0 mapped buffer address.
For MPI Endpoint/Mcpu, Driver should double buffer data buffer/sgl's. This is normally copied from host to internal memory of IOC by DMA engine of PCI Device. Since the interface to DMA from host to mCPU is not present for Mcpu/MPI Endpoint device, Driver does double copy of those buffer directly to the mCPU memory region via BAR-0 region. Introduced API's to calculate and return BAR0 mapped host buffer's physical and virtual address for the provided smid. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 93 + drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + 2 files changed, 95 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index c0a1c0f..dc289c0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -126,6 +126,99 @@ module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); /** + * _base_get_chain - Calculates and Returns virtual chain address + * for the provided smid in BAR0 space. + * + * @ioc: per adapter object + * @smid: system request message index + * @sge_chain_count: Scatter gather chain count. + * + * @Return: chain address. + */ +static inline void * +_base_get_chain(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u8 sge_chain_count) +{ + void *base_chain, *chain_virt; + u16 cmd_credit = ioc->facts.RequestCredit + 1; + + base_chain = (void *)ioc->chip + MPI_FRAME_START_OFFSET + + (cmd_credit * ioc->request_sz) + + REPLY_FREE_POOL_SIZE; + chain_virt = base_chain + (smid * ioc->facts.MaxChainDepth * + ioc->request_sz) + (sge_chain_count * ioc->request_sz); + return chain_virt; +} + +/** + * _base_get_chain_phys - Calculates and Returns physical address + * in BAR0 for scatter gather chains, for + * the provided smid. + * + * @ioc: per adapter object + * @smid: system request message index + * @sge_chain_count: Scatter gather chain count. + * + * @Return - Physical chain address. + */ +static inline void * +_base_get_chain_phys(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u8 sge_chain_count) +{ + void *base_chain_phys, *chain_phys; + u16 cmd_credit = ioc->facts.RequestCredit + 1; + + base_chain_phys = (void *)ioc->chip_phys + MPI_FRAME_START_OFFSET + + (cmd_credit * ioc->request_sz) + + REPLY_FREE_POOL_SIZE; + chain_phys = base_chain_phys + (smid * ioc->facts.MaxChainDepth * + ioc->request_sz) + (sge_chain_count * ioc->request_sz); + return chain_phys; +} + +/** + * _base_get_buffer_bar0 - Calculates and Returns BAR0 mapped Host + * buffer address for the provided smid. + * (Each smid can have 64K starts from 17024) + * + * @ioc: per adapter object + * @smid: system request message index + * + * @Returns - Pointer to buffer location in BAR0. + */ + +static void * +_base_get_buffer_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) +{ + u16 cmd_credit = ioc->facts.RequestCredit + 1; + // Added extra 1 to reach end of chain. + void *chain_end = _base_get_chain(ioc, + cmd_credit + 1, + ioc->facts.MaxChainDepth); + return chain_end + (smid * 64 * 1024); +} + +/** + * _base_get_buffer_phys_bar0 - Calculates and Returns BAR0 mapped + * Host buffer Physical address for the provided smid. + * (Each smid can have 64K starts from 17024) + * + * @ioc: per adapter object + * @smid: system request message index + * + * @Returns - Pointer to buffer location in BAR0. + */ +static void * +_base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) +{ + u16 cmd_credit = ioc->facts.RequestCredit + 1; + void *chain_end_phys = _base_get_chain_phys(ioc, + cmd_credit + 1, + ioc->facts.MaxChainDepth); + return chain_end_phys + (smid * 64 * 1024); +} + +/** * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc * @arg: input argument, used to derive ioc * diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 897394d..2529d25 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -120,6 +120,8 @@ #define MPT3SAS_NVME_QUEUE_DEPTH 128 #define MPT_NAME_LENGTH32 /* generic length of strings */ #define MPT_STRING_LENGTH 64 +#define MPI_FRAME_START_OFFSET 256 +#define REPLY_FREE_POOL_SIZE 512 /*(32 maxcredix *4)*(4 times)*/ #define MPT_MAX_CALLBACKS 32 -- 2.5.5
[PATCH 5/6] mpt3sas: Introduce function to clone mpi request.
1) Added function _base_clone_mpi_to_sys_mem to clone MPI request into system BAR0 mapped region. 2) Seperate out MPI Endpoint IO submissions to function _base_put_smid_mpi_ep_scsi_io. 3) MPI EP requests are submitted in two 32 bit MMIO writes. from _base_mpi_ep_writeq. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 131 +--- 1 file changed, 123 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 40a1806..0248058 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -126,6 +126,24 @@ module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); /** + * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames + * to system/BAR0 region. + * + * @dst_iomem: Pointer to the destinaltion location in BAR0 space. + * @src: Pointer to the Source data. + * @size: Size of data to be copied. + */ +static void +_base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size) +{ + int i; + __le32 *src_virt_mem = (__le32 *)src; + + for (i = 0; i < size/4; i++) + writel(cpu_to_le32(src_virt_mem[i]), dst_iomem + (i * 4)); +} + +/** * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region * * @dst_iomem: Pointer to the destinaltion location in BAR0 space. @@ -3265,6 +3283,29 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) } /** + * _base_mpi_ep_writeq - 32 bit write to MMIO + * @b: data payload + * @addr: address in MMIO space + * @writeq_lock: spin lock + * + * This special handling for MPI EP to take care of 32 bit + * environment where its not quarenteed to send the entire word + * in one transfer. + */ +static inline void +_base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr, + spinlock_t *writeq_lock) +{ + unsigned long flags; + __u64 data_out = cpu_to_le64(b); + + spin_lock_irqsave(writeq_lock, flags); + writel((u32)(data_out), addr); + writel((u32)(data_out >> 32), (addr + 4)); + spin_unlock_irqrestore(writeq_lock, flags); +} + +/** * _base_writeq - 64 bit write to MMIO * @ioc: per adapter object * @b: data payload @@ -3296,6 +3337,36 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) #endif /** + * _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware + * @ioc: per adapter object + * @smid: system request message index + * @handle: device handle + * + * Return nothing. + */ +static void +_base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) +{ + Mpi2RequestDescriptorUnion_t descriptor; + u64 *request = (u64 *)&descriptor; + void *mpi_req_iomem; + __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid); + + _clone_sg_entries(ioc, (void *) mfp, smid); + mpi_req_iomem = (void *)ioc->chip + + MPI_FRAME_START_OFFSET + (smid * ioc->request_sz); + _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp, + ioc->request_sz); + descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; + descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); + descriptor.SCSIIO.SMID = cpu_to_le16(smid); + descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); + descriptor.SCSIIO.LMID = 0; + _base_mpi_ep_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); +} + +/** * _base_put_smid_scsi_io - send SCSI_IO request to firmware * @ioc: per adapter object * @smid: system request message index @@ -3356,7 +3427,23 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 msix_task) { Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; + void *mpi_req_iomem; + u64 *request; + + if (ioc->is_mcpu_endpoint) { + MPI2RequestHeader_t *request_hdr; + + __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid); + + request_hdr = (MPI2RequestHeader_t *)mfp; + /* TBD 256 is offset within sys register. */ + mpi_req_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET + + (smid * ioc->request_sz); + _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp, + ioc->request_sz); + } + + request = (u64 *)&descriptor; descriptor.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; @@ -3364,8 +3451,13 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, descriptor.HighPriority.SMID = cpu_to_le16(smid); descriptor.HighPriority.LMID = 0; descriptor.HighPrior
[PATCH 0/6] mpt3sas: Adding MPI Endpoint device support.
Andromeda is a PCIe switch, and it has a dedicated management CPU (mCPU), nonvolatile flash memory, RAM etc... and Linux kernel runs on mCPU. MPI Endpoint driver is the management driver for Andromeda. The Plx Manager driver running on mCPU synthesizes a virtual/Synthetic MPI End point to host. Synthetic MPI End point is emulated IT firmware running on Linux operating system, which interfaces with PLX management driver. PLX Management driver integrates IOCFW in same driver binary. At the end of Plx_Mgr driver load, it initializes IOC FW as well. Current implementation is single instance of IOC FW (as it supports only one host). PLX management driver will provide required resources and infrastructure for Synthetic MPI End point. Existing PLXManagement driver will reserve virtual slot for MPI end point. currently, Virtual slot number 29 is reserved for MPI end point. Synthetic device in management driver will be marked as new type “PLX_DEV_TYPE_SYNTH_MPI_EP”. PLXmanagement driver will interface with Synthetic MPI Endpoint for any communication happening on PLX_DEV_TYPE_SYNTH_MPI_EP device type from host. Link between host and PLX C2 is in below diagram. ___ ___| | | | | | | PLX C2|===|HOST | | PCI - |===| MACHINE | | SWITCH | | | |___| | | || |___| || || ___||__ | | | MCPU | | | |___| After MPI end point implementation - (Host will see dedicated Virtual SLOT as MPI End point.) In Below single line is logical channel for MPI Endpoint ___ ___| | | | | | | PLX C2|===| HOST| | PCI - |===| MACHINE | | SWITCH | | | | | | --- | |___|---| | IT DRIVER | | || | | --- | || | |___| || | || | ___||__|___ | || | | | MCPU | | |___| | | | PLX MGR| | | | DRIVER | | | || | | | | |___|_ | | | | | | |IOC FW | | | |_| | |___| PLXmanagement driver will create MPI end point based on device table definition. PLXManagement driver will also populate Synthetic device tree based on Device Table for each host. >From host it will be seen as IT HBA (Simplified version of SAS2/MPI2) (PCI Device, in which emulated IT FW running on mCPU behind Synthetic endpoint of PCISWITCH). For host it is considered as actual Physical Device. PLX Management driver provide interface to do DMA from mCPU to Host using “MCPU Response Data Buffer“ method. DMA from Host to mCPU using “MCPU Response Data Buffer” is not possible. Why DMA from host to mCPU is not possible using Responsebuffer ? MCPU Response buffer is not really for reading from host (reading will work, but answer TLP will not come back to the CSR FIFO, but will go to the MCPU root complex - which could be an unexpected read completion! Existing host driver (mpt2sas) will not work for MPI end point. As the interface to DMA from host to mCPU is not present for Mcpu/MPI Endpoint device, To overcome this Driver should do double copy of those buffer directly to the mCPU memory region via BAR-0 region. The host BAR0 region is divided into different group to serve Host assisted DMA. 0- 255 System register(Doorbell, Host Interrupt etc) 256 - 4352MPI Frame. (This is based on maxCredit 32) 4352 - 4864Reply_free pool (512 byte is reserved considering maxCredit 32. Reply needsextra room, for mCPU case kept four times of maxCredit) 4864 -17152SGE chain element. (32 command * 3 chain of 128 byte size = 12288) 17152 -x Host buffer mapped with smid. (Each smid can have 64K Max IO.) BAR0+Last 1KMSIX Addr and DataTotalsize in use 2113664 bytes of 4MB BAR0 MPI end point module of PLX management driver must be aware of regions above. SGE and Host buffer details will be available in MPI frame. Each PCI packets coming from host on MPI end point will end up in mCPU PLXmanagement driver. We can consider this as front end for IOC FW. PLXManagementdriver will call IOC front end API which will be the entry point in IOC FW module. Once PLX management calls relevant callbackfrom IOC FW, rest
[PATCH 4/6] mpt3sas: Introduce Base function for cloning.
All scsi IO's and config requests data buffer and sgl are cloned to system memory in _clone_sg_entries before submitting it to Firmware. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 212 +- drivers/scsi/mpt3sas/mpt3sas_base.h | 3 + drivers/scsi/mpt3sas/mpt3sas_config.c | 1 + 3 files changed, 215 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index dc289c0..40a1806 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -126,6 +126,23 @@ module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); /** + * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region + * + * @dst_iomem: Pointer to the destinaltion location in BAR0 space. + * @src: Pointer to the Source data. + * @size: Size of data to be copied. + */ +static void +_base_clone_to_sys_mem(void *dst_iomem, void *src, u32 size) +{ + int i; + __le32 *src_virt_mem = (__le32 *)(src); + + for (i = 0; i < size/4; i++) + writel(cpu_to_le32(src_virt_mem[i]), dst_iomem + (i * 4)); +} + +/** * _base_get_chain - Calculates and Returns virtual chain address * for the provided smid in BAR0 space. * @@ -219,6 +236,199 @@ _base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) } /** + * _base_get_chain_buffer_dma_to_chain_buffer - Iterates chain + * lookup list and Provides chain_buffer + * address for the matching dma address. + * (Each smid can have 64K starts from 17024) + * + * @ioc: per adapter object + * @chain_buffer_dma: Chain buffer dma address. + * + * @Returns - Pointer to chain buffer. Or Null on Failure. + */ +static void * +_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc, + dma_addr_t chain_buffer_dma) +{ + u16 index; + + for (index = 0; index < ioc->chain_depth; index++) { + if (ioc->chain_lookup[index].chain_buffer_dma == + chain_buffer_dma) + return ioc->chain_lookup[index].chain_buffer; + } + pr_info(MPT3SAS_FMT + "Provided chain_buffer_dma address is not in the lookup list\n", + ioc->name); + return NULL; +} + +/** + * _clone_sg_entries - MPI EP's scsiio and config requests + * are handled here. Base function for + * double buffering, before submitting + * the requests. + * + * @ioc: per adapter object. + * @mpi_request: mf request pointer. + * @smid: system request message index. + * + * @Returns: Nothing. + */ +static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, + void *mpi_request, u16 smid) +{ + Mpi2SGESimple32_t *sgel, *sgel_next; + u32 sgl_flags, sge_chain_count = 0; + bool is_write = 0; + u16 i = 0; + void *buffer_iomem, *buffer_iomem_phys; + void *buff_ptr, *buff_ptr_phys; + void *dst_chain_addr[MCPU_MAX_CHAINS_PER_IO]; + void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO], *dst_addr_phys; + MPI2RequestHeader_t *request_hdr; + struct scsi_cmnd *scmd; + struct scatterlist *sg_scmd = NULL; + int is_scsiio_req = 0; + + request_hdr = (MPI2RequestHeader_t *) mpi_request; + + if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) { + Mpi25SCSIIORequest_t *scsiio_request = + (Mpi25SCSIIORequest_t *)mpi_request; + sgel = (Mpi2SGESimple32_t *) &scsiio_request->SGL; + is_scsiio_req = 1; + } else if (request_hdr->Function == MPI2_FUNCTION_CONFIG) { + Mpi2ConfigRequest_t *config_req = + (Mpi2ConfigRequest_t *)mpi_request; + sgel = (Mpi2SGESimple32_t *) &config_req->PageBufferSGE; + } else + return; + + /* From smid we can get scsi_cmd, once we have sg_scmd, +* we just need to get sg_virt and sg_next to get virual +* address associated with sgel->Address. +*/ + + if (is_scsiio_req) { + /* Get scsi_cmd using smid */ + scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid); + if (scmd == NULL) { + pr_err(MPT3SAS_FMT "scmd is NULL\n", ioc->name); + return; + } + + /* Get sg_scmd from scmd provided */ + sg_scmd = scsi_sglist(scmd); + } + + /* +* 0 - 255 System register +* 256 - 4352 MPI Frame. (This is based on maxCredit 32) +* 4352 - 4864 Reply_free pool (512 byte is reserved +* considering maxCredit 32. Reply need extra +* room, for mCPU case kept four times of +*
[PATCH 1/6] mpt3sas: Add PCI device ID for Andromeda.
Add device ID and flag for Andromeda/MPI Emdpont. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 1 + drivers/scsi/mpt3sas/mpt3sas_base.h | 1 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 -- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index ee11710..0ad88de 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h @@ -524,6 +524,7 @@ typedef struct _MPI2_CONFIG_REPLY { #define MPI2_MFGPAGE_DEVID_SAS2308_1(0x0086) #define MPI2_MFGPAGE_DEVID_SAS2308_2(0x0087) #define MPI2_MFGPAGE_DEVID_SAS2308_3(0x006E) +#define MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP (0x02B0) /*MPI v2.5 SAS products */ #define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 789bc42..897394d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1336,6 +1336,7 @@ struct MPT3SAS_ADAPTER { u32 ring_buffer_offset; u32 ring_buffer_sz; u8 is_warpdrive; + u8 is_mcpu_endpoint; u8 hide_ir_msg; u8 mfg_pg10_hide_flag; u8 hide_drives; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 74fca18..bde3c6f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -10335,6 +10335,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev) case MPI2_MFGPAGE_DEVID_SAS2308_1: case MPI2_MFGPAGE_DEVID_SAS2308_2: case MPI2_MFGPAGE_DEVID_SAS2308_3: + case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP: return MPI2_VERSION; case MPI25_MFGPAGE_DEVID_SAS3004: case MPI25_MFGPAGE_DEVID_SAS3008: @@ -10412,11 +10413,18 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->hba_mpi_version_belonged = hba_mpi_version; ioc->id = mpt2_ids++; sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME); - if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) { + switch (pdev->device) { + case MPI2_MFGPAGE_DEVID_SSS6200: ioc->is_warpdrive = 1; ioc->hide_ir_msg = 1; - } else + break; + case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP: + ioc->is_mcpu_endpoint = 1; + break; + default: ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; + break; + } break; case MPI25_VERSION: case MPI26_VERSION: @@ -10845,6 +10853,8 @@ static const struct pci_device_id mpt3sas_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP, + PCI_ANY_ID, PCI_ANY_ID }, /* SSS6200 */ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, PCI_ANY_ID, PCI_ANY_ID }, -- 2.5.5
[PATCH 2/6] mpt3sas: Configure reply post queue depth, DMA and sgl tablesize.
This configures shost max sector to 128, single reply descriptor post queue, sgl table size to 16 and 32 bit DMA for MPI Endpoint and it supports 64K as max IO. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 47 +++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 40 ++ 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index a44b9be..c0a1c0f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2214,6 +2214,9 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) struct sysinfo s; u64 consistent_dma_mask; + if (ioc->is_mcpu_endpoint) + goto try_32bit; + if (ioc->dma_mask) consistent_dma_mask = DMA_BIT_MASK(64); else @@ -2232,6 +2235,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) } } + try_32bit: if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { ioc->base_add_sg_single = &_base_add_sg_single_32; @@ -3887,17 +3891,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) sg_tablesize = min_t(unsigned short, sg_tablesize, MPT_KDUMP_MIN_PHYS_SEGMENTS); - if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS) - sg_tablesize = MPT_MIN_PHYS_SEGMENTS; - else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { - sg_tablesize = min_t(unsigned short, sg_tablesize, - SG_MAX_SEGMENTS); - pr_warn(MPT3SAS_FMT -"sg_tablesize(%u) is bigger than kernel" -" defined SG_CHUNK_SIZE(%u)\n", ioc->name, -sg_tablesize, MPT_MAX_PHYS_SEGMENTS); + if (ioc->is_mcpu_endpoint) + ioc->shost->sg_tablesize = MPT_MIN_PHYS_SEGMENTS; + else { + if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS) + sg_tablesize = MPT_MIN_PHYS_SEGMENTS; + else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { + sg_tablesize = min_t(unsigned short, sg_tablesize, + SG_MAX_SEGMENTS); + pr_warn(MPT3SAS_FMT + "sg_tablesize(%u) is bigger than kernel " + "defined SG_CHUNK_SIZE(%u)\n", ioc->name, + sg_tablesize, MPT_MAX_PHYS_SEGMENTS); + } + ioc->shost->sg_tablesize = sg_tablesize; } - ioc->shost->sg_tablesize = sg_tablesize; ioc->internal_depth = min_t(int, (facts->HighPriorityCredit + (5)), (facts->RequestCredit / 4)); @@ -3982,13 +3990,18 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) /* reply free queue sizing - taking into account for 64 FW events */ ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - /* calculate reply descriptor post queue depth */ - ioc->reply_post_queue_depth = ioc->hba_queue_depth + - ioc->reply_free_queue_depth + 1 ; - /* align the reply post queue on the next 16 count boundary */ - if (ioc->reply_post_queue_depth % 16) - ioc->reply_post_queue_depth += 16 - - (ioc->reply_post_queue_depth % 16); + /* mCPU manage single counters for simplicity */ + if (ioc->is_mcpu_endpoint) + ioc->reply_post_queue_depth = ioc->reply_free_queue_depth; + else { + /* calculate reply descriptor post queue depth */ + ioc->reply_post_queue_depth = ioc->hba_queue_depth + + ioc->reply_free_queue_depth + 1; + /* align the reply post queue on the next 16 count boundary */ + if (ioc->reply_post_queue_depth % 16) + ioc->reply_post_queue_depth += 16 - + (ioc->reply_post_queue_depth % 16); + } if (ioc->reply_post_queue_depth > facts->MaxReplyDescriptorPostQueueDepth) { diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index bde3c6f..5e52679 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -10521,26 +10521,34 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) shost->transportt = mpt3sas_transport_template; shost->unique_id = ioc->id; - if (max_sectors != 0x) { - if (max_sectors < 64) { - shost->max_sectors = 64; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "va
[PATCH 6/6] mpt3sas: Introduce function to clone mpi reply.
If the posted request has an error of any type, the IOC writes a Reply message into a host-based system reply message frame. This functions clone it in the BAR0 mapped region. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 34 +- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 0248058..fa13916 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -126,6 +126,32 @@ module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); /** + * _base_clone_reply_to_sys_mem - copies reply to reply free iomem + * in BAR0 space. + * + * @ioc: per adapter object + * @reply: reply message frame(lower 32bit addr) + * @index: System request message index. + * + * @Returns - Nothing + */ +static void +_base_clone_reply_to_sys_mem(struct MPT3SAS_ADAPTER *ioc, U32 reply, + u32 index) +{ + /* +* 256 is offset within sys register. +* 256 offset MPI frame starts. Max MPI frame supported is 32. +* 32 * 128 = 4K. From here, Clone of reply free for mcpu starts +*/ + u16 cmd_credit = ioc->facts.RequestCredit + 1; + void *reply_free_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET + + (cmd_credit * ioc->request_sz) + (index * sizeof(u32)); + + writel(cpu_to_le32(reply), reply_free_iomem); +} + +/** * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames * to system/BAR0 region. * @@ -1396,6 +1422,9 @@ _base_interrupt(int irq, void *bus_id) 0 : ioc->reply_free_host_index + 1; ioc->reply_free[ioc->reply_free_host_index] = cpu_to_le32(reply); + if (ioc->is_mcpu_endpoint) + _base_clone_reply_to_sys_mem(ioc, reply, + ioc->reply_free_host_index); writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); } @@ -6244,8 +6273,11 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) /* initialize Reply Free Queue */ for (i = 0, reply_address = (u32)ioc->reply_dma ; i < ioc->reply_free_queue_depth ; i++, reply_address += - ioc->reply_sz) + ioc->reply_sz) { ioc->reply_free[i] = cpu_to_le32(reply_address); + if (ioc->is_mcpu_endpoint) + _base_clone_reply_to_sys_mem(ioc, reply_address, i); + } /* initialize reply queues */ if (ioc->is_driver_loading) -- 2.5.5
Re: [PATCH] sd: succeed check_event if device is not removable
Hi James, Thanks for prompt reply. On Thu, Jan 18, 2018 at 5:32 PM, James Bottomley wrote: > On Thu, 2018-01-18 at 17:22 +0100, Jack Wang wrote: >> From: Jack Wang >> >> The check_events interface was added for check if device changes, >> mainly for device is removable eg. CDROM >> >> In sd_open, it checks if device is removable then check_disk_change. >> >> when the device is not removable, we can simple succeeds the call >> without send TUR. >> >> Signed-off-by: Jack Wang >> --- >> drivers/scsi/sd.c | 4 >> 1 file changed, 4 insertions(+) >> >> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c >> index ab75ebd..773ce81 100644 >> --- a/drivers/scsi/sd.c >> +++ b/drivers/scsi/sd.c >> @@ -1576,6 +1576,10 @@ static unsigned int sd_check_events(struct >> gendisk *disk, unsigned int clearing) >> sdp = sdkp->device; >> SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, >> "sd_check_events\n")); >> >> + if (!sdp->removable) { >> + retval = 0; >> + goto out; >> + } > > This looks like very much the wrong place to fix whatever problem > you're seeing is. We could simply avoid setting up the events work > function in genhd.c:device_add_disk(), which would be way more > efficient. However, I think some devices do require being probed > occasionally with a TUR because its the only way SCSI gets AENs (not > that we make much use of them). > > So first of all, what's the actual problem? > > James > Eagle eyes! The real problem I want to workaround is deadlock between check_event and device removal, reported here: https://patchwork.kernel.org/patch/10057977/ We've see in our production during incident, storage failure lead scsi error handle and offlined both devices, so both multipaths down, raid1 failed one leg (the dm device). During incident recovery, when tried to delete the broken scsi device, there are processes in D state. I failed to reproduce on my test machines, this is why I want to workaround the problem by avoiding TUR. Thanks, -- Jack Wang