diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 00:39:25 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 00:39:25 +0200 |
commit | b68ee1c6131c540a62ecd443be89c406401df091 (patch) | |
tree | e9accd3c0dac35f71bc6b3d81197f866dca9e530 /drivers/scsi | |
parent | Merge tag 'ata-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlem... (diff) | |
parent | scsi: ufs: mcq: Use pointer arithmetic in ufshcd_send_command() (diff) | |
download | linux-b68ee1c6131c540a62ecd443be89c406401df091.tar.xz linux-b68ee1c6131c540a62ecd443be89c406401df091.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"Updates to the usual drivers (megaraid_sas, scsi_debug, lpfc, target,
mpi3mr, hisi_sas, arcmsr).
The major core change is the constification of the host templates
(which touches everything) along with other minor fixups and clean
ups"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (207 commits)
scsi: ufs: mcq: Use pointer arithmetic in ufshcd_send_command()
scsi: ufs: mcq: Annotate ufshcd_inc_sq_tail() appropriately
scsi: cxlflash: s/semahpore/semaphore/
scsi: lpfc: Silence an incorrect device output
scsi: mpi3mr: Use IRQ save variants of spinlock to protect chain frame allocation
scsi: scsi_debug: Fix missing error code in scsi_debug_init()
scsi: hisi_sas: Work around build failure in suspend function
scsi: lpfc: Fix ioremap issues in lpfc_sli4_pci_mem_setup()
scsi: mpt3sas: Fix an issue when driver is being removed
scsi: mpt3sas: Remove HBA BIOS version in the kernel log
scsi: target: core: Fix invalid memory access
scsi: scsi_debug: Drop sdebug_queue
scsi: scsi_debug: Only allow sdebug_max_queue be modified when no shosts
scsi: scsi_debug: Use scsi_host_busy() in delay_store() and ndelay_store()
scsi: scsi_debug: Use blk_mq_tagset_busy_iter() in stop_all_queued()
scsi: scsi_debug: Use blk_mq_tagset_busy_iter() in sdebug_blk_mq_poll()
scsi: scsi_debug: Dynamically allocate sdebug_queued_cmd
scsi: scsi_debug: Use scsi_block_requests() to block queues
scsi: scsi_debug: Protect block_unblock_all_queues() with mutex
scsi: scsi_debug: Change shost list lock to a mutex
...
Diffstat (limited to 'drivers/scsi')
144 files changed, 1291 insertions, 1170 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 6cb9cca9565b..38d20a69ee12 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1976,8 +1976,7 @@ static int twa_slave_configure(struct scsi_device *sdev) return 0; } /* End twa_slave_configure() */ -/* scsi_host_template initializer */ -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "3ware 9000 Storage Controller", .queuecommand = twa_scsi_queue, diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index f41c93454f0c..55989eaa2d9f 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1530,8 +1530,7 @@ static int twl_slave_configure(struct scsi_device *sdev) return 0; } /* End twl_slave_configure() */ -/* scsi_host_template initializer */ -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "3w-sas", .queuecommand = twl_scsi_queue, diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index ffdecb12d654..36c34ced0cc1 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2229,7 +2229,7 @@ static int tw_slave_configure(struct scsi_device *sdev) return 0; } /* End tw_slave_configure() */ -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "3ware Storage Controller", .queuecommand = tw_scsi_queue, diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index f7b7ffda1161..72ceaf650b0d 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -54,7 +54,7 @@ #define FAILURE (-1) #endif -static struct scsi_host_template blogic_template; +static const struct scsi_host_template blogic_template; /* blogic_drvr_options_count is a count of the number of BusLogic Driver @@ -3663,7 +3663,7 @@ static int __init blogic_parseopts(char *options) Get it all started */ -static struct scsi_host_template blogic_template = { +static const struct scsi_host_template blogic_template = { .module = THIS_MODULE, .proc_name = "BusLogic", .write_info = blogic_write_info, diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index d02eb5b213d0..b95147fb18b0 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -1065,7 +1065,7 @@ static irqreturn_t inia100_intr(int irqno, void *devid) return res; } -static struct scsi_host_template inia100_template = { +static const struct scsi_host_template inia100_template = { .proc_name = "inia100", .name = inia100_REVID, .queuecommand = inia100_queue, diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 74312400468b..204448bfd04b 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -180,7 +180,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static struct scsi_host_template a2091_scsi_template = { +static const struct scsi_host_template a2091_scsi_template = { .module = THIS_MODULE, .name = "Commodore A2091/A590 SCSI", .show_info = wd33c93_show_info, diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index 2c5cb1a02e86..c3028726bbe4 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -197,7 +197,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static struct scsi_host_template amiga_a3000_scsi_template = { +static const struct scsi_host_template amiga_a3000_scsi_template = { .module = THIS_MODULE, .name = "Amiga 3000 built-in SCSI", .show_info = wd33c93_show_info, diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 5ba5c18b77b4..68f4dbcfff49 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -26,7 +26,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/pci.h> -#include <linux/aer.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/spinlock.h> @@ -1476,7 +1475,7 @@ static const struct file_operations aac_cfg_fops = { .llseek = noop_llseek, }; -static struct scsi_host_template aac_driver_template = { +static const struct scsi_host_template aac_driver_template = { .module = THIS_MODULE, .name = "AAC", .proc_name = AAC_DRIVERNAME, @@ -1783,7 +1782,6 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) aac_scan_host(aac); - pci_enable_pcie_error_reporting(pdev); pci_save_state(pdev); return 0; @@ -1949,7 +1947,6 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, scsi_host_complete_all_commands(shost, DID_NO_CONNECT); aac_release_resources(aac); - pci_disable_pcie_error_reporting(pdev); aac_adapter_ioremap(aac, 0); return PCI_ERS_RESULT_NEED_RESET; diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index f301aec044bb..ab066bb27a57 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -10602,7 +10602,7 @@ static int AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost) } #endif -static struct scsi_host_template advansys_template = { +static const struct scsi_host_template advansys_template = { .proc_name = DRV_NAME, #ifdef CONFIG_PROC_FS .show_info = advansys_show_info, diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index caeebfb67149..055adb349b0e 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -400,7 +400,7 @@ MODULE_DEVICE_TABLE(isapnp, id_table); #endif /* !AHA152X_PCMCIA */ -static struct scsi_host_template aha152x_driver_template; +static const struct scsi_host_template aha152x_driver_template; /* * internal states of the host @@ -2946,7 +2946,7 @@ static int aha152x_adjust_queue(struct scsi_device *device) return 0; } -static struct scsi_host_template aha152x_driver_template = { +static const struct scsi_host_template aha152x_driver_template = { .module = THIS_MODULE, .name = AHA152X_REVID, .proc_name = "aha152x", diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 552ca95157da..9503996c6325 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -737,7 +737,8 @@ fail: } /* return non-zero on detection */ -static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx) +static struct Scsi_Host *aha1542_hw_init(const struct scsi_host_template *tpnt, + struct device *pdev, int indx) { unsigned int base_io = io[indx]; struct Scsi_Host *sh; @@ -1031,7 +1032,7 @@ static int aha1542_exit_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd) return 0; } -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .proc_name = "aha1542", .name = "Adaptec 1542", diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index 134255751819..3d18945abaf7 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -543,7 +543,7 @@ static int aha1740_eh_abort_handler (struct scsi_cmnd *dummy) return SUCCESS; } -static struct scsi_host_template aha1740_template = { +static const struct scsi_host_template aha1740_template = { .module = THIS_MODULE, .proc_name = "aha1740", .show_info = aha1740_show_info, diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 954d0c5ae2e2..f7f81f6c3fbf 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -35,7 +35,7 @@ static struct scsi_transport_template *aic94xx_transport_template; static int asd_scan_finished(struct Scsi_Host *, unsigned long); static void asd_scan_start(struct Scsi_Host *); -static struct scsi_host_template aic94xx_sht = { +static const struct scsi_host_template aic94xx_sht = { .module = THIS_MODULE, /* .name is initialized */ .name = "aic94xx", diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c index b69edb473295..fbb29dbb1e50 100644 --- a/drivers/scsi/am53c974.c +++ b/drivers/scsi/am53c974.c @@ -371,7 +371,7 @@ static void dc390_check_eeprom(struct esp *esp) static int pci_esp_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { - struct scsi_host_template *hostt = &scsi_esp_template; + const struct scsi_host_template *hostt = &scsi_esp_template; int err = -ENODEV; struct Scsi_Host *shost; struct esp *esp; diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 07df255c4b1b..ed8d9319862a 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -45,11 +45,12 @@ #include <linux/interrupt.h> struct device_attribute; /*The limit of outstanding scsi command that firmware can handle*/ +#define ARCMSR_NAME "arcmsr" #define ARCMSR_MAX_FREECCB_NUM 1024 #define ARCMSR_MAX_OUTSTANDING_CMD 1024 #define ARCMSR_DEFAULT_OUTSTANDING_CMD 128 #define ARCMSR_MIN_OUTSTANDING_CMD 32 -#define ARCMSR_DRIVER_VERSION "v1.50.00.05-20210429" +#define ARCMSR_DRIVER_VERSION "v1.50.00.13-20230206" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index d3fb8a9c1c39..2cd12c7f06c6 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -57,7 +57,6 @@ #include <linux/timer.h> #include <linux/slab.h> #include <linux/pci.h> -#include <linux/aer.h> #include <linux/circ_buf.h> #include <asm/dma.h> #include <asm/io.h> @@ -152,8 +151,9 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_de return scsi_change_queue_depth(sdev, queue_depth); } -static struct scsi_host_template arcmsr_scsi_host_template = { +static const struct scsi_host_template arcmsr_scsi_host_template = { .module = THIS_MODULE, + .proc_name = ARCMSR_NAME, .name = "Areca SAS/SATA RAID driver", .info = arcmsr_info, .queuecommand = arcmsr_queue_command, @@ -997,6 +997,8 @@ static int arcmsr_set_dma_mask(struct AdapterControlBlock *acb) if (((acb->adapter_type == ACB_ADAPTER_TYPE_A) && !dma_mask_64) || dma_set_mask(&pcidev->dev, DMA_BIT_MASK(64))) goto dma32; + if (acb->adapter_type <= ACB_ADAPTER_TYPE_B) + return 0; if (dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(64)) || dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(64))) { printk("arcmsr: set DMA 64 mask failed\n"); @@ -1300,20 +1302,13 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) return rtnval; } -static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) -{ - struct scsi_cmnd *pcmd = ccb->pcmd; - - scsi_dma_unmap(pcmd); -} - static void arcmsr_ccb_complete(struct CommandControlBlock *ccb) { struct AdapterControlBlock *acb = ccb->acb; struct scsi_cmnd *pcmd = ccb->pcmd; unsigned long flags; atomic_dec(&acb->ccboutstandingcount); - arcmsr_pci_unmap_dma(ccb); + scsi_dma_unmap(ccb->pcmd); ccb->startdone = ARCMSR_CCB_DONE; spin_lock_irqsave(&acb->ccblist_lock, flags); list_add_tail(&ccb->list, &acb->ccb_free_list); @@ -1597,7 +1592,7 @@ static void arcmsr_remove_scsi_devices(struct AdapterControlBlock *acb) ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_pci_unmap_dma(ccb); + scsi_dma_unmap(ccb->pcmd); scsi_done(ccb->pcmd); } } @@ -2260,8 +2255,11 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) spin_lock_irqsave(&acb->rqbuffer_lock, flags); prbuffer = arcmsr_get_iop_rqbuffer(acb); - buf_empty_len = (acb->rqbuf_putIndex - acb->rqbuf_getIndex - 1) & - (ARCMSR_MAX_QBUFFER - 1); + if (acb->rqbuf_putIndex >= acb->rqbuf_getIndex) { + buf_empty_len = (ARCMSR_MAX_QBUFFER - 1) - + (acb->rqbuf_putIndex - acb->rqbuf_getIndex); + } else + buf_empty_len = acb->rqbuf_getIndex - acb->rqbuf_putIndex - 1; if (buf_empty_len >= readl(&prbuffer->data_len)) { if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 7602639da9b3..0b046e4b395c 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -2780,7 +2780,7 @@ static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance) return 0; } -static struct scsi_host_template acornscsi_template = { +static const struct scsi_host_template acornscsi_template = { .module = THIS_MODULE, .show_info = acornscsi_show_info, .name = "AcornSCSI", diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c index 2527b542bcdd..925d0bd68aa5 100644 --- a/drivers/scsi/arm/arxescsi.c +++ b/drivers/scsi/arm/arxescsi.c @@ -238,7 +238,7 @@ arxescsi_show_info(struct seq_file *m, struct Scsi_Host *host) return 0; } -static struct scsi_host_template arxescsi_template = { +static const struct scsi_host_template arxescsi_template = { .show_info = arxescsi_show_info, .name = "ARXE SCSI card", .info = arxescsi_info, diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 5d4f67ba74c0..d1a2a22ffe8c 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -211,7 +211,7 @@ static void cumanascsi_write(struct NCR5380_hostdata *hostdata, #include "../NCR5380.c" -static struct scsi_host_template cumanascsi_template = { +static const struct scsi_host_template cumanascsi_template = { .module = THIS_MODULE, .name = "Cumana 16-bit SCSI", .info = cumanascsi_info, diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index d15053f02472..c5d8f4313b31 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -356,7 +356,7 @@ static int cumanascsi_2_show_info(struct seq_file *m, struct Scsi_Host *host) return 0; } -static struct scsi_host_template cumanascsi2_template = { +static const struct scsi_host_template cumanascsi2_template = { .module = THIS_MODULE, .show_info = cumanascsi_2_show_info, .write_info = cumanascsi_2_set_proc_info, diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index 6f374af9f45f..b3ec7635bc72 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -473,7 +473,7 @@ static ssize_t eesoxscsi_store_term(struct device *dev, struct device_attribute static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR, eesoxscsi_show_term, eesoxscsi_store_term); -static struct scsi_host_template eesox_template = { +static const struct scsi_host_template eesox_template = { .module = THIS_MODULE, .show_info = eesoxscsi_show_info, .write_info = eesoxscsi_set_proc_info, diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index f18a0620c808..d69245007096 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -100,7 +100,7 @@ printk("reading %p len %d\n", addr, len); #include "../NCR5380.c" -static struct scsi_host_template oakscsi_template = { +static const struct scsi_host_template oakscsi_template = { .module = THIS_MODULE, .name = "Oak 16-bit SCSI", .info = oakscsi_info, diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 7586d2a03812..3b5991427886 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -279,7 +279,7 @@ powertecscsi_store_term(struct device *dev, struct device_attribute *attr, const static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR, powertecscsi_show_term, powertecscsi_store_term); -static struct scsi_host_template powertecscsi_template = { +static const struct scsi_host_template powertecscsi_template = { .module = THIS_MODULE, .show_info = powertecscsi_show_info, .write_info = powertecscsi_set_proc_info, diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 7143418d690f..2a748af269c2 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -40,7 +40,7 @@ #include "atp870u.h" -static struct scsi_host_template atp870u_template; +static const struct scsi_host_template atp870u_template; static void send_s870(struct atp_unit *dev,unsigned char c); static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode); @@ -1726,7 +1726,7 @@ static void atp870u_remove (struct pci_dev *pdev) } MODULE_LICENSE("GPL"); -static struct scsi_host_template atp870u_template = { +static const struct scsi_host_template atp870u_template = { .module = THIS_MODULE, .name = "atp870u" /* name */, .proc_name = "atp870u", diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 69b1a80e3687..0b59b63bce79 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -1173,7 +1173,6 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); int status; unsigned int curr_pages; - u32 internal_page_offset = 0; u32 temp_num_pages = num_pages; if (num_pages == 0xff) @@ -1192,7 +1191,6 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, req->page_offset = page_offset; be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem); q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE); - internal_page_offset += req->num_pages; page_offset += req->num_pages; num_pages -= req->num_pages; diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 50a577ac3bb4..e48f14ad6dfd 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -139,7 +139,7 @@ beiscsi_disp_param(_name)\ beiscsi_change_param(_name, _minval, _maxval, _defval)\ beiscsi_store_param(_name)\ beiscsi_init_param(_name, _minval, _maxval, _defval)\ -DEVICE_ATTR(beiscsi_##_name, S_IRUGO | S_IWUSR,\ +static DEVICE_ATTR(beiscsi_##_name, S_IRUGO | S_IWUSR,\ beiscsi_##_name##_disp, beiscsi_##_name##_store) /* @@ -155,14 +155,14 @@ BEISCSI_RW_ATTR(log_enable, 0x00, "\t\t\t\tConfiguration Path : 0x20\n" "\t\t\t\tiSCSI Protocol : 0x40\n"); -DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); -DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); -DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); -DEVICE_ATTR(beiscsi_phys_port, S_IRUGO, beiscsi_phys_port_disp, NULL); -DEVICE_ATTR(beiscsi_active_session_count, S_IRUGO, - beiscsi_active_session_disp, NULL); -DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, - beiscsi_free_session_disp, NULL); +static DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); +static DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); +static DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); +static DEVICE_ATTR(beiscsi_phys_port, S_IRUGO, beiscsi_phys_port_disp, NULL); +static DEVICE_ATTR(beiscsi_active_session_count, S_IRUGO, + beiscsi_active_session_disp, NULL); +static DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, + beiscsi_free_session_disp, NULL); static struct attribute *beiscsi_attrs[] = { &dev_attr_beiscsi_log_enable.attr, @@ -398,7 +398,7 @@ static const struct pci_device_id beiscsi_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); -static struct scsi_host_template beiscsi_sht = { +static const struct scsi_host_template beiscsi_sht = { .module = THIS_MODULE, .name = "Emulex 10Gbe open-iscsi Initiator Driver", .proc_name = DRV_NAME, @@ -5545,13 +5545,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto disable_pci; } - /* Enable EEH reporting */ - ret = pci_enable_pcie_error_reporting(pcidev); - if (ret) - beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, - "BM_%d : PCIe Error Reporting " - "Enabling Failed\n"); - pci_save_state(pcidev); /* Initialize Driver configuration Paramters */ @@ -5736,7 +5729,6 @@ free_hba: pci_disable_msix(phba->pcidev); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); - pci_disable_pcie_error_reporting(pcidev); pci_set_drvdata(pcidev, NULL); disable_pci: pci_release_regions(pcidev); @@ -5779,7 +5771,6 @@ static void beiscsi_remove(struct pci_dev *pcidev) pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); - pci_disable_pcie_error_reporting(pcidev); pci_set_drvdata(pcidev, NULL); pci_release_regions(pcidev); pci_disable_device(pcidev); diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 98977c0700f1..71c95d144560 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -16,7 +16,6 @@ #include <linux/in.h> #include <linux/ctype.h> #include <linux/module.h> -#include <linux/aer.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index e5aa982ffedc..529b73a83d69 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -738,9 +738,6 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad) goto out_release_region; } - /* Enable PCIE Advanced Error Recovery (AER) if kernel supports */ - pci_enable_pcie_error_reporting(pdev); - bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2)); @@ -801,8 +798,6 @@ bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad) pci_iounmap(pdev, bfad->pci_bar0_kva); pci_iounmap(pdev, bfad->pci_bar2_kva); pci_release_regions(pdev); - /* Disable PCIE Advanced Error Recovery (AER) */ - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); } @@ -1562,7 +1557,6 @@ bfad_pci_slot_reset(struct pci_dev *pdev) if (restart_bfa(bfad) == -1) goto out_disable_device; - pci_enable_pcie_error_reporting(pdev); dev_printk(KERN_WARNING, &pdev->dev, "slot_reset completed flags: 0x%x!\n", bfad->bfad_flags); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index eaee7c8bc2d2..7682cfa34265 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -30,7 +30,6 @@ #include <linux/vmalloc.h> #include <linux/workqueue.h> #include <linux/bitops.h> -#include <linux/aer.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index a3c800e04a2e..9971f32a663c 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -22,7 +22,7 @@ struct scsi_transport_template *bnx2i_scsi_xport_template; struct iscsi_transport bnx2i_iscsi_transport; -static struct scsi_host_template bnx2i_host_template; +static const struct scsi_host_template bnx2i_host_template; /* * Global endpoint resource info @@ -2250,7 +2250,7 @@ static umode_t bnx2i_attr_is_visible(int param_type, int param) * 'Scsi_Host_Template' structure and 'iscsi_tranport' structure template * used while registering with the scsi host and iSCSI transport module. */ -static struct scsi_host_template bnx2i_host_template = { +static const struct scsi_host_template bnx2i_host_template = { .module = THIS_MODULE, .name = "QLogic Offload iSCSI Initiator", .proc_name = "bnx2i", diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index ccbded3353bd..0c32faefad7c 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c @@ -38,7 +38,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/pci.h> -#include <linux/aer.h> #include <linux/mm.h> #include <linux/notifier.h> #include <linux/kdebug.h> diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index ff9d4287937a..ec6530240707 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -80,7 +80,7 @@ static struct cxgb3_client t3_client = { .event_handler = cxgb3i_dev_event_handler, }; -static struct scsi_host_template cxgb3i_host_template = { +static const struct scsi_host_template cxgb3i_host_template = { .module = THIS_MODULE, .name = DRV_MODULE_NAME, .proc_name = DRV_MODULE_NAME, diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index af281e271f88..eb47c8c96d0e 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -337,7 +337,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev) EXPORT_SYMBOL_GPL(cxgbi_hbas_remove); int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, - unsigned int max_conns, struct scsi_host_template *sht, + unsigned int max_conns, const struct scsi_host_template *sht, struct scsi_transport_template *stt) { struct cxgbi_hba *chba; diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index d8fc7beafa20..d92cf1dccc2f 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -591,7 +591,7 @@ struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *); struct cxgbi_device *cxgbi_device_find_by_netdev_rcu(struct net_device *, int *); int cxgbi_hbas_add(struct cxgbi_device *, u64, unsigned int, - struct scsi_host_template *, + const struct scsi_host_template *, struct scsi_transport_template *); void cxgbi_hbas_remove(struct cxgbi_device *); diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c index 22cfc2e1dfb9..e1b55b03e812 100644 --- a/drivers/scsi/cxlflash/superpipe.c +++ b/drivers/scsi/cxlflash/superpipe.c @@ -358,7 +358,7 @@ retry: dev_dbg(dev, "%s: %ssending cmd(%02x)\n", __func__, retry_cnt ? "re" : "", scsi_cmd[0]); - /* Drop the ioctl read semahpore across lengthy call */ + /* Drop the ioctl read semaphore across lengthy call */ up_read(&cfg->ioctl_rwsem); result = scsi_execute_cmd(sdev, scsi_cmd, REQ_OP_DRV_IN, cmd_buf, CMD_BUFSIZE, to, CMD_RETRIES, &exec_args); diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c index 9caabf550436..cbd5a648a131 100644 --- a/drivers/scsi/cxlflash/vlun.c +++ b/drivers/scsi/cxlflash/vlun.c @@ -448,7 +448,7 @@ static int write_same16(struct scsi_device *sdev, put_unaligned_be32(ws_limit < left ? ws_limit : left, &scsi_cmd[10]); - /* Drop the ioctl read semahpore across lengthy call */ + /* Drop the ioctl read semaphore across lengthy call */ up_read(&cfg->ioctl_rwsem); result = scsi_execute_cmd(sdev, scsi_cmd, REQ_OP_DRV_OUT, cmd_buf, CMD_BUFSIZE, to, diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 670a836a6ba1..c8e86f8a631e 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -4541,7 +4541,7 @@ static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host) } -static struct scsi_host_template dc395x_driver_template = { +static const struct scsi_host_template dc395x_driver_template = { .module = THIS_MODULE, .proc_name = DC395X_NAME, .show_info = dc395x_show_info, diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index a171ce6b70b2..dfb091d34363 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -39,7 +39,7 @@ #define DMX3191D_REGION_LEN 8 -static struct scsi_host_template dmx3191d_driver_template = { +static const struct scsi_host_template dmx3191d_driver_template = { .module = THIS_MODULE, .proc_name = DMX3191D_DRIVER_NAME, .name = "Domex DMX3191D", diff --git a/drivers/scsi/elx/efct/efct_lio.c b/drivers/scsi/elx/efct/efct_lio.c index be4b5c1ee32d..a982b9cf9870 100644 --- a/drivers/scsi/elx/efct/efct_lio.c +++ b/drivers/scsi/elx/efct/efct_lio.c @@ -285,11 +285,6 @@ efct_lio_npiv_check_prod_write_protect(struct se_portal_group *se_tpg) return tpg->tpg_attrib.prod_mode_write_protect; } -static u32 efct_lio_tpg_get_inst_index(struct se_portal_group *se_tpg) -{ - return 1; -} - static int efct_lio_check_stop_free(struct se_cmd *se_cmd) { struct efct_scsi_tgt_io *ocp = @@ -355,15 +350,6 @@ static void efct_lio_close_session(struct se_session *se_sess) efc_node_post_shutdown(node, NULL); } -static u32 efct_lio_sess_get_index(struct se_session *se_sess) -{ - return 0; -} - -static void efct_lio_set_default_node_attrs(struct se_node_acl *nacl) -{ -} - static int efct_lio_get_cmd_state(struct se_cmd *cmd) { struct efct_scsi_tgt_io *ocp = @@ -1607,14 +1593,11 @@ static const struct target_core_fabric_ops efct_lio_ops = { .tpg_check_demo_mode_cache = efct_lio_check_demo_mode_cache, .tpg_check_demo_mode_write_protect = efct_lio_check_demo_write_protect, .tpg_check_prod_mode_write_protect = efct_lio_check_prod_write_protect, - .tpg_get_inst_index = efct_lio_tpg_get_inst_index, .check_stop_free = efct_lio_check_stop_free, .aborted_task = efct_lio_aborted_task, .release_cmd = efct_lio_release_cmd, .close_session = efct_lio_close_session, - .sess_get_index = efct_lio_sess_get_index, .write_pending = efct_lio_write_pending, - .set_default_node_attributes = efct_lio_set_default_node_attrs, .get_cmd_state = efct_lio_get_cmd_state, .queue_data_in = efct_lio_queue_data_in, .queue_status = efct_lio_queue_status, @@ -1644,14 +1627,11 @@ static const struct target_core_fabric_ops efct_lio_npiv_ops = { efct_lio_npiv_check_demo_write_protect, .tpg_check_prod_mode_write_protect = efct_lio_npiv_check_prod_write_protect, - .tpg_get_inst_index = efct_lio_tpg_get_inst_index, .check_stop_free = efct_lio_check_stop_free, .aborted_task = efct_lio_aborted_task, .release_cmd = efct_lio_release_cmd, .close_session = efct_lio_close_session, - .sess_get_index = efct_lio_sess_get_index, .write_pending = efct_lio_write_pending, - .set_default_node_attributes = efct_lio_set_default_node_attrs, .get_cmd_state = efct_lio_get_cmd_state, .queue_data_in = efct_lio_queue_data_in, .queue_status = efct_lio_queue_status, diff --git a/drivers/scsi/elx/efct/efct_xport.c b/drivers/scsi/elx/efct/efct_xport.c index 9495cedcc0b9..cf4dced20b8b 100644 --- a/drivers/scsi/elx/efct/efct_xport.c +++ b/drivers/scsi/elx/efct/efct_xport.c @@ -10,7 +10,7 @@ static struct dentry *efct_debugfs_root; static atomic_t efct_debugfs_count; -static struct scsi_host_template efct_template = { +static const struct scsi_host_template efct_template = { .module = THIS_MODULE, .name = EFCT_DRIVER_NAME, .supported_mode = MODE_TARGET, diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index d7a2c49ff5ee..f700a16cd885 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -231,7 +231,7 @@ struct bin_attribute bin_attr_default_nvram = { .write = NULL }; -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .show_info = esas2r_show_info, .name = ESAS2R_LONGNAME, diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 64ec6bb84550..97816a0e6240 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2660,7 +2660,7 @@ static const char *esp_info(struct Scsi_Host *host) return "esp"; } -struct scsi_host_template scsi_esp_template = { +const struct scsi_host_template scsi_esp_template = { .module = THIS_MODULE, .name = "esp", .info = esp_info, diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index c73760d3cf83..00cd7c0ccc76 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h @@ -572,7 +572,7 @@ struct esp { * 13) Check scsi_esp_register() return value, release all resources * if an error was returned. */ -extern struct scsi_host_template scsi_esp_template; +extern const struct scsi_host_template scsi_esp_template; extern int scsi_esp_register(struct esp *); extern void scsi_esp_unregister(struct esp *); diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 38774a272e62..f1429f270170 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -260,7 +260,7 @@ static struct fc_function_template fcoe_vport_fc_functions = { .bsg_request = fc_lport_bsg_request, }; -static struct scsi_host_template fcoe_shost_template = { +static const struct scsi_host_template fcoe_shost_template = { .module = THIS_MODULE, .name = "FCoE Driver", .proc_name = FCOE_NAME, diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 444eac9b2466..504c4e0c5d17 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -496,7 +496,7 @@ static int fdomain_biosparam(struct scsi_device *sdev, return 0; } -static struct scsi_host_template fdomain_template = { +static const struct scsi_host_template fdomain_template = { .module = THIS_MODULE, .name = "Future Domain TMC-16x0", .proc_name = "fdomain", diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 1077110ab273..984bc5fc55e2 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -95,7 +95,7 @@ static int fnic_slave_alloc(struct scsi_device *sdev) return 0; } -static struct scsi_host_template fnic_host_template = { +static const struct scsi_host_template fnic_host_template = { .module = THIS_MODULE, .name = DRV_NAME, .queuecommand = fnic_queuecommand, diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index e03967463561..f3c3a26a1384 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -781,28 +781,21 @@ void copy_and_format_trace_data(struct fc_trace_hdr *tdata, fnic_dbgfs_t *fnic_dbgfs_prt, int *orig_len, u8 rdata_flag) { - struct tm tm; int j, i = 1, len; - char *fc_trace, *fmt; int ethhdr_len = sizeof(struct ethhdr) - 1; int fcoehdr_len = sizeof(struct fcoe_hdr); int fchdr_len = sizeof(struct fc_frame_header); int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3; + char *fc_trace; tdata->frame_type = tdata->frame_type & 0x7F; len = *orig_len; - time64_to_tm(tdata->time_stamp.tv_sec, 0, &tm); - - fmt = "%02d:%02d:%04ld %02d:%02d:%02d.%09lu ns%8x %c%8x\t"; - len += scnprintf(fnic_dbgfs_prt->buffer + len, - max_size - len, - fmt, - tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, - tm.tm_hour, tm.tm_min, tm.tm_sec, - tdata->time_stamp.tv_nsec, tdata->host_no, - tdata->frame_type, tdata->frame_len); + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, + "%ptTs.%09lu ns%8x %c%8x\t", + &tdata->time_stamp.tv_sec, tdata->time_stamp.tv_nsec, + tdata->host_no, tdata->frame_type, tdata->frame_len); fc_trace = (char *)FC_TRACE_ADDRESS(tdata); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 0c768e7d06b9..f6305e3e60f4 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -219,7 +219,7 @@ static int hp_c2502_irqs[] = { 9, 5, 7, 3, 4, -1 }; -static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, +static int generic_NCR5380_init_one(const struct scsi_host_template *tpnt, struct device *pdev, int base, int irq, int board) { bool is_pmio = base <= 0xffff; @@ -689,7 +689,7 @@ static int generic_NCR5380_dma_residual(struct NCR5380_hostdata *hostdata) #include "NCR5380.c" -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .proc_name = DRV_MODULE_NAME, .name = "Generic NCR5380/NCR53C400 SCSI", diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 7d56a236a011..d2eddad099a2 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -222,7 +222,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static struct scsi_host_template gvp11_scsi_template = { +static const struct scsi_host_template gvp11_scsi_template = { .module = THIS_MODULE, .name = "GVP Series II SCSI", .show_info = wd33c93_show_info, diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 6f8a52a1b808..fb7c52c119df 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -207,6 +207,7 @@ struct hisi_sas_cq { int rd_point; int id; int irq_no; + spinlock_t poll_lock; }; struct hisi_sas_dq { @@ -344,7 +345,7 @@ struct hisi_sas_hw { int delay_ms, int timeout_ms); void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba); int complete_hdr_size; - struct scsi_host_template *sht; + const struct scsi_host_template *sht; }; #define HISI_SAS_MAX_DEBUGFS_DUMP (50) @@ -484,6 +485,8 @@ struct hisi_hba { struct dentry *debugfs_dump_dentry; struct dentry *debugfs_bist_dentry; struct dentry *debugfs_fifo_dentry; + + int iopoll_q_cnt; }; /* Generic HW DMA host memory structures */ @@ -653,16 +656,18 @@ extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy, extern void hisi_sas_phy_bcast(struct hisi_sas_phy *phy); extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, - struct hisi_sas_slot *slot); + struct hisi_sas_slot *slot, + bool need_lock); extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba); extern void hisi_sas_rst_work_handler(struct work_struct *work); extern void hisi_sas_sync_rst_work_handler(struct work_struct *work); -extern void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba); extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no); extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, enum hisi_sas_phy_event event); extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba); extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max); +extern void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba); +extern void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba); extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba); extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba); #endif diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 8c038ccf1c09..412431c901a7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -205,7 +205,7 @@ static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, } void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, - struct hisi_sas_slot *slot) + struct hisi_sas_slot *slot, bool need_lock) { int device_id = slot->device_id; struct hisi_sas_device *sas_dev = &hisi_hba->devices[device_id]; @@ -239,9 +239,13 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, } } - spin_lock(&sas_dev->lock); - list_del_init(&slot->entry); - spin_unlock(&sas_dev->lock); + if (need_lock) { + spin_lock(&sas_dev->lock); + list_del_init(&slot->entry); + spin_unlock(&sas_dev->lock); + } else { + list_del_init(&slot->entry); + } memset(slot, 0, offsetof(struct hisi_sas_slot, buf)); @@ -529,10 +533,21 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) dq_index = blk_mq_unique_tag_to_hwq(blk_tag); dq = &hisi_hba->dq[dq_index]; } else { - struct Scsi_Host *shost = hisi_hba->shost; - struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; - int queue = qmap->mq_map[raw_smp_processor_id()]; + int queue; + + if (hisi_hba->iopoll_q_cnt) { + /* + * Use interrupt queue (queue 0) to deliver and complete + * internal IOs of libsas or libata when there is at least + * one iopoll queue + */ + queue = 0; + } else { + struct Scsi_Host *shost = hisi_hba->shost; + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; + queue = qmap->mq_map[raw_smp_processor_id()]; + } dq = &hisi_hba->dq[queue]; } break; @@ -672,6 +687,55 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) return sas_dev; } +static void hisi_sas_sync_poll_cq(struct hisi_sas_cq *cq) +{ + /* make sure CQ entries being processed are processed to completion */ + spin_lock(&cq->poll_lock); + spin_unlock(&cq->poll_lock); +} + +static bool hisi_sas_queue_is_poll(struct hisi_sas_cq *cq) +{ + struct hisi_hba *hisi_hba = cq->hisi_hba; + + if (cq->id < hisi_hba->queue_count - hisi_hba->iopoll_q_cnt) + return false; + return true; +} + +static void hisi_sas_sync_cq(struct hisi_sas_cq *cq) +{ + if (hisi_sas_queue_is_poll(cq)) + hisi_sas_sync_poll_cq(cq); + else + synchronize_irq(cq->irq_no); +} + +void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba) +{ + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; + + if (hisi_sas_queue_is_poll(cq)) + hisi_sas_sync_poll_cq(cq); + } +} +EXPORT_SYMBOL_GPL(hisi_sas_sync_poll_cqs); + +void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba) +{ + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; + + hisi_sas_sync_cq(cq); + } +} +EXPORT_SYMBOL_GPL(hisi_sas_sync_cqs); + static void hisi_sas_tmf_aborted(struct sas_task *task) { struct hisi_sas_slot *slot = task->lldd_task; @@ -683,10 +747,10 @@ static void hisi_sas_tmf_aborted(struct sas_task *task) struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue]; /* - * sync irq to avoid free'ing task + * sync irq or poll queue to avoid free'ing task * before using task in IO completion */ - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); slot->task = NULL; } } @@ -1021,7 +1085,7 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy) } static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, struct sas_task *task, - struct hisi_sas_slot *slot) + struct hisi_sas_slot *slot, bool need_lock) { if (task) { unsigned long flags; @@ -1038,7 +1102,7 @@ static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, struct sas_task spin_unlock_irqrestore(&task->task_state_lock, flags); } - hisi_sas_slot_task_free(hisi_hba, task, slot); + hisi_sas_slot_task_free(hisi_hba, task, slot, need_lock); } static void hisi_sas_release_task(struct hisi_hba *hisi_hba, @@ -1047,8 +1111,11 @@ static void hisi_sas_release_task(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, *slot2; struct hisi_sas_device *sas_dev = device->lldd_dev; + spin_lock(&sas_dev->lock); list_for_each_entry_safe(slot, slot2, &sas_dev->list, entry) - hisi_sas_do_release_task(hisi_hba, slot->task, slot); + hisi_sas_do_release_task(hisi_hba, slot->task, slot, false); + + spin_unlock(&sas_dev->lock); } void hisi_sas_release_tasks(struct hisi_hba *hisi_hba) @@ -1453,13 +1520,41 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba) } EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_prepare); +static void hisi_sas_async_init_wait_phyup(void *data, async_cookie_t cookie) +{ + struct hisi_sas_phy *phy = data; + struct hisi_hba *hisi_hba = phy->hisi_hba; + struct device *dev = hisi_hba->dev; + DECLARE_COMPLETION_ONSTACK(completion); + int phy_no = phy->sas_phy.id; + + phy->reset_completion = &completion; + hisi_sas_phy_enable(hisi_hba, phy_no, 1); + if (!wait_for_completion_timeout(&completion, + HISI_SAS_WAIT_PHYUP_TIMEOUT)) + dev_warn(dev, "phy%d wait phyup timed out\n", phy_no); + + phy->reset_completion = NULL; +} + void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) { struct Scsi_Host *shost = hisi_hba->shost; + ASYNC_DOMAIN_EXCLUSIVE(async); + int phy_no; /* Init and wait for PHYs to come up and all libsas event finished. */ - hisi_hba->hw->phys_init(hisi_hba); - msleep(1000); + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + + if (!(hisi_hba->phy_state & BIT(phy_no))) + continue; + + async_schedule_domain(hisi_sas_async_init_wait_phyup, + phy, &async); + } + + async_synchronize_full_domain(&async); hisi_sas_refresh_port_id(hisi_hba); clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); @@ -1540,11 +1635,11 @@ static int hisi_sas_abort_task(struct sas_task *task) if (slot) { /* - * sync irq to avoid free'ing task + * sync irq or poll queue to avoid free'ing task * before using task in IO completion */ cq = &hisi_hba->cq[slot->dlvry_queue]; - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); } spin_unlock_irqrestore(&task->task_state_lock, flags); rc = TMF_RESP_FUNC_COMPLETE; @@ -1574,7 +1669,7 @@ static int hisi_sas_abort_task(struct sas_task *task) */ if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) { if (task->lldd_task) - hisi_sas_do_release_task(hisi_hba, task, slot); + hisi_sas_do_release_task(hisi_hba, task, slot, true); } } else if (task->task_proto & SAS_PROTOCOL_SATA || task->task_proto & SAS_PROTOCOL_STP) { @@ -1594,7 +1689,7 @@ static int hisi_sas_abort_task(struct sas_task *task) */ if ((sas_dev->dev_status == HISI_SAS_DEV_NCQ_ERR) && qc && qc->scsicmd) { - hisi_sas_do_release_task(hisi_hba, task, slot); + hisi_sas_do_release_task(hisi_hba, task, slot, true); rc = TMF_RESP_FUNC_COMPLETE; } else { rc = hisi_sas_softreset_ata_disk(device); @@ -1611,10 +1706,10 @@ static int hisi_sas_abort_task(struct sas_task *task) if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) && task->lldd_task) { /* - * sync irq to avoid free'ing task + * sync irq or poll queue to avoid free'ing task * before using task in IO completion */ - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); slot->task = NULL; } } @@ -1885,10 +1980,10 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task, struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue]; /* - * sync irq to avoid free'ing task + * sync irq or poll queue to avoid free'ing task * before using task in IO completion */ - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); slot->task = NULL; } @@ -1992,18 +2087,6 @@ void hisi_sas_phy_bcast(struct hisi_sas_phy *phy) } EXPORT_SYMBOL_GPL(hisi_sas_phy_bcast); -void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba) -{ - int i; - - for (i = 0; i < hisi_hba->cq_nvecs; i++) { - struct hisi_sas_cq *cq = &hisi_hba->cq[i]; - - synchronize_irq(cq->irq_no); - } -} -EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs); - int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type) { struct hisi_hba *hisi_hba = shost_priv(shost); @@ -2101,6 +2184,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) /* Completion queue structure */ cq->id = i; cq->hisi_hba = hisi_hba; + spin_lock_init(&cq->poll_lock); /* Delivery queue structure */ spin_lock_init(&dq->lock); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index d643c5a49aa9..0aa8c9c88535 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1258,7 +1258,11 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, slot_err_v1_hw(hisi_hba, task, slot); if (unlikely(slot->abort)) { - sas_task_abort(task); + if (dev_is_sata(device) && task->ata_task.use_ncq) + sas_ata_device_link_abort(device, true); + else + sas_task_abort(task); + return; } goto out; @@ -1306,7 +1310,7 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, } out: - hisi_sas_slot_task_free(hisi_hba, task, slot); + hisi_sas_slot_task_free(hisi_hba, task, slot, true); if (task->task_done) task->task_done(task); @@ -1735,7 +1739,7 @@ static struct attribute *host_v1_hw_attrs[] = { ATTRIBUTE_GROUPS(host_v1_hw); -static struct scsi_host_template sht_v1_hw = { +static const struct scsi_host_template sht_v1_hw = { .name = DRV_NAME, .proc_name = DRV_NAME, .module = THIS_MODULE, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cded42f4ca44..cd78e4c983aa 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2404,7 +2404,11 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba, error_info[2], error_info[3]); if (unlikely(slot->abort)) { - sas_task_abort(task); + if (dev_is_sata(device) && task->ata_task.use_ncq) + sas_ata_device_link_abort(device, true); + else + sas_task_abort(task); + return; } goto out; @@ -2462,7 +2466,7 @@ out: } task->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&task->task_state_lock, flags); - hisi_sas_slot_task_free(hisi_hba, task, slot); + hisi_sas_slot_task_free(hisi_hba, task, slot, true); if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) { spin_lock_irqsave(&device->done_lock, flags); @@ -3551,7 +3555,7 @@ static void map_queues_v2_hw(struct Scsi_Host *shost) } } -static struct scsi_host_template sht_v2_hw = { +static const struct scsi_host_template sht_v2_hw = { .name = DRV_NAME, .proc_name = DRV_NAME, .module = THIS_MODULE, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index a63279f55d09..12d588454f5d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -552,6 +552,11 @@ static int prot_mask; module_param(prot_mask, int, 0444); MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=0x0 "); +/* the index of iopoll queues are bigger than interrupt queues' */ +static int experimental_iopoll_q_cnt; +module_param(experimental_iopoll_q_cnt, int, 0444); +MODULE_PARM_DESC(experimental_iopoll_q_cnt, "number of queues to be used as poll mode, def=0"); + static void debugfs_work_handler_v3_hw(struct work_struct *work); static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba); @@ -599,6 +604,27 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, readl_poll_timeout_atomic(regs, val, cond, delay_us, timeout_us);\ }) +static void interrupt_enable_v3_hw(struct hisi_hba *hisi_hba) +{ + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) + hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); + + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffc220ff); + hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0x155555); + + for (i = 0; i < hisi_hba->n_phy; i++) { + hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xf2057fff); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe); + hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0); + hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0); + hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0); + } +} + static void init_reg_v3_hw(struct hisi_hba *hisi_hba) { int i, j; @@ -619,20 +645,14 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, ENT_INT_SRC1, 0xffffffff); hisi_sas_write32(hisi_hba, ENT_INT_SRC2, 0xffffffff); hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffc220ff); hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0); hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0); hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0); - hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0x155555); hisi_sas_write32(hisi_hba, AWQOS_AWCACHE_CFG, 0xf0f0); hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0); - for (i = 0; i < hisi_hba->queue_count; i++) - hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); - hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + interrupt_enable_v3_hw(hisi_hba); for (i = 0; i < hisi_hba->n_phy; i++) { enum sas_linkrate max; struct hisi_sas_phy *phy = &hisi_hba->phy[i]; @@ -655,13 +675,8 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000); - hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xf2057fff); - hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe); hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0); - hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0); - hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0); - hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1); hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120); hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01); @@ -883,6 +898,7 @@ static void dereg_device_v3_hw(struct hisi_hba *hisi_hba, cfg_abt_set_query_iptt = hisi_sas_read32(hisi_hba, CFG_ABT_SET_QUERY_IPTT); + spin_lock(&sas_dev->lock); list_for_each_entry_safe(slot, slot2, &sas_dev->list, entry) { cfg_abt_set_query_iptt &= ~CFG_SET_ABORTED_IPTT_MSK; cfg_abt_set_query_iptt |= (1 << CFG_SET_ABORTED_EN_OFF) | @@ -890,6 +906,7 @@ static void dereg_device_v3_hw(struct hisi_hba *hisi_hba, hisi_sas_write32(hisi_hba, CFG_ABT_SET_QUERY_IPTT, cfg_abt_set_query_iptt); } + spin_unlock(&sas_dev->lock); cfg_abt_set_query_iptt &= ~(1 << CFG_SET_ABORTED_EN_OFF); hisi_sas_write32(hisi_hba, CFG_ABT_SET_QUERY_IPTT, cfg_abt_set_query_iptt); @@ -2320,7 +2337,11 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, error_info[0], error_info[1], error_info[2], error_info[3]); if (unlikely(slot->abort)) { - sas_task_abort(task); + if (dev_is_sata(device) && task->ata_task.use_ncq) + sas_ata_device_link_abort(device, true); + else + sas_task_abort(task); + return; } goto out; @@ -2374,7 +2395,7 @@ out: } task->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&task->task_state_lock, flags); - hisi_sas_slot_task_free(hisi_hba, task, slot); + hisi_sas_slot_task_free(hisi_hba, task, slot, true); if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) { spin_lock_irqsave(&device->done_lock, flags); @@ -2391,23 +2412,25 @@ out: task->task_done(task); } -static irqreturn_t cq_thread_v3_hw(int irq_no, void *p) +static int complete_v3_hw(struct hisi_sas_cq *cq) { - struct hisi_sas_cq *cq = p; - struct hisi_hba *hisi_hba = cq->hisi_hba; - struct hisi_sas_slot *slot; struct hisi_sas_complete_v3_hdr *complete_queue; - u32 rd_point = cq->rd_point, wr_point; + struct hisi_hba *hisi_hba = cq->hisi_hba; + u32 rd_point, wr_point; int queue = cq->id; + int completed; + rd_point = cq->rd_point; complete_queue = hisi_hba->complete_hdr[queue]; wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + (0x14 * queue)); + completed = (wr_point + HISI_SAS_QUEUE_SLOTS - rd_point) % HISI_SAS_QUEUE_SLOTS; while (rd_point != wr_point) { struct hisi_sas_complete_v3_hdr *complete_hdr; struct device *dev = hisi_hba->dev; + struct hisi_sas_slot *slot; u32 dw0, dw1, dw3; int iptt; @@ -2451,6 +2474,28 @@ static irqreturn_t cq_thread_v3_hw(int irq_no, void *p) cq->rd_point = rd_point; hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); + return completed; +} + +static int queue_complete_v3_hw(struct Scsi_Host *shost, unsigned int queue) +{ + struct hisi_hba *hisi_hba = shost_priv(shost); + struct hisi_sas_cq *cq = &hisi_hba->cq[queue]; + int completed; + + spin_lock(&cq->poll_lock); + completed = complete_v3_hw(cq); + spin_unlock(&cq->poll_lock); + + return completed; +} + +static irqreturn_t cq_thread_v3_hw(int irq_no, void *p) +{ + struct hisi_sas_cq *cq = p; + + complete_v3_hw(cq); + return IRQ_HANDLED; } @@ -2474,8 +2519,9 @@ static void hisi_sas_v3_free_vectors(void *data) static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba) { - int vectors; - int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi; + /* Allocate all MSI vectors to avoid re-insertion issue */ + int max_msi = HISI_SAS_MSI_COUNT_V3_HW; + int vectors, min_msi; struct Scsi_Host *shost = hisi_hba->shost; struct pci_dev *pdev = hisi_hba->pci_dev; struct irq_affinity desc = { @@ -2492,8 +2538,8 @@ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba) return -ENOENT; - hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW; - shost->nr_hw_queues = hisi_hba->cq_nvecs; + hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW - hisi_hba->iopoll_q_cnt; + shost->nr_hw_queues = hisi_hba->cq_nvecs + hisi_hba->iopoll_q_cnt; return devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev); } @@ -2625,7 +2671,7 @@ static int disable_host_v3_hw(struct hisi_hba *hisi_hba) u32 status, reg_val; int rc; - interrupt_disable_v3_hw(hisi_hba); + hisi_sas_sync_poll_cqs(hisi_hba); hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0); hisi_sas_stop_phys(hisi_hba); @@ -2655,6 +2701,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba) struct device *dev = hisi_hba->dev; int rc; + interrupt_disable_v3_hw(hisi_hba); rc = disable_host_v3_hw(hisi_hba); if (rc) { dev_err(dev, "soft reset: disable host failed rc=%d\n", rc); @@ -2823,6 +2870,18 @@ static ssize_t intr_coal_count_v3_hw_store(struct device *dev, } static DEVICE_ATTR_RW(intr_coal_count_v3_hw); +static ssize_t iopoll_q_cnt_v3_hw_show(struct device *dev, + struct device_attribute + *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct hisi_hba *hisi_hba = shost_priv(shost); + + return scnprintf(buf, PAGE_SIZE, "%u\n", + hisi_hba->iopoll_q_cnt); +} +static DEVICE_ATTR_RO(iopoll_q_cnt_v3_hw); + static int slave_configure_v3_hw(struct scsi_device *sdev) { struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev); @@ -2852,6 +2911,7 @@ static struct attribute *host_v3_hw_attrs[] = { &dev_attr_intr_conv_v3_hw.attr, &dev_attr_intr_coal_ticks_v3_hw.attr, &dev_attr_intr_coal_count_v3_hw.attr, + &dev_attr_iopoll_q_cnt_v3_hw.attr, NULL }; @@ -3038,7 +3098,7 @@ static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000); - hisi_sas_sync_irqs(hisi_hba); + hisi_sas_sync_cqs(hisi_hba); } static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba) @@ -3210,12 +3270,34 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) static void hisi_sas_map_queues(struct Scsi_Host *shost) { struct hisi_hba *hisi_hba = shost_priv(shost); - struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; + struct blk_mq_queue_map *qmap; + int i, qoff; + + for (i = 0, qoff = 0; i < shost->nr_maps; i++) { + qmap = &shost->tag_set.map[i]; + if (i == HCTX_TYPE_DEFAULT) { + qmap->nr_queues = hisi_hba->cq_nvecs; + } else if (i == HCTX_TYPE_POLL) { + qmap->nr_queues = hisi_hba->iopoll_q_cnt; + } else { + qmap->nr_queues = 0; + continue; + } - blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev, BASE_VECTORS_V3_HW); + /* At least one interrupt hardware queue */ + if (!qmap->nr_queues) + WARN_ON(i == HCTX_TYPE_DEFAULT); + qmap->queue_offset = qoff; + if (i == HCTX_TYPE_POLL) + blk_mq_map_queues(qmap); + else + blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev, + BASE_VECTORS_V3_HW); + qoff += qmap->nr_queues; + } } -static struct scsi_host_template sht_v3_hw = { +static const struct scsi_host_template sht_v3_hw = { .name = DRV_NAME, .proc_name = DRV_NAME, .module = THIS_MODULE, @@ -3244,6 +3326,7 @@ static struct scsi_host_template sht_v3_hw = { .tag_alloc_policy = BLK_TAG_ALLOC_RR, .host_reset = hisi_sas_host_reset, .host_tagset = 1, + .mq_poll = queue_complete_v3_hw, }; static const struct hisi_sas_hw hisi_sas_v3_hw = { @@ -3303,6 +3386,13 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) if (hisi_sas_get_fw_info(hisi_hba) < 0) goto err_out; + if (experimental_iopoll_q_cnt < 0 || + experimental_iopoll_q_cnt >= hisi_hba->queue_count) + dev_err(dev, "iopoll queue count %d cannot exceed or equal 16, using default 0\n", + experimental_iopoll_q_cnt); + else + hisi_hba->iopoll_q_cnt = experimental_iopoll_q_cnt; + if (hisi_sas_alloc(hisi_hba)) { hisi_sas_free(hisi_hba); goto err_out; @@ -4858,6 +4948,10 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) shost->max_cmd_len = 16; shost->can_queue = HISI_SAS_UNRESERVED_IPTT; shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; + if (hisi_hba->iopoll_q_cnt) + shost->nr_maps = 3; + else + shost->nr_maps = 1; sha->sas_ha_name = DRV_NAME; sha->dev = dev; @@ -4976,6 +5070,7 @@ static void hisi_sas_reset_prepare_v3_hw(struct pci_dev *pdev) set_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags); hisi_sas_controller_reset_prepare(hisi_hba); + interrupt_disable_v3_hw(hisi_hba); rc = disable_host_v3_hw(hisi_hba); if (rc) dev_err(dev, "FLR: disable host failed rc=%d\n", rc); @@ -5005,6 +5100,21 @@ enum { hip08, }; +static void enable_host_v3_hw(struct hisi_hba *hisi_hba) +{ + u32 reg_val; + + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, + (u32)((1ULL << hisi_hba->queue_count) - 1)); + + phys_init_v3_hw(hisi_hba); + reg_val = hisi_sas_read32(hisi_hba, AXI_MASTER_CFG_BASE + + AM_CTRL_GLOBAL); + reg_val &= ~AM_CTRL_SHUTDOWN_REQ_MSK; + hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE + + AM_CTRL_GLOBAL, reg_val); +} + static int _suspend_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); @@ -5027,14 +5137,20 @@ static int _suspend_v3_hw(struct device *device) scsi_block_requests(shost); set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); flush_workqueue(hisi_hba->wq); + interrupt_disable_v3_hw(hisi_hba); + +#ifdef CONFIG_PM + if (atomic_read(&device->power.usage_count)) { + dev_err(dev, "PM suspend: host status cannot be suspended\n"); + rc = -EBUSY; + goto err_out; + } +#endif rc = disable_host_v3_hw(hisi_hba); if (rc) { dev_err(dev, "PM suspend: disable host failed rc=%d\n", rc); - clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); - clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags); - scsi_unblock_requests(shost); - return rc; + goto err_out_recover_host; } hisi_sas_init_mem(hisi_hba); @@ -5045,6 +5161,17 @@ static int _suspend_v3_hw(struct device *device) dev_warn(dev, "end of suspending controller\n"); return 0; + +err_out_recover_host: + enable_host_v3_hw(hisi_hba); +#ifdef CONFIG_PM +err_out: +#endif + interrupt_enable_v3_hw(hisi_hba); + clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags); + scsi_unblock_requests(shost); + return rc; } static int _resume_v3_hw(struct device *device) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 9b6fbbe15d92..f0bc8bbb3938 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -219,7 +219,7 @@ EXPORT_SYMBOL(scsi_remove_host); int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, struct device *dma_dev) { - struct scsi_host_template *sht = shost->hostt; + const struct scsi_host_template *sht = shost->hostt; int error = -EINVAL; shost_printk(KERN_INFO, shost, "%s\n", @@ -389,7 +389,7 @@ static struct device_type scsi_host_type = { * Return value: * Pointer to a new Scsi_Host **/ -struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) +struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int privsize) { struct Scsi_Host *shost; int index; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f6da34850af9..af18d20f3079 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -967,7 +967,7 @@ ATTRIBUTE_GROUPS(hpsa_shost); #define HPSA_NRESERVED_CMDS (HPSA_CMDS_RESERVED_FOR_DRIVER +\ HPSA_MAX_CONCURRENT_PASSTHRUS) -static struct scsi_host_template hpsa_driver_template = { +static const struct scsi_host_template hpsa_driver_template = { .module = THIS_MODULE, .name = HPSA, .proc_name = HPSA, @@ -9108,7 +9108,6 @@ static void hpsa_remove_one(struct pci_dev *pdev) free_percpu(h->lockup_detected); /* init_one 2 */ h->lockup_detected = NULL; /* init_one 2 */ - /* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */ hpda_free_ctlr_info(h); /* init_one 1 */ } @@ -9476,8 +9475,6 @@ static void hpsa_free_performant_mode(struct ctlr_info *h) static int hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) { u32 trans_support; - unsigned long transMethod = CFGTBL_Trans_Performant | - CFGTBL_Trans_use_short_tags; int i, rc; if (hpsa_simple_mode) @@ -9489,14 +9486,10 @@ static int hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) /* Check for I/O accelerator mode support */ if (trans_support & CFGTBL_Trans_io_accel1) { - transMethod |= CFGTBL_Trans_io_accel1 | - CFGTBL_Trans_enable_directed_msix; rc = hpsa_alloc_ioaccel1_cmd_and_bft(h); if (rc) return rc; } else if (trans_support & CFGTBL_Trans_io_accel2) { - transMethod |= CFGTBL_Trans_io_accel2 | - CFGTBL_Trans_enable_directed_msix; rc = hpsa_alloc_ioaccel2_cmd_and_bft(h); if (rc) return rc; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 7e8903718245..06ccb51bf6a9 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1159,7 +1159,7 @@ static int hptiop_slave_config(struct scsi_device *sdev) return 0; } -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = driver_name, .queuecommand = hptiop_queuecommand, diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 1a0c0b7289d2..ce9eb00e2ca0 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -3611,7 +3611,7 @@ static struct attribute *ibmvfc_host_attrs[] = { ATTRIBUTE_GROUPS(ibmvfc_host); -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "IBM POWER Virtual FC Adapter", .proc_name = IBMVFC_NAME, diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index e8770310a64b..385f812b8793 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -3698,16 +3698,6 @@ static int ibmvscsis_check_true(struct se_portal_group *se_tpg) return 1; } -static int ibmvscsis_check_false(struct se_portal_group *se_tpg) -{ - return 0; -} - -static u32 ibmvscsis_tpg_get_inst_index(struct se_portal_group *se_tpg) -{ - return 1; -} - static int ibmvscsis_check_stop_free(struct se_cmd *se_cmd) { return target_put_sess_cmd(se_cmd); @@ -3726,11 +3716,6 @@ static void ibmvscsis_release_cmd(struct se_cmd *se_cmd) spin_unlock_bh(&vscsi->intr_lock); } -static u32 ibmvscsis_sess_get_index(struct se_session *se_sess) -{ - return 0; -} - static int ibmvscsis_write_pending(struct se_cmd *se_cmd) { struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd, @@ -3765,15 +3750,6 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd) return 0; } -static void ibmvscsis_set_default_node_attrs(struct se_node_acl *nacl) -{ -} - -static int ibmvscsis_get_cmd_state(struct se_cmd *se_cmd) -{ - return 0; -} - static int ibmvscsis_queue_data_in(struct se_cmd *se_cmd) { struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd, @@ -3982,15 +3958,9 @@ static const struct target_core_fabric_ops ibmvscsis_ops = { .tpg_get_default_depth = ibmvscsis_get_default_depth, .tpg_check_demo_mode = ibmvscsis_check_true, .tpg_check_demo_mode_cache = ibmvscsis_check_true, - .tpg_check_demo_mode_write_protect = ibmvscsis_check_false, - .tpg_check_prod_mode_write_protect = ibmvscsis_check_false, - .tpg_get_inst_index = ibmvscsis_tpg_get_inst_index, .check_stop_free = ibmvscsis_check_stop_free, .release_cmd = ibmvscsis_release_cmd, - .sess_get_index = ibmvscsis_sess_get_index, .write_pending = ibmvscsis_write_pending, - .set_default_node_attributes = ibmvscsis_set_default_node_attrs, - .get_cmd_state = ibmvscsis_get_cmd_state, .queue_data_in = ibmvscsis_queue_data_in, .queue_status = ibmvscsis_queue_status, .queue_tm_rsp = ibmvscsis_queue_tm_rsp, diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 7a499d621c25..07db98161a03 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -1096,7 +1096,7 @@ static int imm_adjust_queue(struct scsi_device *device) return 0; } -static struct scsi_host_template imm_template = { +static const struct scsi_host_template imm_template = { .module = THIS_MODULE, .proc_name = "imm", .show_info = imm_show_info, diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 375261d67619..2a50fda3a628 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2788,7 +2788,7 @@ static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem) initio_release_scb(host, cblk); /* Release SCB for current channel */ } -static struct scsi_host_template initio_template = { +static const struct scsi_host_template initio_template = { .proc_name = "INI9100U", .name = "Initio INI-9X00U/UW SCSI device driver", .queuecommand = i91u_queuecommand, diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index c74053f0b72f..4d3c280a7360 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -6736,7 +6736,7 @@ static const char *ipr_ioa_info(struct Scsi_Host *host) return buffer; } -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "IPR", .info = ipr_ioa_info, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index e294d5d961eb..ac1e04b86d8f 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -149,7 +149,7 @@ static struct attribute *isci_host_attrs[] = { ATTRIBUTE_GROUPS(isci_host); -static struct scsi_host_template isci_sht = { +static const struct scsi_host_template isci_sht = { .module = THIS_MODULE, .name = DRV_NAME, diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 15f452908926..9637d4bc2bc9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -47,7 +47,7 @@ MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport; -static struct scsi_host_template iscsi_sw_tcp_sht; +static const struct scsi_host_template iscsi_sw_tcp_sht; static struct iscsi_transport iscsi_sw_tcp_transport; static unsigned int iscsi_max_lun = ~0; @@ -1071,7 +1071,7 @@ static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev) return 0; } -static struct scsi_host_template iscsi_sw_tcp_sht = { +static const struct scsi_host_template iscsi_sw_tcp_sht = { .module = THIS_MODULE, .name = "iSCSI Initiator over TCP/IP", .queuecommand = iscsi_queuecommand, diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index 60a88a95a8e2..0c842fb29aa0 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -104,7 +104,7 @@ static const struct esp_driver_ops jazz_esp_ops = { static int esp_jazz_probe(struct platform_device *dev) { - struct scsi_host_template *tpnt = &scsi_esp_template; + const struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; struct resource *res; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 127f3d7f19dc..0fda8905eabd 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2895,7 +2895,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_add); * This should be called by partial offload and software iscsi drivers. * To access the driver specific memory use the iscsi_host_priv() macro. */ -struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, +struct Scsi_Host *iscsi_host_alloc(const struct scsi_host_template *sht, int dd_data_size, bool xmit_can_sleep) { struct Scsi_Host *shost; diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 72fdb2e5d047..8c6afe724944 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -360,6 +360,33 @@ static void sas_destruct_ports(struct asd_sas_port *port) } } +static bool sas_abort_cmd(struct request *req, void *data) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req); + struct domain_device *dev = data; + + if (dev == cmd_to_domain_dev(cmd)) + blk_abort_request(req); + return true; +} + +static void sas_abort_device_scsi_cmds(struct domain_device *dev) +{ + struct sas_ha_struct *sas_ha = dev->port->ha; + struct Scsi_Host *shost = sas_ha->core.shost; + + if (dev_is_expander(dev->dev_type)) + return; + + /* + * For removed device with active IOs, the user space applications have + * to spend very long time waiting for the timeout. This is not + * necessary because a removed device will not return the IOs. + * Abort the inflight IOs here so that EH can be quickly kicked in. + */ + blk_mq_tagset_busy_iter(&shost->tag_set, sas_abort_cmd, dev); +} + void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) { if (!test_bit(SAS_DEV_DESTROY, &dev->state) && @@ -372,6 +399,8 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) } if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { + if (test_bit(SAS_DEV_GONE, &dev->state)) + sas_abort_device_scsi_cmds(dev); sas_rphy_unlink(dev->rphy); list_move_tail(&dev->disco_list_node, &port->destroy_list); } diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index cf55f8e3bd9f..5e3a93d13a91 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1036,7 +1036,6 @@ struct lpfc_hba { #define FCF_TS_INPROG 0x200 /* FCF table scan in progress */ #define FCF_RR_INPROG 0x400 /* FCF roundrobin flogi in progress */ #define HBA_FIP_SUPPORT 0x800 /* FIP support in HBA */ -#define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */ #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ #define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */ #define HBA_IOQ_FLUSH 0x8000 /* FCP/NVME I/O queues being flushed */ @@ -1190,7 +1189,6 @@ struct lpfc_hba { #define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_FCP #define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_FCP #endif - uint32_t cfg_aer_support; uint32_t cfg_sriov_nr_virtfn; uint32_t cfg_request_firmware_upgrade; uint32_t cfg_suppress_link_up; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 22f2e046e8eb..3863a5341782 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1644,6 +1644,12 @@ lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) !bf_get(lpfc_sliport_status_err, &portstat_reg)) return -EPERM; + /* There is no point to wait if the port is in an unrecoverable + * state. + */ + if (lpfc_sli4_unrecoverable_port(&portstat_reg)) + return -EIO; + /* wait for the SLI port firmware ready after firmware reset */ for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) { msleep(10); @@ -4365,13 +4371,22 @@ static DEVICE_ATTR_RW(lpfc_link_speed); /* # lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER) -# 0 = aer disabled or not supported # 1 = aer supported and enabled (default) -# Value range is [0,1]. Default value is 1. +# PCIe error reporting is always enabled by the PCI core, so this always +# shows 1. +# +# N.B. Parts of LPFC_ATTR open-coded since some of the underlying +# infrastructure (phba->cfg_aer_support) is gone. */ -LPFC_ATTR(aer_support, 1, 0, 1, - "Enable PCIe device AER support"); -lpfc_param_show(aer_support) +static uint lpfc_aer_support = 1; +module_param(lpfc_aer_support, uint, S_IRUGO); +MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support"); +static ssize_t +lpfc_aer_support_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", lpfc_aer_support); +} /** * lpfc_aer_support_store - Set the adapter for aer support @@ -4382,76 +4397,27 @@ lpfc_param_show(aer_support) * @count: unused variable. * * Description: - * If the val is 1 and currently the device's AER capability was not - * enabled, invoke the kernel's enable AER helper routine, trying to - * enable the device's AER capability. If the helper routine enabling - * AER returns success, update the device's cfg_aer_support flag to - * indicate AER is supported by the device; otherwise, if the device - * AER capability is already enabled to support AER, then do nothing. - * - * If the val is 0 and currently the device's AER support was enabled, - * invoke the kernel's disable AER helper routine. After that, update - * the device's cfg_aer_support flag to indicate AER is not supported - * by the device; otherwise, if the device AER capability is already - * disabled from supporting AER, then do nothing. + * PCIe error reporting is enabled by the PCI core, so drivers don't need + * to do anything. Retain this interface for backwards compatibility, + * but do nothing. * * Returns: - * length of the buf on success if val is in range the intended mode - * is supported. - * -EINVAL if val out of range or intended mode is not supported. + * length of the buf on success + * -EINVAL if val out of range **/ static ssize_t lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; - struct lpfc_hba *phba = vport->phba; - int val = 0, rc = -EINVAL; + int val = 0; if (!isdigit(buf[0])) return -EINVAL; if (sscanf(buf, "%i", &val) != 1) return -EINVAL; - switch (val) { - case 0: - if (phba->hba_flag & HBA_AER_ENABLED) { - rc = pci_disable_pcie_error_reporting(phba->pcidev); - if (!rc) { - spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~HBA_AER_ENABLED; - spin_unlock_irq(&phba->hbalock); - phba->cfg_aer_support = 0; - rc = strlen(buf); - } else - rc = -EPERM; - } else { - phba->cfg_aer_support = 0; - rc = strlen(buf); - } - break; - case 1: - if (!(phba->hba_flag & HBA_AER_ENABLED)) { - rc = pci_enable_pcie_error_reporting(phba->pcidev); - if (!rc) { - spin_lock_irq(&phba->hbalock); - phba->hba_flag |= HBA_AER_ENABLED; - spin_unlock_irq(&phba->hbalock); - phba->cfg_aer_support = 1; - rc = strlen(buf); - } else - rc = -EPERM; - } else { - phba->cfg_aer_support = 1; - rc = strlen(buf); - } - break; - default: - rc = -EINVAL; - break; - } - return rc; + dev_info_once(dev, "PCIe error reporting automatically enabled by the PCI core; sysfs write ignored\n"); + return strlen(buf); } static DEVICE_ATTR_RW(lpfc_aer_support); @@ -4464,16 +4430,16 @@ static DEVICE_ATTR_RW(lpfc_aer_support); * @count: unused variable. * * Description: - * If the @buf contains 1 and the device currently has the AER support - * enabled, then invokes the kernel AER helper routine + * If the @buf contains 1, invokes the kernel AER helper routine * pci_aer_clear_nonfatal_status() to clean up the uncorrectable * error status register. * * Notes: * * Returns: - * -EINVAL if the buf does not contain the 1 or the device is not currently - * enabled with the AER support. + * -EINVAL if the buf does not contain 1 + * -EPERM if the OS cannot clear AER error status, i.e., when platform + * firmware owns the AER Capability **/ static ssize_t lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, @@ -4491,8 +4457,7 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, if (val != 1) return -EINVAL; - if (phba->hba_flag & HBA_AER_ENABLED) - rc = pci_aer_clear_nonfatal_status(phba->pcidev); + rc = pci_aer_clear_nonfatal_status(phba->pcidev); if (rc == 0) return strlen(buf); @@ -7277,7 +7242,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); - lpfc_aer_support_init(phba, lpfc_aer_support); lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn); lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade); lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 852b025e2fec..9a322a3a2150 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2009-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -134,8 +134,8 @@ lpfc_free_bsg_buffers(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist) if (mlist) { list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) { - lpfc_mbuf_free(phba, mlast->virt, mlast->phys); list_del(&mlast->list); + lpfc_mbuf_free(phba, mlast->virt, mlast->phys); kfree(mlast); } lpfc_mbuf_free(phba, mlist->virt, mlist->phys); diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 976fd5ee7f7e..b833b983e69d 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -458,6 +458,8 @@ void lpfc_get_cfgparam(struct lpfc_hba *); void lpfc_get_vport_cfgparam(struct lpfc_vport *); int lpfc_alloc_sysfs_attr(struct lpfc_vport *); void lpfc_free_sysfs_attr(struct lpfc_vport *); +bool lpfc_error_lost_link(struct lpfc_vport *vport, u32 ulp_status, + u32 ulp_word4); extern const struct attribute_group *lpfc_hba_groups[]; extern const struct attribute_group *lpfc_vport_groups[]; extern struct scsi_host_template lpfc_template; diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index e941a99aa965..f3bdcebe67f5 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -476,8 +476,8 @@ lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist) struct lpfc_dmabuf *mlast, *next_mlast; list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) { - lpfc_mbuf_free(phba, mlast->virt, mlast->phys); list_del(&mlast->list); + lpfc_mbuf_free(phba, mlast->virt, mlast->phys); kfree(mlast); } lpfc_mbuf_free(phba, mlist->virt, mlist->phys); @@ -958,7 +958,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out; } - if (lpfc_error_lost_link(ulp_status, ulp_word4)) { + if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0226 NS query failed due to link event: " "ulp_status x%x ulp_word4 x%x fc_flag x%x " @@ -1181,7 +1181,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out; } - if (lpfc_error_lost_link(ulp_status, ulp_word4)) { + if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4166 NS query failed due to link event: " "ulp_status x%x ulp_word4 x%x fc_flag x%x " diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index f5252e45a48a..bdf34af4ef36 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2007-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -2157,10 +2157,13 @@ lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf, char mybuf[64]; char *pbuf; int i; + size_t bsize; memset(mybuf, 0, sizeof(mybuf)); - if (copy_from_user(mybuf, buf, nbytes)) + bsize = min(nbytes, (sizeof(mybuf) - 1)); + + if (copy_from_user(mybuf, buf, bsize)) return -EFAULT; pbuf = &mybuf[0]; @@ -2181,7 +2184,7 @@ lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf, qp->lock_conflict.wq_access = 0; } } - return nbytes; + return bsize; } #endif diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 35b252f1ef73..6a15f879e517 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1088,7 +1088,7 @@ stop_rr_fcf_flogi: } /* Do not register VFI if the driver aborted FLOGI */ - if (!lpfc_error_lost_link(ulp_status, ulp_word4)) + if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) lpfc_issue_reg_vfi(vport); lpfc_nlp_put(ndlp); @@ -1207,7 +1207,7 @@ flogifail: phba->fcf.fcf_flag &= ~FCF_DISCOVERY; spin_unlock_irq(&phba->hbalock); - if (!lpfc_error_lost_link(ulp_status, ulp_word4)) { + if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) { /* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); @@ -2087,7 +2087,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ulp_word4); /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if (!lpfc_error_lost_link(ulp_status, ulp_word4)) + if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_PLOGI); @@ -2208,14 +2208,15 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) * outstanding UNREG_RPI mbox command completes, unless we * are going offline. This logic does not apply for Fabric DIDs */ - if ((ndlp->nlp_flag & NLP_UNREG_INP) && + if ((ndlp->nlp_flag & (NLP_IGNR_REG_CMPL | NLP_UNREG_INP)) && ((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) && !(vport->fc_flag & FC_OFFLINE_MODE)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4110 Issue PLOGI x%x deferred " - "on NPort x%x rpi x%x Data: x%px\n", + "on NPort x%x rpi x%x flg x%x Data:" + " x%px\n", ndlp->nlp_defer_did, ndlp->nlp_DID, - ndlp->nlp_rpi, ndlp); + ndlp->nlp_rpi, ndlp->nlp_flag, ndlp); /* We can only defer 1st PLOGI */ if (ndlp->nlp_defer_did == NLP_EVT_NOTHING_PENDING) @@ -2382,7 +2383,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->fc4_prli_sent); /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if (!lpfc_error_lost_link(ulp_status, ulp_word4)) + if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI); @@ -3037,15 +3038,16 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_DID, ulp_status, ulp_word4); - if (lpfc_error_lost_link(ulp_status, ulp_word4)) { + if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) skip_recovery = 1; - goto out; - } } /* Call state machine. This will unregister the rpi if needed. */ lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); + if (skip_recovery) + goto out; + /* The driver sets this flag for an NPIV instance that doesn't want to * log into the remote port. */ @@ -4928,7 +4930,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if ((cmd == ELS_CMD_FLOGI) && (phba->fc_topology != LPFC_TOPOLOGY_LOOP) && - !lpfc_error_lost_link(ulp_status, ulp_word4)) { + !lpfc_error_lost_link(vport, ulp_status, ulp_word4)) { /* FLOGI retry policy */ retry = 1; /* retry FLOGI forever */ @@ -4942,7 +4944,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, else if (cmdiocb->retry >= 32) delay = 1000; } else if ((cmd == ELS_CMD_FDISC) && - !lpfc_error_lost_link(ulp_status, ulp_word4)) { + !lpfc_error_lost_link(vport, ulp_status, ulp_word4)) { /* retry FDISCs every second up to devloss */ retry = 1; maxretry = vport->cfg_devloss_tmo; @@ -5455,18 +5457,20 @@ out: * these conditions and release the RPI. */ if (phba->sli_rev == LPFC_SLI_REV4 && - (vport && vport->port_type == LPFC_NPIV_PORT) && - !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) && - ndlp->nlp_flag & NLP_RELEASE_RPI) { - if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE && - ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { - lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); - spin_lock_irq(&ndlp->lock); - ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; - ndlp->nlp_flag &= ~NLP_RELEASE_RPI; - spin_unlock_irq(&ndlp->lock); - lpfc_drop_node(vport, ndlp); + vport && vport->port_type == LPFC_NPIV_PORT && + !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) { + if (ndlp->nlp_flag & NLP_RELEASE_RPI) { + if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { + lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); + spin_lock_irq(&ndlp->lock); + ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; + ndlp->nlp_flag &= ~NLP_RELEASE_RPI; + spin_unlock_irq(&ndlp->lock); + } } + + lpfc_drop_node(vport, ndlp); } /* Release the originating I/O reference. */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 66cd0b1dbbd0..5ba3a9ad9501 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -5755,8 +5755,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) (NLP_FCP_TARGET | NLP_NVME_TARGET))) return NULL; - ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RECOVERY); spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; @@ -7269,3 +7269,38 @@ lpfc_parse_fcoe_conf(struct lpfc_hba *phba, lpfc_read_fcf_conn_tbl(phba, rec_ptr); } + +/* + * lpfc_error_lost_link - IO failure from link event or FW reset check. + * + * @vport: Pointer to lpfc_vport data structure. + * @ulp_status: IO completion status. + * @ulp_word4: Reason code for the ulp_status. + * + * This function evaluates the ulp_status and ulp_word4 values + * for specific error values that indicate an internal link fault + * or fw reset event for the completing IO. Callers require this + * common data to decide next steps on the IO. + * + * Return: + * false - No link or reset error occurred. + * true - A link or reset error occurred. + */ +bool +lpfc_error_lost_link(struct lpfc_vport *vport, u32 ulp_status, u32 ulp_word4) +{ + /* Mask off the extra port data to get just the reason code. */ + u32 rsn_code = IOERR_PARAM_MASK & ulp_word4; + + if (ulp_status == IOSTAT_LOCAL_REJECT && + (rsn_code == IOERR_SLI_ABORTED || + rsn_code == IOERR_LINK_DOWN || + rsn_code == IOERR_SLI_DOWN)) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI | LOG_ELS, + "0408 Report link error true: <x%x:x%x>\n", + ulp_status, ulp_word4); + return true; + } + + return false; +} diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 5c283936ff08..19b2d2754f32 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -4435,16 +4435,4 @@ lpfc_is_LC_HBA(unsigned short device) return 0; } -/* - * Determine if failed because of a link event or firmware reset. - */ -static inline int -lpfc_error_lost_link(u32 ulp_status, u32 ulp_word4) -{ - return (ulp_status == IOSTAT_LOCAL_REJECT && - (ulp_word4 == IOERR_SLI_ABORTED || - ulp_word4 == IOERR_LINK_DOWN || - ulp_word4 == IOERR_SLI_DOWN)); -} - #define BPL_ALIGN_SZ 8 /* 8 byte alignment for bpl and mbufs */ diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4f7485958c49..867b4c788f08 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -32,7 +32,6 @@ #include <linux/spinlock.h> #include <linux/sched/clock.h> #include <linux/ctype.h> -#include <linux/aer.h> #include <linux/slab.h> #include <linux/firmware.h> #include <linux/miscdevice.h> @@ -2148,7 +2147,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) /* fall through for not able to recover */ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3152 Unrecoverable error\n"); - phba->link_state = LPFC_HBA_ERROR; + lpfc_sli4_offline_eratt(phba); break; case LPFC_SLI_INTF_IF_TYPE_1: default: @@ -9569,8 +9568,7 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) /* Final checks. The port status should be clean. */ if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, ®_data.word0) || - (bf_get(lpfc_sliport_status_err, ®_data) && - !bf_get(lpfc_sliport_status_rn, ®_data))) { + lpfc_sli4_unrecoverable_port(®_data)) { phba->work_status[0] = readl(phba->sli4_hba.u.if_type2. ERR1regaddr); @@ -12026,7 +12024,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) goto out_iounmap_all; } else { error = -ENOMEM; - goto out_iounmap_all; + goto out_iounmap_ctrl; } } @@ -12044,7 +12042,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) dev_err(&pdev->dev, "ioremap failed for SLI4 HBA dpp registers.\n"); error = -ENOMEM; - goto out_iounmap_ctrl; + goto out_iounmap_all; } phba->pci_bar4_memmap_p = phba->sli4_hba.dpp_regs_memmap_p; } @@ -12069,9 +12067,11 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) return 0; out_iounmap_all: - iounmap(phba->sli4_hba.drbl_regs_memmap_p); + if (phba->sli4_hba.drbl_regs_memmap_p) + iounmap(phba->sli4_hba.drbl_regs_memmap_p); out_iounmap_ctrl: - iounmap(phba->sli4_hba.ctrl_regs_memmap_p); + if (phba->sli4_hba.ctrl_regs_memmap_p) + iounmap(phba->sli4_hba.ctrl_regs_memmap_p); out_iounmap_conf: iounmap(phba->sli4_hba.conf_regs_memmap_p); @@ -12107,6 +12107,7 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba) iounmap(phba->sli4_hba.dpp_regs_memmap_p); break; case LPFC_SLI_INTF_IF_TYPE_1: + break; default: dev_printk(KERN_ERR, &phba->pcidev->dev, "FATAL - unsupported SLI4 interface type - %d\n", diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 152245f7cacc..adda70423c77 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -2265,6 +2265,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, } if (!vport->localport || test_bit(HBA_PCI_ERR, &vport->phba->bit_flags) || + phba->link_state == LPFC_HBA_ERROR || vport->load_flag & FC_UNLOADING) return; @@ -2630,7 +2631,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * return values is ignored. The upcall is a courtesy to the * transport. */ - if (vport->load_flag & FC_UNLOADING) + if (vport->load_flag & FC_UNLOADING || + unlikely(vport->phba->link_state == LPFC_HBA_ERROR)) (void)nvme_fc_set_remoteport_devloss(remoteport, 0); ret = nvme_fc_unregister_remoteport(remoteport); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index cf630aa6734e..8693578888f1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -34,7 +34,6 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_transport_fc.h> #include <scsi/fc/fc_fs.h> -#include <linux/aer.h> #include <linux/crash_dump.h> #ifdef CONFIG_X86 #include <asm/set_memory.h> @@ -5204,13 +5203,9 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) volatile struct MAILBOX_word0 mb; struct lpfc_sli *psli; void __iomem *to_slim; - uint32_t hba_aer_enabled; spin_lock_irq(&phba->hbalock); - /* Take PCIe device Advanced Error Reporting (AER) state */ - hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED; - psli = &phba->sli; /* Restart HBA */ @@ -5251,10 +5246,6 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) /* Give the INITFF and Post time to settle. */ mdelay(100); - /* Reset HBA AER if it was enabled, note hba_flag was reset above */ - if (hba_aer_enabled) - pci_disable_pcie_error_reporting(phba->pcidev); - lpfc_hba_down_post(phba); return 0; @@ -5273,7 +5264,6 @@ static int lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) { struct lpfc_sli *psli = &phba->sli; - uint32_t hba_aer_enabled; int rc; /* Restart HBA */ @@ -5281,9 +5271,6 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) "0296 Restart HBA Data: x%x x%x\n", phba->pport->port_state, psli->sli_flag); - /* Take PCIe device Advanced Error Reporting (AER) state */ - hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED; - rc = lpfc_sli4_brdreset(phba); if (rc) { phba->link_state = LPFC_HBA_ERROR; @@ -5301,10 +5288,6 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets)); psli->stats_start = ktime_get_seconds(); - /* Reset HBA AER if it was enabled, note hba_flag was reset above */ - if (hba_aer_enabled) - pci_disable_pcie_error_reporting(phba->pcidev); - hba_down_queue: lpfc_hba_down_post(phba); lpfc_sli4_queue_destroy(phba); @@ -5725,25 +5708,6 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) } phba->fcp_embed_io = 0; /* SLI4 FC support only */ - /* Enable PCIe device Advanced Error Reporting (AER) if configured */ - if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) { - rc = pci_enable_pcie_error_reporting(phba->pcidev); - if (!rc) { - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "2709 This device supports " - "Advanced Error Reporting (AER)\n"); - spin_lock_irq(&phba->hbalock); - phba->hba_flag |= HBA_AER_ENABLED; - spin_unlock_irq(&phba->hbalock); - } else { - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "2708 This device does not support " - "Advanced Error Reporting (AER): %d\n", - rc); - phba->cfg_aer_support = 0; - } - } - if (phba->sli_rev == 3) { phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE; phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE; @@ -8080,16 +8044,16 @@ int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor, /** * lpfc_rx_monitor_destroy_ring - Free ring buffer for rx_monitor * @rx_monitor: Pointer to lpfc_rx_info_monitor object + * + * Called after cancellation of cmf_timer. **/ void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor) { - spin_lock(&rx_monitor->lock); kfree(rx_monitor->ring); rx_monitor->ring = NULL; rx_monitor->entries = 0; rx_monitor->head_idx = 0; rx_monitor->tail_idx = 0; - spin_unlock(&rx_monitor->lock); } /** @@ -9053,25 +9017,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) mod_timer(&phba->eratt_poll, jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval)); - /* Enable PCIe device Advanced Error Reporting (AER) if configured */ - if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) { - rc = pci_enable_pcie_error_reporting(phba->pcidev); - if (!rc) { - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "2829 This device supports " - "Advanced Error Reporting (AER)\n"); - spin_lock_irq(&phba->hbalock); - phba->hba_flag |= HBA_AER_ENABLED; - spin_unlock_irq(&phba->hbalock); - } else { - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "2830 This device does not support " - "Advanced Error Reporting (AER)\n"); - phba->cfg_aer_support = 0; - } - rc = 0; - } - /* * The port is ready, set the host's link state to LINK_DOWN * in preparation for link interrupts. @@ -9895,7 +9840,8 @@ lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba) * port for twice the regular mailbox command timeout value. * * 0 - no timeout on waiting for bootstrap mailbox register ready. - * MBXERR_ERROR - wait for bootstrap mailbox register timed out. + * MBXERR_ERROR - wait for bootstrap mailbox register timed out or port + * is in an unrecoverable state. **/ static int lpfc_sli4_wait_bmbx_ready(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) @@ -9903,6 +9849,23 @@ lpfc_sli4_wait_bmbx_ready(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) uint32_t db_ready; unsigned long timeout; struct lpfc_register bmbx_reg; + struct lpfc_register portstat_reg = {-1}; + + /* Sanity check - there is no point to wait if the port is in an + * unrecoverable state. + */ + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >= + LPFC_SLI_INTF_IF_TYPE_2) { + if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, + &portstat_reg.word0) || + lpfc_sli4_unrecoverable_port(&portstat_reg)) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3858 Skipping bmbx ready because " + "Port Status x%x\n", + portstat_reg.word0); + return MBXERR_ERROR; + } + } timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq) * 1000) + jiffies; @@ -22325,10 +22288,10 @@ lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba, /* Free sgl pool */ list_for_each_entry_safe(list_entry, tmp, buf_list, list_node) { + list_del(&list_entry->list_node); dma_pool_free(phba->lpfc_sg_dma_buf_pool, list_entry->dma_sgl, list_entry->dma_phys_sgl); - list_del(&list_entry->list_node); kfree(list_entry); } @@ -22475,10 +22438,10 @@ lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, list_for_each_entry_safe(list_entry, tmp, buf_list, list_node) { + list_del(&list_entry->list_node); dma_pool_free(phba->lpfc_cmd_rsp_buf_pool, list_entry->fcp_cmnd, list_entry->fcp_cmd_rsp_dma_handle); - list_del(&list_entry->list_node); kfree(list_entry); } diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 3b62c4032c31..2a0864e6d7cd 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -1180,3 +1180,22 @@ static inline void *lpfc_sli4_qe(struct lpfc_queue *q, uint16_t idx) return q->q_pgs[idx / q->entry_cnt_per_pg] + (q->entry_size * (idx % q->entry_cnt_per_pg)); } + +/** + * lpfc_sli4_unrecoverable_port - Check ERR and RN bits in portstat_reg + * @portstat_reg: portstat_reg pointer containing portstat_reg contents + * + * Description: + * Use only for SLI4 interface type-2 or later. If ERR is set && RN is 0, then + * port is deemed unrecoverable. + * + * Returns: + * true - ERR && !RN + * false - otherwise + */ +static inline bool +lpfc_sli4_unrecoverable_port(struct lpfc_register *portstat_reg) +{ + return bf_get(lpfc_sliport_status_err, portstat_reg) && + !bf_get(lpfc_sliport_status_rn, portstat_reg); +} diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 0238208cdd11..c97411b0992e 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.2.0.10" +#define LPFC_DRIVER_VERSION "14.2.0.11" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index f75928f7773e..6a019132109c 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -392,7 +392,7 @@ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd) mac53c94_priv(cmd)->this_residual = total; } -static struct scsi_host_template mac53c94_template = { +static const struct scsi_host_template mac53c94_template = { .proc_name = "53c94", .name = "53C94", .queuecommand = mac53c94_queue, diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 6d23ab5aee56..3f0061b00494 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -289,7 +289,7 @@ static struct esp_driver_ops mac_esp_ops = { static int esp_mac_probe(struct platform_device *dev) { - struct scsi_host_template *tpnt = &scsi_esp_template; + const struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; int err; diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index bf491af9f0d6..e92f1a73cc9b 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1441,6 +1441,7 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) */ if (cmdid == CMDID_INT_CMDS) { scb = &adapter->int_scb; + cmd = scb->cmd; list_del_init(&scb->list); scb->state = SCB_FREE; @@ -4100,7 +4101,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) return rval; } -static struct scsi_host_template megaraid_template = { +static const struct scsi_host_template megaraid_template = { .module = THIS_MODULE, .name = "MegaRAID", .proc_name = "megaraid_legacy", diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 132de68c14e9..ef2b6380e19a 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -325,7 +325,7 @@ ATTRIBUTE_GROUPS(megaraid_sdev); /* * Scsi host template for megaraid unified driver */ -static struct scsi_host_template megaraid_template_g = { +static const struct scsi_host_template megaraid_template_g = { .module = THIS_MODULE, .name = "LSI Logic MegaRAID driver", .proc_name = "megaraid", diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index c895189375e2..317c944c68e3 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3505,7 +3505,7 @@ ATTRIBUTE_GROUPS(megaraid_host); /* * Scsi host template for megaraid_sas driver */ -static struct scsi_host_template megasas_template = { +static const struct scsi_host_template megasas_template = { .module = THIS_MODULE, .name = "Avago SAS based MegaRAID driver", diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 84b541a57b7b..e276583c590c 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1830,7 +1830,7 @@ static int mesh_shutdown(struct macio_dev *mdev) return 0; } -static struct scsi_host_template mesh_template = { +static const struct scsi_host_template mesh_template = { .proc_name = "mesh", .name = "MESH", .queuecommand = mesh_queue, diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index 0a2af48915a5..2fc196499c89 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2017-2022 Broadcom Inc. All rights reserved. + * Copyright 2017-2023 Broadcom Inc. All rights reserved. */ #ifndef MPI30_CNFG_H #define MPI30_CNFG_H 1 @@ -63,8 +63,9 @@ #define MPI3_PCIE_LINK_PGAD_LINKNUM_MASK (0x000000ff) #define MPI3_SECURITY_PGAD_FORM_MASK (0xf0000000) #define MPI3_SECURITY_PGAD_FORM_GET_NEXT_SLOT (0x00000000) -#define MPI3_SECURITY_PGAD_FORM_SOT_NUM (0x10000000) +#define MPI3_SECURITY_PGAD_FORM_SLOT_NUM (0x10000000) #define MPI3_SECURITY_PGAD_SLOT_GROUP_MASK (0x0000ff00) +#define MPI3_SECURITY_PGAD_SLOT_GROUP_SHIFT (8) #define MPI3_SECURITY_PGAD_SLOT_MASK (0x000000ff) struct mpi3_config_request { __le16 host_tag; @@ -135,7 +136,6 @@ struct mpi3_config_page_header { #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_ACTIVE (0x00000000) #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_PARTIAL (0x08000000) #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_SLUMBER (0x10000000) -#define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_SHIFT (0) #define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_CHANGED_MASK (0x04000000) #define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_CHANGED_SHIFT (26) #define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT_MASK (0x02000000) @@ -201,6 +201,11 @@ struct mpi3_config_page_header { #define MPI3_TEMP_SENSOR_LOCATION_DRAM (0x3) #define MPI3_MFGPAGE_VENDORID_BROADCOM (0x1000) #define MPI3_MFGPAGE_DEVID_SAS4116 (0x00a5) +#define MPI3_MFGPAGE_DEVID_SAS5116_MPI (0x00b3) +#define MPI3_MFGPAGE_DEVID_SAS5116_NVME (0x00b4) +#define MPI3_MFGPAGE_DEVID_SAS5116_MPI_MGMT (0x00b5) +#define MPI3_MFGPAGE_DEVID_SAS5116_NVME_MGMT (0x00b6) +#define MPI3_MFGPAGE_DEVID_SAS5116_PCIE_SWITCH (0x00b8) struct mpi3_man_page0 { struct mpi3_config_page_header header; u8 chip_revision[8]; @@ -466,7 +471,7 @@ struct mpi3_man_page9 { #define MPI3_MAN9_PAGEVERSION (0x00) struct mpi3_man10_istwi_ctrlr_entry { - __le16 slave_address; + __le16 target_address; __le16 flags; u8 scl_low_override; u8 scl_high_override; @@ -476,8 +481,8 @@ struct mpi3_man10_istwi_ctrlr_entry { #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_MASK (0x000c) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_100K (0x0000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_400K (0x0004) -#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_SLAVE_ENABLED (0x0002) -#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_MASTER_ENABLED (0x0001) +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_TARGET_ENABLED (0x0002) +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_INITIATOR_ENABLED (0x0001) #ifndef MPI3_MAN10_ISTWI_CTRLR_MAX #define MPI3_MAN10_ISTWI_CTRLR_MAX (1) #endif @@ -1160,7 +1165,7 @@ struct mpi3_io_unit_page12 { struct mpi3_iounit13_allowed_function { __le16 sub_function; u8 function_code; - u8 fuction_flags; + u8 function_flags; }; #define MPI3_IOUNIT13_FUNCTION_FLAGS_ADMIN_BLOCKED (0x04) #define MPI3_IOUNIT13_FUNCTION_FLAGS_OOB_BLOCKED (0x02) @@ -1176,6 +1181,48 @@ struct mpi3_io_unit_page13 { #define MPI3_IOUNIT13_PAGEVERSION (0x00) #define MPI3_IOUNIT13_FLAGS_ADMIN_BLOCKED (0x0002) #define MPI3_IOUNIT13_FLAGS_OOB_BLOCKED (0x0001) +#ifndef MPI3_IOUNIT14_MD_MAX +#define MPI3_IOUNIT14_MD_MAX (1) +#endif +struct mpi3_iounit14_pagemetadata { + u8 page_type; + u8 page_number; + u8 reserved02; + u8 page_flags; +}; +#define MPI3_IOUNIT14_PAGEMETADATA_PAGEFLAGS_OOBWRITE_ALLOWED (0x02) +#define MPI3_IOUNIT14_PAGEMETADATA_PAGEFLAGS_HOSTWRITE_ALLOWED (0x01) +struct mpi3_io_unit_page14 { + struct mpi3_config_page_header header; + u8 flags; + u8 reserved09[3]; + u8 num_pages; + u8 reserved0d[3]; + struct mpi3_iounit14_pagemetadata page_metadata[MPI3_IOUNIT14_MD_MAX]; +}; +#define MPI3_IOUNIT14_PAGEVERSION (0x00) +#define MPI3_IOUNIT14_FLAGS_READONLY (0x01) +#ifndef MPI3_IOUNIT15_PBD_MAX +#define MPI3_IOUNIT15_PBD_MAX (1) +#endif +struct mpi3_io_unit_page15 { + struct mpi3_config_page_header header; + u8 flags; + u8 reserved09[3]; + __le32 reserved0c; + u8 power_budgeting_capability; + u8 reserved11[3]; + u8 num_power_budget_data; + u8 reserved15[3]; + __le32 power_budget_data[MPI3_IOUNIT15_PBD_MAX]; +}; +#define MPI3_IOUNIT15_PAGEVERSION (0x00) +#define MPI3_IOUNIT15_FLAGS_EPRINIT_INITREQUIRED (0x04) +#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_MASK (0x03) +#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_NOT_SUPPORTED (0x00) +#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITHOUT_POWER_BRAKE_GPIO (0x01) +#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITH_POWER_BRAKE_GPIO (0x02) +#define MPI3_IOUNIT15_NUMPOWERBUDGETDATA_POWER_BUDGETING_DISABLED (0x00) struct mpi3_ioc_page0 { struct mpi3_config_page_header header; __le32 reserved08; @@ -1273,6 +1320,7 @@ struct mpi3_driver_page0 { #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_MASK (0x00000003) #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000) #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_ONLY (0x00000001) +#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_INTERNAL_DEVS (0x00000002) struct mpi3_driver_page1 { struct mpi3_config_page_header header; __le32 flags; @@ -1340,7 +1388,7 @@ union mpi3_driver2_trigger_element { #define MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_FW_RELEASE (0x01) struct mpi3_driver_page2 { struct mpi3_config_page_header header; - __le64 master_trigger; + __le64 global_trigger; __le32 reserved10[3]; u8 num_triggers; u8 reserved1d[3]; @@ -1348,11 +1396,13 @@ struct mpi3_driver_page2 { }; #define MPI3_DRIVER2_PAGEVERSION (0x00) -#define MPI3_DRIVER2_MASTERTRIGGER_DIAG_TRACE_RELEASE (0x8000000000000000ULL) -#define MPI3_DRIVER2_MASTERTRIGGER_DIAG_FW_RELEASE (0x4000000000000000ULL) -#define MPI3_DRIVER2_MASTERTRIGGER_SNAPDUMP (0x2000000000000000ULL) -#define MPI3_DRIVER2_MASTERTRIGGER_DEVICE_REMOVAL_ENABLED (0x0000000000000004ULL) -#define MPI3_DRIVER2_MASTERTRIGGER_TASK_MANAGEMENT_ENABLED (0x0000000000000002ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_DIAG_TRACE_RELEASE (0x8000000000000000ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_DIAG_FW_RELEASE (0x4000000000000000ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_SNAPDUMP_ENABLED (0x2000000000000000ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_POST_DIAG_TRACE_DISABLED (0x1000000000000000ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_POST_DIAG_FW_DISABLED (0x0800000000000000ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_DEVICE_REMOVAL_ENABLED (0x0000000000000004ULL) +#define MPI3_DRIVER2_GLOBALTRIGGER_TASK_MANAGEMENT_ENABLED (0x0000000000000002ULL) struct mpi3_driver_page10 { struct mpi3_config_page_header header; __le16 flags; @@ -1395,6 +1445,12 @@ union mpi3_security_nonce { u8 byte[64]; }; +union mpi3_security_root_digest { + __le32 dword[16]; + __le16 word[32]; + u8 byte[64]; +}; + union mpi3_security0_cert_chain { __le32 dword[1024]; __le16 word[2048]; @@ -1467,6 +1523,32 @@ struct mpi3_security_page1 { }; #define MPI3_SECURITY1_PAGEVERSION (0x00) +#ifndef MPI3_SECURITY2_TRUSTED_ROOT_MAX +#define MPI3_SECURITY2_TRUSTED_ROOT_MAX 1 +#endif +struct mpi3_security2_trusted_root { + u8 level; + u8 hash_algorithm; + __le16 trusted_root_flags; + __le32 reserved04[3]; + union mpi3_security_root_digest root_digest; +}; +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_MASK (0x0006) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_SHIFT (1) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_HA_FIELD (0x0000) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_AKI (0x0002) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_USERPROVISIONED_YES (0x0001) +struct mpi3_security_page2 { + struct mpi3_config_page_header header; + __le32 reserved08[2]; + union mpi3_security_mac mac; + union mpi3_security_nonce nonce; + __le32 reserved90[3]; + u8 num_roots; + u8 reserved9d[3]; + struct mpi3_security2_trusted_root trusted_root[MPI3_SECURITY2_TRUSTED_ROOT_MAX]; +}; +#define MPI3_SECURITY2_PAGEVERSION (0x00) struct mpi3_sas_io_unit0_phy_data { u8 io_unit_port; u8 port_flags; @@ -2351,6 +2433,10 @@ struct mpi3_device_page0 { #define MPI3_DEVICE0_ASTATUS_NVME_MAX (0x5f) #define MPI3_DEVICE0_ASTATUS_VD_UNKNOWN (0x80) #define MPI3_DEVICE0_ASTATUS_VD_MAX (0x8f) +#define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_MASK (0xe000) +#define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_NO_LIMIT (0x0000) +#define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_256_LB (0x2000) +#define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_2048_LB (0x4000) #define MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE (0x0080) #define MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED (0x0010) #define MPI3_DEVICE0_FLAGS_HIDDEN (0x0008) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_image.h b/drivers/scsi/mpi3mr/mpi/mpi30_image.h index 64c58815988a..47035b811902 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_image.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_image.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2018-2022 Broadcom Inc. All rights reserved. + * Copyright 2018-2023 Broadcom Inc. All rights reserved. */ #ifndef MPI30_IMAGE_H #define MPI30_IMAGE_H 1 diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_init.h b/drivers/scsi/mpi3mr/mpi/mpi30_init.h index 3c03610ecfa6..af86d12c8e49 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_init.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_init.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2022 Broadcom Inc. All rights reserved. + * Copyright 2016-2023 Broadcom Inc. All rights reserved. */ #ifndef MPI30_INIT_H #define MPI30_INIT_H 1 @@ -56,6 +56,7 @@ struct mpi3_scsi_io_request { #define MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI (0x00010000) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_MASK (0x000000f0) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING (0x00000010) +#define MPI3_SCSIIO_FLAGS_DIVERT_REASON_WRITE_SAME_TOO_LARGE (0x00000020) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_PROD_SPECIFIC (0x00000080) #define MPI3_SCSIIO_METASGL_INDEX (3) struct mpi3_scsi_io_reply { @@ -114,4 +115,24 @@ struct mpi3_scsi_io_reply { #define MPI3_SCSI_RSP_ARI0_MASK (0xff000000) #define MPI3_SCSI_RSP_ARI0_SHIFT (24) #define MPI3_SCSI_TASKTAG_UNKNOWN (0xffff) +#define MPI3_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x08) +#define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) +#define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK_SET (0x02) +#define MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) +#define MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) +#define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) +#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) +#define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08) +#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK_SET (0x09) +#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_ASYNC_EVENT (0x0a) +#define MPI3_SCSITASKMGMT_TASKTYPE_I_T_NEXUS_RESET (0x0b) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE (0x00) +#define MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME (0x02) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED (0x04) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED (0x05) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED (0x08) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN (0x09) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG (0x0a) +#define MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC (0x80) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED (0x81) #endif diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h index 1c6c6730df5c..f5e9c2309ce6 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2022 Broadcom Inc. All rights reserved. + * Copyright 2016-2023 Broadcom Inc. All rights reserved. */ #ifndef MPI30_IOC_H #define MPI30_IOC_H 1 diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h index b7a5df01120d..7c15e5851ce4 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2022 Broadcom Inc. All rights reserved. + * Copyright 2016-2023 Broadcom Inc. All rights reserved. * */ #ifndef MPI30_PCI_H #define MPI30_PCI_H 1 - +#ifndef MPI3_NVME_ENCAP_CMD_MAX +#define MPI3_NVME_ENCAP_CMD_MAX (1) +#endif #define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_MASK (0x0002) #define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_FAIL_ONLY (0x0000) #define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_ALL (0x0002) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h index e587f77ccd68..4a93c67d335f 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2022 Broadcom Inc. All rights reserved. + * Copyright 2016-2023 Broadcom Inc. All rights reserved. */ #ifndef MPI30_SAS_H #define MPI30_SAS_H 1 diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h index 9b76b9632751..441cfc2c7f09 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2022 Broadcom Inc. All rights reserved. + * Copyright 2016-2023 Broadcom Inc. All rights reserved. */ #ifndef MPI30_TRANSPORT_H #define MPI30_TRANSPORT_H 1 @@ -18,7 +18,7 @@ union mpi3_version_union { #define MPI3_VERSION_MAJOR (3) #define MPI3_VERSION_MINOR (0) -#define MPI3_VERSION_UNIT (26) +#define MPI3_VERSION_UNIT (27) #define MPI3_VERSION_DEV (0) #define MPI3_DEVHANDLE_INVALID (0xffff) struct mpi3_sysif_oper_queue_indexes { diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 364fb1b5e45a..dfe6b87fe288 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -2,7 +2,7 @@ /* * Driver for Broadcom MPI3 Storage Controllers * - * Copyright (C) 2017-2022 Broadcom Inc. + * Copyright (C) 2017-2023 Broadcom Inc. * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) * */ @@ -55,8 +55,8 @@ extern struct list_head mrioc_list; extern int prot_mask; extern atomic64_t event_counter; -#define MPI3MR_DRIVER_VERSION "8.2.0.3.0" -#define MPI3MR_DRIVER_RELDATE "08-September-2022" +#define MPI3MR_DRIVER_VERSION "8.4.1.0.0" +#define MPI3MR_DRIVER_RELDATE "16-March-2023" #define MPI3MR_DRIVER_NAME "mpi3mr" #define MPI3MR_DRIVER_LICENSE "GPL" @@ -126,6 +126,7 @@ extern atomic64_t event_counter; #define MPI3MR_RAID_ERRREC_RESET_TIMEOUT 180 #define MPI3MR_PREPARE_FOR_RESET_TIMEOUT 180 #define MPI3MR_RESET_ACK_TIMEOUT 30 +#define MPI3MR_MUR_TIMEOUT 120 #define MPI3MR_WATCHDOG_INTERVAL 1000 /* in milli seconds */ @@ -652,7 +653,11 @@ union _form_spec_inf { struct tgt_dev_vd vd_inf; }; - +enum mpi3mr_dev_state { + MPI3MR_DEV_CREATED = 1, + MPI3MR_DEV_REMOVE_HS_STARTED = 2, + MPI3MR_DEV_DELETED = 3, +}; /** * struct mpi3mr_tgt_dev - target device data structure @@ -676,6 +681,7 @@ union _form_spec_inf { * @enclosure_logical_id: Enclosure logical identifier * @dev_spec: Device type specific information * @ref_count: Reference count + * @state: device state */ struct mpi3mr_tgt_dev { struct list_head list; @@ -697,6 +703,7 @@ struct mpi3mr_tgt_dev { u64 enclosure_logical_id; union _form_spec_inf dev_spec; struct kref ref_count; + enum mpi3mr_dev_state state; }; /** diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index d10c6afb7f9c..08645a99ad6b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -2,7 +2,7 @@ /* * Driver for Broadcom MPI3 Storage Controllers * - * Copyright (C) 2017-2022 Broadcom Inc. + * Copyright (C) 2017-2023 Broadcom Inc. * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) * */ @@ -922,6 +922,7 @@ err_out: /** * mpi3mr_bsg_process_mpt_cmds - MPI Pass through BSG handler * @job: BSG job reference + * @reply_payload_rcv_len: length of payload recvd * * This function is the top level handler for MPI Pass through * command, this does basic validation of the input data buffers, @@ -1471,6 +1472,7 @@ static int mpi3mr_bsg_request(struct bsg_job *job) /** * mpi3mr_bsg_exit - de-registration from bsg layer + * @mrioc: Adapter instance reference * * This will be called during driver unload and all * bsg resources allocated during load will be freed. @@ -1505,6 +1507,7 @@ static void mpi3mr_bsg_node_release(struct device *dev) /** * mpi3mr_bsg_init - registration with bsg layer + * @mrioc: Adapter instance reference * * This will be called during driver load and it will * register driver with bsg layer diff --git a/drivers/scsi/mpi3mr/mpi3mr_debug.h b/drivers/scsi/mpi3mr/mpi3mr_debug.h index ee6edd8322e6..e94f7520d153 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_debug.h +++ b/drivers/scsi/mpi3mr/mpi3mr_debug.h @@ -2,7 +2,7 @@ /* * Driver for Broadcom MPI3 Storage Controllers * - * Copyright (C) 2017-2022 Broadcom Inc. + * Copyright (C) 2017-2023 Broadcom Inc. * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) * */ diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index d109a4ceb72b..075fa67e95ee 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -2,7 +2,7 @@ /* * Driver for Broadcom MPI3 Storage Controllers * - * Copyright (C) 2017-2022 Broadcom Inc. + * Copyright (C) 2017-2023 Broadcom Inc. * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) * */ @@ -1098,7 +1098,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc, ioc_config &= ~MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC; writel(ioc_config, &mrioc->sysif_regs->ioc_configuration); - timeout = MPI3MR_RESET_ACK_TIMEOUT * 10; + timeout = MPI3MR_MUR_TIMEOUT * 10; do { ioc_status = readl(&mrioc->sysif_regs->ioc_status); if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)) { @@ -2620,14 +2620,12 @@ static int mpi3mr_setup_admin_qpair(struct mpi3mr_ioc *mrioc) mrioc->num_admin_req = mrioc->admin_req_q_sz / MPI3MR_ADMIN_REQ_FRAME_SZ; mrioc->admin_req_ci = mrioc->admin_req_pi = 0; - mrioc->admin_req_base = NULL; mrioc->admin_reply_q_sz = MPI3MR_ADMIN_REPLY_Q_SIZE; mrioc->num_admin_replies = mrioc->admin_reply_q_sz / MPI3MR_ADMIN_REPLY_FRAME_SZ; mrioc->admin_reply_ci = 0; mrioc->admin_reply_ephase = 1; - mrioc->admin_reply_base = NULL; atomic_set(&mrioc->admin_reply_q_in_use, 0); if (!mrioc->admin_req_base) { diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 6d55698ea4d1..d627355303d7 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -2,7 +2,7 @@ /* * Driver for Broadcom MPI3 Storage Controllers * - * Copyright (C) 2017-2022 Broadcom Inc. + * Copyright (C) 2017-2023 Broadcom Inc. * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) * */ @@ -652,6 +652,7 @@ static void mpi3mr_tgtdev_add_to_list(struct mpi3mr_ioc *mrioc, mpi3mr_tgtdev_get(tgtdev); INIT_LIST_HEAD(&tgtdev->list); list_add_tail(&tgtdev->list, &mrioc->tgtdev_list); + tgtdev->state = MPI3MR_DEV_CREATED; spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); } @@ -659,20 +660,25 @@ static void mpi3mr_tgtdev_add_to_list(struct mpi3mr_ioc *mrioc, * mpi3mr_tgtdev_del_from_list -Delete tgtdevice from the list * @mrioc: Adapter instance reference * @tgtdev: Target device + * @must_delete: Must delete the target device from the list irrespective + * of the device state. * * Remove the target device from the target device list * * Return: Nothing. */ static void mpi3mr_tgtdev_del_from_list(struct mpi3mr_ioc *mrioc, - struct mpi3mr_tgt_dev *tgtdev) + struct mpi3mr_tgt_dev *tgtdev, bool must_delete) { unsigned long flags; spin_lock_irqsave(&mrioc->tgtdev_lock, flags); - if (!list_empty(&tgtdev->list)) { - list_del_init(&tgtdev->list); - mpi3mr_tgtdev_put(tgtdev); + if ((tgtdev->state == MPI3MR_DEV_REMOVE_HS_STARTED) || (must_delete == true)) { + if (!list_empty(&tgtdev->list)) { + list_del_init(&tgtdev->list); + tgtdev->state = MPI3MR_DEV_DELETED; + mpi3mr_tgtdev_put(tgtdev); + } } spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); } @@ -1036,7 +1042,7 @@ void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc) tgtdev->perst_id); if (tgtdev->host_exposed) mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, true); mpi3mr_tgtdev_put(tgtdev); } } @@ -1281,12 +1287,12 @@ static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_ioc *mrioc, if (!tgtdev->host_exposed) mpi3mr_report_tgtdev_to_host(mrioc, tgtdev->perst_id); } - if (tgtdev->starget && tgtdev->starget->hostdata) { - if (delete) - mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - } + + if (delete) + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); + if (cleanup) { - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, false); mpi3mr_tgtdev_put(tgtdev); } @@ -1604,7 +1610,7 @@ static void mpi3mr_sastopochg_evt_bh(struct mpi3mr_ioc *mrioc, case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: if (tgtdev->host_exposed) mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, false); mpi3mr_tgtdev_put(tgtdev); break; case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING: @@ -1762,7 +1768,7 @@ static void mpi3mr_pcietopochg_evt_bh(struct mpi3mr_ioc *mrioc, case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: if (tgtdev->host_exposed) mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, false); mpi3mr_tgtdev_put(tgtdev); break; default: @@ -2016,12 +2022,18 @@ static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc, int retval = 0; struct mpi3mr_tgt_dev *tgtdev = NULL; u16 perst_id = 0; + unsigned long flags; perst_id = le16_to_cpu(dev_pg0->persistent_id); if (perst_id == MPI3_DEVICE0_PERSISTENTID_INVALID) return retval; - tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id); + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + tgtdev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id); + if (tgtdev) + tgtdev->state = MPI3MR_DEV_CREATED; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + if (tgtdev) { mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0, true); mpi3mr_tgtdev_put(tgtdev); @@ -2219,6 +2231,14 @@ static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle, u8 retrycount = 5; struct mpi3mr_drv_cmd *drv_cmd = cmdparam; struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; + struct mpi3mr_tgt_dev *tgtdev = NULL; + unsigned long flags; + + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + tgtdev = __mpi3mr_get_tgtdev_by_handle(mrioc, handle); + if (tgtdev && (iou_rc == MPI3_CTRL_OP_REMOVE_DEVICE)) + tgtdev->state = MPI3MR_DEV_REMOVE_HS_STARTED; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); if (drv_cmd) goto issue_cmd; @@ -3311,19 +3331,19 @@ static int mpi3mr_get_chain_idx(struct mpi3mr_ioc *mrioc) { u8 retry_count = 5; int cmd_idx = -1; + unsigned long flags; + spin_lock_irqsave(&mrioc->chain_buf_lock, flags); do { - spin_lock(&mrioc->chain_buf_lock); cmd_idx = find_first_zero_bit(mrioc->chain_bitmap, mrioc->chain_buf_count); if (cmd_idx < mrioc->chain_buf_count) { set_bit(cmd_idx, mrioc->chain_bitmap); - spin_unlock(&mrioc->chain_buf_lock); break; } - spin_unlock(&mrioc->chain_buf_lock); cmd_idx = -1; } while (retry_count--); + spin_unlock_irqrestore(&mrioc->chain_buf_lock, flags); return cmd_idx; } @@ -3996,10 +4016,14 @@ static int mpi3mr_eh_target_reset(struct scsi_cmnd *scmd) stgt_priv_data = sdev_priv_data->tgt_priv_data; dev_handle = stgt_priv_data->dev_handle; if (stgt_priv_data->dev_removed) { + struct scmd_priv *cmd_priv = scsi_cmd_priv(scmd); sdev_printk(KERN_INFO, scmd->device, "%s:target(handle = 0x%04x) is removed, target reset is not issued\n", mrioc->name, dev_handle); - retval = FAILED; + if (!cmd_priv->in_lld_scope || cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID) + retval = SUCCESS; + else + retval = FAILED; goto out; } sdev_printk(KERN_INFO, scmd->device, @@ -4064,10 +4088,14 @@ static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd) stgt_priv_data = sdev_priv_data->tgt_priv_data; dev_handle = stgt_priv_data->dev_handle; if (stgt_priv_data->dev_removed) { + struct scmd_priv *cmd_priv = scsi_cmd_priv(scmd); sdev_printk(KERN_INFO, scmd->device, "%s: device(handle = 0x%04x) is removed, device(LUN) reset is not issued\n", mrioc->name, dev_handle); - retval = FAILED; + if (!cmd_priv->in_lld_scope || cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID) + retval = SUCCESS; + else + retval = FAILED; goto out; } sdev_printk(KERN_INFO, scmd->device, @@ -4625,13 +4653,24 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost, goto out; } + stgt_priv_data = sdev_priv_data->tgt_priv_data; + dev_handle = stgt_priv_data->dev_handle; + + /* Avoid error handling escalation when device is removed or blocked */ + + if (scmd->device->host->shost_state == SHOST_RECOVERY && + scmd->cmnd[0] == TEST_UNIT_READY && + (stgt_priv_data->dev_removed || (dev_handle == MPI3MR_INVALID_DEV_HANDLE))) { + scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07); + scsi_done(scmd); + goto out; + } + if (mrioc->reset_in_progress) { retval = SCSI_MLQUEUE_HOST_BUSY; goto out; } - stgt_priv_data = sdev_priv_data->tgt_priv_data; - if (atomic_read(&stgt_priv_data->block_io)) { if (mrioc->stop_drv_processing) { scmd->result = DID_NO_CONNECT << 16; @@ -4642,7 +4681,6 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost, goto out; } - dev_handle = stgt_priv_data->dev_handle; if (dev_handle == MPI3MR_INVALID_DEV_HANDLE) { scmd->result = DID_NO_CONNECT << 16; scsi_done(scmd); @@ -4758,7 +4796,7 @@ out: return retval; } -static struct scsi_host_template mpi3mr_driver_template = { +static const struct scsi_host_template mpi3mr_driver_template = { .module = THIS_MODULE, .name = "MPI3 Storage Controller", .proc_name = MPI3MR_DRIVER_NAME, @@ -5111,7 +5149,7 @@ static void mpi3mr_remove(struct pci_dev *pdev) list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, list) { mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, true); mpi3mr_tgtdev_put(tgtdev); } mpi3mr_stop_watchdog(mrioc); diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 5748bd9369ff..4d84d5bd173f 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -2,7 +2,7 @@ /* * Driver for Broadcom MPI3 Storage Controllers * - * Copyright (C) 2017-2022 Broadcom Inc. + * Copyright (C) 2017-2023 Broadcom Inc. * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) * */ diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 14ae0a9c5d3d..53f5492579cb 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -60,7 +60,6 @@ #include <linux/ktime.h> #include <linux/kthread.h> #include <asm/page.h> /* To get host page size per arch */ -#include <linux/aer.h> #include "mpt3sas_base.h" @@ -3535,7 +3534,6 @@ mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) if (pci_is_enabled(pdev)) { pci_release_selected_regions(ioc->pdev, ioc->bars); - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); } } @@ -3615,9 +3613,6 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) goto out_fail; } -/* AER (Advanced Error Reporting) hooks */ - pci_enable_pcie_error_reporting(pdev); - pci_set_master(pdev); @@ -4761,21 +4756,15 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) int i = 0; char desc[17] = {0}; u32 iounit_pg1_flags; - u32 bios_version; - bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); strncpy(desc, ioc->manu_pg0.ChipName, 16); - ioc_info(ioc, "%s: FWVersion(%02d.%02d.%02d.%02d), ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n", + ioc_info(ioc, "%s: FWVersion(%02d.%02d.%02d.%02d), ChipRevision(0x%02x)\n", desc, (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, ioc->facts.FWVersion.Word & 0x000000FF, - ioc->pdev->revision, - (bios_version & 0xFF000000) >> 24, - (bios_version & 0x00FF0000) >> 16, - (bios_version & 0x0000FF00) >> 8, - bios_version & 0x000000FF); + ioc->pdev->revision); _base_display_OEMs_branding(ioc); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 8e24ebcebfe5..c3c1f466fe01 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -52,7 +52,6 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/interrupt.h> -#include <linux/aer.h> #include <linux/raid_class.h> #include <linux/blk-mq-pci.h> #include <asm/unaligned.h> @@ -11926,7 +11925,7 @@ static void scsih_map_queues(struct Scsi_Host *shost) } /* shost template for SAS 2.0 HBA devices */ -static struct scsi_host_template mpt2sas_driver_template = { +static const struct scsi_host_template mpt2sas_driver_template = { .module = THIS_MODULE, .name = "Fusion MPT SAS Host", .proc_name = MPT2SAS_DRIVER_NAME, @@ -11964,7 +11963,7 @@ static struct raid_function_template mpt2sas_raid_functions = { }; /* shost template for SAS 3.0 HBA devices */ -static struct scsi_host_template mpt3sas_driver_template = { +static const struct scsi_host_template mpt3sas_driver_template = { .module = THIS_MODULE, .name = "Fusion MPT SAS Host", .proc_name = MPT3SAS_DRIVER_NAME, @@ -12930,10 +12929,10 @@ _mpt3sas_exit(void) pr_info("mpt3sas version %s unloading\n", MPT3SAS_DRIVER_VERSION); - mpt3sas_ctl_exit(hbas_to_enumerate); - pci_unregister_driver(&mpt3sas_driver); + mpt3sas_ctl_exit(hbas_to_enumerate); + scsih_exit(); } diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 472fa043094f..98b99c0f5bc7 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -69,7 +69,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, m147_pcc->dma_cntrl = 0; } -static struct scsi_host_template mvme147_host_template = { +static const struct scsi_host_template mvme147_host_template = { .module = THIS_MODULE, .proc_name = "MVME147", .name = "MVME147 built-in SCSI", diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index cfe84473a515..49e2a5e7ce54 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -29,7 +29,7 @@ static const struct attribute_group *mvst_host_groups[]; #define SOC_SAS_NUM 2 -static struct scsi_host_template mvs_sht = { +static const struct scsi_host_template mvs_sht = { .module = THIS_MODULE, .name = DRV_NAME, .queuecommand = sas_queuecommand, diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 60c65586f30e..73aa7059b556 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -2168,7 +2168,7 @@ mvumi_bios_param(struct scsi_device *sdev, struct block_device *bdev, return 0; } -static struct scsi_host_template mvumi_template = { +static const struct scsi_host_template mvumi_template = { .module = THIS_MODULE, .name = "Marvell Storage Controller", diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c index e885c1dbf61f..ca2e932dd9b7 100644 --- a/drivers/scsi/myrb.c +++ b/drivers/scsi/myrb.c @@ -2203,7 +2203,7 @@ static struct attribute *myrb_shost_attrs[] = { ATTRIBUTE_GROUPS(myrb_shost); -static struct scsi_host_template myrb_template = { +static const struct scsi_host_template myrb_template = { .module = THIS_MODULE, .name = "DAC960", .proc_name = "myrb", diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c index 7eb8c39da366..a1eec65a9713 100644 --- a/drivers/scsi/myrs.c +++ b/drivers/scsi/myrs.c @@ -1915,7 +1915,7 @@ static void myrs_slave_destroy(struct scsi_device *sdev) kfree(sdev->hostdata); } -static struct scsi_host_template myrs_template = { +static const struct scsi_host_template myrs_template = { .module = THIS_MODULE, .name = "DAC960", .proc_name = "myrs", diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 75bb0028ed74..b7987019686e 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -259,7 +259,7 @@ static void nsp32_dmessage(const char *, int, int, char *, ...); /* * max_sectors is currently limited up to 128. */ -static struct scsi_host_template nsp32_template = { +static const struct scsi_host_template nsp32_template = { .proc_name = "nsp32", .name = "Workbit NinjaSCSI-32Bi/UDE", .show_info = nsp32_show_info, diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 5d7dfefd6f6c..278c78d066c4 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -668,7 +668,7 @@ ATTRIBUTE_GROUPS(SYM53C500_shost); /* * scsi_host_template initializer */ -static struct scsi_host_template sym53c500_driver_template = { +static const struct scsi_host_template sym53c500_driver_template = { .module = THIS_MODULE, .name = "SYM53C500", .info = SYM53C500_info, @@ -702,7 +702,7 @@ SYM53C500_config(struct pcmcia_device *link) int ret; int irq_level, port_base; struct Scsi_Host *host; - struct scsi_host_template *tpnt = &sym53c500_driver_template; + const struct scsi_host_template *tpnt = &sym53c500_driver_template; struct sym53c500_data *data; dev_dbg(&link->dev, "SYM53C500_config\n"); diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 7e589fe3e010..8b9490011e36 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -96,7 +96,7 @@ static void pm8001_map_queues(struct Scsi_Host *shost) /* * The main structure which LLDD must register for scsi core. */ -static struct scsi_host_template pm8001_sht = { +static const struct scsi_host_template pm8001_sht = { .module = THIS_MODULE, .name = DRV_NAME, .proc_name = DRV_NAME, diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 836ddc476764..23c5230dbed4 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3611,7 +3611,7 @@ static struct attribute *pmcraid_host_attrs[] = { ATTRIBUTE_GROUPS(pmcraid_host); /* host template structure for pmcraid driver */ -static struct scsi_host_template pmcraid_host_template = { +static const struct scsi_host_template pmcraid_host_template = { .module = THIS_MODULE, .name = PMCRAID_DRIVER_NAME, .queuecommand = pmcraid_queuecommand, diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index c6c1bc608224..909c49541984 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -972,7 +972,7 @@ static int ppa_adjust_queue(struct scsi_device *device) return 0; } -static struct scsi_host_template ppa_template = { +static const struct scsi_host_template ppa_template = { .module = THIS_MODULE, .proc_name = "ppa", .show_info = ppa_show_info, diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index 2b80cab70333..90495a832f34 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -323,7 +323,7 @@ done: return IRQ_HANDLED; } -static struct scsi_host_template ps3rom_host_template = { +static const struct scsi_host_template ps3rom_host_template = { .name = DEVICE_NAME, .slave_configure = ps3rom_slave_configure, .queuecommand = ps3rom_queuecommand, diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 35e16600fc63..3b64de81ea0d 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -979,7 +979,7 @@ static int qedf_slave_configure(struct scsi_device *sdev) return 0; } -static struct scsi_host_template qedf_host_template = { +static const struct scsi_host_template qedf_host_template = { .module = THIS_MODULE, .name = QEDF_MODULE_NAME, .this_id = -1, @@ -2224,7 +2224,6 @@ static bool qedf_process_completions(struct qedf_fastpath *fp) u16 prod_idx; struct fcoe_cqe *cqe; struct qedf_io_work *io_work; - int num_handled = 0; unsigned int cpu; struct qedf_ioreq *io_req = NULL; u16 xid; @@ -2247,7 +2246,6 @@ static bool qedf_process_completions(struct qedf_fastpath *fp) while (new_cqes) { fp->completions++; - num_handled++; cqe = &que->cq[que->cq_cons_idx]; comp_type = (cqe->cqe_data >> FCOE_CQE_CQE_TYPE_SHIFT) & diff --git a/drivers/scsi/qedi/qedi_gbl.h b/drivers/scsi/qedi/qedi_gbl.h index 72942772b198..0e316cc24b19 100644 --- a/drivers/scsi/qedi/qedi_gbl.h +++ b/drivers/scsi/qedi/qedi_gbl.h @@ -17,7 +17,7 @@ extern int qedi_do_not_recover; extern uint qedi_io_tracing; -extern struct scsi_host_template qedi_host_template; +extern const struct scsi_host_template qedi_host_template; extern struct iscsi_transport qedi_iscsi_transport; extern const struct qed_iscsi_ops *qedi_ops; extern const struct qedi_debugfs_ops qedi_debugfs_ops[]; diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 31ec429104e2..6ed8ef97642c 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -40,7 +40,7 @@ static int qedi_eh_host_reset(struct scsi_cmnd *cmd) return qedi_recover_all_conns(qedi); } -struct scsi_host_template qedi_host_template = { +const struct scsi_host_template qedi_host_template = { .module = THIS_MODULE, .name = "QLogic QEDI 25/40/100Gb iSCSI Initiator Driver", .proc_name = QEDI_MODULE_NAME, diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 1e7f4d138e06..6e5e89aaa283 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4115,7 +4115,7 @@ qla1280_get_token(char *str) } -static struct scsi_host_template qla1280_driver_template = { +static const struct scsi_host_template qla1280_driver_template = { .module = THIS_MODULE, .proc_name = "qla1280", .name = "Qlogic ISP 1280/12160", diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ec0e987b71fa..df5e5b7fdcfe 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -22,7 +22,6 @@ #include <linux/interrupt.h> #include <linux/workqueue.h> #include <linux/firmware.h> -#include <linux/aer.h> #include <linux/mutex.h> #include <linux/btree.h> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 9aba07c7bde4..391c8b3623a6 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -214,7 +214,7 @@ extern void qla2x00_free_exchoffld_buffer(struct qla_hw_data *); extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); -extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, +extern struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *, struct qla_hw_data *); extern void qla2x00_free_host(struct scsi_qla_host *); extern void qla2x00_relogin(struct scsi_qla_host *); diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 78661b658dcd..b67416951a5f 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -496,7 +496,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost); struct qla_hw_data *ha = base_vha->hw; scsi_qla_host_t *vha; - struct scsi_host_template *sht = &qla2xxx_driver_template; + const struct scsi_host_template *sht = &qla2xxx_driver_template; struct Scsi_Host *host; vha = qla2x00_create_host(sht, ha); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d0cdbfe771a9..2fa695bf38b7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2958,9 +2958,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql2xallocfwdump = 0; } - /* This may fail but that's ok */ - pci_enable_pcie_error_reporting(pdev); - ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, @@ -3968,8 +3965,6 @@ qla2x00_remove_one(struct pci_dev *pdev) pci_release_selected_regions(ha->pdev, ha->bars); kfree(ha); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); } @@ -5024,8 +5019,8 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->vp_map = NULL; } -struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, - struct qla_hw_data *ha) +struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *sht, + struct qla_hw_data *ha) { struct Scsi_Host *host; struct scsi_qla_host *vha = NULL; @@ -6845,7 +6840,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) qla2x00_unmap_iobases(ha); pci_release_selected_regions(ha->pdev, ha->bars); - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); /* diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index aa0cf5ca6c1c..5258b07687a9 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6395,8 +6395,7 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) return -ENOMEM; } - if (!(base_vha->host->hostt->supported_mode & MODE_TARGET)) - base_vha->host->hostt->supported_mode |= MODE_TARGET; + qla2xxx_driver_template.supported_mode |= MODE_TARGET; rc = btree_init64(&tgt->lun_qpair_map); if (rc) { diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 8024322c9c5a..3b5ba4b47b3b 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -377,11 +377,6 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess) tcm_qla2xxx_put_sess(sess); } -static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess) -{ - return 0; -} - static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, @@ -421,11 +416,6 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) return qlt_rdy_to_xfer(cmd); } -static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl) -{ - return; -} - static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) { if (!(se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { @@ -1811,10 +1801,8 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { .check_stop_free = tcm_qla2xxx_check_stop_free, .release_cmd = tcm_qla2xxx_release_cmd, .close_session = tcm_qla2xxx_close_session, - .sess_get_index = tcm_qla2xxx_sess_get_index, .sess_get_initiator_sid = NULL, .write_pending = tcm_qla2xxx_write_pending, - .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, .get_cmd_state = tcm_qla2xxx_get_cmd_state, .queue_data_in = tcm_qla2xxx_queue_data_in, .queue_status = tcm_qla2xxx_queue_status, @@ -1852,10 +1840,8 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { .check_stop_free = tcm_qla2xxx_check_stop_free, .release_cmd = tcm_qla2xxx_release_cmd, .close_session = tcm_qla2xxx_close_session, - .sess_get_index = tcm_qla2xxx_sess_get_index, .sess_get_initiator_sid = NULL, .write_pending = tcm_qla2xxx_write_pending, - .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, .get_cmd_state = tcm_qla2xxx_get_cmd_state, .queue_data_in = tcm_qla2xxx_queue_data_in, .queue_status = tcm_qla2xxx_queue_status, diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 5f82c8afd5e0..5e683ba49fa5 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -23,7 +23,6 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/mutex.h> -#include <linux/aer.h> #include <linux/bsg-lib.h> #include <linux/vmalloc.h> diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 6f0e77dc2a34..cf52258ecdde 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -472,14 +472,12 @@ static void qla4xxx_mbox_status_entry(struct scsi_qla_host *ha, **/ void qla4xxx_process_response_queue(struct scsi_qla_host *ha) { - uint32_t count = 0; struct srb *srb = NULL; struct status_entry *sts_entry; /* Process all responses from response queue */ while ((ha->response_ptr->signature != RESPONSE_PROCESSED)) { sts_entry = (struct status_entry *) ha->response_ptr; - count++; /* Advance pointers for next entry */ if (ha->response_out == (RESPONSE_QUEUE_DEPTH - 1)) { diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 005502125b27..ee6d784c095c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -8639,8 +8639,6 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev, ha->host_no = host->host_no; ha->func_num = PCI_FUNC(ha->pdev->devfn); - pci_enable_pcie_error_reporting(pdev); - /* Setup Runtime configurable options */ if (is_qla8022(ha)) { ha->isp_ops = &qla4_82xx_isp_ops; @@ -8867,7 +8865,6 @@ probe_failed: qla4xxx_free_adapter(ha); probe_failed_ioconfig: - pci_disable_pcie_error_reporting(pdev); scsi_host_put(ha->host); probe_disable_device: @@ -9022,7 +9019,6 @@ static void qla4xxx_remove_adapter(struct pci_dev *pdev) scsi_host_put(ha->host); - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); } diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 8c961ff03fcd..1e8fbd457248 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -513,7 +513,7 @@ static int qlogicpti_load_firmware(struct qlogicpti *qpti) qpti->qpti_id); err = 1; goto out; - } + } sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL); @@ -563,7 +563,7 @@ static int qlogicpti_load_firmware(struct qlogicpti *qpti) qpti->qpti_id); err = 1; goto out; - } + } /* Load it up.. */ for (i = 0; i < risc_code_length; i++) { @@ -1136,7 +1136,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) if (!(sbus_readw(qpti->qregs + SBUS_STAT) & SBUS_STAT_RINT)) return NULL; - + in_ptr = sbus_readw(qpti->qregs + MBOX5); sbus_writew(HCCTRL_CRIRQ, qpti->qregs + HCCTRL); if (sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK) { @@ -1287,7 +1287,7 @@ static int qlogicpti_reset(struct scsi_cmnd *Cmnd) return return_status; } -static struct scsi_host_template qpti_template = { +static const struct scsi_host_template qpti_template = { .module = THIS_MODULE, .name = "qlogicpti", .info = qlogicpti_info, @@ -1362,9 +1362,8 @@ static int qpti_sbus_probe(struct platform_device *op) fcode = of_get_property(dp, "isp-fcode", NULL); if (fcode && fcode[0]) printk("(FCode %s)", fcode); - if (of_find_property(dp, "differential", NULL) != NULL) - qpti->differential = 1; - + qpti->differential = of_property_read_bool(dp, "differential"); + printk("\nqlogicpti%d: [%s Wide, using %s interface]\n", qpti->qpti_id, (qpti->ultra ? "Ultra" : "Fast"), diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 8553277effb3..f4fa1035a191 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -250,6 +250,11 @@ static const char *sdebug_version_date = "20210520"; #define SDEB_XA_NOT_IN_USE XA_MARK_1 +static struct kmem_cache *queued_cmd_cache; + +#define TO_QUEUED_CMD(scmd) ((void *)(scmd)->host_scribble) +#define ASSIGN_QUEUED_CMD(scmnd, qc) { (scmnd)->host_scribble = (void *) qc; } + /* Zone types (zbcr05 table 25) */ enum sdebug_z_type { ZBC_ZTYPE_CNV = 0x1, @@ -288,7 +293,6 @@ struct sdebug_dev_info { uuid_t lu_name; struct sdebug_host_info *sdbg_host; unsigned long uas_bm[1]; - atomic_t num_in_q; atomic_t stopped; /* 1: by SSU, 2: device start */ bool used; @@ -324,9 +328,12 @@ struct sdeb_store_info { void *map_storep; /* provisioning map */ }; -#define to_sdebug_host(d) \ +#define dev_to_sdebug_host(d) \ container_of(d, struct sdebug_host_info, dev) +#define shost_to_sdebug_host(shost) \ + dev_to_sdebug_host(shost->dma_dev) + enum sdeb_defer_type {SDEB_DEFER_NONE = 0, SDEB_DEFER_HRT = 1, SDEB_DEFER_WQ = 2, SDEB_DEFER_POLL = 3}; @@ -334,13 +341,7 @@ struct sdebug_defer { struct hrtimer hrt; struct execute_work ew; ktime_t cmpl_ts;/* time since boot to complete this cmd */ - int sqa_idx; /* index of sdebug_queue array */ - int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */ - int hc_idx; /* hostwide tag index */ int issuing_cpu; - bool init_hrt; - bool init_wq; - bool init_poll; bool aborted; /* true when blk_abort_request() already called */ enum sdeb_defer_type defer_t; }; @@ -349,15 +350,12 @@ struct sdebug_queued_cmd { /* corresponding bit set in in_use_bm[] in owning struct sdebug_queue * instance indicates this slot is in use. */ - struct sdebug_defer *sd_dp; - struct scsi_cmnd *a_cmnd; + struct sdebug_defer sd_dp; + struct scsi_cmnd *scmd; }; -struct sdebug_queue { - struct sdebug_queued_cmd qc_arr[SDEBUG_CANQUEUE]; - unsigned long in_use_bm[SDEBUG_CANQUEUE_WORDS]; - spinlock_t qc_lock; - atomic_t blocked; /* to temporarily stop more being queued */ +struct sdebug_scsi_cmd { + spinlock_t lock; }; static atomic_t sdebug_cmnd_count; /* number of incoming commands */ @@ -507,6 +505,8 @@ static int sdebug_add_store(void); static void sdebug_erase_store(int idx, struct sdeb_store_info *sip); static void sdebug_erase_all_stores(bool apart_from_first); +static void sdebug_free_queued_cmd(struct sdebug_queued_cmd *sqcp); + /* * The following are overflow arrays for cdbs that "hit" the same index in * the opcode_info_arr array. The most time sensitive (or commonly used) cdb @@ -754,7 +754,6 @@ static int sdebug_max_luns = DEF_MAX_LUNS; static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */ static unsigned int sdebug_medium_error_start = OPT_MEDIUM_ERR_ADDR; static int sdebug_medium_error_count = OPT_MEDIUM_ERR_NUM; -static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ static int sdebug_ndelay = DEF_NDELAY; /* if > 0 then unit is nanoseconds */ static int sdebug_no_lun_0 = DEF_NO_LUN_0; static int sdebug_no_uld; @@ -814,7 +813,7 @@ static int sdebug_cylinders_per; /* cylinders per surface */ static int sdebug_sectors_per; /* sectors per cylinder */ static LIST_HEAD(sdebug_host_list); -static DEFINE_SPINLOCK(sdebug_host_list_lock); +static DEFINE_MUTEX(sdebug_host_list_mutex); static struct xarray per_store_arr; static struct xarray *per_store_ap = &per_store_arr; @@ -841,7 +840,6 @@ static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES; static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */ static int poll_queues; /* iouring iopoll interface.*/ -static struct sdebug_queue *sdebug_q_arr; /* ptr to array of submit queues */ static DEFINE_RWLOCK(atomic_rw); static DEFINE_RWLOCK(atomic_rw2); @@ -906,7 +904,7 @@ static void sdebug_max_tgts_luns(void) struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { hpnt = sdbg_host->shost; if ((hpnt->this_id >= 0) && @@ -917,7 +915,7 @@ static void sdebug_max_tgts_luns(void) /* sdebug_max_luns; */ hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1; } - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); } enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1}; @@ -1049,30 +1047,27 @@ static void all_config_cdb_len(void) struct Scsi_Host *shost; struct scsi_device *sdev; - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { shost = sdbg_host->shost; shost_for_each_device(sdev, shost) { config_cdb_len(sdev); } } - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); } static void clear_luns_changed_on_target(struct sdebug_dev_info *devip) { - struct sdebug_host_info *sdhp; + struct sdebug_host_info *sdhp = devip->sdbg_host; struct sdebug_dev_info *dp; - spin_lock(&sdebug_host_list_lock); - list_for_each_entry(sdhp, &sdebug_host_list, host_list) { - list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) { - if ((devip->sdbg_host == dp->sdbg_host) && - (devip->target == dp->target)) - clear_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm); + list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) { + if ((devip->sdbg_host == dp->sdbg_host) && + (devip->target == dp->target)) { + clear_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm); } } - spin_unlock(&sdebug_host_list_lock); } static int make_ua(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) @@ -4899,20 +4894,6 @@ fini: return res; } -static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) -{ - u16 hwq; - u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmnd)); - - hwq = blk_mq_unique_tag_to_hwq(tag); - - pr_debug("tag=%#x, hwq=%d\n", tag, hwq); - if (WARN_ON_ONCE(hwq >= submit_queues)) - hwq = 0; - - return sdebug_q_arr + hwq; -} - static u32 get_tag(struct scsi_cmnd *cmnd) { return blk_mq_unique_tag(scsi_cmd_to_rq(cmnd)); @@ -4921,75 +4902,41 @@ static u32 get_tag(struct scsi_cmnd *cmnd) /* Queued (deferred) command completions converge here. */ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) { - bool aborted = sd_dp->aborted; - int qc_idx; - int retiring = 0; - unsigned long iflags; - struct sdebug_queue *sqp; - struct sdebug_queued_cmd *sqcp; - struct scsi_cmnd *scp; - struct sdebug_dev_info *devip; + struct sdebug_queued_cmd *sqcp = container_of(sd_dp, struct sdebug_queued_cmd, sd_dp); + unsigned long flags; + struct scsi_cmnd *scp = sqcp->scmd; + struct sdebug_scsi_cmd *sdsc; + bool aborted; - if (unlikely(aborted)) - sd_dp->aborted = false; - qc_idx = sd_dp->qc_idx; - sqp = sdebug_q_arr + sd_dp->sqa_idx; if (sdebug_statistics) { atomic_inc(&sdebug_completions); if (raw_smp_processor_id() != sd_dp->issuing_cpu) atomic_inc(&sdebug_miss_cpus); } - if (unlikely((qc_idx < 0) || (qc_idx >= SDEBUG_CANQUEUE))) { - pr_err("wild qc_idx=%d\n", qc_idx); - return; - } - spin_lock_irqsave(&sqp->qc_lock, iflags); - WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_NONE); - sqcp = &sqp->qc_arr[qc_idx]; - scp = sqcp->a_cmnd; - if (unlikely(scp == NULL)) { - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d, hc_idx=%d\n", - sd_dp->sqa_idx, qc_idx, sd_dp->hc_idx); - return; - } - devip = (struct sdebug_dev_info *)scp->device->hostdata; - if (likely(devip)) - atomic_dec(&devip->num_in_q); - else - pr_err("devip=NULL\n"); - if (unlikely(atomic_read(&retired_max_queue) > 0)) - retiring = 1; - - sqcp->a_cmnd = NULL; - if (unlikely(!test_and_clear_bit(qc_idx, sqp->in_use_bm))) { - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - pr_err("Unexpected completion\n"); - return; + + if (!scp) { + pr_err("scmd=NULL\n"); + goto out; } - if (unlikely(retiring)) { /* user has reduced max_queue */ - int k, retval; + sdsc = scsi_cmd_priv(scp); + spin_lock_irqsave(&sdsc->lock, flags); + aborted = sd_dp->aborted; + if (unlikely(aborted)) + sd_dp->aborted = false; + ASSIGN_QUEUED_CMD(scp, NULL); + + spin_unlock_irqrestore(&sdsc->lock, flags); - retval = atomic_read(&retired_max_queue); - if (qc_idx >= retval) { - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - pr_err("index %d too large\n", retval); - return; - } - k = find_last_bit(sqp->in_use_bm, retval); - if ((k < sdebug_max_queue) || (k == retval)) - atomic_set(&retired_max_queue, 0); - else - atomic_set(&retired_max_queue, k + 1); - } - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - if (unlikely(aborted)) { - if (sdebug_verbose) - pr_info("bypassing scsi_done() due to aborted cmd\n"); - return; + if (aborted) { + pr_info("bypassing scsi_done() due to aborted cmd, kicking-off EH\n"); + blk_abort_request(scsi_cmd_to_rq(scp)); + goto out; } + scsi_done(scp); /* callback to mid level */ +out: + sdebug_free_queued_cmd(sqcp); } /* When high resolution timer goes off this function is called. */ @@ -5152,7 +5099,6 @@ static struct sdebug_dev_info *sdebug_device_create( } else { devip->zmodel = BLK_ZONED_NONE; } - devip->sdbg_host = sdbg_host; devip->create_ts = ktime_get_boottime(); atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); @@ -5166,11 +5112,7 @@ static struct sdebug_dev_info *find_build_dev_info(struct scsi_device *sdev) struct sdebug_dev_info *open_devip = NULL; struct sdebug_dev_info *devip; - sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); - if (!sdbg_host) { - pr_err("Host info NULL\n"); - return NULL; - } + sdbg_host = shost_to_sdebug_host(sdev->host); list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { if ((devip->used) && (devip->channel == sdev->channel) && @@ -5194,7 +5136,6 @@ static struct sdebug_dev_info *find_build_dev_info(struct scsi_device *sdev) open_devip->target = sdev->id; open_devip->lun = sdev->lun; open_devip->sdbg_host = sdbg_host; - atomic_set(&open_devip->num_in_q, 0); set_bit(SDEBUG_UA_POOCCUR, open_devip->uas_bm); open_devip->used = true; return open_devip; @@ -5245,215 +5186,171 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) } } -static void stop_qc_helper(struct sdebug_defer *sd_dp, +/* Returns true if we require the queued memory to be freed by the caller. */ +static bool stop_qc_helper(struct sdebug_defer *sd_dp, enum sdeb_defer_type defer_t) { - if (!sd_dp) - return; - if (defer_t == SDEB_DEFER_HRT) - hrtimer_cancel(&sd_dp->hrt); - else if (defer_t == SDEB_DEFER_WQ) - cancel_work_sync(&sd_dp->ew.work); -} - -/* If @cmnd found deletes its timer or work queue and returns true; else - returns false */ -static bool stop_queued_cmnd(struct scsi_cmnd *cmnd) -{ - unsigned long iflags; - int j, k, qmax, r_qmax; - enum sdeb_defer_type l_defer_t; - struct sdebug_queue *sqp; - struct sdebug_queued_cmd *sqcp; - struct sdebug_dev_info *devip; - struct sdebug_defer *sd_dp; + if (defer_t == SDEB_DEFER_HRT) { + int res = hrtimer_try_to_cancel(&sd_dp->hrt); - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { - spin_lock_irqsave(&sqp->qc_lock, iflags); - qmax = sdebug_max_queue; - r_qmax = atomic_read(&retired_max_queue); - if (r_qmax > qmax) - qmax = r_qmax; - for (k = 0; k < qmax; ++k) { - if (test_bit(k, sqp->in_use_bm)) { - sqcp = &sqp->qc_arr[k]; - if (cmnd != sqcp->a_cmnd) - continue; - /* found */ - devip = (struct sdebug_dev_info *) - cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - sd_dp = sqcp->sd_dp; - if (sd_dp) { - l_defer_t = READ_ONCE(sd_dp->defer_t); - WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_NONE); - } else - l_defer_t = SDEB_DEFER_NONE; - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - stop_qc_helper(sd_dp, l_defer_t); - clear_bit(k, sqp->in_use_bm); - return true; - } + switch (res) { + case 0: /* Not active, it must have already run */ + case -1: /* -1 It's executing the CB */ + return false; + case 1: /* Was active, we've now cancelled */ + default: + return true; } - spin_unlock_irqrestore(&sqp->qc_lock, iflags); + } else if (defer_t == SDEB_DEFER_WQ) { + /* Cancel if pending */ + if (cancel_work_sync(&sd_dp->ew.work)) + return true; + /* Was not pending, so it must have run */ + return false; + } else if (defer_t == SDEB_DEFER_POLL) { + return true; } + return false; } -/* Deletes (stops) timers or work queues of all queued commands */ -static void stop_all_queued(void) + +static bool scsi_debug_stop_cmnd(struct scsi_cmnd *cmnd) { - unsigned long iflags; - int j, k; enum sdeb_defer_type l_defer_t; - struct sdebug_queue *sqp; - struct sdebug_queued_cmd *sqcp; - struct sdebug_dev_info *devip; struct sdebug_defer *sd_dp; + struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmnd); + struct sdebug_queued_cmd *sqcp = TO_QUEUED_CMD(cmnd); - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { - spin_lock_irqsave(&sqp->qc_lock, iflags); - for (k = 0; k < SDEBUG_CANQUEUE; ++k) { - if (test_bit(k, sqp->in_use_bm)) { - sqcp = &sqp->qc_arr[k]; - if (sqcp->a_cmnd == NULL) - continue; - devip = (struct sdebug_dev_info *) - sqcp->a_cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - sd_dp = sqcp->sd_dp; - if (sd_dp) { - l_defer_t = READ_ONCE(sd_dp->defer_t); - WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_NONE); - } else - l_defer_t = SDEB_DEFER_NONE; - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - stop_qc_helper(sd_dp, l_defer_t); - clear_bit(k, sqp->in_use_bm); - spin_lock_irqsave(&sqp->qc_lock, iflags); - } - } - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - } + lockdep_assert_held(&sdsc->lock); + + if (!sqcp) + return false; + sd_dp = &sqcp->sd_dp; + l_defer_t = READ_ONCE(sd_dp->defer_t); + ASSIGN_QUEUED_CMD(cmnd, NULL); + + if (stop_qc_helper(sd_dp, l_defer_t)) + sdebug_free_queued_cmd(sqcp); + + return true; +} + +/* + * Called from scsi_debug_abort() only, which is for timed-out cmd. + */ +static bool scsi_debug_abort_cmnd(struct scsi_cmnd *cmnd) +{ + struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmnd); + unsigned long flags; + bool res; + + spin_lock_irqsave(&sdsc->lock, flags); + res = scsi_debug_stop_cmnd(cmnd); + spin_unlock_irqrestore(&sdsc->lock, flags); + + return res; } -/* Free queued command memory on heap */ -static void free_all_queued(void) +/* + * All we can do is set the cmnd as internally aborted and wait for it to + * finish. We cannot call scsi_done() as normal completion path may do that. + */ +static bool sdebug_stop_cmnd(struct request *rq, void *data) { - int j, k; - struct sdebug_queue *sqp; - struct sdebug_queued_cmd *sqcp; + scsi_debug_abort_cmnd(blk_mq_rq_to_pdu(rq)); - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { - for (k = 0; k < SDEBUG_CANQUEUE; ++k) { - sqcp = &sqp->qc_arr[k]; - kfree(sqcp->sd_dp); - sqcp->sd_dp = NULL; - } + return true; +} + +/* Deletes (stops) timers or work queues of all queued commands */ +static void stop_all_queued(void) +{ + struct sdebug_host_info *sdhp; + + mutex_lock(&sdebug_host_list_mutex); + list_for_each_entry(sdhp, &sdebug_host_list, host_list) { + struct Scsi_Host *shost = sdhp->shost; + + blk_mq_tagset_busy_iter(&shost->tag_set, sdebug_stop_cmnd, NULL); } + mutex_unlock(&sdebug_host_list_mutex); } static int scsi_debug_abort(struct scsi_cmnd *SCpnt) { - bool ok; + bool ok = scsi_debug_abort_cmnd(SCpnt); ++num_aborts; - if (SCpnt) { - ok = stop_queued_cmnd(SCpnt); - if (SCpnt->device && (SDEBUG_OPT_ALL_NOISE & sdebug_opts)) - sdev_printk(KERN_INFO, SCpnt->device, - "%s: command%s found\n", __func__, - ok ? "" : " not"); - } + + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) + sdev_printk(KERN_INFO, SCpnt->device, + "%s: command%s found\n", __func__, + ok ? "" : " not"); + return SUCCESS; } static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt) { + struct scsi_device *sdp = SCpnt->device; + struct sdebug_dev_info *devip = sdp->hostdata; + ++num_dev_resets; - if (SCpnt && SCpnt->device) { - struct scsi_device *sdp = SCpnt->device; - struct sdebug_dev_info *devip = - (struct sdebug_dev_info *)sdp->hostdata; - if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) - sdev_printk(KERN_INFO, sdp, "%s\n", __func__); - if (devip) - set_bit(SDEBUG_UA_POR, devip->uas_bm); - } + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + if (devip) + set_bit(SDEBUG_UA_POR, devip->uas_bm); + return SUCCESS; } static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) { - struct sdebug_host_info *sdbg_host; + struct scsi_device *sdp = SCpnt->device; + struct sdebug_host_info *sdbg_host = shost_to_sdebug_host(sdp->host); struct sdebug_dev_info *devip; - struct scsi_device *sdp; - struct Scsi_Host *hp; int k = 0; ++num_target_resets; - if (!SCpnt) - goto lie; - sdp = SCpnt->device; - if (!sdp) - goto lie; if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s\n", __func__); - hp = sdp->host; - if (!hp) - goto lie; - sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); - if (sdbg_host) { - list_for_each_entry(devip, - &sdbg_host->dev_info_list, - dev_list) - if (devip->target == sdp->id) { - set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); - ++k; - } + + list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { + if (devip->target == sdp->id) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } + if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s: %d device(s) found in target\n", __func__, k); -lie: + return SUCCESS; } static int scsi_debug_bus_reset(struct scsi_cmnd *SCpnt) { - struct sdebug_host_info *sdbg_host; + struct scsi_device *sdp = SCpnt->device; + struct sdebug_host_info *sdbg_host = shost_to_sdebug_host(sdp->host); struct sdebug_dev_info *devip; - struct scsi_device *sdp; - struct Scsi_Host *hp; int k = 0; ++num_bus_resets; - if (!(SCpnt && SCpnt->device)) - goto lie; - sdp = SCpnt->device; + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s\n", __func__); - hp = sdp->host; - if (hp) { - sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); - if (sdbg_host) { - list_for_each_entry(devip, - &sdbg_host->dev_info_list, - dev_list) { - set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); - ++k; - } - } + + list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; } + if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s: %d device(s) found in host\n", __func__, k); -lie: return SUCCESS; } @@ -5464,9 +5361,9 @@ static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt) int k = 0; ++num_host_resets; - if ((SCpnt->device) && (SDEBUG_OPT_ALL_NOISE & sdebug_opts)) + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__); - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { @@ -5474,7 +5371,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt) ++k; } } - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); stop_all_queued(); if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) sdev_printk(KERN_INFO, SCpnt->device, @@ -5537,11 +5434,18 @@ static void sdebug_build_parts(unsigned char *ramp, unsigned long store_size) static void block_unblock_all_queues(bool block) { - int j; - struct sdebug_queue *sqp; + struct sdebug_host_info *sdhp; - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) - atomic_set(&sqp->blocked, (int)block); + lockdep_assert_held(&sdebug_host_list_mutex); + + list_for_each_entry(sdhp, &sdebug_host_list, host_list) { + struct Scsi_Host *shost = sdhp->shost; + + if (block) + scsi_block_requests(shost); + else + scsi_unblock_requests(shost); + } } /* Adjust (by rounding down) the sdebug_cmnd_count so abs(every_nth)-1 @@ -5554,10 +5458,13 @@ static void tweak_cmnd_count(void) modulo = abs(sdebug_every_nth); if (modulo < 2) return; + + mutex_lock(&sdebug_host_list_mutex); block_unblock_all_queues(true); count = atomic_read(&sdebug_cmnd_count); atomic_set(&sdebug_cmnd_count, (count / modulo) * modulo); block_unblock_all_queues(false); + mutex_unlock(&sdebug_host_list_mutex); } static void clear_queue_stats(void) @@ -5577,6 +5484,33 @@ static bool inject_on_this_cmd(void) #define INCLUSIVE_TIMING_MAX_NS 1000000 /* 1 millisecond */ + +void sdebug_free_queued_cmd(struct sdebug_queued_cmd *sqcp) +{ + if (sqcp) + kmem_cache_free(queued_cmd_cache, sqcp); +} + +static struct sdebug_queued_cmd *sdebug_alloc_queued_cmd(struct scsi_cmnd *scmd) +{ + struct sdebug_queued_cmd *sqcp; + struct sdebug_defer *sd_dp; + + sqcp = kmem_cache_zalloc(queued_cmd_cache, GFP_ATOMIC); + if (!sqcp) + return NULL; + + sd_dp = &sqcp->sd_dp; + + hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); + sd_dp->hrt.function = sdebug_q_cmd_hrt_complete; + INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete); + + sqcp->scmd = scmd; + + return sqcp; +} + /* Complete the processing of the thread that queued a SCSI command to this * driver. It either completes the command by calling cmnd_done() or * schedules a hr timer or work queue then returns 0. Returns @@ -5588,13 +5522,11 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, struct sdebug_dev_info *), int delta_jiff, int ndelay) { - bool new_sd_dp; - bool inject = false; - bool polled = scsi_cmd_to_rq(cmnd)->cmd_flags & REQ_POLLED; - int k, num_in_q, qdepth; - unsigned long iflags; + struct request *rq = scsi_cmd_to_rq(cmnd); + bool polled = rq->cmd_flags & REQ_POLLED; + struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmnd); + unsigned long flags; u64 ns_from_boot = 0; - struct sdebug_queue *sqp; struct sdebug_queued_cmd *sqcp; struct scsi_device *sdp; struct sdebug_defer *sd_dp; @@ -5609,66 +5541,30 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, if (delta_jiff == 0) goto respond_in_thread; - sqp = get_queue(cmnd); - spin_lock_irqsave(&sqp->qc_lock, iflags); - if (unlikely(atomic_read(&sqp->blocked))) { - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - return SCSI_MLQUEUE_HOST_BUSY; - } - num_in_q = atomic_read(&devip->num_in_q); - qdepth = cmnd->device->queue_depth; - if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) { - if (scsi_result) { - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - goto respond_in_thread; - } else - scsi_result = device_qfull_result; - } else if (unlikely(sdebug_every_nth && - (SDEBUG_OPT_RARE_TSF & sdebug_opts) && - (scsi_result == 0))) { - if ((num_in_q == (qdepth - 1)) && + + if (unlikely(sdebug_every_nth && (SDEBUG_OPT_RARE_TSF & sdebug_opts) && + (scsi_result == 0))) { + int num_in_q = scsi_device_busy(sdp); + int qdepth = cmnd->device->queue_depth; + + if ((num_in_q == qdepth) && (atomic_inc_return(&sdebug_a_tsf) >= abs(sdebug_every_nth))) { atomic_set(&sdebug_a_tsf, 0); - inject = true; scsi_result = device_qfull_result; - } - } - k = find_first_zero_bit(sqp->in_use_bm, sdebug_max_queue); - if (unlikely(k >= sdebug_max_queue)) { - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - if (scsi_result) - goto respond_in_thread; - scsi_result = device_qfull_result; - if (SDEBUG_OPT_Q_NOISE & sdebug_opts) - sdev_printk(KERN_INFO, sdp, "%s: max_queue=%d exceeded: TASK SET FULL\n", - __func__, sdebug_max_queue); - goto respond_in_thread; - } - set_bit(k, sqp->in_use_bm); - atomic_inc(&devip->num_in_q); - sqcp = &sqp->qc_arr[k]; - sqcp->a_cmnd = cmnd; - cmnd->host_scribble = (unsigned char *)sqcp; - sd_dp = sqcp->sd_dp; - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - - if (!sd_dp) { - sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC); - if (!sd_dp) { - atomic_dec(&devip->num_in_q); - clear_bit(k, sqp->in_use_bm); - return SCSI_MLQUEUE_HOST_BUSY; + if (unlikely(SDEBUG_OPT_Q_NOISE & sdebug_opts)) + sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, <inject> status: TASK SET FULL\n", + __func__, num_in_q); } - new_sd_dp = true; - } else { - new_sd_dp = false; } - /* Set the hostwide tag */ - if (sdebug_host_max_queue) - sd_dp->hc_idx = get_tag(cmnd); + sqcp = sdebug_alloc_queued_cmd(cmnd); + if (!sqcp) { + pr_err("%s no alloc\n", __func__); + return SCSI_MLQUEUE_HOST_BUSY; + } + sd_dp = &sqcp->sd_dp; if (polled) ns_from_boot = ktime_get_boottime_ns(); @@ -5715,14 +5611,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, u64 d = ktime_get_boottime_ns() - ns_from_boot; if (kt <= d) { /* elapsed duration >= kt */ - spin_lock_irqsave(&sqp->qc_lock, iflags); - sqcp->a_cmnd = NULL; - atomic_dec(&devip->num_in_q); - clear_bit(k, sqp->in_use_bm); - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - if (new_sd_dp) - kfree(sd_dp); /* call scsi_done() from this thread */ + sdebug_free_queued_cmd(sqcp); scsi_done(cmnd); return 0; } @@ -5730,72 +5620,54 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, kt -= d; } } + if (sdebug_statistics) + sd_dp->issuing_cpu = raw_smp_processor_id(); if (polled) { + spin_lock_irqsave(&sdsc->lock, flags); sd_dp->cmpl_ts = ktime_add(ns_to_ktime(ns_from_boot), kt); - spin_lock_irqsave(&sqp->qc_lock, iflags); - if (!sd_dp->init_poll) { - sd_dp->init_poll = true; - sqcp->sd_dp = sd_dp; - sd_dp->sqa_idx = sqp - sdebug_q_arr; - sd_dp->qc_idx = k; - } + ASSIGN_QUEUED_CMD(cmnd, sqcp); WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_POLL); - spin_unlock_irqrestore(&sqp->qc_lock, iflags); + spin_unlock_irqrestore(&sdsc->lock, flags); } else { - if (!sd_dp->init_hrt) { - sd_dp->init_hrt = true; - sqcp->sd_dp = sd_dp; - hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC, - HRTIMER_MODE_REL_PINNED); - sd_dp->hrt.function = sdebug_q_cmd_hrt_complete; - sd_dp->sqa_idx = sqp - sdebug_q_arr; - sd_dp->qc_idx = k; - } - WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_HRT); /* schedule the invocation of scsi_done() for a later time */ + spin_lock_irqsave(&sdsc->lock, flags); + ASSIGN_QUEUED_CMD(cmnd, sqcp); + WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_HRT); hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED); + /* + * The completion handler will try to grab sqcp->lock, + * so there is no chance that the completion handler + * will call scsi_done() until we release the lock + * here (so ok to keep referencing sdsc). + */ + spin_unlock_irqrestore(&sdsc->lock, flags); } - if (sdebug_statistics) - sd_dp->issuing_cpu = raw_smp_processor_id(); } else { /* jdelay < 0, use work queue */ if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) && - atomic_read(&sdeb_inject_pending))) + atomic_read(&sdeb_inject_pending))) { sd_dp->aborted = true; + atomic_set(&sdeb_inject_pending, 0); + sdev_printk(KERN_INFO, sdp, "abort request tag=%#x\n", + blk_mq_unique_tag_to_tag(get_tag(cmnd))); + } + + if (sdebug_statistics) + sd_dp->issuing_cpu = raw_smp_processor_id(); if (polled) { + spin_lock_irqsave(&sdsc->lock, flags); + ASSIGN_QUEUED_CMD(cmnd, sqcp); sd_dp->cmpl_ts = ns_to_ktime(ns_from_boot); - spin_lock_irqsave(&sqp->qc_lock, iflags); - if (!sd_dp->init_poll) { - sd_dp->init_poll = true; - sqcp->sd_dp = sd_dp; - sd_dp->sqa_idx = sqp - sdebug_q_arr; - sd_dp->qc_idx = k; - } WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_POLL); - spin_unlock_irqrestore(&sqp->qc_lock, iflags); + spin_unlock_irqrestore(&sdsc->lock, flags); } else { - if (!sd_dp->init_wq) { - sd_dp->init_wq = true; - sqcp->sd_dp = sd_dp; - sd_dp->sqa_idx = sqp - sdebug_q_arr; - sd_dp->qc_idx = k; - INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete); - } + spin_lock_irqsave(&sdsc->lock, flags); + ASSIGN_QUEUED_CMD(cmnd, sqcp); WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_WQ); schedule_work(&sd_dp->ew.work); - } - if (sdebug_statistics) - sd_dp->issuing_cpu = raw_smp_processor_id(); - if (unlikely(sd_dp->aborted)) { - sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", - scsi_cmd_to_rq(cmnd)->tag); - blk_abort_request(scsi_cmd_to_rq(cmnd)); - atomic_set(&sdeb_inject_pending, 0); - sd_dp->aborted = false; + spin_unlock_irqrestore(&sdsc->lock, flags); } } - if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && scsi_result == device_qfull_result)) - sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__, - num_in_q, (inject ? "<inject> " : ""), "status: TASK SET FULL"); + return 0; respond_in_thread: /* call back to mid-layer using invocation thread */ @@ -5996,14 +5868,39 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, return length; } +struct sdebug_submit_queue_data { + int *first; + int *last; + int queue_num; +}; + +static bool sdebug_submit_queue_iter(struct request *rq, void *opaque) +{ + struct sdebug_submit_queue_data *data = opaque; + u32 unique_tag = blk_mq_unique_tag(rq); + u16 hwq = blk_mq_unique_tag_to_hwq(unique_tag); + u16 tag = blk_mq_unique_tag_to_tag(unique_tag); + int queue_num = data->queue_num; + + if (hwq != queue_num) + return true; + + /* Rely on iter'ing in ascending tag order */ + if (*data->first == -1) + *data->first = *data->last = tag; + else + *data->last = tag; + + return true; +} + /* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the * same for each scsi_debug host (if more than one). Some of the counters * output are not atomics so might be inaccurate in a busy system. */ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) { - int f, j, l; - struct sdebug_queue *sqp; struct sdebug_host_info *sdhp; + int j; seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n", SDEBUG_VERSION, sdebug_version_date); @@ -6031,11 +5928,17 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) atomic_read(&sdeb_mq_poll_count)); seq_printf(m, "submit_queues=%d\n", submit_queues); - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { + for (j = 0; j < submit_queues; ++j) { + int f = -1, l = -1; + struct sdebug_submit_queue_data data = { + .queue_num = j, + .first = &f, + .last = &l, + }; seq_printf(m, " queue %d:\n", j); - f = find_first_bit(sqp->in_use_bm, sdebug_max_queue); - if (f != sdebug_max_queue) { - l = find_last_bit(sqp->in_use_bm, sdebug_max_queue); + blk_mq_tagset_busy_iter(&host->tag_set, sdebug_submit_queue_iter, + &data); + if (f >= 0) { seq_printf(m, " in_use_bm BUSY: %s: %d,%d\n", "first,last bits", f, l); } @@ -6086,15 +5989,15 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, if (count > 0 && sscanf(buf, "%d", &jdelay) == 1) { res = count; if (sdebug_jdelay != jdelay) { - int j, k; - struct sdebug_queue *sqp; + struct sdebug_host_info *sdhp; + mutex_lock(&sdebug_host_list_mutex); block_unblock_all_queues(true); - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; - ++j, ++sqp) { - k = find_first_bit(sqp->in_use_bm, - sdebug_max_queue); - if (k != sdebug_max_queue) { + + list_for_each_entry(sdhp, &sdebug_host_list, host_list) { + struct Scsi_Host *shost = sdhp->shost; + + if (scsi_host_busy(shost)) { res = -EBUSY; /* queued commands */ break; } @@ -6104,6 +6007,7 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, sdebug_ndelay = 0; } block_unblock_all_queues(false); + mutex_unlock(&sdebug_host_list_mutex); } return res; } @@ -6126,25 +6030,27 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, (ndelay >= 0) && (ndelay < (1000 * 1000 * 1000))) { res = count; if (sdebug_ndelay != ndelay) { - int j, k; - struct sdebug_queue *sqp; + struct sdebug_host_info *sdhp; + mutex_lock(&sdebug_host_list_mutex); block_unblock_all_queues(true); - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; - ++j, ++sqp) { - k = find_first_bit(sqp->in_use_bm, - sdebug_max_queue); - if (k != sdebug_max_queue) { + + list_for_each_entry(sdhp, &sdebug_host_list, host_list) { + struct Scsi_Host *shost = sdhp->shost; + + if (scsi_host_busy(shost)) { res = -EBUSY; /* queued commands */ break; } } + if (res > 0) { sdebug_ndelay = ndelay; sdebug_jdelay = ndelay ? JDELAY_OVERRIDDEN : DEF_JDELAY; } block_unblock_all_queues(false); + mutex_unlock(&sdebug_host_list_mutex); } return res; } @@ -6390,13 +6296,13 @@ static ssize_t lun_format_store(struct device_driver *ddp, const char *buf, struct sdebug_host_info *sdhp; struct sdebug_dev_info *dp; - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_for_each_entry(sdhp, &sdebug_host_list, host_list) { list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) { set_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm); } } - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); } return count; } @@ -6426,7 +6332,7 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, struct sdebug_host_info *sdhp; struct sdebug_dev_info *dp; - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_for_each_entry(sdhp, &sdebug_host_list, host_list) { list_for_each_entry(dp, &sdhp->dev_info_list, @@ -6435,7 +6341,7 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, dp->uas_bm); } } - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); } return count; } @@ -6452,28 +6358,19 @@ static ssize_t max_queue_show(struct device_driver *ddp, char *buf) static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, size_t count) { - int j, n, k, a; - struct sdebug_queue *sqp; + int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && (n <= SDEBUG_CANQUEUE) && (sdebug_host_max_queue == 0)) { - block_unblock_all_queues(true); - k = 0; - for (j = 0, sqp = sdebug_q_arr; j < submit_queues; - ++j, ++sqp) { - a = find_last_bit(sqp->in_use_bm, SDEBUG_CANQUEUE); - if (a > k) - k = a; - } - sdebug_max_queue = n; - if (k == SDEBUG_CANQUEUE) - atomic_set(&retired_max_queue, 0); - else if (k >= n) - atomic_set(&retired_max_queue, k + 1); + mutex_lock(&sdebug_host_list_mutex); + + /* We may only change sdebug_max_queue when we have no shosts */ + if (list_empty(&sdebug_host_list)) + sdebug_max_queue = n; else - atomic_set(&retired_max_queue, 0); - block_unblock_all_queues(false); + count = -EBUSY; + mutex_unlock(&sdebug_host_list_mutex); return count; } return -EINVAL; @@ -6542,7 +6439,7 @@ static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, struct sdebug_host_info *sdhp; struct sdebug_dev_info *dp; - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_for_each_entry(sdhp, &sdebug_host_list, host_list) { list_for_each_entry(dp, &sdhp->dev_info_list, @@ -6551,7 +6448,7 @@ static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, dp->uas_bm); } } - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); } return count; } @@ -6901,7 +6798,6 @@ static int __init scsi_debug_init(void) ramdisk_lck_a[0] = &atomic_rw; ramdisk_lck_a[1] = &atomic_rw2; - atomic_set(&retired_max_queue, 0); if (sdebug_ndelay >= 1000 * 1000 * 1000) { pr_warn("ndelay must be less than 1 second, ignored\n"); @@ -6997,13 +6893,6 @@ static int __init scsi_debug_init(void) sdebug_max_queue); } - sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue), - GFP_KERNEL); - if (sdebug_q_arr == NULL) - return -ENOMEM; - for (k = 0; k < submit_queues; ++k) - spin_lock_init(&sdebug_q_arr[k].qc_lock); - /* * check for host managed zoned block device specified with * ptype=0x14 or zbc=XXX. @@ -7012,10 +6901,8 @@ static int __init scsi_debug_init(void) sdeb_zbc_model = BLK_ZONED_HM; } else if (sdeb_zbc_model_s && *sdeb_zbc_model_s) { k = sdeb_zbc_model_str(sdeb_zbc_model_s); - if (k < 0) { - ret = k; - goto free_q_arr; - } + if (k < 0) + return k; sdeb_zbc_model = k; switch (sdeb_zbc_model) { case BLK_ZONED_NONE: @@ -7027,8 +6914,7 @@ static int __init scsi_debug_init(void) break; default: pr_err("Invalid ZBC model\n"); - ret = -EINVAL; - goto free_q_arr; + return -EINVAL; } } if (sdeb_zbc_model != BLK_ZONED_NONE) { @@ -7075,17 +6961,14 @@ static int __init scsi_debug_init(void) sdebug_unmap_granularity <= sdebug_unmap_alignment) { pr_err("ERR: unmap_granularity <= unmap_alignment\n"); - ret = -EINVAL; - goto free_q_arr; + return -EINVAL; } } xa_init_flags(per_store_ap, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); if (want_store) { idx = sdebug_add_store(); - if (idx < 0) { - ret = idx; - goto free_q_arr; - } + if (idx < 0) + return idx; } pseudo_primary = root_device_register("pseudo_0"); @@ -7108,6 +6991,12 @@ static int __init scsi_debug_init(void) hosts_to_add = sdebug_add_host; sdebug_add_host = 0; + queued_cmd_cache = KMEM_CACHE(sdebug_queued_cmd, SLAB_HWCACHE_ALIGN); + if (!queued_cmd_cache) { + ret = -ENOMEM; + goto driver_unreg; + } + for (k = 0; k < hosts_to_add; k++) { if (want_store && k == 0) { ret = sdebug_add_host_helper(idx); @@ -7130,14 +7019,14 @@ static int __init scsi_debug_init(void) return 0; +driver_unreg: + driver_unregister(&sdebug_driverfs_driver); bus_unreg: bus_unregister(&pseudo_lld_bus); dev_unreg: root_device_unregister(pseudo_primary); free_vm: sdebug_erase_store(idx, NULL); -free_q_arr: - kfree(sdebug_q_arr); return ret; } @@ -7145,17 +7034,15 @@ static void __exit scsi_debug_exit(void) { int k = sdebug_num_hosts; - stop_all_queued(); for (; k; k--) sdebug_do_remove_host(true); - free_all_queued(); + kmem_cache_destroy(queued_cmd_cache); driver_unregister(&sdebug_driverfs_driver); bus_unregister(&pseudo_lld_bus); root_device_unregister(pseudo_primary); sdebug_erase_all_stores(false); xa_destroy(per_store_ap); - kfree(sdebug_q_arr); } device_initcall(scsi_debug_init); @@ -7165,7 +7052,7 @@ static void sdebug_release_adapter(struct device *dev) { struct sdebug_host_info *sdbg_host; - sdbg_host = to_sdebug_host(dev); + sdbg_host = dev_to_sdebug_host(dev); kfree(sdbg_host); } @@ -7311,9 +7198,9 @@ static int sdebug_add_host_helper(int per_host_idx) goto clean; } - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_add_tail(&sdbg_host->host_list, &sdebug_host_list); - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); sdbg_host->dev.bus = &pseudo_lld_bus; sdbg_host->dev.parent = pseudo_primary; @@ -7322,9 +7209,9 @@ static int sdebug_add_host_helper(int per_host_idx) error = device_register(&sdbg_host->dev); if (error) { - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); list_del(&sdbg_host->host_list); - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); goto clean; } @@ -7364,7 +7251,7 @@ static void sdebug_do_remove_host(bool the_end) struct sdebug_host_info *sdbg_host = NULL; struct sdebug_host_info *sdbg_host2; - spin_lock(&sdebug_host_list_lock); + mutex_lock(&sdebug_host_list_mutex); if (!list_empty(&sdebug_host_list)) { sdbg_host = list_entry(sdebug_host_list.prev, struct sdebug_host_info, host_list); @@ -7389,7 +7276,7 @@ static void sdebug_do_remove_host(bool the_end) } if (sdbg_host) list_del(&sdbg_host->host_list); - spin_unlock(&sdebug_host_list_lock); + mutex_unlock(&sdebug_host_list_mutex); if (!sdbg_host) return; @@ -7400,16 +7287,13 @@ static void sdebug_do_remove_host(bool the_end) static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) { - int num_in_q = 0; - struct sdebug_dev_info *devip; + struct sdebug_dev_info *devip = sdev->hostdata; - block_unblock_all_queues(true); - devip = (struct sdebug_dev_info *)sdev->hostdata; - if (NULL == devip) { - block_unblock_all_queues(false); + if (!devip) return -ENODEV; - } - num_in_q = atomic_read(&devip->num_in_q); + + mutex_lock(&sdebug_host_list_mutex); + block_unblock_all_queues(true); if (qdepth > SDEBUG_CANQUEUE) { qdepth = SDEBUG_CANQUEUE; @@ -7421,11 +7305,12 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) if (qdepth != sdev->queue_depth) scsi_change_queue_depth(sdev, qdepth); - if (SDEBUG_OPT_Q_NOISE & sdebug_opts) { - sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n", - __func__, qdepth, num_in_q); - } block_unblock_all_queues(false); + mutex_unlock(&sdebug_host_list_mutex); + + if (SDEBUG_OPT_Q_NOISE & sdebug_opts) + sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d\n", __func__, qdepth); + return sdev->queue_depth; } @@ -7515,94 +7400,82 @@ static void sdebug_map_queues(struct Scsi_Host *shost) } } -static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) +struct sdebug_blk_mq_poll_data { + unsigned int queue_num; + int *num_entries; +}; + +/* + * We don't handle aborted commands here, but it does not seem possible to have + * aborted polled commands from schedule_resp() + */ +static bool sdebug_blk_mq_poll_iter(struct request *rq, void *opaque) { - bool first; - bool retiring = false; - int num_entries = 0; - unsigned int qc_idx = 0; - unsigned long iflags; - ktime_t kt_from_boot = ktime_get_boottime(); - struct sdebug_queue *sqp; - struct sdebug_queued_cmd *sqcp; - struct scsi_cmnd *scp; - struct sdebug_dev_info *devip; + struct sdebug_blk_mq_poll_data *data = opaque; + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmd); struct sdebug_defer *sd_dp; + u32 unique_tag = blk_mq_unique_tag(rq); + u16 hwq = blk_mq_unique_tag_to_hwq(unique_tag); + struct sdebug_queued_cmd *sqcp; + unsigned long flags; + int queue_num = data->queue_num; + ktime_t time; - sqp = sdebug_q_arr + queue_num; + /* We're only interested in one queue for this iteration */ + if (hwq != queue_num) + return true; - spin_lock_irqsave(&sqp->qc_lock, iflags); + /* Subsequent checks would fail if this failed, but check anyway */ + if (!test_bit(SCMD_STATE_INFLIGHT, &cmd->state)) + return true; - qc_idx = find_first_bit(sqp->in_use_bm, sdebug_max_queue); - if (qc_idx >= sdebug_max_queue) - goto unlock; + time = ktime_get_boottime(); - for (first = true; first || qc_idx + 1 < sdebug_max_queue; ) { - if (first) { - first = false; - if (!test_bit(qc_idx, sqp->in_use_bm)) - continue; - } else { - qc_idx = find_next_bit(sqp->in_use_bm, sdebug_max_queue, qc_idx + 1); - } - if (qc_idx >= sdebug_max_queue) - break; + spin_lock_irqsave(&sdsc->lock, flags); + sqcp = TO_QUEUED_CMD(cmd); + if (!sqcp) { + spin_unlock_irqrestore(&sdsc->lock, flags); + return true; + } - sqcp = &sqp->qc_arr[qc_idx]; - sd_dp = sqcp->sd_dp; - if (unlikely(!sd_dp)) - continue; - scp = sqcp->a_cmnd; - if (unlikely(scp == NULL)) { - pr_err("scp is NULL, queue_num=%d, qc_idx=%u from %s\n", - queue_num, qc_idx, __func__); - break; - } - if (READ_ONCE(sd_dp->defer_t) == SDEB_DEFER_POLL) { - if (kt_from_boot < sd_dp->cmpl_ts) - continue; + sd_dp = &sqcp->sd_dp; + if (READ_ONCE(sd_dp->defer_t) != SDEB_DEFER_POLL) { + spin_unlock_irqrestore(&sdsc->lock, flags); + return true; + } - } else /* ignoring non REQ_POLLED requests */ - continue; - devip = (struct sdebug_dev_info *)scp->device->hostdata; - if (likely(devip)) - atomic_dec(&devip->num_in_q); - else - pr_err("devip=NULL from %s\n", __func__); - if (unlikely(atomic_read(&retired_max_queue) > 0)) - retiring = true; - - sqcp->a_cmnd = NULL; - if (unlikely(!test_and_clear_bit(qc_idx, sqp->in_use_bm))) { - pr_err("Unexpected completion sqp %p queue_num=%d qc_idx=%u from %s\n", - sqp, queue_num, qc_idx, __func__); - break; - } - if (unlikely(retiring)) { /* user has reduced max_queue */ - int k, retval; + if (time < sd_dp->cmpl_ts) { + spin_unlock_irqrestore(&sdsc->lock, flags); + return true; + } - retval = atomic_read(&retired_max_queue); - if (qc_idx >= retval) { - pr_err("index %d too large\n", retval); - break; - } - k = find_last_bit(sqp->in_use_bm, retval); - if ((k < sdebug_max_queue) || (k == retval)) - atomic_set(&retired_max_queue, 0); - else - atomic_set(&retired_max_queue, k + 1); - } - WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_NONE); - spin_unlock_irqrestore(&sqp->qc_lock, iflags); - scsi_done(scp); /* callback to mid level */ - num_entries++; - spin_lock_irqsave(&sqp->qc_lock, iflags); - if (find_first_bit(sqp->in_use_bm, sdebug_max_queue) >= sdebug_max_queue) - break; + ASSIGN_QUEUED_CMD(cmd, NULL); + spin_unlock_irqrestore(&sdsc->lock, flags); + + if (sdebug_statistics) { + atomic_inc(&sdebug_completions); + if (raw_smp_processor_id() != sd_dp->issuing_cpu) + atomic_inc(&sdebug_miss_cpus); } -unlock: - spin_unlock_irqrestore(&sqp->qc_lock, iflags); + sdebug_free_queued_cmd(sqcp); + + scsi_done(cmd); /* callback to mid level */ + (*data->num_entries)++; + return true; +} + +static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) +{ + int num_entries = 0; + struct sdebug_blk_mq_poll_data data = { + .queue_num = queue_num, + .num_entries = &num_entries, + }; + + blk_mq_tagset_busy_iter(&shost->tag_set, sdebug_blk_mq_poll_iter, + &data); if (num_entries > 0) atomic_add(num_entries, &sdeb_mq_poll_count); @@ -7776,6 +7649,16 @@ err_out: return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, NULL, 0, 0); } +static int sdebug_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmd); + + spin_lock_init(&sdsc->lock); + + return 0; +} + + static struct scsi_host_template sdebug_driver_template = { .show_info = scsi_debug_show_info, .write_info = scsi_debug_write_info, @@ -7803,6 +7686,8 @@ static struct scsi_host_template sdebug_driver_template = { .max_segment_size = -1U, .module = THIS_MODULE, .track_queue_depth = 1, + .cmd_size = sizeof(struct sdebug_scsi_cmd), + .init_cmd_priv = sdebug_init_cmd_priv, }; static int sdebug_driver_probe(struct device *dev) @@ -7812,14 +7697,14 @@ static int sdebug_driver_probe(struct device *dev) struct Scsi_Host *hpnt; int hprot; - sdbg_host = to_sdebug_host(dev); + sdbg_host = dev_to_sdebug_host(dev); sdebug_driver_template.can_queue = sdebug_max_queue; sdebug_driver_template.cmd_per_lun = sdebug_max_queue; if (!sdebug_clustering) sdebug_driver_template.dma_boundary = PAGE_SIZE - 1; - hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); + hpnt = scsi_host_alloc(&sdebug_driver_template, 0); if (NULL == hpnt) { pr_err("scsi_host_alloc failed\n"); error = -ENODEV; @@ -7862,7 +7747,6 @@ static int sdebug_driver_probe(struct device *dev) hpnt->nr_maps = 3; sdbg_host->shost = hpnt; - *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; if ((hpnt->this_id >= 0) && (sdebug_num_tgts > hpnt->this_id)) hpnt->max_id = sdebug_num_tgts + 1; else @@ -7936,7 +7820,7 @@ static void sdebug_driver_remove(struct device *dev) struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *sdbg_devinfo, *tmp; - sdbg_host = to_sdebug_host(dev); + sdbg_host = dev_to_sdebug_host(dev); scsi_remove_host(sdbg_host->shost); @@ -7950,15 +7834,8 @@ static void sdebug_driver_remove(struct device *dev) scsi_host_put(sdbg_host->shost); } -static int pseudo_lld_bus_match(struct device *dev, - struct device_driver *dev_driver) -{ - return 1; -} - static struct bus_type pseudo_lld_bus = { .name = "pseudo", - .match = pseudo_lld_bus_match, .probe = sdebug_driver_probe, .remove = sdebug_driver_remove, .drv_groups = sdebug_drv_groups, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2aa2c2aee6e7..3ec8bfd4090f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -58,7 +58,7 @@ #define HOST_RESET_SETTLE_TIME (10) static int scsi_eh_try_stu(struct scsi_cmnd *scmd); -static enum scsi_disposition scsi_try_to_abort_cmd(struct scsi_host_template *, +static enum scsi_disposition scsi_try_to_abort_cmd(const struct scsi_host_template *, struct scsi_cmnd *); void scsi_eh_wakeup(struct Scsi_Host *shost) @@ -699,7 +699,7 @@ EXPORT_SYMBOL_GPL(scsi_check_sense); static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) { - struct scsi_host_template *sht = sdev->host->hostt; + const struct scsi_host_template *sht = sdev->host->hostt; struct scsi_device *tmp_sdev; if (!sht->track_queue_depth || @@ -731,7 +731,7 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) static void scsi_handle_queue_full(struct scsi_device *sdev) { - struct scsi_host_template *sht = sdev->host->hostt; + const struct scsi_host_template *sht = sdev->host->hostt; struct scsi_device *tmp_sdev; if (!sht->track_queue_depth) @@ -840,7 +840,7 @@ static enum scsi_disposition scsi_try_host_reset(struct scsi_cmnd *scmd) unsigned long flags; enum scsi_disposition rtn; struct Scsi_Host *host = scmd->device->host; - struct scsi_host_template *hostt = host->hostt; + const struct scsi_host_template *hostt = host->hostt; SCSI_LOG_ERROR_RECOVERY(3, shost_printk(KERN_INFO, host, "Snd Host RST\n")); @@ -870,7 +870,7 @@ static enum scsi_disposition scsi_try_bus_reset(struct scsi_cmnd *scmd) unsigned long flags; enum scsi_disposition rtn; struct Scsi_Host *host = scmd->device->host; - struct scsi_host_template *hostt = host->hostt; + const struct scsi_host_template *hostt = host->hostt; SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "%s: Snd Bus RST\n", __func__)); @@ -912,7 +912,7 @@ static enum scsi_disposition scsi_try_target_reset(struct scsi_cmnd *scmd) unsigned long flags; enum scsi_disposition rtn; struct Scsi_Host *host = scmd->device->host; - struct scsi_host_template *hostt = host->hostt; + const struct scsi_host_template *hostt = host->hostt; if (!hostt->eh_target_reset_handler) return FAILED; @@ -941,7 +941,7 @@ static enum scsi_disposition scsi_try_target_reset(struct scsi_cmnd *scmd) static enum scsi_disposition scsi_try_bus_device_reset(struct scsi_cmnd *scmd) { enum scsi_disposition rtn; - struct scsi_host_template *hostt = scmd->device->host->hostt; + const struct scsi_host_template *hostt = scmd->device->host->hostt; if (!hostt->eh_device_reset_handler) return FAILED; @@ -970,7 +970,7 @@ static enum scsi_disposition scsi_try_bus_device_reset(struct scsi_cmnd *scmd) * link down on FibreChannel) */ static enum scsi_disposition -scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd) +scsi_try_to_abort_cmd(const struct scsi_host_template *hostt, struct scsi_cmnd *scmd) { if (!hostt->eh_abort_handler) return FAILED; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ee28f73af4d4..603e8fcfcb8a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -296,7 +296,7 @@ store_host_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct Scsi_Host *shost = class_to_shost(dev); - struct scsi_host_template *sht = shost->hostt; + const struct scsi_host_template *sht = shost->hostt; int ret = -EINVAL; int type; @@ -1025,7 +1025,7 @@ sdev_store_queue_depth(struct device *dev, struct device_attribute *attr, { int depth, retval; struct scsi_device *sdev = to_scsi_device(dev); - struct scsi_host_template *sht = sdev->host->hostt; + const struct scsi_host_template *sht = sdev->host->hostt; if (!sht->change_queue_depth) return -EINVAL; @@ -1606,7 +1606,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) { unsigned long flags; struct Scsi_Host *shost = sdev->host; - struct scsi_host_template *hostt = shost->hostt; + const struct scsi_host_template *hostt = shost->hostt; struct scsi_target *starget = sdev->sdev_target; device_initialize(&sdev->sdev_gendev); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index f12e9467ebb4..64ff2629eaf9 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -905,7 +905,7 @@ fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf, { struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf; struct fc_tlv_desc *tlv; - u32 desc_cnt = 0, bytes_remain; + u32 bytes_remain; u32 dtag; enum fc_host_event_code event_code = event_acknowledge ? FCH_EVT_LINK_FPIN_ACK : FCH_EVT_LINK_FPIN; @@ -932,7 +932,6 @@ fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf, fc_fpin_congn_stats_update(shost, tlv); } - desc_cnt++; bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); tlv = fc_tlv_next_desc(tlv); } diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index 57d5dff62f63..88e2b5eb9caa 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -204,7 +204,7 @@ static inline void init_hpc_chain(struct ip22_hostdata *hdata) * arguments not with pointers. So this is going to blow up beautyfully * on 64-bit systems with memory outside the compat address spaces. */ -static struct scsi_host_template sgiwd93_template = { +static const struct scsi_host_template sgiwd93_template = { .module = THIS_MODULE, .proc_name = "SGIWD93", .name = "SGI WD93", diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 49a8f91810b6..03de97cd72c2 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -7403,7 +7403,7 @@ static struct attribute *pqi_sdev_attrs[] = { ATTRIBUTE_GROUPS(pqi_sdev); -static struct scsi_host_template pqi_driver_template = { +static const struct scsi_host_template pqi_driver_template = { .module = THIS_MODULE, .name = DRIVER_NAME_SHORT, .proc_name = DRIVER_NAME_SHORT, diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c index 174f7811fe50..cc824dcfe7da 100644 --- a/drivers/scsi/snic/snic_main.c +++ b/drivers/scsi/snic/snic_main.c @@ -100,7 +100,7 @@ snic_change_queue_depth(struct scsi_device *sdev, int qdepth) return sdev->queue_depth; } -static struct scsi_host_template snic_host_template = { +static const struct scsi_host_template snic_host_template = { .module = THIS_MODULE, .name = SNIC_DRV_NAME, .queuecommand = snic_queuecommand, diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index 961af6fc21bc..c50ede326cc4 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -487,7 +487,6 @@ snic_process_icmnd_cmpl_status(struct snic *snic, struct scsi_cmnd *sc) { u8 scsi_stat = icmnd_cmpl->scsi_status; - u64 xfer_len = 0; int ret = 0; /* Mark the IO as complete */ @@ -496,15 +495,11 @@ snic_process_icmnd_cmpl_status(struct snic *snic, if (likely(cmpl_stat == SNIC_STAT_IO_SUCCESS)) { sc->result = (DID_OK << 16) | scsi_stat; - xfer_len = scsi_bufflen(sc); - /* Update SCSI Cmd with resid value */ scsi_set_resid(sc, le32_to_cpu(icmnd_cmpl->resid)); - if (icmnd_cmpl->flags & SNIC_ICMND_CMPL_UNDR_RUN) { - xfer_len -= le32_to_cpu(icmnd_cmpl->resid); + if (icmnd_cmpl->flags & SNIC_ICMND_CMPL_UNDR_RUN) atomic64_inc(&snic->s_stats.misc.io_under_run); - } if (icmnd_cmpl->scsi_status == SAM_STAT_TASK_SET_FULL) atomic64_inc(&snic->s_stats.misc.qfull); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 9e51dcd30bfd..12869e6d4ebd 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -590,20 +590,15 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose) { struct scsi_cd *cd = cdi->handle; struct scsi_device *sdev = cd->device; - int retval; /* * If the device is in error recovery, wait until it is done. * If the device is offline, then disallow any access to it. */ - retval = -ENXIO; if (!scsi_block_when_processing_errors(sdev)) - goto error_out; + return -ENXIO; return 0; - -error_out: - return retval; } static void sr_release(struct cdrom_device_info *cdi) diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 8def242675ef..5b230e149c3d 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -1472,7 +1472,7 @@ static int stex_biosparam(struct scsi_device *sdev, return 0; } -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = DRV_NAME, .proc_name = DRV_NAME, diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index d3489ac7ab28..30f67cbf4a7a 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -169,7 +169,7 @@ static const struct esp_driver_ops sun3x_esp_ops = { static int esp_sun3x_probe(struct platform_device *dev) { - struct scsi_host_template *tpnt = &scsi_esp_template; + const struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; struct resource *res; diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 5dc38d35745b..d06e933191a2 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -146,7 +146,7 @@ static void esp_get_differential(struct esp *esp) struct device_node *dp; dp = op->dev.of_node; - if (of_find_property(dp, "differential", NULL)) + if (of_property_read_bool(dp, "differential")) esp->flags |= ESP_FLAG_DIFFERENTIAL; else esp->flags &= ~ESP_FLAG_DIFFERENTIAL; @@ -451,7 +451,7 @@ static const struct esp_driver_ops sbus_esp_ops = { static int esp_sbus_probe_one(struct platform_device *op, struct platform_device *espdma, int hme) { - struct scsi_host_template *tpnt = &scsi_esp_template; + const struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; int err; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 2e2852bd5860..ee36a9c15d9c 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1224,7 +1224,7 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev, * If all is OK, install interrupt handling and * start the timer daemon. */ -static struct Scsi_Host *sym_attach(struct scsi_host_template *tpnt, int unit, +static struct Scsi_Host *sym_attach(const struct scsi_host_template *tpnt, int unit, struct sym_device *dev) { struct sym_data *sym_data; @@ -1625,7 +1625,7 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev) /* * Driver host template. */ -static struct scsi_host_template sym2_template = { +static const struct scsi_host_template sym2_template = { .module = THIS_MODULE, .name = "sym53c8xx", .info = sym53c8xx_info, diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index c5558c45ab3a..58498da9869a 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -746,7 +746,7 @@ static enum scsi_timeout_action virtscsi_eh_timed_out(struct scsi_cmnd *scmnd) return SCSI_EH_RESET_TIMER; } -static struct scsi_host_template virtscsi_host_template = { +static const struct scsi_host_template virtscsi_host_template = { .module = THIS_MODULE, .name = "Virtio SCSI HBA", .proc_name = "virtio_scsi", diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c index ff1b22077251..5a380eecfc75 100644 --- a/drivers/scsi/wd719x.c +++ b/drivers/scsi/wd719x.c @@ -878,7 +878,7 @@ fail_free_params: return ret; } -static struct scsi_host_template wd719x_template = { +static const struct scsi_host_template wd719x_template = { .module = THIS_MODULE, .name = "Western Digital 719x", .cmd_size = sizeof(struct wd719x_scb), diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index 71a3bb83984c..caae61aa2afe 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c @@ -770,7 +770,7 @@ static void scsifront_sdev_destroy(struct scsi_device *sdev) } } -static struct scsi_host_template scsifront_sht = { +static const struct scsi_host_template scsifront_sht = { .module = THIS_MODULE, .name = "Xen SCSI frontend driver", .queuecommand = scsifront_queuecommand, diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c index 928c8adf5cb3..56cae22a4242 100644 --- a/drivers/scsi/zorro_esp.c +++ b/drivers/scsi/zorro_esp.c @@ -713,7 +713,7 @@ MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); static int zorro_esp_probe(struct zorro_dev *z, const struct zorro_device_id *ent) { - struct scsi_host_template *tpnt = &scsi_esp_template; + const struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; const struct zorro_driver_data *zdd; |