From 68130c99480919c2088df530fc25b5e314ad806a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 11 Sep 2016 15:31:23 +0200 Subject: [PATCH 001/256] scsi: arcmsr: Use pci_alloc_irq_vectors Switch the arcmsr driver to use pci_alloc_irq_vectors. We need to two calls to pci_alloc_irq_vectors as arcmsr only supports multiple MSI-X vectors, but not multiple MSI vectors. Otherwise this cleans up a lot of cruft and allows to use a common request_irq loop for irq types, which happens to only iterate over a single line in the non MSI-X case. Signed-off-by: Christoph Hellwig Acked-by: Ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr.h | 5 +- drivers/scsi/arcmsr/arcmsr_hba.c | 80 +++++++++++++------------------- 2 files changed, 32 insertions(+), 53 deletions(-) diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index cf99f8cf4cdd..a254b32eba39 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -629,7 +629,6 @@ struct AdapterControlBlock struct pci_dev * pdev; struct Scsi_Host * host; unsigned long vir2phy_offset; - struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; uint32_t cdb_phyaddr_hi32; @@ -671,8 +670,6 @@ struct AdapterControlBlock /* iop init */ #define ACB_F_ABORT 0x0200 #define ACB_F_FIRMWARE_TRAP 0x0400 - #define ACB_F_MSI_ENABLED 0x1000 - #define ACB_F_MSIX_ENABLED 0x2000 struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ struct list_head ccb_free_list; @@ -725,7 +722,7 @@ struct AdapterControlBlock atomic_t rq_map_token; atomic_t ante_token_value; uint32_t maxOutstanding; - int msix_vector_count; + int vector_count; };/* HW_DEVICE_EXTENSION */ /* ******************************************************************************* diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f0cfb0451757..9e45749d55ed 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -720,51 +720,39 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) static int arcmsr_request_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb) { - int i, j, r; - struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; + unsigned long flags; + int nvec, i; - for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) - entries[i].entry = i; - r = pci_enable_msix_range(pdev, entries, 1, ARCMST_NUM_MSIX_VECTORS); - if (r < 0) - goto msi_int; - acb->msix_vector_count = r; - for (i = 0; i < r; i++) { - if (request_irq(entries[i].vector, - arcmsr_do_interrupt, 0, "arcmsr", acb)) { + nvec = pci_alloc_irq_vectors(pdev, 1, ARCMST_NUM_MSIX_VECTORS, + PCI_IRQ_MSIX); + if (nvec > 0) { + pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no); + flags = 0; + } else { + nvec = pci_alloc_irq_vectors(pdev, 1, 1, + PCI_IRQ_MSI | PCI_IRQ_LEGACY); + if (nvec < 1) + return FAILED; + + flags = IRQF_SHARED; + } + + acb->vector_count = nvec; + for (i = 0; i < nvec; i++) { + if (request_irq(pci_irq_vector(pdev, i), arcmsr_do_interrupt, + flags, "arcmsr", acb)) { pr_warn("arcmsr%d: request_irq =%d failed!\n", - acb->host->host_no, entries[i].vector); - for (j = 0 ; j < i ; j++) - free_irq(entries[j].vector, acb); - pci_disable_msix(pdev); - goto msi_int; + acb->host->host_no, pci_irq_vector(pdev, i)); + goto out_free_irq; } - acb->entries[i] = entries[i]; - } - acb->acb_flags |= ACB_F_MSIX_ENABLED; - pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no); - return SUCCESS; -msi_int: - if (pci_enable_msi_exact(pdev, 1) < 0) - goto legacy_int; - if (request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb)) { - pr_warn("arcmsr%d: request_irq =%d failed!\n", - acb->host->host_no, pdev->irq); - pci_disable_msi(pdev); - goto legacy_int; - } - acb->acb_flags |= ACB_F_MSI_ENABLED; - pr_info("arcmsr%d: msi enabled\n", acb->host->host_no); - return SUCCESS; -legacy_int: - if (request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb)) { - pr_warn("arcmsr%d: request_irq = %d failed!\n", - acb->host->host_no, pdev->irq); - return FAILED; } + return SUCCESS; +out_free_irq: + while (--i >= 0) + free_irq(pci_irq_vector(pdev, i), acb); + pci_free_irq_vectors(pdev); + return FAILED; } static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -886,15 +874,9 @@ static void arcmsr_free_irq(struct pci_dev *pdev, { int i; - if (acb->acb_flags & ACB_F_MSI_ENABLED) { - free_irq(pdev->irq, acb); - pci_disable_msi(pdev); - } else if (acb->acb_flags & ACB_F_MSIX_ENABLED) { - for (i = 0; i < acb->msix_vector_count; i++) - free_irq(acb->entries[i].vector, acb); - pci_disable_msix(pdev); - } else - free_irq(pdev->irq, acb); + for (i = 0; i < acb->vector_count; i++) + free_irq(pci_irq_vector(pdev, i), acb); + pci_free_irq_vectors(pdev); } static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) From a299ee62cf40d6d80a9f11d57220f0a28077fe2d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 11 Sep 2016 15:31:24 +0200 Subject: [PATCH 002/256] scsi: ipr: Use pci_irq_allocate_vectors Switch the ipr driver to use pci_alloc_irq_vectors. We need to two calls to pci_alloc_irq_vectors as ipr only supports multiple MSI-X vectors, but not multiple MSI vectors. Otherwise this cleans up a lot of cruft and allows to use a common request_irq loop for irq types, which happens to only iterate over a single line in the non MSI-X case. Signed-off-by: Christoph Hellwig Acked-by: Brian King Signed-off-by: Martin K. Petersen --- drivers/scsi/ipr.c | 173 +++++++++++++-------------------------------- drivers/scsi/ipr.h | 7 +- 2 files changed, 52 insertions(+), 128 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 532474109624..534dc3c877da 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -186,16 +186,16 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { }; static const struct ipr_chip_t ipr_chip[] = { - { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_RATTLESNAKE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] } + { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, false, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, false, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, false, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, false, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, true, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, false, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, false, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, true, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE, true, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_RATTLESNAKE, true, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] } }; static int ipr_max_bus_speeds[] = { @@ -9439,23 +9439,11 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) static void ipr_free_irqs(struct ipr_ioa_cfg *ioa_cfg) { struct pci_dev *pdev = ioa_cfg->pdev; + int i; - if (ioa_cfg->intr_flag == IPR_USE_MSI || - ioa_cfg->intr_flag == IPR_USE_MSIX) { - int i; - for (i = 0; i < ioa_cfg->nvectors; i++) - free_irq(ioa_cfg->vectors_info[i].vec, - &ioa_cfg->hrrq[i]); - } else - free_irq(pdev->irq, &ioa_cfg->hrrq[0]); - - if (ioa_cfg->intr_flag == IPR_USE_MSI) { - pci_disable_msi(pdev); - ioa_cfg->intr_flag &= ~IPR_USE_MSI; - } else if (ioa_cfg->intr_flag == IPR_USE_MSIX) { - pci_disable_msix(pdev); - ioa_cfg->intr_flag &= ~IPR_USE_MSIX; - } + for (i = 0; i < ioa_cfg->nvectors; i++) + free_irq(pci_irq_vector(pdev, i), &ioa_cfg->hrrq[i]); + pci_free_irq_vectors(pdev); } /** @@ -9883,45 +9871,6 @@ static void ipr_wait_for_pci_err_recovery(struct ipr_ioa_cfg *ioa_cfg) } } -static int ipr_enable_msix(struct ipr_ioa_cfg *ioa_cfg) -{ - struct msix_entry entries[IPR_MAX_MSIX_VECTORS]; - int i, vectors; - - for (i = 0; i < ARRAY_SIZE(entries); ++i) - entries[i].entry = i; - - vectors = pci_enable_msix_range(ioa_cfg->pdev, - entries, 1, ipr_number_of_msix); - if (vectors < 0) { - ipr_wait_for_pci_err_recovery(ioa_cfg); - return vectors; - } - - for (i = 0; i < vectors; i++) - ioa_cfg->vectors_info[i].vec = entries[i].vector; - ioa_cfg->nvectors = vectors; - - return 0; -} - -static int ipr_enable_msi(struct ipr_ioa_cfg *ioa_cfg) -{ - int i, vectors; - - vectors = pci_enable_msi_range(ioa_cfg->pdev, 1, ipr_number_of_msix); - if (vectors < 0) { - ipr_wait_for_pci_err_recovery(ioa_cfg); - return vectors; - } - - for (i = 0; i < vectors; i++) - ioa_cfg->vectors_info[i].vec = ioa_cfg->pdev->irq + i; - ioa_cfg->nvectors = vectors; - - return 0; -} - static void name_msi_vectors(struct ipr_ioa_cfg *ioa_cfg) { int vec_idx, n = sizeof(ioa_cfg->vectors_info[0].desc) - 1; @@ -9934,19 +9883,20 @@ static void name_msi_vectors(struct ipr_ioa_cfg *ioa_cfg) } } -static int ipr_request_other_msi_irqs(struct ipr_ioa_cfg *ioa_cfg) +static int ipr_request_other_msi_irqs(struct ipr_ioa_cfg *ioa_cfg, + struct pci_dev *pdev) { int i, rc; for (i = 1; i < ioa_cfg->nvectors; i++) { - rc = request_irq(ioa_cfg->vectors_info[i].vec, + rc = request_irq(pci_irq_vector(pdev, i), ipr_isr_mhrrq, 0, ioa_cfg->vectors_info[i].desc, &ioa_cfg->hrrq[i]); if (rc) { while (--i >= 0) - free_irq(ioa_cfg->vectors_info[i].vec, + free_irq(pci_irq_vector(pdev, i), &ioa_cfg->hrrq[i]); return rc; } @@ -9984,8 +9934,7 @@ static irqreturn_t ipr_test_intr(int irq, void *devp) * ipr_test_msi - Test for Message Signaled Interrupt (MSI) support. * @pdev: PCI device struct * - * Description: The return value from pci_enable_msi_range() can not always be - * trusted. This routine sets up and initiates a test interrupt to determine + * Description: This routine sets up and initiates a test interrupt to determine * if the interrupt is received via the ipr_test_intr() service routine. * If the tests fails, the driver will fall back to LSI. * @@ -9997,6 +9946,7 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev) int rc; volatile u32 int_reg; unsigned long lock_flags = 0; + int irq = pci_irq_vector(pdev, 0); ENTER; @@ -10008,15 +9958,12 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev) int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - if (ioa_cfg->intr_flag == IPR_USE_MSIX) - rc = request_irq(ioa_cfg->vectors_info[0].vec, ipr_test_intr, 0, IPR_NAME, ioa_cfg); - else - rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg); + rc = request_irq(irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg); if (rc) { - dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq); + dev_err(&pdev->dev, "Can not assign irq %d\n", irq); return rc; } else if (ipr_debug) - dev_info(&pdev->dev, "IRQ assigned: %d\n", pdev->irq); + dev_info(&pdev->dev, "IRQ assigned: %d\n", irq); writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg32); int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); @@ -10033,10 +9980,7 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev) spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - if (ioa_cfg->intr_flag == IPR_USE_MSIX) - free_irq(ioa_cfg->vectors_info[0].vec, ioa_cfg); - else - free_irq(pdev->irq, ioa_cfg); + free_irq(irq, ioa_cfg); LEAVE; @@ -10060,6 +10004,7 @@ static int ipr_probe_ioa(struct pci_dev *pdev, int rc = PCIBIOS_SUCCESSFUL; volatile u32 mask, uproc, interrupts; unsigned long lock_flags, driver_lock_flags; + unsigned int irq_flag; ENTER; @@ -10175,18 +10120,18 @@ static int ipr_probe_ioa(struct pci_dev *pdev, ipr_number_of_msix = IPR_MAX_MSIX_VECTORS; } - if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI && - ipr_enable_msix(ioa_cfg) == 0) - ioa_cfg->intr_flag = IPR_USE_MSIX; - else if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI && - ipr_enable_msi(ioa_cfg) == 0) - ioa_cfg->intr_flag = IPR_USE_MSI; - else { - ioa_cfg->intr_flag = IPR_USE_LSI; - ioa_cfg->clear_isr = 1; - ioa_cfg->nvectors = 1; - dev_info(&pdev->dev, "Cannot enable MSI.\n"); + irq_flag = PCI_IRQ_LEGACY; + if (ioa_cfg->ipr_chip->has_msi) + irq_flag |= PCI_IRQ_MSI | PCI_IRQ_MSIX; + rc = pci_alloc_irq_vectors(pdev, 1, ipr_number_of_msix, irq_flag); + if (rc < 0) { + ipr_wait_for_pci_err_recovery(ioa_cfg); + goto cleanup_nomem; } + ioa_cfg->nvectors = rc; + + if (!pdev->msi_enabled && !pdev->msix_enabled) + ioa_cfg->clear_isr = 1; pci_set_master(pdev); @@ -10199,33 +10144,22 @@ static int ipr_probe_ioa(struct pci_dev *pdev, } } - if (ioa_cfg->intr_flag == IPR_USE_MSI || - ioa_cfg->intr_flag == IPR_USE_MSIX) { + if (pdev->msi_enabled || pdev->msix_enabled) { rc = ipr_test_msi(ioa_cfg, pdev); - if (rc == -EOPNOTSUPP) { + switch (rc) { + case 0: + dev_info(&pdev->dev, + "Request for %d MSI%ss succeeded.", ioa_cfg->nvectors, + pdev->msix_enabled ? "-X" : ""); + break; + case -EOPNOTSUPP: ipr_wait_for_pci_err_recovery(ioa_cfg); - if (ioa_cfg->intr_flag == IPR_USE_MSI) { - ioa_cfg->intr_flag &= ~IPR_USE_MSI; - pci_disable_msi(pdev); - } else if (ioa_cfg->intr_flag == IPR_USE_MSIX) { - ioa_cfg->intr_flag &= ~IPR_USE_MSIX; - pci_disable_msix(pdev); - } + pci_free_irq_vectors(pdev); - ioa_cfg->intr_flag = IPR_USE_LSI; ioa_cfg->nvectors = 1; - } - else if (rc) + break; + default: goto out_msi_disable; - else { - if (ioa_cfg->intr_flag == IPR_USE_MSI) - dev_info(&pdev->dev, - "Request for %d MSIs succeeded with starting IRQ: %d\n", - ioa_cfg->nvectors, pdev->irq); - else if (ioa_cfg->intr_flag == IPR_USE_MSIX) - dev_info(&pdev->dev, - "Request for %d MSIXs succeeded.", - ioa_cfg->nvectors); } } @@ -10273,15 +10207,13 @@ static int ipr_probe_ioa(struct pci_dev *pdev, ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - if (ioa_cfg->intr_flag == IPR_USE_MSI - || ioa_cfg->intr_flag == IPR_USE_MSIX) { + if (pdev->msi_enabled || pdev->msix_enabled) { name_msi_vectors(ioa_cfg); - rc = request_irq(ioa_cfg->vectors_info[0].vec, ipr_isr, - 0, + rc = request_irq(pci_irq_vector(pdev, 0), ipr_isr, 0, ioa_cfg->vectors_info[0].desc, &ioa_cfg->hrrq[0]); if (!rc) - rc = ipr_request_other_msi_irqs(ioa_cfg); + rc = ipr_request_other_msi_irqs(ioa_cfg, pdev); } else { rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, @@ -10323,10 +10255,7 @@ cleanup_nolog: ipr_free_mem(ioa_cfg); out_msi_disable: ipr_wait_for_pci_err_recovery(ioa_cfg); - if (ioa_cfg->intr_flag == IPR_USE_MSI) - pci_disable_msi(pdev); - else if (ioa_cfg->intr_flag == IPR_USE_MSIX) - pci_disable_msix(pdev); + pci_free_irq_vectors(pdev); cleanup_nomem: iounmap(ipr_regs); out_disable: diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 8995053d01b3..b7d2e98eb45b 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1413,10 +1413,7 @@ struct ipr_chip_cfg_t { struct ipr_chip_t { u16 vendor; u16 device; - u16 intr_type; -#define IPR_USE_LSI 0x00 -#define IPR_USE_MSI 0x01 -#define IPR_USE_MSIX 0x02 + bool has_msi; u16 sis_type; #define IPR_SIS32 0x00 #define IPR_SIS64 0x01 @@ -1593,11 +1590,9 @@ struct ipr_ioa_cfg { struct ipr_cmnd **ipr_cmnd_list; dma_addr_t *ipr_cmnd_list_dma; - u16 intr_flag; unsigned int nvectors; struct { - unsigned short vec; char desc[22]; } vectors_info[IPR_MAX_MSIX_VECTORS]; From 48c4676dcbfc731a197bcf01763fcd07d9dc6725 Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Sat, 1 Oct 2016 16:48:14 -0700 Subject: [PATCH 003/256] scsi: fnic: Use time64_t to represent trace timestamps Trace timestamps use struct timespec and CURRENT_TIME which are not y2038 safe. These timestamps are only part of the trace log on the machine and are not shared with the fnic. Replace then with y2038 safe struct timespec64 and ktime_get_real_ts64(), respectively. Signed-off-by: Deepa Dinamani Reviewed-by: Arnd Bergmann Cc: Hiral Patel Cc: Suma Ramars Cc: Brian Uchino Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: linux-scsi@vger.kernel.org Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_trace.c | 4 ++-- drivers/scsi/fnic/fnic_trace.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index 4e15c4bf0795..5a5fa01576b7 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -613,7 +613,7 @@ int fnic_fc_trace_set_data(u32 host_no, u8 frame_type, fc_trace_entries.rd_idx = 0; } - fc_buf->time_stamp = CURRENT_TIME; + ktime_get_real_ts64(&fc_buf->time_stamp); fc_buf->host_no = host_no; fc_buf->frame_type = frame_type; @@ -740,7 +740,7 @@ void copy_and_format_trace_data(struct fc_trace_hdr *tdata, len = *orig_len; - time_to_tm(tdata->time_stamp.tv_sec, 0, &tm); + time64_to_tm(tdata->time_stamp.tv_sec, 0, &tm); fmt = "%02d:%02d:%04ld %02d:%02d:%02d.%09lu ns%8x %c%8x\t"; len += snprintf(fnic_dbgfs_prt->buffer + len, diff --git a/drivers/scsi/fnic/fnic_trace.h b/drivers/scsi/fnic/fnic_trace.h index a8aa0578fcb0..e375d0c2eaaf 100644 --- a/drivers/scsi/fnic/fnic_trace.h +++ b/drivers/scsi/fnic/fnic_trace.h @@ -72,7 +72,7 @@ struct fnic_trace_data { typedef struct fnic_trace_data fnic_trace_data_t; struct fc_trace_hdr { - struct timespec time_stamp; + struct timespec64 time_stamp; u32 host_no; u8 frame_type; u8 frame_len; From 64110cce987df0b14cd7e389f59f54685aacc6f0 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 4 Oct 2016 19:11:09 +0800 Subject: [PATCH 004/256] scsi: devicetree: bindings: hisi_sas: add hip07 support Add support for hip07 chipset to hisi_sas controller. Chipset hip07 has v2 hw. Signed-off-by: John Garry Signed-off-by: Xiang Chen Acked-by: Rob Herring Signed-off-by: Martin K. Petersen --- Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt index bf2411f366e5..2a42a323fa1a 100644 --- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt @@ -6,6 +6,7 @@ Main node required properties: - compatible : value should be as follows: (a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset (b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset + (c) "hisilicon,hip07-sas-v2" for v2 hw in hip07 chipset - sas-addr : array of 8 bytes for host SAS address - reg : Address and length of the SAS register - hisilicon,sas-syscon: phandle of syscon used for sas control From 039ae102a8d43bbaa00e678b37f58310f4674650 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 4 Oct 2016 19:11:10 +0800 Subject: [PATCH 005/256] scsi: hisi_sas: Add device tree support for hip07 Chipset hip07 incorporates v2 hw. Signed-off-by: John Garry Signed-off-by: Xiang Chen Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 9825a3f49f53..758e06f14d4a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2319,6 +2319,7 @@ static int hisi_sas_v2_remove(struct platform_device *pdev) static const struct of_device_id sas_v2_of_match[] = { { .compatible = "hisilicon,hip06-sas-v2",}, + { .compatible = "hisilicon,hip07-sas-v2",}, {}, }; MODULE_DEVICE_TABLE(of, sas_v2_of_match); From 3bc45af81d0dff722c5a2d5d009f2d2d91b52b56 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 4 Oct 2016 19:11:11 +0800 Subject: [PATCH 006/256] scsi: hisi_sas: Add v2 hw support for different refclk The hip06 D03 and hip07 D05 boards have different reference clock frequencies for the SAS controller. Register PHY_CTRL needs to be programmed differently according to this frequency, so add support for this. The default register setting in PHY_CTRL is for 50MHz, so only update this register when the refclk frequency is 66MHz. For ACPI we expect the _RST handler to set the correct value for PHY_CTRL (we're forced to take different approach for DT and ACPI as ACPI does not support fixed-clock device). Signed-off-by: John Garry Signed-off-by: Xiang Chen Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 2 ++ drivers/scsi/hisi_sas/hisi_sas_main.c | 7 +++++++ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 72c98522bd26..64046c5853a5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -13,6 +13,7 @@ #define _HISI_SAS_H_ #include +#include #include #include #include @@ -183,6 +184,7 @@ struct hisi_hba { u32 ctrl_reset_reg; u32 ctrl_reset_sts_reg; u32 ctrl_clock_ena_reg; + u32 refclk_frequency_mhz; u8 sas_addr[SAS_ADDR_SIZE]; int n_phy; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 2f872f784e10..9afc6978cb77 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1396,6 +1396,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, struct hisi_hba *hisi_hba; struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; + struct clk *refclk; shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba)); if (!shost) @@ -1432,6 +1433,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, goto err_out; } + refclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(refclk)) + dev_info(dev, "no ref clk property\n"); + else + hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 1000000; + if (device_property_read_u32(dev, "phy-count", &hisi_hba->n_phy)) goto err_out; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 758e06f14d4a..0763b4764ad5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -836,7 +836,9 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, CHL_INT_COAL_EN, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0); - hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694); + if (hisi_hba->refclk_frequency_mhz == 66) + hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694); + /* else, do nothing -> leave it how you found it */ } for (i = 0; i < hisi_hba->queue_count; i++) { From 4d2095cc42a2d8062590891f929d9d694cbd927f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:14 +0200 Subject: [PATCH 007/256] scsi: libfc: Revisit kref handling The kref handling in fc_rport is a mess. This patch updates the kref handling according to the following rules: - Take a reference whenever scheduling a workqueue - Take a reference whenever an ELS command is send - Drop the reference at the end of the workqueue function - Drop the reference at the end of handling ELS replies - Take a reference when allocating an rport - Drop the reference when removing an rport Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 131 ++++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 97aeaddd600d..4ec896e42120 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -44,6 +44,19 @@ * path this potential over-use of the mutex is acceptable. */ +/* + * RPORT REFERENCE COUNTING + * + * A rport reference should be taken when: + * - an rport is allocated + * - a workqueue item is scheduled + * - an ELS request is send + * The reference should be dropped when: + * - the workqueue function has finished + * - the ELS response is handled + * - an rport is removed + */ + #include #include #include @@ -242,6 +255,8 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata, /** * fc_rport_work() - Handler for remote port events in the rport_event_queue * @work: Handle to the remote port being dequeued + * + * Reference counting: drops kref on return */ static void fc_rport_work(struct work_struct *work) { @@ -329,7 +344,8 @@ static void fc_rport_work(struct work_struct *work) FC_RPORT_DBG(rdata, "lld callback ev %d\n", event); rdata->lld_event_callback(lport, rdata, event); } - cancel_delayed_work_sync(&rdata->retry_work); + if (cancel_delayed_work_sync(&rdata->retry_work)) + kref_put(&rdata->kref, lport->tt.rport_destroy); /* * Reset any outstanding exchanges before freeing rport. @@ -381,6 +397,7 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); break; } + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -431,10 +448,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata) * Set the new event so that the old pending event will not occur. * Since we have the mutex, even if fc_rport_work() is already started, * it'll see the new event. + * + * Reference counting: does not modify kref */ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, enum fc_rport_event event) { + struct fc_lport *lport = rdata->local_port; + if (rdata->rp_state == RPORT_ST_DELETE) return; @@ -442,8 +463,11 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, fc_rport_state_enter(rdata, RPORT_ST_DELETE); - if (rdata->event == RPORT_EV_NONE) - queue_work(rport_event_queue, &rdata->event_work); + kref_get(&rdata->kref); + if (rdata->event == RPORT_EV_NONE && + !queue_work(rport_event_queue, &rdata->event_work)) + kref_put(&rdata->kref, lport->tt.rport_destroy); + rdata->event = event; } @@ -496,15 +520,22 @@ out: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: schedules workqueue, does not modify kref */ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) { + struct fc_lport *lport = rdata->local_port; + fc_rport_state_enter(rdata, RPORT_ST_READY); FC_RPORT_DBG(rdata, "Port is Ready\n"); - if (rdata->event == RPORT_EV_NONE) - queue_work(rport_event_queue, &rdata->event_work); + kref_get(&rdata->kref); + if (rdata->event == RPORT_EV_NONE && + !queue_work(rport_event_queue, &rdata->event_work)) + kref_put(&rdata->kref, lport->tt.rport_destroy); + rdata->event = RPORT_EV_READY; } @@ -515,11 +546,14 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* * function and then unlock the rport. + * + * Reference counting: Drops kref on return. */ static void fc_rport_timeout(struct work_struct *work) { struct fc_rport_priv *rdata = container_of(work, struct fc_rport_priv, retry_work.work); + struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); @@ -547,6 +581,7 @@ static void fc_rport_timeout(struct work_struct *work) } mutex_unlock(&rdata->rp_mutex); + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -556,6 +591,8 @@ static void fc_rport_timeout(struct work_struct *work) * * Locking Note: The rport lock is expected to be held before * calling this routine + * + * Reference counting: does not modify kref */ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) { @@ -602,11 +639,14 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) * * Locking Note: The rport lock is expected to be held before * calling this routine + * + * Reference counting: increments kref when scheduling retry_work */ static void fc_rport_error_retry(struct fc_rport_priv *rdata, struct fc_frame *fp) { unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV); + struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ if (PTR_ERR(fp) == -FC_EX_CLOSED) @@ -619,7 +659,9 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, /* no additional delay on exchange timeouts */ if (PTR_ERR(fp) == -FC_EX_TIMEOUT) delay = 0; - schedule_delayed_work(&rdata->retry_work, delay); + kref_get(&rdata->kref); + if (!schedule_delayed_work(&rdata->retry_work, delay)) + kref_put(&rdata->kref, lport->tt.rport_destroy); return; } @@ -740,6 +782,8 @@ bad: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) { @@ -758,18 +802,21 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) if (!fp) return fc_rport_error_retry(rdata, fp); + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI, fc_rport_flogi_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode * @lport: The local port that received the PLOGI request * @rx_fp: The PLOGI request frame + * + * Reference counting: drops kref on return */ static void fc_rport_recv_flogi_req(struct fc_lport *lport, struct fc_frame *rx_fp) @@ -824,8 +871,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, * RPORT wouldn;t have created and 'rport_lookup' would have * failed anyway in that case. */ - if (lport->point_to_multipoint) - break; + break; case RPORT_ST_DELETE: mutex_unlock(&rdata->rp_mutex); rjt_data.reason = ELS_RJT_FIP; @@ -969,6 +1015,8 @@ fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata) * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) { @@ -995,12 +1043,13 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) } rdata->e_d_tov = lport->e_d_tov; + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, fc_rport_plogi_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1108,6 +1157,8 @@ err: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) { @@ -1151,11 +1202,12 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) fc_host_port_id(lport->host), FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); + kref_get(&rdata->kref); if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, - NULL, rdata, 2 * lport->r_a_tov)) + NULL, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1230,6 +1282,8 @@ err: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) { @@ -1247,12 +1301,13 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) return; } + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, fc_rport_rtv_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1262,15 +1317,16 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) * @lport_arg: The local port */ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, - void *lport_arg) + void *rdata_arg) { - struct fc_lport *lport = lport_arg; + struct fc_rport_priv *rdata = rdata_arg; + struct fc_lport *lport = rdata->local_port; FC_RPORT_ID_DBG(lport, fc_seq_exch(sp)->did, "Received a LOGO %s\n", fc_els_resp_type(fp)); - if (IS_ERR(fp)) - return; - fc_frame_free(fp); + if (!IS_ERR(fp)) + fc_frame_free(fp); + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -1279,6 +1335,8 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) { @@ -1291,8 +1349,10 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo)); if (!fp) return; - (void)lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, - fc_rport_logo_resp, lport, 0); + kref_get(&rdata->kref); + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, + fc_rport_logo_resp, rdata, 0)) + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -1359,6 +1419,8 @@ err: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) { @@ -1375,12 +1437,13 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) fc_rport_error_retry(rdata, fp); return; } + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, fc_rport_adisc_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1494,6 +1557,8 @@ out: * The ELS opcode has already been validated by the caller. * * Locking Note: Called with the lport lock held. + * + * Reference counting: does not modify kref */ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) { @@ -1561,6 +1626,8 @@ reject: * @fp: The request frame * * Locking Note: Called with the lport lock held. + * + * Reference counting: does not modify kref */ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { @@ -1605,6 +1672,8 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) * @rx_fp: The PLOGI request frame * * Locking Note: The rport lock is held before calling this function. + * + * Reference counting: increments kref on return */ static void fc_rport_recv_plogi_req(struct fc_lport *lport, struct fc_frame *rx_fp) @@ -1919,6 +1988,8 @@ drop: * * Locking Note: The rport lock is expected to be held before calling * this function. + * + * Reference counting: drops kref on return */ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) { From a407c593398c886db4fa1fc5c6fec55e61187a09 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:15 +0200 Subject: [PATCH 008/256] scsi: libfc: Fixup disc_mutex handling The list of attached 'rdata' remote port structures is RCU protected, so there is no need to take the 'disc_mutex' when traversing it. Rather we should be using rcu_read_lock() and kref_get_unless_zero() to validate the entries. We need, however, take the disc_mutex when deleting an entry; otherwise we risk clashes with list_add. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 39 +++++++++++++++++++++++++++-------- drivers/scsi/libfc/fc_disc.c | 38 ++++++++++++++++++++++------------ drivers/scsi/libfc/fc_lport.c | 9 ++++++-- drivers/scsi/libfc/fc_rport.c | 2 ++ 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index dcf36537a767..9bba58191b3d 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2145,9 +2145,15 @@ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) { struct fc_rport_priv *rdata; + rcu_read_lock(); + list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { + if (kref_get_unless_zero(&rdata->kref)) { + lport->tt.rport_logoff(rdata); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } + } + rcu_read_unlock(); mutex_lock(&lport->disc.disc_mutex); - list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) - lport->tt.rport_logoff(rdata); lport->disc.disc_callback = NULL; mutex_unlock(&lport->disc.disc_mutex); } @@ -2472,17 +2478,22 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) mutex_unlock(&lport->disc.disc_mutex); return; } + mutex_lock(&rdata->rp_mutex); + mutex_unlock(&lport->disc.disc_mutex); rdata->ops = &fcoe_ctlr_vn_rport_ops; rdata->disc_id = lport->disc.disc_id; ids = &rdata->ids; if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) || - (ids->node_name != -1 && ids->node_name != new->ids.node_name)) + (ids->node_name != -1 && ids->node_name != new->ids.node_name)) { + mutex_unlock(&rdata->rp_mutex); lport->tt.rport_logoff(rdata); + mutex_lock(&rdata->rp_mutex); + } ids->port_name = new->ids.port_name; ids->node_name = new->ids.node_name; - mutex_unlock(&lport->disc.disc_mutex); + mutex_unlock(&rdata->rp_mutex); frport = fcoe_ctlr_rport(rdata); LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n", @@ -2638,11 +2649,15 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) unsigned long deadline; next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10); - mutex_lock(&lport->disc.disc_mutex); + rcu_read_lock(); list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { - frport = fcoe_ctlr_rport(rdata); - if (!frport->time) + if (!kref_get_unless_zero(&rdata->kref)) continue; + frport = fcoe_ctlr_rport(rdata); + if (!frport->time) { + kref_put(&rdata->kref, lport->tt.rport_destroy); + continue; + } deadline = frport->time + msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10); if (time_after_eq(jiffies, deadline)) { @@ -2653,8 +2668,9 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) lport->tt.rport_logoff(rdata); } else if (time_before(deadline, next_time)) next_time = deadline; + kref_put(&rdata->kref, lport->tt.rport_destroy); } - mutex_unlock(&lport->disc.disc_mutex); + rcu_read_unlock(); return next_time; } @@ -2991,12 +3007,17 @@ static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip) mutex_lock(&disc->disc_mutex); callback = disc->pending ? disc->disc_callback : NULL; disc->pending = 0; + mutex_unlock(&disc->disc_mutex); + rcu_read_lock(); list_for_each_entry_rcu(rdata, &disc->rports, peers) { + if (!kref_get_unless_zero(&rdata->kref)) + continue; frport = fcoe_ctlr_rport(rdata); if (frport->time) lport->tt.rport_login(rdata); + kref_put(&rdata->kref, lport->tt.rport_destroy); } - mutex_unlock(&disc->disc_mutex); + rcu_read_unlock(); if (callback) callback(lport, DISC_EV_SUCCESS); } diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 880a9068ca12..ad3965f9d03d 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -68,10 +68,14 @@ static void fc_disc_stop_rports(struct fc_disc *disc) lport = fc_disc_lport(disc); - mutex_lock(&disc->disc_mutex); - list_for_each_entry_rcu(rdata, &disc->rports, peers) - lport->tt.rport_logoff(rdata); - mutex_unlock(&disc->disc_mutex); + rcu_read_lock(); + list_for_each_entry_rcu(rdata, &disc->rports, peers) { + if (kref_get_unless_zero(&rdata->kref)) { + lport->tt.rport_logoff(rdata); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } + } + rcu_read_unlock(); } /** @@ -289,15 +293,19 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) * Skip ports which were never discovered. These are the dNS port * and ports which were created by PLOGI. */ + rcu_read_lock(); list_for_each_entry_rcu(rdata, &disc->rports, peers) { - if (!rdata->disc_id) + if (!kref_get_unless_zero(&rdata->kref)) continue; - if (rdata->disc_id == disc->disc_id) - lport->tt.rport_login(rdata); - else - lport->tt.rport_logoff(rdata); + if (rdata->disc_id) { + if (rdata->disc_id == disc->disc_id) + lport->tt.rport_login(rdata); + else + lport->tt.rport_logoff(rdata); + } + kref_put(&rdata->kref, lport->tt.rport_destroy); } - + rcu_read_unlock(); mutex_unlock(&disc->disc_mutex); disc->disc_callback(lport, event); mutex_lock(&disc->disc_mutex); @@ -592,7 +600,6 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, lport = rdata->local_port; disc = &lport->disc; - mutex_lock(&disc->disc_mutex); if (PTR_ERR(fp) == -FC_EX_CLOSED) goto out; if (IS_ERR(fp)) @@ -607,16 +614,19 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, goto redisc; pn = (struct fc_ns_gid_pn *)(cp + 1); port_name = get_unaligned_be64(&pn->fn_wwpn); + mutex_lock(&rdata->rp_mutex); if (rdata->ids.port_name == -1) rdata->ids.port_name = port_name; else if (rdata->ids.port_name != port_name) { FC_DISC_DBG(disc, "GPN_ID accepted. WWPN changed. " "Port-id %6.6x wwpn %16.16llx\n", rdata->ids.port_id, port_name); + mutex_unlock(&rdata->rp_mutex); lport->tt.rport_logoff(rdata); - + mutex_lock(&lport->disc.disc_mutex); new_rdata = lport->tt.rport_create(lport, rdata->ids.port_id); + mutex_unlock(&lport->disc.disc_mutex); if (new_rdata) { new_rdata->disc_id = disc->disc_id; lport->tt.rport_login(new_rdata); @@ -624,6 +634,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, goto out; } rdata->disc_id = disc->disc_id; + mutex_unlock(&rdata->rp_mutex); lport->tt.rport_login(rdata); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n", @@ -633,10 +644,11 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n", ntohs(cp->ct_cmd)); redisc: + mutex_lock(&disc->disc_mutex); fc_disc_restart(disc); + mutex_unlock(&disc->disc_mutex); } out: - mutex_unlock(&disc->disc_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); } diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 04ce7cfb6d1b..4e11c90c783c 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -237,16 +237,19 @@ static const char *fc_lport_state(struct fc_lport *lport) * @remote_fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport * @remote_wwnn: The WWNN of the ptp rport + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. */ static void fc_lport_ptp_setup(struct fc_lport *lport, u32 remote_fid, u64 remote_wwpn, u64 remote_wwnn) { - mutex_lock(&lport->disc.disc_mutex); if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); } + mutex_lock(&lport->disc.disc_mutex); lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); kref_get(&lport->ptp_rdata->kref); lport->ptp_rdata->ids.port_name = remote_wwpn; @@ -1007,8 +1010,10 @@ EXPORT_SYMBOL(fc_lport_reset); */ static void fc_lport_reset_locked(struct fc_lport *lport) { - if (lport->dns_rdata) + if (lport->dns_rdata) { lport->tt.rport_logoff(lport->dns_rdata); + lport->dns_rdata = NULL; + } if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4ec896e42120..a0ceba10c679 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -378,7 +378,9 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); } else { FC_RPORT_DBG(rdata, "work delete\n"); + mutex_lock(&lport->disc.disc_mutex); list_del_rcu(&rdata->peers); + mutex_unlock(&lport->disc.disc_mutex); mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); } From 785141c62a26f055b27355ee9234e145955a51c6 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 30 Sep 2016 11:01:16 +0200 Subject: [PATCH 009/256] scsi: libfc: Do not take rdata->rp_mutex when processing a -FC_EX_CLOSED ELS response. When an ELS response handler receives a -FC_EX_CLOSED, the rdata->rp_mutex is already held which can lead to a deadlock condition like the following stack trace: [] fc_rport_plogi_resp+0x28/0x200 [libfc] [] fc_invoke_resp+0x6a/0xe0 [libfc] [] fc_exch_mgr_reset+0x1b8/0x280 [libfc] [] fc_rport_logoff+0x43/0xd0 [libfc] [] fc_disc_stop+0x6d/0xf0 [libfc] [] fc_disc_stop_final+0xe/0x20 [libfc] [] fc_fabric_logoff+0x17/0x70 [libfc] The other ELS handlers need to follow the FLOGI response handler and simply do a kref_put against the fc_rport_priv struct and exit when receving a -FC_EX_CLOSED response. Signed-off-by: Chad Dupuis Reviewed-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a0ceba10c679..ff33ae6bdf7c 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -952,10 +952,13 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, u16 cssp_seq; u8 op; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a PLOGI %s\n", fc_els_resp_type(fp)); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_PLOGI) { FC_RPORT_DBG(rdata, "Received a PLOGI response, but in state " "%s\n", fc_rport_state(rdata)); @@ -994,6 +997,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, lport->tt.rport_destroy); } @@ -1079,10 +1083,13 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, u8 op; u8 resp_code = 0; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp)); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_PRLI) { FC_RPORT_DBG(rdata, "Received a PRLI response, but in state " "%s\n", fc_rport_state(rdata)); @@ -1150,6 +1157,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } @@ -1230,10 +1238,13 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_rport_priv *rdata = rdata_arg; u8 op; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a RTV %s\n", fc_els_resp_type(fp)); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_RTV) { FC_RPORT_DBG(rdata, "Received a RTV response, but in state " "%s\n", fc_rport_state(rdata)); @@ -1275,6 +1286,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } @@ -1374,10 +1386,13 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_els_adisc *adisc; u8 op; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a ADISC response\n"); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_ADISC) { FC_RPORT_DBG(rdata, "Received a ADISC resp but in state %s\n", fc_rport_state(rdata)); @@ -1412,6 +1427,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } From e5a20009dae054344d71a79e9bfbea84152f3eb8 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:17 +0200 Subject: [PATCH 010/256] scsi: libfc: Do not drop down to FLOGI for fc_rport_login() When fc_rport_login() is called while the rport is not in RPORT_ST_INIT, RPORT_ST_READY, or RPORT_ST_DELETE login is already in progress and there's no need to drop down to FLOGI; doing so will only confuse the other side. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index ff33ae6bdf7c..4e4087a00836 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -427,10 +427,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata) case RPORT_ST_DELETE: FC_RPORT_DBG(rdata, "Restart deleted port\n"); break; - default: + case RPORT_ST_INIT: FC_RPORT_DBG(rdata, "Login to port\n"); fc_rport_enter_flogi(rdata); break; + default: + FC_RPORT_DBG(rdata, "Login in progress, state %s\n", + fc_rport_state(rdata)); + break; } mutex_unlock(&rdata->rp_mutex); From 06ee2571a438653bd14c33c70379a5f008a91901 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:18 +0200 Subject: [PATCH 011/256] scsi: libfc: Do not login if the port is already started When the port is already started we don't need to login; that will only confuse the state machine. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4e4087a00836..72a7183fdd06 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -418,6 +418,12 @@ static int fc_rport_login(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); + if (rdata->flags & FC_RP_STARTED) { + FC_RPORT_DBG(rdata, "port already started\n"); + mutex_unlock(&rdata->rp_mutex); + return 0; + } + rdata->flags |= FC_RP_STARTED; switch (rdata->rp_state) { case RPORT_ST_READY: From f89b8d67db792a8a303e14e3d02785035e6f1a05 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:19 +0200 Subject: [PATCH 012/256] scsi: libfc: don't advance state machine for incoming FLOGI When we receive an FLOGI but have already sent our own we should not advance the state machine but rather wait for our FLOGI to return before continuing with PLOGI. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 72a7183fdd06..4b9bb6dd4004 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -765,8 +765,10 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, goto bad; flogi = fc_frame_payload_get(fp, sizeof(*flogi)); - if (!flogi) + if (!flogi) { + FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); goto bad; + } r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov); if (r_a_tov > rdata->r_a_tov) rdata->r_a_tov = r_a_tov; @@ -783,7 +785,6 @@ put: kref_put(&rdata->kref, lport->tt.rport_destroy); return; bad: - FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); fc_rport_error_retry(rdata, fp); goto out; } @@ -925,10 +926,17 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); lport->tt.frame_send(lport, fp); - if (rdata->ids.port_name < lport->wwpn) - fc_rport_enter_plogi(rdata); - else - fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); + /* + * Do not proceed with the state machine if our + * FLOGI has crossed with an FLOGI from the + * remote port; wait for the FLOGI response instead. + */ + if (rdata->rp_state != RPORT_ST_FLOGI) { + if (rdata->ids.port_name < lport->wwpn) + fc_rport_enter_plogi(rdata); + else + fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); + } out: mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); From fd37f66eb6801b6188155ce276d346754ac1799e Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 30 Sep 2016 11:01:20 +0200 Subject: [PATCH 013/256] scsi: fcoe: Harden CVL handling when we have not logged into the fabric. If we haven't logged into the fabric yet we want to be a little more nuanced with our CVL handling than what we've been: - If the FCF has been selected, check the source MAC to make sure the frame is from the FCF we've selected. - If a FCF is selected and the CVL is from the FCF but we have not logged in yet, then reset everything and go back to solicitation. Signed-off-by: Chad Dupuis Reviewed-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 9bba58191b3d..05573c32254d 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -1316,7 +1316,7 @@ drop: * The overall length has already been checked. */ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, - struct fip_header *fh) + struct sk_buff *skb) { struct fip_desc *desc; struct fip_mac_desc *mp; @@ -1331,20 +1331,49 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, int num_vlink_desc; int reset_phys_port = 0; struct fip_vn_desc **vlink_desc_arr = NULL; + struct fip_header *fh = (struct fip_header *)skb->data; + struct ethhdr *eh = eth_hdr(skb); LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); - if (!fcf || !lport->port_id) { + if (!fcf) { /* * We are yet to select best FCF, but we got CVL in the * meantime. reset the ctlr and let it rediscover the FCF */ + LIBFCOE_FIP_DBG(fip, "Resetting fcoe_ctlr as FCF has not been " + "selected yet\n"); mutex_lock(&fip->ctlr_mutex); fcoe_ctlr_reset(fip); mutex_unlock(&fip->ctlr_mutex); return; } + /* + * If we've selected an FCF check that the CVL is from there to avoid + * processing CVLs from an unexpected source. If it is from an + * unexpected source drop it on the floor. + */ + if (!ether_addr_equal(eh->h_source, fcf->fcf_mac)) { + LIBFCOE_FIP_DBG(fip, "Dropping CVL due to source address " + "mismatch with FCF src=%pM\n", eh->h_source); + return; + } + + /* + * If we haven't logged into the fabric but receive a CVL we should + * reset everything and go back to solicitation. + */ + if (!lport->port_id) { + LIBFCOE_FIP_DBG(fip, "lport not logged in, resoliciting\n"); + mutex_lock(&fip->ctlr_mutex); + fcoe_ctlr_reset(fip); + mutex_unlock(&fip->ctlr_mutex); + fc_lport_reset(fip->lp); + fcoe_ctlr_solicit(fip, NULL); + return; + } + /* * mask of required descriptors. Validating each one clears its bit. */ @@ -1576,7 +1605,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) if (op == FIP_OP_DISC && sub == FIP_SC_ADV) fcoe_ctlr_recv_adv(fip, skb); else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) - fcoe_ctlr_recv_clr_vlink(fip, fiph); + fcoe_ctlr_recv_clr_vlink(fip, skb); kfree_skb(skb); return 0; drop: From 1e879e8fa9f62e18d79bfc339050bf8fed7a81e4 Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 6 Oct 2016 21:48:22 -0700 Subject: [PATCH 014/256] scsi: ufshcd: Fix possible unclocked register access Vendor specific setup_clocks callback may require the clocks managed by ufshcd driver to be ON. So if the vendor specific setup_clocks callback is called while the required clocks are turned off, it could result into unclocked register access. To prevent possible unclock register access, this change adds one more argument to setup_clocks callback to let it know whether it is called pre/post the clock changes by core driver. Signed-off-by: Subhash Jadavani Reviewed-by: Kiwoong Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 10 ++++++---- drivers/scsi/ufs/ufshcd.c | 17 ++++++++--------- drivers/scsi/ufs/ufshcd.h | 8 +++++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 3aedf73f1131..3c4f602eecd2 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1094,10 +1094,12 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) * ufs_qcom_setup_clocks - enables/disable clocks * @hba: host controller instance * @on: If true, enable clocks else disable them. + * @status: PRE_CHANGE or POST_CHANGE notify * * Returns 0 on success, non-zero on failure. */ -static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) +static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, + enum ufs_notify_change_status status) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); int err; @@ -1111,7 +1113,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) if (!host) return 0; - if (on) { + if (on && (status == POST_CHANGE)) { err = ufs_qcom_phy_enable_iface_clk(host->generic_phy); if (err) goto out; @@ -1130,7 +1132,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) if (vote == host->bus_vote.min_bw_vote) ufs_qcom_update_bus_bw_vote(host); - } else { + } else if (!on && (status == PRE_CHANGE)) { /* M-PHY RMMI interface clocks can be turned off */ ufs_qcom_phy_disable_iface_clk(host->generic_phy); @@ -1254,7 +1256,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) ufs_qcom_set_caps(hba); ufs_qcom_advertise_quirks(hba); - ufs_qcom_setup_clocks(hba, true); + ufs_qcom_setup_clocks(hba, true, POST_CHANGE); if (hba->dev->id < MAX_UFS_QCOM_HOSTS) ufs_qcom_hosts[hba->dev->id] = host; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 05c745663c10..571a2f64a01d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5389,6 +5389,10 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, if (!head || list_empty(head)) goto out; + ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); + if (ret) + return ret; + list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { if (skip_ref_clk && !strcmp(clki->name, "ref_clk")) @@ -5410,7 +5414,10 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, } } - ret = ufshcd_vops_setup_clocks(hba, on); + ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); + if (ret) + return ret; + out: if (ret) { list_for_each_entry(clki, head, list) { @@ -5500,8 +5507,6 @@ static void ufshcd_variant_hba_exit(struct ufs_hba *hba) if (!hba->vops) return; - ufshcd_vops_setup_clocks(hba, false); - ufshcd_vops_setup_regulators(hba, false); ufshcd_vops_exit(hba); @@ -5905,10 +5910,6 @@ disable_clks: if (ret) goto set_link_active; - ret = ufshcd_vops_setup_clocks(hba, false); - if (ret) - goto vops_resume; - if (!ufshcd_is_link_active(hba)) ufshcd_setup_clocks(hba, false); else @@ -5925,8 +5926,6 @@ disable_clks: ufshcd_hba_vreg_set_lpm(hba); goto out; -vops_resume: - ufshcd_vops_resume(hba, pm_op); set_link_active: ufshcd_vreg_set_hpm(hba); if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba)) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 430bef111293..afff7f4de81b 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -273,7 +273,8 @@ struct ufs_hba_variant_ops { u32 (*get_ufs_hci_version)(struct ufs_hba *); int (*clk_scale_notify)(struct ufs_hba *, bool, enum ufs_notify_change_status); - int (*setup_clocks)(struct ufs_hba *, bool); + int (*setup_clocks)(struct ufs_hba *, bool, + enum ufs_notify_change_status); int (*setup_regulators)(struct ufs_hba *, bool); int (*hce_enable_notify)(struct ufs_hba *, enum ufs_notify_change_status); @@ -755,10 +756,11 @@ static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba, return 0; } -static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on) +static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on, + enum ufs_notify_change_status status) { if (hba->vops && hba->vops->setup_clocks) - return hba->vops->setup_clocks(hba, on); + return hba->vops->setup_clocks(hba, on, status); return 0; } From b61bacbc2bf5df11f227bd9bd97b3bace4dc9108 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 10 Oct 2016 00:46:52 -0400 Subject: [PATCH 015/256] scsi: g_NCR5380: Merge g_NCR5380 and g_NCR5380_mmio drivers Merge the port-mapped IO and memory-mapped IO support (with the help of ioport_map) into the g_NCR5380 module and delete g_NCR5380_mmio. Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- MAINTAINERS | 1 - drivers/scsi/Kconfig | 32 +---- drivers/scsi/Makefile | 1 - drivers/scsi/g_NCR5380.c | 256 ++++++++++++++++------------------ drivers/scsi/g_NCR5380.h | 33 ++--- drivers/scsi/g_NCR5380_mmio.c | 10 -- 6 files changed, 136 insertions(+), 197 deletions(-) delete mode 100644 drivers/scsi/g_NCR5380_mmio.c diff --git a/MAINTAINERS b/MAINTAINERS index 411e3b87b8c2..3d15bd5b63b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8316,7 +8316,6 @@ F: drivers/scsi/arm/oak.c F: drivers/scsi/atari_scsi.* F: drivers/scsi/dmx3191d.c F: drivers/scsi/g_NCR5380.* -F: drivers/scsi/g_NCR5380_mmio.c F: drivers/scsi/mac_scsi.* F: drivers/scsi/sun3_scsi.* F: drivers/scsi/sun3_scsi_vme.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3e2bdb90813c..98451fe031a4 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -743,40 +743,18 @@ config SCSI_ISCI control unit found in the Intel(R) C600 series chipset. config SCSI_GENERIC_NCR5380 - tristate "Generic NCR5380/53c400 SCSI PIO support" + tristate "Generic NCR5380/53c400 SCSI ISA card support" depends on ISA && SCSI select SCSI_SPI_ATTRS ---help--- - This is a driver for the old NCR 53c80 series of SCSI controllers - on boards using PIO. Most boards such as the Trantor T130 fit this - category, along with a large number of ISA 8bit controllers shipped - for free with SCSI scanners. If you have a PAS16, T128 or DMX3191 - you should select the specific driver for that card rather than - generic 5380 support. - - It is explained in section 3.8 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . + This is a driver for old ISA card SCSI controllers based on a + NCR 5380, 53C80, 53C400, 53C400A, or DTC 436 device. + Most boards such as the Trantor T130 fit this category, as do + various 8-bit and 16-bit ISA cards bundled with SCSI scanners. To compile this driver as a module, choose M here: the module will be called g_NCR5380. -config SCSI_GENERIC_NCR5380_MMIO - tristate "Generic NCR5380/53c400 SCSI MMIO support" - depends on ISA && SCSI - select SCSI_SPI_ATTRS - ---help--- - This is a driver for the old NCR 53c80 series of SCSI controllers - on boards using memory mapped I/O. - It is explained in section 3.8 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . - - To compile this driver as a module, choose M here: the - module will be called g_NCR5380_mmio. - config SCSI_IPS tristate "IBM ServeRAID support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 38d938d7fe67..2ac1b9fe56ea 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -74,7 +74,6 @@ obj-$(CONFIG_SCSI_ISCI) += isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o -obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index cbf010324c18..4d7a9de01645 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -64,9 +64,9 @@ static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; module_param_array(card, int, NULL, 0); MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)"); +MODULE_ALIAS("g_NCR5380_mmio"); MODULE_LICENSE("GPL"); -#ifndef SCSI_G_NCR5380_MEM /* * Configure I/O address of 53C400A or DTC436 by writing magic numbers * to ports 0x779 and 0x379. @@ -88,40 +88,35 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) cfg = 0x80 | idx | (irq << 4); outb(cfg, 0x379); } -#endif + +static unsigned int ncr_53c400a_ports[] = { + 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 +}; +static unsigned int dtc_3181e_ports[] = { + 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 +}; +static u8 ncr_53c400a_magic[] = { /* 53C400A & DTC436 */ + 0x59, 0xb9, 0xc5, 0xae, 0xa6 +}; +static u8 hp_c2502_magic[] = { /* HP C2502 */ + 0x0f, 0x22, 0xf0, 0x20, 0x80 +}; static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, struct device *pdev, int base, int irq, int board) { - unsigned int *ports; + bool is_pmio = base <= 0xffff; + int ret; + int flags = 0; + unsigned int *ports = NULL; u8 *magic = NULL; -#ifndef SCSI_G_NCR5380_MEM int i; int port_idx = -1; unsigned long region_size; -#endif - static unsigned int ncr_53c400a_ports[] = { - 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 - }; - static unsigned int dtc_3181e_ports[] = { - 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 - }; - static u8 ncr_53c400a_magic[] = { /* 53C400A & DTC436 */ - 0x59, 0xb9, 0xc5, 0xae, 0xa6 - }; - static u8 hp_c2502_magic[] = { /* HP C2502 */ - 0x0f, 0x22, 0xf0, 0x20, 0x80 - }; - int flags, ret; struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; -#ifdef SCSI_G_NCR5380_MEM void __iomem *iomem; - resource_size_t iomem_size; -#endif - ports = NULL; - flags = 0; switch (board) { case BOARD_NCR5380: flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; @@ -140,8 +135,7 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, break; } -#ifndef SCSI_G_NCR5380_MEM - if (ports && magic) { + if (is_pmio && ports && magic) { /* wakeup sequence for the NCR53C400A and DTC3181E */ /* Disable the adapter and look for a free io port */ @@ -179,75 +173,81 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, port_idx = i; } else return -EINVAL; - } - else - { + } else if (is_pmio) { /* NCR5380 - no configuration, just grab */ region_size = 8; if (!base || !request_region(base, region_size, "ncr5380")) return -EBUSY; + } else { /* MMIO */ + region_size = NCR53C400_region_size; + if (!request_mem_region(base, region_size, "ncr5380")) + return -EBUSY; } -#else - iomem_size = NCR53C400_region_size; - if (!request_mem_region(base, iomem_size, "ncr5380")) - return -EBUSY; - iomem = ioremap(base, iomem_size); + + if (is_pmio) + iomem = ioport_map(base, region_size); + else + iomem = ioremap(base, region_size); + if (!iomem) { - release_mem_region(base, iomem_size); - return -ENOMEM; - } -#endif - instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); - if (instance == NULL) { ret = -ENOMEM; goto out_release; } + + instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); + if (instance == NULL) { + ret = -ENOMEM; + goto out_unmap; + } hostdata = shost_priv(instance); -#ifndef SCSI_G_NCR5380_MEM - instance->io_port = base; - instance->n_io_port = region_size; - hostdata->io_width = 1; /* 8-bit PDMA by default */ - - /* - * On NCR53C400 boards, NCR5380 registers are mapped 8 past - * the base address. - */ - switch (board) { - case BOARD_NCR53C400: - instance->io_port += 8; - hostdata->c400_ctl_status = 0; - hostdata->c400_blk_cnt = 1; - hostdata->c400_host_buf = 4; - break; - case BOARD_DTC3181E: - hostdata->io_width = 2; /* 16-bit PDMA */ - /* fall through */ - case BOARD_NCR53C400A: - case BOARD_HP_C2502: - hostdata->c400_ctl_status = 9; - hostdata->c400_blk_cnt = 10; - hostdata->c400_host_buf = 8; - break; - } -#else - instance->base = base; hostdata->iomem = iomem; - hostdata->iomem_size = iomem_size; - switch (board) { - case BOARD_NCR53C400: - hostdata->c400_ctl_status = 0x100; - hostdata->c400_blk_cnt = 0x101; - hostdata->c400_host_buf = 0x104; - break; - case BOARD_DTC3181E: - case BOARD_NCR53C400A: - case BOARD_HP_C2502: - pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); - ret = -EINVAL; - goto out_unregister; + + if (is_pmio) { + instance->io_port = base; + instance->n_io_port = region_size; + hostdata->io_width = 1; /* 8-bit PDMA by default */ + hostdata->offset = 0; + + /* + * On NCR53C400 boards, NCR5380 registers are mapped 8 past + * the base address. + */ + switch (board) { + case BOARD_NCR53C400: + instance->io_port += 8; + hostdata->c400_ctl_status = 0; + hostdata->c400_blk_cnt = 1; + hostdata->c400_host_buf = 4; + break; + case BOARD_DTC3181E: + hostdata->io_width = 2; /* 16-bit PDMA */ + /* fall through */ + case BOARD_NCR53C400A: + case BOARD_HP_C2502: + hostdata->c400_ctl_status = 9; + hostdata->c400_blk_cnt = 10; + hostdata->c400_host_buf = 8; + break; + } + } else { + instance->base = base; + hostdata->iomem_size = region_size; + hostdata->offset = NCR53C400_mem_base; + switch (board) { + case BOARD_NCR53C400: + hostdata->c400_ctl_status = 0x100; + hostdata->c400_blk_cnt = 0x101; + hostdata->c400_host_buf = 0x104; + break; + case BOARD_DTC3181E: + case BOARD_NCR53C400A: + case BOARD_HP_C2502: + pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); + ret = -EINVAL; + goto out_unregister; + } } -#endif ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP); if (ret) @@ -273,11 +273,9 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, instance->irq = NO_IRQ; if (instance->irq != NO_IRQ) { -#ifndef SCSI_G_NCR5380_MEM /* set IRQ for HP C2502 */ if (board == BOARD_HP_C2502) magic_configure(port_idx, instance->irq, magic); -#endif if (request_irq(instance->irq, generic_NCR5380_intr, 0, "NCR5380", instance)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); @@ -303,32 +301,29 @@ out_free_irq: NCR5380_exit(instance); out_unregister: scsi_host_put(instance); -out_release: -#ifndef SCSI_G_NCR5380_MEM - release_region(base, region_size); -#else +out_unmap: iounmap(iomem); - release_mem_region(base, iomem_size); -#endif +out_release: + if (is_pmio) + release_region(base, region_size); + else + release_mem_region(base, region_size); return ret; } static void generic_NCR5380_release_resources(struct Scsi_Host *instance) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); + scsi_remove_host(instance); if (instance->irq != NO_IRQ) free_irq(instance->irq, instance); NCR5380_exit(instance); -#ifndef SCSI_G_NCR5380_MEM - release_region(instance->io_port, instance->n_io_port); -#else - { - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - iounmap(hostdata->iomem); + iounmap(hostdata->iomem); + if (instance->io_port) + release_region(instance->io_port, instance->n_io_port); + else release_mem_region(instance->base, hostdata->iomem_size); - } -#endif scsi_host_put(instance); } @@ -361,18 +356,16 @@ static inline int generic_NCR5380_pread(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; /* FIXME - no timeout */ -#ifndef SCSI_G_NCR5380_MEM - if (hostdata->io_width == 2) + if (instance->io_port && hostdata->io_width == 2) insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64); - else + else if (instance->io_port) insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); -#else - /* implies SCSI_G_NCR5380_MEM */ - memcpy_fromio(dst + start, - hostdata->iomem + NCR53C400_host_buffer, 128); -#endif + else + memcpy_fromio(dst + start, + hostdata->iomem + NCR53C400_host_buffer, 128); + start += 128; blocks--; } @@ -381,18 +374,16 @@ static inline int generic_NCR5380_pread(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; /* FIXME - no timeout */ -#ifndef SCSI_G_NCR5380_MEM - if (hostdata->io_width == 2) + if (instance->io_port && hostdata->io_width == 2) insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64); - else + else if (instance->io_port) insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); -#else - /* implies SCSI_G_NCR5380_MEM */ - memcpy_fromio(dst + start, - hostdata->iomem + NCR53C400_host_buffer, 128); -#endif + else + memcpy_fromio(dst + start, + hostdata->iomem + NCR53C400_host_buffer, 128); + start += 128; blocks--; } @@ -439,18 +430,17 @@ static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, break; while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout -#ifndef SCSI_G_NCR5380_MEM - if (hostdata->io_width == 2) + + if (instance->io_port && hostdata->io_width == 2) outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64); - else + else if (instance->io_port) outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128); -#else - /* implies SCSI_G_NCR5380_MEM */ - memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, - src + start, 128); -#endif + else + memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, + src + start, 128); + start += 128; blocks--; } @@ -458,18 +448,16 @@ static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - no timeout -#ifndef SCSI_G_NCR5380_MEM - if (hostdata->io_width == 2) + if (instance->io_port && hostdata->io_width == 2) outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64); - else + else if (instance->io_port) outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128); -#else - /* implies SCSI_G_NCR5380_MEM */ - memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, - src + start, 128); -#endif + else + memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, + src + start, 128); + start += 128; blocks--; } @@ -566,7 +554,7 @@ static struct isa_driver generic_NCR5380_isa_driver = { }, }; -#if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) +#ifdef CONFIG_PNP static struct pnp_device_id generic_NCR5380_pnp_ids[] = { { .id = "DTC436e", .driver_data = BOARD_DTC3181E }, { .id = "" } @@ -600,7 +588,7 @@ static struct pnp_driver generic_NCR5380_pnp_driver = { .probe = generic_NCR5380_pnp_probe, .remove = generic_NCR5380_pnp_remove, }; -#endif /* !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) */ +#endif /* defined(CONFIG_PNP) */ static int pnp_registered, isa_registered; @@ -624,7 +612,7 @@ static int __init generic_NCR5380_init(void) card[0] = BOARD_HP_C2502; } -#if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) +#ifdef CONFIG_PNP if (!pnp_register_driver(&generic_NCR5380_pnp_driver)) pnp_registered = 1; #endif @@ -637,7 +625,7 @@ static int __init generic_NCR5380_init(void) static void __exit generic_NCR5380_exit(void) { -#if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) +#ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_driver(&generic_NCR5380_pnp_driver); #endif diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index b175b9234458..2b77782439f1 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -14,44 +14,30 @@ #ifndef GENERIC_NCR5380_H #define GENERIC_NCR5380_H -#ifndef SCSI_G_NCR5380_MEM #define DRV_MODULE_NAME "g_NCR5380" #define NCR5380_read(reg) \ - inb(instance->io_port + (reg)) + ioread8(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ + ((struct NCR5380_hostdata *)shost_priv(instance))->offset + \ + (reg)) #define NCR5380_write(reg, value) \ - outb(value, instance->io_port + (reg)) + iowrite8(value, ((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ + ((struct NCR5380_hostdata *)shost_priv(instance))->offset + \ + (reg)) #define NCR5380_implementation_fields \ + int offset; \ + void __iomem *iomem; \ + resource_size_t iomem_size; \ int c400_ctl_status; \ int c400_blk_cnt; \ int c400_host_buf; \ int io_width; -#else -/* therefore SCSI_G_NCR5380_MEM */ -#define DRV_MODULE_NAME "g_NCR5380_mmio" - #define NCR53C400_mem_base 0x3880 #define NCR53C400_host_buffer 0x3900 #define NCR53C400_region_size 0x3a00 -#define NCR5380_read(reg) \ - readb(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ - NCR53C400_mem_base + (reg)) -#define NCR5380_write(reg, value) \ - writeb(value, ((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ - NCR53C400_mem_base + (reg)) - -#define NCR5380_implementation_fields \ - void __iomem *iomem; \ - resource_size_t iomem_size; \ - int c400_ctl_status; \ - int c400_blk_cnt; \ - int c400_host_buf; - -#endif - #define NCR5380_dma_xfer_len(instance, cmd, phase) \ generic_NCR5380_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup generic_NCR5380_pread @@ -73,4 +59,3 @@ #define BOARD_HP_C2502 4 #endif /* GENERIC_NCR5380_H */ - diff --git a/drivers/scsi/g_NCR5380_mmio.c b/drivers/scsi/g_NCR5380_mmio.c deleted file mode 100644 index 8cdde71ba0c8..000000000000 --- a/drivers/scsi/g_NCR5380_mmio.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * There is probably a nicer way to do this but this one makes - * pretty obvious what is happening. We rebuild the same file with - * different options for mmio versus pio. - */ - -#define SCSI_G_NCR5380_MEM - -#include "g_NCR5380.c" - From b223680da0627eccf38ba28453746ac7bee06342 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:52 -0400 Subject: [PATCH 016/256] scsi: cumana_1: Remove unused cumanascsi_setup() function Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Acked-by: Russell King Signed-off-by: Martin K. Petersen --- drivers/scsi/arm/cumana_1.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 8e9cfe8f22f5..f616756feee5 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -33,10 +33,6 @@ #include "../NCR5380.h" -void cumanascsi_setup(char *str, int *ints) -{ -} - #define CTRL 0x16fc #define STAT 0x2004 #define L(v) (((v)<<16)|((v) & 0x0000ffff)) From abd12b09292cc87a75f7c3e3c3f2b12589560bb1 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:52 -0400 Subject: [PATCH 017/256] scsi: atari_scsi: Make device register accessors re-entrant This patch fixes an old bug: accesses to device registers from the interrupt handler (after reselection, DMA completion etc.) could mess up a device register access elsewhere, if the latter takes place outside of an irq lock (during selection etc.). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index a59ad94ea52b..862f30c23ff0 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -670,14 +670,26 @@ static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value) static unsigned char atari_scsi_falcon_reg_read(unsigned char reg) { - dma_wd.dma_mode_status= (u_short)(0x88 + reg); - return (u_char)dma_wd.fdc_acces_seccount; + unsigned long flags; + unsigned char result; + + reg += 0x88; + local_irq_save(flags); + dma_wd.dma_mode_status = (u_short)reg; + result = (u_char)dma_wd.fdc_acces_seccount; + local_irq_restore(flags); + return result; } static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value) { - dma_wd.dma_mode_status = (u_short)(0x88 + reg); + unsigned long flags; + + reg += 0x88; + local_irq_save(flags); + dma_wd.dma_mode_status = (u_short)reg; dma_wd.fdc_acces_seccount = (u_short)value; + local_irq_restore(flags); } From d4408dd7ecff6ed3561f155923738474c585f31d Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:52 -0400 Subject: [PATCH 018/256] scsi: ncr5380: Simplify register polling limit When polling a device register under irq lock the polling loop terminates after a given number of jiffies. Make this timeout independent of the HZ setting. All 5380 drivers benefit from this patch, which optimizes the PIO fast path, because they all use PIO transfers (for phases other than DATA IN and DATA OUT). Some cards support only PIO transfers (even for DATA phases). CPU cycles are scarce on some of these systems, so a small improvement here makes a big difference. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 10 ++++------ drivers/scsi/NCR5380.h | 5 ++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 790babc5ef66..c5c15573e23f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -200,13 +200,9 @@ static int NCR5380_poll_politely2(struct Scsi_Host *instance, int reg2, int bit2, int val2, int wait) { struct NCR5380_hostdata *hostdata = shost_priv(instance); + unsigned long n = hostdata->poll_loops; unsigned long deadline = jiffies + wait; - unsigned long n; - /* Busy-wait for up to 10 ms */ - n = min(10000U, jiffies_to_usecs(wait)); - n *= hostdata->accesses_per_ms; - n /= 2000; do { if ((NCR5380_read(reg1) & bit1) == val1) return 0; @@ -482,6 +478,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) struct NCR5380_hostdata *hostdata = shost_priv(instance); int i; unsigned long deadline; + unsigned long accesses_per_ms; instance->max_lun = 7; @@ -530,7 +527,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) ++i; cpu_relax(); } while (time_is_after_jiffies(deadline)); - hostdata->accesses_per_ms = i / 256; + accesses_per_ms = i / 256; + hostdata->poll_loops = NCR5380_REG_POLL_TIME * accesses_per_ms / 2; return 0; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 965d92339455..cbb29d604fe0 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -239,7 +239,7 @@ struct NCR5380_hostdata { * transfer to handle chip overruns */ struct work_struct main_task; struct workqueue_struct *work_q; - unsigned long accesses_per_ms; /* chip register accesses per ms */ + unsigned long poll_loops; /* register polling limit */ }; #ifdef __KERNEL__ @@ -252,6 +252,9 @@ struct NCR5380_cmd { #define NCR5380_PIO_CHUNK_SIZE 256 +/* Time limit (ms) to poll registers when IRQs are disabled, e.g. during PDMA */ +#define NCR5380_REG_POLL_TIME 10 + static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) { return ((struct scsi_cmnd *)ncmd_ptr) - 1; From 4822827a69d7cd3bc5a07b7637484ebd2cf88db6 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:52 -0400 Subject: [PATCH 019/256] scsi: ncr5380: Increase register polling limit If NCR5380_poll_politely() is called under irq lock, the polling time limit is clamped to avoid a spike in interrupt latency. When not under irq lock, the same polling time limit acts as the worst case delay between schedule() calls. During PDMA (under irq lock) I've found that the 10 ms time limit is sometimes too short, and leads to the error message, sd 0:0:0:0: [sda] tag#1 macscsi_pread: !REQ and !ACK This particular target identifies itself as a QUANTUM DAYTONA514S. It seems to be slower to assert ACK than the other targets I've tested. This patch solves the problem by increasing the polling timeout. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index cbb29d604fe0..f0eea44107d2 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -253,7 +253,7 @@ struct NCR5380_cmd { #define NCR5380_PIO_CHUNK_SIZE 256 /* Time limit (ms) to poll registers when IRQs are disabled, e.g. during PDMA */ -#define NCR5380_REG_POLL_TIME 10 +#define NCR5380_REG_POLL_TIME 15 static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) { From 25894d1f98aed363bf03e2509d0237c69ab0c8ec Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 020/256] scsi: ncr5380: Improve hostdata struct member alignment and cache-ability Re-order struct members so that hot data lies at the beginning of the struct and cold data at the end. Improve the comments while we're here. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index f0eea44107d2..ceafa0cd80be 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -219,27 +219,27 @@ #define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */ struct NCR5380_hostdata { - NCR5380_implementation_fields; /* implementation specific */ - struct Scsi_Host *host; /* Host backpointer */ - unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ - unsigned char busy[8]; /* index = target, bit = lun */ - int dma_len; /* requested length of DMA */ - unsigned char last_message; /* last message OUT */ - struct scsi_cmnd *connected; /* currently connected cmnd */ - struct scsi_cmnd *selecting; /* cmnd to be connected */ - struct list_head unissued; /* waiting to be issued */ - struct list_head autosense; /* priority issue queue */ - struct list_head disconnected; /* waiting for reconnect */ - spinlock_t lock; /* protects this struct */ - int flags; - struct scsi_eh_save ses; - struct scsi_cmnd *sensing; + NCR5380_implementation_fields; /* Board-specific data */ + unsigned long poll_loops; /* Register polling limit */ + spinlock_t lock; /* Protects this struct */ + struct scsi_cmnd *connected; /* Currently connected cmnd */ + struct list_head disconnected; /* Waiting for reconnect */ + struct Scsi_Host *host; /* SCSI host backpointer */ + struct workqueue_struct *work_q; /* SCSI host work queue */ + struct work_struct main_task; /* Work item for main loop */ + int flags; /* Board-specific quirks */ + int dma_len; /* Requested length of DMA */ + int read_overruns; /* Transfer size reduction for DMA erratum */ + struct list_head unissued; /* Waiting to be issued */ + struct scsi_cmnd *selecting; /* Cmnd to be connected */ + struct list_head autosense; /* Priority cmnd queue */ + struct scsi_cmnd *sensing; /* Cmnd needing autosense */ + struct scsi_eh_save ses; /* Cmnd state saved for EH */ + unsigned char busy[8]; /* Index = target, bit = lun */ + unsigned char id_mask; /* 1 << Host ID */ + unsigned char id_higher_mask; /* All bits above id_mask */ + unsigned char last_message; /* Last Message Out */ char info[256]; - int read_overruns; /* number of bytes to cut from a - * transfer to handle chip overruns */ - struct work_struct main_task; - struct workqueue_struct *work_q; - unsigned long poll_loops; /* register polling limit */ }; #ifdef __KERNEL__ From 820682b1b34ebb97434c4abc00c744870364e2be Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 021/256] scsi: ncr5380: Store IO ports and addresses in host private data The various 5380 drivers inconsistently store register pointers either in the Scsi_Host struct "legacy crap" area or in special, board-specific members of the NCR5380_hostdata struct. Uniform use of the latter struct makes for simpler and faster code (see the following patches) and helps to reduce use of the NCR5380_implementation_fields macro. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Acked-by: Russell King Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 8 ++--- drivers/scsi/NCR5380.h | 5 +++ drivers/scsi/arm/cumana_1.c | 60 +++++++++++++++++---------------- drivers/scsi/arm/oak.c | 23 ++++++------- drivers/scsi/dmx3191d.c | 14 +++++--- drivers/scsi/g_NCR5380.c | 67 +++++++++++++++++++------------------ drivers/scsi/g_NCR5380.h | 6 ++-- drivers/scsi/mac_scsi.c | 27 +++++++++------ drivers/scsi/sun3_scsi.c | 5 ++- 9 files changed, 118 insertions(+), 97 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index c5c15573e23f..1e6421ac1ed9 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -437,14 +437,14 @@ static void prepare_info(struct Scsi_Host *instance) struct NCR5380_hostdata *hostdata = shost_priv(instance); snprintf(hostdata->info, sizeof(hostdata->info), - "%s, io_port 0x%lx, n_io_port %d, " - "base 0x%lx, irq %d, " + "%s, irq %d, " + "io_port 0x%lx, base 0x%lx, " "can_queue %d, cmd_per_lun %d, " "sg_tablesize %d, this_id %d, " "flags { %s%s%s}, " "options { %s} ", - instance->hostt->name, instance->io_port, instance->n_io_port, - instance->base, instance->irq, + instance->hostt->name, instance->irq, + hostdata->io_port, hostdata->base, instance->can_queue, instance->cmd_per_lun, instance->sg_tablesize, instance->this_id, hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index ceafa0cd80be..02f20ff757ae 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -220,6 +220,8 @@ struct NCR5380_hostdata { NCR5380_implementation_fields; /* Board-specific data */ + u8 __iomem *io; /* Remapped 5380 address */ + u8 __iomem *pdma_io; /* Remapped PDMA address */ unsigned long poll_loops; /* Register polling limit */ spinlock_t lock; /* Protects this struct */ struct scsi_cmnd *connected; /* Currently connected cmnd */ @@ -230,6 +232,8 @@ struct NCR5380_hostdata { int flags; /* Board-specific quirks */ int dma_len; /* Requested length of DMA */ int read_overruns; /* Transfer size reduction for DMA erratum */ + unsigned long io_port; /* Device IO port */ + unsigned long base; /* Device base address */ struct list_head unissued; /* Waiting to be issued */ struct scsi_cmnd *selecting; /* Cmnd to be connected */ struct list_head autosense; /* Priority cmnd queue */ @@ -239,6 +243,7 @@ struct NCR5380_hostdata { unsigned char id_mask; /* 1 << Host ID */ unsigned char id_higher_mask; /* All bits above id_mask */ unsigned char last_message; /* Last Message Out */ + unsigned long region_size; /* Size of address/port range */ char info[256]; }; diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index f616756feee5..88db2816f97c 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -27,9 +27,7 @@ #define NCR5380_info cumanascsi_info #define NCR5380_implementation_fields \ - unsigned ctrl; \ - void __iomem *base; \ - void __iomem *dma + unsigned ctrl #include "../NCR5380.h" @@ -42,17 +40,18 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) { unsigned long *laddr; - void __iomem *dma = priv(host)->dma + 0x2000; + u8 __iomem *base = priv(host)->io; + u8 __iomem *dma = priv(host)->pdma_io + 0x2000; if(!len) return 0; - writeb(0x02, priv(host)->base + CTRL); + writeb(0x02, base + CTRL); laddr = (unsigned long *)addr; while(len >= 32) { unsigned int status; unsigned long v; - status = readb(priv(host)->base + STAT); + status = readb(base + STAT); if(status & 0x80) goto end; if(!(status & 0x40)) @@ -71,12 +70,12 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, } addr = (unsigned char *)laddr; - writeb(0x12, priv(host)->base + CTRL); + writeb(0x12, base + CTRL); while(len > 0) { unsigned int status; - status = readb(priv(host)->base + STAT); + status = readb(base + STAT); if(status & 0x80) goto end; if(status & 0x40) @@ -86,7 +85,7 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, break; } - status = readb(priv(host)->base + STAT); + status = readb(base + STAT); if(status & 0x80) goto end; if(status & 0x40) @@ -97,7 +96,7 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, } } end: - writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); + writeb(priv(host)->ctrl | 0x40, base + CTRL); if (len) return -1; @@ -108,16 +107,17 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, unsigned char *addr, int len) { unsigned long *laddr; - void __iomem *dma = priv(host)->dma + 0x2000; + u8 __iomem *base = priv(host)->io; + u8 __iomem *dma = priv(host)->pdma_io + 0x2000; if(!len) return 0; - writeb(0x00, priv(host)->base + CTRL); + writeb(0x00, base + CTRL); laddr = (unsigned long *)addr; while(len >= 32) { unsigned int status; - status = readb(priv(host)->base + STAT); + status = readb(base + STAT); if(status & 0x80) goto end; if(!(status & 0x40)) @@ -136,12 +136,12 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, } addr = (unsigned char *)laddr; - writeb(0x10, priv(host)->base + CTRL); + writeb(0x10, base + CTRL); while(len > 0) { unsigned int status; - status = readb(priv(host)->base + STAT); + status = readb(base + STAT); if(status & 0x80) goto end; if(status & 0x40) @@ -151,7 +151,7 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, break; } - status = readb(priv(host)->base + STAT); + status = readb(base + STAT); if(status & 0x80) goto end; if(status & 0x40) @@ -162,7 +162,7 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, } } end: - writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); + writeb(priv(host)->ctrl | 0x40, base + CTRL); if (len) return -1; @@ -171,7 +171,7 @@ end: static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) { - void __iomem *base = priv(host)->base; + u8 __iomem *base = priv(host)->io; unsigned char val; writeb(0, base + CTRL); @@ -186,7 +186,7 @@ static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) static void cumanascsi_write(struct Scsi_Host *host, unsigned int reg, unsigned int value) { - void __iomem *base = priv(host)->base; + u8 __iomem *base = priv(host)->io; writeb(0, base + CTRL); @@ -231,11 +231,11 @@ static int cumanascsi1_probe(struct expansion_card *ec, goto out_release; } - priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW), - ecard_resource_len(ec, ECARD_RES_IOCSLOW)); - priv(host)->dma = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), - ecard_resource_len(ec, ECARD_RES_MEMC)); - if (!priv(host)->base || !priv(host)->dma) { + priv(host)->io = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW), + ecard_resource_len(ec, ECARD_RES_IOCSLOW)); + priv(host)->pdma_io = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!priv(host)->io || !priv(host)->pdma_io) { ret = -ENOMEM; goto out_unmap; } @@ -249,7 +249,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, NCR5380_maybe_reset_bus(host); priv(host)->ctrl = 0; - writeb(0, priv(host)->base + CTRL); + writeb(0, priv(host)->io + CTRL); ret = request_irq(host->irq, cumanascsi_intr, 0, "CumanaSCSI-1", host); @@ -271,8 +271,8 @@ static int cumanascsi1_probe(struct expansion_card *ec, out_exit: NCR5380_exit(host); out_unmap: - iounmap(priv(host)->base); - iounmap(priv(host)->dma); + iounmap(priv(host)->io); + iounmap(priv(host)->pdma_io); scsi_host_put(host); out_release: ecard_release_resources(ec); @@ -283,15 +283,17 @@ static int cumanascsi1_probe(struct expansion_card *ec, static void cumanascsi1_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); + void __iomem *base = priv(host)->io; + void __iomem *dma = priv(host)->pdma_io; ecard_set_drvdata(ec, NULL); scsi_remove_host(host); free_irq(host->irq, host); NCR5380_exit(host); - iounmap(priv(host)->base); - iounmap(priv(host)->dma); scsi_host_put(host); + iounmap(base); + iounmap(dma); ecard_release_resources(ec); } diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index a396024a3cae..1c4a44a1e62d 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -17,9 +17,9 @@ #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_read(reg) \ - readb(priv(instance)->base + ((reg) << 2)) + readb(priv(instance)->io + ((reg) << 2)) #define NCR5380_write(reg, value) \ - writeb(value, priv(instance)->base + ((reg) << 2)) + writeb(value, priv(instance)->io + ((reg) << 2)) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup oakscsi_pread @@ -29,8 +29,7 @@ #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info -#define NCR5380_implementation_fields \ - void __iomem *base +#define NCR5380_implementation_fields /* none */ #include "../NCR5380.h" @@ -43,7 +42,7 @@ static inline int oakscsi_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len) { - void __iomem *base = priv(instance)->base; + u8 __iomem *base = priv(instance)->io; printk("writing %p len %d\n",addr, len); @@ -58,7 +57,7 @@ printk("writing %p len %d\n",addr, len); static inline int oakscsi_pread(struct Scsi_Host *instance, unsigned char *addr, int len) { - void __iomem *base = priv(instance)->base; + u8 __iomem *base = priv(instance)->io; printk("reading %p len %d\n", addr, len); while(len > 0) { @@ -133,15 +132,14 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) goto release; } - priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), - ecard_resource_len(ec, ECARD_RES_MEMC)); - if (!priv(host)->base) { + priv(host)->io = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!priv(host)->io) { ret = -ENOMEM; goto unreg; } host->irq = NO_IRQ; - host->n_io_port = 255; ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); if (ret) @@ -159,7 +157,7 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) out_exit: NCR5380_exit(host); out_unmap: - iounmap(priv(host)->base); + iounmap(priv(host)->io); unreg: scsi_host_put(host); release: @@ -171,13 +169,14 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) static void oakscsi_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); + void __iomem *base = priv(host)->io; ecard_set_drvdata(ec, NULL); scsi_remove_host(host); NCR5380_exit(host); - iounmap(priv(host)->base); scsi_host_put(host); + iounmap(base); ecard_release_resources(ec); } diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 9b5a457d4bca..3b6df905a81c 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -34,8 +34,10 @@ * Definitions for the generic 5380 driver. */ -#define NCR5380_read(reg) inb(instance->io_port + reg) -#define NCR5380_write(reg, value) outb(value, instance->io_port + reg) +#define priv(instance) ((struct NCR5380_hostdata *)shost_priv(instance)) + +#define NCR5380_read(reg) inb(priv(instance)->base + (reg)) +#define NCR5380_write(reg, value) outb(value, priv(instance)->base + (reg)) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup(instance, dst, len) (0) @@ -71,6 +73,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *shost; + struct NCR5380_hostdata *hostdata; unsigned long io; int error = -ENODEV; @@ -88,7 +91,9 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, sizeof(struct NCR5380_hostdata)); if (!shost) goto out_release_region; - shost->io_port = io; + + hostdata = shost_priv(shost); + hostdata->base = io; /* This card does not seem to raise an interrupt on pdev->irq. * Steam-powered SCSI controllers run without an IRQ anyway. @@ -125,7 +130,8 @@ out_host_put: static void dmx3191d_remove_one(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); - unsigned long io = shost->io_port; + struct NCR5380_hostdata *hostdata = shost_priv(shost); + unsigned long io = hostdata->base; scsi_remove_host(shost); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 4d7a9de01645..98aef0eb8b59 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -115,7 +115,7 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, unsigned long region_size; struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; - void __iomem *iomem; + u8 __iomem *iomem; switch (board) { case BOARD_NCR5380: @@ -201,11 +201,11 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, } hostdata = shost_priv(instance); - hostdata->iomem = iomem; + hostdata->io = iomem; + hostdata->region_size = region_size; if (is_pmio) { - instance->io_port = base; - instance->n_io_port = region_size; + hostdata->io_port = base; hostdata->io_width = 1; /* 8-bit PDMA by default */ hostdata->offset = 0; @@ -215,7 +215,7 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, */ switch (board) { case BOARD_NCR53C400: - instance->io_port += 8; + hostdata->io_port += 8; hostdata->c400_ctl_status = 0; hostdata->c400_blk_cnt = 1; hostdata->c400_host_buf = 4; @@ -231,8 +231,7 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, break; } } else { - instance->base = base; - hostdata->iomem_size = region_size; + hostdata->base = base; hostdata->offset = NCR53C400_mem_base; switch (board) { case BOARD_NCR53C400: @@ -314,17 +313,21 @@ out_release: static void generic_NCR5380_release_resources(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); + void __iomem *iomem = hostdata->io; + unsigned long io_port = hostdata->io_port; + unsigned long base = hostdata->base; + unsigned long region_size = hostdata->region_size; scsi_remove_host(instance); if (instance->irq != NO_IRQ) free_irq(instance->irq, instance); NCR5380_exit(instance); - iounmap(hostdata->iomem); - if (instance->io_port) - release_region(instance->io_port, instance->n_io_port); - else - release_mem_region(instance->base, hostdata->iomem_size); scsi_host_put(instance); + iounmap(iomem); + if (io_port) + release_region(io_port, region_size); + else + release_mem_region(base, region_size); } /** @@ -356,15 +359,15 @@ static inline int generic_NCR5380_pread(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; /* FIXME - no timeout */ - if (instance->io_port && hostdata->io_width == 2) - insw(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_port && hostdata->io_width == 2) + insw(hostdata->io_port + hostdata->c400_host_buf, dst + start, 64); - else if (instance->io_port) - insb(instance->io_port + hostdata->c400_host_buf, + else if (hostdata->io_port) + insb(hostdata->io_port + hostdata->c400_host_buf, dst + start, 128); else memcpy_fromio(dst + start, - hostdata->iomem + NCR53C400_host_buffer, 128); + hostdata->io + NCR53C400_host_buffer, 128); start += 128; blocks--; @@ -374,15 +377,15 @@ static inline int generic_NCR5380_pread(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; /* FIXME - no timeout */ - if (instance->io_port && hostdata->io_width == 2) - insw(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_port && hostdata->io_width == 2) + insw(hostdata->io_port + hostdata->c400_host_buf, dst + start, 64); - else if (instance->io_port) - insb(instance->io_port + hostdata->c400_host_buf, + else if (hostdata->io_port) + insb(hostdata->io_port + hostdata->c400_host_buf, dst + start, 128); else memcpy_fromio(dst + start, - hostdata->iomem + NCR53C400_host_buffer, 128); + hostdata->io + NCR53C400_host_buffer, 128); start += 128; blocks--; @@ -431,14 +434,14 @@ static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout - if (instance->io_port && hostdata->io_width == 2) - outsw(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_port && hostdata->io_width == 2) + outsw(hostdata->io_port + hostdata->c400_host_buf, src + start, 64); - else if (instance->io_port) - outsb(instance->io_port + hostdata->c400_host_buf, + else if (hostdata->io_port) + outsb(hostdata->io_port + hostdata->c400_host_buf, src + start, 128); else - memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, + memcpy_toio(hostdata->io + NCR53C400_host_buffer, src + start, 128); start += 128; @@ -448,14 +451,14 @@ static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - no timeout - if (instance->io_port && hostdata->io_width == 2) - outsw(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_port && hostdata->io_width == 2) + outsw(hostdata->io_port + hostdata->c400_host_buf, src + start, 64); - else if (instance->io_port) - outsb(instance->io_port + hostdata->c400_host_buf, + else if (hostdata->io_port) + outsb(hostdata->io_port + hostdata->c400_host_buf, src + start, 128); else - memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, + memcpy_toio(hostdata->io + NCR53C400_host_buffer, src + start, 128); start += 128; diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 2b77782439f1..ec4d70bef5e5 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -17,18 +17,16 @@ #define DRV_MODULE_NAME "g_NCR5380" #define NCR5380_read(reg) \ - ioread8(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ + ioread8(((struct NCR5380_hostdata *)shost_priv(instance))->io + \ ((struct NCR5380_hostdata *)shost_priv(instance))->offset + \ (reg)) #define NCR5380_write(reg, value) \ - iowrite8(value, ((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ + iowrite8(value, ((struct NCR5380_hostdata *)shost_priv(instance))->io + \ ((struct NCR5380_hostdata *)shost_priv(instance))->offset + \ (reg)) #define NCR5380_implementation_fields \ int offset; \ - void __iomem *iomem; \ - resource_size_t iomem_size; \ int c400_ctl_status; \ int c400_blk_cnt; \ int c400_host_buf; \ diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index a590089b9397..80e10d9f2067 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -28,8 +28,7 @@ /* Definitions for the core NCR5380 driver. */ -#define NCR5380_implementation_fields unsigned char *pdma_base; \ - int pdma_residual +#define NCR5380_implementation_fields int pdma_residual #define NCR5380_read(reg) macscsi_read(instance, reg) #define NCR5380_write(reg, value) macscsi_write(instance, reg, value) @@ -67,12 +66,16 @@ module_param(setup_toshiba_delay, int, 0); static inline char macscsi_read(struct Scsi_Host *instance, int reg) { - return in_8(instance->base + (reg << 4)); + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + return in_8(hostdata->io + (reg << 4)); } static inline void macscsi_write(struct Scsi_Host *instance, int reg, int value) { - out_8(instance->base + (reg << 4), value); + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + out_8(hostdata->io + (reg << 4), value); } #ifndef MODULE @@ -171,7 +174,7 @@ static int macscsi_pread(struct Scsi_Host *instance, unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char *s = hostdata->pdma_base + (INPUT_DATA_REG << 4); + unsigned char *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); unsigned char *d = dst; int n = len; int transferred; @@ -275,7 +278,7 @@ static int macscsi_pwrite(struct Scsi_Host *instance, { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char *s = src; - unsigned char *d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4); + unsigned char *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); int n = len; int transferred; @@ -356,6 +359,7 @@ static struct scsi_host_template mac_scsi_template = { static int __init mac_scsi_probe(struct platform_device *pdev) { struct Scsi_Host *instance; + struct NCR5380_hostdata *hostdata; int error; int host_flags = 0; struct resource *irq, *pio_mem, *pdma_mem = NULL; @@ -388,17 +392,18 @@ static int __init mac_scsi_probe(struct platform_device *pdev) if (!instance) return -ENOMEM; - instance->base = pio_mem->start; if (irq) instance->irq = irq->start; else instance->irq = NO_IRQ; - if (pdma_mem && setup_use_pdma) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); + hostdata = shost_priv(instance); + hostdata->base = pio_mem->start; + hostdata->io = (void *)pio_mem->start; - hostdata->pdma_base = (unsigned char *)pdma_mem->start; - } else + if (pdma_mem && setup_use_pdma) + hostdata->pdma_io = (void *)pdma_mem->start; + else host_flags |= FLAG_NO_PSEUDO_DMA; host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 3c4c07038948..efee144c6056 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -428,6 +428,7 @@ static struct scsi_host_template sun3_scsi_template = { static int __init sun3_scsi_probe(struct platform_device *pdev) { struct Scsi_Host *instance; + struct NCR5380_hostdata *hostdata; int error; struct resource *irq, *mem; unsigned char *ioaddr; @@ -502,9 +503,11 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) goto fail_alloc; } - instance->io_port = (unsigned long)ioaddr; instance->irq = irq->start; + hostdata = shost_priv(instance); + hostdata->base = (unsigned long)ioaddr; + error = NCR5380_init(instance, host_flags); if (error) goto fail_init; From 61e1ce588b101f13a4c6f713b95d65551c8572e3 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 022/256] scsi: ncr5380: Use correct types for device register accessors For timeout values adopt unsigned long, which is the type of jiffies etc. For chip register values and bit masks pass u8, which is the return type of readb, inb etc. For device register offsets adopt unsigned int, as it is suitable for adding to base addresses. Pass the NCR5380_hostdata pointer to the board-specific routines instead of the Scsi_Host pointer. The board-specific code is concerned with hardware and not with SCSI protocol or the mid-layer. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Acked-by: Russell King Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 10 ++++++++-- drivers/scsi/NCR5380.h | 7 +++++-- drivers/scsi/arm/cumana_1.c | 20 +++++++++++--------- drivers/scsi/arm/oak.c | 6 ++---- drivers/scsi/atari_scsi.c | 16 ++++++++-------- drivers/scsi/dmx3191d.c | 6 ++---- drivers/scsi/g_NCR5380.h | 8 ++------ drivers/scsi/mac_scsi.c | 22 ++-------------------- drivers/scsi/sun3_scsi.c | 32 +++++++++----------------------- 9 files changed, 49 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 1e6421ac1ed9..33676c9ec5fb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -196,8 +196,9 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) */ static int NCR5380_poll_politely2(struct Scsi_Host *instance, - int reg1, int bit1, int val1, - int reg2, int bit2, int val2, int wait) + unsigned int reg1, u8 bit1, u8 val1, + unsigned int reg2, u8 bit2, u8 val2, + unsigned long wait) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long n = hostdata->poll_loops; @@ -284,6 +285,7 @@ mrs[] = { static void NCR5380_print(struct Scsi_Host *instance) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char status, data, basr, mr, icr, i; data = NCR5380_read(CURRENT_SCSI_DATA_REG); @@ -333,6 +335,7 @@ static struct { static void NCR5380_print_phase(struct Scsi_Host *instance) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char status; int i; @@ -1316,6 +1319,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char p = *phase, tmp; int c = *count; unsigned char *d = *data; @@ -1438,6 +1442,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, static void do_reset(struct Scsi_Host *instance) { + struct NCR5380_hostdata __maybe_unused *hostdata = shost_priv(instance); unsigned long flags; local_irq_save(flags); @@ -1460,6 +1465,7 @@ static void do_reset(struct Scsi_Host *instance) static int do_abort(struct Scsi_Host *instance) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char *msgptr, phase, tmp; int len; int rc; diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 02f20ff757ae..c2d8b78d1a38 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -302,10 +302,13 @@ static void NCR5380_reselect(struct Scsi_Host *instance); static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, int, int); +static int NCR5380_poll_politely2(struct Scsi_Host *, + unsigned int, u8, u8, + unsigned int, u8, u8, unsigned long); static inline int NCR5380_poll_politely(struct Scsi_Host *instance, - int reg, int bit, int val, int wait) + unsigned int reg, u8 bit, u8 val, + unsigned long wait) { return NCR5380_poll_politely2(instance, reg, bit, val, reg, bit, val, wait); diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 88db2816f97c..ae1d4c6786de 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -14,8 +14,8 @@ #include #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) -#define NCR5380_read(reg) cumanascsi_read(instance, reg) -#define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) +#define NCR5380_read(reg) cumanascsi_read(hostdata, reg) +#define NCR5380_write(reg, value) cumanascsi_write(hostdata, reg, value) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup cumanascsi_pread @@ -169,30 +169,32 @@ end: return 0; } -static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) +static u8 cumanascsi_read(struct NCR5380_hostdata *hostdata, + unsigned int reg) { - u8 __iomem *base = priv(host)->io; - unsigned char val; + u8 __iomem *base = hostdata->io; + u8 val; writeb(0, base + CTRL); val = readb(base + 0x2100 + (reg << 2)); - priv(host)->ctrl = 0x40; + hostdata->ctrl = 0x40; writeb(0x40, base + CTRL); return val; } -static void cumanascsi_write(struct Scsi_Host *host, unsigned int reg, unsigned int value) +static void cumanascsi_write(struct NCR5380_hostdata *hostdata, + unsigned int reg, u8 value) { - u8 __iomem *base = priv(host)->io; + u8 __iomem *base = hostdata->io; writeb(0, base + CTRL); writeb(value, base + 0x2100 + (reg << 2)); - priv(host)->ctrl = 0x40; + hostdata->ctrl = 0x40; writeb(0x40, base + CTRL); } diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 1c4a44a1e62d..d320f88c32c4 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -16,10 +16,8 @@ #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) -#define NCR5380_read(reg) \ - readb(priv(instance)->io + ((reg) << 2)) -#define NCR5380_write(reg, value) \ - writeb(value, priv(instance)->io + ((reg) << 2)) +#define NCR5380_read(reg) readb(hostdata->io + ((reg) << 2)) +#define NCR5380_write(reg, value) writeb(value, hostdata->io + ((reg) << 2)) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup oakscsi_pread diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 862f30c23ff0..aed69ac334eb 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -126,8 +126,8 @@ static inline unsigned long SCSI_DMA_GETADR(void) static void atari_scsi_fetch_restbytes(void); -static unsigned char (*atari_scsi_reg_read)(unsigned char reg); -static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value); +static u8 (*atari_scsi_reg_read)(unsigned int); +static void (*atari_scsi_reg_write)(unsigned int, u8); static unsigned long atari_dma_residual, atari_dma_startaddr; static short atari_dma_active; @@ -658,30 +658,30 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, * NCR5380_write call these functions via function pointers. */ -static unsigned char atari_scsi_tt_reg_read(unsigned char reg) +static u8 atari_scsi_tt_reg_read(unsigned int reg) { return tt_scsi_regp[reg * 2]; } -static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value) +static void atari_scsi_tt_reg_write(unsigned int reg, u8 value) { tt_scsi_regp[reg * 2] = value; } -static unsigned char atari_scsi_falcon_reg_read(unsigned char reg) +static u8 atari_scsi_falcon_reg_read(unsigned int reg) { unsigned long flags; - unsigned char result; + u8 result; reg += 0x88; local_irq_save(flags); dma_wd.dma_mode_status = (u_short)reg; - result = (u_char)dma_wd.fdc_acces_seccount; + result = (u8)dma_wd.fdc_acces_seccount; local_irq_restore(flags); return result; } -static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value) +static void atari_scsi_falcon_reg_write(unsigned int reg, u8 value) { unsigned long flags; diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 3b6df905a81c..ab7b097a465f 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -34,10 +34,8 @@ * Definitions for the generic 5380 driver. */ -#define priv(instance) ((struct NCR5380_hostdata *)shost_priv(instance)) - -#define NCR5380_read(reg) inb(priv(instance)->base + (reg)) -#define NCR5380_write(reg, value) outb(value, priv(instance)->base + (reg)) +#define NCR5380_read(reg) inb(hostdata->base + (reg)) +#define NCR5380_write(reg, value) outb(value, hostdata->base + (reg)) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup(instance, dst, len) (0) diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index ec4d70bef5e5..10191d1c488a 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -17,13 +17,9 @@ #define DRV_MODULE_NAME "g_NCR5380" #define NCR5380_read(reg) \ - ioread8(((struct NCR5380_hostdata *)shost_priv(instance))->io + \ - ((struct NCR5380_hostdata *)shost_priv(instance))->offset + \ - (reg)) + ioread8(hostdata->io + hostdata->offset + (reg)) #define NCR5380_write(reg, value) \ - iowrite8(value, ((struct NCR5380_hostdata *)shost_priv(instance))->io + \ - ((struct NCR5380_hostdata *)shost_priv(instance))->offset + \ - (reg)) + iowrite8(value, hostdata->io + hostdata->offset + (reg)) #define NCR5380_implementation_fields \ int offset; \ diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 80e10d9f2067..9ac38229c02d 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -30,8 +30,8 @@ #define NCR5380_implementation_fields int pdma_residual -#define NCR5380_read(reg) macscsi_read(instance, reg) -#define NCR5380_write(reg, value) macscsi_write(instance, reg, value) +#define NCR5380_read(reg) in_8(hostdata->io + ((reg) << 4)) +#define NCR5380_write(reg, value) out_8(hostdata->io + ((reg) << 4), value) #define NCR5380_dma_xfer_len(instance, cmd, phase) \ macscsi_dma_xfer_len(instance, cmd) @@ -60,24 +60,6 @@ module_param(setup_hostid, int, 0); static int setup_toshiba_delay = -1; module_param(setup_toshiba_delay, int, 0); -/* - * NCR 5380 register access functions - */ - -static inline char macscsi_read(struct Scsi_Host *instance, int reg) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - return in_8(hostdata->io + (reg << 4)); -} - -static inline void macscsi_write(struct Scsi_Host *instance, int reg, int value) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - out_8(hostdata->io + (reg << 4), value); -} - #ifndef MODULE static int __init mac_scsi_setup(char *str) { diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index efee144c6056..b408474885dc 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -43,8 +43,8 @@ #define NCR5380_implementation_fields /* none */ -#define NCR5380_read(reg) sun3scsi_read(reg) -#define NCR5380_write(reg, value) sun3scsi_write(reg, value) +#define NCR5380_read(reg) in_8(hostdata->io + (reg)) +#define NCR5380_write(reg, value) out_8(hostdata->io + (reg), value) #define NCR5380_queue_command sun3scsi_queue_command #define NCR5380_bus_reset sun3scsi_bus_reset @@ -82,7 +82,6 @@ module_param(setup_hostid, int, 0); #define SUN3_DVMA_BUFSIZE 0xe000 static struct scsi_cmnd *sun3_dma_setup_done; -static unsigned char *sun3_scsi_regp; static volatile struct sun3_dma_regs *dregs; static struct sun3_udc_regs *udc_regs; static unsigned char *sun3_dma_orig_addr; @@ -90,20 +89,6 @@ static unsigned long sun3_dma_orig_count; static int sun3_dma_active; static unsigned long last_residual; -/* - * NCR 5380 register access functions - */ - -static inline unsigned char sun3scsi_read(int reg) -{ - return in_8(sun3_scsi_regp + reg); -} - -static inline void sun3scsi_write(int reg, int value) -{ - out_8(sun3_scsi_regp + reg, value); -} - #ifndef SUN3_SCSI_VME /* dma controller register access functions */ @@ -431,7 +416,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) struct NCR5380_hostdata *hostdata; int error; struct resource *irq, *mem; - unsigned char *ioaddr; + void __iomem *ioaddr; int host_flags = 0; #ifdef SUN3_SCSI_VME int i; @@ -494,8 +479,6 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) } #endif - sun3_scsi_regp = ioaddr; - instance = scsi_host_alloc(&sun3_scsi_template, sizeof(struct NCR5380_hostdata)); if (!instance) { @@ -506,7 +489,8 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) instance->irq = irq->start; hostdata = shost_priv(instance); - hostdata->base = (unsigned long)ioaddr; + hostdata->base = mem->start; + hostdata->io = ioaddr; error = NCR5380_init(instance, host_flags); if (error) @@ -555,13 +539,15 @@ fail_init: fail_alloc: if (udc_regs) dvma_free(udc_regs); - iounmap(sun3_scsi_regp); + iounmap(ioaddr); return error; } static int __exit sun3_scsi_remove(struct platform_device *pdev) { struct Scsi_Host *instance = platform_get_drvdata(pdev); + struct NCR5380_hostdata *hostdata = shost_priv(instance); + void __iomem *ioaddr = hostdata->io; scsi_remove_host(instance); free_irq(instance->irq, instance); @@ -569,7 +555,7 @@ static int __exit sun3_scsi_remove(struct platform_device *pdev) scsi_host_put(instance); if (udc_regs) dvma_free(udc_regs); - iounmap(sun3_scsi_regp); + iounmap(ioaddr); return 0; } From d5d37a0ab13b8f4ccfa58a4e852e19bcbf47ed5e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 023/256] scsi: ncr5380: Pass hostdata pointer to register polling routines Pass a NCR5380_hostdata struct pointer to the board-specific routines instead of a Scsi_Host struct pointer. This reduces pointer chasing in the PIO and PDMA fast paths. The old way was a mistake because it is slow and the board-specific code is not concerned with the mid-layer. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 33 ++++++++++++++++----------------- drivers/scsi/NCR5380.h | 6 +++--- drivers/scsi/mac_scsi.c | 10 +++++----- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 33676c9ec5fb..85589922ef03 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -178,7 +178,7 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) /** * NCR5380_poll_politely2 - wait for two chip register values - * @instance: controller to poll + * @hostdata: host private data * @reg1: 5380 register to poll * @bit1: Bitmask to check * @val1: Expected value @@ -195,12 +195,11 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. */ -static int NCR5380_poll_politely2(struct Scsi_Host *instance, +static int NCR5380_poll_politely2(struct NCR5380_hostdata *hostdata, unsigned int reg1, u8 bit1, u8 val1, unsigned int reg2, u8 bit2, u8 val2, unsigned long wait) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long n = hostdata->poll_loops; unsigned long deadline = jiffies + wait; @@ -561,7 +560,7 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) case 3: case 5: shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n"); - NCR5380_poll_politely(instance, + NCR5380_poll_politely(hostdata, STATUS_REG, SR_BSY, 0, 5 * HZ); break; case 2: @@ -1076,7 +1075,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, */ spin_unlock_irq(&hostdata->lock); - err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, + err = NCR5380_poll_politely2(hostdata, MODE_REG, MR_ARBITRATE, 0, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, HZ); spin_lock_irq(&hostdata->lock); @@ -1202,7 +1201,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * selection. */ - err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY, + err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_BSY, SR_BSY, msecs_to_jiffies(250)); if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { @@ -1248,7 +1247,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, /* Wait for start of REQ/ACK handshake */ - err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ); spin_lock_irq(&hostdata->lock); if (err < 0) { shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); @@ -1338,7 +1337,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, * valid */ - if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) break; dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); @@ -1383,7 +1382,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); } - if (NCR5380_poll_politely(instance, + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) break; @@ -1483,7 +1482,7 @@ static int do_abort(struct Scsi_Host *instance) * the target sees, so we just handshake. */ - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); + rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); if (rc < 0) goto timeout; @@ -1494,7 +1493,7 @@ static int do_abort(struct Scsi_Host *instance) if (tmp != PHASE_MSGOUT) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); + rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 3 * HZ); if (rc < 0) goto timeout; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -1682,12 +1681,12 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * byte. */ - if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, HZ) < 0) { result = -1; shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); } - if (NCR5380_poll_politely(instance, STATUS_REG, + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, HZ) < 0) { result = -1; shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); @@ -1698,7 +1697,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. */ - if (NCR5380_poll_politely2(instance, + if (NCR5380_poll_politely2(hostdata, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) { result = -1; @@ -2077,7 +2076,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } /* switch(phase) */ } else { spin_unlock_irq(&hostdata->lock); - NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ); spin_lock_irq(&hostdata->lock); } } @@ -2123,7 +2122,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - if (NCR5380_poll_politely(instance, + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); return; @@ -2134,7 +2133,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) * Wait for target to go into MSGIN. */ - if (NCR5380_poll_politely(instance, + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) { do_abort(instance); return; diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index c2d8b78d1a38..4682baab07ed 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -302,15 +302,15 @@ static void NCR5380_reselect(struct Scsi_Host *instance); static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -static int NCR5380_poll_politely2(struct Scsi_Host *, +static int NCR5380_poll_politely2(struct NCR5380_hostdata *, unsigned int, u8, u8, unsigned int, u8, u8, unsigned long); -static inline int NCR5380_poll_politely(struct Scsi_Host *instance, +static inline int NCR5380_poll_politely(struct NCR5380_hostdata *hostdata, unsigned int reg, u8 bit, u8 val, unsigned long wait) { - return NCR5380_poll_politely2(instance, reg, bit, val, + return NCR5380_poll_politely2(hostdata, reg, bit, val, reg, bit, val, wait); } diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 9ac38229c02d..07f956c18266 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -161,7 +161,7 @@ static int macscsi_pread(struct Scsi_Host *instance, int n = len; int transferred; - while (!NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_DRQ | BASR_PHASE_MATCH, BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { CP_IO_TO_MEM(s, d, n); @@ -174,7 +174,7 @@ static int macscsi_pread(struct Scsi_Host *instance, return 0; /* Target changed phase early? */ - if (NCR5380_poll_politely2(instance, STATUS_REG, SR_REQ, SR_REQ, + if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0) scmd_printk(KERN_ERR, hostdata->connected, "%s: !REQ and !ACK\n", __func__); @@ -264,7 +264,7 @@ static int macscsi_pwrite(struct Scsi_Host *instance, int n = len; int transferred; - while (!NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_DRQ | BASR_PHASE_MATCH, BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { CP_MEM_TO_IO(s, d, n); @@ -273,7 +273,7 @@ static int macscsi_pwrite(struct Scsi_Host *instance, hostdata->pdma_residual = len - transferred; /* Target changed phase early? */ - if (NCR5380_poll_politely2(instance, STATUS_REG, SR_REQ, SR_REQ, + if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0) scmd_printk(KERN_ERR, hostdata->connected, "%s: !REQ and !ACK\n", __func__); @@ -282,7 +282,7 @@ static int macscsi_pwrite(struct Scsi_Host *instance, /* No bus error. */ if (n == 0) { - if (NCR5380_poll_politely(instance, TARGET_COMMAND_REG, + if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT, HZ / 64) < 0) scmd_printk(KERN_ERR, hostdata->connected, From 7c60663143c29ea64f51e692f950f8619e0e4c77 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 024/256] scsi: ncr5380: Expedite register polling Avoid the call to NCR5380_poll_politely2() when possible. The call is easily short-circuited on the PIO fast path, using the inline wrapper. This requires that the NCR5380_read macro be made available before any #include "NCR5380.h" so a few declarations have to be moved too. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 3 +++ drivers/scsi/arm/cumana_1.c | 4 ++++ drivers/scsi/atari_scsi.c | 6 +++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 4682baab07ed..b2c560cb0218 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -310,6 +310,9 @@ static inline int NCR5380_poll_politely(struct NCR5380_hostdata *hostdata, unsigned int reg, u8 bit, u8 val, unsigned long wait) { + if ((NCR5380_read(reg) & bit) == val) + return 0; + return NCR5380_poll_politely2(hostdata, reg, bit, val, reg, bit, val, wait); } diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index ae1d4c6786de..fb7600dec5be 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -29,6 +29,10 @@ #define NCR5380_implementation_fields \ unsigned ctrl +struct NCR5380_hostdata; +static u8 cumanascsi_read(struct NCR5380_hostdata *, unsigned int); +static void cumanascsi_write(struct NCR5380_hostdata *, unsigned int, u8); + #include "../NCR5380.h" #define CTRL 0x16fc diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index aed69ac334eb..f77c311ba5d0 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -57,6 +57,9 @@ #define NCR5380_implementation_fields /* none */ +static u8 (*atari_scsi_reg_read)(unsigned int); +static void (*atari_scsi_reg_write)(unsigned int, u8); + #define NCR5380_read(reg) atari_scsi_reg_read(reg) #define NCR5380_write(reg, value) atari_scsi_reg_write(reg, value) @@ -126,9 +129,6 @@ static inline unsigned long SCSI_DMA_GETADR(void) static void atari_scsi_fetch_restbytes(void); -static u8 (*atari_scsi_reg_read)(unsigned int); -static void (*atari_scsi_reg_write)(unsigned int, u8); - static unsigned long atari_dma_residual, atari_dma_startaddr; static short atari_dma_active; /* pointer to the dribble buffer */ From 4a98f896bf2c66a69517fc5e10dc67288cb8da93 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 025/256] scsi: ncr5380: Use correct types for DMA routines Apply prototypes to get consistent function signatures for the DMA functions implemented in the board-specific drivers. To avoid using macros to alter actual parameters, some of those functions are reworked slightly. This is a step toward the goal of passing the board-specific routines to the core driver using an ops struct (as in a platform driver or library module). This also helps fix some inconsistent types: where the core driver uses ints (cmd->SCp.this_residual and hostdata->dma_len) for keeping track of transfers, certain board-specific routines used unsigned long. While we are fixing these function signatures, pass the hostdata pointer to DMA routines instead of a Scsi_Host pointer, for shorter and faster code. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Acked-by: Russell King Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 74 ++++++++++++++++++++----------------- drivers/scsi/NCR5380.h | 25 +++++++++++++ drivers/scsi/arm/cumana_1.c | 26 ++++++++----- drivers/scsi/arm/oak.c | 13 ++++--- drivers/scsi/atari_scsi.c | 45 ++++++++++++---------- drivers/scsi/dmx3191d.c | 8 ++-- drivers/scsi/g_NCR5380.c | 13 +++---- drivers/scsi/g_NCR5380.h | 5 +-- drivers/scsi/mac_scsi.c | 36 +++++++++--------- drivers/scsi/sun3_scsi.c | 45 +++++++++++++++------- 10 files changed, 176 insertions(+), 114 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 85589922ef03..7d4e135a36cb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -121,9 +121,10 @@ * * Either real DMA *or* pseudo DMA may be implemented * - * NCR5380_dma_write_setup(instance, src, count) - initialize - * NCR5380_dma_read_setup(instance, dst, count) - initialize - * NCR5380_dma_residual(instance); - residual count + * NCR5380_dma_xfer_len - determine size of DMA/PDMA transfer + * NCR5380_dma_send_setup - execute DMA/PDMA from memory to 5380 + * NCR5380_dma_recv_setup - execute DMA/PDMA from 5380 to memory + * NCR5380_dma_residual - residual byte count * * The generic driver is initialized by calling NCR5380_init(instance), * after setting the appropriate host specific fields and ID. If the @@ -871,7 +872,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_read(RESET_PARITY_INTERRUPT_REG); - transferred = hostdata->dma_len - NCR5380_dma_residual(instance); + transferred = hostdata->dma_len - NCR5380_dma_residual(hostdata); hostdata->dma_len = 0; data = (unsigned char **)&hostdata->connected->SCp.ptr; @@ -1578,9 +1579,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * starting the NCR. This is also the cleaner way for the TT. */ if (p & SR_IO) - result = NCR5380_dma_recv_setup(instance, d, c); + result = NCR5380_dma_recv_setup(hostdata, d, c); else - result = NCR5380_dma_send_setup(instance, d, c); + result = NCR5380_dma_send_setup(hostdata, d, c); } /* @@ -1612,9 +1613,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * NCR access, else the DMA setup gets trashed! */ if (p & SR_IO) - result = NCR5380_dma_recv_setup(instance, d, c); + result = NCR5380_dma_recv_setup(hostdata, d, c); else - result = NCR5380_dma_send_setup(instance, d, c); + result = NCR5380_dma_send_setup(hostdata, d, c); } /* On failure, NCR5380_dma_xxxx_setup() returns a negative int. */ @@ -1754,22 +1755,26 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); } #ifdef CONFIG_SUN3 - if (phase == PHASE_CMDOUT) { - void *d; - unsigned long count; + if (phase == PHASE_CMDOUT && + sun3_dma_setup_done != cmd) { + int count; if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - count = cmd->SCp.buffer->length; - d = sg_virt(cmd->SCp.buffer); - } else { - count = cmd->SCp.this_residual; - d = cmd->SCp.ptr; + ++cmd->SCp.buffer; + --cmd->SCp.buffers_residual; + cmd->SCp.this_residual = cmd->SCp.buffer->length; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); } - if (sun3_dma_setup_done != cmd && - sun3scsi_dma_xfer_len(count, cmd) > 0) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(cmd->request)); + count = sun3scsi_dma_xfer_len(hostdata, cmd); + + if (count > 0) { + if (rq_data_dir(cmd->request)) + sun3scsi_dma_send_setup(hostdata, + cmd->SCp.ptr, count); + else + sun3scsi_dma_recv_setup(hostdata, + cmd->SCp.ptr, count); sun3_dma_setup_done = cmd; } #ifdef SUN3_SCSI_VME @@ -1830,7 +1835,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) transfersize = 0; if (!cmd->device->borken) - transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); + transfersize = NCR5380_dma_xfer_len(hostdata, cmd); if (transfersize > 0) { len = transfersize; @@ -2207,22 +2212,25 @@ static void NCR5380_reselect(struct Scsi_Host *instance) } #ifdef CONFIG_SUN3 - { - void *d; - unsigned long count; + if (sun3_dma_setup_done != tmp) { + int count; if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) { - count = tmp->SCp.buffer->length; - d = sg_virt(tmp->SCp.buffer); - } else { - count = tmp->SCp.this_residual; - d = tmp->SCp.ptr; + ++tmp->SCp.buffer; + --tmp->SCp.buffers_residual; + tmp->SCp.this_residual = tmp->SCp.buffer->length; + tmp->SCp.ptr = sg_virt(tmp->SCp.buffer); } - if (sun3_dma_setup_done != tmp && - sun3scsi_dma_xfer_len(count, tmp) > 0) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(tmp->request)); + count = sun3scsi_dma_xfer_len(hostdata, tmp); + + if (count > 0) { + if (rq_data_dir(tmp->request)) + sun3scsi_dma_send_setup(hostdata, + tmp->SCp.ptr, count); + else + sun3scsi_dma_recv_setup(hostdata, + tmp->SCp.ptr, count); sun3_dma_setup_done = tmp; } } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index b2c560cb0218..3c6ce5434449 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -317,5 +317,30 @@ static inline int NCR5380_poll_politely(struct NCR5380_hostdata *hostdata, reg, bit, val, wait); } +static int NCR5380_dma_xfer_len(struct NCR5380_hostdata *, + struct scsi_cmnd *); +static int NCR5380_dma_send_setup(struct NCR5380_hostdata *, + unsigned char *, int); +static int NCR5380_dma_recv_setup(struct NCR5380_hostdata *, + unsigned char *, int); +static int NCR5380_dma_residual(struct NCR5380_hostdata *); + +static inline int NCR5380_dma_xfer_none(struct NCR5380_hostdata *hostdata, + struct scsi_cmnd *cmd) +{ + return 0; +} + +static inline int NCR5380_dma_setup_none(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count) +{ + return 0; +} + +static inline int NCR5380_dma_residual_none(struct NCR5380_hostdata *hostdata) +{ + return 0; +} + #endif /* __KERNEL__ */ #endif /* NCR5380_H */ diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index fb7600dec5be..a87b99c7fb9a 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -17,10 +17,10 @@ #define NCR5380_read(reg) cumanascsi_read(hostdata, reg) #define NCR5380_write(reg, value) cumanascsi_write(hostdata, reg, value) -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_xfer_len cumanascsi_dma_xfer_len #define NCR5380_dma_recv_setup cumanascsi_pread #define NCR5380_dma_send_setup cumanascsi_pwrite -#define NCR5380_dma_residual(instance) (0) +#define NCR5380_dma_residual NCR5380_dma_residual_none #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command @@ -40,12 +40,12 @@ static void cumanascsi_write(struct NCR5380_hostdata *, unsigned int, u8); #define L(v) (((v)<<16)|((v) & 0x0000ffff)) #define H(v) (((v)>>16)|((v) & 0xffff0000)) -static inline int cumanascsi_pwrite(struct Scsi_Host *host, +static inline int cumanascsi_pwrite(struct NCR5380_hostdata *hostdata, unsigned char *addr, int len) { unsigned long *laddr; - u8 __iomem *base = priv(host)->io; - u8 __iomem *dma = priv(host)->pdma_io + 0x2000; + u8 __iomem *base = hostdata->io; + u8 __iomem *dma = hostdata->pdma_io + 0x2000; if(!len) return 0; @@ -100,19 +100,19 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, } } end: - writeb(priv(host)->ctrl | 0x40, base + CTRL); + writeb(hostdata->ctrl | 0x40, base + CTRL); if (len) return -1; return 0; } -static inline int cumanascsi_pread(struct Scsi_Host *host, +static inline int cumanascsi_pread(struct NCR5380_hostdata *hostdata, unsigned char *addr, int len) { unsigned long *laddr; - u8 __iomem *base = priv(host)->io; - u8 __iomem *dma = priv(host)->pdma_io + 0x2000; + u8 __iomem *base = hostdata->io; + u8 __iomem *dma = hostdata->pdma_io + 0x2000; if(!len) return 0; @@ -166,13 +166,19 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, } } end: - writeb(priv(host)->ctrl | 0x40, base + CTRL); + writeb(hostdata->ctrl | 0x40, base + CTRL); if (len) return -1; return 0; } +static int cumanascsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, + struct scsi_cmnd *cmd) +{ + return cmd->transfersize; +} + static u8 cumanascsi_read(struct NCR5380_hostdata *hostdata, unsigned int reg) { diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index d320f88c32c4..6be6666534d4 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -19,10 +19,10 @@ #define NCR5380_read(reg) readb(hostdata->io + ((reg) << 2)) #define NCR5380_write(reg, value) writeb(value, hostdata->io + ((reg) << 2)) -#define NCR5380_dma_xfer_len(instance, cmd, phase) (0) +#define NCR5380_dma_xfer_len NCR5380_dma_xfer_none #define NCR5380_dma_recv_setup oakscsi_pread #define NCR5380_dma_send_setup oakscsi_pwrite -#define NCR5380_dma_residual(instance) (0) +#define NCR5380_dma_residual NCR5380_dma_residual_none #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info @@ -37,10 +37,10 @@ #define STAT ((128 + 16) << 2) #define DATA ((128 + 8) << 2) -static inline int oakscsi_pwrite(struct Scsi_Host *instance, +static inline int oakscsi_pwrite(struct NCR5380_hostdata *hostdata, unsigned char *addr, int len) { - u8 __iomem *base = priv(instance)->io; + u8 __iomem *base = hostdata->io; printk("writing %p len %d\n",addr, len); @@ -52,10 +52,11 @@ printk("writing %p len %d\n",addr, len); return 0; } -static inline int oakscsi_pread(struct Scsi_Host *instance, +static inline int oakscsi_pread(struct NCR5380_hostdata *hostdata, unsigned char *addr, int len) { - u8 __iomem *base = priv(instance)->io; + u8 __iomem *base = hostdata->io; + printk("reading %p len %d\n", addr, len); while(len > 0) { diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index f77c311ba5d0..105b35393ce9 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -67,14 +67,10 @@ static void (*atari_scsi_reg_write)(unsigned int, u8); #define NCR5380_abort atari_scsi_abort #define NCR5380_info atari_scsi_info -#define NCR5380_dma_recv_setup(instance, data, count) \ - atari_scsi_dma_setup(instance, data, count, 0) -#define NCR5380_dma_send_setup(instance, data, count) \ - atari_scsi_dma_setup(instance, data, count, 1) -#define NCR5380_dma_residual(instance) \ - atari_scsi_dma_residual(instance) -#define NCR5380_dma_xfer_len(instance, cmd, phase) \ - atari_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO)) +#define NCR5380_dma_xfer_len atari_scsi_dma_xfer_len +#define NCR5380_dma_recv_setup atari_scsi_dma_recv_setup +#define NCR5380_dma_send_setup atari_scsi_dma_send_setup +#define NCR5380_dma_residual atari_scsi_dma_residual #define NCR5380_acquire_dma_irq(instance) falcon_get_lock(instance) #define NCR5380_release_dma_irq(instance) falcon_release_lock() @@ -457,15 +453,14 @@ static int __init atari_scsi_setup(char *str) __setup("atascsi=", atari_scsi_setup); #endif /* !MODULE */ - -static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, +static unsigned long atari_scsi_dma_setup(struct NCR5380_hostdata *hostdata, void *data, unsigned long count, int dir) { unsigned long addr = virt_to_phys(data); - dprintk(NDEBUG_DMA, "scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, " - "dir = %d\n", instance->host_no, data, addr, count, dir); + dprintk(NDEBUG_DMA, "scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, dir = %d\n", + hostdata->host->host_no, data, addr, count, dir); if (!IS_A_TT() && !STRAM_ADDR(addr)) { /* If we have a non-DMAable address on a Falcon, use the dribble @@ -522,8 +517,19 @@ static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, return count; } +static inline int atari_scsi_dma_recv_setup(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count) +{ + return atari_scsi_dma_setup(hostdata, data, count, 0); +} -static long atari_scsi_dma_residual(struct Scsi_Host *instance) +static inline int atari_scsi_dma_send_setup(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count) +{ + return atari_scsi_dma_setup(hostdata, data, count, 1); +} + +static int atari_scsi_dma_residual(struct NCR5380_hostdata *hostdata) { return atari_dma_residual; } @@ -564,10 +570,11 @@ static int falcon_classify_cmd(struct scsi_cmnd *cmd) * the overrun problem, so this question is academic :-) */ -static unsigned long atari_dma_xfer_len(unsigned long wanted_len, - struct scsi_cmnd *cmd, int write_flag) +static int atari_scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, + struct scsi_cmnd *cmd) { - unsigned long possible_len, limit; + int wanted_len = cmd->SCp.this_residual; + int possible_len, limit; if (wanted_len < DMA_MIN_SIZE) return 0; @@ -604,7 +611,7 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes. */ - if (write_flag) { + if (cmd->sc_data_direction == DMA_TO_DEVICE) { /* Write operation can always use the DMA, but the transfer size must * be rounded up to the next multiple of 512 (atari_dma_setup() does * this). @@ -644,8 +651,8 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, possible_len = limit; if (possible_len != wanted_len) - dprintk(NDEBUG_DMA, "Sorry, must cut DMA transfer size to %ld bytes " - "instead of %ld\n", possible_len, wanted_len); + dprintk(NDEBUG_DMA, "DMA transfer now %d bytes instead of %d\n", + possible_len, wanted_len); return possible_len; } diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index ab7b097a465f..3aa4657478e8 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -37,10 +37,10 @@ #define NCR5380_read(reg) inb(hostdata->base + (reg)) #define NCR5380_write(reg, value) outb(value, hostdata->base + (reg)) -#define NCR5380_dma_xfer_len(instance, cmd, phase) (0) -#define NCR5380_dma_recv_setup(instance, dst, len) (0) -#define NCR5380_dma_send_setup(instance, src, len) (0) -#define NCR5380_dma_residual(instance) (0) +#define NCR5380_dma_xfer_len NCR5380_dma_xfer_none +#define NCR5380_dma_recv_setup NCR5380_dma_setup_none +#define NCR5380_dma_send_setup NCR5380_dma_setup_none +#define NCR5380_dma_residual NCR5380_dma_residual_none #define NCR5380_implementation_fields /* none */ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 98aef0eb8b59..7299ad9889c9 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -332,7 +332,7 @@ static void generic_NCR5380_release_resources(struct Scsi_Host *instance) /** * generic_NCR5380_pread - pseudo DMA read - * @instance: adapter to read from + * @hostdata: scsi host private data * @dst: buffer to read into * @len: buffer length * @@ -340,10 +340,9 @@ static void generic_NCR5380_release_resources(struct Scsi_Host *instance) * controller */ -static inline int generic_NCR5380_pread(struct Scsi_Host *instance, +static inline int generic_NCR5380_pread(struct NCR5380_hostdata *hostdata, unsigned char *dst, int len) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; int start = 0; @@ -406,7 +405,7 @@ static inline int generic_NCR5380_pread(struct Scsi_Host *instance, /** * generic_NCR5380_pwrite - pseudo DMA write - * @instance: adapter to read from + * @hostdata: scsi host private data * @dst: buffer to read into * @len: buffer length * @@ -414,10 +413,9 @@ static inline int generic_NCR5380_pread(struct Scsi_Host *instance, * controller */ -static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, +static inline int generic_NCR5380_pwrite(struct NCR5380_hostdata *hostdata, unsigned char *src, int len) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; int start = 0; @@ -480,10 +478,9 @@ static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, return 0; } -static int generic_NCR5380_dma_xfer_len(struct Scsi_Host *instance, +static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata, struct scsi_cmnd *cmd) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); int transfersize = cmd->transfersize; if (hostdata->flags & FLAG_NO_PSEUDO_DMA) diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 10191d1c488a..3ce5b65ccb00 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -32,11 +32,10 @@ #define NCR53C400_host_buffer 0x3900 #define NCR53C400_region_size 0x3a00 -#define NCR5380_dma_xfer_len(instance, cmd, phase) \ - generic_NCR5380_dma_xfer_len(instance, cmd) +#define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len #define NCR5380_dma_recv_setup generic_NCR5380_pread #define NCR5380_dma_send_setup generic_NCR5380_pwrite -#define NCR5380_dma_residual(instance) (0) +#define NCR5380_dma_residual NCR5380_dma_residual_none #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 07f956c18266..ccb68d12692c 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -33,11 +33,10 @@ #define NCR5380_read(reg) in_8(hostdata->io + ((reg) << 4)) #define NCR5380_write(reg, value) out_8(hostdata->io + ((reg) << 4), value) -#define NCR5380_dma_xfer_len(instance, cmd, phase) \ - macscsi_dma_xfer_len(instance, cmd) +#define NCR5380_dma_xfer_len macscsi_dma_xfer_len #define NCR5380_dma_recv_setup macscsi_pread #define NCR5380_dma_send_setup macscsi_pwrite -#define NCR5380_dma_residual(instance) (hostdata->pdma_residual) +#define NCR5380_dma_residual macscsi_dma_residual #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -152,10 +151,9 @@ __asm__ __volatile__ \ : "0"(s), "1"(d), "2"(n) \ : "d0") -static int macscsi_pread(struct Scsi_Host *instance, - unsigned char *dst, int len) +static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, + unsigned char *dst, int len) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); unsigned char *d = dst; int n = len; @@ -181,16 +179,16 @@ static int macscsi_pread(struct Scsi_Host *instance, if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) return 0; - dsprintk(NDEBUG_PSEUDO_DMA, instance, + dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, "%s: bus error (%d/%d)\n", __func__, transferred, len); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); d = dst + transferred; n = len - transferred; } scmd_printk(KERN_ERR, hostdata->connected, "%s: phase mismatch or !DRQ\n", __func__); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); return -1; } @@ -255,10 +253,9 @@ __asm__ __volatile__ \ : "0"(s), "1"(d), "2"(n) \ : "d0") -static int macscsi_pwrite(struct Scsi_Host *instance, - unsigned char *src, int len) +static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, + unsigned char *src, int len) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char *s = src; unsigned char *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); int n = len; @@ -290,25 +287,23 @@ static int macscsi_pwrite(struct Scsi_Host *instance, return 0; } - dsprintk(NDEBUG_PSEUDO_DMA, instance, + dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, "%s: bus error (%d/%d)\n", __func__, transferred, len); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); s = src + transferred; n = len - transferred; } scmd_printk(KERN_ERR, hostdata->connected, "%s: phase mismatch or !DRQ\n", __func__); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); return -1; } -static int macscsi_dma_xfer_len(struct Scsi_Host *instance, +static int macscsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, struct scsi_cmnd *cmd) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); - if (hostdata->flags & FLAG_NO_PSEUDO_DMA || cmd->SCp.this_residual < 16) return 0; @@ -316,6 +311,11 @@ static int macscsi_dma_xfer_len(struct Scsi_Host *instance, return cmd->SCp.this_residual; } +static int macscsi_dma_residual(struct NCR5380_hostdata *hostdata) +{ + return hostdata->pdma_residual; +} + #include "NCR5380.c" #define DRV_MODULE_NAME "mac_scsi" diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index b408474885dc..88db6992420e 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -51,12 +51,10 @@ #define NCR5380_abort sun3scsi_abort #define NCR5380_info sun3scsi_info -#define NCR5380_dma_recv_setup(instance, data, count) (count) -#define NCR5380_dma_send_setup(instance, data, count) (count) -#define NCR5380_dma_residual(instance) \ - sun3scsi_dma_residual(instance) -#define NCR5380_dma_xfer_len(instance, cmd, phase) \ - sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd) +#define NCR5380_dma_xfer_len sun3scsi_dma_xfer_len +#define NCR5380_dma_recv_setup sun3scsi_dma_count +#define NCR5380_dma_send_setup sun3scsi_dma_count +#define NCR5380_dma_residual sun3scsi_dma_residual #define NCR5380_acquire_dma_irq(instance) (1) #define NCR5380_release_dma_irq(instance) @@ -143,8 +141,8 @@ static irqreturn_t scsi_sun3_intr(int irq, void *dev) } /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ -static unsigned long sun3scsi_dma_setup(struct Scsi_Host *instance, - void *data, unsigned long count, int write_flag) +static int sun3scsi_dma_setup(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count, int write_flag) { void *addr; @@ -196,9 +194,10 @@ static unsigned long sun3scsi_dma_setup(struct Scsi_Host *instance, dregs->csr |= CSR_FIFO; if(dregs->fifo_count != count) { - shost_printk(KERN_ERR, instance, "FIFO mismatch %04x not %04x\n", + shost_printk(KERN_ERR, hostdata->host, + "FIFO mismatch %04x not %04x\n", dregs->fifo_count, (unsigned int) count); - NCR5380_dprint(NDEBUG_DMA, instance); + NCR5380_dprint(NDEBUG_DMA, hostdata->host); } /* setup udc */ @@ -233,14 +232,34 @@ static unsigned long sun3scsi_dma_setup(struct Scsi_Host *instance, } -static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) +static int sun3scsi_dma_count(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count) +{ + return count; +} + +static inline int sun3scsi_dma_recv_setup(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count) +{ + return sun3scsi_dma_setup(hostdata, data, count, 0); +} + +static inline int sun3scsi_dma_send_setup(struct NCR5380_hostdata *hostdata, + unsigned char *data, int count) +{ + return sun3scsi_dma_setup(hostdata, data, count, 1); +} + +static int sun3scsi_dma_residual(struct NCR5380_hostdata *hostdata) { return last_residual; } -static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted_len, - struct scsi_cmnd *cmd) +static int sun3scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, + struct scsi_cmnd *cmd) { + int wanted_len = cmd->SCp.this_residual; + if (wanted_len < DMA_MIN_SIZE || cmd->request->cmd_type != REQ_TYPE_FS) return 0; From 9af9fecb9e5380c778e89501aefe8bc779783c01 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 10 Oct 2016 00:46:53 -0400 Subject: [PATCH 026/256] scsi: ncr5380: Suppress unhelpful "interrupt without IRQ bit" message If a NCR5380 host instance ends up on a shared interrupt line then this printk will be a problem. It is already a problem on some Mac models: when testing mac_scsi on a PowerBook 180 I found that PDMA transfers (but not PIO transfers) cause the message to be logged. These spurious interrupts don't appear to come from the DRQ signal from the 5380. And they don't happen at all on the Mac LC III. A comment in the NetBSD source code mentions this mystery. Testing seems to show that we can safely ignore these interrupts. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 7d4e135a36cb..d849ffa378b1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -995,7 +995,7 @@ static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id) } handled = 1; } else { - shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); + dsprintk(NDEBUG_INTR, instance, "interrupt without IRQ bit\n"); #ifdef SUN3_SCSI_VME dregs->csr |= CSR_DMA_ENABLE; #endif From 4e6f767dba1c9a7279b3b24694cdf3b73e00f722 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 13 Oct 2016 10:46:41 +0200 Subject: [PATCH 027/256] scsi: mptscsih: Remove bogus interpretation of request->ioprio Having an I/O priority does not mean we should send all requests as HEAD OF QUEUE tags. Reported-by: Adam Manzanares Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptscsih.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 6c9fc11efb87..08a807d6a44f 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1366,15 +1366,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt) /* Default to untagged. Once a target structure has been allocated, * use the Inquiry data to determine if device supports tagged. */ - if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) - && (SCpnt->device->tagged_supported)) { + if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) && + SCpnt->device->tagged_supported) scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; - if (SCpnt->request && SCpnt->request->ioprio) { - if (((SCpnt->request->ioprio & 0x7) == 1) || - !(SCpnt->request->ioprio & 0x7)) - scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ; - } - } else + else scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED; From 19be606be1df35479333bd04e2cdaddc9d77e38c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 13 Oct 2016 13:10:08 -0300 Subject: [PATCH 028/256] scsi: hpsa: Remove unneeded void pointer cast It's not necessary to cast the result of kmalloc, since void pointers are promoted to any other type. This also fixes following coccinelle warning: casting value returned by memory allocation function to (BIG_IOCTL_Command_struct *) is useless. Signed-off-by: Javier Martinez Canillas Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index d007ec18179a..4e82b692298e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6657,8 +6657,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) return -EINVAL; if (!capable(CAP_SYS_RAWIO)) return -EPERM; - ioc = (BIG_IOCTL_Command_struct *) - kmalloc(sizeof(*ioc), GFP_KERNEL); + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); if (!ioc) { status = -ENOMEM; goto cleanup1; From 6f4f788f4667fb461932d4c97a1b3ef50f7c0164 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 13 Oct 2016 13:57:41 -0300 Subject: [PATCH 029/256] MAINTAINERS: Remove defunct iss storage mailing list It appears that the mailing list email address doesn't exist anymore: : host smtp.hp.com[15.73.96.116] said: 550 5.1.1 : Recipient address rejected: User unknown in virtual alias table (in reply to RCPT TO command) Signed-off-by: Javier Martinez Canillas Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3d15bd5b63b5..7213f7e76cde 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5613,7 +5613,6 @@ F: drivers/watchdog/hpwdt.c HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa) M: Don Brace -L: iss_storagedev@hp.com L: esc.storagedev@microsemi.com L: linux-scsi@vger.kernel.org S: Supported @@ -5624,7 +5623,6 @@ F: include/uapi/linux/cciss*.h HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) M: Don Brace -L: iss_storagedev@hp.com L: esc.storagedev@microsemi.com L: linux-scsi@vger.kernel.org S: Supported From bdee98606f68dfadbc5f4f31a3c351b5bc68e2c2 Mon Sep 17 00:00:00 2001 From: Joao Pinto Date: Fri, 14 Oct 2016 16:59:23 +0100 Subject: [PATCH 030/256] MAINTAINERS: Changing maintainer for ufs DWC. I am going to leave Synopsys and so this patch changes the Maintainer for UFS Synopsys' specific drivers to my colleagues Manjunath and Prabu. Signed-off-by: Joao Pinto Signed-off-by: Martin K. Petersen --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7213f7e76cde..e2d184ebf3b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12393,7 +12393,8 @@ F: Documentation/scsi/ufs.txt F: drivers/scsi/ufs/ UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS -M: Joao Pinto +M: Manjunath M Bettegowda +M: Prabu Thangamuthu L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/ufs/*dwc* From 4b160ae8a34983f11635981168760412ed3c2cfa Mon Sep 17 00:00:00 2001 From: "Milan P. Gandhi" Date: Thu, 13 Oct 2016 15:06:02 -0700 Subject: [PATCH 031/256] scsi: lpfc: Fix few small typos in lpfc_scsi.c This patch does a cleanup and fixes few small typos in lpfc_scsi.c Signed-off-by: Milan P. Gandhi Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index d197aa176dee..ca56f28f5836 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -607,7 +607,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, } /** - * lpfc_sli4_post_scsi_sgl_list - Psot blocks of scsi buffer sgls from a list + * lpfc_sli4_post_scsi_sgl_list - Post blocks of scsi buffer sgls from a list * @phba: pointer to lpfc hba data structure. * @post_sblist: pointer to the scsi buffer list. * @@ -736,7 +736,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba, } /** - * lpfc_sli4_repost_scsi_sgl_list - Repsot all the allocated scsi buffer sgls + * lpfc_sli4_repost_scsi_sgl_list - Repost all the allocated scsi buffer sgls * @phba: pointer to lpfc hba data structure. * * This routine walks the list of scsi buffers that have been allocated and @@ -857,7 +857,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) psb->data, psb->dma_handle); kfree(psb); lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "3368 Failed to allocated IOTAG for" + "3368 Failed to allocate IOTAG for" " XRI:0x%x\n", lxri); lpfc_sli4_free_xri(phba, lxri); break; @@ -1136,7 +1136,7 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) * * This routine does the pci dma mapping for scatter-gather list of scsi cmnd * field of @lpfc_cmd for device with SLI-3 interface spec. This routine scans - * through sg elements and format the bdea. This routine also initializes all + * through sg elements and format the bde. This routine also initializes all * IOCB fields which are dependent on scsi command request buffer. * * Return codes: @@ -1269,13 +1269,16 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) #ifdef CONFIG_SCSI_LPFC_DEBUG_FS -/* Return if if error injection is detected by Initiator */ +/* Return BG_ERR_INIT if error injection is detected by Initiator */ #define BG_ERR_INIT 0x1 -/* Return if if error injection is detected by Target */ +/* Return BG_ERR_TGT if error injection is detected by Target */ #define BG_ERR_TGT 0x2 -/* Return if if swapping CSUM<-->CRC is required for error injection */ +/* Return BG_ERR_SWAP if swapping CSUM<-->CRC is required for error injection */ #define BG_ERR_SWAP 0x10 -/* Return if disabling Guard/Ref/App checking is required for error injection */ +/** + * Return BG_ERR_CHECK if disabling Guard/Ref/App checking is required for + * error injection + **/ #define BG_ERR_CHECK 0x20 /** @@ -4822,7 +4825,7 @@ wait_for_cmpl: ret = FAILED; lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "0748 abort handler timed out waiting " - "for abortng I/O (xri:x%x) to complete: " + "for aborting I/O (xri:x%x) to complete: " "ret %#x, ID %d, LUN %llu\n", iocb->sli4_xritag, ret, cmnd->device->id, cmnd->device->lun); From dc58f44c2140748d96e33a533cd9e80692f58518 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:03 -0700 Subject: [PATCH 032/256] scsi: lpfc: Correct embedded io wq element size Correct embedded io wq element size. Embedded element sizes are 128 byte elements Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 734a0428ef0e..af64d708f84f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7256,6 +7256,7 @@ int lpfc_sli4_queue_create(struct lpfc_hba *phba) { struct lpfc_queue *qdesc; + uint32_t wqesize; int idx; /* @@ -7340,15 +7341,10 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.fcp_cq[idx] = qdesc; /* Create Fast Path FCP WQs */ - if (phba->fcp_embed_io) { - qdesc = lpfc_sli4_queue_alloc(phba, - LPFC_WQE128_SIZE, - LPFC_WQE128_DEF_COUNT); - } else { - qdesc = lpfc_sli4_queue_alloc(phba, - phba->sli4_hba.wq_esize, - phba->sli4_hba.wq_ecount); - } + wqesize = (phba->fcp_embed_io) ? + LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize; + qdesc = lpfc_sli4_queue_alloc(phba, wqesize, + phba->sli4_hba.wq_ecount); if (!qdesc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0503 Failed allocate fast-path FCP " From eed695d70e7eff55595f222b55b96f105d4a27ca Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:04 -0700 Subject: [PATCH 033/256] scsi: lpfc: Fix sg_reset on SCSI device causing kernel crash Fix sg_reset on SCSI device causing kernel crash Driver could reference stale node pointers in task mgmt call. Changed to use resetting cmd and look up node pointer in task mgmt function. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index ca56f28f5836..4c53149ed618 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4948,26 +4948,30 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd) * 0x2002 - Success. **/ static int -lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, - unsigned tgt_id, uint64_t lun_id, - uint8_t task_mgmt_cmd) +lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, + unsigned int tgt_id, uint64_t lun_id, + uint8_t task_mgmt_cmd) { struct lpfc_hba *phba = vport->phba; struct lpfc_scsi_buf *lpfc_cmd; struct lpfc_iocbq *iocbq; struct lpfc_iocbq *iocbqrsp; - struct lpfc_nodelist *pnode = rdata->pnode; + struct lpfc_rport_data *rdata; + struct lpfc_nodelist *pnode; int ret; int status; - if (!pnode || !NLP_CHK_NODE_ACT(pnode)) + rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + if (!rdata || !rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode)) return FAILED; + pnode = rdata->pnode; - lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode); + lpfc_cmd = lpfc_get_scsi_buf(phba, pnode); if (lpfc_cmd == NULL) return FAILED; lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo; lpfc_cmd->rdata = rdata; + lpfc_cmd->pCmd = cmnd; status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, task_mgmt_cmd); @@ -5174,7 +5178,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id, + status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id, FCP_LUN_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, @@ -5252,7 +5256,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id, + status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id, FCP_TARGET_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, @@ -5331,7 +5335,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) if (!match) continue; - status = lpfc_send_taskmgmt(vport, ndlp->rport->dd_data, + status = lpfc_send_taskmgmt(vport, cmnd, i, 0, FCP_TARGET_RESET); if (status != SUCCESS) { From 61bda8f7c3ce46ce5de7c91a3383f7fe963643b9 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:05 -0700 Subject: [PATCH 034/256] scsi: lpfc: Set driver environment data on adapter Set driver environment data on adapter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 12 ++++++++++++ drivers/scsi/lpfc/lpfc_sli.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index ee8022737591..0b2c3377fa0a 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -921,6 +921,7 @@ struct mbox_header { #define LPFC_MBOX_OPCODE_GET_PORT_NAME 0x4D #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A #define LPFC_MBOX_OPCODE_GET_VPD_DATA 0x5B +#define LPFC_MBOX_OPCODE_SET_HOST_DATA 0x5D #define LPFC_MBOX_OPCODE_SEND_ACTIVATION 0x73 #define LPFC_MBOX_OPCODE_RESET_LICENSES 0x74 #define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A @@ -2919,6 +2920,16 @@ struct lpfc_mbx_set_feature { }; +#define LPFC_SET_HOST_OS_DRIVER_VERSION 0x2 +struct lpfc_mbx_set_host_data { +#define LPFC_HOST_OS_DRIVER_VERSION_SIZE 48 + struct mbox_header header; + uint32_t param_id; + uint32_t param_len; + uint8_t data[LPFC_HOST_OS_DRIVER_VERSION_SIZE]; +}; + + struct lpfc_mbx_get_sli4_parameters { struct mbox_header header; struct lpfc_sli4_parameters sli4_parameters; @@ -3313,6 +3324,7 @@ struct lpfc_mqe { struct lpfc_mbx_get_port_name get_port_name; struct lpfc_mbx_set_feature set_feature; struct lpfc_mbx_memory_dump_type3 mem_dump_type3; + struct lpfc_mbx_set_host_data set_host_data; struct lpfc_mbx_nop nop; } un; }; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c5326055beee..cb59f4ec46b0 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -47,6 +47,7 @@ #include "lpfc_compat.h" #include "lpfc_debugfs.h" #include "lpfc_vport.h" +#include "lpfc_version.h" /* There are only four IOCB completion types. */ typedef enum _lpfc_iocb_type { @@ -6289,6 +6290,25 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba) return 0; } +void +lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) +{ + uint32_t len; + + len = sizeof(struct lpfc_mbx_set_host_data) - + sizeof(struct lpfc_sli4_cfg_mhdr); + lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, + LPFC_MBOX_OPCODE_SET_HOST_DATA, len, + LPFC_SLI4_MBX_EMBED); + + mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION; + mbox->u.mqe.un.set_host_data.param_len = 8; + snprintf(mbox->u.mqe.un.set_host_data.data, + LPFC_HOST_OS_DRIVER_VERSION_SIZE, + "Linux %s v"LPFC_DRIVER_VERSION, + (phba->hba_flag & HBA_FCOE_MODE) ? "FCoE" : "FC"); +} + /** * lpfc_sli4_hba_setup - SLI4 device intialization PCI function * @phba: Pointer to HBA context object. @@ -6540,6 +6560,15 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) goto out_free_mbox; } + lpfc_set_host_data(phba, mboxq); + + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + if (rc) { + lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "2134 Failed to set host os driver version %x", + rc); + } + /* Read the port's service parameters. */ rc = lpfc_read_sparam(phba, mboxq, vport->vpi); if (rc) { From b3b98b742962eece44bcb134ef8fb84e1d6149f2 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:06 -0700 Subject: [PATCH 035/256] scsi: lpfc: Make lpfc_prot_xxx params per hba parameters Make lpfc_prot_mask and lpfc_prot_guard per hba parameters Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 ++ drivers/scsi/lpfc/lpfc_attr.c | 23 ++++++++++++++--------- drivers/scsi/lpfc/lpfc_crtn.h | 2 -- drivers/scsi/lpfc/lpfc_init.c | 28 +++++++++++++++------------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index b484859464f6..debba5e77d9c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -746,6 +746,8 @@ struct lpfc_hba { uint32_t cfg_oas_priority; uint32_t cfg_XLanePriority; uint32_t cfg_enable_bg; + uint32_t cfg_prot_mask; + uint32_t cfg_prot_guard; uint32_t cfg_hostmem_hgp; uint32_t cfg_log_verbose; uint32_t cfg_aer_support; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index f1019908800e..be81e617b174 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4691,12 +4691,15 @@ unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF; # HBA supports DIX Type 1: Host to HBA Type 1 protection # */ -unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION | - SHOST_DIX_TYPE0_PROTECTION | - SHOST_DIX_TYPE1_PROTECTION; - -module_param(lpfc_prot_mask, uint, S_IRUGO); -MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); +LPFC_ATTR(prot_mask, + (SHOST_DIF_TYPE1_PROTECTION | + SHOST_DIX_TYPE0_PROTECTION | + SHOST_DIX_TYPE1_PROTECTION), + 0, + (SHOST_DIF_TYPE1_PROTECTION | + SHOST_DIX_TYPE0_PROTECTION | + SHOST_DIX_TYPE1_PROTECTION), + "T10-DIF host protection capabilities mask"); /* # lpfc_prot_guard: i @@ -4706,9 +4709,9 @@ MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); # - Default will result in registering capabilities for all guard types # */ -unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP; -module_param(lpfc_prot_guard, byte, S_IRUGO); -MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type"); +LPFC_ATTR(prot_guard, + SHOST_DIX_GUARD_IP, SHOST_DIX_GUARD_CRC, SHOST_DIX_GUARD_IP, + "T10-DIF host protection guard type"); /* * Delay initial NPort discovery when Clean Address bit is cleared in @@ -5828,6 +5831,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->cfg_oas_flags = 0; phba->cfg_oas_priority = 0; lpfc_enable_bg_init(phba, lpfc_enable_bg); + lpfc_prot_mask_init(phba, lpfc_prot_mask); + lpfc_prot_guard_init(phba, lpfc_prot_guard); if (phba->sli_rev == LPFC_SLI_REV4) phba->cfg_poll = 0; else diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index bd7576d452f2..16195b73a536 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -397,8 +397,6 @@ extern spinlock_t _dump_buf_lock; extern int _dump_buf_done; extern spinlock_t pgcnt_lock; extern unsigned int pgcnt; -extern unsigned int lpfc_prot_mask; -extern unsigned char lpfc_prot_guard; extern unsigned int lpfc_fcp_look_ahead; /* Interface exported by fabric iocb scheduler */ diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index af64d708f84f..117c69a82786 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6279,34 +6279,36 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) uint32_t old_guard; int pagecnt = 10; - if (lpfc_prot_mask && lpfc_prot_guard) { + if (phba->cfg_prot_mask && phba->cfg_prot_guard) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "1478 Registering BlockGuard with the " "SCSI layer\n"); - old_mask = lpfc_prot_mask; - old_guard = lpfc_prot_guard; + old_mask = phba->cfg_prot_mask; + old_guard = phba->cfg_prot_guard; /* Only allow supported values */ - lpfc_prot_mask &= (SHOST_DIF_TYPE1_PROTECTION | + phba->cfg_prot_mask &= (SHOST_DIF_TYPE1_PROTECTION | SHOST_DIX_TYPE0_PROTECTION | SHOST_DIX_TYPE1_PROTECTION); - lpfc_prot_guard &= (SHOST_DIX_GUARD_IP | SHOST_DIX_GUARD_CRC); + phba->cfg_prot_guard &= (SHOST_DIX_GUARD_IP | + SHOST_DIX_GUARD_CRC); /* DIF Type 1 protection for profiles AST1/C1 is end to end */ - if (lpfc_prot_mask == SHOST_DIX_TYPE1_PROTECTION) - lpfc_prot_mask |= SHOST_DIF_TYPE1_PROTECTION; + if (phba->cfg_prot_mask == SHOST_DIX_TYPE1_PROTECTION) + phba->cfg_prot_mask |= SHOST_DIF_TYPE1_PROTECTION; - if (lpfc_prot_mask && lpfc_prot_guard) { - if ((old_mask != lpfc_prot_mask) || - (old_guard != lpfc_prot_guard)) + if (phba->cfg_prot_mask && phba->cfg_prot_guard) { + if ((old_mask != phba->cfg_prot_mask) || + (old_guard != phba->cfg_prot_guard)) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "1475 Registering BlockGuard with the " "SCSI layer: mask %d guard %d\n", - lpfc_prot_mask, lpfc_prot_guard); + phba->cfg_prot_mask, + phba->cfg_prot_guard); - scsi_host_set_prot(shost, lpfc_prot_mask); - scsi_host_set_guard(shost, lpfc_prot_guard); + scsi_host_set_prot(shost, phba->cfg_prot_mask); + scsi_host_set_guard(shost, phba->cfg_prot_guard); } else lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "1479 Not Registering BlockGuard with the SCSI " From 0d8c8ba3fa5e21eebf36ef7ab7e370622309ac1c Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:07 -0700 Subject: [PATCH 036/256] scsi: lpfc: Code clean up for lpfc_iocb_cnt parameter Code clean up for lpfc_iocb_cnt parameter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index be81e617b174..e5092dc7c92f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2827,14 +2827,8 @@ lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(txcmplq_hw, S_IRUGO, lpfc_txcmplq_hw_show, NULL); -int lpfc_iocb_cnt = 2; -module_param(lpfc_iocb_cnt, int, S_IRUGO); -MODULE_PARM_DESC(lpfc_iocb_cnt, +LPFC_ATTR_R(iocb_cnt, 2, 1, 5, "Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs"); -lpfc_param_show(iocb_cnt); -lpfc_param_init(iocb_cnt, 2, 1, 5); -static DEVICE_ATTR(lpfc_iocb_cnt, S_IRUGO, - lpfc_iocb_cnt_show, NULL); /* # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear From 31202b0e3c8dded6623a13ea0033a7bf03121c0a Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:08 -0700 Subject: [PATCH 037/256] scsi: lpfc: Code cleanup for lpfc_enable_rrq parameter Code cleanup for lpfc_enable_rrq parameter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e5092dc7c92f..22a66c74476a 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2759,18 +2759,14 @@ LPFC_ATTR_R(enable_npiv, 1, 0, 1, LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2, "FCF Fast failover=1 Priority failover=2"); -int lpfc_enable_rrq = 2; -module_param(lpfc_enable_rrq, int, S_IRUGO); -MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality"); -lpfc_param_show(enable_rrq); /* # lpfc_enable_rrq: Track XRI/OXID reuse after IO failures # 0x0 = disabled, XRI/OXID use not tracked. # 0x1 = XRI/OXID reuse is timed with ratov, RRQ sent. # 0x2 = XRI/OXID reuse is timed with ratov, No RRQ sent. */ -lpfc_param_init(enable_rrq, 2, 0, 2); -static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL); +LPFC_ATTR_R(enable_rrq, 2, 0, 2, + "Enable RRQ functionality"); /* # lpfc_suppress_link_up: Bring link up at initialization From 506139a23eff91c365098fe9cc418e0fdcc5b660 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:09 -0700 Subject: [PATCH 038/256] scsi: lpfc: Code cleanup for lpfc_aer_support parameter Code cleanup for lpfc_aer_support parameter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 43 +++-------------------------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 22a66c74476a..ae76aaa1da50 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3779,6 +3779,9 @@ static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, # 1 = aer supported and enabled (default) # Value range is [0,1]. Default value is 1. */ +LPFC_ATTR(aer_support, 1, 0, 1, + "Enable PCIe device AER support"); +lpfc_param_show(aer_support) /** * lpfc_aer_support_store - Set the adapter for aer support @@ -3861,46 +3864,6 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, return rc; } -static int lpfc_aer_support = 1; -module_param(lpfc_aer_support, int, S_IRUGO); -MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support"); -lpfc_param_show(aer_support) - -/** - * lpfc_aer_support_init - Set the initial adapters aer support flag - * @phba: lpfc_hba pointer. - * @val: enable aer or disable aer flag. - * - * Description: - * If val is in a valid range [0,1], then set the adapter's initial - * cfg_aer_support field. It will be up to the driver's probe_one - * routine to determine whether the device's AER support can be set - * or not. - * - * Notes: - * If the value is not in range log a kernel error message, and - * choose the default value of setting AER support and return. - * - * Returns: - * zero if val saved. - * -EINVAL val out of range - **/ -static int -lpfc_aer_support_init(struct lpfc_hba *phba, int val) -{ - if (val == 0 || val == 1) { - phba->cfg_aer_support = val; - return 0; - } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2712 lpfc_aer_support attribute value %d out " - "of range, allowed values are 0|1, setting it " - "to default value of 1\n", val); - /* By default, try to enable AER on a device */ - phba->cfg_aer_support = 1; - return -EINVAL; -} - static DEVICE_ATTR(lpfc_aer_support, S_IRUGO | S_IWUSR, lpfc_aer_support_show, lpfc_aer_support_store); From 0a0354398cf8775c40973bcfa60ec8d5a72ee58d Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:10 -0700 Subject: [PATCH 039/256] scsi: lpfc: Code cleanup for lpfc_topology parameter Code cleanup for lpfc_topology parameter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ae76aaa1da50..81b1fafd4f97 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3194,6 +3194,8 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6]. # Default value is 0. */ +LPFC_ATTR(topology, 0, 0, 6, + "Select Fibre Channel topology"); /** * lpfc_topology_set - Set the adapters topology field @@ -3271,11 +3273,8 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr, phba->brd_no, val); return -EINVAL; } -static int lpfc_topology = 0; -module_param(lpfc_topology, int, S_IRUGO); -MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology"); + lpfc_param_show(topology) -lpfc_param_init(topology, 0, 0, 6) static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, lpfc_topology_show, lpfc_topology_store); From ed5b152913971aeac12751f313655358ca2ab6e4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:11 -0700 Subject: [PATCH 040/256] scsi: lpfc: Code cleanup for lpfc_max_scsicmpl_time parameter Code cleanup for lpfc_max_scsicmpl_time parameter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 81b1fafd4f97..3051e6628a67 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4393,12 +4393,10 @@ LPFC_VPORT_ATTR_RW(first_burst_size, 0, 0, 65536, # to limit the I/O completion time to the parameter value. # The value is set in milliseconds. */ -static int lpfc_max_scsicmpl_time; -module_param(lpfc_max_scsicmpl_time, int, S_IRUGO); -MODULE_PARM_DESC(lpfc_max_scsicmpl_time, +LPFC_VPORT_ATTR(max_scsicmpl_time, 0, 0, 60000, "Use command completion time to control queue depth"); + lpfc_vport_param_show(max_scsicmpl_time); -lpfc_vport_param_init(max_scsicmpl_time, 0, 0, 60000); static int lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val) { From 0cfbbf2f9672c07637427f24768647a7fe19bd75 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:12 -0700 Subject: [PATCH 041/256] scsi: lpfc: Code cleanup for lpfc_sriov_nr_virtfn parameter Code cleanup for lpfc_sriov_nr_virtfn parameter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 3051e6628a67..1b6090ccb803 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4007,39 +4007,10 @@ lpfc_sriov_nr_virtfn_store(struct device *dev, struct device_attribute *attr, return rc; } -static int lpfc_sriov_nr_virtfn = LPFC_DEF_VFN_PER_PFN; -module_param(lpfc_sriov_nr_virtfn, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(lpfc_sriov_nr_virtfn, "Enable PCIe device SR-IOV virtual fn"); +LPFC_ATTR(sriov_nr_virtfn, LPFC_DEF_VFN_PER_PFN, 0, LPFC_MAX_VFN_PER_PFN, + "Enable PCIe device SR-IOV virtual fn"); + lpfc_param_show(sriov_nr_virtfn) - -/** - * lpfc_sriov_nr_virtfn_init - Set the initial sr-iov virtual function enable - * @phba: lpfc_hba pointer. - * @val: link speed value. - * - * Description: - * If val is in a valid range [0,255], then set the adapter's initial - * cfg_sriov_nr_virtfn field. If it's greater than the maximum, the maximum - * number shall be used instead. It will be up to the driver's probe_one - * routine to determine whether the device's SR-IOV is supported or not. - * - * Returns: - * zero if val saved. - * -EINVAL val out of range - **/ -static int -lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val) -{ - if (val >= 0 && val <= LPFC_MAX_VFN_PER_PFN) { - phba->cfg_sriov_nr_virtfn = val; - return 0; - } - - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3017 Enabling %d virtual functions is not " - "allowed.\n", val); - return -EINVAL; -} static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR, lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store); From 6c86068dd235b61af9bfdcb8d3ec0d98ccbcf5a6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:13 -0700 Subject: [PATCH 042/256] scsi: lpfc: Revise strings with full lpfc parameter name Revise strings with full lpfc parameter name Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 1b6090ccb803..3740e5d168a2 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2877,9 +2877,9 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) vport->cfg_nodev_tmo = vport->cfg_devloss_tmo; if (val != LPFC_DEF_DEVLOSS_TMO) lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "0407 Ignoring nodev_tmo module " - "parameter because devloss_tmo is " - "set.\n"); + "0407 Ignoring lpfc_nodev_tmo module " + "parameter because lpfc_devloss_tmo " + "is set.\n"); return 0; } @@ -2938,8 +2938,8 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val) if (vport->dev_loss_tmo_changed || (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "0401 Ignoring change to nodev_tmo " - "because devloss_tmo is set.\n"); + "0401 Ignoring change to lpfc_nodev_tmo " + "because lpfc_devloss_tmo is set.\n"); return 0; } if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { @@ -2954,7 +2954,7 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val) return 0; } lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "0403 lpfc_nodev_tmo attribute cannot be set to" + "0403 lpfc_nodev_tmo attribute cannot be set to " "%d, allowed range is [%d, %d]\n", val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); return -EINVAL; @@ -3005,8 +3005,8 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val) } lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "0404 lpfc_devloss_tmo attribute cannot be set to" - " %d, allowed range is [%d, %d]\n", + "0404 lpfc_devloss_tmo attribute cannot be set to " + "%d, allowed range is [%d, %d]\n", val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); return -EINVAL; } @@ -4174,7 +4174,8 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val) } lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3016 fcp_imax: %d out of range, using default\n", val); + "3016 lpfc_fcp_imax: %d out of range, using default\n", + val); phba->cfg_fcp_imax = LPFC_DEF_IMAX; return 0; @@ -4324,8 +4325,8 @@ lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val) } lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3326 fcp_cpu_map: %d out of range, using default\n", - val); + "3326 lpfc_fcp_cpu_map: %d out of range, using " + "default\n", val); phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP; return 0; From 401304cc0d508de2e366e693fedbe52b18aef0a8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:14 -0700 Subject: [PATCH 043/256] scsi: lpfc: Fix lost target in pt-to-pt connect Fix lost target in pt-to-pt connect Change reject code to something that allows a retry Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b7d54bfb1df9..236e4e51d161 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -7610,7 +7610,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* reject till our FLOGI completes */ if ((vport->port_state < LPFC_FABRIC_CFG_LINK) && (cmd != ELS_CMD_FLOGI)) { - rjt_err = LSRJT_UNABLE_TPC; + rjt_err = LSRJT_LOGICAL_BSY; rjt_exp = LSEXP_NOTHING_MORE; goto lsrjt; } From 89533e9be08aeda5cdc4600d46c1540c7b440299 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:15 -0700 Subject: [PATCH 044/256] scsi: lpfc: Correct panics with eh_timeout and eh_deadline Correct panics with eh_timeout and eh_deadline We were having double completions on our SLI-3 version of adapters. Solved by clearing our command pointer before calling scsi_done. The eh paths potentially ran simulatenously and would see the non-null value and invoke scsi_done again. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 6 +++--- drivers/scsi/lpfc/lpfc_sli.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 4c53149ed618..1b0ef79d0821 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4142,13 +4142,13 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); - /* The sdev is not guaranteed to be valid post scsi_done upcall. */ - cmd->scsi_done(cmd); - spin_lock_irqsave(&phba->hbalock, flags); lpfc_cmd->pCmd = NULL; spin_unlock_irqrestore(&phba->hbalock, flags); + /* The sdev is not guaranteed to be valid post scsi_done upcall. */ + cmd->scsi_done(cmd); + /* * If there is a thread waiting for command completion * wake up the thread. diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index cb59f4ec46b0..27cbd6853524 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2677,15 +2677,16 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; - list_del_init(&cmd_iocb->list); if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { + /* remove from txcmpl queue list */ + list_del_init(&cmd_iocb->list); cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + return cmd_iocb; } - return cmd_iocb; } lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0317 iotag x%x is out off " + "0317 iotag x%x is out of " "range: max iotag x%x wd0 x%x\n", iotag, phba->sli.last_iotag, *(((uint32_t *) &prspiocb->iocb) + 7)); @@ -2720,8 +2721,9 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, return cmd_iocb; } } + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0372 iotag x%x is out off range: max iotag (x%x)\n", + "0372 iotag x%x is out of range: max iotag (x%x)\n", iotag, phba->sli.last_iotag); return NULL; } @@ -11808,6 +11810,8 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, /* Look up the ELS command IOCB and create pseudo response IOCB */ cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, bf_get(lpfc_wcqe_c_request_tag, wcqe)); + /* Put the iocb back on the txcmplq */ + lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq); spin_unlock_irqrestore(&pring->ring_lock, iflags); if (unlikely(!cmdiocbq)) { From c691816e00d0b4da376f005ffc06eec8a9711dcf Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:16 -0700 Subject: [PATCH 045/256] scsi: lpfc: Synchronize link speed with boot driver Synchronize link speed with boot driver Link speed settings set by the boot driver are reported by the hw. Driver will attempt to read them, and if set, will respect their values. The driver can override the settings with its own if instructed by user space (via bsg), with the new values being picked up by the boot driver. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 4 +++ drivers/scsi/lpfc/lpfc_attr.c | 7 ++++- drivers/scsi/lpfc/lpfc_bsg.c | 45 +++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_bsg.h | 10 +++++++ drivers/scsi/lpfc/lpfc_hw4.h | 3 ++ drivers/scsi/lpfc/lpfc_init.c | 54 +++++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index debba5e77d9c..8a20b4e86224 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -648,6 +648,10 @@ struct lpfc_hba { #define HBA_FCP_IOQ_FLUSH 0x8000 /* FCP I/O queues being flushed */ #define HBA_FW_DUMP_OP 0x10000 /* Skips fn reset before FW dump */ #define HBA_RECOVERABLE_UE 0x20000 /* Firmware supports recoverable UE */ +#define HBA_FORCED_LINK_SPEED 0x40000 /* + * Firmware supports Forced Link Speed + * capability + */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ struct lpfc_dmabuf slim2p; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 3740e5d168a2..c84775562c65 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3668,7 +3668,12 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, int nolip = 0; const char *val_buf = buf; int err; - uint32_t prev_val; + uint32_t prev_val, if_type; + + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + if (if_type == LPFC_SLI_INTF_IF_TYPE_2 && + phba->hba_flag & HBA_FORCED_LINK_SPEED) + return -EPERM; if (!strncmp(buf, "nolip ", strlen("nolip "))) { nolip = 1; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 05dcc2abd541..e6a5254abd4f 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -5185,6 +5185,48 @@ no_dd_data: return rc; } +static int +lpfc_forced_link_speed(struct fc_bsg_job *job) +{ + struct Scsi_Host *shost = job->shost; + struct lpfc_vport *vport = shost_priv(shost); + struct lpfc_hba *phba = vport->phba; + struct forced_link_speed_support_reply *forced_reply; + int rc = 0; + + if (job->request_len < + sizeof(struct fc_bsg_request) + + sizeof(struct get_forced_link_speed_support)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, + "0048 Received FORCED_LINK_SPEED request " + "below minimum size\n"); + rc = -EINVAL; + goto job_error; + } + + forced_reply = (struct forced_link_speed_support_reply *) + job->reply->reply_data.vendor_reply.vendor_rsp; + + if (job->reply_len < + sizeof(struct fc_bsg_request) + + sizeof(struct forced_link_speed_support_reply)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, + "0049 Received FORCED_LINK_SPEED reply below " + "minimum size\n"); + rc = -EINVAL; + goto job_error; + } + + forced_reply->supported = (phba->hba_flag & HBA_FORCED_LINK_SPEED) + ? LPFC_FORCED_LINK_SPEED_SUPPORTED + : LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED; +job_error: + job->reply->result = rc; + if (rc == 0) + job->job_done(job); + return rc; +} + /** * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job * @job: fc_bsg_job to handle @@ -5227,6 +5269,9 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) case LPFC_BSG_VENDOR_MENLO_DATA: rc = lpfc_menlo_cmd(job); break; + case LPFC_BSG_VENDOR_FORCED_LINK_SPEED: + rc = lpfc_forced_link_speed(job); + break; default: rc = -EINVAL; job->reply->reply_payload_rcv_len = 0; diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index e557bcdbcb19..f2247aa4fa17 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h @@ -35,6 +35,7 @@ #define LPFC_BSG_VENDOR_MENLO_DATA 9 #define LPFC_BSG_VENDOR_DIAG_MODE_END 10 #define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11 +#define LPFC_BSG_VENDOR_FORCED_LINK_SPEED 14 struct set_ct_event { uint32_t command; @@ -284,6 +285,15 @@ struct lpfc_sli_config_mbox { } un; }; +#define LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED 0 +#define LPFC_FORCED_LINK_SPEED_SUPPORTED 1 +struct get_forced_link_speed_support { + uint32_t command; +}; +struct forced_link_speed_support_reply { + uint8_t supported; +}; + /* driver only */ #define SLI_CONFIG_NOT_HANDLED 0 #define SLI_CONFIG_HANDLED 1 diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 0b2c3377fa0a..bbdcb5abcf56 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2290,6 +2290,9 @@ struct lpfc_mbx_read_config { #define lpfc_mbx_rd_conf_r_a_tov_SHIFT 0 #define lpfc_mbx_rd_conf_r_a_tov_MASK 0x0000FFFF #define lpfc_mbx_rd_conf_r_a_tov_WORD word6 +#define lpfc_mbx_rd_conf_link_speed_SHIFT 16 +#define lpfc_mbx_rd_conf_link_speed_MASK 0x0000FFFF +#define lpfc_mbx_rd_conf_link_speed_WORD word6 uint32_t rsvd_7; uint32_t rsvd_8; uint32_t word9; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 117c69a82786..53227e5fd2fd 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6931,6 +6931,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) struct lpfc_mbx_get_func_cfg *get_func_cfg; struct lpfc_rsrc_desc_fcfcoe *desc; char *pdesc_0; + uint16_t forced_link_speed; + uint32_t if_type; int length, i, rc = 0, rc2; pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -7024,6 +7026,58 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) if (rc) goto read_cfg_out; + /* Update link speed if forced link speed is supported */ + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { + forced_link_speed = + bf_get(lpfc_mbx_rd_conf_link_speed, rd_config); + if (forced_link_speed) { + phba->hba_flag |= HBA_FORCED_LINK_SPEED; + + switch (forced_link_speed) { + case LINK_SPEED_1G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_1G; + break; + case LINK_SPEED_2G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_2G; + break; + case LINK_SPEED_4G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_4G; + break; + case LINK_SPEED_8G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_8G; + break; + case LINK_SPEED_10G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_10G; + break; + case LINK_SPEED_16G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_16G; + break; + case LINK_SPEED_32G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_32G; + break; + case 0xffff: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_AUTO; + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "0047 Unrecognized link " + "speed : %d\n", + forced_link_speed); + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_AUTO; + } + } + } + /* Reset the DFT_HBA_Q_DEPTH to the max xri */ length = phba->sli4_hba.max_cfg_param.max_xri - lpfc_sli4_get_els_iocb_cnt(phba); From 6b6ef5db2590f0f6b99ba25fb018b60653ea66fe Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:17 -0700 Subject: [PATCH 046/256] scsi: lpfc: Fix fw download on SLI-4 FC adapters Fix fw download on SLI-4 FC adapters Driver performs a quick validation of magic numbers in the fw download image. Driver needed to be updated for more recent magic numbers. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 3 ++- drivers/scsi/lpfc/lpfc_init.c | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index bbdcb5abcf56..5646699b0516 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -3996,7 +3996,8 @@ union lpfc_wqe128 { struct gen_req64_wqe gen_req; }; -#define LPFC_GROUP_OJECT_MAGIC_NUM 0xfeaa0001 +#define LPFC_GROUP_OJECT_MAGIC_G5 0xfeaa0001 +#define LPFC_GROUP_OJECT_MAGIC_G6 0xfeaa0003 #define LPFC_FILE_TYPE_GROUP 0xf7 #define LPFC_FILE_ID_GROUP 0xa2 struct lpfc_grp_hdr { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 53227e5fd2fd..7be9b8a7bb19 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -10312,6 +10312,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context) int i, rc = 0; struct lpfc_dmabuf *dmabuf, *next; uint32_t offset = 0, temp_offset = 0; + uint32_t magic_number, ftype, fid, fsize; /* It can be null in no-wait mode, sanity check */ if (!fw) { @@ -10320,18 +10321,19 @@ lpfc_write_firmware(const struct firmware *fw, void *context) } image = (struct lpfc_grp_hdr *)fw->data; + magic_number = be32_to_cpu(image->magic_number); + ftype = bf_get_be32(lpfc_grp_hdr_file_type, image); + fid = bf_get_be32(lpfc_grp_hdr_id, image), + fsize = be32_to_cpu(image->size); + INIT_LIST_HEAD(&dma_buffer_list); - if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) || - (bf_get_be32(lpfc_grp_hdr_file_type, image) != - LPFC_FILE_TYPE_GROUP) || - (bf_get_be32(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) || - (be32_to_cpu(image->size) != fw->size)) { + if ((magic_number != LPFC_GROUP_OJECT_MAGIC_G5 && + magic_number != LPFC_GROUP_OJECT_MAGIC_G6) || + ftype != LPFC_FILE_TYPE_GROUP || fsize != fw->size) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3022 Invalid FW image found. " - "Magic:%x Type:%x ID:%x\n", - be32_to_cpu(image->magic_number), - bf_get_be32(lpfc_grp_hdr_file_type, image), - bf_get_be32(lpfc_grp_hdr_id, image)); + "Magic:%x Type:%x ID:%x Size %d %ld\n", + magic_number, ftype, fid, fsize, fw->size); rc = -EINVAL; goto release_out; } From c74f95d63044a0767994a21f4f5351134752f922 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 13 Oct 2016 15:06:18 -0700 Subject: [PATCH 047/256] scsi: lpfc: lpfc version changed to 11.2.0.2 lpfc version changed to 11.2.0.2 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c9bf20eb7223..50bfc43ebcb0 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "11.2.0.0." +#define LPFC_DRIVER_VERSION "11.2.0.2" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ From f8f91f3f3120b2168189100c588aeaf2ff5e9ac4 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Fri, 14 Oct 2016 16:37:29 -0400 Subject: [PATCH 048/256] scsi: libfc: Revert "[SCSI] libfc: use offload EM instance again instead jumping to next EM" This reverts commit 3e22760d4db6fd89e0be46c3d132390a251da9c6. This revert came about because of efforts by Ewan Milne, Curtis Taylor and I. In researching this issue, significant performance issues were seen on large CPU count systems using the software FCOE stack. Hannes also weighed in. The same was not apparent on much smaller low count CPU systems. The behavior introduced by commit 3e22760d4db6fd89e0be46c3d132390a251da9c6 lands sup with large count CPU systems seeing continual blk_requeue_request() calls due to ML_QUEUE_HOST_BUSY. fc_exch_alloc() used to try all the available exchange managers in the list for an available exchange id, but this was changed in 2010 so that if the first matched exchange manager couldn't allocate one, it fails and we end up returning host busy. This was due to commit: Setting the ddp_min module parameter to fcoe to 128MB prevents the ->match function from permitting the use of the offload exchange manager for the frame, and we no longer see the problem with host busy status, since it uses the larger non-offloaded pool. Reverting commit 3e22760d4db6fd89e0be46c3d132390a251da9c6 was tested to also prevent the host busy issue due to failing allocations. Suggested-by: Ewan Milne Suggested-by: Curtis Taylor Tested-by: Laurence Oberman Signed-off-by: Laurence Oberman --- drivers/scsi/libfc/fc_exch.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 16ca31ad5ec0..dd95e2aece66 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -888,14 +888,19 @@ err: * EM is selected when a NULL match function pointer is encountered * or when a call to a match function returns true. */ -static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport, - struct fc_frame *fp) +static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, + struct fc_frame *fp) { struct fc_exch_mgr_anchor *ema; + struct fc_exch *ep; - list_for_each_entry(ema, &lport->ema_list, ema_list) - if (!ema->match || ema->match(fp)) - return fc_exch_em_alloc(lport, ema->mp); + list_for_each_entry(ema, &lport->ema_list, ema_list) { + if (!ema->match || ema->match(fp)) { + ep = fc_exch_em_alloc(lport, ema->mp); + if (ep) + return ep; + } + } return NULL; } From 57d3ec7e468bb6659d9a461294d8747906fb7231 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:37 +0200 Subject: [PATCH 049/256] scsi: libfc: additional debugging messages Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 59 ++++++++++++++++++++++++++++------- drivers/scsi/libfc/fc_fcp.c | 41 +++++++++++++++++++----- drivers/scsi/libfc/fc_rport.c | 25 ++++++++++++--- 3 files changed, 101 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index dd95e2aece66..91800cb776ec 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -362,8 +362,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep, fc_exch_hold(ep); /* hold for timer */ if (!queue_delayed_work(fc_exch_workqueue, &ep->timeout_work, - msecs_to_jiffies(timer_msec))) + msecs_to_jiffies(timer_msec))) { + FC_EXCH_DBG(ep, "Exchange already queued\n"); fc_exch_release(ep); + } } /** @@ -632,9 +634,13 @@ static int fc_exch_abort_locked(struct fc_exch *ep, struct fc_frame *fp; int error; + FC_EXCH_DBG(ep, "exch: abort, time %d msecs\n", timer_msec); if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) || - ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) + ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) { + FC_EXCH_DBG(ep, "exch: already completed esb %x state %x\n", + ep->esb_stat, ep->state); return -ENXIO; + } /* * Send the abort on a new sequence if possible. @@ -758,7 +764,7 @@ static void fc_exch_timeout(struct work_struct *work) u32 e_stat; int rc = 1; - FC_EXCH_DBG(ep, "Exchange timed out\n"); + FC_EXCH_DBG(ep, "Exchange timed out state %x\n", ep->state); spin_lock_bh(&ep->ex_lock); if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) @@ -1263,8 +1269,10 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) */ if (fc_sof_needs_ack(fr_sof(rx_fp))) { fp = fc_frame_alloc(lport, 0); - if (!fp) + if (!fp) { + FC_EXCH_DBG(ep, "Drop ACK request, out of memory\n"); return; + } fh = fc_frame_header_get(fp); fh->fh_r_ctl = FC_RCTL_ACK_1; @@ -1317,13 +1325,18 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, struct fc_frame_header *rx_fh; struct fc_frame_header *fh; struct fc_ba_rjt *rp; + struct fc_seq *sp; struct fc_lport *lport; unsigned int f_ctl; lport = fr_dev(rx_fp); + sp = fr_seq(rx_fp); fp = fc_frame_alloc(lport, sizeof(*rp)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(fc_seq_exch(sp), + "Drop BA_RJT request, out of memory\n"); return; + } fh = fc_frame_header_get(fp); rx_fh = fc_frame_header_get(rx_fp); @@ -1388,14 +1401,17 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) if (!ep) goto reject; + FC_EXCH_DBG(ep, "exch: ABTS received\n"); fp = fc_frame_alloc(ep->lp, sizeof(*ap)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(ep, "Drop ABTS request, out of memory\n"); goto free; + } spin_lock_bh(&ep->ex_lock); if (ep->esb_stat & ESB_ST_COMPLETE) { spin_unlock_bh(&ep->ex_lock); - + FC_EXCH_DBG(ep, "exch: ABTS rejected, exchange complete\n"); fc_frame_free(fp); goto reject; } @@ -1789,11 +1805,16 @@ static void fc_seq_ls_acc(struct fc_frame *rx_fp) struct fc_lport *lport; struct fc_els_ls_acc *acc; struct fc_frame *fp; + struct fc_seq *sp; lport = fr_dev(rx_fp); + sp = fr_seq(rx_fp); fp = fc_frame_alloc(lport, sizeof(*acc)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(fc_seq_exch(sp), + "exch: drop LS_ACC, out of memory\n"); return; + } acc = fc_frame_payload_get(fp, sizeof(*acc)); memset(acc, 0, sizeof(*acc)); acc->la_cmd = ELS_LS_ACC; @@ -1816,11 +1837,16 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason, struct fc_lport *lport; struct fc_els_ls_rjt *rjt; struct fc_frame *fp; + struct fc_seq *sp; lport = fr_dev(rx_fp); + sp = fr_seq(rx_fp); fp = fc_frame_alloc(lport, sizeof(*rjt)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(fc_seq_exch(sp), + "exch: drop LS_ACC, out of memory\n"); return; + } rjt = fc_frame_payload_get(fp, sizeof(*rjt)); memset(rjt, 0, sizeof(*rjt)); rjt->er_cmd = ELS_LS_RJT; @@ -1980,15 +2006,23 @@ static void fc_exch_els_rec(struct fc_frame *rfp) ep = fc_exch_lookup(lport, sid == fc_host_port_id(lport->host) ? oxid : rxid); explan = ELS_EXPL_OXID_RXID; - if (!ep) + if (!ep) { + FC_LPORT_DBG(lport, + "REC request from %x: rxid %x oxid %x not found\n", + sid, rxid, oxid); goto reject; + } + FC_EXCH_DBG(ep, "REC request from %x: rxid %x oxid %x\n", + sid, rxid, oxid); if (ep->oid != sid || oxid != ep->oxid) goto rel; if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid) goto rel; fp = fc_frame_alloc(lport, sizeof(*acc)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(ep, "Drop REC request, out of memory\n"); goto out; + } acc = fc_frame_payload_get(fp, sizeof(*acc)); memset(acc, 0, sizeof(*acc)); @@ -2181,6 +2215,7 @@ static void fc_exch_rrq(struct fc_exch *ep) return; retry: + FC_EXCH_DBG(ep, "exch: RRQ send failed\n"); spin_lock_bh(&ep->ex_lock); if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) { spin_unlock_bh(&ep->ex_lock); @@ -2223,6 +2258,8 @@ static void fc_exch_els_rrq(struct fc_frame *fp) if (!ep) goto reject; spin_lock_bh(&ep->ex_lock); + FC_EXCH_DBG(ep, "RRQ request from %x: xid %x rxid %x oxid %x\n", + sid, xid, ntohs(rp->rrq_rx_id), ntohs(rp->rrq_ox_id)); if (ep->oxid != ntohs(rp->rrq_ox_id)) goto unlock_reject; if (ep->rxid != ntohs(rp->rrq_rx_id) && diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5121272f28fd..5c6c73a80379 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -764,8 +764,11 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) fh = fc_frame_header_get(fp); r_ctl = fh->fh_r_ctl; - if (lport->state != LPORT_ST_READY) + if (lport->state != LPORT_ST_READY) { + FC_FCP_DBG(fsp, "lport state %d, ignoring r_ctl %x\n", + lport->state, r_ctl); goto out; + } if (fc_fcp_lock_pkt(fsp)) goto out; @@ -774,8 +777,10 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) goto unlock; } - if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) + if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) { + FC_FCP_DBG(fsp, "command aborted, ignoring r_ctl %x\n", r_ctl); goto unlock; + } if (r_ctl == FC_RCTL_DD_DATA_DESC) { /* @@ -910,6 +915,10 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Wait a at least one jiffy to see if it is delivered. * If this expires without data, we may do SRR. */ + FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun " + "len %x, data len %x\n", + fsp->rport->port_id, + fsp->xfer_len, expected_len, fsp->data_len); fc_fcp_timer_set(fsp, 2); return; } @@ -959,8 +968,11 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) if (fsp->cdb_status == SAM_STAT_GOOD && fsp->xfer_len < fsp->data_len && !fsp->io_status && (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || - fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) + fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { + FC_FCP_DBG(fsp, "data underrun, xfer %zx data %x\n", + fsp->xfer_len, fsp->data_len); fsp->status_code = FC_DATA_UNDRUN; + } } seq = fsp->seq_ptr; @@ -1222,8 +1234,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) int rc = FAILED; unsigned long ticks_left; - if (fc_fcp_send_abort(fsp)) + FC_FCP_DBG(fsp, "pkt abort state %x\n", fsp->state); + if (fc_fcp_send_abort(fsp)) { + FC_FCP_DBG(fsp, "failed to send abort\n"); return FAILED; + } init_completion(&fsp->tm_done); fsp->wait_for_comp = 1; @@ -1394,6 +1409,8 @@ static void fc_fcp_timeout(unsigned long data) if (fsp->cdb_cmd.fc_tm_flags) goto unlock; + FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n", + rpriv->flags, fsp->state); fsp->state |= FC_SRB_FCP_PROCESSING_TMO; if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) @@ -1486,8 +1503,8 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) rjt = fc_frame_payload_get(fp, sizeof(*rjt)); switch (rjt->er_reason) { default: - FC_FCP_DBG(fsp, "device %x unexpected REC reject " - "reason %d expl %d\n", + FC_FCP_DBG(fsp, + "device %x invalid REC reject %d/%d\n", fsp->rport->port_id, rjt->er_reason, rjt->er_explan); /* fall through */ @@ -1503,6 +1520,9 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) break; case ELS_RJT_LOGIC: case ELS_RJT_UNAB: + FC_FCP_DBG(fsp, "device %x REC reject %d/%d\n", + fsp->rport->port_id, rjt->er_reason, + rjt->er_explan); /* * If no data transfer, the command frame got dropped * so we just retry. If data was transferred, we @@ -1608,6 +1628,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) switch (error) { case -FC_EX_CLOSED: + FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n", + fsp, fsp->rport->port_id); fc_fcp_retry_cmd(fsp); break; @@ -1622,8 +1644,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Assume REC or LS_ACC was lost. * The exchange manager will have aborted REC, so retry. */ - FC_FCP_DBG(fsp, "REC fid %6.6x error error %d retry %d/%d\n", - fsp->rport->port_id, error, fsp->recov_retry, + FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange timeout retry %d/%d\n", + fsp, fsp->rport->port_id, fsp->recov_retry, FC_MAX_RECOV_RETRY); if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); @@ -1642,6 +1664,7 @@ out: */ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code) { + FC_FCP_DBG(fsp, "start recovery code %x\n", code); fsp->status_code = code; fsp->cdb_status = 0; fsp->io_status = 0; @@ -1768,12 +1791,14 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) goto out; switch (PTR_ERR(fp)) { case -FC_EX_TIMEOUT: + FC_FCP_DBG(fsp, "SRR timeout, retries %d\n", fsp->recov_retry); if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else fc_fcp_recovery(fsp, FC_TIMED_OUT); break; case -FC_EX_CLOSED: /* e.g., link failure */ + FC_FCP_DBG(fsp, "SRR error, exchange closed\n"); /* fall through */ default: fc_fcp_retry_cmd(fsp); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4b9bb6dd4004..bcd1cd3c5285 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -287,8 +287,10 @@ static void fc_rport_work(struct work_struct *work) kref_get(&rdata->kref); mutex_unlock(&rdata->rp_mutex); - if (!rport) + if (!rport) { + FC_RPORT_DBG(rdata, "No rport!\n"); rport = fc_remote_port_add(lport->host, 0, &ids); + } if (!rport) { FC_RPORT_DBG(rdata, "Failed to add the rport\n"); lport->tt.rport_logoff(rdata); @@ -389,8 +391,10 @@ static void fc_rport_work(struct work_struct *work) * Re-open for events. Reissue READY event if ready. */ rdata->event = RPORT_EV_NONE; - if (rdata->rp_state == RPORT_ST_READY) + if (rdata->rp_state == RPORT_ST_READY) { + FC_RPORT_DBG(rdata, "work reopen\n"); fc_rport_enter_ready(rdata); + } mutex_unlock(&rdata->rp_mutex); } break; @@ -568,6 +572,7 @@ static void fc_rport_timeout(struct work_struct *work) struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); + FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata)); switch (rdata->rp_state) { case RPORT_ST_FLOGI: @@ -1095,6 +1100,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_els_spp spp; } *pp; struct fc_els_spp temp_spp; + struct fc_els_ls_rjt *rjt; struct fc4_prov *prov; u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 fcp_parm = 0; @@ -1167,8 +1173,10 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, fc_rport_enter_rtv(rdata); } else { - FC_RPORT_DBG(rdata, "Bad ELS response for PRLI command\n"); - fc_rport_error_retry(rdata, fp); + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n", + rjt->er_reason, rjt->er_explan); + fc_rport_error_retry(rdata, NULL); } out: @@ -1602,8 +1610,12 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) struct fc_seq_els_data els_data; rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); - if (!rdata) + if (!rdata) { + FC_RPORT_ID_DBG(lport, fc_frame_sid(fp), + "Received ELS 0x%02x from non-logged-in port\n", + fc_frame_payload_op(fp)); goto reject; + } mutex_lock(&rdata->rp_mutex); @@ -1614,6 +1626,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) case RPORT_ST_ADISC: break; default: + FC_RPORT_DBG(rdata, + "Reject ELS 0x%02x while in state %s\n", + fc_frame_payload_op(fp), fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); goto reject; From a0452bb45c6bcf523acff635325fee7dd961c6bd Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:38 +0200 Subject: [PATCH 050/256] scsi: libfc: spurious I/O error under high load If a command times out libfc is sending an REC, which also might fail (due to frames being lost or something). If no data has been transferred we can simply retry the command, but the current code sets a state of FC_ERROR, which then is being translated into DID_ERROR, resulting in an I/O error. So to handle this properly we need to set a separate state FC_TRANS_RESET and mapping it onto DID_SOFT_RETRY. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5c6c73a80379..9f9eb7b0ba2d 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -122,6 +122,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); #define FC_HRD_ERROR 9 #define FC_CRC_ERROR 10 #define FC_TIMED_OUT 11 +#define FC_TRANS_RESET 12 /* * Error recovery timeout values. @@ -283,7 +284,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) * fc_io_compl() will notify the SCSI-ml that the I/O is done. * The SCSI-ml will retry the command. */ -static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) +static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code) { if (fsp->seq_ptr) { fsp->lp->tt.exch_done(fsp->seq_ptr); @@ -292,7 +293,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) fsp->state &= ~FC_SRB_ABORT_PENDING; fsp->io_status = 0; - fsp->status_code = FC_ERROR; + fsp->status_code = status_code; fc_fcp_complete_locked(fsp); } @@ -1208,7 +1209,7 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) return; if (error == -FC_EX_CLOSED) { - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_ERROR); goto unlock; } @@ -1531,10 +1532,11 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) */ if (rjt->er_explan == ELS_EXPL_OXID_RXID && fsp->xfer_len == 0) { - fc_fcp_retry_cmd(fsp); + fsp->state |= FC_SRB_ABORTED; + fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); break; } - fc_fcp_recovery(fsp, FC_ERROR); + fc_fcp_recovery(fsp, FC_TRANS_RESET); break; } } else if (opcode == ELS_LS_ACC) { @@ -1630,7 +1632,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) case -FC_EX_CLOSED: FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n", fsp, fsp->rport->port_id); - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_ERROR); break; default: @@ -1729,7 +1731,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) fc_fcp_pkt_hold(fsp); /* hold for outstanding SRR */ return; retry: - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); } /** @@ -1801,7 +1803,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) FC_FCP_DBG(fsp, "SRR error, exchange closed\n"); /* fall through */ default: - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_ERROR); break; } fc_fcp_unlock_pkt(fsp); @@ -2014,6 +2016,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) "due to FC_CMD_RESET\n"); sc_cmd->result = (DID_RESET << 16); break; + case FC_TRANS_RESET: + FC_FCP_DBG(fsp, "Returning DID_SOFT_ERROR to scsi-ml " + "due to FC_TRANS_RESET\n"); + sc_cmd->result = (DID_SOFT_ERROR << 16); + break; case FC_HRD_ERROR: FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml " "due to FC_HRD_ERROR\n"); From f7ce413ceac01d502ea4a27c0ba542b57b728e5c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:39 +0200 Subject: [PATCH 051/256] scsi: libfc: use configured lport R_A_TOV We should be using the configured R_A_TOV value when sending the exchange. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 91800cb776ec..99cc5a941997 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2140,7 +2140,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, ep->resp = resp; ep->destructor = destructor; ep->arg = arg; - ep->r_a_tov = FC_DEF_R_A_TOV; + ep->r_a_tov = lport->r_a_tov; ep->lp = lport; sp = &ep->seq; From a50cc9eccce6ae9708e8a713c4070dc2efd1b3d5 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:40 +0200 Subject: [PATCH 052/256] scsi: libfc: use configured rport E_D_TOV If fc_rport_error_retry() is attempting to retry the remote port state we should be waiting for the configured e_d_tov value rather than the default. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index bcd1cd3c5285..bb7e9d9a3179 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -662,7 +662,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) static void fc_rport_error_retry(struct fc_rport_priv *rdata, struct fc_frame *fp) { - unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV); + unsigned long delay = msecs_to_jiffies(rdata->e_d_tov); struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ From 76e72ad117812bb79abf647ac40ca6df1740b729 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:41 +0200 Subject: [PATCH 053/256] scsi: libfc: sanitize E_D_TOV and R_A_TOV setting When setting the FCP timeout we need to ensure a lower boundary for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O issues due to the fcp timer firing too early. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 9 +++++---- drivers/scsi/libfc/fc_lport.c | 8 +++++--- drivers/scsi/libfc/fc_rport.c | 6 ++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 9f9eb7b0ba2d..10faca2686ba 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1137,8 +1137,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) { struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; + unsigned int e_d_tov = FC_DEF_E_D_TOV; - return msecs_to_jiffies(rpriv->e_d_tov) + HZ; + if (rpriv && rpriv->e_d_tov > e_d_tov) + e_d_tov = rpriv->e_d_tov; + return msecs_to_jiffies(e_d_tov) + HZ; } /** @@ -1693,7 +1696,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) struct fc_seq *seq; struct fcp_srr *srr; struct fc_frame *fp; - unsigned int rec_tov; rport = fsp->rport; rpriv = rport->dd_data; @@ -1717,10 +1719,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); - rec_tov = get_fsp_rec_tov(fsp); seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, fc_fcp_pkt_destroy, - fsp, jiffies_to_msecs(rec_tov)); + fsp, get_fsp_rec_tov(fsp)); if (!seq) goto retry; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 4e11c90c783c..81ad8ac5a33d 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1777,7 +1777,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, if ((csp_flags & FC_SP_FT_FPORT) == 0) { if (e_d_tov > lport->e_d_tov) lport->e_d_tov = e_d_tov; - lport->r_a_tov = 2 * e_d_tov; + lport->r_a_tov = 2 * lport->e_d_tov; fc_lport_set_port_id(lport, did, fp); printk(KERN_INFO "host%d: libfc: " "Port (%6.6x) entered " @@ -1789,8 +1789,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, get_unaligned_be64( &flp->fl_wwnn)); } else { - lport->e_d_tov = e_d_tov; - lport->r_a_tov = r_a_tov; + if (e_d_tov > lport->e_d_tov) + lport->e_d_tov = e_d_tov; + if (r_a_tov > lport->r_a_tov) + lport->r_a_tov = r_a_tov; fc_host_fabric_name(lport->host) = get_unaligned_be64(&flp->fl_wwnn); fc_lport_set_port_id(lport, did, fp); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index bb7e9d9a3179..3d2baba4103e 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1296,13 +1296,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, tov = ntohl(rtv->rtv_r_a_tov); if (tov == 0) tov = 1; - rdata->r_a_tov = tov; + if (tov > rdata->r_a_tov) + rdata->r_a_tov = tov; tov = ntohl(rtv->rtv_e_d_tov); if (toq & FC_ELS_RTV_EDRES) tov /= 1000000; if (tov == 0) tov = 1; - rdata->e_d_tov = tov; + if (tov > rdata->e_d_tov) + rdata->e_d_tov = tov; } } From 69aabccede61f86b828928084dc8df288ecb2d83 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:42 +0200 Subject: [PATCH 054/256] scsi: fcoe: make R_A_TOV and E_D_TOV configurable The user might want to modify the values for R_A_TOV and E_D_TOV, so add new module parameters 'e_d_tov' and 'r_a_tov' for the 'fcoe' modules and allow to modify them via sysfs attributes. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 12 +++++- drivers/scsi/fcoe/fcoe_sysfs.c | 71 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 9bd41a35a78a..c907661a2ec3 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -63,6 +63,14 @@ unsigned int fcoe_debug_logging; module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); +unsigned int fcoe_e_d_tov = 2 * 1000; +module_param_named(e_d_tov, fcoe_e_d_tov, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(e_d_tov, "E_D_TOV in ms, default 2000"); + +unsigned int fcoe_r_a_tov = 2 * 2 * 1000; +module_param_named(r_a_tov, fcoe_r_a_tov, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(r_a_tov, "R_A_TOV in ms, default 4000"); + static DEFINE_MUTEX(fcoe_config_mutex); static struct workqueue_struct *fcoe_wq; @@ -633,8 +641,8 @@ static int fcoe_lport_config(struct fc_lport *lport) lport->qfull = 0; lport->max_retry_count = 3; lport->max_rport_retry_count = 3; - lport->e_d_tov = 2 * 1000; /* FC-FS default */ - lport->r_a_tov = 2 * 2 * 1000; + lport->e_d_tov = fcoe_e_d_tov; + lport->r_a_tov = fcoe_r_a_tov; lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); lport->does_npiv = 1; diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c index 0675fd128734..9e6baac18e76 100644 --- a/drivers/scsi/fcoe/fcoe_sysfs.c +++ b/drivers/scsi/fcoe/fcoe_sysfs.c @@ -423,6 +423,75 @@ static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR, show_ctlr_fip_resp, store_ctlr_fip_resp); +static ssize_t +fcoe_ctlr_var_store(u32 *var, const char *buf, size_t count) +{ + int err; + unsigned long v; + + err = kstrtoul(buf, 10, &v); + if (err || v > UINT_MAX) + return -EINVAL; + + *var = v; + + return count; +} + +static ssize_t store_ctlr_r_a_tov(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev); + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); + + if (ctlr_dev->enabled == FCOE_CTLR_ENABLED) + return -EBUSY; + if (ctlr_dev->enabled == FCOE_CTLR_DISABLED) + return fcoe_ctlr_var_store(&ctlr->lp->r_a_tov, buf, count); + return -ENOTSUPP; +} + +static ssize_t show_ctlr_r_a_tov(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev); + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); + + return sprintf(buf, "%d\n", ctlr->lp->r_a_tov); +} + +static FCOE_DEVICE_ATTR(ctlr, r_a_tov, S_IRUGO | S_IWUSR, + show_ctlr_r_a_tov, store_ctlr_r_a_tov); + +static ssize_t store_ctlr_e_d_tov(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev); + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); + + if (ctlr_dev->enabled == FCOE_CTLR_ENABLED) + return -EBUSY; + if (ctlr_dev->enabled == FCOE_CTLR_DISABLED) + return fcoe_ctlr_var_store(&ctlr->lp->e_d_tov, buf, count); + return -ENOTSUPP; +} + +static ssize_t show_ctlr_e_d_tov(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev); + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); + + return sprintf(buf, "%d\n", ctlr->lp->e_d_tov); +} + +static FCOE_DEVICE_ATTR(ctlr, e_d_tov, S_IRUGO | S_IWUSR, + show_ctlr_e_d_tov, store_ctlr_e_d_tov); + static ssize_t store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr, @@ -507,6 +576,8 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = { static struct attribute *fcoe_ctlr_attrs[] = { &device_attr_fcoe_ctlr_fip_vlan_responder.attr, &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, + &device_attr_fcoe_ctlr_r_a_tov.attr, + &device_attr_fcoe_ctlr_e_d_tov.attr, &device_attr_fcoe_ctlr_enabled.attr, &device_attr_fcoe_ctlr_mode.attr, NULL, From 0f4c16a2f41400dba12e5039429e780aa938aa0c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:43 +0200 Subject: [PATCH 055/256] scsi: libfc: do not overwrite DID_TIME_OUT status When a command is aborted it might already have the DID_TIME_OUT status set, so we shouldn't be overwriting that. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 10faca2686ba..0e2a2016af71 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2008,9 +2008,15 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status; break; case FC_CMD_ABORTED: - FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " - "due to FC_CMD_ABORTED\n"); - sc_cmd->result = (DID_ERROR << 16) | fsp->io_status; + if (host_byte(sc_cmd->result) == DID_TIME_OUT) + FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml " + "due to FC_CMD_ABORTED\n"); + else { + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " + "due to FC_CMD_ABORTED\n"); + set_host_byte(sc_cmd, DID_ERROR); + } + sc_cmd->result |= fsp->io_status; break; case FC_CMD_RESET: FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml " From 9f9504a7cdee39e167f0421346ff17568a5f29a0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:44 +0200 Subject: [PATCH 056/256] scsi: libfc: use error code for fc_rport_error() We only ever use the 'fp' argument for fc_rport_error() to encapsulate the error code, so we can as well do away with that and pass the error directly. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 101 ++++++++++++++++++++-------------- include/scsi/libfc.h | 5 ++ 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 3d2baba4103e..d2d8607ff6a0 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -87,8 +87,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *); static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *); static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *); static void fc_rport_timeout(struct work_struct *); -static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *); -static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *); +static void fc_rport_error(struct fc_rport_priv *, int); +static void fc_rport_error_retry(struct fc_rport_priv *, int); static void fc_rport_work(struct work_struct *); static const char *fc_rport_state_names[] = { @@ -604,20 +604,19 @@ static void fc_rport_timeout(struct work_struct *work) /** * fc_rport_error() - Error handler, called once retries have been exhausted * @rdata: The remote port the error is happened on - * @fp: The error code encapsulated in a frame pointer + * @err: The error code * * Locking Note: The rport lock is expected to be held before * calling this routine * * Reference counting: does not modify kref */ -static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) +static void fc_rport_error(struct fc_rport_priv *rdata, int err) { struct fc_lport *lport = rdata->local_port; - FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n", - IS_ERR(fp) ? -PTR_ERR(fp) : 0, - fc_rport_state(rdata), rdata->retries); + FC_RPORT_DBG(rdata, "Error %d in state %s, retries %d\n", + -err, fc_rport_state(rdata), rdata->retries); switch (rdata->rp_state) { case RPORT_ST_FLOGI: @@ -649,7 +648,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) /** * fc_rport_error_retry() - Handler for remote port state retries * @rdata: The remote port whose state is to be retried - * @fp: The error code encapsulated in a frame pointer + * @err: The error code * * If the error was an exchange timeout retry immediately, * otherwise wait for E_D_TOV. @@ -659,22 +658,21 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) * * Reference counting: increments kref when scheduling retry_work */ -static void fc_rport_error_retry(struct fc_rport_priv *rdata, - struct fc_frame *fp) +static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err) { unsigned long delay = msecs_to_jiffies(rdata->e_d_tov); struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ - if (PTR_ERR(fp) == -FC_EX_CLOSED) + if (err == -FC_EX_CLOSED) goto out; if (rdata->retries < rdata->local_port->max_rport_retry_count) { - FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n", - PTR_ERR(fp), fc_rport_state(rdata)); + FC_RPORT_DBG(rdata, "Error %d in state %s, retrying\n", + err, fc_rport_state(rdata)); rdata->retries++; /* no additional delay on exchange timeouts */ - if (PTR_ERR(fp) == -FC_EX_TIMEOUT) + if (err == -FC_EX_TIMEOUT) delay = 0; kref_get(&rdata->kref); if (!schedule_delayed_work(&rdata->retry_work, delay)) @@ -683,7 +681,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, } out: - fc_rport_error(rdata, fp); + fc_rport_error(rdata, err); } /** @@ -743,8 +741,11 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_lport *lport = rdata->local_port; struct fc_els_flogi *flogi; unsigned int r_a_tov; + u8 opcode; + int err = 0; - FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp)); + FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", + IS_ERR(fp) ? "error" : fc_els_resp_type(fp)); if (fp == ERR_PTR(-FC_EX_CLOSED)) goto put; @@ -760,18 +761,32 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rdata, fp); + fc_rport_error(rdata, PTR_ERR(fp)); goto err; } + opcode = fc_frame_payload_op(fp); + if (opcode == ELS_LS_RJT) { + struct fc_els_ls_rjt *rjt; - if (fc_frame_payload_op(fp) != ELS_LS_ACC) + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + FC_RPORT_DBG(rdata, "FLOGI ELS rejected, reason %x expl %x\n", + rjt->er_reason, rjt->er_explan); + err = -FC_EX_ELS_RJT; goto bad; - if (fc_rport_login_complete(rdata, fp)) + } else if (opcode != ELS_LS_ACC) { + FC_RPORT_DBG(rdata, "FLOGI ELS invalid opcode %x\n", opcode); + err = -FC_EX_ELS_RJT; goto bad; + } + if (fc_rport_login_complete(rdata, fp)) { + FC_RPORT_DBG(rdata, "FLOGI failed, no login\n"); + err = -FC_EX_INV_LOGIN; + goto bad; + } flogi = fc_frame_payload_get(fp, sizeof(*flogi)); if (!flogi) { - FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); + err = -FC_EX_ALLOC_ERR; goto bad; } r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov); @@ -790,7 +805,8 @@ put: kref_put(&rdata->kref, lport->tt.rport_destroy); return; bad: - fc_rport_error_retry(rdata, fp); + FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); + fc_rport_error_retry(rdata, err); goto out; } @@ -818,13 +834,13 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) - return fc_rport_error_retry(rdata, fp); + return fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI, fc_rport_flogi_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -991,7 +1007,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, PTR_ERR(fp)); goto err; } @@ -1013,9 +1029,14 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, rdata->max_seq = csp_seq; rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs); fc_rport_enter_prli(rdata); - } else - fc_rport_error_retry(rdata, fp); + } else { + struct fc_els_ls_rjt *rjt; + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + FC_RPORT_DBG(rdata, "PLOGI ELS rejected, reason %x expl %x\n", + rjt->er_reason, rjt->er_explan); + fc_rport_error_retry(rdata, -FC_EX_ELS_RJT); + } out: fc_frame_free(fp); err: @@ -1067,7 +1088,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { FC_RPORT_DBG(rdata, "%s frame alloc failed\n", __func__); - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } rdata->e_d_tov = lport->e_d_tov; @@ -1076,7 +1097,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, fc_rport_plogi_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -1123,7 +1144,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, PTR_ERR(fp)); goto err; } @@ -1142,9 +1163,9 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, rdata->spp_type = pp->spp.spp_type; if (resp_code != FC_SPP_RESP_ACK) { if (resp_code == FC_SPP_RESP_CONF) - fc_rport_error(rdata, fp); + fc_rport_error(rdata, -FC_EX_SEQ_ERR); else - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR); goto out; } if (pp->prli.prli_spp_len < sizeof(pp->spp)) @@ -1176,7 +1197,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, rjt = fc_frame_payload_get(fp, sizeof(*rjt)); FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n", rjt->er_reason, rjt->er_explan); - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, FC_EX_ELS_RJT); } out: @@ -1222,7 +1243,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(*pp)); if (!fp) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } @@ -1241,7 +1262,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) kref_get(&rdata->kref); if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, NULL, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -1280,7 +1301,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rdata, fp); + fc_rport_error(rdata, PTR_ERR(fp)); goto err; } @@ -1339,7 +1360,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv)); if (!fp) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } @@ -1347,7 +1368,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, fc_rport_rtv_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -1430,7 +1451,7 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rdata, fp); + fc_rport_error(rdata, PTR_ERR(fp)); goto err; } @@ -1480,14 +1501,14 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_adisc)); if (!fp) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, fc_rport_adisc_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 7428a53257ca..dc42d8070f6f 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -44,6 +44,11 @@ #define FC_NO_ERR 0 /* no error */ #define FC_EX_TIMEOUT 1 /* Exchange timeout */ #define FC_EX_CLOSED 2 /* Exchange closed */ +#define FC_EX_ALLOC_ERR 3 /* Exchange allocation failed */ +#define FC_EX_XMIT_ERR 4 /* Exchange transmit failed */ +#define FC_EX_ELS_RJT 5 /* ELS rejected */ +#define FC_EX_INV_LOGIN 6 /* Login not completed */ +#define FC_EX_SEQ_ERR 6 /* Exchange sequence error */ /** * enum fc_lport_state - Local port states From 7c5a51b8f82fcfba1925fa64f08413c8258590d2 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:45 +0200 Subject: [PATCH 057/256] scsi: libfc: Implement RTV responder The libfc stack generates an RTV request, so we should be implementing an RTV responder, too. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 41 ++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index d2d8607ff6a0..426c39989952 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1268,7 +1268,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) } /** - * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses + * fc_rport_rtv_resp() - Handler for Request Timeout Value (RTV) responses * @sp: The sequence the RTV was on * @fp: The RTV response frame * @rdata_arg: The remote port that sent the RTV response @@ -1373,6 +1373,41 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) } } +/** + * fc_rport_recv_rtv_req() - Handler for Read Timeout Value (RTV) requests + * @rdata: The remote port that sent the RTV request + * @in_fp: The RTV request frame + * + * Locking Note: Called with the lport and rport locks held. + */ +static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata, + struct fc_frame *in_fp) +{ + struct fc_lport *lport = rdata->local_port; + struct fc_frame *fp; + struct fc_els_rtv_acc *rtv; + struct fc_seq_els_data rjt_data; + + FC_RPORT_DBG(rdata, "Received RTV request\n"); + + fp = fc_frame_alloc(lport, sizeof(*rtv)); + if (!fp) { + rjt_data.reason = ELS_RJT_UNAB; + rjt_data.reason = ELS_EXPL_INSUF_RES; + lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + goto drop; + } + rtv = fc_frame_payload_get(fp, sizeof(*rtv)); + rtv->rtv_cmd = ELS_LS_ACC; + rtv->rtv_r_a_tov = htonl(lport->r_a_tov); + rtv->rtv_e_d_tov = htonl(lport->e_d_tov); + rtv->rtv_toq = 0; + fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); +drop: + fc_frame_free(in_fp); +} + /** * fc_rport_logo_resp() - Handler for logout (LOGO) responses * @sp: The sequence the LOGO was on @@ -1678,6 +1713,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) case ELS_RLS: fc_rport_recv_rls_req(rdata, fp); break; + case ELS_RTV: + fc_rport_recv_rtv_req(rdata, fp); + break; default: fc_frame_free(fp); /* can't happen */ break; @@ -1729,6 +1767,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) case ELS_RRQ: case ELS_REC: case ELS_RLS: + case ELS_RTV: fc_rport_recv_els_req(lport, fp); break; default: From 386b97b43c0c9e0d878eec7ea1db16af22b036ae Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:46 +0200 Subject: [PATCH 058/256] scsi: libfc: Rework PRLI handling PRLI is only required if the port is acting as an initiator; ports which support target functionality only do not need to send PRLI. At the same time the PRLI state is only used if the port initiated a PRLI transfer; if we received a PRLI request we should _not_ change the state as this would cause our PRLI response to be dropped. And when we receive a PRLI response we need to check if an image pair has been established; if not the remote port cannot act as a target for us and we need to disable target functionality. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 56 ++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 426c39989952..2b8214f335db 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1126,7 +1126,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 fcp_parm = 0; u8 op; - u8 resp_code = 0; + enum fc_els_spp_resp resp_code; FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp)); @@ -1158,8 +1158,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, goto out; resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK); - FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n", - pp->spp.spp_flags); + FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n", + pp->spp.spp_flags, pp->spp.spp_type); rdata->spp_type = pp->spp.spp_type; if (resp_code != FC_SPP_RESP_ACK) { if (resp_code == FC_SPP_RESP_CONF) @@ -1177,13 +1177,26 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, if (fcp_parm & FCP_SPPF_CONF_COMPL) rdata->flags |= FC_RP_FLAGS_CONF_REQ; - prov = fc_passive_prov[FC_TYPE_FCP]; + /* + * Call prli provider if we should act as a target + */ + prov = fc_passive_prov[rdata->spp_type]; if (prov) { memset(&temp_spp, 0, sizeof(temp_spp)); prov->prli(rdata, pp->prli.prli_spp_len, &pp->spp, &temp_spp); } - + /* + * Check if the image pair could be established + */ + if (rdata->spp_type != FC_TYPE_FCP || + resp_code != FC_SPP_RESP_ACK || + !(pp->spp.spp_flags & FC_SPP_EST_IMG_PAIR)) { + /* + * Nope; we can't use this port as a target. + */ + fcp_parm &= ~FCP_SPPF_TARG_FCN; + } rdata->supported_classes = FC_COS_CLASS3; if (fcp_parm & FCP_SPPF_INIT_FCN) roles |= FC_RPORT_ROLE_FCP_INITIATOR; @@ -1236,6 +1249,15 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) return; } + /* + * And if the local port does not support the initiator function + * there's no need to send a PRLI, either. + */ + if (!(lport->service_params & FCP_SPPF_INIT_FCN)) { + fc_rport_enter_ready(rdata); + return; + } + FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n", fc_rport_state(rdata)); @@ -1926,7 +1948,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, unsigned int len; unsigned int plen; enum fc_els_spp_resp resp; - enum fc_els_spp_resp passive; struct fc_seq_els_data rjt_data; struct fc4_prov *prov; @@ -1976,15 +1997,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, resp = 0; if (rspp->spp_type < FC_FC4_PROV_SIZE) { + enum fc_els_spp_resp active = 0, passive = 0; + prov = fc_active_prov[rspp->spp_type]; if (prov) - resp = prov->prli(rdata, plen, rspp, spp); + active = prov->prli(rdata, plen, rspp, spp); prov = fc_passive_prov[rspp->spp_type]; - if (prov) { + if (prov) passive = prov->prli(rdata, plen, rspp, spp); - if (!resp || passive == FC_SPP_RESP_ACK) - resp = passive; - } + if (!active || passive == FC_SPP_RESP_ACK) + resp = passive; + else + resp = active; + FC_RPORT_DBG(rdata, "PRLI rspp type %x " + "active %x passive %x\n", + rspp->spp_type, active, passive); } if (!resp) { if (spp->spp_flags & FC_SPP_EST_IMG_PAIR) @@ -2005,13 +2032,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); lport->tt.frame_send(lport, fp); - switch (rdata->rp_state) { - case RPORT_ST_PRLI: - fc_rport_enter_ready(rdata); - break; - default: - break; - } goto drop; reject_len: From 8acf1b50cfa44c8260fb1fcf7464a4eee69aefcf Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:47 +0200 Subject: [PATCH 059/256] scsi: libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Occasionally it might happen that we receive a PRLI while we're still waiting for our PLOGI response. In that case we should return 'busy' LS status instead of 'plogi required' LS status. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 2b8214f335db..a867874ff367 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1705,6 +1705,15 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) case RPORT_ST_READY: case RPORT_ST_ADISC: break; + case RPORT_ST_PLOGI: + if (fc_frame_payload_op(fp) == ELS_PRLI) { + FC_RPORT_DBG(rdata, "Reject ELS PRLI " + "while in state %s\n", + fc_rport_state(rdata)); + mutex_unlock(&rdata->rp_mutex); + kref_put(&rdata->kref, lport->tt.rport_destroy); + goto busy; + } default: FC_RPORT_DBG(rdata, "Reject ELS 0x%02x while in state %s\n", @@ -1752,6 +1761,14 @@ reject: els_data.explan = ELS_EXPL_PLOGI_REQD; lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); + return; + +busy: + els_data.reason = ELS_RJT_BUSY; + els_data.explan = ELS_EXPL_NONE; + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_frame_free(fp); + return; } /** From 5d339d163a541ceb13074789ac2f8c35b11ebda9 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:48 +0200 Subject: [PATCH 060/256] scsi: libfc: Clarify ramp-down messages When the queue depth is reduced we should print out the reason for this; it might be due to a queue full condition. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 0e2a2016af71..f7700cccf793 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -403,8 +403,6 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport) if (!can_queue) can_queue = 1; lport->host->can_queue = can_queue; - shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n" - "Reducing can_queue to %d.\n", can_queue); unlock: spin_unlock_irqrestore(lport->host->host_lock, flags); @@ -431,6 +429,9 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport, put_cpu(); /* error case */ fc_fcp_can_queue_ramp_down(lport); + shost_printk(KERN_ERR, lport->host, + "libfc: Could not allocate frame, " + "reducing can_queue to %d.\n", lport->host->can_queue); return NULL; } @@ -1860,8 +1861,13 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd) rpriv = rport->dd_data; if (!fc_fcp_lport_queue_ready(lport)) { - if (lport->qfull) + if (lport->qfull) { fc_fcp_can_queue_ramp_down(lport); + shost_printk(KERN_ERR, lport->host, + "libfc: queue full, " + "reducing can_queue to %d.\n", + lport->host->can_queue); + } rc = SCSI_MLQUEUE_HOST_BUSY; goto out; } From b73aa56ee91cd88a4977033cfd2a18d6b25dddde Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:49 +0200 Subject: [PATCH 061/256] scsi: libfc: safeguard against invalid exchange index The cached exchange index might be invalid, in which case we should drop down to allocate a new one. And we should not try to access an invalid exchange when responding to a BA_ABTS. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 99cc5a941997..7b47ab1389ca 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -827,14 +827,18 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, /* peek cache of free slot */ if (pool->left != FC_XID_UNKNOWN) { - index = pool->left; - pool->left = FC_XID_UNKNOWN; - goto hit; + if (!WARN_ON(fc_exch_ptr_get(pool, pool->left))) { + index = pool->left; + pool->left = FC_XID_UNKNOWN; + goto hit; + } } if (pool->right != FC_XID_UNKNOWN) { - index = pool->right; - pool->right = FC_XID_UNKNOWN; - goto hit; + if (!WARN_ON(fc_exch_ptr_get(pool, pool->right))) { + index = pool->right; + pool->right = FC_XID_UNKNOWN; + goto hit; + } } index = pool->next_index; @@ -1782,7 +1786,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) fc_frame_free(fp); break; case FC_RCTL_BA_ABTS: - fc_exch_recv_abts(ep, fp); + if (ep) + fc_exch_recv_abts(ep, fp); + else + fc_frame_free(fp); break; default: /* ignore junk */ fc_frame_free(fp); From 9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:50 +0200 Subject: [PATCH 062/256] scsi: libfc: quarantine timed out xids When a sequence times out we have no idea what happened to the frame. And we do not know if we will ever receive the frame. Hence we cannot re-use the xid as we would risk data corruption if the xid had been re-used and the timed out frame would be received after that. So we need to quarantine the xid until the lport is reset. Yes, I know this will (eventually) deplete the xid pool. But for now it's the safest method. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 33 ++++++++++++++++++++++----------- drivers/scsi/libfc/fc_fcp.c | 13 +++++++------ include/scsi/libfc.h | 1 + 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7b47ab1389ca..ca7d947dc427 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -94,6 +94,7 @@ struct fc_exch_pool { struct fc_exch_mgr { struct fc_exch_pool __percpu *pool; mempool_t *ep_pool; + struct fc_lport *lport; enum fc_class class; struct kref kref; u16 min_xid; @@ -408,6 +409,8 @@ static int fc_exch_done_locked(struct fc_exch *ep) return rc; } +static struct fc_exch fc_quarantine_exch; + /** * fc_exch_ptr_get() - Return an exchange from an exchange pool * @pool: Exchange Pool to get an exchange from @@ -452,14 +455,17 @@ static void fc_exch_delete(struct fc_exch *ep) /* update cache of free slot */ index = (ep->xid - ep->em->min_xid) >> fc_cpu_order; - if (pool->left == FC_XID_UNKNOWN) - pool->left = index; - else if (pool->right == FC_XID_UNKNOWN) - pool->right = index; - else - pool->next_index = index; - - fc_exch_ptr_set(pool, index, NULL); + if (!(ep->state & FC_EX_QUARANTINE)) { + if (pool->left == FC_XID_UNKNOWN) + pool->left = index; + else if (pool->right == FC_XID_UNKNOWN) + pool->right = index; + else + pool->next_index = index; + fc_exch_ptr_set(pool, index, NULL); + } else { + fc_exch_ptr_set(pool, index, &fc_quarantine_exch); + } list_del(&ep->ex_list); spin_unlock_bh(&pool->lock); fc_exch_release(ep); /* drop hold for exch in mp */ @@ -921,14 +927,14 @@ static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, */ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) { + struct fc_lport *lport = mp->lport; struct fc_exch_pool *pool; struct fc_exch *ep = NULL; u16 cpu = xid & fc_cpu_mask; if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) { - printk_ratelimited(KERN_ERR - "libfc: lookup request for XID = %d, " - "indicates invalid CPU %d\n", xid, cpu); + pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:", + lport->host->host_no, lport->port_id, xid, cpu); return NULL; } @@ -936,6 +942,10 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) pool = per_cpu_ptr(mp->pool, cpu); spin_lock_bh(&pool->lock); ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order); + if (ep == &fc_quarantine_exch) { + FC_LPORT_DBG(lport, "xid %x quarantined\n", xid); + ep = NULL; + } if (ep) { WARN_ON(ep->xid != xid); fc_exch_hold(ep); @@ -2434,6 +2444,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport, return NULL; mp->class = class; + mp->lport = lport; /* adjust em exch xid range for offload */ mp->min_xid = min_xid; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index f7700cccf793..780d9f09a267 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1529,13 +1529,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fsp->rport->port_id, rjt->er_reason, rjt->er_explan); /* - * If no data transfer, the command frame got dropped - * so we just retry. If data was transferred, we - * lost the response but the target has no record, - * so we abort and retry. + * If response got lost or is stuck in the + * queue somewhere we have no idea if and when + * the response will be received. So quarantine + * the xid and retry the command. */ - if (rjt->er_explan == ELS_EXPL_OXID_RXID && - fsp->xfer_len == 0) { + if (rjt->er_explan == ELS_EXPL_OXID_RXID) { + struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr); + ep->state |= FC_EX_QUARANTINE; fsp->state |= FC_SRB_ABORTED; fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); break; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index dc42d8070f6f..8cb752f8d12b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -390,6 +390,7 @@ struct fc_seq { #define FC_EX_DONE (1 << 0) /* ep is completed */ #define FC_EX_RST_CLEANUP (1 << 1) /* reset is forcing completion */ +#define FC_EX_QUARANTINE (1 << 2) /* exch is quarantined */ /** * struct fc_exch - Fibre Channel Exchange From d11b44eff113e2a848577ce58af6488f161b6f7d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:51 +0200 Subject: [PATCH 063/256] scsi: libfc: don't fail sequence abort for completed exchanges If a sequence should be aborted the exchange might already be completed (eg if the response is still queued in the rx queue), so this shouldn't considered as an error. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 40 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 780d9f09a267..d43c925bace3 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -258,6 +258,17 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) mod_timer(&fsp->timer, jiffies + delay); } +static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp) +{ + fsp->state |= FC_SRB_ABORTED; + fsp->state &= ~FC_SRB_ABORT_PENDING; + + if (fsp->wait_for_comp) + complete(&fsp->tm_done); + else + fc_fcp_complete_locked(fsp); +} + /** * fc_fcp_send_abort() - Send an abort for exchanges associated with a * fcp_pkt @@ -265,6 +276,8 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) */ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) { + int rc; + if (!fsp->seq_ptr) return -EINVAL; @@ -272,7 +285,16 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) put_cpu(); fsp->state |= FC_SRB_ABORT_PENDING; - return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); + rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); + /* + * ->seq_exch_abort() might return -ENXIO if + * the sequence is already completed + */ + if (rc == -ENXIO) { + fc_fcp_abort_done(fsp); + rc = 0; + } + return rc; } /** @@ -729,15 +751,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) ba_done = 0; } - if (ba_done) { - fsp->state |= FC_SRB_ABORTED; - fsp->state &= ~FC_SRB_ABORT_PENDING; - - if (fsp->wait_for_comp) - complete(&fsp->tm_done); - else - fc_fcp_complete_locked(fsp); - } + if (ba_done) + fc_fcp_abort_done(fsp); } /** @@ -1245,6 +1260,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) return FAILED; } + if (fsp->state & FC_SRB_ABORTED) { + FC_FCP_DBG(fsp, "target abort cmd completed\n"); + return SUCCESS; + } + init_completion(&fsp->tm_done); fsp->wait_for_comp = 1; From 53db8fa8a3b37d076f89bac67095e1381a2fb19a Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:52 +0200 Subject: [PATCH 064/256] scsi: libfc: Do not drop out-of-order frames When receiving packets from the network we cannot guarantee any frame ordering, so we should be receiving all valid frames and let the upper layers deal with it. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ca7d947dc427..44feffa2ee25 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1597,9 +1597,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if (fc_sof_is_init(sof)) { sp->ssb_stat |= SSB_ST_RESP; sp->id = fh->fh_seq_id; - } else if (sp->id != fh->fh_seq_id) { - atomic_inc(&mp->stats.seq_not_found); - goto rel; } f_ctl = ntoh24(fh->fh_f_ctl); From ad3120cfe0c5dcd5aaa87a0f7c42d4b09a94fa12 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:53 +0200 Subject: [PATCH 065/256] scsi: libfc: reset timeout on queue full When we're receiving a timeout we should be checking for queue full status; if there are still some packets pending we should be resetting the counter to ensure we're not missing out any packets which are still queued. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 20 +++++++++++++++++--- include/scsi/libfc.h | 3 ++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index d43c925bace3..fb2ebc76e0eb 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -254,8 +254,10 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp) */ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) { - if (!(fsp->state & FC_SRB_COMPL)) + if (!(fsp->state & FC_SRB_COMPL)) { mod_timer(&fsp->timer, jiffies + delay); + fsp->timer_delay = delay; + } } static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp) @@ -932,6 +934,11 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Wait a at least one jiffy to see if it is delivered. * If this expires without data, we may do SRR. */ + if (fsp->lp->qfull) { + FC_FCP_DBG(fsp, "tgt %6.6x queue busy retry\n", + fsp->rport->port_id); + return; + } FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun " "len %x, data len %x\n", fsp->rport->port_id, @@ -1434,8 +1441,15 @@ static void fc_fcp_timeout(unsigned long data) if (fsp->cdb_cmd.fc_tm_flags) goto unlock; - FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n", - rpriv->flags, fsp->state); + if (fsp->lp->qfull) { + FC_FCP_DBG(fsp, "fcp timeout, resetting timer delay %d\n", + fsp->timer_delay); + setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp); + fc_fcp_timer_set(fsp, fsp->timer_delay); + goto unlock; + } + FC_FCP_DBG(fsp, "fcp timeout, delay %d flags %x state %x\n", + fsp->timer_delay, rpriv->flags, fsp->state); fsp->state |= FC_SRB_FCP_PROCESSING_TMO; if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 8cb752f8d12b..f5aa54b40e75 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -355,7 +355,8 @@ struct fc_fcp_pkt { /* Timeout/error related information */ struct timer_list timer; - int wait_for_comp; + int wait_for_comp; + int timer_delay; u32 recov_retry; struct fc_seq *recov_seq; struct completion tm_done; From 87da3b832e54bcee7fac220bec00ca42b931bab0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:54 +0200 Subject: [PATCH 066/256] scsi: libfc: wait for E_D_TOV when out-of-order sequence is received When detecting an out-of-order sequence we should be waiting for E_D_TOV before trying to abort the sequence. The response might still be stuck in the queue somewhere. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 38 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index fb2ebc76e0eb..c033946875a7 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -459,6 +459,22 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport, return NULL; } +/** + * get_fsp_rec_tov() - Helper function to get REC_TOV + * @fsp: the FCP packet + * + * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second + */ +static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) +{ + struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; + unsigned int e_d_tov = FC_DEF_E_D_TOV; + + if (rpriv && rpriv->e_d_tov > e_d_tov) + e_d_tov = rpriv->e_d_tov; + return msecs_to_jiffies(e_d_tov) + HZ; +} + /** * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target * @fsp: The FCP packet the data is on @@ -562,8 +578,10 @@ crc_err: * and completes the transfer, call the completion handler. */ if (unlikely(fsp->state & FC_SRB_RCV_STATUS) && - fsp->xfer_len == fsp->data_len - fsp->scsi_resid) + fsp->xfer_len == fsp->data_len - fsp->scsi_resid) { + FC_FCP_DBG( fsp, "complete out-of-order sequence\n" ); fc_fcp_complete_locked(fsp); + } return; err: fc_fcp_recovery(fsp, host_bcode); @@ -943,7 +961,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) "len %x, data len %x\n", fsp->rport->port_id, fsp->xfer_len, expected_len, fsp->data_len); - fc_fcp_timer_set(fsp, 2); + fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp)); return; } fsp->status_code = FC_DATA_OVRRUN; @@ -1151,22 +1169,6 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) return rc; } -/** - * get_fsp_rec_tov() - Helper function to get REC_TOV - * @fsp: the FCP packet - * - * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second - */ -static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) -{ - struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; - unsigned int e_d_tov = FC_DEF_E_D_TOV; - - if (rpriv && rpriv->e_d_tov > e_d_tov) - e_d_tov = rpriv->e_d_tov; - return msecs_to_jiffies(e_d_tov) + HZ; -} - /** * fc_fcp_cmd_send() - Send a FCP command * @lport: The local port to send the command on From e0a25286d8acd97ac0b9db5b8b776755fc8b62fa Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:55 +0200 Subject: [PATCH 067/256] scsi: libfc: Check xid when looking up REC exchanges We currently can only lookup the local xid, so we need to reject REC with empty rxid. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 44feffa2ee25..9921dbbaeaff 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2005,8 +2005,7 @@ static void fc_exch_els_rec(struct fc_frame *rfp) enum fc_els_rjt_reason reason = ELS_RJT_LOGIC; enum fc_els_rjt_explan explan; u32 sid; - u16 rxid; - u16 oxid; + u16 xid, rxid, oxid; lport = fr_dev(rfp); rp = fc_frame_payload_get(rfp, sizeof(*rp)); @@ -2017,9 +2016,18 @@ static void fc_exch_els_rec(struct fc_frame *rfp) rxid = ntohs(rp->rec_rx_id); oxid = ntohs(rp->rec_ox_id); - ep = fc_exch_lookup(lport, - sid == fc_host_port_id(lport->host) ? oxid : rxid); explan = ELS_EXPL_OXID_RXID; + if (sid == fc_host_port_id(lport->host)) + xid = oxid; + else + xid = rxid; + if (xid == FC_XID_UNKNOWN) { + FC_LPORT_DBG(lport, + "REC request from %x: invalid rxid %x oxid %x\n", + sid, rxid, oxid); + goto reject; + } + ep = fc_exch_lookup(lport, xid); if (!ep) { FC_LPORT_DBG(lport, "REC request from %x: rxid %x oxid %x not found\n", From c216e8762f96b6bddf043b5788094e0b698dd4b3 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:56 +0200 Subject: [PATCH 068/256] scsi: fcoe: set default TC priority If DCB is not enabled or compiled in we still should be setting a sane default priority. So put FCoE frames in priority class 'interactive' and FIP frames in priority class 'besteffort'. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index c907661a2ec3..9876fca8946a 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2168,6 +2168,8 @@ static bool fcoe_match(struct net_device *netdev) */ static void fcoe_dcb_create(struct fcoe_interface *fcoe) { + int ctlr_prio = TC_PRIO_BESTEFFORT; + int fcoe_prio = TC_PRIO_INTERACTIVE; #ifdef CONFIG_DCB int dcbx; u8 fup, up; @@ -2194,10 +2196,12 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) fup = dcb_getapp(netdev, &app); } - fcoe->priority = ffs(up) ? ffs(up) - 1 : 0; - ctlr->priority = ffs(fup) ? ffs(fup) - 1 : fcoe->priority; + fcoe_prio = ffs(up) ? ffs(up) - 1 : 0; + ctlr_prio = ffs(fup) ? ffs(fup) - 1 : fcoe_prio; } #endif + fcoe->priority = fcoe_prio; + ctlr->priority = ctlr_prio; } enum fcoe_create_link_state { From 5cc5512690537fcfafd50a5941cdbdb9f4134308 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:57 +0200 Subject: [PATCH 069/256] scsi: fcoe: catch invalid values for the 'enabled' attribute The 'enabled' sysfs attribute only accepts the values '0' and '1', so we should error out any other values. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_sysfs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c index 9e6baac18e76..9cf3d56296ab 100644 --- a/drivers/scsi/fcoe/fcoe_sysfs.c +++ b/drivers/scsi/fcoe/fcoe_sysfs.c @@ -335,16 +335,24 @@ static ssize_t store_ctlr_enabled(struct device *dev, const char *buf, size_t count) { struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); + bool enabled; int rc; + if (*buf == '1') + enabled = true; + else if (*buf == '0') + enabled = false; + else + return -EINVAL; + switch (ctlr->enabled) { case FCOE_CTLR_ENABLED: - if (*buf == '1') + if (enabled) return count; ctlr->enabled = FCOE_CTLR_DISABLED; break; case FCOE_CTLR_DISABLED: - if (*buf == '0') + if (!enabled) return count; ctlr->enabled = FCOE_CTLR_ENABLED; break; From c959655042b8eb4814e849dde4518682c6d963e1 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:58 +0200 Subject: [PATCH 070/256] scsi: fcoe: FIP debugging Add additional statements for debugging FIP frames. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 48 ++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 05573c32254d..d773b4658861 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -801,6 +801,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, return -EINPROGRESS; drop: kfree_skb(skb); + LIBFCOE_FIP_DBG(fip, "drop els_send op %u d_id %x\n", + op, ntoh24(fh->fh_d_id)); return -EINVAL; } EXPORT_SYMBOL(fcoe_ctlr_els_send); @@ -2428,6 +2430,8 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, switch (fip->state) { case FIP_ST_VNMP_CLAIM: case FIP_ST_VNMP_UP: + LIBFCOE_FIP_DBG(fip, "vn_probe_req: send reply, state %x\n", + fip->state); fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP, frport->enode_mac, 0); break; @@ -2442,15 +2446,21 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, */ if (fip->lp->wwpn > rdata->ids.port_name && !(frport->flags & FIP_FL_REC_OR_P2P)) { + LIBFCOE_FIP_DBG(fip, "vn_probe_req: " + "port_id collision\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP, frport->enode_mac, 0); break; } /* fall through */ case FIP_ST_VNMP_START: + LIBFCOE_FIP_DBG(fip, "vn_probe_req: " + "restart VN2VN negotiation\n"); fcoe_ctlr_vn_restart(fip); break; default: + LIBFCOE_FIP_DBG(fip, "vn_probe_req: ignore state %x\n", + fip->state); break; } } @@ -2472,9 +2482,12 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip, case FIP_ST_VNMP_PROBE1: case FIP_ST_VNMP_PROBE2: case FIP_ST_VNMP_CLAIM: + LIBFCOE_FIP_DBG(fip, "vn_probe_reply: restart state %x\n", + fip->state); fcoe_ctlr_vn_restart(fip); break; case FIP_ST_VNMP_UP: + LIBFCOE_FIP_DBG(fip, "vn_probe_reply: send claim notify\n"); fcoe_ctlr_vn_send_claim(fip); break; default: @@ -2517,6 +2530,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) || (ids->node_name != -1 && ids->node_name != new->ids.node_name)) { mutex_unlock(&rdata->rp_mutex); + LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id); lport->tt.rport_logoff(rdata); mutex_lock(&rdata->rp_mutex); } @@ -2525,8 +2539,9 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) mutex_unlock(&rdata->rp_mutex); frport = fcoe_ctlr_rport(rdata); - LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n", - port_id, frport->fcoe_len ? "old" : "new"); + LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n", + port_id, frport->fcoe_len ? "old" : "new", + rdata->rp_state); *frport = *fcoe_ctlr_rport(new); frport->time = 0; } @@ -2569,6 +2584,7 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip, struct fcoe_rport *frport = fcoe_ctlr_rport(new); if (frport->flags & FIP_FL_REC_OR_P2P) { + LIBFCOE_FIP_DBG(fip, "send probe req for P2P/REC\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); return; } @@ -2576,25 +2592,37 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip, case FIP_ST_VNMP_START: case FIP_ST_VNMP_PROBE1: case FIP_ST_VNMP_PROBE2: - if (new->ids.port_id == fip->port_id) + if (new->ids.port_id == fip->port_id) { + LIBFCOE_FIP_DBG(fip, "vn_claim_notify: " + "restart, state %d\n", + fip->state); fcoe_ctlr_vn_restart(fip); + } break; case FIP_ST_VNMP_CLAIM: case FIP_ST_VNMP_UP: if (new->ids.port_id == fip->port_id) { if (new->ids.port_name > fip->lp->wwpn) { + LIBFCOE_FIP_DBG(fip, "vn_claim_notify: " + "restart, port_id collision\n"); fcoe_ctlr_vn_restart(fip); break; } + LIBFCOE_FIP_DBG(fip, "vn_claim_notify: " + "send claim notify\n"); fcoe_ctlr_vn_send_claim(fip); break; } + LIBFCOE_FIP_DBG(fip, "vn_claim_notify: send reply to %x\n", + new->ids.port_id); fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac, min((u32)frport->fcoe_len, fcoe_ctlr_fcoe_size(fip))); fcoe_ctlr_vn_add(fip, new); break; default: + LIBFCOE_FIP_DBG(fip, "vn_claim_notify: " + "ignoring claim from %x\n", new->ids.port_id); break; } } @@ -2631,6 +2659,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, frport = fcoe_ctlr_rport(new); if (frport->flags & FIP_FL_REC_OR_P2P) { + LIBFCOE_FIP_DBG(fip, "p2p beacon while in vn2vn mode\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); return; } @@ -2639,8 +2668,14 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, if (rdata->ids.node_name == new->ids.node_name && rdata->ids.port_name == new->ids.port_name) { frport = fcoe_ctlr_rport(rdata); - if (!frport->time && fip->state == FIP_ST_VNMP_UP) + LIBFCOE_FIP_DBG(fip, "beacon from rport %x\n", + rdata->ids.port_id); + if (!frport->time && fip->state == FIP_ST_VNMP_UP) { + LIBFCOE_FIP_DBG(fip, "beacon expired " + "for rport %x\n", + rdata->ids.port_id); lport->tt.rport_login(rdata); + } frport->time = jiffies; } kref_put(&rdata->kref, lport->tt.rport_destroy); @@ -3065,11 +3100,13 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) switch (fip->state) { case FIP_ST_VNMP_START: fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1); + LIBFCOE_FIP_DBG(fip, "vn_timeout: send 1st probe request\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT); break; case FIP_ST_VNMP_PROBE1: fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2); + LIBFCOE_FIP_DBG(fip, "vn_timeout: send 2nd probe request\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); break; @@ -3080,6 +3117,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) hton24(mac + 3, new_port_id); fcoe_ctlr_map_dest(fip); fip->update_mac(fip->lp, mac); + LIBFCOE_FIP_DBG(fip, "vn_timeout: send claim notify\n"); fcoe_ctlr_vn_send_claim(fip); next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); break; @@ -3091,6 +3129,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT); if (time_after_eq(jiffies, next_time)) { fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP); + LIBFCOE_FIP_DBG(fip, "vn_timeout: send vn2vn beacon\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON, fcoe_all_vn2vn, 0); next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); @@ -3101,6 +3140,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) case FIP_ST_VNMP_UP: next_time = fcoe_ctlr_vn_age(fip); if (time_after_eq(jiffies, fip->port_ka_time)) { + LIBFCOE_FIP_DBG(fip, "vn_timeout: send vn2vn beacon\n"); fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON, fcoe_all_vn2vn, 0); fip->port_ka_time = jiffies + From f7e6ed0654128979a1939be6640416abb6a54811 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:59 +0200 Subject: [PATCH 071/256] scsi: fcoe: correct sending FIP VLAN packets on VLAN 0 The FIP VLAN frame consists of an ethernet header followed by the FIP VLAN frame, so we need to skip the ethernet header if we want to check the FIP opcode. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 9876fca8946a..cf4adaafd668 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -590,7 +590,8 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) * Use default VLAN for FIP VLAN discovery protocol */ frame = (struct fip_frame *)skb->data; - if (frame->fip.fip_op == ntohs(FIP_OP_VLAN) && + if (ntohs(frame->eth.h_proto) == ETH_P_FIP && + ntohs(frame->fip.fip_op) == FIP_OP_VLAN && fcoe->realdev != fcoe->netdev) skb->dev = fcoe->realdev; else From 5d5a51d205ba841b88d758deb6ff537fb754adbc Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:11:00 +0200 Subject: [PATCH 072/256] scsi: fcoe: filter out frames from invalid vlans Any multicase address is set on all interfaces, the base interface and any VLAN interfaces on top of this. So we might receive frames which are not destined for us. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index d773b4658861..4aacd60f49b3 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2754,11 +2754,21 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) struct fc_rport_priv rdata; struct fcoe_rport frport; } buf; - int rc; + int rc, vlan_id = 0; fiph = (struct fip_header *)skb->data; sub = fiph->fip_subcode; + if (fip->lp->vlan) + vlan_id = skb_vlan_tag_get_id(skb); + + if (vlan_id && vlan_id != fip->lp->vlan) { + LIBFCOE_FIP_DBG(fip, "vn_recv drop frame sub %x vlan %d\n", + sub, vlan_id); + rc = -EAGAIN; + goto drop; + } + rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata); if (rc) { LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc); From efe583c6d3cdafbeb0c039cd5d0f88fd26637065 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 17 Oct 2016 14:35:46 +0200 Subject: [PATCH 073/256] scsi: lpfc: Use %zd format string for size_t A recent bugfix introduced a harmless warning in the lpfc driver: drivers/scsi/lpfc/lpfc_init.c: In function 'lpfc_write_firmware': drivers/scsi/lpfc/lpfc_logmsg.h:56:45: error: format '%ld' expects argument of type 'long int', but argument 9 has type 'size_t {aka const unsigned int}' [-Werror=format=] 'size_t' is always the same width as 'long' in the kernel, but the compiler doesn't know that. The %z modifier is what the standard expects to be used here, and this shuts up the warning. Fixes: 679053c651fb ("scsi: lpfc: Fix fw download on SLI-4 FC adapters") Signed-off-by: Arnd Bergmann Reviewed-by: Johannes Thumshirn Acked-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7be9b8a7bb19..4776fd85514f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -10332,7 +10332,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context) ftype != LPFC_FILE_TYPE_GROUP || fsize != fw->size) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3022 Invalid FW image found. " - "Magic:%x Type:%x ID:%x Size %d %ld\n", + "Magic:%x Type:%x ID:%x Size %d %zd\n", magic_number, ftype, fid, fsize, fw->size); rc = -EINVAL; goto release_out; From c5969656715d16f95f54be550c2130520b075b72 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 08:39:16 +0200 Subject: [PATCH 074/256] scsi: fcoe: Fixup missing initialisation in fcoe_dcb_create() Found by 0-day robot. Fixes: a99ac6e715bc ("scsi: fcoe: set default TC priority") Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cf4adaafd668..59150cad0353 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2171,11 +2171,11 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) { int ctlr_prio = TC_PRIO_BESTEFFORT; int fcoe_prio = TC_PRIO_INTERACTIVE; + struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); #ifdef CONFIG_DCB int dcbx; u8 fup, up; struct net_device *netdev = fcoe->realdev; - struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); struct dcb_app app = { .priority = 0, .protocol = ETH_P_FCOE From c1f7cf0aeed1e57bb8374a07eab3a6aa784da2b6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 18 Oct 2016 17:18:06 +0200 Subject: [PATCH 075/256] scsi: g_NCR5380: add HAS_IOPORT_MAP dependency The driver was changed to call ioport_map, which breaks platforms that cannot provide this function: drivers/scsi/g_NCR5380.o: In function `generic_NCR5380_init_one.constprop.0': g_NCR5380.c:(.text.generic_NCR5380_init_one.constprop.0+0x388): undefined reference to `ioport_map' This adds a Kconfig dependency. Fixes: 04c40f82ccc5 ("scsi: g_NCR5380: Merge g_NCR5380 and g_NCR5380_mmio drivers") Signed-off-by: Arnd Bergmann Acked-by: Finn Thain Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 98451fe031a4..3b416c9efe5e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -744,7 +744,7 @@ config SCSI_ISCI config SCSI_GENERIC_NCR5380 tristate "Generic NCR5380/53c400 SCSI ISA card support" - depends on ISA && SCSI + depends on ISA && SCSI && HAS_IOPORT_MAP select SCSI_SPI_ATTRS ---help--- This is a driver for old ISA card SCSI controllers based on a From 79fac9c9b74f4951c9ce82b22e714bcc34ae4a56 Mon Sep 17 00:00:00 2001 From: Michael Cyr Date: Thu, 13 Oct 2016 11:02:38 -0500 Subject: [PATCH 076/256] scsi: ibmvscsis: Rearrange functions for future patches This patch reorders functions in a manner necessary for a follow-on patch. It also makes some minor styling changes (mostly removing extra spaces) and fixes some typos. There are no code changes in this patch, with one exception: due to the reordering of the functions, I needed to explicitly declare a function at the top of the file. However, this will be removed in the next patch, since the code requiring the predeclaration will be removed. Signed-off-by: Michael Cyr Signed-off-by: Bryant G. Ly Tested-by: Steven Royer Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 658 ++++++++++++----------- 1 file changed, 330 insertions(+), 328 deletions(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 642b739ad0da..01a430cc15e4 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -22,7 +22,7 @@ * ****************************************************************************/ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -61,6 +61,8 @@ static long ibmvscsis_parse_command(struct scsi_info *vscsi, static void ibmvscsis_adapter_idle(struct scsi_info *vscsi); +static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state); + static void ibmvscsis_determine_resid(struct se_cmd *se_cmd, struct srp_rsp *rsp) { @@ -81,7 +83,7 @@ static void ibmvscsis_determine_resid(struct se_cmd *se_cmd, } } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { if (se_cmd->data_direction == DMA_TO_DEVICE) { - /* residual data from an overflow write */ + /* residual data from an overflow write */ rsp->flags = SRP_RSP_FLAG_DOOVER; rsp->data_out_res_cnt = cpu_to_be32(residual_count); } else if (se_cmd->data_direction == DMA_FROM_DEVICE) { @@ -101,7 +103,7 @@ static void ibmvscsis_determine_resid(struct se_cmd *se_cmd, * and the function returns TRUE. * * EXECUTION ENVIRONMENT: - * Interrupt or Process environment + * Interrupt or Process environment */ static bool connection_broken(struct scsi_info *vscsi) { @@ -324,7 +326,7 @@ static struct viosrp_crq *ibmvscsis_cmd_q_dequeue(uint mask, } /** - * ibmvscsis_send_init_message() - send initialize message to the client + * ibmvscsis_send_init_message() - send initialize message to the client * @vscsi: Pointer to our adapter structure * @format: Which Init Message format to send * @@ -382,13 +384,13 @@ static long ibmvscsis_check_init_msg(struct scsi_info *vscsi, uint *format) vscsi->cmd_q.base_addr); if (crq) { *format = (uint)(crq->format); - rc = ERROR; + rc = ERROR; crq->valid = INVALIDATE_CMD_RESP_EL; dma_rmb(); } } else { *format = (uint)(crq->format); - rc = ERROR; + rc = ERROR; crq->valid = INVALIDATE_CMD_RESP_EL; dma_rmb(); } @@ -396,166 +398,6 @@ static long ibmvscsis_check_init_msg(struct scsi_info *vscsi, uint *format) return rc; } -/** - * ibmvscsis_establish_new_q() - Establish new CRQ queue - * @vscsi: Pointer to our adapter structure - * @new_state: New state being established after resetting the queue - * - * Must be called with interrupt lock held. - */ -static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) -{ - long rc = ADAPT_SUCCESS; - uint format; - - vscsi->flags &= PRESERVE_FLAG_FIELDS; - vscsi->rsp_q_timer.timer_pops = 0; - vscsi->debit = 0; - vscsi->credit = 0; - - rc = vio_enable_interrupts(vscsi->dma_dev); - if (rc) { - pr_warn("reset_queue: failed to enable interrupts, rc %ld\n", - rc); - return rc; - } - - rc = ibmvscsis_check_init_msg(vscsi, &format); - if (rc) { - dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n", - rc); - return rc; - } - - if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) { - rc = ibmvscsis_send_init_message(vscsi, INIT_MSG); - switch (rc) { - case H_SUCCESS: - case H_DROPPED: - case H_CLOSED: - rc = ADAPT_SUCCESS; - break; - - case H_PARAMETER: - case H_HARDWARE: - break; - - default: - vscsi->state = UNDEFINED; - rc = H_HARDWARE; - break; - } - } - - return rc; -} - -/** - * ibmvscsis_reset_queue() - Reset CRQ Queue - * @vscsi: Pointer to our adapter structure - * @new_state: New state to establish after resetting the queue - * - * This function calls h_free_q and then calls h_reg_q and does all - * of the bookkeeping to get us back to where we can communicate. - * - * Actually, we don't always call h_free_crq. A problem was discovered - * where one partition would close and reopen his queue, which would - * cause his partner to get a transport event, which would cause him to - * close and reopen his queue, which would cause the original partition - * to get a transport event, etc., etc. To prevent this, we don't - * actually close our queue if the client initiated the reset, (i.e. - * either we got a transport event or we have detected that the client's - * queue is gone) - * - * EXECUTION ENVIRONMENT: - * Process environment, called with interrupt lock held - */ -static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state) -{ - int bytes; - long rc = ADAPT_SUCCESS; - - pr_debug("reset_queue: flags 0x%x\n", vscsi->flags); - - /* don't reset, the client did it for us */ - if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) { - vscsi->flags &= PRESERVE_FLAG_FIELDS; - vscsi->rsp_q_timer.timer_pops = 0; - vscsi->debit = 0; - vscsi->credit = 0; - vscsi->state = new_state; - vio_enable_interrupts(vscsi->dma_dev); - } else { - rc = ibmvscsis_free_command_q(vscsi); - if (rc == ADAPT_SUCCESS) { - vscsi->state = new_state; - - bytes = vscsi->cmd_q.size * PAGE_SIZE; - rc = h_reg_crq(vscsi->dds.unit_id, - vscsi->cmd_q.crq_token, bytes); - if (rc == H_CLOSED || rc == H_SUCCESS) { - rc = ibmvscsis_establish_new_q(vscsi, - new_state); - } - - if (rc != ADAPT_SUCCESS) { - pr_debug("reset_queue: reg_crq rc %ld\n", rc); - - vscsi->state = ERR_DISCONNECTED; - vscsi->flags |= RESPONSE_Q_DOWN; - ibmvscsis_free_command_q(vscsi); - } - } else { - vscsi->state = ERR_DISCONNECTED; - vscsi->flags |= RESPONSE_Q_DOWN; - } - } -} - -/** - * ibmvscsis_free_cmd_resources() - Free command resources - * @vscsi: Pointer to our adapter structure - * @cmd: Command which is not longer in use - * - * Must be called with interrupt lock held. - */ -static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi, - struct ibmvscsis_cmd *cmd) -{ - struct iu_entry *iue = cmd->iue; - - switch (cmd->type) { - case TASK_MANAGEMENT: - case SCSI_CDB: - /* - * When the queue goes down this value is cleared, so it - * cannot be cleared in this general purpose function. - */ - if (vscsi->debit) - vscsi->debit -= 1; - break; - case ADAPTER_MAD: - vscsi->flags &= ~PROCESSING_MAD; - break; - case UNSET_TYPE: - break; - default: - dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n", - cmd->type); - break; - } - - cmd->iue = NULL; - list_add_tail(&cmd->list, &vscsi->free_cmd); - srp_iu_put(iue); - - if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) && - list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) { - vscsi->flags &= ~WAIT_FOR_IDLE; - complete(&vscsi->wait_idle); - } -} - /** * ibmvscsis_disconnect() - Helper function to disconnect * @work: Pointer to work_struct, gives access to our adapter structure @@ -589,7 +431,7 @@ static void ibmvscsis_disconnect(struct work_struct *work) * should transitition to the new state */ switch (vscsi->state) { - /* Should never be called while in this state. */ + /* Should never be called while in this state. */ case NO_QUEUE: /* * Can never transition from this state; @@ -805,6 +647,316 @@ static void ibmvscsis_post_disconnect(struct scsi_info *vscsi, uint new_state, vscsi->flags, vscsi->new_state); } +/** + * ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message + * @vscsi: Pointer to our adapter structure + * + * Must be called with interrupt lock held. + */ +static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi) +{ + long rc = ADAPT_SUCCESS; + + switch (vscsi->state) { + case NO_QUEUE: + case ERR_DISCONNECT: + case ERR_DISCONNECT_RECONNECT: + case ERR_DISCONNECTED: + case UNCONFIGURING: + case UNDEFINED: + rc = ERROR; + break; + + case WAIT_CONNECTION: + vscsi->state = CONNECTED; + break; + + case WAIT_IDLE: + case SRP_PROCESSING: + case CONNECTED: + case WAIT_ENABLED: + case PART_UP_WAIT_ENAB: + default: + rc = ERROR; + dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n", + vscsi->state); + ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); + break; + } + + return rc; +} + +/** + * ibmvscsis_handle_init_msg() - Respond to an Init Message + * @vscsi: Pointer to our adapter structure + * + * Must be called with interrupt lock held. + */ +static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi) +{ + long rc = ADAPT_SUCCESS; + + switch (vscsi->state) { + case WAIT_ENABLED: + vscsi->state = PART_UP_WAIT_ENAB; + break; + + case WAIT_CONNECTION: + rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG); + switch (rc) { + case H_SUCCESS: + vscsi->state = CONNECTED; + break; + + case H_PARAMETER: + dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n", + rc); + ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0); + break; + + case H_DROPPED: + dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n", + rc); + rc = ERROR; + ibmvscsis_post_disconnect(vscsi, + ERR_DISCONNECT_RECONNECT, 0); + break; + + case H_CLOSED: + pr_warn("init_msg: failed to send, rc %ld\n", rc); + rc = 0; + break; + } + break; + + case UNDEFINED: + rc = ERROR; + break; + + case UNCONFIGURING: + break; + + case PART_UP_WAIT_ENAB: + case CONNECTED: + case SRP_PROCESSING: + case WAIT_IDLE: + case NO_QUEUE: + case ERR_DISCONNECT: + case ERR_DISCONNECT_RECONNECT: + case ERR_DISCONNECTED: + default: + rc = ERROR; + dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n", + vscsi->state); + ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); + break; + } + + return rc; +} + +/** + * ibmvscsis_init_msg() - Respond to an init message + * @vscsi: Pointer to our adapter structure + * @crq: Pointer to CRQ element containing the Init Message + * + * EXECUTION ENVIRONMENT: + * Interrupt, interrupt lock held + */ +static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq) +{ + long rc = ADAPT_SUCCESS; + + pr_debug("init_msg: state 0x%hx\n", vscsi->state); + + rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO, + (u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0, + 0); + if (rc == H_SUCCESS) { + vscsi->client_data.partition_number = + be64_to_cpu(*(u64 *)vscsi->map_buf); + pr_debug("init_msg, part num %d\n", + vscsi->client_data.partition_number); + } else { + pr_debug("init_msg h_vioctl rc %ld\n", rc); + rc = ADAPT_SUCCESS; + } + + if (crq->format == INIT_MSG) { + rc = ibmvscsis_handle_init_msg(vscsi); + } else if (crq->format == INIT_COMPLETE_MSG) { + rc = ibmvscsis_handle_init_compl_msg(vscsi); + } else { + rc = ERROR; + dev_err(&vscsi->dev, "init_msg: invalid format %d\n", + (uint)crq->format); + ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); + } + + return rc; +} + +/** + * ibmvscsis_establish_new_q() - Establish new CRQ queue + * @vscsi: Pointer to our adapter structure + * @new_state: New state being established after resetting the queue + * + * Must be called with interrupt lock held. + */ +static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) +{ + long rc = ADAPT_SUCCESS; + uint format; + + vscsi->flags &= PRESERVE_FLAG_FIELDS; + vscsi->rsp_q_timer.timer_pops = 0; + vscsi->debit = 0; + vscsi->credit = 0; + + rc = vio_enable_interrupts(vscsi->dma_dev); + if (rc) { + pr_warn("reset_queue: failed to enable interrupts, rc %ld\n", + rc); + return rc; + } + + rc = ibmvscsis_check_init_msg(vscsi, &format); + if (rc) { + dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n", + rc); + return rc; + } + + if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) { + rc = ibmvscsis_send_init_message(vscsi, INIT_MSG); + switch (rc) { + case H_SUCCESS: + case H_DROPPED: + case H_CLOSED: + rc = ADAPT_SUCCESS; + break; + + case H_PARAMETER: + case H_HARDWARE: + break; + + default: + vscsi->state = UNDEFINED; + rc = H_HARDWARE; + break; + } + } + + return rc; +} + +/** + * ibmvscsis_reset_queue() - Reset CRQ Queue + * @vscsi: Pointer to our adapter structure + * @new_state: New state to establish after resetting the queue + * + * This function calls h_free_q and then calls h_reg_q and does all + * of the bookkeeping to get us back to where we can communicate. + * + * Actually, we don't always call h_free_crq. A problem was discovered + * where one partition would close and reopen his queue, which would + * cause his partner to get a transport event, which would cause him to + * close and reopen his queue, which would cause the original partition + * to get a transport event, etc., etc. To prevent this, we don't + * actually close our queue if the client initiated the reset, (i.e. + * either we got a transport event or we have detected that the client's + * queue is gone) + * + * EXECUTION ENVIRONMENT: + * Process environment, called with interrupt lock held + */ +static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state) +{ + int bytes; + long rc = ADAPT_SUCCESS; + + pr_debug("reset_queue: flags 0x%x\n", vscsi->flags); + + /* don't reset, the client did it for us */ + if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) { + vscsi->flags &= PRESERVE_FLAG_FIELDS; + vscsi->rsp_q_timer.timer_pops = 0; + vscsi->debit = 0; + vscsi->credit = 0; + vscsi->state = new_state; + vio_enable_interrupts(vscsi->dma_dev); + } else { + rc = ibmvscsis_free_command_q(vscsi); + if (rc == ADAPT_SUCCESS) { + vscsi->state = new_state; + + bytes = vscsi->cmd_q.size * PAGE_SIZE; + rc = h_reg_crq(vscsi->dds.unit_id, + vscsi->cmd_q.crq_token, bytes); + if (rc == H_CLOSED || rc == H_SUCCESS) { + rc = ibmvscsis_establish_new_q(vscsi, + new_state); + } + + if (rc != ADAPT_SUCCESS) { + pr_debug("reset_queue: reg_crq rc %ld\n", rc); + + vscsi->state = ERR_DISCONNECTED; + vscsi->flags |= RESPONSE_Q_DOWN; + ibmvscsis_free_command_q(vscsi); + } + } else { + vscsi->state = ERR_DISCONNECTED; + vscsi->flags |= RESPONSE_Q_DOWN; + } + } +} + +/** + * ibmvscsis_free_cmd_resources() - Free command resources + * @vscsi: Pointer to our adapter structure + * @cmd: Command which is not longer in use + * + * Must be called with interrupt lock held. + */ +static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi, + struct ibmvscsis_cmd *cmd) +{ + struct iu_entry *iue = cmd->iue; + + switch (cmd->type) { + case TASK_MANAGEMENT: + case SCSI_CDB: + /* + * When the queue goes down this value is cleared, so it + * cannot be cleared in this general purpose function. + */ + if (vscsi->debit) + vscsi->debit -= 1; + break; + case ADAPTER_MAD: + vscsi->flags &= ~PROCESSING_MAD; + break; + case UNSET_TYPE: + break; + default: + dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n", + cmd->type); + break; + } + + cmd->iue = NULL; + list_add_tail(&cmd->list, &vscsi->free_cmd); + srp_iu_put(iue); + + if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) && + list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) { + vscsi->flags &= ~WAIT_FOR_IDLE; + complete(&vscsi->wait_idle); + } +} + /** * ibmvscsis_trans_event() - Handle a Transport Event * @vscsi: Pointer to our adapter structure @@ -895,7 +1047,7 @@ static long ibmvscsis_trans_event(struct scsi_info *vscsi, } } - rc = vscsi->flags & SCHEDULE_DISCONNECT; + rc = vscsi->flags & SCHEDULE_DISCONNECT; pr_debug("Leaving trans_event: flags 0x%x, state 0x%hx, rc %ld\n", vscsi->flags, vscsi->state, rc); @@ -1220,7 +1372,7 @@ static long ibmvscsis_copy_crq_packet(struct scsi_info *vscsi, * @iue: Information Unit containing the Adapter Info MAD request * * EXECUTION ENVIRONMENT: - * Interrupt adpater lock is held + * Interrupt adapter lock is held */ static long ibmvscsis_adapter_info(struct scsi_info *vscsi, struct iu_entry *iue) @@ -1691,7 +1843,7 @@ static void ibmvscsis_send_mad_resp(struct scsi_info *vscsi, * @crq: Pointer to the CRQ entry containing the MAD request * * EXECUTION ENVIRONMENT: - * Interrupt called with adapter lock held + * Interrupt, called with adapter lock held */ static long ibmvscsis_mad(struct scsi_info *vscsi, struct viosrp_crq *crq) { @@ -1864,7 +2016,7 @@ static long ibmvscsis_srp_login_rej(struct scsi_info *vscsi, break; case H_PERMISSION: if (connection_broken(vscsi)) - flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED; + flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED; dev_err(&vscsi->dev, "login_rej: error copying to client, rc %ld\n", rc); ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, @@ -2186,156 +2338,6 @@ static long ibmvscsis_ping_response(struct scsi_info *vscsi) return rc; } -/** - * ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message - * @vscsi: Pointer to our adapter structure - * - * Must be called with interrupt lock held. - */ -static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi) -{ - long rc = ADAPT_SUCCESS; - - switch (vscsi->state) { - case NO_QUEUE: - case ERR_DISCONNECT: - case ERR_DISCONNECT_RECONNECT: - case ERR_DISCONNECTED: - case UNCONFIGURING: - case UNDEFINED: - rc = ERROR; - break; - - case WAIT_CONNECTION: - vscsi->state = CONNECTED; - break; - - case WAIT_IDLE: - case SRP_PROCESSING: - case CONNECTED: - case WAIT_ENABLED: - case PART_UP_WAIT_ENAB: - default: - rc = ERROR; - dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n", - vscsi->state); - ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); - break; - } - - return rc; -} - -/** - * ibmvscsis_handle_init_msg() - Respond to an Init Message - * @vscsi: Pointer to our adapter structure - * - * Must be called with interrupt lock held. - */ -static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi) -{ - long rc = ADAPT_SUCCESS; - - switch (vscsi->state) { - case WAIT_ENABLED: - vscsi->state = PART_UP_WAIT_ENAB; - break; - - case WAIT_CONNECTION: - rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG); - switch (rc) { - case H_SUCCESS: - vscsi->state = CONNECTED; - break; - - case H_PARAMETER: - dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n", - rc); - ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0); - break; - - case H_DROPPED: - dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n", - rc); - rc = ERROR; - ibmvscsis_post_disconnect(vscsi, - ERR_DISCONNECT_RECONNECT, 0); - break; - - case H_CLOSED: - pr_warn("init_msg: failed to send, rc %ld\n", rc); - rc = 0; - break; - } - break; - - case UNDEFINED: - rc = ERROR; - break; - - case UNCONFIGURING: - break; - - case PART_UP_WAIT_ENAB: - case CONNECTED: - case SRP_PROCESSING: - case WAIT_IDLE: - case NO_QUEUE: - case ERR_DISCONNECT: - case ERR_DISCONNECT_RECONNECT: - case ERR_DISCONNECTED: - default: - rc = ERROR; - dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n", - vscsi->state); - ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); - break; - } - - return rc; -} - -/** - * ibmvscsis_init_msg() - Respond to an init message - * @vscsi: Pointer to our adapter structure - * @crq: Pointer to CRQ element containing the Init Message - * - * EXECUTION ENVIRONMENT: - * Interrupt, interrupt lock held - */ -static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq) -{ - long rc = ADAPT_SUCCESS; - - pr_debug("init_msg: state 0x%hx\n", vscsi->state); - - rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO, - (u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0, - 0); - if (rc == H_SUCCESS) { - vscsi->client_data.partition_number = - be64_to_cpu(*(u64 *)vscsi->map_buf); - pr_debug("init_msg, part num %d\n", - vscsi->client_data.partition_number); - } else { - pr_debug("init_msg h_vioctl rc %ld\n", rc); - rc = ADAPT_SUCCESS; - } - - if (crq->format == INIT_MSG) { - rc = ibmvscsis_handle_init_msg(vscsi); - } else if (crq->format == INIT_COMPLETE_MSG) { - rc = ibmvscsis_handle_init_compl_msg(vscsi); - } else { - rc = ERROR; - dev_err(&vscsi->dev, "init_msg: invalid format %d\n", - (uint)crq->format); - ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); - } - - return rc; -} - /** * ibmvscsis_parse_command() - Parse an element taken from the cmd rsp queue. * @vscsi: Pointer to our adapter structure @@ -2391,7 +2393,7 @@ static long ibmvscsis_parse_command(struct scsi_info *vscsi, break; case VALID_TRANS_EVENT: - rc = ibmvscsis_trans_event(vscsi, crq); + rc = ibmvscsis_trans_event(vscsi, crq); break; case VALID_INIT_MSG: @@ -3270,7 +3272,7 @@ static void ibmvscsis_handle_crq(unsigned long data) /* * if we are in a path where we are waiting for all pending commands * to complete because we received a transport event and anything in - * the command queue is for a new connection, do nothing + * the command queue is for a new connection, do nothing */ if (TARGET_STOP(vscsi)) { vio_enable_interrupts(vscsi->dma_dev); @@ -3314,7 +3316,7 @@ cmd_work: * everything but transport events on the queue * * need to decrement the queue index so we can - * look at the elment again + * look at the element again */ if (vscsi->cmd_q.index) vscsi->cmd_q.index -= 1; @@ -3983,10 +3985,10 @@ static struct attribute *ibmvscsis_dev_attrs[] = { ATTRIBUTE_GROUPS(ibmvscsis_dev); static struct class ibmvscsis_class = { - .name = "ibmvscsis", - .dev_release = ibmvscsis_dev_release, - .class_attrs = ibmvscsis_class_attrs, - .dev_groups = ibmvscsis_dev_groups, + .name = "ibmvscsis", + .dev_release = ibmvscsis_dev_release, + .class_attrs = ibmvscsis_class_attrs, + .dev_groups = ibmvscsis_dev_groups, }; static struct vio_device_id ibmvscsis_device_table[] = { From c9b3379f60a83288a5e2f8ea75476460978689b0 Mon Sep 17 00:00:00 2001 From: Michael Cyr Date: Thu, 13 Oct 2016 11:02:39 -0500 Subject: [PATCH 077/256] scsi: ibmvscsis: Synchronize cmds at tpg_enable_store time This patch changes the way the IBM vSCSI server driver manages its Command/Response Queue (CRQ). We used to register the CRQ with phyp at probe time. Now we wait until tpg_enable_store. Similarly, when tpg_enable_store is called to "disable" (i.e. the stored value is 0), we unregister the queue with phyp. One consquence to this is that we have no need for the PART_UP_WAIT_ENAB state, since we can't get an Init Message from the client in our CRQ if we're waiting to be enabled, since we haven't registered the queue yet. Signed-off-by: Michael Cyr Signed-off-by: Bryant G. Ly Tested-by: Steven Royer Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 226 ++++------------------- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h | 2 - 2 files changed, 39 insertions(+), 189 deletions(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 01a430cc15e4..2ce1d73033b2 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -61,8 +61,6 @@ static long ibmvscsis_parse_command(struct scsi_info *vscsi, static void ibmvscsis_adapter_idle(struct scsi_info *vscsi); -static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state); - static void ibmvscsis_determine_resid(struct se_cmd *se_cmd, struct srp_rsp *rsp) { @@ -417,7 +415,6 @@ static void ibmvscsis_disconnect(struct work_struct *work) proc_work); u16 new_state; bool wait_idle = false; - long rc = ADAPT_SUCCESS; spin_lock_bh(&vscsi->intr_lock); new_state = vscsi->new_state; @@ -470,30 +467,12 @@ static void ibmvscsis_disconnect(struct work_struct *work) vscsi->state = new_state; break; - /* - * If this is a transition into an error state. - * a client is attempting to establish a connection - * and has violated the RPA protocol. - * There can be nothing pending on the adapter although - * there can be requests in the command queue. - */ case WAIT_ENABLED: - case PART_UP_WAIT_ENAB: switch (new_state) { - case ERR_DISCONNECT: - vscsi->flags |= RESPONSE_Q_DOWN; - vscsi->state = new_state; - vscsi->flags &= ~(SCHEDULE_DISCONNECT | - DISCONNECT_SCHEDULED); - ibmvscsis_free_command_q(vscsi); - break; - case ERR_DISCONNECT_RECONNECT: - ibmvscsis_reset_queue(vscsi, WAIT_ENABLED); - break; - /* should never happen */ + case ERR_DISCONNECT: + case ERR_DISCONNECT_RECONNECT: case WAIT_IDLE: - rc = ERROR; dev_err(&vscsi->dev, "disconnect: invalid state %d for WAIT_IDLE\n", vscsi->state); break; @@ -630,7 +609,6 @@ static void ibmvscsis_post_disconnect(struct scsi_info *vscsi, uint new_state, break; case WAIT_ENABLED: - case PART_UP_WAIT_ENAB: case WAIT_IDLE: case WAIT_CONNECTION: case CONNECTED: @@ -675,7 +653,6 @@ static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi) case SRP_PROCESSING: case CONNECTED: case WAIT_ENABLED: - case PART_UP_WAIT_ENAB: default: rc = ERROR; dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n", @@ -698,10 +675,6 @@ static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi) long rc = ADAPT_SUCCESS; switch (vscsi->state) { - case WAIT_ENABLED: - vscsi->state = PART_UP_WAIT_ENAB; - break; - case WAIT_CONNECTION: rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG); switch (rc) { @@ -737,7 +710,7 @@ static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi) case UNCONFIGURING: break; - case PART_UP_WAIT_ENAB: + case WAIT_ENABLED: case CONNECTED: case SRP_PROCESSING: case WAIT_IDLE: @@ -800,11 +773,10 @@ static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq) /** * ibmvscsis_establish_new_q() - Establish new CRQ queue * @vscsi: Pointer to our adapter structure - * @new_state: New state being established after resetting the queue * * Must be called with interrupt lock held. */ -static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) +static long ibmvscsis_establish_new_q(struct scsi_info *vscsi) { long rc = ADAPT_SUCCESS; uint format; @@ -816,19 +788,19 @@ static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) rc = vio_enable_interrupts(vscsi->dma_dev); if (rc) { - pr_warn("reset_queue: failed to enable interrupts, rc %ld\n", + pr_warn("establish_new_q: failed to enable interrupts, rc %ld\n", rc); return rc; } rc = ibmvscsis_check_init_msg(vscsi, &format); if (rc) { - dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n", + dev_err(&vscsi->dev, "establish_new_q: check_init_msg failed, rc %ld\n", rc); return rc; } - if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) { + if (format == UNUSED_FORMAT) { rc = ibmvscsis_send_init_message(vscsi, INIT_MSG); switch (rc) { case H_SUCCESS: @@ -846,6 +818,8 @@ static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) rc = H_HARDWARE; break; } + } else if (format == INIT_MSG) { + rc = ibmvscsis_handle_init_msg(vscsi); } return rc; @@ -854,7 +828,6 @@ static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) /** * ibmvscsis_reset_queue() - Reset CRQ Queue * @vscsi: Pointer to our adapter structure - * @new_state: New state to establish after resetting the queue * * This function calls h_free_q and then calls h_reg_q and does all * of the bookkeeping to get us back to where we can communicate. @@ -871,7 +844,7 @@ static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state) * EXECUTION ENVIRONMENT: * Process environment, called with interrupt lock held */ -static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state) +static void ibmvscsis_reset_queue(struct scsi_info *vscsi) { int bytes; long rc = ADAPT_SUCCESS; @@ -884,19 +857,18 @@ static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state) vscsi->rsp_q_timer.timer_pops = 0; vscsi->debit = 0; vscsi->credit = 0; - vscsi->state = new_state; + vscsi->state = WAIT_CONNECTION; vio_enable_interrupts(vscsi->dma_dev); } else { rc = ibmvscsis_free_command_q(vscsi); if (rc == ADAPT_SUCCESS) { - vscsi->state = new_state; + vscsi->state = WAIT_CONNECTION; bytes = vscsi->cmd_q.size * PAGE_SIZE; rc = h_reg_crq(vscsi->dds.unit_id, vscsi->cmd_q.crq_token, bytes); if (rc == H_CLOSED || rc == H_SUCCESS) { - rc = ibmvscsis_establish_new_q(vscsi, - new_state); + rc = ibmvscsis_establish_new_q(vscsi); } if (rc != ADAPT_SUCCESS) { @@ -1015,10 +987,6 @@ static long ibmvscsis_trans_event(struct scsi_info *vscsi, TRANS_EVENT)); break; - case PART_UP_WAIT_ENAB: - vscsi->state = WAIT_ENABLED; - break; - case SRP_PROCESSING: if ((vscsi->debit > 0) || !list_empty(&vscsi->schedule_q) || @@ -1219,15 +1187,18 @@ static void ibmvscsis_adapter_idle(struct scsi_info *vscsi) switch (vscsi->state) { case ERR_DISCONNECT_RECONNECT: - ibmvscsis_reset_queue(vscsi, WAIT_CONNECTION); + ibmvscsis_reset_queue(vscsi); pr_debug("adapter_idle, disc_rec: flags 0x%x\n", vscsi->flags); break; case ERR_DISCONNECT: ibmvscsis_free_command_q(vscsi); - vscsi->flags &= ~DISCONNECT_SCHEDULED; + vscsi->flags &= ~(SCHEDULE_DISCONNECT | DISCONNECT_SCHEDULED); vscsi->flags |= RESPONSE_Q_DOWN; - vscsi->state = ERR_DISCONNECTED; + if (vscsi->tport.enabled) + vscsi->state = ERR_DISCONNECTED; + else + vscsi->state = WAIT_ENABLED; pr_debug("adapter_idle, disc: flags 0x%x, state 0x%hx\n", vscsi->flags, vscsi->state); break; @@ -1772,8 +1743,8 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi) be64_to_cpu(msg_hi), be64_to_cpu(cmd->rsp.tag)); - pr_debug("send_messages: tag 0x%llx, rc %ld\n", - be64_to_cpu(cmd->rsp.tag), rc); + pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n", + cmd, be64_to_cpu(cmd->rsp.tag), rc); /* if all ok free up the command element resources */ if (rc == H_SUCCESS) { @@ -2787,36 +2758,6 @@ static irqreturn_t ibmvscsis_interrupt(int dummy, void *data) return IRQ_HANDLED; } -/** - * ibmvscsis_check_q() - Helper function to Check Init Message Valid - * @vscsi: Pointer to our adapter structure - * - * Checks if a initialize message was queued by the initiatior - * while the timing window was open. This function is called from - * probe after the CRQ is created and interrupts are enabled. - * It would only be used by adapters who wait for some event before - * completing the init handshake with the client. For ibmvscsi, this - * event is waiting for the port to be enabled. - * - * EXECUTION ENVIRONMENT: - * Process level only, interrupt lock held - */ -static long ibmvscsis_check_q(struct scsi_info *vscsi) -{ - uint format; - long rc; - - rc = ibmvscsis_check_init_msg(vscsi, &format); - if (rc) - ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0); - else if (format == UNUSED_FORMAT) - vscsi->state = WAIT_ENABLED; - else - vscsi->state = PART_UP_WAIT_ENAB; - - return rc; -} - /** * ibmvscsis_enable_change_state() - Set new state based on enabled status * @vscsi: Pointer to our adapter structure @@ -2828,77 +2769,19 @@ static long ibmvscsis_check_q(struct scsi_info *vscsi) */ static long ibmvscsis_enable_change_state(struct scsi_info *vscsi) { + int bytes; long rc = ADAPT_SUCCESS; -handle_state_change: - switch (vscsi->state) { - case WAIT_ENABLED: - rc = ibmvscsis_send_init_message(vscsi, INIT_MSG); - switch (rc) { - case H_SUCCESS: - case H_DROPPED: - case H_CLOSED: - vscsi->state = WAIT_CONNECTION; - rc = ADAPT_SUCCESS; - break; + bytes = vscsi->cmd_q.size * PAGE_SIZE; + rc = h_reg_crq(vscsi->dds.unit_id, vscsi->cmd_q.crq_token, bytes); + if (rc == H_CLOSED || rc == H_SUCCESS) { + vscsi->state = WAIT_CONNECTION; + rc = ibmvscsis_establish_new_q(vscsi); + } - case H_PARAMETER: - break; - - case H_HARDWARE: - break; - - default: - vscsi->state = UNDEFINED; - rc = H_HARDWARE; - break; - } - break; - case PART_UP_WAIT_ENAB: - rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG); - switch (rc) { - case H_SUCCESS: - vscsi->state = CONNECTED; - rc = ADAPT_SUCCESS; - break; - - case H_DROPPED: - case H_CLOSED: - vscsi->state = WAIT_ENABLED; - goto handle_state_change; - - case H_PARAMETER: - break; - - case H_HARDWARE: - break; - - default: - rc = H_HARDWARE; - break; - } - break; - - case WAIT_CONNECTION: - case WAIT_IDLE: - case SRP_PROCESSING: - case CONNECTED: - rc = ADAPT_SUCCESS; - break; - /* should not be able to get here */ - case UNCONFIGURING: - rc = ERROR; - vscsi->state = UNDEFINED; - break; - - /* driver should never allow this to happen */ - case ERR_DISCONNECT: - case ERR_DISCONNECT_RECONNECT: - default: - dev_err(&vscsi->dev, "in invalid state %d during enable_change_state\n", - vscsi->state); - rc = ADAPT_SUCCESS; - break; + if (rc != ADAPT_SUCCESS) { + vscsi->state = ERR_DISCONNECTED; + vscsi->flags |= RESPONSE_Q_DOWN; } return rc; @@ -2918,7 +2801,6 @@ handle_state_change: */ static long ibmvscsis_create_command_q(struct scsi_info *vscsi, int num_cmds) { - long rc = 0; int pages; struct vio_dev *vdev = vscsi->dma_dev; @@ -2942,22 +2824,7 @@ static long ibmvscsis_create_command_q(struct scsi_info *vscsi, int num_cmds) return -ENOMEM; } - rc = h_reg_crq(vscsi->dds.unit_id, vscsi->cmd_q.crq_token, PAGE_SIZE); - if (rc) { - if (rc == H_CLOSED) { - vscsi->state = WAIT_ENABLED; - rc = 0; - } else { - dma_unmap_single(&vdev->dev, vscsi->cmd_q.crq_token, - PAGE_SIZE, DMA_BIDIRECTIONAL); - free_page((unsigned long)vscsi->cmd_q.base_addr); - rc = -ENODEV; - } - } else { - vscsi->state = WAIT_ENABLED; - } - - return rc; + return 0; } /** @@ -3487,31 +3354,12 @@ static int ibmvscsis_probe(struct vio_dev *vdev, goto destroy_WQ; } - spin_lock_bh(&vscsi->intr_lock); - vio_enable_interrupts(vdev); - if (rc) { - dev_err(&vscsi->dev, "enabling interrupts failed, rc %d\n", rc); - rc = -ENODEV; - spin_unlock_bh(&vscsi->intr_lock); - goto free_irq; - } - - if (ibmvscsis_check_q(vscsi)) { - rc = ERROR; - dev_err(&vscsi->dev, "probe: check_q failed, rc %d\n", rc); - spin_unlock_bh(&vscsi->intr_lock); - goto disable_interrupt; - } - spin_unlock_bh(&vscsi->intr_lock); + vscsi->state = WAIT_ENABLED; dev_set_drvdata(&vdev->dev, vscsi); return 0; -disable_interrupt: - vio_disable_interrupts(vdev); -free_irq: - free_irq(vdev->irq, vscsi); destroy_WQ: destroy_workqueue(vscsi->work_q); unmap_buf: @@ -3905,18 +3753,22 @@ static ssize_t ibmvscsis_tpg_enable_store(struct config_item *item, } if (tmp) { - tport->enabled = true; spin_lock_bh(&vscsi->intr_lock); + tport->enabled = true; lrc = ibmvscsis_enable_change_state(vscsi); if (lrc) pr_err("enable_change_state failed, rc %ld state %d\n", lrc, vscsi->state); spin_unlock_bh(&vscsi->intr_lock); } else { + spin_lock_bh(&vscsi->intr_lock); tport->enabled = false; + /* This simulates the server going down */ + ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0); + spin_unlock_bh(&vscsi->intr_lock); } - pr_debug("tpg_enable_store, state %d\n", vscsi->state); + pr_debug("tpg_enable_store, tmp %ld, state %d\n", tmp, vscsi->state); return count; } diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h index 981a0c992b6c..17e0ef43c525 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h @@ -204,8 +204,6 @@ struct scsi_info { struct list_head waiting_rsp; #define NO_QUEUE 0x00 #define WAIT_ENABLED 0X01 - /* driver has received an initialize command */ -#define PART_UP_WAIT_ENAB 0x02 #define WAIT_CONNECTION 0x04 /* have established a connection */ #define CONNECTED 0x08 From 8bf11557d44d00562360d370de8aa70ba89aa0d5 Mon Sep 17 00:00:00 2001 From: Michael Cyr Date: Thu, 13 Oct 2016 11:02:40 -0500 Subject: [PATCH 078/256] scsi: ibmvscsis: Synchronize cmds at remove time This patch adds code to disconnect from the client, which will make sure any outstanding commands have been completed, before continuing on with the remove operation. Signed-off-by: Michael Cyr Signed-off-by: Bryant G. Ly Tested-by: Steven Royer Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 39 +++++++++++++++++++++--- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h | 3 ++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 2ce1d73033b2..41af435a8943 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -469,6 +469,18 @@ static void ibmvscsis_disconnect(struct work_struct *work) case WAIT_ENABLED: switch (new_state) { + case UNCONFIGURING: + vscsi->state = new_state; + vscsi->flags |= RESPONSE_Q_DOWN; + vscsi->flags &= ~(SCHEDULE_DISCONNECT | + DISCONNECT_SCHEDULED); + dma_rmb(); + if (vscsi->flags & CFG_SLEEPING) { + vscsi->flags &= ~CFG_SLEEPING; + complete(&vscsi->unconfig); + } + break; + /* should never happen */ case ERR_DISCONNECT: case ERR_DISCONNECT_RECONNECT: @@ -481,6 +493,13 @@ static void ibmvscsis_disconnect(struct work_struct *work) case WAIT_IDLE: switch (new_state) { + case UNCONFIGURING: + vscsi->flags |= RESPONSE_Q_DOWN; + vscsi->state = new_state; + vscsi->flags &= ~(SCHEDULE_DISCONNECT | + DISCONNECT_SCHEDULED); + ibmvscsis_free_command_q(vscsi); + break; case ERR_DISCONNECT: case ERR_DISCONNECT_RECONNECT: vscsi->state = new_state; @@ -1186,6 +1205,15 @@ static void ibmvscsis_adapter_idle(struct scsi_info *vscsi) free_qs = true; switch (vscsi->state) { + case UNCONFIGURING: + ibmvscsis_free_command_q(vscsi); + dma_rmb(); + isync(); + if (vscsi->flags & CFG_SLEEPING) { + vscsi->flags &= ~CFG_SLEEPING; + complete(&vscsi->unconfig); + } + break; case ERR_DISCONNECT_RECONNECT: ibmvscsis_reset_queue(vscsi); pr_debug("adapter_idle, disc_rec: flags 0x%x\n", vscsi->flags); @@ -3338,6 +3366,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev, (unsigned long)vscsi); init_completion(&vscsi->wait_idle); + init_completion(&vscsi->unconfig); snprintf(wq_name, 24, "ibmvscsis%s", dev_name(&vdev->dev)); vscsi->work_q = create_workqueue(wq_name); @@ -3393,10 +3422,11 @@ static int ibmvscsis_remove(struct vio_dev *vdev) pr_debug("remove (%s)\n", dev_name(&vscsi->dma_dev->dev)); - /* - * TBD: Need to handle if there are commands on the waiting_rsp q - * Actually, can there still be cmds outstanding to tcm? - */ + spin_lock_bh(&vscsi->intr_lock); + ibmvscsis_post_disconnect(vscsi, UNCONFIGURING, 0); + vscsi->flags |= CFG_SLEEPING; + spin_unlock_bh(&vscsi->intr_lock); + wait_for_completion(&vscsi->unconfig); vio_disable_interrupts(vdev); free_irq(vdev->irq, vscsi); @@ -3405,7 +3435,6 @@ static int ibmvscsis_remove(struct vio_dev *vdev) DMA_BIDIRECTIONAL); kfree(vscsi->map_buf); tasklet_kill(&vscsi->work_task); - ibmvscsis_unregister_command_q(vscsi); ibmvscsis_destroy_command_q(vscsi); ibmvscsis_freetimer(vscsi); ibmvscsis_free_cmds(vscsi); diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h index 17e0ef43c525..98b0ca79a5c5 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h @@ -257,6 +257,8 @@ struct scsi_info { #define SCHEDULE_DISCONNECT 0x00400 /* disconnect handler is scheduled */ #define DISCONNECT_SCHEDULED 0x00800 + /* remove function is sleeping */ +#define CFG_SLEEPING 0x01000 u32 flags; /* adapter lock */ spinlock_t intr_lock; @@ -285,6 +287,7 @@ struct scsi_info { struct workqueue_struct *work_q; struct completion wait_idle; + struct completion unconfig; struct device dev; struct vio_dev *dma_dev; struct srp_target target; From 7435b32e2d2fb5da6c2ae9b9c8ce56d8a3cb3bc3 Mon Sep 17 00:00:00 2001 From: Michael Cyr Date: Thu, 13 Oct 2016 11:02:41 -0500 Subject: [PATCH 079/256] scsi: ibmvscsis: Clean up properly if target_submit_cmd/tmr fails Signed-off-by: Michael Cyr Signed-off-by: Bryant G. Ly Tested-by: Steven Royer Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 41af435a8943..cd9f5c734018 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -2560,6 +2560,10 @@ static void ibmvscsis_parse_cmd(struct scsi_info *vscsi, data_len, attr, dir, 0); if (rc) { dev_err(&vscsi->dev, "target_submit_cmd failed, rc %d\n", rc); + spin_lock_bh(&vscsi->intr_lock); + list_del(&cmd->list); + ibmvscsis_free_cmd_resources(vscsi, cmd); + spin_unlock_bh(&vscsi->intr_lock); goto fail; } return; @@ -2639,6 +2643,9 @@ static void ibmvscsis_parse_task(struct scsi_info *vscsi, if (rc) { dev_err(&vscsi->dev, "target_submit_tmr failed, rc %d\n", rc); + spin_lock_bh(&vscsi->intr_lock); + list_del(&cmd->list); + spin_unlock_bh(&vscsi->intr_lock); cmd->se_cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; } From 9c93cf03d4eb3dc58931ff7cac0af9c344fe5e0b Mon Sep 17 00:00:00 2001 From: Michael Cyr Date: Thu, 13 Oct 2016 11:02:42 -0500 Subject: [PATCH 080/256] scsi: ibmvscsis: Return correct partition name/# to client Signed-off-by: Michael Cyr Signed-off-by: Bryant G. Ly Tested-by: Steven Royer Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index cd9f5c734018..fe220a145079 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -3297,6 +3297,9 @@ static int ibmvscsis_probe(struct vio_dev *vdev, strncat(vscsi->eye, vdev->name, MAX_EYE); vscsi->dds.unit_id = vdev->unit_address; + strncpy(vscsi->dds.partition_name, partition_name, + sizeof(vscsi->dds.partition_name)); + vscsi->dds.partition_num = partition_number; spin_lock_bh(&ibmvscsis_dev_lock); list_add_tail(&vscsi->list, &ibmvscsis_dev_list); @@ -3495,7 +3498,7 @@ static int ibmvscsis_get_system_info(void) num = of_get_property(rootdn, "ibm,partition-no", NULL); if (num) - partition_number = *num; + partition_number = of_read_number(num, 1); of_node_put(rootdn); From 11950d70b52d2bc5e3580da8cd63909ef38d67db Mon Sep 17 00:00:00 2001 From: Michael Cyr Date: Thu, 13 Oct 2016 11:02:43 -0500 Subject: [PATCH 081/256] scsi: ibmvscsis: Issues from Dan Carpenter/Smatch Signed-off-by: Michael Cyr Signed-off-by: Bryant G. Ly Tested-by: Steven Royer Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index fe220a145079..c9fa3565c671 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1896,14 +1896,7 @@ static long ibmvscsis_mad(struct scsi_info *vscsi, struct viosrp_crq *crq) pr_debug("mad: type %d\n", be32_to_cpu(mad->type)); - if (be16_to_cpu(mad->length) < 0) { - dev_err(&vscsi->dev, "mad: length is < 0\n"); - ibmvscsis_post_disconnect(vscsi, - ERR_DISCONNECT_RECONNECT, 0); - rc = SRP_VIOLATION; - } else { - rc = ibmvscsis_process_mad(vscsi, iue); - } + rc = ibmvscsis_process_mad(vscsi, iue); pr_debug("mad: status %hd, rc %ld\n", be16_to_cpu(mad->status), rc); @@ -2523,7 +2516,6 @@ static void ibmvscsis_parse_cmd(struct scsi_info *vscsi, dev_err(&vscsi->dev, "0x%llx: parsing SRP descriptor table failed.\n", srp->tag); goto fail; - return; } cmd->rsp.sol_not = srp->sol_not; @@ -3282,7 +3274,8 @@ static int ibmvscsis_probe(struct vio_dev *vdev, INIT_LIST_HEAD(&vscsi->waiting_rsp); INIT_LIST_HEAD(&vscsi->active_q); - snprintf(vscsi->tport.tport_name, 256, "%s", dev_name(&vdev->dev)); + snprintf(vscsi->tport.tport_name, IBMVSCSIS_NAMELEN, "%s", + dev_name(&vdev->dev)); pr_debug("probe tport_name: %s\n", vscsi->tport.tport_name); From 7ab24dd16579514d261a669aa3b9e19220df5456 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:35 +0200 Subject: [PATCH 082/256] scsi: libfc: Replace ->seq_els_rsp_send callback with function call The 'seq_els_rsp_send' callback only ever had one implementation, so we might as well drop it and use the function directly. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 2 +- drivers/scsi/libfc/fc_disc.c | 4 ++-- drivers/scsi/libfc/fc_exch.c | 8 +++----- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 26 +++++++++++++------------- include/scsi/libfc.h | 10 ++-------- 6 files changed, 24 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 4aacd60f49b3..6cedc5185fee 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -3031,7 +3031,7 @@ static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp) rjt_data.reason = ELS_RJT_UNSUP; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index ad3965f9d03d..4e3115211631 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -154,7 +154,7 @@ static void fc_disc_recv_rscn_req(struct fc_disc *disc, struct fc_frame *fp) break; } } - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); /* * If not doing a complete rediscovery, do GPN_ID on @@ -182,7 +182,7 @@ reject: FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 9921dbbaeaff..3f58aeb8937e 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1222,8 +1222,8 @@ static void fc_exch_set_addr(struct fc_exch *ep, * * The received frame is not freed. */ -static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, - struct fc_seq_els_data *els_data) +void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, + struct fc_seq_els_data *els_data) { switch (els_cmd) { case ELS_LS_RJT: @@ -1242,6 +1242,7 @@ static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, FC_LPORT_DBG(fr_dev(fp), "Invalid ELS CMD:%x\n", els_cmd); } } +EXPORT_SYMBOL_GPL(fc_seq_els_rsp_send); /** * fc_seq_send_last() - Send a sequence that is the last in the exchange @@ -2635,9 +2636,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_send) lport->tt.seq_send = fc_seq_send; - if (!lport->tt.seq_els_rsp_send) - lport->tt.seq_els_rsp_send = fc_seq_els_rsp_send; - if (!lport->tt.exch_done) lport->tt.exch_done = fc_exch_done; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 81ad8ac5a33d..bf79c9bd2a14 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -412,7 +412,7 @@ static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", fc_lport_state(lport)); - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); fc_frame_free(fp); } @@ -481,7 +481,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, if (!req) { rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); } else { fmt = req->rnid_fmt; len = sizeof(*rp); @@ -521,7 +521,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, */ static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) { - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); fc_lport_enter_reset(lport); fc_frame_free(fp); } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a867874ff367..4ca0f40dc0d6 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -967,7 +967,7 @@ out: reject_put: kref_put(&rdata->kref, lport->tt.rport_destroy); reject: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); fc_frame_free(rx_fp); } @@ -1416,7 +1416,7 @@ static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata, if (!fp) { rjt_data.reason = ELS_RJT_UNAB; rjt_data.reason = ELS_EXPL_INSUF_RES; - lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); goto drop; } rtv = fc_frame_payload_get(fp, sizeof(*rtv)); @@ -1591,7 +1591,7 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, if (!adisc) { rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; - lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); goto drop; } @@ -1667,7 +1667,7 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, goto out; out_rjt: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); out: fc_frame_free(rx_fp); } @@ -1734,11 +1734,11 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) fc_rport_recv_adisc_req(rdata, fp); break; case ELS_RRQ: - lport->tt.seq_els_rsp_send(fp, ELS_RRQ, NULL); + fc_seq_els_rsp_send(fp, ELS_RRQ, NULL); fc_frame_free(fp); break; case ELS_REC: - lport->tt.seq_els_rsp_send(fp, ELS_REC, NULL); + fc_seq_els_rsp_send(fp, ELS_REC, NULL); fc_frame_free(fp); break; case ELS_RLS: @@ -1759,14 +1759,14 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) reject: els_data.reason = ELS_RJT_UNAB; els_data.explan = ELS_EXPL_PLOGI_REQD; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); return; busy: els_data.reason = ELS_RJT_BUSY; els_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); return; } @@ -1812,7 +1812,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) default: els_data.reason = ELS_RJT_UNSUP; els_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); break; } @@ -1939,7 +1939,7 @@ out: return; reject: - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } @@ -2055,7 +2055,7 @@ reject_len: rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; reject: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); drop: fc_frame_free(rx_fp); } @@ -2126,7 +2126,7 @@ reject_len: rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; reject: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); drop: fc_frame_free(rx_fp); } @@ -2146,7 +2146,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) struct fc_rport_priv *rdata; u32 sid; - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); sid = fc_frame_sid(fp); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index f5aa54b40e75..0e9580311e60 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -552,14 +552,6 @@ struct libfc_function_template { int (*seq_send)(struct fc_lport *, struct fc_seq *, struct fc_frame *); - /* - * Send an ELS response using information from the received frame. - * - * STATUS: OPTIONAL - */ - void (*seq_els_rsp_send)(struct fc_frame *, enum fc_els_cmd, - struct fc_seq_els_data *); - /* * Abort an exchange and sequence. Generally called because of a * exchange timeout or an abort from the upper layer. @@ -1138,6 +1130,8 @@ void fc_fill_hdr(struct fc_frame *, const struct fc_frame *, *****************************/ int fc_exch_init(struct fc_lport *); void fc_exch_update_stats(struct fc_lport *lport); +void fc_seq_els_rsp_send(struct fc_frame *, enum fc_els_cmd, + struct fc_seq_els_data *); struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, struct fc_exch_mgr *, bool (*match)(struct fc_frame *)); From 31c0a631a430b01e05ff1e35f287fb8dfa0ef519 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:36 +0200 Subject: [PATCH 083/256] scsi: libfc: Replace ->lport_reset callback with function call The ->lport_reset callback only ever had one implementation, which already is exported. So remove it and use the function directly. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_scsi.c | 2 +- drivers/scsi/libfc/fc_fcp.c | 2 +- drivers/scsi/libfc/fc_lport.c | 3 --- include/scsi/libfc.h | 7 ------- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index d9fd2f841585..bfaba069937f 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -2543,7 +2543,7 @@ int fnic_reset(struct Scsi_Host *shost) * Reset local port, this will clean up libFC exchanges, * reset remote port sessions, and if link is up, begin flogi */ - ret = lp->tt.lport_reset(lp); + ret = fc_lport_reset(lp); FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "Returning from fnic reset %s\n", diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index c033946875a7..831de3eada9c 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2224,7 +2224,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) fc_block_scsi_eh(sc_cmd); - lport->tt.lport_reset(lport); + fc_lport_reset(lport); wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT; while (!fc_fcp_lport_queue_ready(lport) && time_before(jiffies, wait_tmo)) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index bf79c9bd2a14..05f83a65cc1e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1868,9 +1868,6 @@ int fc_lport_init(struct fc_lport *lport) if (!lport->tt.lport_recv) lport->tt.lport_recv = fc_lport_recv_req; - if (!lport->tt.lport_reset) - lport->tt.lport_reset = fc_lport_reset; - fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; fc_host_node_name(lport->host) = lport->wwnn; fc_host_port_name(lport->host) = lport->wwpn; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 0e9580311e60..7ee0d2741192 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -627,13 +627,6 @@ struct libfc_function_template { */ void (*lport_recv)(struct fc_lport *, struct fc_frame *); - /* - * Reset the local port. - * - * STATUS: OPTIONAL - */ - int (*lport_reset)(struct fc_lport *); - /* * Set the local port FC_ID. * From c5cb444c31d1577d2dd207101ba9cf498e1c2d48 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:37 +0200 Subject: [PATCH 084/256] scsi: libfc: Replace ->lport_recv with function call The ->lport_recv callback only ever had one implementation, so call the function directly and remove the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 9 +++------ include/scsi/libfc.h | 8 +------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 3f58aeb8937e..cc320a91b7b7 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1527,7 +1527,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, * The upper-level protocol may request one later, if needed. */ if (fh->fh_rx_id == htons(FC_XID_UNKNOWN)) - return lport->tt.lport_recv(lport, fp); + return fc_lport_recv(lport, fp); reject = fc_seq_lookup_recip(lport, mp, fp); if (reject == FC_RJT_NONE) { @@ -1548,7 +1548,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, * first. */ if (!fc_invoke_resp(ep, sp, fp)) - lport->tt.lport_recv(lport, fp); + fc_lport_recv(lport, fp); fc_exch_release(ep); /* release from lookup */ } else { FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 05f83a65cc1e..42dcb722172b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -944,15 +944,14 @@ struct fc4_prov fc_lport_els_prov = { }; /** - * fc_lport_recv_req() - The generic lport request handler + * fc_lport_recv() - The generic lport request handler * @lport: The lport that received the request * @fp: The frame the request is in * * Locking Note: This function should not be called with the lport * lock held because it may grab the lock. */ -static void fc_lport_recv_req(struct fc_lport *lport, - struct fc_frame *fp) +void fc_lport_recv(struct fc_lport *lport, struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_seq *sp = fr_seq(fp); @@ -983,6 +982,7 @@ drop: if (sp) lport->tt.exch_done(sp); } +EXPORT_SYMBOL(fc_lport_recv); /** * fc_lport_reset() - Reset a local port @@ -1865,9 +1865,6 @@ EXPORT_SYMBOL(fc_lport_config); */ int fc_lport_init(struct fc_lport *lport) { - if (!lport->tt.lport_recv) - lport->tt.lport_recv = fc_lport_recv_req; - fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; fc_host_node_name(lport->host) = lport->wwnn; fc_host_port_name(lport->host) = lport->wwpn; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 7ee0d2741192..7bba81ebb0e7 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -620,13 +620,6 @@ struct libfc_function_template { */ void (*rport_flush_queue)(void); - /* - * Receive a frame for a local port. - * - * STATUS: OPTIONAL - */ - void (*lport_recv)(struct fc_lport *, struct fc_frame *); - /* * Set the local port FC_ID. * @@ -1060,6 +1053,7 @@ void fc_vport_setlink(struct fc_lport *); void fc_vports_linkchange(struct fc_lport *); int fc_lport_config(struct fc_lport *); int fc_lport_reset(struct fc_lport *); +void fc_lport_recv(struct fc_lport *lport, struct fc_frame *fp); int fc_set_mfs(struct fc_lport *, u32 mfs); struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); From 3afd2d1521951cb05ef5279b71634cc55ace688b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:38 +0200 Subject: [PATCH 085/256] scsi: libfc: Replace ->exch_seq_send callback with function call The ->exch_seq_send callback only ever had one implementation, so we can call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_elsct.c | 2 +- drivers/scsi/libfc/fc_exch.c | 37 ++++++++++++++++++++++++---------- drivers/scsi/libfc/fc_fcp.c | 11 +++++----- drivers/scsi/libfc/fc_lport.c | 8 ++++---- drivers/scsi/libfc/fc_rport.c | 4 ++-- include/scsi/libfc.h | 38 +++++++---------------------------- 6 files changed, 45 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index c2384d501470..6384a98048af 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -67,7 +67,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, FC_FCTL_REQ, 0); - return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); + return fc_exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); } EXPORT_SYMBOL(fc_elsct_send); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index cc320a91b7b7..f5c3c1d09651 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2127,6 +2127,24 @@ cleanup: * @arg: The argument to be passed to the response handler * @timer_msec: The timeout period for the exchange * + * The exchange response handler is set in this routine to resp() + * function pointer. It can be called in two scenarios: if a timeout + * occurs or if a response frame is received for the exchange. The + * fc_frame pointer in response handler will also indicate timeout + * as error using IS_ERR related macros. + * + * The exchange destructor handler is also set in this routine. + * The destructor handler is invoked by EM layer when exchange + * is about to free, this can be used by caller to free its + * resources along with exchange free. + * + * The arg is passed back to resp and destructor handler. + * + * The timeout value (in msec) for an exchange is set if non zero + * timer_msec argument is specified. The timer is canceled when + * it fires or when the exchange is done. The exchange timeout handler + * is registered by EM layer. + * * The frame pointer with some of the header's fields must be * filled before calling this routine, those fields are: * @@ -2137,14 +2155,13 @@ cleanup: * - frame control * - parameter or relative offset */ -static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, - struct fc_frame *fp, - void (*resp)(struct fc_seq *, - struct fc_frame *fp, - void *arg), - void (*destructor)(struct fc_seq *, - void *), - void *arg, u32 timer_msec) +struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, + struct fc_frame *fp, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void (*destructor)(struct fc_seq *, void *), + void *arg, u32 timer_msec) { struct fc_exch *ep; struct fc_seq *sp = NULL; @@ -2197,6 +2214,7 @@ err: fc_exch_delete(ep); return NULL; } +EXPORT_SYMBOL(fc_exch_seq_send); /** * fc_exch_rrq() - Send an ELS RRQ (Reinstate Recovery Qualifier) command @@ -2630,9 +2648,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.exch_seq_send) - lport->tt.exch_seq_send = fc_exch_seq_send; - if (!lport->tt.seq_send) lport->tt.seq_send = fc_seq_send; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 831de3eada9c..5cf1d2e3b575 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -196,7 +196,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) * @seq: The sequence that the FCP packet is on (required by destructor API) * @fsp: The FCP packet to be released * - * This routine is called by a destructor callback in the exch_seq_send() + * This routine is called by a destructor callback in the fc_exch_seq_send() * routine of the libfc Transport Template. The 'struct fc_seq' is a required * argument even though it is not used by this routine. * @@ -1206,8 +1206,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); - seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, - fsp, 0); + seq = fc_exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, fsp, 0); if (!seq) { rc = -1; goto unlock; @@ -1757,9 +1756,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); - seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, - fc_fcp_pkt_destroy, - fsp, get_fsp_rec_tov(fsp)); + seq = fc_exch_seq_send(lport, fp, fc_fcp_srr_resp, + fc_fcp_pkt_destroy, + fsp, get_fsp_rec_tov(fsp)); if (!seq) goto retry; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 42dcb722172b..1a4f17617260 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2006,8 +2006,8 @@ static int fc_lport_els_request(struct fc_bsg_job *job, info->nents = job->reply_payload.sg_cnt; info->sg = job->reply_payload.sg_list; - if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, - NULL, info, tov)) { + if (!fc_exch_seq_send(lport, fp, fc_lport_bsg_resp, + NULL, info, tov)) { kfree(info); return -ECOMM; } @@ -2067,8 +2067,8 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, info->nents = job->reply_payload.sg_cnt; info->sg = job->reply_payload.sg_list; - if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, - NULL, info, tov)) { + if (!fc_exch_seq_send(lport, fp, fc_lport_bsg_resp, + NULL, info, tov)) { kfree(info); return -ECOMM; } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4ca0f40dc0d6..d275df04f03a 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1282,8 +1282,8 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); kref_get(&rdata->kref); - if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, - NULL, rdata, 2 * lport->r_a_tov)) { + if (!fc_exch_seq_send(lport, fp, fc_rport_prli_resp, + NULL, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 7bba81ebb0e7..5e8a2083dbf0 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -484,37 +484,6 @@ struct libfc_function_template { struct fc_frame *, void *arg), void *arg, u32 timer_msec); - /* - * Send the FC frame payload using a new exchange and sequence. - * - * The exchange response handler is set in this routine to resp() - * function pointer. It can be called in two scenarios: if a timeout - * occurs or if a response frame is received for the exchange. The - * fc_frame pointer in response handler will also indicate timeout - * as error using IS_ERR related macros. - * - * The exchange destructor handler is also set in this routine. - * The destructor handler is invoked by EM layer when exchange - * is about to free, this can be used by caller to free its - * resources along with exchange free. - * - * The arg is passed back to resp and destructor handler. - * - * The timeout value (in msec) for an exchange is set if non zero - * timer_msec argument is specified. The timer is canceled when - * it fires or when the exchange is done. The exchange timeout handler - * is registered by EM layer. - * - * STATUS: OPTIONAL - */ - struct fc_seq *(*exch_seq_send)(struct fc_lport *, struct fc_frame *, - void (*resp)(struct fc_seq *, - struct fc_frame *, - void *), - void (*destructor)(struct fc_seq *, - void *), - void *, unsigned int timer_msec); - /* * Sets up the DDP context for a given exchange id on the given * scatterlist if LLD supports DDP for large receive. @@ -1117,6 +1086,13 @@ void fc_fill_hdr(struct fc_frame *, const struct fc_frame *, *****************************/ int fc_exch_init(struct fc_lport *); void fc_exch_update_stats(struct fc_lport *lport); +struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, + struct fc_frame *fp, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void (*destructor)(struct fc_seq *, void *), + void *arg, u32 timer_msec); void fc_seq_els_rsp_send(struct fc_frame *, enum fc_els_cmd, struct fc_seq_els_data *); struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, From 944ef9689d8affc13d16c09ac2dba56c5b4c5ff7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:39 +0200 Subject: [PATCH 086/256] scsi: libfc: Replace ->rport_destroy callback with function call The ->rport_destroy callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 12 +++---- drivers/scsi/libfc/fc_disc.c | 6 ++-- drivers/scsi/libfc/fc_lport.c | 6 ++-- drivers/scsi/libfc/fc_rport.c | 68 ++++++++++++++++------------------- include/scsi/libfc.h | 7 +--- 5 files changed, 43 insertions(+), 56 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 6cedc5185fee..4fc7677feb50 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2180,7 +2180,7 @@ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { lport->tt.rport_logoff(rdata); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } rcu_read_unlock(); @@ -2566,7 +2566,7 @@ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac) frport = fcoe_ctlr_rport(rdata); memcpy(mac, frport->enode_mac, ETH_ALEN); ret = 0; - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } return ret; } @@ -2678,7 +2678,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, } frport->time = jiffies; } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; } if (fip->state != FIP_ST_VNMP_UP) @@ -2719,7 +2719,7 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) continue; frport = fcoe_ctlr_rport(rdata); if (!frport->time) { - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); continue; } deadline = frport->time + @@ -2732,7 +2732,7 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) lport->tt.rport_logoff(rdata); } else if (time_before(deadline, next_time)) next_time = deadline; - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } rcu_read_unlock(); return next_time; @@ -3089,7 +3089,7 @@ static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip) frport = fcoe_ctlr_rport(rdata); if (frport->time) lport->tt.rport_login(rdata); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } rcu_read_unlock(); if (callback) diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 4e3115211631..e5ffeab9f670 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -72,7 +72,7 @@ static void fc_disc_stop_rports(struct fc_disc *disc) list_for_each_entry_rcu(rdata, &disc->rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { lport->tt.rport_logoff(rdata); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } rcu_read_unlock(); @@ -303,7 +303,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) else lport->tt.rport_logoff(rdata); } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } rcu_read_unlock(); mutex_unlock(&disc->disc_mutex); @@ -649,7 +649,7 @@ redisc: mutex_unlock(&disc->disc_mutex); } out: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 1a4f17617260..ad45808c4833 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -247,7 +247,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, { if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); - kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); + kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); } mutex_lock(&lport->disc.disc_mutex); lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); @@ -1017,7 +1017,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport) if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); - kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); + kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); lport->ptp_rdata = NULL; } @@ -2129,7 +2129,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) if (!rdata) break; tov = rdata->e_d_tov; - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } rc = fc_lport_ct_request(job, lport, did, tov); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index d275df04f03a..47ab9625246b 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -176,13 +176,14 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, * fc_rport_destroy() - Free a remote port after last reference is released * @kref: The remote port's kref */ -static void fc_rport_destroy(struct kref *kref) +void fc_rport_destroy(struct kref *kref) { struct fc_rport_priv *rdata; rdata = container_of(kref, struct fc_rport_priv, kref); kfree_rcu(rdata, rcu); } +EXPORT_SYMBOL(fc_rport_destroy); /** * fc_rport_state() - Return a string identifying the remote port's state @@ -294,7 +295,7 @@ static void fc_rport_work(struct work_struct *work) if (!rport) { FC_RPORT_DBG(rdata, "Failed to add the rport\n"); lport->tt.rport_logoff(rdata); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; } mutex_lock(&rdata->rp_mutex); @@ -320,7 +321,7 @@ static void fc_rport_work(struct work_struct *work) FC_RPORT_DBG(rdata, "lld callback ev %d\n", event); rdata->lld_event_callback(lport, rdata, event); } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); break; case RPORT_EV_FAILED: @@ -347,7 +348,7 @@ static void fc_rport_work(struct work_struct *work) rdata->lld_event_callback(lport, rdata, event); } if (cancel_delayed_work_sync(&rdata->retry_work)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); /* * Reset any outstanding exchanges before freeing rport. @@ -369,7 +370,7 @@ static void fc_rport_work(struct work_struct *work) if (port_id == FC_FID_DIR_SERV) { rdata->event = RPORT_EV_NONE; mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } else if ((rdata->flags & FC_RP_STARTED) && rdata->major_retries < lport->max_rport_retry_count) { @@ -384,7 +385,7 @@ static void fc_rport_work(struct work_struct *work) list_del_rcu(&rdata->peers); mutex_unlock(&lport->disc.disc_mutex); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } else { /* @@ -403,7 +404,7 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); break; } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -470,8 +471,6 @@ static int fc_rport_login(struct fc_rport_priv *rdata) static void fc_rport_enter_delete(struct fc_rport_priv *rdata, enum fc_rport_event event) { - struct fc_lport *lport = rdata->local_port; - if (rdata->rp_state == RPORT_ST_DELETE) return; @@ -482,7 +481,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, kref_get(&rdata->kref); if (rdata->event == RPORT_EV_NONE && !queue_work(rport_event_queue, &rdata->event_work)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); rdata->event = event; } @@ -541,8 +540,6 @@ out: */ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) { - struct fc_lport *lport = rdata->local_port; - fc_rport_state_enter(rdata, RPORT_ST_READY); FC_RPORT_DBG(rdata, "Port is Ready\n"); @@ -550,7 +547,7 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) kref_get(&rdata->kref); if (rdata->event == RPORT_EV_NONE && !queue_work(rport_event_queue, &rdata->event_work)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); rdata->event = RPORT_EV_READY; } @@ -569,7 +566,6 @@ static void fc_rport_timeout(struct work_struct *work) { struct fc_rport_priv *rdata = container_of(work, struct fc_rport_priv, retry_work.work); - struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata)); @@ -598,7 +594,7 @@ static void fc_rport_timeout(struct work_struct *work) } mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -661,7 +657,6 @@ static void fc_rport_error(struct fc_rport_priv *rdata, int err) static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err) { unsigned long delay = msecs_to_jiffies(rdata->e_d_tov); - struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ if (err == -FC_EX_CLOSED) @@ -676,7 +671,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err) delay = 0; kref_get(&rdata->kref); if (!schedule_delayed_work(&rdata->retry_work, delay)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; } @@ -802,7 +797,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; bad: FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); @@ -841,7 +836,7 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) fc_rport_flogi_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -960,12 +955,12 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, } out: mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); fc_frame_free(rx_fp); return; reject_put: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); reject: fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); fc_frame_free(rx_fp); @@ -1042,7 +1037,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } static bool @@ -1098,7 +1093,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) fc_rport_plogi_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1218,7 +1213,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1285,7 +1280,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) if (!fc_exch_seq_send(lport, fp, fc_rport_prli_resp, NULL, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1358,7 +1353,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1391,7 +1386,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) fc_rport_rtv_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1446,7 +1441,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, "Received a LOGO %s\n", fc_els_resp_type(fp)); if (!IS_ERR(fp)) fc_frame_free(fp); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1472,7 +1467,7 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, fc_rport_logo_resp, rdata, 0)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1534,7 +1529,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1566,7 +1561,7 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) fc_rport_adisc_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1711,7 +1706,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) "while in state %s\n", fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); goto busy; } default: @@ -1719,7 +1714,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) "Reject ELS 0x%02x while in state %s\n", fc_frame_payload_op(fp), fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); goto reject; } @@ -1753,7 +1748,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) } mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; reject: @@ -2158,7 +2153,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) fc_rport_enter_delete(rdata, RPORT_EV_STOP); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } else FC_RPORT_ID_DBG(lport, sid, "Received LOGO from non-logged-in port\n"); @@ -2197,9 +2192,6 @@ int fc_rport_init(struct fc_lport *lport) if (!lport->tt.rport_flush_queue) lport->tt.rport_flush_queue = fc_rport_flush_queue; - if (!lport->tt.rport_destroy) - lport->tt.rport_destroy = fc_rport_destroy; - return 0; } EXPORT_SYMBOL(fc_rport_init); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 5e8a2083dbf0..cec450f2db7b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -651,12 +651,6 @@ struct libfc_function_template { */ struct fc_rport_priv *(*rport_lookup)(const struct fc_lport *, u32); - /* - * Destroy an rport after final kref_put(). - * The argument is a pointer to the kref inside the fc_rport_priv. - */ - void (*rport_destroy)(struct kref *); - /* * Callback routine after the remote port is logged in * @@ -1035,6 +1029,7 @@ void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); *****************************/ int fc_rport_init(struct fc_lport *); void fc_rport_terminate_io(struct fc_rport *); +void fc_rport_destroy(struct kref *kref); /* * DISCOVERY LAYER From e87b77779381ca148006da1d5f541df52ff6a445 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:40 +0200 Subject: [PATCH 087/256] scsi: libfc: Replace ->rport_lookup callback with function call The ->rport_lookup callback only ever had a single implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 16 +++++++--------- include/scsi/libfc.h | 9 ++------- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 4fc7677feb50..bae4e5a4f0ec 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2561,7 +2561,7 @@ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac) struct fcoe_rport *frport; int ret = -1; - rdata = lport->tt.rport_lookup(lport, port_id); + rdata = fc_rport_lookup(lport, port_id); if (rdata) { frport = fcoe_ctlr_rport(rdata); memcpy(mac, frport->enode_mac, ETH_ALEN); @@ -2663,7 +2663,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); return; } - rdata = lport->tt.rport_lookup(lport, new->ids.port_id); + rdata = fc_rport_lookup(lport, new->ids.port_id); if (rdata) { if (rdata->ids.node_name == new->ids.node_name && rdata->ids.port_name == new->ids.port_name) { diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index ad45808c4833..2da6c7c6544d 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2125,7 +2125,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; tov = rdata->e_d_tov; } else { - rdata = lport->tt.rport_lookup(lport, did); + rdata = fc_rport_lookup(lport, did); if (!rdata) break; tov = rdata->e_d_tov; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 47ab9625246b..5f674fc8412f 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -111,8 +111,8 @@ static const char *fc_rport_state_names[] = { * The reference count of the fc_rport_priv structure is * increased by one. */ -static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, - u32 port_id) +struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, + u32 port_id) { struct fc_rport_priv *rdata = NULL, *tmp_rdata; @@ -126,6 +126,7 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, rcu_read_unlock(); return rdata; } +EXPORT_SYMBOL(fc_rport_lookup); /** * fc_rport_create() - Create a new remote port @@ -141,7 +142,7 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, { struct fc_rport_priv *rdata; - rdata = lport->tt.rport_lookup(lport, port_id); + rdata = fc_rport_lookup(lport, port_id); if (rdata) return rdata; @@ -875,7 +876,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, goto reject; } - rdata = lport->tt.rport_lookup(lport, sid); + rdata = fc_rport_lookup(lport, sid); if (!rdata) { rjt_data.reason = ELS_RJT_FIP; rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR; @@ -1684,7 +1685,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) struct fc_rport_priv *rdata; struct fc_seq_els_data els_data; - rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); + rdata = fc_rport_lookup(lport, fc_frame_sid(fp)); if (!rdata) { FC_RPORT_ID_DBG(lport, fc_frame_sid(fp), "Received ELS 0x%02x from non-logged-in port\n", @@ -2145,7 +2146,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) sid = fc_frame_sid(fp); - rdata = lport->tt.rport_lookup(lport, sid); + rdata = fc_rport_lookup(lport, sid); if (rdata) { mutex_lock(&rdata->rp_mutex); FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", @@ -2174,9 +2175,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_lookup) - lport->tt.rport_lookup = fc_rport_lookup; - if (!lport->tt.rport_create) lport->tt.rport_create = fc_rport_create; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index cec450f2db7b..683201f23500 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -644,13 +644,6 @@ struct libfc_function_template { */ void (*rport_recv_req)(struct fc_lport *, struct fc_frame *); - /* - * lookup an rport by it's port ID. - * - * STATUS: OPTIONAL - */ - struct fc_rport_priv *(*rport_lookup)(const struct fc_lport *, u32); - /* * Callback routine after the remote port is logged in * @@ -1029,6 +1022,8 @@ void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); *****************************/ int fc_rport_init(struct fc_lport *); void fc_rport_terminate_io(struct fc_rport *); +struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, + u32 port_id); void fc_rport_destroy(struct kref *kref); /* From 558b88fe6dd88a16563a4d72b674947b8130a550 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:41 +0200 Subject: [PATCH 088/256] scsi: scsi_transport_fc: rename 'fc_rport_create' to 'fc_remote_port_create' Required for the next patch. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 0f3a3869524b..45340857f240 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2592,7 +2592,7 @@ fc_rport_final_delete(struct work_struct *work) /** - * fc_rport_create - allocates and creates a remote FC port. + * fc_remote_port_create - allocates and creates a remote FC port. * @shost: scsi host the remote port is connected to. * @channel: Channel on shost port connected to. * @ids: The world wide names, fc address, and FC4 port @@ -2605,8 +2605,8 @@ fc_rport_final_delete(struct work_struct *work) * This routine assumes no locks are held on entry. */ static struct fc_rport * -fc_rport_create(struct Scsi_Host *shost, int channel, - struct fc_rport_identifiers *ids) +fc_remote_port_create(struct Scsi_Host *shost, int channel, + struct fc_rport_identifiers *ids) { struct fc_host_attrs *fc_host = shost_to_fc_host(shost); struct fc_internal *fci = to_fc_internal(shost->transportt); @@ -2914,7 +2914,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, spin_unlock_irqrestore(shost->host_lock, flags); /* No consistent binding found - create new remote port entry */ - rport = fc_rport_create(shost, channel, ids); + rport = fc_remote_port_create(shost, channel, ids); return rport; } From 2580064b5ec6dc9efa475298b276ab21f5cc287d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:42 +0200 Subject: [PATCH 089/256] scsi: libfc: Replace ->rport_create callback with function call The ->rport_create callback only ever had a single implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 2 +- drivers/scsi/libfc/fc_disc.c | 7 +++---- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 9 +++------ include/scsi/libfc.h | 8 +------- 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index bae4e5a4f0ec..38e67797fc72 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2515,7 +2515,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) return; mutex_lock(&lport->disc.disc_mutex); - rdata = lport->tt.rport_create(lport, port_id); + rdata = fc_rport_create(lport, port_id); if (!rdata) { mutex_unlock(&lport->disc.disc_mutex); return; diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index e5ffeab9f670..305dd8541963 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -454,7 +454,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) if (ids.port_id != lport->port_id && ids.port_name != lport->wwpn) { - rdata = lport->tt.rport_create(lport, ids.port_id); + rdata = fc_rport_create(lport, ids.port_id); if (rdata) { rdata->ids.port_name = ids.port_name; rdata->disc_id = disc->disc_id; @@ -624,8 +624,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_unlock(&rdata->rp_mutex); lport->tt.rport_logoff(rdata); mutex_lock(&lport->disc.disc_mutex); - new_rdata = lport->tt.rport_create(lport, - rdata->ids.port_id); + new_rdata = fc_rport_create(lport, rdata->ids.port_id); mutex_unlock(&lport->disc.disc_mutex); if (new_rdata) { new_rdata->disc_id = disc->disc_id; @@ -690,7 +689,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp) { struct fc_rport_priv *rdata; - rdata = lport->tt.rport_create(lport, dp->port_id); + rdata = fc_rport_create(lport, dp->port_id); if (!rdata) return -ENOMEM; rdata->disc_id = 0; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2da6c7c6544d..a16936a833f8 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -250,7 +250,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); } mutex_lock(&lport->disc.disc_mutex); - lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); + lport->ptp_rdata = fc_rport_create(lport, remote_fid); kref_get(&lport->ptp_rdata->kref); lport->ptp_rdata->ids.port_name = remote_wwpn; lport->ptp_rdata->ids.node_name = remote_wwnn; @@ -1431,7 +1431,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_DNS); mutex_lock(&lport->disc.disc_mutex); - rdata = lport->tt.rport_create(lport, FC_FID_DIR_SERV); + rdata = fc_rport_create(lport, FC_FID_DIR_SERV); mutex_unlock(&lport->disc.disc_mutex); if (!rdata) goto err; @@ -1548,7 +1548,7 @@ static void fc_lport_enter_fdmi(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_FDMI); mutex_lock(&lport->disc.disc_mutex); - rdata = lport->tt.rport_create(lport, FC_FID_MGMT_SERV); + rdata = fc_rport_create(lport, FC_FID_MGMT_SERV); mutex_unlock(&lport->disc.disc_mutex); if (!rdata) goto err; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 5f674fc8412f..b05fa9997db5 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -137,8 +137,7 @@ EXPORT_SYMBOL(fc_rport_lookup); * * Locking note: must be called with the disc_mutex held. */ -static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, - u32 port_id) +struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id) { struct fc_rport_priv *rdata; @@ -172,6 +171,7 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, } return rdata; } +EXPORT_SYMBOL(fc_rport_create); /** * fc_rport_destroy() - Free a remote port after last reference is released @@ -1847,7 +1847,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, disc = &lport->disc; mutex_lock(&disc->disc_mutex); - rdata = lport->tt.rport_create(lport, sid); + rdata = fc_rport_create(lport, sid); if (!rdata) { mutex_unlock(&disc->disc_mutex); rjt_data.reason = ELS_RJT_UNAB; @@ -2175,9 +2175,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_create) - lport->tt.rport_create = fc_rport_create; - if (!lport->tt.rport_login) lport->tt.rport_login = fc_rport_login; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 683201f23500..47b69d26be99 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -609,13 +609,6 @@ struct libfc_function_template { void (*lport_set_port_id)(struct fc_lport *, u32 port_id, struct fc_frame *); - /* - * Create a remote port with a given port ID - * - * STATUS: OPTIONAL - */ - struct fc_rport_priv *(*rport_create)(struct fc_lport *, u32); - /* * Initiates the RP state machine. It is called from the LP module. * This function will issue the following commands to the N_Port @@ -1024,6 +1017,7 @@ int fc_rport_init(struct fc_lport *); void fc_rport_terminate_io(struct fc_rport *); struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, u32 port_id); +struct fc_rport_priv *fc_rport_create(struct fc_lport *, u32); void fc_rport_destroy(struct kref *kref); /* From 05d7d3b0bd07e3990ab7a39ee93be28dbf7091d4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:43 +0200 Subject: [PATCH 090/256] scsi: libfc: Replace ->rport_login callback with function call The ->rport_login callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 4 ++-- drivers/scsi/libfc/fc_disc.c | 6 +++--- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 14 ++++++++++---- include/scsi/libfc.h | 14 +------------- 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 38e67797fc72..ff0eca31cebe 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2674,7 +2674,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, LIBFCOE_FIP_DBG(fip, "beacon expired " "for rport %x\n", rdata->ids.port_id); - lport->tt.rport_login(rdata); + fc_rport_login(rdata); } frport->time = jiffies; } @@ -3088,7 +3088,7 @@ static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip) continue; frport = fcoe_ctlr_rport(rdata); if (frport->time) - lport->tt.rport_login(rdata); + fc_rport_login(rdata); kref_put(&rdata->kref, fc_rport_destroy); } rcu_read_unlock(); diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 305dd8541963..8d0aa19b1f5b 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -299,7 +299,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) continue; if (rdata->disc_id) { if (rdata->disc_id == disc->disc_id) - lport->tt.rport_login(rdata); + fc_rport_login(rdata); else lport->tt.rport_logoff(rdata); } @@ -628,13 +628,13 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_unlock(&lport->disc.disc_mutex); if (new_rdata) { new_rdata->disc_id = disc->disc_id; - lport->tt.rport_login(new_rdata); + fc_rport_login(new_rdata); } goto out; } rdata->disc_id = disc->disc_id; mutex_unlock(&rdata->rp_mutex); - lport->tt.rport_login(rdata); + fc_rport_login(rdata); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n", cp->ct_reason, cp->ct_explan); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a16936a833f8..e20c1519be15 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -256,7 +256,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, lport->ptp_rdata->ids.node_name = remote_wwnn; mutex_unlock(&lport->disc.disc_mutex); - lport->tt.rport_login(lport->ptp_rdata); + fc_rport_login(lport->ptp_rdata); fc_lport_enter_ready(lport); } @@ -1437,7 +1437,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) goto err; rdata->ops = &fc_lport_rport_ops; - lport->tt.rport_login(rdata); + fc_rport_login(rdata); return; err: @@ -1554,7 +1554,7 @@ static void fc_lport_enter_fdmi(struct fc_lport *lport) goto err; rdata->ops = &fc_lport_rport_ops; - lport->tt.rport_login(rdata); + fc_rport_login(rdata); return; err: diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index b05fa9997db5..c045bc459910 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -412,6 +412,14 @@ static void fc_rport_work(struct work_struct *work) * fc_rport_login() - Start the remote port login state machine * @rdata: The remote port to be logged in to * + * Initiates the RP state machine. It is called from the LP module. + * This function will issue the following commands to the N_Port + * identified by the FC ID provided. + * + * - PLOGI + * - PRLI + * - RTV + * * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* * function and then unlock the rport. @@ -420,7 +428,7 @@ static void fc_rport_work(struct work_struct *work) * If it appears we are already logged in, ADISC is used to verify * the setup. */ -static int fc_rport_login(struct fc_rport_priv *rdata) +int fc_rport_login(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); @@ -452,6 +460,7 @@ static int fc_rport_login(struct fc_rport_priv *rdata) return 0; } +EXPORT_SYMBOL(fc_rport_login); /** * fc_rport_enter_delete() - Schedule a remote port to be deleted @@ -2175,9 +2184,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_login) - lport->tt.rport_login = fc_rport_login; - if (!lport->tt.rport_logoff) lport->tt.rport_logoff = fc_rport_logoff; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 47b69d26be99..64045778e616 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -609,19 +609,6 @@ struct libfc_function_template { void (*lport_set_port_id)(struct fc_lport *, u32 port_id, struct fc_frame *); - /* - * Initiates the RP state machine. It is called from the LP module. - * This function will issue the following commands to the N_Port - * identified by the FC ID provided. - * - * - PLOGI - * - PRLI - * - RTV - * - * STATUS: OPTIONAL - */ - int (*rport_login)(struct fc_rport_priv *); - /* * Logoff, and remove the rport from the transport if * it had been added. This will send a LOGO to the target. @@ -1019,6 +1006,7 @@ struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, u32 port_id); struct fc_rport_priv *fc_rport_create(struct fc_lport *, u32); void fc_rport_destroy(struct kref *kref); +int fc_rport_login(struct fc_rport_priv *rdata); /* * DISCOVERY LAYER From c96c792aee33ab1a06c4d595959cd92eddbdbf3e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:44 +0200 Subject: [PATCH 091/256] scsi: libfc: Replace ->rport_logoff callback with function call The ->rport_logoff callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Reviewed-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_tgt.c | 3 +-- drivers/scsi/fcoe/fcoe_ctlr.c | 8 ++++---- drivers/scsi/libfc/fc_disc.c | 8 ++++---- drivers/scsi/libfc/fc_lport.c | 10 +++++----- drivers/scsi/libfc/fc_rport.c | 8 +++----- include/scsi/libfc.h | 9 +-------- 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index 08ec318afb99..739bfb62aff6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -80,7 +80,6 @@ static void bnx2fc_offload_session(struct fcoe_port *port, struct bnx2fc_rport *tgt, struct fc_rport_priv *rdata) { - struct fc_lport *lport = rdata->local_port; struct fc_rport *rport = rdata->rport; struct bnx2fc_interface *interface = port->priv; struct bnx2fc_hba *hba = interface->hba; @@ -160,7 +159,7 @@ ofld_err: tgt_init_err: if (tgt->fcoe_conn_id != -1) bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index ff0eca31cebe..12aecf337540 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2153,7 +2153,7 @@ static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport, LIBFCOE_FIP_DBG(fip, "rport FLOGI limited port_id %6.6x\n", rdata->ids.port_id); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } break; default: @@ -2179,7 +2179,7 @@ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) rcu_read_lock(); list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); kref_put(&rdata->kref, fc_rport_destroy); } } @@ -2531,7 +2531,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) (ids->node_name != -1 && ids->node_name != new->ids.node_name)) { mutex_unlock(&rdata->rp_mutex); LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); mutex_lock(&rdata->rp_mutex); } ids->port_name = new->ids.port_name; @@ -2729,7 +2729,7 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) LIBFCOE_FIP_DBG(fip, "port %16.16llx fc_id %6.6x beacon expired\n", rdata->ids.port_name, rdata->ids.port_id); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } else if (time_before(deadline, next_time)) next_time = deadline; kref_put(&rdata->kref, fc_rport_destroy); diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 8d0aa19b1f5b..7efa5a66e92a 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -71,7 +71,7 @@ static void fc_disc_stop_rports(struct fc_disc *disc) rcu_read_lock(); list_for_each_entry_rcu(rdata, &disc->rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); kref_put(&rdata->kref, fc_rport_destroy); } } @@ -301,7 +301,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) if (rdata->disc_id == disc->disc_id) fc_rport_login(rdata); else - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } kref_put(&rdata->kref, fc_rport_destroy); } @@ -622,7 +622,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, "Port-id %6.6x wwpn %16.16llx\n", rdata->ids.port_id, port_name); mutex_unlock(&rdata->rp_mutex); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); mutex_lock(&lport->disc.disc_mutex); new_rdata = fc_rport_create(lport, rdata->ids.port_id); mutex_unlock(&lport->disc.disc_mutex); @@ -638,7 +638,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n", cp->ct_reason, cp->ct_explan); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } else { FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n", ntohs(cp->ct_cmd)); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e20c1519be15..a391cb160f4b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -200,7 +200,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, "in the DNS or FDMI state, it's in the " "%d state", rdata->ids.port_id, lport->state); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } break; case RPORT_EV_LOGO: @@ -246,7 +246,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, u64 remote_wwnn) { if (lport->ptp_rdata) { - lport->tt.rport_logoff(lport->ptp_rdata); + fc_rport_logoff(lport->ptp_rdata); kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); } mutex_lock(&lport->disc.disc_mutex); @@ -623,7 +623,7 @@ int fc_fabric_logoff(struct fc_lport *lport) lport->tt.disc_stop_final(lport); mutex_lock(&lport->lp_mutex); if (lport->dns_rdata) - lport->tt.rport_logoff(lport->dns_rdata); + fc_rport_logoff(lport->dns_rdata); mutex_unlock(&lport->lp_mutex); lport->tt.rport_flush_queue(); mutex_lock(&lport->lp_mutex); @@ -1011,12 +1011,12 @@ EXPORT_SYMBOL(fc_lport_reset); static void fc_lport_reset_locked(struct fc_lport *lport) { if (lport->dns_rdata) { - lport->tt.rport_logoff(lport->dns_rdata); + fc_rport_logoff(lport->dns_rdata); lport->dns_rdata = NULL; } if (lport->ptp_rdata) { - lport->tt.rport_logoff(lport->ptp_rdata); + fc_rport_logoff(lport->ptp_rdata); kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); lport->ptp_rdata = NULL; } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index c045bc459910..22c8c928ee2b 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -295,7 +295,7 @@ static void fc_rport_work(struct work_struct *work) } if (!rport) { FC_RPORT_DBG(rdata, "Failed to add the rport\n"); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); kref_put(&rdata->kref, fc_rport_destroy); return; } @@ -504,7 +504,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, * function will hold the rport lock, call an _enter_* * function and then unlock the rport. */ -static int fc_rport_logoff(struct fc_rport_priv *rdata) +int fc_rport_logoff(struct fc_rport_priv *rdata) { struct fc_lport *lport = rdata->local_port; u32 port_id = rdata->ids.port_id; @@ -538,6 +538,7 @@ out: mutex_unlock(&rdata->rp_mutex); return 0; } +EXPORT_SYMBOL(fc_rport_logoff); /** * fc_rport_enter_ready() - Transition to the RPORT_ST_READY state @@ -2184,9 +2185,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_logoff) - lport->tt.rport_logoff = fc_rport_logoff; - if (!lport->tt.rport_recv_req) lport->tt.rport_recv_req = fc_rport_recv_req; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 64045778e616..b75a1820d226 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -609,14 +609,6 @@ struct libfc_function_template { void (*lport_set_port_id)(struct fc_lport *, u32 port_id, struct fc_frame *); - /* - * Logoff, and remove the rport from the transport if - * it had been added. This will send a LOGO to the target. - * - * STATUS: OPTIONAL - */ - int (*rport_logoff)(struct fc_rport_priv *); - /* * Receive a request from a remote port. * @@ -1007,6 +999,7 @@ struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, struct fc_rport_priv *fc_rport_create(struct fc_lport *, u32); void fc_rport_destroy(struct kref *kref); int fc_rport_login(struct fc_rport_priv *rdata); +int fc_rport_logoff(struct fc_rport_priv *rdata); /* * DISCOVERY LAYER From e76ee65fa649740fde0da44a0e1dc458407c685c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:45 +0200 Subject: [PATCH 092/256] scsi: libfc: Replace ->rport_recv_req callback with function call The ->rport_recv_req callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 6 ++---- include/scsi/libfc.h | 8 +------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a391cb160f4b..937a442cc70e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -902,7 +902,7 @@ static void fc_lport_recv_els_req(struct fc_lport *lport, /* * Check opcode. */ - recv = lport->tt.rport_recv_req; + recv = fc_rport_recv_req; switch (fc_frame_payload_op(fp)) { case ELS_FLOGI: if (!lport->point_to_multipoint) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 22c8c928ee2b..feae7abf05c3 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1786,7 +1786,7 @@ busy: * * Reference counting: does not modify kref */ -static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) +void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_seq_els_data els_data; @@ -1823,6 +1823,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) break; } } +EXPORT_SYMBOL(fc_rport_recv_req); /** * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests @@ -2185,9 +2186,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_recv_req) - lport->tt.rport_recv_req = fc_rport_recv_req; - if (!lport->tt.rport_flush_queue) lport->tt.rport_flush_queue = fc_rport_flush_queue; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index b75a1820d226..1e1dbc94d54a 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -609,13 +609,6 @@ struct libfc_function_template { void (*lport_set_port_id)(struct fc_lport *, u32 port_id, struct fc_frame *); - /* - * Receive a request from a remote port. - * - * STATUS: OPTIONAL - */ - void (*rport_recv_req)(struct fc_lport *, struct fc_frame *); - /* * Callback routine after the remote port is logged in * @@ -1000,6 +993,7 @@ struct fc_rport_priv *fc_rport_create(struct fc_lport *, u32); void fc_rport_destroy(struct kref *kref); int fc_rport_login(struct fc_rport_priv *rdata); int fc_rport_logoff(struct fc_rport_priv *rdata); +void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp); /* * DISCOVERY LAYER From 5922a957457c9146fc601ce3c36a076dde249593 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:46 +0200 Subject: [PATCH 093/256] scsi: libfc: Replace ->rport_flush_queue callback with function call The ->rport_flush_queue callback only ever had a single implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe_ctlr.c | 2 +- drivers/scsi/libfc/fc_disc.c | 2 +- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 6 ++---- include/scsi/libfc.h | 8 +------- 5 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 12aecf337540..12efc1d5df78 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2215,7 +2215,7 @@ static void fcoe_ctlr_disc_stop(struct fc_lport *lport) static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport) { fcoe_ctlr_disc_stop(lport); - lport->tt.rport_flush_queue(); + fc_rport_flush_queue(); synchronize_rcu(); } diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 7efa5a66e92a..6103231104da 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -719,7 +719,7 @@ static void fc_disc_stop(struct fc_lport *lport) static void fc_disc_stop_final(struct fc_lport *lport) { fc_disc_stop(lport); - lport->tt.rport_flush_queue(); + fc_rport_flush_queue(); } /** diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 937a442cc70e..7315675d3e33 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -625,7 +625,7 @@ int fc_fabric_logoff(struct fc_lport *lport) if (lport->dns_rdata) fc_rport_logoff(lport->dns_rdata); mutex_unlock(&lport->lp_mutex); - lport->tt.rport_flush_queue(); + fc_rport_flush_queue(); mutex_lock(&lport->lp_mutex); fc_lport_enter_logo(lport); mutex_unlock(&lport->lp_mutex); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index feae7abf05c3..6e5022627777 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -2175,10 +2175,11 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) /** * fc_rport_flush_queue() - Flush the rport_event_queue */ -static void fc_rport_flush_queue(void) +void fc_rport_flush_queue(void) { flush_workqueue(rport_event_queue); } +EXPORT_SYMBOL(fc_rport_flush_queue); /** * fc_rport_init() - Initialize the remote port layer for a local port @@ -2186,9 +2187,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_flush_queue) - lport->tt.rport_flush_queue = fc_rport_flush_queue; - return 0; } EXPORT_SYMBOL(fc_rport_init); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 1e1dbc94d54a..57630c5a7fc4 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -582,13 +582,6 @@ struct libfc_function_template { */ void (*exch_mgr_reset)(struct fc_lport *, u32 s_id, u32 d_id); - /* - * Flush the rport work queue. Generally used before shutdown. - * - * STATUS: OPTIONAL - */ - void (*rport_flush_queue)(void); - /* * Set the local port FC_ID. * @@ -994,6 +987,7 @@ void fc_rport_destroy(struct kref *kref); int fc_rport_login(struct fc_rport_priv *rdata); int fc_rport_logoff(struct fc_rport_priv *rdata); void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp); +void fc_rport_flush_queue(void); /* * DISCOVERY LAYER From a8220ded095695f2f11f0c35e1d2578bb0ec0e8f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:47 +0200 Subject: [PATCH 094/256] scsi: libfc: Remove fc_rport_init() Function is empty now and can be removed. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Reviewed-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 1 - drivers/scsi/fcoe/fcoe_ctlr.c | 1 - drivers/scsi/libfc/fc_rport.c | 10 ---------- include/scsi/libfc.h | 1 - 4 files changed, 13 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index f9ddb6156f14..0990130821fa 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -970,7 +970,6 @@ static int bnx2fc_libfc_config(struct fc_lport *lport) sizeof(struct libfc_function_template)); fc_elsct_init(lport); fc_exch_init(lport); - fc_rport_init(lport); fc_disc_init(lport); fc_disc_config(lport, lport); return 0; diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 12efc1d5df78..cea57e27e713 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -3235,7 +3235,6 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, fc_exch_init(lport); fc_elsct_init(lport); fc_lport_init(lport); - fc_rport_init(lport); fc_disc_init(lport); fcoe_ctlr_mode_set(lport, fip, fip->mode); return 0; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6e5022627777..110a707d8e82 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -2181,16 +2181,6 @@ void fc_rport_flush_queue(void) } EXPORT_SYMBOL(fc_rport_flush_queue); -/** - * fc_rport_init() - Initialize the remote port layer for a local port - * @lport: The local port to initialize the remote port layer for - */ -int fc_rport_init(struct fc_lport *lport) -{ - return 0; -} -EXPORT_SYMBOL(fc_rport_init); - /** * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator. * @rdata: remote port private diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 57630c5a7fc4..a77690125021 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -978,7 +978,6 @@ void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); /* * REMOTE PORT LAYER *****************************/ -int fc_rport_init(struct fc_lport *); void fc_rport_terminate_io(struct fc_rport *); struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, u32 port_id); From 0cac937da525ae3aa9f4b82c6ca129d16bb321fe Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:48 +0200 Subject: [PATCH 095/256] scsi: libfc: Replace ->seq_send callback with function call The ->seq_send callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 7 ++----- drivers/scsi/libfc/fc_fcp.c | 4 ++-- drivers/target/tcm_fc/tfc_cmd.c | 6 +++--- drivers/target/tcm_fc/tfc_io.c | 2 +- include/scsi/libfc.h | 8 +------- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index f5c3c1d09651..ee34cc6aded7 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -533,8 +533,7 @@ out: * Note: The frame will be freed either by a direct call to fc_frame_free(fp) * or indirectly by calling libfc_function_template.frame_send(). */ -static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, - struct fc_frame *fp) +int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp) { struct fc_exch *ep; int error; @@ -544,6 +543,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, spin_unlock_bh(&ep->ex_lock); return error; } +EXPORT_SYMBOL(fc_seq_send); /** * fc_seq_alloc() - Allocate a sequence for a given exchange @@ -2648,9 +2648,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.seq_send) - lport->tt.seq_send = fc_seq_send; - if (!lport->tt.exch_done) lport->tt.exch_done = fc_exch_done; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5cf1d2e3b575..daad70ff8c8f 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -731,7 +731,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, /* * send fragment using for a sequence. */ - error = lport->tt.seq_send(lport, seq, fp); + error = fc_seq_send(lport, seq, fp); if (error) { WARN_ON(1); /* send error should be rare */ return error; @@ -1033,7 +1033,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) fc_fill_fc_hdr(conf_frame, FC_RCTL_DD_SOL_CTL, ep->did, ep->sid, FC_TYPE_FCP, f_ctl, 0); - lport->tt.seq_send(lport, csp, conf_frame); + fc_seq_send(lport, csp, conf_frame); } } lport->tt.exch_done(seq); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index ff5de9a96643..42f09ca5db1a 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -165,7 +165,7 @@ int ft_queue_status(struct se_cmd *se_cmd) fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP, FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0); - rc = lport->tt.seq_send(lport, cmd->seq, fp); + rc = fc_seq_send(lport, cmd->seq, fp); if (rc) { pr_info_ratelimited("%s: Failed to send response frame %p, " "xid <0x%x>\n", __func__, fp, ep->xid); @@ -242,7 +242,7 @@ int ft_write_pending(struct se_cmd *se_cmd) cmd->was_ddp_setup = 1; } } - lport->tt.seq_send(lport, cmd->seq, fp); + fc_seq_send(lport, cmd->seq, fp); return 0; } @@ -323,7 +323,7 @@ static void ft_send_resp_status(struct fc_lport *lport, fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0); sp = fr_seq(fp); if (sp) { - lport->tt.seq_send(lport, sp, fp); + fc_seq_send(lport, sp, fp); lport->tt.exch_done(sp); } else { lport->tt.frame_send(lport, fp); diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index 6f7c65abfe2a..b10ebfd05d13 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -174,7 +174,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd) f_ctl |= FC_FC_END_SEQ; fc_fill_fc_hdr(fp, FC_RCTL_DD_SOL_DATA, ep->did, ep->sid, FC_TYPE_FCP, f_ctl, fh_off); - error = lport->tt.seq_send(lport, seq, fp); + error = fc_seq_send(lport, seq, fp); if (error) { pr_info_ratelimited("%s: Failed to send frame %p, " "xid <0x%x>, remaining %zu, " diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index a77690125021..7514cc969f8c 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -513,13 +513,6 @@ struct libfc_function_template { * STATUS: OPTIONAL */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Send a frame using an existing sequence and exchange. - * - * STATUS: OPTIONAL - */ - int (*seq_send)(struct fc_lport *, struct fc_seq *, - struct fc_frame *); /* * Abort an exchange and sequence. Generally called because of a @@ -1058,6 +1051,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *, enum fc_class class, void fc_exch_mgr_free(struct fc_lport *); void fc_exch_recv(struct fc_lport *, struct fc_frame *); void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id); +int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp); /* * Functions for fc_functions_template From 0ebaed17febadeda0f4da21da2c0f295f46348a4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:49 +0200 Subject: [PATCH 096/256] scsi: libfc: Replace ->seq_exch_abort callback with function call The ->seq_exch_abort callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 13 ++++++++----- drivers/scsi/libfc/fc_fcp.c | 4 ++-- include/scsi/libfc.h | 14 +------------- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ee34cc6aded7..fffb9a3162e2 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -629,6 +629,13 @@ static void fc_seq_set_resp(struct fc_seq *sp, * @ep: The exchange to be aborted * @timer_msec: The period of time to wait before aborting * + * Abort an exchange and sequence. Generally called because of a + * exchange timeout or an abort from the upper layer. + * + * A timer_msec can be specified for abort timeout, if non-zero + * timer_msec value is specified then exchange resp handler + * will be called with timeout error if no response to abort. + * * Locking notes: Called with exch lock held * * Return value: 0 on success else error code @@ -692,8 +699,7 @@ static int fc_exch_abort_locked(struct fc_exch *ep, * * Return value: 0 on success else error code */ -static int fc_seq_exch_abort(const struct fc_seq *req_sp, - unsigned int timer_msec) +int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec) { struct fc_exch *ep; int error; @@ -2654,9 +2660,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lport->tt.seq_exch_abort) - lport->tt.seq_exch_abort = fc_seq_exch_abort; - if (!lport->tt.seq_assign) lport->tt.seq_assign = fc_seq_assign; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index daad70ff8c8f..2bb3f9f74ad2 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -287,9 +287,9 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) put_cpu(); fsp->state |= FC_SRB_ABORT_PENDING; - rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); + rc = fc_seq_exch_abort(fsp->seq_ptr, 0); /* - * ->seq_exch_abort() might return -ENXIO if + * fc_seq_exch_abort() might return -ENXIO if * the sequence is already completed */ if (rc == -ENXIO) { diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 7514cc969f8c..50d1af1eba1e 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -514,19 +514,6 @@ struct libfc_function_template { */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Abort an exchange and sequence. Generally called because of a - * exchange timeout or an abort from the upper layer. - * - * A timer_msec can be specified for abort timeout, if non-zero - * timer_msec value is specified then exchange resp handler - * will be called with timeout error if no response to abort. - * - * STATUS: OPTIONAL - */ - int (*seq_exch_abort)(const struct fc_seq *, - unsigned int timer_msec); - /* * Indicate that an exchange/sequence tuple is complete and the memory * allocated for the related objects may be freed. @@ -1052,6 +1039,7 @@ void fc_exch_mgr_free(struct fc_lport *); void fc_exch_recv(struct fc_lport *, struct fc_frame *); void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id); int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp); +int fc_seq_exch_abort(const struct fc_seq *, unsigned int timer_msec); /* * Functions for fc_functions_template From 768c72cc34a26ed1c41c9af89886f91af08ded8c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:50 +0200 Subject: [PATCH 097/256] scsi: libfc: Replace ->exch_done callback with function call The ->exch_done callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- drivers/scsi/libfc/fc_fcp.c | 20 +++++++++----------- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/target/tcm_fc/tfc_cmd.c | 4 ++-- include/scsi/libfc.h | 9 +-------- 5 files changed, 15 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index fffb9a3162e2..b98ad3f743cb 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -969,7 +969,7 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) * * Note: May sleep if invoked from outside a response handler. */ -static void fc_exch_done(struct fc_seq *sp) +void fc_exch_done(struct fc_seq *sp) { struct fc_exch *ep = fc_seq_exch(sp); int rc; @@ -982,6 +982,7 @@ static void fc_exch_done(struct fc_seq *sp) if (!rc) fc_exch_delete(ep); } +EXPORT_SYMBOL(fc_exch_done); /** * fc_exch_resp() - Allocate a new exchange for a response frame @@ -2654,9 +2655,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.exch_done) - lport->tt.exch_done = fc_exch_done; - if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2bb3f9f74ad2..4fadd6249700 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -311,7 +311,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code) { if (fsp->seq_ptr) { - fsp->lp->tt.exch_done(fsp->seq_ptr); + fc_exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } @@ -1036,7 +1036,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) fc_seq_send(lport, csp, conf_frame); } } - lport->tt.exch_done(seq); + fc_exch_done(seq); } /* * Some resets driven by SCSI are not I/Os and do not have @@ -1054,10 +1054,8 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) */ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) { - struct fc_lport *lport = fsp->lp; - if (fsp->seq_ptr) { - lport->tt.exch_done(fsp->seq_ptr); + fc_exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } fsp->status_code = error; @@ -1349,7 +1347,7 @@ static int fc_lun_reset(struct fc_lport *lport, struct fc_fcp_pkt *fsp, spin_lock_bh(&fsp->scsi_pkt_lock); if (fsp->seq_ptr) { - lport->tt.exch_done(fsp->seq_ptr); + fc_exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } fsp->wait_for_comp = 0; @@ -1403,7 +1401,7 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg) if (fh->fh_type != FC_TYPE_BLS) fc_fcp_resp(fsp, fp); fsp->seq_ptr = NULL; - fsp->lp->tt.exch_done(seq); + fc_exch_done(seq); out_unlock: fc_fcp_unlock_pkt(fsp); out: @@ -1793,9 +1791,9 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fh = fc_frame_header_get(fp); /* - * BUG? fc_fcp_srr_error calls exch_done which would release + * BUG? fc_fcp_srr_error calls fc_exch_done which would release * the ep. But if fc_fcp_srr_error had got -FC_EX_TIMEOUT, - * then fc_exch_timeout would be sending an abort. The exch_done + * then fc_exch_timeout would be sending an abort. The fc_exch_done * call by fc_fcp_srr_error would prevent fc_exch.c from seeing * an abort response though. */ @@ -1816,7 +1814,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) } fc_fcp_unlock_pkt(fsp); out: - fsp->lp->tt.exch_done(seq); + fc_exch_done(seq); fc_frame_free(fp); } @@ -1846,7 +1844,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } fc_fcp_unlock_pkt(fsp); out: - fsp->lp->tt.exch_done(fsp->recov_seq); + fc_exch_done(fsp->recov_seq); } /** diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 7315675d3e33..2d3133f62463 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -980,7 +980,7 @@ drop: FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type); fc_frame_free(fp); if (sp) - lport->tt.exch_done(sp); + fc_exch_done(sp); } EXPORT_SYMBOL(fc_lport_recv); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 42f09ca5db1a..7f6562638abf 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -177,7 +177,7 @@ int ft_queue_status(struct se_cmd *se_cmd) se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL; return -ENOMEM; } - lport->tt.exch_done(cmd->seq); + fc_exch_done(cmd->seq); /* * Drop the extra ACK_KREF reference taken by target_submit_cmd() * ahead of ft_check_stop_free() -> transport_generic_free_cmd() @@ -324,7 +324,7 @@ static void ft_send_resp_status(struct fc_lport *lport, sp = fr_seq(fp); if (sp) { fc_seq_send(lport, sp, fp); - lport->tt.exch_done(sp); + fc_exch_done(sp); } else { lport->tt.frame_send(lport, fp); } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 50d1af1eba1e..19f38eb318ec 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -514,14 +514,6 @@ struct libfc_function_template { */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Indicate that an exchange/sequence tuple is complete and the memory - * allocated for the related objects may be freed. - * - * STATUS: OPTIONAL - */ - void (*exch_done)(struct fc_seq *); - /* * Start a new sequence on the same exchange/sequence tuple. * @@ -1040,6 +1032,7 @@ void fc_exch_recv(struct fc_lport *, struct fc_frame *); void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id); int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp); int fc_seq_exch_abort(const struct fc_seq *, unsigned int timer_msec); +void fc_exch_done(struct fc_seq *sp); /* * Functions for fc_functions_template From c6865b30be7ed894839687b26f2cde9b99b97270 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:51 +0200 Subject: [PATCH 098/256] scsi: libfc: Replace ->seq_start_next callback with function call The ->seq_start_next callback only ever had one implementation, so call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- drivers/scsi/libfc/fc_fcp.c | 4 ++-- drivers/scsi/libfc/fc_libfc.c | 2 +- drivers/target/tcm_fc/tfc_cmd.c | 4 ++-- drivers/target/tcm_fc/tfc_io.c | 2 +- include/scsi/libfc.h | 8 +------- 6 files changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index b98ad3f743cb..8a99f846441a 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -585,7 +585,7 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) * for a given sequence/exchange pair * @sp: The sequence/exchange to get a new exchange for */ -static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) +struct fc_seq *fc_seq_start_next(struct fc_seq *sp) { struct fc_exch *ep = fc_seq_exch(sp); @@ -595,6 +595,7 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) return sp; } +EXPORT_SYMBOL(fc_seq_start_next); /* * Set the response handler for the exchange associated with a sequence. @@ -2649,9 +2650,6 @@ EXPORT_SYMBOL(fc_exch_recv); */ int fc_exch_init(struct fc_lport *lport) { - if (!lport->tt.seq_start_next) - lport->tt.seq_start_next = fc_seq_start_next; - if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 4fadd6249700..0e67621477a8 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -653,7 +653,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, remaining = seq_blen; fh_parm_offset = frame_offset = offset; tlen = 0; - seq = lport->tt.seq_start_next(seq); + seq = fc_seq_start_next(seq); f_ctl = FC_FC_REL_OFF; WARN_ON(!seq); @@ -1024,7 +1024,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) struct fc_frame *conf_frame; struct fc_seq *csp; - csp = lport->tt.seq_start_next(seq); + csp = fc_seq_start_next(seq); conf_frame = fc_fcp_frame_alloc(fsp->lp, 0); if (conf_frame) { f_ctl = FC_FC_SEQ_INIT; diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c index c11a638f32e6..d623d084b7ec 100644 --- a/drivers/scsi/libfc/fc_libfc.c +++ b/drivers/scsi/libfc/fc_libfc.c @@ -226,7 +226,7 @@ void fc_fill_reply_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, sp = fr_seq(in_fp); if (sp) - fr_seq(fp) = fr_dev(in_fp)->tt.seq_start_next(sp); + fr_seq(fp) = fc_seq_start_next(sp); fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset); } EXPORT_SYMBOL(fc_fill_reply_hdr); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 7f6562638abf..12aec538e39b 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -161,7 +161,7 @@ int ft_queue_status(struct se_cmd *se_cmd) /* * Send response. */ - cmd->seq = lport->tt.seq_start_next(cmd->seq); + cmd->seq = fc_seq_start_next(cmd->seq); fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP, FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0); @@ -221,7 +221,7 @@ int ft_write_pending(struct se_cmd *se_cmd) memset(txrdy, 0, sizeof(*txrdy)); txrdy->ft_burst_len = htonl(se_cmd->data_length); - cmd->seq = lport->tt.seq_start_next(cmd->seq); + cmd->seq = fc_seq_start_next(cmd->seq); fc_fill_fc_hdr(fp, FC_RCTL_DD_DATA_DESC, ep->did, ep->sid, FC_TYPE_FCP, FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index b10ebfd05d13..1eb1f58e00e4 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -82,7 +82,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd) ep = fc_seq_exch(cmd->seq); lport = ep->lp; - cmd->seq = lport->tt.seq_start_next(cmd->seq); + cmd->seq = fc_seq_start_next(cmd->seq); remaining = se_cmd->data_length; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 19f38eb318ec..39143cabaa90 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -514,13 +514,6 @@ struct libfc_function_template { */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Start a new sequence on the same exchange/sequence tuple. - * - * STATUS: OPTIONAL - */ - struct fc_seq *(*seq_start_next)(struct fc_seq *); - /* * Set a response handler for the exchange of the sequence. * @@ -1019,6 +1012,7 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, void *arg, u32 timer_msec); void fc_seq_els_rsp_send(struct fc_frame *, enum fc_els_cmd, struct fc_seq_els_data *); +struct fc_seq *fc_seq_start_next(struct fc_seq *sp); struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, struct fc_exch_mgr *, bool (*match)(struct fc_frame *)); From f1d61e6e682cd241c145e6268be3a9f30af934eb Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:52 +0200 Subject: [PATCH 099/256] scsi: libfc: Replace ->seq_set_resp callback with direct function call The ->seq_set_resp callback only ever had one implementation, so call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 11 ++++------- drivers/target/tcm_fc/tfc_cmd.c | 2 +- include/scsi/libfc.h | 13 +++---------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8a99f846441a..ceeccd7b3ba7 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -602,10 +602,9 @@ EXPORT_SYMBOL(fc_seq_start_next); * * Note: May sleep if invoked from outside a response handler. */ -static void fc_seq_set_resp(struct fc_seq *sp, - void (*resp)(struct fc_seq *, struct fc_frame *, - void *), - void *arg) +void fc_seq_set_resp(struct fc_seq *sp, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg) { struct fc_exch *ep = fc_seq_exch(sp); DEFINE_WAIT(wait); @@ -624,6 +623,7 @@ static void fc_seq_set_resp(struct fc_seq *sp, ep->arg = arg; spin_unlock_bh(&ep->ex_lock); } +EXPORT_SYMBOL(fc_seq_set_resp); /** * fc_exch_abort_locked() - Abort an exchange @@ -2650,9 +2650,6 @@ EXPORT_SYMBOL(fc_exch_recv); */ int fc_exch_init(struct fc_lport *lport) { - if (!lport->tt.seq_set_resp) - lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 12aec538e39b..d6d06644f1da 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -563,7 +563,7 @@ static void ft_send_work(struct work_struct *work) task_attr = TCM_SIMPLE_TAG; } - fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd); + fc_seq_set_resp(cmd->seq, ft_recv_seq, cmd); cmd->se_cmd.tag = fc_seq_exch(cmd->seq)->rxid; /* * Use a single se_cmd->cmd_kref as we expect to release se_cmd diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 39143cabaa90..e8669f9f2e50 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -514,16 +514,6 @@ struct libfc_function_template { */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Set a response handler for the exchange of the sequence. - * - * STATUS: OPTIONAL - */ - void (*seq_set_resp)(struct fc_seq *sp, - void (*resp)(struct fc_seq *, struct fc_frame *, - void *), - void *arg); - /* * Assign a sequence for an incoming request frame. * @@ -1013,6 +1003,9 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, void fc_seq_els_rsp_send(struct fc_frame *, enum fc_els_cmd, struct fc_seq_els_data *); struct fc_seq *fc_seq_start_next(struct fc_seq *sp); +void fc_seq_set_resp(struct fc_seq *sp, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg); struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, struct fc_exch_mgr *, bool (*match)(struct fc_frame *)); From 96d564e24ac2b69fbfa2b81d48069ffeede549d7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:53 +0200 Subject: [PATCH 100/256] scsi: libfc: Replace ->seq_assign callback with function call The ->seq_assign callback only ever had one implementation, so call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- drivers/target/tcm_fc/tfc_cmd.c | 2 +- include/scsi/libfc.h | 8 +------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ceeccd7b3ba7..efb6a4b7a62a 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1477,7 +1477,7 @@ reject: * A reference will be held on the exchange/sequence for the caller, which * must call fc_seq_release(). */ -static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) +struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) { struct fc_exch_mgr_anchor *ema; @@ -1491,6 +1491,7 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) break; return fr_seq(fp); } +EXPORT_SYMBOL(fc_seq_assign); /** * fc_seq_release() - Release the hold @@ -2653,9 +2654,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lport->tt.seq_assign) - lport->tt.seq_assign = fc_seq_assign; - if (!lport->tt.seq_release) lport->tt.seq_release = fc_seq_release; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index d6d06644f1da..962eff3d190d 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -461,7 +461,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp) cmd->se_cmd.map_tag = tag; cmd->sess = sess; - cmd->seq = lport->tt.seq_assign(lport, fp); + cmd->seq = fc_seq_assign(lport, fp); if (!cmd->seq) { percpu_ida_free(&se_sess->sess_tag_pool, tag); goto busy; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index e8669f9f2e50..2baa2553c977 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -514,13 +514,6 @@ struct libfc_function_template { */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Assign a sequence for an incoming request frame. - * - * STATUS: OPTIONAL - */ - struct fc_seq *(*seq_assign)(struct fc_lport *, struct fc_frame *); - /* * Release the reference on the sequence returned by seq_assign(). * @@ -1006,6 +999,7 @@ struct fc_seq *fc_seq_start_next(struct fc_seq *sp); void fc_seq_set_resp(struct fc_seq *sp, void (*resp)(struct fc_seq *, struct fc_frame *, void *), void *arg); +struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp); struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, struct fc_exch_mgr *, bool (*match)(struct fc_frame *)); From 9625cc483b8c41d500ec78f0f2e61d71db1431f5 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:54 +0200 Subject: [PATCH 101/256] scsi: libfc: Replace ->seq_release callback with function call The ->seq_release callback only ever had one implementation, so call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- drivers/target/tcm_fc/tfc_cmd.c | 2 +- include/scsi/libfc.h | 8 +------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index efb6a4b7a62a..442a6c1d5efc 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1497,10 +1497,11 @@ EXPORT_SYMBOL(fc_seq_assign); * fc_seq_release() - Release the hold * @sp: The sequence. */ -static void fc_seq_release(struct fc_seq *sp) +void fc_seq_release(struct fc_seq *sp) { fc_exch_release(fc_seq_exch(sp)); } +EXPORT_SYMBOL(fc_seq_release); /** * fc_exch_recv_req() - Handler for an incoming request @@ -2654,9 +2655,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lport->tt.seq_release) - lport->tt.seq_release = fc_seq_release; - return 0; } EXPORT_SYMBOL(fc_exch_init); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 962eff3d190d..9af7842b8178 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -92,7 +92,7 @@ static void ft_free_cmd(struct ft_cmd *cmd) fp = cmd->req_frame; lport = fr_dev(fp); if (fr_seq(fp)) - lport->tt.seq_release(fr_seq(fp)); + fc_seq_release(fr_seq(fp)); fc_frame_free(fp); percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); ft_sess_put(sess); /* undo get from lookup at recv */ diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 2baa2553c977..6f81b28364da 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -514,13 +514,6 @@ struct libfc_function_template { */ void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); - /* - * Release the reference on the sequence returned by seq_assign(). - * - * STATUS: OPTIONAL - */ - void (*seq_release)(struct fc_seq *); - /* * Reset an exchange manager, completing all sequences and exchanges. * If s_id is non-zero, reset only exchanges originating from that FID. @@ -1000,6 +993,7 @@ void fc_seq_set_resp(struct fc_seq *sp, void (*resp)(struct fc_seq *, struct fc_frame *, void *), void *arg); struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp); +void fc_seq_release(struct fc_seq *sp); struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, struct fc_exch_mgr *, bool (*match)(struct fc_frame *)); From b8aca0c17e11fb6250b1f18734bc7600a4174989 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 24 Oct 2016 09:05:06 -0700 Subject: [PATCH 102/256] MAINTAINERS: Revise lpfc maintainers to reflect Broadcom Avago is now known as Broadcom. Revise the emails and website for lpfc accordingly. Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e2d184ebf3b2..f4c5f215e6e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4688,11 +4688,11 @@ M: David Woodhouse L: linux-embedded@vger.kernel.org S: Maintained -EMULEX/AVAGO LPFC FC/FCOE SCSI DRIVER -M: James Smart -M: Dick Kennedy +EMULEX/BROADCOM LPFC FC/FCOE SCSI DRIVER +M: James Smart +M: Dick Kennedy L: linux-scsi@vger.kernel.org -W: http://www.avagotech.com +W: http://www.broadcom.com S: Supported F: drivers/scsi/lpfc/ From 18e1c7f68a5814442abad849abe6eacbf02ffd7c Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:29 -0700 Subject: [PATCH 103/256] scsi: megaraid_sas: For SRIOV enabled firmware, ensure VF driver waits for 30secs before reset For SRIOV enabled firmware, if there is a OCR(online controller reset) possibility driver set the convert flag to 1, which is not happening if there are outstanding commands even after 180 seconds. As driver does not set convert flag to 1 and still making the OCR to run, VF(Virtual function) driver is directly writing on to the register instead of waiting for 30 seconds. Setting convert flag to 1 will cause VF driver will wait for 30 secs before going for reset. CC: stable@vger.kernel.org Signed-off-by: Kiran Kumar Kasturi Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 52d8bbf7feb5..61be7ed73a7c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2823,6 +2823,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, dev_err(&instance->pdev->dev, "pending commands remain after waiting, " "will reset adapter scsi%d.\n", instance->host->host_no); + *convert = 1; retval = 1; } out: From b3e3827bdd329da1c1b5697e74dfcaf51b65885c Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:30 -0700 Subject: [PATCH 104/256] scsi: megaraid_sas: Send correct PhysArm to FW for R1 VD downgrade This patch fixes the issue of wrong PhysArm was sent to firmware for R1 VD downgrade. Signed-off-by: Kiran Kumar Kasturi Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index e413113c86ac..f237d0003df3 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -782,7 +782,8 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; else if (raid->level == 1) { - pd = MR_ArPdGet(arRef, physArm + 1, map); + physArm = physArm + 1; + pd = MR_ArPdGet(arRef, physArm, map); if (pd != MR_PD_INVALID) *pDevHandle = MR_PdDevHandleGet(pd, map); } @@ -879,7 +880,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; else if (raid->level == 1) { /* Get alternate Pd. */ - pd = MR_ArPdGet(arRef, physArm + 1, map); + physArm = physArm + 1; + pd = MR_ArPdGet(arRef, physArm, map); if (pd != MR_PD_INVALID) /* Get dev handle from Pd */ *pDevHandle = MR_PdDevHandleGet(pd, map); From a1dfd62c1ebce71a62f5de002c694d5a22fb32a1 Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:31 -0700 Subject: [PATCH 105/256] scsi: megaraid_sas: Do not fire DCMDs during PCI shutdown/detach This patch addresses the issue of driver firing DCMDs in PCI shutdown/detach path irrespective of firmware state. Driver will now check whether firmware is in operational state or not before firing DCMDs. If firmware is in unrecoverable state or does not become operational within specfied time, driver will skip firing DCMDs. [mkp: fixed typos] Signed-off-by: Sumit Saxena Signed-off-by: Shivasharan Srikanteshwara Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 39 +++++++++++++++++++++ drivers/scsi/megaraid/megaraid_sas_fusion.c | 9 +++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index d8b1fbd4c8aa..d5410a39d956 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -6245,6 +6245,34 @@ fail_reenable_msix: #define megasas_resume NULL #endif +static inline int +megasas_wait_for_adapter_operational(struct megasas_instance *instance) +{ + int wait_time = MEGASAS_RESET_WAIT_TIME * 2; + int i; + + if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) + return 1; + + for (i = 0; i < wait_time; i++) { + if (atomic_read(&instance->adprecovery) == MEGASAS_HBA_OPERATIONAL) + break; + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) + dev_notice(&instance->pdev->dev, "waiting for controller reset to finish\n"); + + msleep(1000); + } + + if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { + dev_info(&instance->pdev->dev, "%s timed out while waiting for HBA to recover.\n", + __func__); + return 1; + } + + return 0; +} + /** * megasas_detach_one - PCI hot"un"plug entry point * @pdev: PCI device structure @@ -6269,9 +6297,14 @@ static void megasas_detach_one(struct pci_dev *pdev) if (instance->fw_crash_state != UNAVAILABLE) megasas_free_host_crash_buffer(instance); scsi_remove_host(instance->host); + + if (megasas_wait_for_adapter_operational(instance)) + goto skip_firing_dcmds; + megasas_flush_cache(instance); megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); +skip_firing_dcmds: /* cancel the delayed work if this work still in queue*/ if (instance->ev != NULL) { struct megasas_aen_event *ev = instance->ev; @@ -6385,8 +6418,14 @@ static void megasas_shutdown(struct pci_dev *pdev) struct megasas_instance *instance = pci_get_drvdata(pdev); instance->unload = 1; + + if (megasas_wait_for_adapter_operational(instance)) + goto skip_firing_dcmds; + megasas_flush_cache(instance); megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); + +skip_firing_dcmds: instance->instancet->disable_intr(instance); megasas_destroy_irqs(instance); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 61be7ed73a7c..2159f6ae5a31 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2463,12 +2463,15 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) /* Start collecting crash, if DMA bit is done */ if ((fw_state == MFI_STATE_FAULT) && dma_state) schedule_work(&instance->crash_init); - else if (fw_state == MFI_STATE_FAULT) - schedule_work(&instance->work_init); + else if (fw_state == MFI_STATE_FAULT) { + if (instance->unload == 0) + schedule_work(&instance->work_init); + } } else if (fw_state == MFI_STATE_FAULT) { dev_warn(&instance->pdev->dev, "Iop2SysDoorbellInt" "for scsi%d\n", instance->host->host_no); - schedule_work(&instance->work_init); + if (instance->unload == 0) + schedule_work(&instance->work_init); } } From 36fe90b0f0bdc9d030e88ba2153f3c8d6b6a5964 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 22 Oct 2016 20:32:26 +0300 Subject: [PATCH 106/256] scsi: fnic: use kernel's '%pM' format option to print MAC Instead of supplying each byte through stack let's use %pM specifier. Cc: Hiral Patel Cc: Suma Ramars Acked-by: Tom Tucker Signed-off-by: Andy Shevchenko Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/vnic_dev.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c index 9795d6f3e197..ba69d6112fa1 100644 --- a/drivers/scsi/fnic/vnic_dev.c +++ b/drivers/scsi/fnic/vnic_dev.c @@ -499,10 +499,7 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); if (err) - printk(KERN_ERR - "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], - err); + pr_err("Can't add addr [%pM], %d\n", addr, err); } void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) @@ -517,10 +514,7 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); if (err) - printk(KERN_ERR - "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], - err); + pr_err("Can't del addr [%pM], %d\n", addr, err); } int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) From caf4ebcbe7fda6cb96cdf64d4dd624356c03e437 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 22 Oct 2016 20:32:27 +0300 Subject: [PATCH 107/256] scsi: fusion: print lan address via %pMR LAN MAC addresses can be printed directly using %pMR specifier. Cc: Sathya Prakash Cc: Chaitra P B Cc: Suganath Prabu Subramani Signed-off-by: Andy Shevchenko Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptbase.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 89c7ed16b4df..f82745c6cdf7 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -2585,10 +2585,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) (void) GetLanConfigPages(ioc); a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; dprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "LanAddr = %02X:%02X:%02X" - ":%02X:%02X:%02X\n", - ioc->name, a[5], a[4], - a[3], a[2], a[1], a[0])); + "LanAddr = %pMR\n", ioc->name, a)); } break; @@ -6783,8 +6780,7 @@ static int mpt_iocinfo_proc_show(struct seq_file *m, void *v) if (ioc->bus_type == FC) { if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - seq_printf(m, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - a[5], a[4], a[3], a[2], a[1], a[0]); + seq_printf(m, " LanAddr = %pMR\n", a); } seq_printf(m, " WWN = %08X%08X:%08X%08X\n", ioc->fc_port_page0[p].WWNN.High, @@ -6861,8 +6857,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X", - a[5], a[4], a[3], a[2], a[1], a[0]); + y += sprintf(buffer+len+y, ", LanAddr=%pMR", a); } y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); @@ -6896,8 +6891,7 @@ static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X", - a[5], a[4], a[3], a[2], a[1], a[0]); + seq_printf(m, ", LanAddr=%pMR", a); } seq_printf(m, ", IRQ=%d", ioc->pci_irq); From d1d81bd097763b0c7c47026ca55d6d4d081d0448 Mon Sep 17 00:00:00 2001 From: Oleksandr Khoshaba Date: Sat, 22 Oct 2016 20:32:28 +0300 Subject: [PATCH 108/256] scsi: qla4xxx: print MAC and SID via %p[mM][R] In the kernel we have nice specifier to print MAC by given pointer to the address in a binary form. Signed-off-by: Oleksandr Khoshaba Acked-by: Vikas Chaudhary Cc: QLogic-Storage-Upstream@qlogic.com Signed-off-by: Andy Shevchenko Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_mbx.c | 5 +---- drivers/scsi/qla4xxx/ql4_nx.c | 8 ++------ drivers/scsi/qla4xxx/ql4_os.c | 15 ++++----------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index c291fdff1b33..1da04f323d38 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -2032,10 +2032,7 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha, ptid = (uint16_t *)&fw_ddb_entry->isid[1]; *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id); - DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%02x%02x%02x%02x%02x%02x]\n", - fw_ddb_entry->isid[5], fw_ddb_entry->isid[4], - fw_ddb_entry->isid[3], fw_ddb_entry->isid[2], - fw_ddb_entry->isid[1], fw_ddb_entry->isid[0])); + DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%pmR]\n", fw_ddb_entry->isid)); iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options); memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias)); diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 06ddd13cb7cc..bccd8b674234 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -4094,12 +4094,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) ha->phy_port_num = sys_info->port_num; ha->iscsi_pci_func_cnt = sys_info->iscsi_pci_func_cnt; - DEBUG2(printk("scsi%ld: %s: " - "mac %02x:%02x:%02x:%02x:%02x:%02x " - "serial %s\n", ha->host_no, __func__, - ha->my_mac[0], ha->my_mac[1], ha->my_mac[2], - ha->my_mac[3], ha->my_mac[4], ha->my_mac[5], - ha->serial_number)); + DEBUG2(printk("scsi%ld: %s: mac %pM serial %s\n", + ha->host_no, __func__, ha->my_mac, ha->serial_number)); status = QLA_SUCCESS; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 01c3610a60cf..9fbb33fc90c7 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -6304,13 +6304,9 @@ static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, * ISID would not match firmware generated ISID. */ if (is_isid_compare) { - DEBUG2(ql4_printk(KERN_INFO, ha, "%s: old ISID [%02x%02x%02x" - "%02x%02x%02x] New ISID [%02x%02x%02x%02x%02x%02x]\n", - __func__, old_tddb->isid[5], old_tddb->isid[4], - old_tddb->isid[3], old_tddb->isid[2], old_tddb->isid[1], - old_tddb->isid[0], new_tddb->isid[5], new_tddb->isid[4], - new_tddb->isid[3], new_tddb->isid[2], new_tddb->isid[1], - new_tddb->isid[0])); + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: old ISID [%pmR] New ISID [%pmR]\n", + __func__, old_tddb->isid, new_tddb->isid)); if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0], sizeof(old_tddb->isid))) @@ -7925,10 +7921,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, rc = sprintf(buf, "%u\n", fnode_conn->keepalive_timeout); break; case ISCSI_FLASHNODE_ISID: - rc = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", - fnode_sess->isid[0], fnode_sess->isid[1], - fnode_sess->isid[2], fnode_sess->isid[3], - fnode_sess->isid[4], fnode_sess->isid[5]); + rc = sprintf(buf, "%pm\n", fnode_sess->isid); break; case ISCSI_FLASHNODE_TSID: rc = sprintf(buf, "%u\n", fnode_sess->tsid); From 1bc504552e20d268d91af4560c1109207d5af295 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 22 Oct 2016 20:32:29 +0300 Subject: [PATCH 109/256] scsi: ips: don't use custom hex_asc_upper[] table We have table of the HEX characters in the kernel. Replace custom by a generic one. Cc: Adaptec OEM Raid Solutions Signed-off-by: Andy Shevchenko Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/ips.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 02cb76fd4420..3419e1bcdff6 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -2241,9 +2241,6 @@ ips_get_bios_version(ips_ha_t * ha, int intr) uint8_t minor; uint8_t subminor; uint8_t *buffer; - char hexDigits[] = - { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', - 'D', 'E', 'F' }; METHOD_TRACE("ips_get_bios_version", 1); @@ -2374,13 +2371,13 @@ ips_get_bios_version(ips_ha_t * ha, int intr) } } - ha->bios_version[0] = hexDigits[(major & 0xF0) >> 4]; + ha->bios_version[0] = hex_asc_upper_hi(major); ha->bios_version[1] = '.'; - ha->bios_version[2] = hexDigits[major & 0x0F]; - ha->bios_version[3] = hexDigits[subminor]; + ha->bios_version[2] = hex_asc_upper_lo(major); + ha->bios_version[3] = hex_asc_upper_lo(subminor); ha->bios_version[4] = '.'; - ha->bios_version[5] = hexDigits[(minor & 0xF0) >> 4]; - ha->bios_version[6] = hexDigits[minor & 0x0F]; + ha->bios_version[5] = hex_asc_upper_hi(minor); + ha->bios_version[6] = hex_asc_upper_lo(minor); ha->bios_version[7] = 0; } From df441cc030545fe8a5f6891e3767990f761e1600 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 22 Oct 2016 20:32:30 +0300 Subject: [PATCH 110/256] scsi: replace custom approach to hexdump small buffers In kernel we have defined specifier (%*ph[C]) to dump small buffers in a hex format. Replace custom approach by a generic one. Cc: Jon Mason Signed-off-by: Andy Shevchenko Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_srp.c | 11 +---------- drivers/scsi/sd.c | 4 +--- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index e3cd3ece4412..02cfc6b1ee5a 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -115,21 +115,12 @@ static DECLARE_TRANSPORT_CLASS(srp_host_class, "srp_host", srp_host_setup, static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports", NULL, NULL, NULL); -#define SRP_PID(p) \ - (p)->port_id[0], (p)->port_id[1], (p)->port_id[2], (p)->port_id[3], \ - (p)->port_id[4], (p)->port_id[5], (p)->port_id[6], (p)->port_id[7], \ - (p)->port_id[8], (p)->port_id[9], (p)->port_id[10], (p)->port_id[11], \ - (p)->port_id[12], (p)->port_id[13], (p)->port_id[14], (p)->port_id[15] - -#define SRP_PID_FMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \ - "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" - static ssize_t show_srp_rport_id(struct device *dev, struct device_attribute *attr, char *buf) { struct srp_rport *rport = transport_class_to_srp_rport(dev); - return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport)); + return sprintf(buf, "%16phC\n", rport->port_id); } static DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 51e56296f465..b4933afe08a1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2419,9 +2419,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) if (sdkp->first_scan || old_wp != sdkp->write_prot) { sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", sdkp->write_prot ? "on" : "off"); - sd_printk(KERN_DEBUG, sdkp, - "Mode Sense: %02x %02x %02x %02x\n", - buffer[0], buffer[1], buffer[2], buffer[3]); + sd_printk(KERN_DEBUG, sdkp, "Mode Sense: %4ph\n", buffer); } } } From 8d9c1f86a303de8fb631fb6b76260cb1fa8883a1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 22 Oct 2016 20:32:31 +0300 Subject: [PATCH 111/256] scsi: cciss: replace custom function to hexdump For small buffers we may use %*ph[N] specifier, for the bigger blocks print_hex_dump() call. Cc: Don Brace Cc: esc.storagedev@microsemi.com Signed-off-by: Andy Shevchenko Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/block/cciss_scsi.c | 72 ++++++-------------------------------- 1 file changed, 10 insertions(+), 62 deletions(-) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 1537302e56e3..a18de9d727b0 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -260,43 +260,6 @@ scsi_cmd_stack_free(ctlr_info_t *h) } #if 0 -static int xmargin=8; -static int amargin=60; - -static void -print_bytes (unsigned char *c, int len, int hex, int ascii) -{ - - int i; - unsigned char *x; - - if (hex) - { - x = c; - for (i=0;i0) printk("\n"); - if ((i % xmargin) == 0) printk("0x%04x:", i); - printk(" %02x", *x); - x++; - } - printk("\n"); - } - if (ascii) - { - x = c; - for (i=0;i0) printk("\n"); - if ((i % amargin) == 0) printk("0x%04x:", i); - if (*x > 26 && *x < 128) printk("%c", *x); - else printk("."); - x++; - } - printk("\n"); - } -} - static void print_cmd(CommandList_struct *cp) { @@ -305,30 +268,13 @@ print_cmd(CommandList_struct *cp) printk("sgtot:%d\n", cp->Header.SGTotal); printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper, cp->Header.Tag.lower); - printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - cp->Header.LUN.LunAddrBytes[0], - cp->Header.LUN.LunAddrBytes[1], - cp->Header.LUN.LunAddrBytes[2], - cp->Header.LUN.LunAddrBytes[3], - cp->Header.LUN.LunAddrBytes[4], - cp->Header.LUN.LunAddrBytes[5], - cp->Header.LUN.LunAddrBytes[6], - cp->Header.LUN.LunAddrBytes[7]); + printk("LUN:0x%8phN\n", cp->Header.LUN.LunAddrBytes); printk("CDBLen:%d\n", cp->Request.CDBLen); printk("Type:%d\n",cp->Request.Type.Type); printk("Attr:%d\n",cp->Request.Type.Attribute); printk(" Dir:%d\n",cp->Request.Type.Direction); printk("Timeout:%d\n",cp->Request.Timeout); - printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x" - " %02x %02x %02x %02x %02x %02x %02x %02x\n", - cp->Request.CDB[0], cp->Request.CDB[1], - cp->Request.CDB[2], cp->Request.CDB[3], - cp->Request.CDB[4], cp->Request.CDB[5], - cp->Request.CDB[6], cp->Request.CDB[7], - cp->Request.CDB[8], cp->Request.CDB[9], - cp->Request.CDB[10], cp->Request.CDB[11], - cp->Request.CDB[12], cp->Request.CDB[13], - cp->Request.CDB[14], cp->Request.CDB[15]), + printk("CDB: %16ph\n", cp->Request.CDB); printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n", cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower, cp->ErrDesc.Len); @@ -340,9 +286,7 @@ print_cmd(CommandList_struct *cp) printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size); printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num); printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value); - } - #endif static int @@ -782,8 +726,10 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, "reported\n", c); break; case CMD_INVALID: { - /* print_bytes(c, sizeof(*c), 1, 0); - print_cmd(c); */ + /* + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, c, sizeof(*c), false); + print_cmd(c); + */ /* We get CMD_INVALID if you address a non-existent tape drive instead of a selection timeout (no response). You will see this if you yank out a tape drive, then try to access it. This is kind of a shame @@ -985,8 +931,10 @@ cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c) dev_warn(&h->pdev->dev, "%p is reported invalid (probably means " "target device no longer present)\n", c); - /* print_bytes((unsigned char *) c, sizeof(*c), 1, 0); - print_cmd(c); */ + /* + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, c, sizeof(*c), false); + print_cmd(c); + */ } break; case CMD_PROTOCOL_ERR: From e3ce73d69aff44421d7899b235fec5ac2c306ff4 Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Mon, 17 Oct 2016 17:09:24 -0700 Subject: [PATCH 112/256] scsi: ufs: fix bugs related to null pointer access and array size In this change there are a few fixes of possible NULL pointer access and possible access to index that exceeds array boundaries. Signed-off-by: Yaniv Gardi Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs.h | 3 ++- drivers/scsi/ufs/ufshcd.c | 25 +++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 845b874e2977..7a6ccb680049 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -46,6 +46,7 @@ #define QUERY_DESC_HDR_SIZE 2 #define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ (sizeof(struct utp_upiu_header))) +#define RESPONSE_UPIU_SENSE_DATA_LENGTH 18 #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ @@ -416,7 +417,7 @@ struct utp_cmd_rsp { __be32 residual_transfer_count; __be32 reserved[4]; __be16 sense_data_len; - u8 sense_data[18]; + u8 sense_data[RESPONSE_UPIU_SENSE_DATA_LENGTH]; }; /** diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 571a2f64a01d..d46709ed0555 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -889,10 +889,14 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) int len; if (lrbp->sense_buffer && ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) { + int len_to_copy; + len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len); + len_to_copy = min_t(int, RESPONSE_UPIU_SENSE_DATA_LENGTH, len); + memcpy(lrbp->sense_buffer, lrbp->ucd_rsp_ptr->sr.sense_data, - min_t(int, len, SCSI_SENSE_BUFFERSIZE)); + min_t(int, len_to_copy, SCSI_SENSE_BUFFERSIZE)); } } @@ -6091,7 +6095,10 @@ EXPORT_SYMBOL(ufshcd_system_suspend); int ufshcd_system_resume(struct ufs_hba *hba) { - if (!hba || !hba->is_powered || pm_runtime_suspended(hba->dev)) + if (!hba) + return -EINVAL; + + if (!hba->is_powered || pm_runtime_suspended(hba->dev)) /* * Let the runtime resume take care of resuming * if runtime suspended. @@ -6112,7 +6119,10 @@ EXPORT_SYMBOL(ufshcd_system_resume); */ int ufshcd_runtime_suspend(struct ufs_hba *hba) { - if (!hba || !hba->is_powered) + if (!hba) + return -EINVAL; + + if (!hba->is_powered) return 0; return ufshcd_suspend(hba, UFS_RUNTIME_PM); @@ -6142,10 +6152,13 @@ EXPORT_SYMBOL(ufshcd_runtime_suspend); */ int ufshcd_runtime_resume(struct ufs_hba *hba) { - if (!hba || !hba->is_powered) + if (!hba) + return -EINVAL; + + if (!hba->is_powered) return 0; - else - return ufshcd_resume(hba, UFS_RUNTIME_PM); + + return ufshcd_resume(hba, UFS_RUNTIME_PM); } EXPORT_SYMBOL(ufshcd_runtime_resume); From ad1a1b9cd67a4b5bee8a62454336d94f9e816c1f Mon Sep 17 00:00:00 2001 From: Gilad Broner Date: Mon, 17 Oct 2016 17:09:36 -0700 Subject: [PATCH 113/256] scsi: ufs: commit descriptors before setting the doorbell Add a write memory barrier to make sure descriptors prepared are actually written to memory before ringing the doorbell. We have also added the write memory barrier after ringing the doorbell register so that controller sees the new request immediately. Signed-off-by: Gilad Broner Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d46709ed0555..2fbbe62f3696 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -878,6 +878,8 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) ufshcd_clk_scaling_start_busy(hba); __set_bit(task_tag, &hba->outstanding_reqs); ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL); + /* Make sure that doorbell is committed immediately */ + wmb(); } /** @@ -1475,6 +1477,8 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) clear_bit_unlock(tag, &hba->lrb_in_use); goto out; } + /* Make sure descriptors are ready before ringing the doorbell */ + wmb(); /* issue command to the controller */ spin_lock_irqsave(hba->host->host_lock, flags); @@ -1585,6 +1589,8 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, time_left = wait_for_completion_timeout(hba->dev_cmd.complete, msecs_to_jiffies(max_timeout)); + /* Make sure descriptors are ready before ringing the doorbell */ + wmb(); spin_lock_irqsave(hba->host->host_lock, flags); hba->dev_cmd.complete = NULL; if (likely(time_left)) { @@ -4322,6 +4328,8 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, wmb(); ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL); + /* Make sure that doorbell is committed immediately */ + wmb(); spin_unlock_irqrestore(host->host_lock, flags); From dcea0bfbc4cb6796a222ffaeebd77a0a89a1babc Mon Sep 17 00:00:00 2001 From: Gilad Broner Date: Mon, 17 Oct 2016 17:09:48 -0700 Subject: [PATCH 114/256] scsi: ufs: fix sense buffer size to 18 bytes According to UFS device specification, sense data can be only 18 bytes long, this change makes the changes accordingly. Signed-off-by: Gilad Broner Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2fbbe62f3696..6c3c259b6f37 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -45,6 +45,8 @@ #include "ufs_quirks.h" #include "unipro.h" +#define UFSHCD_REQ_SENSE_SIZE 18 + #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) @@ -898,7 +900,7 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) memcpy(lrbp->sense_buffer, lrbp->ucd_rsp_ptr->sr.sense_data, - min_t(int, len_to_copy, SCSI_SENSE_BUFFERSIZE)); + min_t(int, len_to_copy, UFSHCD_REQ_SENSE_SIZE)); } } @@ -1463,7 +1465,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) WARN_ON(lrbp->cmd); lrbp->cmd = cmd; - lrbp->sense_bufflen = SCSI_SENSE_BUFFERSIZE; + lrbp->sense_bufflen = UFSHCD_REQ_SENSE_SIZE; lrbp->sense_buffer = cmd->sense_buffer; lrbp->task_tag = tag; lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun); @@ -5594,19 +5596,19 @@ ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp) 0, 0, 0, - SCSI_SENSE_BUFFERSIZE, + UFSHCD_REQ_SENSE_SIZE, 0}; char *buffer; int ret; - buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + buffer = kzalloc(UFSHCD_REQ_SENSE_SIZE, GFP_KERNEL); if (!buffer) { ret = -ENOMEM; goto out; } ret = scsi_execute_req_flags(sdp, cmd, DMA_FROM_DEVICE, buffer, - SCSI_SENSE_BUFFERSIZE, NULL, + UFSHCD_REQ_SENSE_SIZE, NULL, msecs_to_jiffies(1000), 3, NULL, REQ_PM); if (ret) pr_err("%s: failed with err %d\n", __func__, ret); From a508253d0916a0c5973081c4059425ec04e324c8 Mon Sep 17 00:00:00 2001 From: Gilad Broner Date: Mon, 17 Oct 2016 17:10:00 -0700 Subject: [PATCH 115/256] scsi: ufs: suspend clock scaling for failed runtime_resume During runtime resume operation, clock scaling may get indirectly resumed via call to ufshcd_set_dev_pwr_mode(): Start/Stop Unit command times out and SCSI error handling ultimately calls the host reset handler to recover, during which clock scaling is resumed. Error case exit path of runtime resume will disable clocks. As clock scaling was already resumed, it will get scheduled later on and try to access UFS registers while clocks are disabled, resulting in unclocked register access. Signed-off-by: Gilad Broner Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 40 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6c3c259b6f37..93e2fe82822f 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -600,6 +600,20 @@ static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba) return false; } +static void ufshcd_suspend_clkscaling(struct ufs_hba *hba) +{ + if (ufshcd_is_clkscaling_enabled(hba)) { + devfreq_suspend_device(hba->devfreq); + hba->clk_scaling.window_start_t = 0; + } +} + +static void ufshcd_resume_clkscaling(struct ufs_hba *hba) +{ + if (ufshcd_is_clkscaling_enabled(hba)) + devfreq_resume_device(hba->devfreq); +} + static void ufshcd_ungate_work(struct work_struct *work) { int ret; @@ -633,8 +647,7 @@ static void ufshcd_ungate_work(struct work_struct *work) hba->clk_gating.is_suspended = false; } unblock_reqs: - if (ufshcd_is_clkscaling_enabled(hba)) - devfreq_resume_device(hba->devfreq); + ufshcd_resume_clkscaling(hba); scsi_unblock_requests(hba->host); } @@ -733,10 +746,7 @@ static void ufshcd_gate_work(struct work_struct *work) ufshcd_set_link_hibern8(hba); } - if (ufshcd_is_clkscaling_enabled(hba)) { - devfreq_suspend_device(hba->devfreq); - hba->clk_scaling.window_start_t = 0; - } + ufshcd_suspend_clkscaling(hba); if (!ufshcd_is_link_active(hba)) ufshcd_setup_clocks(hba, false); @@ -5076,8 +5086,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) hba->is_init_prefetch = true; /* Resume devfreq after UFS device is detected */ - if (ufshcd_is_clkscaling_enabled(hba)) - devfreq_resume_device(hba->devfreq); + ufshcd_resume_clkscaling(hba); out: /* @@ -5583,6 +5592,7 @@ static void ufshcd_hba_exit(struct ufs_hba *hba) if (hba->is_powered) { ufshcd_variant_hba_exit(hba); ufshcd_setup_vreg(hba, false); + ufshcd_suspend_clkscaling(hba); ufshcd_setup_clocks(hba, false); ufshcd_setup_hba_vreg(hba, false); hba->is_powered = false; @@ -5911,10 +5921,8 @@ disable_clks: * for pending clock scaling work to be done before clocks are * turned off. */ - if (ufshcd_is_clkscaling_enabled(hba)) { - devfreq_suspend_device(hba->devfreq); - hba->clk_scaling.window_start_t = 0; - } + ufshcd_suspend_clkscaling(hba); + /* * Call vendor specific suspend callback. As these callbacks may access * vendor specific host controller register space call them before the @@ -5941,6 +5949,7 @@ disable_clks: goto out; set_link_active: + ufshcd_resume_clkscaling(hba); ufshcd_vreg_set_hpm(hba); if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba)) ufshcd_set_link_active(hba); @@ -6028,8 +6037,7 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_urgent_bkops(hba); hba->clk_gating.is_suspended = false; - if (ufshcd_is_clkscaling_enabled(hba)) - devfreq_resume_device(hba->devfreq); + ufshcd_resume_clkscaling(hba); /* Schedule clock gating in case of no access to UFS device yet */ ufshcd_release(hba); @@ -6043,6 +6051,7 @@ disable_vreg: ufshcd_vreg_set_lpm(hba); disable_irq_and_vops_clks: ufshcd_disable_irq(hba); + ufshcd_suspend_clkscaling(hba); ufshcd_setup_clocks(hba, false); out: hba->pm_op_in_progress = 0; @@ -6529,8 +6538,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) goto out_remove_scsi_host; } /* Suspend devfreq until the UFS device is detected */ - devfreq_suspend_device(hba->devfreq); - hba->clk_scaling.window_start_t = 0; + ufshcd_suspend_clkscaling(hba); } /* Hold auto suspend until async scan completes */ From 8643ae66ce749f63ea0de928f5059b7b5f8b30cd Mon Sep 17 00:00:00 2001 From: Dov Levenglick Date: Mon, 17 Oct 2016 17:10:14 -0700 Subject: [PATCH 116/256] scsi: ufs: fail ufshcd_probe_hba() if power configuration fails In case the power configuration fails, skip further processing of the probing function and return immediately. This has 2 reasons: 1. Don't allow the UFS to continue running in PWM 2. Avoid multiple calls to pm_runtime_put_sync() when not in error handling or power management contexts Signed-off-by: Dov Levenglick Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 93e2fe82822f..d2930fb8b446 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5051,9 +5051,11 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) __func__); } else { ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); - if (ret) + if (ret) { dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", __func__, ret); + goto out; + } } /* set the state as operational after switching to desired gear */ From f2a785ac23125fa0774327d39e837e45cf28fe92 Mon Sep 17 00:00:00 2001 From: Venkat Gopalakrishnan Date: Mon, 17 Oct 2016 17:10:53 -0700 Subject: [PATCH 117/256] scsi: ufshcd: Fix race between clk scaling and ungate work The ungate work turns on the clock before it exits hibern8, if the link was put in hibern8 during clock gating work. There occurs a race condition when clock scaling work calls ufshcd_hold() to make sure low power states cannot be entered, but that returns by checking only whether the clocks are on. This causes the clock scaling work to issue UIC commands when the link is in hibern8 causing failures. Make sure we exit hibern8 state before returning from ufshcd_hold(). Callstacks for race condition: ufshcd_scale_gear ufshcd_devfreq_scale ufshcd_devfreq_target update_devfreq devfreq_monitor process_one_work worker_thread kthread ret_from_fork ufshcd_uic_hibern8_exit ufshcd_ungate_work process_one_work worker_thread kthread ret_from_fork Signed-off-by: Venkat Gopalakrishnan Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d2930fb8b446..5ad4480afd01 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -675,6 +675,21 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) start: switch (hba->clk_gating.state) { case CLKS_ON: + /* + * Wait for the ungate work to complete if in progress. + * Though the clocks may be in ON state, the link could + * still be in hibner8 state if hibern8 is allowed + * during clock gating. + * Make sure we exit hibern8 state also in addition to + * clocks being ON. + */ + if (ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_link_hibern8(hba)) { + spin_unlock_irqrestore(hba->host->host_lock, flags); + flush_work(&hba->clk_gating.ungate_work); + spin_lock_irqsave(hba->host->host_lock, flags); + goto start; + } break; case REQ_CLKS_OFF: if (cancel_delayed_work(&hba->clk_gating.gate_work)) { From 3f0c06de80d3898e68adcaba83a2b7ac51cf23d8 Mon Sep 17 00:00:00 2001 From: Venkat Gopalakrishnan Date: Mon, 17 Oct 2016 17:11:07 -0700 Subject: [PATCH 118/256] scsi: ufs: optimize clock gate work In a case where gate work is called as part of cancel work from ungate path the clk state would be marked as REQ_CLKS_ON. There is no point gating the clocks and then end up turning them ON immediately in ungate work, save time by skipping the gate work and change the clk state to CLKS_ON as they are not turned off yet. Signed-off-by: Venkat Gopalakrishnan Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5ad4480afd01..304adce3bdbe 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -739,7 +739,14 @@ static void ufshcd_gate_work(struct work_struct *work) unsigned long flags; spin_lock_irqsave(hba->host->host_lock, flags); - if (hba->clk_gating.is_suspended) { + /* + * In case you are here to cancel this work the gating state + * would be marked as REQ_CLKS_ON. In this case save time by + * skipping the gating work and exit after changing the clock + * state to CLKS_ON. + */ + if (hba->clk_gating.is_suspended || + (hba->clk_gating.state == REQ_CLKS_ON)) { hba->clk_gating.state = CLKS_ON; goto rel_lock; } From d5c3eb26d9ad78a2705ec675dd2399e985c5ee52 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 21 Oct 2016 14:10:53 -0700 Subject: [PATCH 119/256] scsi: libfc: Don't have fc_exch_find log errors on a new exchange With the error message I added in "libfc: sanity check cpu number extracted from xid" I didn't account for the fact that fc_exch_find is called with FC_XID_UNKNOWN at the start of a new exchange if we are the responder. It doesn't come up with the initiator much, but that's basically every exchange for a target. By checking the xid for FC_XID_UNKNOWN first, we not only prevent the erroneous error message, but skip the unnecessary lookup attempt as well. [mkp: applied by hand due to conflict with Hannes' libfc patch series] Signed-off-by: Chris Leech Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 442a6c1d5efc..42bcf7f3a0f9 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -939,6 +939,9 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) struct fc_exch *ep = NULL; u16 cpu = xid & fc_cpu_mask; + if (xid == FC_XID_UNKNOWN) + return NULL; + if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) { pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:", lport->host->host_no, lport->port_id, xid, cpu); From f46e7cd36b5f2ce2bfb567e278a10ca717f85b84 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 24 Oct 2016 17:51:55 +0200 Subject: [PATCH 120/256] scsi: advansys: fix build warning for PCI=n The advansys probe function tries to handle both ISA and PCI cases, each hidden in an #ifdef when unused. This leads to a warning indicating that when PCI is disabled we could be using uninitialized data: drivers/scsi/advansys.c: In function advansys_board_found : drivers/scsi/advansys.c:11036:5: error: ret may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/scsi/advansys.c:10928:28: note: ret was declared here drivers/scsi/advansys.c:11309:8: error: share_irq may be used uninitialized in this function [-Werror=maybe-uninitialized] drivers/scsi/advansys.c:10928:6: note: share_irq was declared here This cannot happen in practice because the hardware in question only exists for PCI, but changing the code to just error out here is better for consistency and avoids the warning. Signed-off-by: Arnd Bergmann Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/advansys.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index febbd83e2ecd..81dd0927246b 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -11030,6 +11030,9 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop, ASC_DBG(2, "AdvInitGetConfig()\n"); ret = AdvInitGetConfig(pdev, shost) ? -ENODEV : 0; +#else + share_irq = 0; + ret = -ENODEV; #endif /* CONFIG_PCI */ } From b2fe6be798754a222ee5f22b90d175739c75c8c1 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:32 +0530 Subject: [PATCH 121/256] scsi: mpt3sas: Fix for improper info displayed in var log, while blocking or unblocking the device. Return value and Device_handle Arguments passed in correct order to match with its format string. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 209a969a979d..282ca40d62a5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2837,7 +2837,7 @@ _scsih_internal_device_block(struct scsi_device *sdev, if (r == -EINVAL) sdev_printk(KERN_WARNING, sdev, "device_block failed with return(%d) for handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle, r); + r, sas_device_priv_data->sas_target->handle); } /** @@ -2867,20 +2867,20 @@ _scsih_internal_device_unblock(struct scsi_device *sdev, sdev_printk(KERN_WARNING, sdev, "device_unblock failed with return(%d) for handle(0x%04x) " "performing a block followed by an unblock\n", - sas_device_priv_data->sas_target->handle, r); + r, sas_device_priv_data->sas_target->handle); sas_device_priv_data->block = 1; r = scsi_internal_device_block(sdev); if (r) sdev_printk(KERN_WARNING, sdev, "retried device_block " "failed with return(%d) for handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle, r); + r, sas_device_priv_data->sas_target->handle); sas_device_priv_data->block = 0; r = scsi_internal_device_unblock(sdev, SDEV_RUNNING); if (r) sdev_printk(KERN_WARNING, sdev, "retried device_unblock" " failed with return(%d) for handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle, r); + r, sas_device_priv_data->sas_target->handle); } } From bb3506612346c2e54bb71717d9b8cf7a7d188ead Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:33 +0530 Subject: [PATCH 122/256] scsi: mpt3sas: Fix for incorrect numbers for MSIX vectors enabled when non RDPQ card is enumerated first. No. of MSIX vectors supported = min (Total no. of CPU cores, MSIX vectors supported by card) when RDPQ is disabled "max_msix_vectors" module parameter which was declared as global was set to '8' and hence if there are more than one card in system among which if RDPQ disabled card is enumerated first then only 8 MSIX vectors was getting enabled for all the cards(including RDPQ enabled card,which can support more than 8 MSIX vectors). Used local variable instead of global variable ,if RDPQ is disabled this local variable is set to '8' else it is set to "max_msix_vectors" (by default this is set to -1, whose value can be set by user during driver load time).So now regardless of whether RDPQ disabled card is enumerated first or RDPQ enabled card is enumerated first , MSIX vectors enabled depends on the cards capability. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index a1a5ceb42ce6..4ea81e134365 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1959,7 +1959,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) { struct msix_entry *entries, *a; int r; - int i; + int i, local_max_msix_vectors; u8 try_msix = 0; if (msix_disable == -1 || msix_disable == 0) @@ -1979,13 +1979,15 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) ioc->cpu_count, max_msix_vectors); if (!ioc->rdpq_array_enable && max_msix_vectors == -1) - max_msix_vectors = 8; + local_max_msix_vectors = 8; + else + local_max_msix_vectors = max_msix_vectors; - if (max_msix_vectors > 0) { - ioc->reply_queue_count = min_t(int, max_msix_vectors, + if (local_max_msix_vectors > 0) { + ioc->reply_queue_count = min_t(int, local_max_msix_vectors, ioc->reply_queue_count); ioc->msix_vector_count = ioc->reply_queue_count; - } else if (max_msix_vectors == 0) + } else if (local_max_msix_vectors == 0) goto try_ioapic; if (ioc->msix_vector_count < ioc->cpu_count) From c696f7b83edeac804e898952058089143f49ca0a Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:34 +0530 Subject: [PATCH 123/256] scsi: mpt3sas: Implement device_remove_in_progress check in IOCTL path When device missing event arrives, device_remove_in_progress bit will be set and hence driver has to stop sending IOCTL commands.Now the check has been added in IOCTL path to test device_remove_in_progress bit is set, if so then IOCTL will be failed printing failure message. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 19 ++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 5 +++ drivers/scsi/mpt3sas/mpt3sas_ctl.c | 46 +++++++++++++++++++++++----- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 24 ++++++++++++++- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 4ea81e134365..9ad7f7ceced8 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5334,6 +5334,21 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) goto out_free_resources; } + /* allocate memory for pending OS device add list */ + ioc->pend_os_device_add_sz = (ioc->facts.MaxDevHandle / 8); + if (ioc->facts.MaxDevHandle % 8) + ioc->pend_os_device_add_sz++; + ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz, + GFP_KERNEL); + if (!ioc->pend_os_device_add) + goto out_free_resources; + + ioc->device_remove_in_progress_sz = ioc->pend_os_device_add_sz; + ioc->device_remove_in_progress = + kzalloc(ioc->device_remove_in_progress_sz, GFP_KERNEL); + if (!ioc->device_remove_in_progress) + goto out_free_resources; + ioc->fwfault_debug = mpt3sas_fwfault_debug; /* base internal command bits */ @@ -5416,6 +5431,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) kfree(ioc->reply_post_host_index); kfree(ioc->pd_handles); kfree(ioc->blocking_handles); + kfree(ioc->device_remove_in_progress); + kfree(ioc->pend_os_device_add); kfree(ioc->tm_cmds.reply); kfree(ioc->transport_cmds.reply); kfree(ioc->scsih_cmds.reply); @@ -5457,6 +5474,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) kfree(ioc->reply_post_host_index); kfree(ioc->pd_handles); kfree(ioc->blocking_handles); + kfree(ioc->device_remove_in_progress); + kfree(ioc->pend_os_device_add); kfree(ioc->pfacts); kfree(ioc->ctl_cmds.reply); kfree(ioc->ctl_cmds.sense); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 3e71bc1b4a80..4221a4d25ae2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1079,6 +1079,9 @@ struct MPT3SAS_ADAPTER { void *pd_handles; u16 pd_handles_sz; + void *pend_os_device_add; + u16 pend_os_device_add_sz; + /* config page */ u16 config_page_sz; void *config_page; @@ -1187,6 +1190,8 @@ struct MPT3SAS_ADAPTER { struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event; struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi; struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi; + void *device_remove_in_progress; + u16 device_remove_in_progress_sz; }; typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 26cdc127ac89..de720c9dad72 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -654,6 +654,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, size_t data_in_sz = 0; long ret; u16 wait_state_count; + u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE; issue_reset = 0; @@ -738,10 +739,13 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, data_in_sz = karg.data_in_size; if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - if (!le16_to_cpu(mpi_request->FunctionDependent1) || - le16_to_cpu(mpi_request->FunctionDependent1) > - ioc->facts.MaxDevHandle) { + mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT || + mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH) { + + device_handle = le16_to_cpu(mpi_request->FunctionDependent1); + if (!device_handle || (device_handle > + ioc->facts.MaxDevHandle)) { ret = -EINVAL; mpt3sas_base_free_smid(ioc, smid); goto out; @@ -797,12 +801,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, scsiio_request->SenseBufferLowAddress = mpt3sas_base_get_sense_buffer_dma(ioc, smid); memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); + if (test_bit(device_handle, ioc->device_remove_in_progress)) { + dtmprintk(ioc, pr_info(MPT3SAS_FMT + "handle(0x%04x) :ioctl failed due to device removal in progress\n", + ioc->name, device_handle)); + mpt3sas_base_free_smid(ioc, smid); + ret = -EINVAL; + goto out; + } ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) - mpt3sas_base_put_smid_scsi_io(ioc, smid, - le16_to_cpu(mpi_request->FunctionDependent1)); + mpt3sas_base_put_smid_scsi_io(ioc, smid, device_handle); else mpt3sas_base_put_smid_default(ioc, smid); break; @@ -827,6 +837,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, } } + if (test_bit(device_handle, ioc->device_remove_in_progress)) { + dtmprintk(ioc, pr_info(MPT3SAS_FMT + "handle(0x%04x) :ioctl failed due to device removal in progress\n", + ioc->name, device_handle)); + mpt3sas_base_free_smid(ioc, smid); + ret = -EINVAL; + goto out; + } mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu( tm_request->DevHandle)); ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, @@ -866,6 +884,20 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, break; } case MPI2_FUNCTION_SATA_PASSTHROUGH: + { + if (test_bit(device_handle, ioc->device_remove_in_progress)) { + dtmprintk(ioc, pr_info(MPT3SAS_FMT + "handle(0x%04x) :ioctl failed due to device removal in progress\n", + ioc->name, device_handle)); + mpt3sas_base_free_smid(ioc, smid); + ret = -EINVAL; + goto out; + } + ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, + data_in_sz); + mpt3sas_base_put_smid_default(ioc, smid); + break; + } case MPI2_FUNCTION_FW_DOWNLOAD: case MPI2_FUNCTION_FW_UPLOAD: { diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 282ca40d62a5..9584d6b00c9a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -788,6 +788,11 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, list_add_tail(&sas_device->list, &ioc->sas_device_list); spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (ioc->hide_drives) { + clear_bit(sas_device->handle, ioc->pend_os_device_add); + return; + } + if (!mpt3sas_transport_port_add(ioc, sas_device->handle, sas_device->sas_address_parent)) { _scsih_sas_device_remove(ioc, sas_device); @@ -803,7 +808,8 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, sas_device->sas_address_parent); _scsih_sas_device_remove(ioc, sas_device); } - } + } else + clear_bit(sas_device->handle, ioc->pend_os_device_add); } /** @@ -3138,6 +3144,8 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) if (test_bit(handle, ioc->pd_handles)) return; + clear_bit(handle, ioc->pend_os_device_add); + spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); if (sas_device && sas_device->starget && @@ -3192,6 +3200,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + set_bit(handle, ioc->device_remove_in_progress); mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); @@ -3326,6 +3335,11 @@ _scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid, le16_to_cpu(mpi_reply->IOCStatus), le32_to_cpu(mpi_reply->IOCLogInfo))); + if (le16_to_cpu(mpi_reply->IOCStatus) == + MPI2_IOCSTATUS_SUCCESS) { + clear_bit(le16_to_cpu(mpi_reply->DevHandle), + ioc->device_remove_in_progress); + } } else { pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); @@ -5449,6 +5463,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); if (!(_scsih_is_end_device(device_info))) return -1; + set_bit(handle, ioc->pend_os_device_add); sas_address = le64_to_cpu(sas_device_pg0.SASAddress); /* check if device is present */ @@ -5467,6 +5482,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, sas_device = mpt3sas_get_sdev_by_addr(ioc, sas_address); if (sas_device) { + clear_bit(handle, ioc->pend_os_device_add); sas_device_put(sas_device); return -1; } @@ -5790,6 +5806,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, _scsih_check_device(ioc, sas_address, handle, phy_number, link_rate); + if (!test_bit(handle, ioc->pend_os_device_add)) + break; + case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: @@ -7707,6 +7726,9 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) complete(&ioc->tm_cmds.done); } + memset(ioc->pend_os_device_add, 0, ioc->pend_os_device_add_sz); + memset(ioc->device_remove_in_progress, 0, + ioc->device_remove_in_progress_sz); _scsih_fw_event_cleanup_queue(ioc); _scsih_flush_running_cmds(ioc); break; From 58e2fe7afe2194be1dab12fdaf4d51cc6f109de8 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:35 +0530 Subject: [PATCH 124/256] scsi: mpt3sas: Remove unused macro "MPT_DEVICE_TLR_ON" Removing macro "MPT_DEVICE_TLR_ON" defined in header file as its unused Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 4221a4d25ae2..e923c9170000 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -375,7 +375,6 @@ struct MPT3SAS_TARGET { * per device private data */ #define MPT_DEVICE_FLAGS_INIT 0x01 -#define MPT_DEVICE_TLR_ON 0x02 #define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003) #define MFG_PAGE10_HIDE_ALL_DISKS (0x00) From e270263ec1e14b835890cbc32cf32db8b661bd3b Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:36 +0530 Subject: [PATCH 125/256] scsi: mpt3sas: Bump driver version as "14.100.00.00" Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index e923c9170000..6f03a86ba1da 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -73,8 +73,8 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "13.100.00.00" -#define MPT3SAS_MAJOR_VERSION 13 +#define MPT3SAS_DRIVER_VERSION "14.100.00.00" +#define MPT3SAS_MAJOR_VERSION 14 #define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 From 998f26aedf41bc5cdce3b3c9233ac0e0672fa307 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:37 +0530 Subject: [PATCH 126/256] scsi: mpt3sas: Added Device ID's for SAS35 devices and updated MPI header. Added Device ID's for SAS35 devices (Ventura, Crusader, Harpoon & Tomcat) and updated mpi header file for the same. Also added "is_gen35_ioc" to MPT3SAS_ADAPTER structure for identifying SAS35 adapters. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 7 +++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 1 + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 5 ++++- drivers/scsi/mpt3sas/mpt3sas_ctl.h | 1 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 31 ++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index 95356a82ee99..fa61baf7c74d 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h @@ -478,6 +478,13 @@ typedef struct _MPI2_CONFIG_REPLY { #define MPI26_MFGPAGE_DEVID_SAS3324_3 (0x00C2) #define MPI26_MFGPAGE_DEVID_SAS3324_4 (0x00C3) +#define MPI26_MFGPAGE_DEVID_SAS3516 (0x00AA) +#define MPI26_MFGPAGE_DEVID_SAS3516_1 (0x00AB) +#define MPI26_MFGPAGE_DEVID_SAS3416 (0x00AC) +#define MPI26_MFGPAGE_DEVID_SAS3508 (0x00AD) +#define MPI26_MFGPAGE_DEVID_SAS3508_1 (0x00AE) +#define MPI26_MFGPAGE_DEVID_SAS3408 (0x00AF) + /*Manufacturing Page 0 */ typedef struct _MPI2_CONFIG_PAGE_MAN_0 { diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 6f03a86ba1da..3d75c57215b3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1191,6 +1191,7 @@ struct MPT3SAS_ADAPTER { struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi; void *device_remove_in_progress; u16 device_remove_in_progress_sz; + u8 is_gen35_ioc; }; typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index de720c9dad72..a287bfb70784 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -1096,7 +1096,10 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg) break; case MPI25_VERSION: case MPI26_VERSION: - karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3; + if (ioc->is_gen35_ioc) + karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS35; + else + karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3; strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION); break; } diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h index 89408356d252..f3e17a8c1b07 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h @@ -143,6 +143,7 @@ struct mpt3_ioctl_pci_info { #define MPT2_IOCTL_INTERFACE_SAS2 (0x04) #define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05) #define MPT3_IOCTL_INTERFACE_SAS3 (0x06) +#define MPT3_IOCTL_INTERFACE_SAS35 (0x07) #define MPT2_IOCTL_VERSION_LENGTH (32) /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 9584d6b00c9a..521849d5d598 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -8660,6 +8660,12 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev) case MPI26_MFGPAGE_DEVID_SAS3324_2: case MPI26_MFGPAGE_DEVID_SAS3324_3: case MPI26_MFGPAGE_DEVID_SAS3324_4: + case MPI26_MFGPAGE_DEVID_SAS3508: + case MPI26_MFGPAGE_DEVID_SAS3508_1: + case MPI26_MFGPAGE_DEVID_SAS3408: + case MPI26_MFGPAGE_DEVID_SAS3516: + case MPI26_MFGPAGE_DEVID_SAS3516_1: + case MPI26_MFGPAGE_DEVID_SAS3416: return MPI26_VERSION; } return 0; @@ -8728,6 +8734,18 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->hba_mpi_version_belonged = hba_mpi_version; ioc->id = mpt3_ids++; sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME); + switch (pdev->device) { + case MPI26_MFGPAGE_DEVID_SAS3508: + case MPI26_MFGPAGE_DEVID_SAS3508_1: + case MPI26_MFGPAGE_DEVID_SAS3408: + case MPI26_MFGPAGE_DEVID_SAS3516: + case MPI26_MFGPAGE_DEVID_SAS3516_1: + case MPI26_MFGPAGE_DEVID_SAS3416: + ioc->is_gen35_ioc = 1; + break; + default: + ioc->is_gen35_ioc = 0; + } if ((ioc->hba_mpi_version_belonged == MPI25_VERSION && pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) || (ioc->hba_mpi_version_belonged == MPI26_VERSION)) @@ -9134,6 +9152,19 @@ static const struct pci_device_id mpt3sas_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_4, PCI_ANY_ID, PCI_ANY_ID }, + /* Ventura, Crusader, Harpoon & Tomcat ~ 3516, 3416, 3508 & 3408*/ + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3508, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3508_1, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3408, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3516, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3516_1, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3416, + PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table); From 0bb337c97c2cdc9c0215205a81406f968c1dcae0 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:38 +0530 Subject: [PATCH 127/256] scsi: mpt3sas: Increased/Additional MSIX support for SAS35 devices. For SAS35 devices MSIX vectors are inceased to 128 from 96. To support this Reply post host index register count is increased to 16. Also variable msix96_vector is replaced with combined_reply_queue and variable combined_reply_index_count is added to set different values for SAS3 and SAS35 devices. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 14 +++++++------- drivers/scsi/mpt3sas/mpt3sas_base.h | 8 +++++--- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 11 +++++++++-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 9ad7f7ceced8..43cdc02e6a04 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1078,7 +1078,7 @@ _base_interrupt(int irq, void *bus_id) * new reply host index value in ReplyPostIndex Field and msix_index * value in MSIxIndex field. */ - if (ioc->msix96_vector) + if (ioc->combined_reply_queue) writel(reply_q->reply_post_host_index | ((msix_index & 7) << MPI2_RPHI_MSIX_INDEX_SHIFT), ioc->replyPostRegisterIndex[msix_index/8]); @@ -2052,7 +2052,7 @@ mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) _base_free_irq(ioc); _base_disable_msix(ioc); - if (ioc->msix96_vector) { + if (ioc->combined_reply_queue) { kfree(ioc->replyPostRegisterIndex); ioc->replyPostRegisterIndex = NULL; } @@ -2162,7 +2162,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) /* Use the Combined reply queue feature only for SAS3 C0 & higher * revision HBAs and also only when reply queue count is greater than 8 */ - if (ioc->msix96_vector && ioc->reply_queue_count > 8) { + if (ioc->combined_reply_queue && ioc->reply_queue_count > 8) { /* Determine the Supplemental Reply Post Host Index Registers * Addresse. Supplemental Reply Post Host Index Registers * starts at offset MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET and @@ -2170,7 +2170,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET from previous one. */ ioc->replyPostRegisterIndex = kcalloc( - MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT, + ioc->combined_reply_index_count, sizeof(resource_size_t *), GFP_KERNEL); if (!ioc->replyPostRegisterIndex) { dfailprintk(ioc, printk(MPT3SAS_FMT @@ -2180,14 +2180,14 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) goto out_fail; } - for (i = 0; i < MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT; i++) { + for (i = 0; i < ioc->combined_reply_index_count; i++) { ioc->replyPostRegisterIndex[i] = (resource_size_t *) ((u8 *)&ioc->chip->Doorbell + MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET + (i * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET)); } } else - ioc->msix96_vector = 0; + ioc->combined_reply_queue = 0; if (ioc->is_warpdrive) { ioc->reply_post_host_index[0] = (resource_size_t __iomem *) @@ -5140,7 +5140,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) /* initialize reply post host index */ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - if (ioc->msix96_vector) + if (ioc->combined_reply_queue) writel((reply_q->msix_index & 7)<< MPI2_RPHI_MSIX_INDEX_SHIFT, ioc->replyPostRegisterIndex[reply_q->msix_index/8]); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 3d75c57215b3..acb410628671 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -300,8 +300,9 @@ * There are twelve Supplemental Reply Post Host Index Registers * and each register is at offset 0x10 bytes from the previous one. */ -#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT 12 -#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET (0x10) +#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3 12 +#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G35 16 +#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET (0x10) /* OEM Identifiers */ #define MFG10_OEM_ID_INVALID (0x00000000) @@ -1158,7 +1159,8 @@ struct MPT3SAS_ADAPTER { u8 reply_queue_count; struct list_head reply_queue_list; - u8 msix96_vector; + u8 combined_reply_queue; + u8 combined_reply_index_count; /* reply post register index */ resource_size_t **replyPostRegisterIndex; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 521849d5d598..a1c541d9e550 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -8748,8 +8748,15 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } if ((ioc->hba_mpi_version_belonged == MPI25_VERSION && pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) || - (ioc->hba_mpi_version_belonged == MPI26_VERSION)) - ioc->msix96_vector = 1; + (ioc->hba_mpi_version_belonged == MPI26_VERSION)) { + ioc->combined_reply_queue = 1; + if (ioc->is_gen35_ioc) + ioc->combined_reply_index_count = + MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G35; + else + ioc->combined_reply_index_count = + MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3; + } break; default: return -ENODEV; From 186a18e51db08d51011fc4bd2aa773e173f632c9 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:39 +0530 Subject: [PATCH 128/256] scsi: mpt3sas: set EEDP-escape-flags for SAS35 devices. An UNMAP command on a PI formatted device will leave the Logical Block Application Tag and Logical Block Reference Tag as all F's (for those LBAs that are unmapped). To avoid IO errors if those LBAs are subsequently read before they are written with valid tag fields, the MPI SCSI IO requests need to set the EEDPFlags element EEDP Escape Mode field, Bits [7:6] appropriately. A value of 2 should be set to disable all PI checks if the Logical Block Application Tag is 0xFFFF for PI types 1 and 2. A value of 3 should be set to disable all PI checks if the Logical Block Application Tag is 0xFFFF and the Logical Block Reference Tag is 0xFFFFFFFF for PI type 3. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index a1c541d9e550..c58f3265e31f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3989,6 +3989,9 @@ _scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, mpi_request_3v->EEDPBlockSize = cpu_to_le16(scmd->device->sector_size); + + if (ioc->is_gen35_ioc) + eedp_flags |= MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE; mpi_request->EEDPFlags = cpu_to_le16(eedp_flags); } From 81c16f83231a92eca246cb91649c4726899a704d Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:40 +0530 Subject: [PATCH 129/256] scsi: mpt3sas: Use the new MPI 2.6 32-bit Atomic Request Descriptors for SAS35 devices. Support Atomic Request Descriptors for Ventura/SAS35 devices. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 141 ++++++++++++++++++++--- drivers/scsi/mpt3sas/mpt3sas_base.h | 18 +-- drivers/scsi/mpt3sas/mpt3sas_config.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 22 ++-- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 24 ++-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 8 +- 6 files changed, 161 insertions(+), 54 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 43cdc02e6a04..f00ef88a378a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -849,7 +849,7 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) ack_request->EventContext = mpi_reply->EventContext; ack_request->VF_ID = 0; /* TODO */ ack_request->VP_ID = 0; - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); out: @@ -2464,15 +2464,15 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) #endif /** - * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware + * _base_put_smid_scsi_io - send SCSI_IO request to firmware * @ioc: per adapter object * @smid: system request message index * @handle: device handle * * Return nothing. */ -void -mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) +static void +_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { Mpi2RequestDescriptorUnion_t descriptor; u64 *request = (u64 *)&descriptor; @@ -2488,15 +2488,15 @@ mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) } /** - * mpt3sas_base_put_smid_fast_path - send fast path request to firmware + * _base_put_smid_fast_path - send fast path request to firmware * @ioc: per adapter object * @smid: system request message index * @handle: device handle * * Return nothing. */ -void -mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, +static void +_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { Mpi2RequestDescriptorUnion_t descriptor; @@ -2513,14 +2513,14 @@ mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, } /** - * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware + * _base_put_smid_hi_priority - send Task Management request to firmware * @ioc: per adapter object * @smid: system request message index * @msix_task: msix_task will be same as msix of IO incase of task abort else 0. * Return nothing. */ -void -mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, +static void +_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 msix_task) { Mpi2RequestDescriptorUnion_t descriptor; @@ -2537,14 +2537,14 @@ mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, } /** - * mpt3sas_base_put_smid_default - Default, primarily used for config pages + * _base_put_smid_default - Default, primarily used for config pages * @ioc: per adapter object * @smid: system request message index * * Return nothing. */ -void -mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) +static void +_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) { Mpi2RequestDescriptorUnion_t descriptor; u64 *request = (u64 *)&descriptor; @@ -2558,6 +2558,95 @@ mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) &ioc->scsi_lookup_lock); } +/** +* _base_put_smid_scsi_io_atomic - send SCSI_IO request to firmware using +* Atomic Request Descriptor +* @ioc: per adapter object +* @smid: system request message index +* @handle: device handle, unused in this function, for function type match +* +* Return nothing. +*/ +static void +_base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 handle) +{ + Mpi26AtomicRequestDescriptor_t descriptor; + u32 *request = (u32 *)&descriptor; + + descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; + descriptor.MSIxIndex = _base_get_msix_index(ioc); + descriptor.SMID = cpu_to_le16(smid); + + writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); +} + +/** + * _base_put_smid_fast_path_atomic - send fast path request to firmware + * using Atomic Request Descriptor + * @ioc: per adapter object + * @smid: system request message index + * @handle: device handle, unused in this function, for function type match + * Return nothing + */ +static void +_base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 handle) +{ + Mpi26AtomicRequestDescriptor_t descriptor; + u32 *request = (u32 *)&descriptor; + + descriptor.RequestFlags = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; + descriptor.MSIxIndex = _base_get_msix_index(ioc); + descriptor.SMID = cpu_to_le16(smid); + + writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); +} + +/** + * _base_put_smid_hi_priority_atomic - send Task Management request to + * firmware using Atomic Request Descriptor + * @ioc: per adapter object + * @smid: system request message index + * @msix_task: msix_task will be same as msix of IO incase of task abort else 0 + * + * Return nothing. + */ +static void +_base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 msix_task) +{ + Mpi26AtomicRequestDescriptor_t descriptor; + u32 *request = (u32 *)&descriptor; + + descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + descriptor.MSIxIndex = msix_task; + descriptor.SMID = cpu_to_le16(smid); + + writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); +} + +/** + * _base_put_smid_default - Default, primarily used for config pages + * use Atomic Request Descriptor + * @ioc: per adapter object + * @smid: system request message index + * + * Return nothing. + */ +static void +_base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) +{ + Mpi26AtomicRequestDescriptor_t descriptor; + u32 *request = (u32 *)&descriptor; + + descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; + descriptor.MSIxIndex = _base_get_msix_index(ioc); + descriptor.SMID = cpu_to_le16(smid); + + writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); +} + /** * _base_display_OEMs_branding - Display branding string * @ioc: per adapter object @@ -4072,7 +4161,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) ioc->ioc_link_reset_in_progress = 1; init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || @@ -4172,7 +4261,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, ioc->base_cmds.smid = smid; memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { @@ -4357,6 +4446,8 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc) if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE)) ioc->rdpq_array_capable = 1; + if (facts->IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ) + ioc->atomic_desc_capable = 1; facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); facts->IOCRequestFrameSize = le16_to_cpu(mpi_reply.IOCRequestFrameSize); @@ -4584,7 +4675,7 @@ _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc) mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; init_completion(&ioc->port_enable_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->port_enable_cmds.done, 300*HZ); if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -4647,7 +4738,7 @@ mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc) memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); return 0; } @@ -4766,7 +4857,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc) mpi_request->EventMasks[i] = cpu_to_le32(ioc->event_masks[i]); init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -5282,9 +5373,23 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ioc->build_sg = &_base_build_sg_ieee; ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); + break; } + if (ioc->atomic_desc_capable) { + ioc->put_smid_default = &_base_put_smid_default_atomic; + ioc->put_smid_scsi_io = &_base_put_smid_scsi_io_atomic; + ioc->put_smid_fast_path = &_base_put_smid_fast_path_atomic; + ioc->put_smid_hi_priority = &_base_put_smid_hi_priority_atomic; + } else { + ioc->put_smid_default = &_base_put_smid_default; + ioc->put_smid_scsi_io = &_base_put_smid_scsi_io; + ioc->put_smid_fast_path = &_base_put_smid_fast_path; + ioc->put_smid_hi_priority = &_base_put_smid_hi_priority; + } + + /* * These function pointers for other requests that don't * the require IEEE scatter gather elements. diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index acb410628671..5d9ae15cddd4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -736,7 +736,10 @@ typedef void (*MPT_BUILD_SG)(struct MPT3SAS_ADAPTER *ioc, void *psge, typedef void (*MPT_BUILD_ZERO_LEN_SGE)(struct MPT3SAS_ADAPTER *ioc, void *paddr); - +/* To support atomic and non atomic descriptors*/ +typedef void (*PUT_SMID_IO_FP_HIP) (struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 funcdep); +typedef void (*PUT_SMID_DEFAULT) (struct MPT3SAS_ADAPTER *ioc, u16 smid); /* IOC Facts and Port Facts converted from little endian to cpu */ union mpi3_version_union { @@ -1194,6 +1197,12 @@ struct MPT3SAS_ADAPTER { void *device_remove_in_progress; u16 device_remove_in_progress_sz; u8 is_gen35_ioc; + u8 atomic_desc_capable; + PUT_SMID_IO_FP_HIP put_smid_scsi_io; + PUT_SMID_IO_FP_HIP put_smid_fast_path; + PUT_SMID_IO_FP_HIP put_smid_hi_priority; + PUT_SMID_DEFAULT put_smid_default; + }; typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, @@ -1239,13 +1248,6 @@ u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle); -void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle); -void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, - u16 smid, u16 msix_task); -void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid); void mpt3sas_base_initialize_callback_handler(void); u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func); void mpt3sas_base_release_callback_handler(u8 cb_idx); diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index cebfd734fd76..dd6270125614 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -384,7 +384,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); _config_display_some_debug(ioc, smid, "config_request", NULL); init_completion(&ioc->config_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ); if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index a287bfb70784..050bd788ad02 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -812,9 +812,9 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) - mpt3sas_base_put_smid_scsi_io(ioc, smid, device_handle); + ioc->put_smid_scsi_io(ioc, smid, device_handle); else - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_SCSI_TASK_MGMT: @@ -849,7 +849,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, tm_request->DevHandle)); ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); + ioc->put_smid_hi_priority(ioc, smid, 0); break; } case MPI2_FUNCTION_SMP_PASSTHROUGH: @@ -880,7 +880,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, } ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_SATA_PASSTHROUGH: @@ -895,7 +895,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, } ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_FW_DOWNLOAD: @@ -903,7 +903,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, { ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_TOOLBOX: @@ -918,7 +918,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); } - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: @@ -937,7 +937,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, default: ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); break; } @@ -1526,7 +1526,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, cpu_to_le32(ioc->product_specific[buffer_type][i]); init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); @@ -1873,7 +1873,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, mpi_request->VP_ID = 0; init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); @@ -2140,7 +2140,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) mpi_request->VP_ID = 0; init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index c58f3265e31f..6d17f6635251 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2285,7 +2285,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, msix_task = scsi_lookup->msix_io; else msix_task = 0; - mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task); + ioc->put_smid_hi_priority(ioc, smid, msix_task); wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -3201,7 +3201,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; set_bit(handle, ioc->device_remove_in_progress); - mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); + ioc->put_smid_hi_priority(ioc, smid, 0); mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); out: @@ -3300,7 +3300,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; mpi_request->DevHandle = mpi_request_tm->DevHandle; - mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl); + ioc->put_smid_default(ioc, smid_sas_ctrl); return _scsih_check_for_pending_tm(ioc, smid); } @@ -3395,7 +3395,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); + ioc->put_smid_hi_priority(ioc, smid, 0); } /** @@ -3487,7 +3487,7 @@ _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, ack_request->EventContext = event_context; ack_request->VF_ID = 0; /* TODO */ ack_request->VP_ID = 0; - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); } /** @@ -3544,7 +3544,7 @@ _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; mpi_request->DevHandle = handle; - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); } /** @@ -4158,12 +4158,12 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len | MPI25_SCSIIO_IOFLAGS_FAST_PATH); - mpt3sas_base_put_smid_fast_path(ioc, smid, handle); + ioc->put_smid_fast_path(ioc, smid, handle); } else - mpt3sas_base_put_smid_scsi_io(ioc, smid, + ioc->put_smid_scsi_io(ioc, smid, le16_to_cpu(mpi_request->DevHandle)); } else - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); return 0; out: @@ -4659,7 +4659,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); mpi_request->DevHandle = cpu_to_le16(sas_device_priv_data->sas_target->handle); - mpt3sas_base_put_smid_scsi_io(ioc, smid, + ioc->put_smid_scsi_io(ioc, smid, sas_device_priv_data->sas_target->handle); return 0; } @@ -6273,7 +6273,7 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) handle, phys_disk_num)); init_completion(&ioc->scsih_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { @@ -8122,7 +8122,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) if (!ioc->hide_ir_msg) pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name); init_completion(&ioc->scsih_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index b74faf1a69b2..7f1d5785bc30 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -392,7 +392,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, "report_manufacture - send to sas_addr(0x%016llx)\n", ioc->name, (unsigned long long)sas_address)); init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { @@ -1198,7 +1198,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, ioc->name, (unsigned long long)phy->identify.sas_address, phy->number)); init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { @@ -1514,7 +1514,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, ioc->name, (unsigned long long)phy->identify.sas_address, phy->number, phy_operation)); init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { @@ -2032,7 +2032,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, "%s - sending smp request\n", ioc->name, __func__)); init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); + ioc->put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { From aa53bb89522fa3536faebf7e6b7275c84c4f9148 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:41 +0530 Subject: [PATCH 130/256] scsi: mpt3sas: Fix for Endianness issue. Use le16_to_cpu only for accessing two byte data provided by controller. Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 6d17f6635251..981be7b1df6a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5384,10 +5384,10 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, sas_device->handle, handle); sas_target_priv_data->handle = handle; sas_device->handle = handle; - if (sas_device_pg0.Flags & + if (le16_to_cpu(sas_device_pg0.Flags) & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { sas_device->enclosure_level = - le16_to_cpu(sas_device_pg0.EnclosureLevel); + sas_device_pg0.EnclosureLevel; memcpy(sas_device->connector_name, sas_device_pg0.ConnectorName, 4); sas_device->connector_name[4] = '\0'; @@ -5516,9 +5516,10 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; - if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { + if (le16_to_cpu(sas_device_pg0.Flags) + & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { sas_device->enclosure_level = - le16_to_cpu(sas_device_pg0.EnclosureLevel); + sas_device_pg0.EnclosureLevel; memcpy(sas_device->connector_name, sas_device_pg0.ConnectorName, 4); sas_device->connector_name[4] = '\0'; @@ -7056,7 +7057,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0) if (sas_device_pg0->Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { sas_device->enclosure_level = - le16_to_cpu(sas_device_pg0->EnclosureLevel); + sas_device_pg0->EnclosureLevel; memcpy(&sas_device->connector_name[0], &sas_device_pg0->ConnectorName[0], 4); } else { @@ -7118,6 +7119,7 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) sas_device_pg0.SASAddress = le64_to_cpu(sas_device_pg0.SASAddress); sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot); + sas_device_pg0.Flags = le16_to_cpu(sas_device_pg0.Flags); _scsih_mark_responding_sas_device(ioc, &sas_device_pg0); } From 6b64b286c8b6329e053941367a9c788f3e268a1d Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 26 Oct 2016 13:34:42 +0530 Subject: [PATCH 131/256] scsi: mpt3sas: Bump driver version as "14.101.00.00" Signed-off-by: Chaitra P B Signed-off-by: Sathya Prakash Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 5d9ae15cddd4..8de0eda8cd00 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -73,9 +73,9 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "14.100.00.00" +#define MPT3SAS_DRIVER_VERSION "14.101.00.00" #define MPT3SAS_MAJOR_VERSION 14 -#define MPT3SAS_MINOR_VERSION 100 +#define MPT3SAS_MINOR_VERSION 101 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 From 30fc33f1ef475480dc5bea4fe1bda84b003b992c Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 27 Oct 2016 17:25:47 -0700 Subject: [PATCH 132/256] scsi: ufs: fix race between clock gating and devfreq scaling work UFS devfreq clock scaling work may require clocks to be ON if it need to execute some UFS commands hence it may request for clock hold before issuing the command. But if UFS clock gating work is already running in parallel, ungate work would end up waiting for the clock gating work to finish and as clock gating work would also wait for the clock scaling work to finish, we would enter in deadlock state. Here is the call trace during this deadlock state: Workqueue: devfreq_wq devfreq_monitor __switch_to __schedule schedule schedule_timeout wait_for_common wait_for_completion flush_work ufshcd_hold ufshcd_send_uic_cmd ufshcd_dme_get_attr ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div ufs_qcom_clk_scale_notify ufshcd_scale_clks ufshcd_devfreq_target update_devfreq devfreq_monitor process_one_work worker_thread kthread ret_from_fork Workqueue: events ufshcd_gate_work __switch_to __schedule schedule schedule_preempt_disabled __mutex_lock_slowpath mutex_lock devfreq_monitor_suspend devfreq_simple_ondemand_handler devfreq_suspend_device ufshcd_gate_work process_one_work worker_thread kthread ret_from_fork Workqueue: events ufshcd_ungate_work __switch_to __schedule schedule schedule_timeout wait_for_common wait_for_completion flush_work __cancel_work_timer cancel_delayed_work_sync ufshcd_ungate_work process_one_work worker_thread kthread ret_from_fork This change fixes this deadlock by doing this in devfreq work (devfreq_wq): Try cancelling clock gating work. If we are able to cancel gating work or it wasn't scheduled, hold the clock reference count until scaling is in progress. If gate work is already running in parallel, let's skip the frequecy scaling at this time and it will be retried once next scaling window expires. Reviewed-by: Sahitya Tummala Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 304adce3bdbe..5c931d1ba288 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6379,15 +6379,47 @@ static int ufshcd_devfreq_target(struct device *dev, { int err = 0; struct ufs_hba *hba = dev_get_drvdata(dev); + bool release_clk_hold = false; + unsigned long irq_flags; if (!ufshcd_is_clkscaling_enabled(hba)) return -EINVAL; + spin_lock_irqsave(hba->host->host_lock, irq_flags); + if (ufshcd_eh_in_progress(hba)) { + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + return 0; + } + + if (ufshcd_is_clkgating_allowed(hba) && + (hba->clk_gating.state != CLKS_ON)) { + if (cancel_delayed_work(&hba->clk_gating.gate_work)) { + /* hold the vote until the scaling work is completed */ + hba->clk_gating.active_reqs++; + release_clk_hold = true; + hba->clk_gating.state = CLKS_ON; + } else { + /* + * Clock gating work seems to be running in parallel + * hence skip scaling work to avoid deadlock between + * current scaling work and gating work. + */ + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + return 0; + } + } + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + if (*freq == UINT_MAX) err = ufshcd_scale_clks(hba, true); else if (*freq == 0) err = ufshcd_scale_clks(hba, false); + spin_lock_irqsave(hba->host->host_lock, irq_flags); + if (release_clk_hold) + __ufshcd_release(hba); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + return err; } From afa3dfd42d205b106787476647735aa1de1a5d02 Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 27 Oct 2016 17:25:58 -0700 Subject: [PATCH 133/256] scsi: ufshcd: release resources if probe fails If ufshcd pltfrm/pci driver's probe fails for some reason then ensure that scsi host is released to avoid memory leak but managed memory allocations (via devm_* calls) need not to be freed explicitly on probe failure as memory allocated with these functions is automatically freed on driver detach. Reviewed-by: Sahitya Tummala Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd-pci.c | 2 ++ drivers/scsi/ufs/ufshcd-pltfrm.c | 5 +---- drivers/scsi/ufs/ufshcd.c | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index d15eaa466c59..52b546fb509b 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -104,6 +104,7 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) pm_runtime_forbid(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); ufshcd_remove(hba); + ufshcd_dealloc_host(hba); } /** @@ -147,6 +148,7 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) err = ufshcd_init(hba, mmio_base, pdev->irq); if (err) { dev_err(&pdev->dev, "Initialization failed\n"); + ufshcd_dealloc_host(hba); return err; } diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index db53f38da864..a72a4ba78125 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -163,7 +163,7 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, if (ret) { dev_err(dev, "%s: unable to find %s err %d\n", __func__, prop_name, ret); - goto out_free; + goto out; } vreg->min_uA = 0; @@ -185,9 +185,6 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, goto out; -out_free: - devm_kfree(dev, vreg); - vreg = NULL; out: if (!ret) *out_vreg = vreg; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5c931d1ba288..6c0082e2591e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6253,8 +6253,6 @@ void ufshcd_remove(struct ufs_hba *hba) ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba, true); - scsi_host_put(hba->host); - ufshcd_exit_clk_gating(hba); if (ufshcd_is_clkscaling_enabled(hba)) devfreq_remove_device(hba->devfreq); @@ -6616,7 +6614,6 @@ exit_gating: ufshcd_exit_clk_gating(hba); out_disable: hba->is_irq_enabled = false; - scsi_host_put(host); ufshcd_hba_exit(hba); out_error: return err; From d6fcf81a0d97a9e9f5035973c3a4dc219c9488b0 Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 27 Oct 2016 17:26:09 -0700 Subject: [PATCH 134/256] scsi: ufs: suspend clock scaling at the start of suspend Currently clock scaling is suspended only after the host and device are put in low power mode but we should avoid clock scaling running after UFS link is put in low power mode (hibern8). This change suspends clock scaling before putting host/device in low power mode. Reviewed-by: Sahitya Tummala Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6c0082e2591e..9ed96ae942f6 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5892,6 +5892,8 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_hold(hba, false); hba->clk_gating.is_suspended = true; + ufshcd_suspend_clkscaling(hba); + if (req_dev_pwr_mode == UFS_ACTIVE_PWR_MODE && req_link_state == UIC_LINK_ACTIVE_STATE) { goto disable_clks; @@ -5899,12 +5901,12 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) if ((req_dev_pwr_mode == hba->curr_dev_pwr_mode) && (req_link_state == hba->uic_link_state)) - goto out; + goto enable_gating; /* UFS device & link must be active before we enter in this function */ if (!ufshcd_is_ufs_dev_active(hba) || !ufshcd_is_link_active(hba)) { ret = -EINVAL; - goto out; + goto enable_gating; } if (ufshcd_is_runtime_pm(pm_op)) { @@ -5940,13 +5942,6 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_vreg_set_lpm(hba); disable_clks: - /* - * The clock scaling needs access to controller registers. Hence, Wait - * for pending clock scaling work to be done before clocks are - * turned off. - */ - ufshcd_suspend_clkscaling(hba); - /* * Call vendor specific suspend callback. As these callbacks may access * vendor specific host controller register space call them before the @@ -5983,6 +5978,7 @@ set_dev_active: if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE)) ufshcd_disable_auto_bkops(hba); enable_gating: + ufshcd_resume_clkscaling(hba); hba->clk_gating.is_suspended = false; ufshcd_release(hba); out: From 69d72ac8369a503926b5c494182dd209484de67e Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 27 Oct 2016 17:26:24 -0700 Subject: [PATCH 135/256] scsi: ufs: change device rails hpm mode ramp up sequence When we are resuming the UFS device rails in HPM mode, we are first powering on the VCC rail while VCCQ and VCCQ2 rails still being in LPM mode. Some UFS devices may take VCC on event as hint that host wants UFS device to be resumed and may start drawing more power from the VCCQ/VCCQ2 rails (while they are still in LPM mode) causing voltage drop on these rails. This change fixes this issue by bringing VCCQ & VCCQ2 rails out of LPM before powering on VCC rail. Reviewed-by: Venkat Gopalakrishnan Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9ed96ae942f6..8cf5d8f7683b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5819,7 +5819,6 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) !hba->dev_info.is_lu_power_on_wp) { ret = ufshcd_setup_vreg(hba, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { - ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true); if (!ret && !ufshcd_is_link_active(hba)) { ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (ret) @@ -5828,6 +5827,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) if (ret) goto vccq_lpm; } + ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true); } goto out; From 9e5a7e22951bc12ee45cb617919d57b5efce56b5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 08:12:47 -0600 Subject: [PATCH 136/256] blk-mq: export blk_mq_map_queues This will allow SCSI to have a single blk_mq_ops structure that either lets the LLDD map the queues to PCIe MSIx vectors or use the default. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Sagi Grimberg Reviewed-by: Jens Axboe Signed-off-by: Martin K. Petersen --- block/blk-mq-cpumap.c | 1 + block/blk-mq.h | 1 - include/linux/blk-mq.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c index 19b1d9c5f07e..8e61e8640e17 100644 --- a/block/blk-mq-cpumap.c +++ b/block/blk-mq-cpumap.c @@ -87,6 +87,7 @@ int blk_mq_map_queues(struct blk_mq_tag_set *set) free_cpumask_var(cpus); return 0; } +EXPORT_SYMBOL_GPL(blk_mq_map_queues); /* * We have no quick way of doing reverse lookups. This is only used at diff --git a/block/blk-mq.h b/block/blk-mq.h index e5d25249028c..5347f011e90d 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -38,7 +38,6 @@ void blk_mq_disable_hotplug(void); /* * CPU -> queue mappings */ -int blk_mq_map_queues(struct blk_mq_tag_set *set); extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int); static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 535ab2e13d2e..6c0fb259581f 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -237,6 +237,7 @@ void blk_mq_unfreeze_queue(struct request_queue *q); void blk_mq_freeze_queue_start(struct request_queue *q); int blk_mq_reinit_tagset(struct blk_mq_tag_set *set); +int blk_mq_map_queues(struct blk_mq_tag_set *set); void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues); /* From 2d9c5c20c93eacc00642f6ce10ce47f31fa0b6ac Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 08:12:48 -0600 Subject: [PATCH 137/256] scsi: allow LLDDs to expose the queue mapping to blk-mq Just hand through the blk-mq map_queues method in the host template. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 10 ++++++++++ include/scsi/scsi_host.h | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 2cca9cffc63f..f23ec240cab0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1990,6 +1990,15 @@ static void scsi_exit_request(void *data, struct request *rq, kfree(cmd->sense_buffer); } +static int scsi_map_queues(struct blk_mq_tag_set *set) +{ + struct Scsi_Host *shost = container_of(set, struct Scsi_Host, tag_set); + + if (shost->hostt->map_queues) + return shost->hostt->map_queues(shost); + return blk_mq_map_queues(set); +} + static u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) { struct device *host_dev; @@ -2082,6 +2091,7 @@ static struct blk_mq_ops scsi_mq_ops = { .timeout = scsi_timeout, .init_request = scsi_init_request, .exit_request = scsi_exit_request, + .map_queues = scsi_map_queues, }; struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev) diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7e4cd53139ed..36680f13270d 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -277,6 +277,14 @@ struct scsi_host_template { */ int (* change_queue_depth)(struct scsi_device *, int); + /* + * This functions lets the driver expose the queue mapping + * to the block layer. + * + * Status: OPTIONAL + */ + int (* map_queues)(struct Scsi_Host *shost); + /* * This function determines the BIOS parameters for a given * harddisk. These tend to be numbers that are made up by From 5219822687be40d89bfc30d4040f6a3bb6d17d1f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 1 Nov 2016 08:12:49 -0600 Subject: [PATCH 138/256] scsi: smartpqi: switch to pci_alloc_irq_vectors Which cleans up a lot of the MSI-X handling, and allows us to use the PCI IRQ layer provided vector mapping, which we can then expose to blk-mq. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Sagi Grimberg Acked-by: Don Brace Tested-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi.h | 2 - drivers/scsi/smartpqi/smartpqi_init.c | 102 ++++++++------------------ 2 files changed, 32 insertions(+), 72 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 07b6444d3e0a..b673825f46b5 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -929,8 +929,6 @@ struct pqi_ctrl_info { int max_msix_vectors; int num_msix_vectors_enabled; int num_msix_vectors_initialized; - u32 msix_vectors[PQI_MAX_MSIX_VECTORS]; - void *intr_data[PQI_MAX_MSIX_VECTORS]; int event_irq; struct Scsi_Host *scsi_host; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index a535b2661f38..8702d9cf8040 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -2887,19 +2888,19 @@ static irqreturn_t pqi_irq_handler(int irq, void *data) static int pqi_request_irqs(struct pqi_ctrl_info *ctrl_info) { + struct pci_dev *pdev = ctrl_info->pci_dev; int i; int rc; - ctrl_info->event_irq = ctrl_info->msix_vectors[0]; + ctrl_info->event_irq = pci_irq_vector(pdev, 0); for (i = 0; i < ctrl_info->num_msix_vectors_enabled; i++) { - rc = request_irq(ctrl_info->msix_vectors[i], - pqi_irq_handler, 0, - DRIVER_NAME_SHORT, ctrl_info->intr_data[i]); + rc = request_irq(pci_irq_vector(pdev, i), pqi_irq_handler, 0, + DRIVER_NAME_SHORT, &ctrl_info->queue_groups[i]); if (rc) { - dev_err(&ctrl_info->pci_dev->dev, + dev_err(&pdev->dev, "irq %u init failed with error %d\n", - ctrl_info->msix_vectors[i], rc); + pci_irq_vector(pdev, i), rc); return rc; } ctrl_info->num_msix_vectors_initialized++; @@ -2908,72 +2909,23 @@ static int pqi_request_irqs(struct pqi_ctrl_info *ctrl_info) return 0; } -static void pqi_free_irqs(struct pqi_ctrl_info *ctrl_info) -{ - int i; - - for (i = 0; i < ctrl_info->num_msix_vectors_initialized; i++) - free_irq(ctrl_info->msix_vectors[i], - ctrl_info->intr_data[i]); -} - static int pqi_enable_msix_interrupts(struct pqi_ctrl_info *ctrl_info) { - unsigned int i; - int max_vectors; - int num_vectors_enabled; - struct msix_entry msix_entries[PQI_MAX_MSIX_VECTORS]; + int ret; - max_vectors = ctrl_info->num_queue_groups; - - for (i = 0; i < max_vectors; i++) - msix_entries[i].entry = i; - - num_vectors_enabled = pci_enable_msix_range(ctrl_info->pci_dev, - msix_entries, PQI_MIN_MSIX_VECTORS, max_vectors); - - if (num_vectors_enabled < 0) { + ret = pci_alloc_irq_vectors(ctrl_info->pci_dev, + PQI_MIN_MSIX_VECTORS, ctrl_info->num_queue_groups, + PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); + if (ret < 0) { dev_err(&ctrl_info->pci_dev->dev, - "MSI-X init failed with error %d\n", - num_vectors_enabled); - return num_vectors_enabled; - } - - ctrl_info->num_msix_vectors_enabled = num_vectors_enabled; - for (i = 0; i < num_vectors_enabled; i++) { - ctrl_info->msix_vectors[i] = msix_entries[i].vector; - ctrl_info->intr_data[i] = &ctrl_info->queue_groups[i]; + "MSI-X init failed with error %d\n", ret); + return ret; } + ctrl_info->num_msix_vectors_enabled = ret; return 0; } -static void pqi_irq_set_affinity_hint(struct pqi_ctrl_info *ctrl_info) -{ - int i; - int rc; - int cpu; - - cpu = cpumask_first(cpu_online_mask); - for (i = 0; i < ctrl_info->num_msix_vectors_initialized; i++) { - rc = irq_set_affinity_hint(ctrl_info->msix_vectors[i], - get_cpu_mask(cpu)); - if (rc) - dev_err(&ctrl_info->pci_dev->dev, - "error %d setting affinity hint for irq vector %u\n", - rc, ctrl_info->msix_vectors[i]); - cpu = cpumask_next(cpu, cpu_online_mask); - } -} - -static void pqi_irq_unset_affinity_hint(struct pqi_ctrl_info *ctrl_info) -{ - int i; - - for (i = 0; i < ctrl_info->num_msix_vectors_initialized; i++) - irq_set_affinity_hint(ctrl_info->msix_vectors[i], NULL); -} - static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info) { unsigned int i; @@ -4743,6 +4695,13 @@ static int pqi_slave_configure(struct scsi_device *sdev) return 0; } +static int pqi_map_queues(struct Scsi_Host *shost) +{ + struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost); + + return blk_mq_pci_map_queues(&shost->tag_set, ctrl_info->pci_dev); +} + static int pqi_getpciinfo_ioctl(struct pqi_ctrl_info *ctrl_info, void __user *arg) { @@ -5130,6 +5089,7 @@ static struct scsi_host_template pqi_driver_template = { .ioctl = pqi_ioctl, .slave_alloc = pqi_slave_alloc, .slave_configure = pqi_slave_configure, + .map_queues = pqi_map_queues, .sdev_attrs = pqi_sdev_attrs, .shost_attrs = pqi_shost_attrs, }; @@ -5159,7 +5119,7 @@ static int pqi_register_scsi(struct pqi_ctrl_info *ctrl_info) shost->cmd_per_lun = shost->can_queue; shost->sg_tablesize = ctrl_info->sg_tablesize; shost->transportt = pqi_sas_transport_template; - shost->irq = ctrl_info->msix_vectors[0]; + shost->irq = pci_irq_vector(ctrl_info->pci_dev, 0); shost->unique_id = shost->irq; shost->nr_hw_queues = ctrl_info->num_queue_groups; shost->hostdata[0] = (unsigned long)ctrl_info; @@ -5409,8 +5369,6 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) if (rc) return rc; - pqi_irq_set_affinity_hint(ctrl_info); - rc = pqi_create_queues(ctrl_info); if (rc) return rc; @@ -5557,10 +5515,14 @@ static inline void pqi_free_ctrl_info(struct pqi_ctrl_info *ctrl_info) static void pqi_free_interrupts(struct pqi_ctrl_info *ctrl_info) { - pqi_irq_unset_affinity_hint(ctrl_info); - pqi_free_irqs(ctrl_info); - if (ctrl_info->num_msix_vectors_enabled) - pci_disable_msix(ctrl_info->pci_dev); + int i; + + for (i = 0; i < ctrl_info->num_msix_vectors_initialized; i++) { + free_irq(pci_irq_vector(ctrl_info->pci_dev, i), + &ctrl_info->queue_groups[i]); + } + + pci_free_irq_vectors(ctrl_info->pci_dev); } static void pqi_free_ctrl_resources(struct pqi_ctrl_info *ctrl_info) From d0fc91d67c59068ce6d42e41ce66a4c471e5bc74 Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:33 -0700 Subject: [PATCH 139/256] scsi: megaraid_sas: Send SYNCHRONIZE_CACHE for VD to firmware Until now the megaraid_sas driver has reported successful completion on SYNCHRONIZE_CACHE commands without sending them down to the controller. The controller firmware has been responsible for taking care of flushing disk caches for all drives that belong to a Virtual Disk at the time of system reboot/shutdown. There may have been a reason to avoid sending SYNCHRONIZE_CACHE to a VD in the past but that no longer appears to be valid. Older versions of MegaRaid firmware (Gen2 and Gen2.5) set the WCE bit for Virtual Disks but the firmware does not report correct completion status for a SYNCHRONIZE_CACHE command. As a result, we must use another method to identify whether it is safe to send the command to the controller. We use the canHandleSyncCache firmware flag in the scratch pad register at offset 0xB4. New SYNCHRONIZE_CACHE behavior: IF 'JBOD' Driver sends SYNCHRONIZE_CACHE command to the firmware Firmware sends SYNCHRONIZE_CACHE to drive Firmware obtains status from drive and returns same status back to driver ELSEIF 'VirtualDisk' IF firmware supports new API bit called canHandleSyncCache Driver sends SYNCHRONIZE_CACHE command to the firmware Firmware does not send SYNCHRONIZE_CACHE to drives Firmware returns SUCCESS ELSE Driver does not send SYNCHRONIZE_CACHE command to the firmware Driver return SUCCESS for that command ENDIF ENDIF [mkp: edited patch description] Signed-off-by: Kashyap Desai Signed-off-by: Sumit Saxena Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 3 +++ drivers/scsi/megaraid/megaraid_sas_base.c | 7 ++----- drivers/scsi/megaraid/megaraid_sas_fusion.c | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index ca86c885dfaa..43fd14fad1a6 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1429,6 +1429,8 @@ enum FW_BOOT_CONTEXT { #define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14 #define MR_MAX_MSIX_REG_ARRAY 16 #define MR_RDPQ_MODE_OFFSET 0X00800000 +#define MR_CAN_HANDLE_SYNC_CACHE_OFFSET 0X01000000 + /* * register set for both 1068 and 1078 controllers * structure extended for 1078 registers @@ -2140,6 +2142,7 @@ struct megasas_instance { u8 is_imr; u8 is_rdpq; bool dev_handle; + bool fw_sync_cache_support; }; struct MR_LD_VF_MAP { u32 size; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index d5410a39d956..f6db7abf150d 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -1700,11 +1700,8 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) goto out_done; } - /* - * FW takes care of flush cache on its own for Virtual Disk. - * No need to send it down for VD. For JBOD send SYNCHRONIZE_CACHE to FW. - */ - if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd)) { + if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd) && + (!instance->fw_sync_cache_support)) { scmd->result = DID_OK << 16; goto out_done; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 2159f6ae5a31..2e61306de9c8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -748,6 +748,11 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) goto fail_fw_init; } + instance->fw_sync_cache_support = (scratch_pad_2 & + MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0; + dev_info(&instance->pdev->dev, "FW supports sync cache\t: %s\n", + instance->fw_sync_cache_support ? "Yes" : "No"); + IOCInitMessage = dma_alloc_coherent(&instance->pdev->dev, sizeof(struct MPI2_IOC_INIT_REQUEST), From 295dde2f1c659a4e0e53fb85e742fc05cb650b56 Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:34 -0700 Subject: [PATCH 140/256] MAINTAINERS: Update megaraid maintainers list Update MEGARAID drivers maintainers list. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- MAINTAINERS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f4c5f215e6e5..b3a77741da80 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7836,12 +7836,12 @@ S: Maintained F: drivers/net/wireless/mediatek/mt7601u/ MEGARAID SCSI/SAS DRIVERS -M: Kashyap Desai -M: Sumit Saxena -M: Uday Lingala -L: megaraidlinux.pdl@avagotech.com +M: Kashyap Desai +M: Sumit Saxena +M: Shivasharan S +L: megaraidlinux.pdl@broadcom.com L: linux-scsi@vger.kernel.org -W: http://www.lsi.com +W: http://www.avagotech.com/support/ S: Maintained F: Documentation/scsi/megaraid.txt F: drivers/scsi/megaraid.* From d5573584429254a14708cf8375c47092b5edaf2c Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:35 -0700 Subject: [PATCH 141/256] scsi: megaraid_sas: Do not set MPI2_TYPE_CUDA for JBOD FP path for FW which does not support JBOD sequence map CC: stable@vger.kernel.org Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 2e61306de9c8..24778ba4b6e8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2005,6 +2005,8 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, io_request->DevHandle = pd_sync->seq[pd_index].devHandle; pRAID_Context->regLockFlags |= (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA); + pRAID_Context->Type = MPI2_TYPE_CUDA; + pRAID_Context->nseg = 0x1; } else if (fusion->fast_path_io) { pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); pRAID_Context->configSeqNum = 0; @@ -2040,12 +2042,10 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, pRAID_Context->timeoutValue = cpu_to_le16((os_timeout_value > timeout_limit) ? timeout_limit : os_timeout_value); - if (fusion->adapter_type == INVADER_SERIES) { - pRAID_Context->Type = MPI2_TYPE_CUDA; - pRAID_Context->nseg = 0x1; + if (fusion->adapter_type == INVADER_SERIES) io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH); - } + cmd->request_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_FP_IO << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); From fd3e165ac8be7bfbc47318e7b720458a5d5d6227 Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Fri, 21 Oct 2016 06:33:36 -0700 Subject: [PATCH 142/256] scsi: megaraid_sas: driver version upgrade Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 43fd14fad1a6..74c7b441aace 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -35,8 +35,8 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "06.811.02.00-rc1" -#define MEGASAS_RELDATE "April 12, 2016" +#define MEGASAS_VERSION "06.812.07.00-rc1" +#define MEGASAS_RELDATE "August 22, 2016" /* * Device IDs From fd91ddad2e9a1eab3df63ccd0f60fdfa08dbe452 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:40 +0530 Subject: [PATCH 143/256] phy: qcom-ufs: Remove unnecessary BUG_ON BUG_ON() are not preferred in the driver, plus the variable on which BUG_ON is asserted is already checked in the code before passing. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 18a5b495ad65..455064cd270d 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -322,8 +322,6 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy, struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); struct device *dev = ufs_qcom_phy->dev; - BUG_ON(!vreg); - if (regulator_count_voltages(reg) > 0) { min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); From add78fc05702b1082b31cf99c670bab5919cbe80 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:41 +0530 Subject: [PATCH 144/256] phy: qcom-ufs: Use devm sibling of kstrdup for regulator names This helps us in avoiding any requirement for kfree() operation to be called exclusively over the allocated string pointer. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 455064cd270d..5dc24d8554a8 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -251,7 +251,7 @@ static int __ufs_qcom_phy_init_vreg(struct phy *phy, char prop_name[MAX_PROP_NAME]; - vreg->name = kstrdup(name, GFP_KERNEL); + vreg->name = devm_kstrdup(dev, name, GFP_KERNEL); if (!vreg->name) { err = -ENOMEM; goto out; @@ -637,9 +637,6 @@ int ufs_qcom_phy_remove(struct phy *generic_phy, { phy_power_off(generic_phy); - kfree(ufs_qcom_phy->vdda_pll.name); - kfree(ufs_qcom_phy->vdda_phy.name); - return 0; } EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); From 89bd296b78bc2222c04b6e9cae5b56295b023228 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:42 +0530 Subject: [PATCH 145/256] phy: qcom-ufs: Cleanup clock and regulator initialization Different menthods pass around generic phy pointer to extract device pointer. Instead, pass the device pointer directly between function calls. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs-i.h | 6 +-- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 4 +- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 4 +- drivers/phy/phy-qcom-ufs.c | 80 +++++++++++------------------ 4 files changed, 37 insertions(+), 57 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h index 2bd5ce43a724..69e836d0ec3e 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/phy-qcom-ufs-i.h @@ -142,10 +142,8 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); int ufs_qcom_phy_power_on(struct phy *generic_phy); int ufs_qcom_phy_power_off(struct phy *generic_phy); int ufs_qcom_phy_exit(struct phy *generic_phy); -int ufs_qcom_phy_init_clks(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); -int ufs_qcom_phy_init_vregulators(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); +int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common); +int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common); int ufs_qcom_phy_remove(struct phy *generic_phy, struct ufs_qcom_phy *ufs_qcom_phy); struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 6ee51490f786..e3bede73ec73 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -48,14 +48,14 @@ static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) struct ufs_qcom_phy *phy_common = &phy->common_cfg; int err; - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + err = ufs_qcom_phy_init_clks(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", __func__, err); goto out; } - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + err = ufs_qcom_phy_init_vregulators(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", __func__, err); diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 770087ab05e2..e09ecb8c1e5f 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -67,14 +67,14 @@ static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) struct ufs_qcom_phy *phy_common = &phy->common_cfg; int err = 0; - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + err = ufs_qcom_phy_init_clks(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", __func__, err); goto out; } - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + err = ufs_qcom_phy_init_vregulators(phy_common); if (err) { dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", __func__, err); diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 5dc24d8554a8..b0171fef3868 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -22,9 +22,9 @@ #define VDDP_REF_CLK_MIN_UV 1200000 #define VDDP_REF_CLK_MAX_UV 1200000 -static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, +static int __ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, const char *, bool); -static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, +static int ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, const char *); static int ufs_qcom_phy_base_init(struct platform_device *pdev, struct ufs_qcom_phy *phy_common); @@ -154,13 +154,11 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev, return 0; } -static int __ufs_qcom_phy_clk_get(struct phy *phy, +static int __ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out, bool err_print) { struct clk *clk; int err = 0; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { @@ -174,30 +172,27 @@ static int __ufs_qcom_phy_clk_get(struct phy *phy, return err; } -static -int ufs_qcom_phy_clk_get(struct phy *phy, +static int ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out) { - return __ufs_qcom_phy_clk_get(phy, name, clk_out, true); + return __ufs_qcom_phy_clk_get(dev, name, clk_out, true); } -int -ufs_qcom_phy_init_clks(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common) +int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common) { int err; - err = ufs_qcom_phy_clk_get(generic_phy, "tx_iface_clk", + err = ufs_qcom_phy_clk_get(phy_common->dev, "tx_iface_clk", &phy_common->tx_iface_clk); if (err) goto out; - err = ufs_qcom_phy_clk_get(generic_phy, "rx_iface_clk", + err = ufs_qcom_phy_clk_get(phy_common->dev, "rx_iface_clk", &phy_common->rx_iface_clk); if (err) goto out; - err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk_src", + err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_src", &phy_common->ref_clk_src); if (err) goto out; @@ -206,10 +201,10 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy, * "ref_clk_parent" is optional hence don't abort init if it's not * found. */ - __ufs_qcom_phy_clk_get(generic_phy, "ref_clk_parent", + __ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_parent", &phy_common->ref_clk_parent, false); - err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk", + err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk", &phy_common->ref_clk); out: @@ -217,37 +212,33 @@ out: } EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks); -int -ufs_qcom_phy_init_vregulators(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common) +int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common) { int err; - err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_pll, + err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_pll, "vdda-pll"); if (err) goto out; - err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_phy, + err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_phy, "vdda-phy"); if (err) goto out; /* vddp-ref-clk-* properties are optional */ - __ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vddp_ref_clk, + __ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk, "vddp-ref-clk", true); out: return err; } EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators); -static int __ufs_qcom_phy_init_vreg(struct phy *phy, +static int __ufs_qcom_phy_init_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional) { int err = 0; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; char prop_name[MAX_PROP_NAME]; @@ -304,14 +295,13 @@ out: return err; } -static int ufs_qcom_phy_init_vreg(struct phy *phy, +static int ufs_qcom_phy_init_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg, const char *name) { - return __ufs_qcom_phy_init_vreg(phy, vreg, name, false); + return __ufs_qcom_phy_init_vreg(dev, vreg, name, false); } -static -int ufs_qcom_phy_cfg_vreg(struct phy *phy, +static int ufs_qcom_phy_cfg_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg, bool on) { int ret = 0; @@ -319,8 +309,6 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy, const char *name = vreg->name; int min_uV; int uA_load; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; if (regulator_count_voltages(reg) > 0) { min_uV = on ? vreg->min_uV : 0; @@ -348,18 +336,15 @@ out: return ret; } -static -int ufs_qcom_phy_enable_vreg(struct phy *phy, +static int ufs_qcom_phy_enable_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg) { - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; int ret = 0; if (!vreg || vreg->enabled) goto out; - ret = ufs_qcom_phy_cfg_vreg(phy, vreg, true); + ret = ufs_qcom_phy_cfg_vreg(dev, vreg, true); if (ret) { dev_err(dev, "%s: ufs_qcom_phy_cfg_vreg() failed, err=%d\n", __func__, ret); @@ -430,12 +415,9 @@ out: } EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk); -static -int ufs_qcom_phy_disable_vreg(struct phy *phy, +static int ufs_qcom_phy_disable_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg) { - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; int ret = 0; if (!vreg || !vreg->enabled || vreg->is_always_on) @@ -445,7 +427,7 @@ int ufs_qcom_phy_disable_vreg(struct phy *phy, if (!ret) { /* ignore errors on applying disable config */ - ufs_qcom_phy_cfg_vreg(phy, vreg, false); + ufs_qcom_phy_cfg_vreg(dev, vreg, false); vreg->enabled = false; } else { dev_err(dev, "%s: %s disable failed, err=%d\n", @@ -673,7 +655,7 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) struct device *dev = phy_common->dev; int err; - err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_phy); + err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy); if (err) { dev_err(dev, "%s enable vdda_phy failed, err=%d\n", __func__, err); @@ -683,7 +665,7 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) phy_common->phy_spec_ops->power_control(phy_common, true); /* vdda_pll also enables ref clock LDOs so enable it first */ - err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_pll); + err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_pll); if (err) { dev_err(dev, "%s enable vdda_pll failed, err=%d\n", __func__, err); @@ -699,7 +681,7 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) /* enable device PHY ref_clk pad rail */ if (phy_common->vddp_ref_clk.reg) { - err = ufs_qcom_phy_enable_vreg(generic_phy, + err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vddp_ref_clk); if (err) { dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n", @@ -714,9 +696,9 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) out_disable_ref_clk: ufs_qcom_phy_disable_ref_clk(generic_phy); out_disable_pll: - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); + ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_pll); out_disable_phy: - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); + ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_phy); out: return err; } @@ -729,12 +711,12 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) phy_common->phy_spec_ops->power_control(phy_common, false); if (phy_common->vddp_ref_clk.reg) - ufs_qcom_phy_disable_vreg(generic_phy, + ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vddp_ref_clk); ufs_qcom_phy_disable_ref_clk(generic_phy); - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); + ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll); + ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy); phy_common->is_powered_on = false; return 0; From e41973769bb5d458c9449694b98382ba5d530cde Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:43 +0530 Subject: [PATCH 146/256] phy: qcom-ufs-14nm: Add new compatible for msm8996 based phy Add a new compatible string for 14nm ufs phy present on msm8996 chipset. This phy is bit different from the legacy 14nm ufs phy in terms of the clocks that are needed to be handled in the driver. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- Documentation/devicetree/bindings/ufs/ufs-qcom.txt | 7 +++++-- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt index 070baf4d7d97..b6b5130e5f65 100644 --- a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt +++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt @@ -7,8 +7,11 @@ To bind UFS PHY with UFS host controller, the controller node should contain a phandle reference to UFS PHY node. Required properties: -- compatible : compatible list, contains "qcom,ufs-phy-qmp-20nm" - or "qcom,ufs-phy-qmp-14nm" according to the relevant phy in use. +- compatible : compatible list, contains one of the following - + "qcom,ufs-phy-qmp-20nm" for 20nm ufs phy, + "qcom,ufs-phy-qmp-14nm" for legacy 14nm ufs phy, + "qcom,msm8996-ufs-phy-qmp-14nm" for 14nm ufs phy + present on MSM8996 chipset. - reg : should contain PHY register address space (mandatory), - reg-names : indicates various resources passed to driver (via reg proptery) by name. Required "reg-names" is "phy_mem". diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index e3bede73ec73..b3d2612a7ae8 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -180,6 +180,7 @@ static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev) static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-14nm"}, + {.compatible = "qcom,msm8996-ufs-phy-qmp-14nm"}, {}, }; MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match); From 300f96771d78e125c42592792e18b4c0cf58d386 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:44 +0530 Subject: [PATCH 147/256] phy: qcom-ufs: Skip obtaining rx/tx_iface_clk for msm8996 based phy The tx_iface_clk and rx_iface_clk no longer exist with UFS Phy present on msm8996. So skip obtaining these clocks using compatible match. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index b0171fef3868..3fa7b07aaeca 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -182,6 +182,10 @@ int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common) { int err; + if (of_device_is_compatible(phy_common->dev->of_node, + "qcom,msm8996-ufs-phy-qmp-14nm")) + goto skip_txrx_clk; + err = ufs_qcom_phy_clk_get(phy_common->dev, "tx_iface_clk", &phy_common->tx_iface_clk); if (err) @@ -197,6 +201,7 @@ int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common) if (err) goto out; +skip_txrx_clk: /* * "ref_clk_parent" is optional hence don't abort init if it's not * found. From a378508d361ccfce89557c4f1be01914ce70f1c3 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:45 +0530 Subject: [PATCH 148/256] phy: qcom-ufs-qmp-xx: Discard remove callback for drivers. remove() callback does a phy_power_off() only over the phy, and nothing else now. The phy_power_off() over the generic phy is called from the phy consumer, and phy provider driver should not explicitly need to call any phy ops. So discard the remove callback for qcom-ufs phy platform drivers. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 16 ---------------- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 16 ---------------- drivers/phy/phy-qcom-ufs.c | 9 --------- 3 files changed, 41 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index b3d2612a7ae8..560f272810f1 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -163,21 +163,6 @@ out: return err; } -static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-14nm"}, {.compatible = "qcom,msm8996-ufs-phy-qmp-14nm"}, @@ -187,7 +172,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match); static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = { .probe = ufs_qcom_phy_qmp_14nm_probe, - .remove = ufs_qcom_phy_qmp_14nm_remove, .driver = { .of_match_table = ufs_qcom_phy_qmp_14nm_of_match, .name = "ufs_qcom_phy_qmp_14nm", diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index e09ecb8c1e5f..9a2f53d5aa1d 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -219,21 +219,6 @@ out: return err; } -static int ufs_qcom_phy_qmp_20nm_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = { {.compatible = "qcom,ufs-phy-qmp-20nm"}, {}, @@ -242,7 +227,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match); static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = { .probe = ufs_qcom_phy_qmp_20nm_probe, - .remove = ufs_qcom_phy_qmp_20nm_remove, .driver = { .of_match_table = ufs_qcom_phy_qmp_20nm_of_match, .name = "ufs_qcom_phy_qmp_20nm", diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 3fa7b07aaeca..b85f88251aa2 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -619,15 +619,6 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) } EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy); -int ufs_qcom_phy_remove(struct phy *generic_phy, - struct ufs_qcom_phy *ufs_qcom_phy) -{ - phy_power_off(generic_phy); - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); - int ufs_qcom_phy_exit(struct phy *generic_phy) { struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); From 15887cb8cb912513c24e8834428922b8f4ae8eb5 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:46 +0530 Subject: [PATCH 149/256] phy: qcom-ufs: Remove unnecessary function declarations Move the functions' definitions to remove unnecessary declarations. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs.c | 131 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 69 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index b85f88251aa2..c5c29fef4c56 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -22,13 +22,6 @@ #define VDDP_REF_CLK_MIN_UV 1200000 #define VDDP_REF_CLK_MAX_UV 1200000 -static int __ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, - const char *, bool); -static int ufs_qcom_phy_init_vreg(struct device *, struct ufs_qcom_phy_vreg *, - const char *); -static int ufs_qcom_phy_base_init(struct platform_device *pdev, - struct ufs_qcom_phy *phy_common); - int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A, @@ -75,45 +68,6 @@ out: } EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate); -struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, - struct ufs_qcom_phy *common_cfg, - const struct phy_ops *ufs_qcom_phy_gen_ops, - struct ufs_qcom_phy_specific_ops *phy_spec_ops) -{ - int err; - struct device *dev = &pdev->dev; - struct phy *generic_phy = NULL; - struct phy_provider *phy_provider; - - err = ufs_qcom_phy_base_init(pdev, common_cfg); - if (err) { - dev_err(dev, "%s: phy base init failed %d\n", __func__, err); - goto out; - } - - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) { - err = PTR_ERR(phy_provider); - dev_err(dev, "%s: failed to register phy %d\n", __func__, err); - goto out; - } - - generic_phy = devm_phy_create(dev, NULL, ufs_qcom_phy_gen_ops); - if (IS_ERR(generic_phy)) { - err = PTR_ERR(generic_phy); - dev_err(dev, "%s: failed to create phy %d\n", __func__, err); - generic_phy = NULL; - goto out; - } - - common_cfg->phy_spec_ops = phy_spec_ops; - common_cfg->dev = dev; - -out: - return generic_phy; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); - /* * This assumes the embedded phy structure inside generic_phy is of type * struct ufs_qcom_phy. In order to function properly it's crucial @@ -154,6 +108,45 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev, return 0; } +struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, + struct ufs_qcom_phy *common_cfg, + const struct phy_ops *ufs_qcom_phy_gen_ops, + struct ufs_qcom_phy_specific_ops *phy_spec_ops) +{ + int err; + struct device *dev = &pdev->dev; + struct phy *generic_phy = NULL; + struct phy_provider *phy_provider; + + err = ufs_qcom_phy_base_init(pdev, common_cfg); + if (err) { + dev_err(dev, "%s: phy base init failed %d\n", __func__, err); + goto out; + } + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + err = PTR_ERR(phy_provider); + dev_err(dev, "%s: failed to register phy %d\n", __func__, err); + goto out; + } + + generic_phy = devm_phy_create(dev, NULL, ufs_qcom_phy_gen_ops); + if (IS_ERR(generic_phy)) { + err = PTR_ERR(generic_phy); + dev_err(dev, "%s: failed to create phy %d\n", __func__, err); + generic_phy = NULL; + goto out; + } + + common_cfg->phy_spec_ops = phy_spec_ops; + common_cfg->dev = dev; + +out: + return generic_phy; +} +EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); + static int __ufs_qcom_phy_clk_get(struct device *dev, const char *name, struct clk **clk_out, bool err_print) { @@ -217,29 +210,6 @@ out: } EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks); -int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common) -{ - int err; - - err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_pll, - "vdda-pll"); - if (err) - goto out; - - err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_phy, - "vdda-phy"); - - if (err) - goto out; - - /* vddp-ref-clk-* properties are optional */ - __ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk, - "vddp-ref-clk", true); -out: - return err; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators); - static int __ufs_qcom_phy_init_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional) { @@ -306,6 +276,29 @@ static int ufs_qcom_phy_init_vreg(struct device *dev, return __ufs_qcom_phy_init_vreg(dev, vreg, name, false); } +int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common) +{ + int err; + + err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_pll, + "vdda-pll"); + if (err) + goto out; + + err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_phy, + "vdda-phy"); + + if (err) + goto out; + + /* vddp-ref-clk-* properties are optional */ + __ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk, + "vddp-ref-clk", true); +out: + return err; +} +EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators); + static int ufs_qcom_phy_cfg_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg, bool on) { From 9c7ce698ba41eec51b7d3e6a68c29fca26a32793 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:47 +0530 Subject: [PATCH 150/256] phy: qcom-ufs-qmp-xx: Move clock and regulator init out of phy init The phy init is meant to do phy initialization rather than just getting the clock and regulator. Move these clock and regulator get to probe(), to make room for actual phy initialization sequence. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 52 ++++++++++++++--------------- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 46 ++++++++++++------------- 2 files changed, 46 insertions(+), 52 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 560f272810f1..ae74614baeb2 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -44,30 +44,7 @@ void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common) static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) { - struct ufs_qcom_phy_qmp_14nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = &phy->common_cfg; - int err; - - err = ufs_qcom_phy_init_clks(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; - phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; - - ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); - -out: - return err; + return 0; } static @@ -136,6 +113,7 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct phy *generic_phy; struct ufs_qcom_phy_qmp_14nm *phy; + struct ufs_qcom_phy *phy_common; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); @@ -143,8 +121,9 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) err = -ENOMEM; goto out; } + phy_common = &phy->common_cfg; - generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg, + generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common, &ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops); if (!generic_phy) { @@ -154,10 +133,29 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) goto out; } + err = ufs_qcom_phy_init_clks(phy_common); + if (err) { + dev_err(phy_common->dev, + "%s: ufs_qcom_phy_init_clks() failed %d\n", + __func__, err); + goto out; + } + + err = ufs_qcom_phy_init_vregulators(phy_common); + if (err) { + dev_err(phy_common->dev, + "%s: ufs_qcom_phy_init_vregulators() failed %d\n", + __func__, err); + goto out; + } + phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; + phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; + + ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); + phy_set_drvdata(generic_phy, phy); - strlcpy(phy->common_cfg.name, UFS_PHY_NAME, - sizeof(phy->common_cfg.name)); + strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name)); out: return err; diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 9a2f53d5aa1d..dfc51755d661 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -63,28 +63,7 @@ void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common) static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) { - struct ufs_qcom_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = &phy->common_cfg; - int err = 0; - - err = ufs_qcom_phy_init_clks(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - - ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common); - -out: - return err; + return 0; } static @@ -192,6 +171,7 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct phy *generic_phy; struct ufs_qcom_phy_qmp_20nm *phy; + struct ufs_qcom_phy *phy_common; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); @@ -199,8 +179,9 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) err = -ENOMEM; goto out; } + phy_common = &phy->common_cfg; - generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg, + generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common, &ufs_qcom_phy_qmp_20nm_phy_ops, &phy_20nm_ops); if (!generic_phy) { @@ -210,10 +191,25 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) goto out; } + err = ufs_qcom_phy_init_clks(phy_common); + if (err) { + dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", + __func__, err); + goto out; + } + + err = ufs_qcom_phy_init_vregulators(phy_common); + if (err) { + dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", + __func__, err); + goto out; + } + + ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common); + phy_set_drvdata(generic_phy, phy); - strlcpy(phy->common_cfg.name, UFS_PHY_NAME, - sizeof(phy->common_cfg.name)); + strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name)); out: return err; From feb3d79800ece19c18b979c5edd1c28755f59d07 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:48 +0530 Subject: [PATCH 151/256] scsi: ufs-qcom: phy/hcd: Refactoring phy clock handling Add phy clock enable code to phy_power_on/off callbacks, and remove explicit calls to enable these phy clocks from the ufs-qcom hcd driver. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs.c | 36 ++++++++++++++++---------------- drivers/scsi/ufs/ufs-qcom.c | 21 ++++++------------- include/linux/phy/phy-qcom-ufs.h | 18 ---------------- 3 files changed, 24 insertions(+), 51 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index c5c29fef4c56..fdd9b901983f 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -361,10 +361,9 @@ out: return ret; } -int ufs_qcom_phy_enable_ref_clk(struct phy *generic_phy) +static int ufs_qcom_phy_enable_ref_clk(struct ufs_qcom_phy *phy) { int ret = 0; - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); if (phy->is_ref_clk_enabled) goto out; @@ -411,7 +410,6 @@ out_disable_src: out: return ret; } -EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk); static int ufs_qcom_phy_disable_vreg(struct device *dev, struct ufs_qcom_phy_vreg *vreg) @@ -435,10 +433,8 @@ out: return ret; } -void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy) +static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy) { - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - if (phy->is_ref_clk_enabled) { clk_disable_unprepare(phy->ref_clk); /* @@ -451,7 +447,6 @@ void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy) phy->is_ref_clk_enabled = false; } } -EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk); #define UFS_REF_CLK_EN (1 << 5) @@ -504,9 +499,8 @@ void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy) EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk); /* Turn ON M-PHY RMMI interface clocks */ -int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy) +static int ufs_qcom_phy_enable_iface_clk(struct ufs_qcom_phy *phy) { - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); int ret = 0; if (phy->is_iface_clk_enabled) @@ -530,20 +524,16 @@ int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy) out: return ret; } -EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk); /* Turn OFF M-PHY RMMI interface clocks */ -void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy) +void ufs_qcom_phy_disable_iface_clk(struct ufs_qcom_phy *phy) { - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - if (phy->is_iface_clk_enabled) { clk_disable_unprepare(phy->tx_iface_clk); clk_disable_unprepare(phy->rx_iface_clk); phy->is_iface_clk_enabled = false; } } -EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk); int ufs_qcom_phy_start_serdes(struct phy *generic_phy) { @@ -661,11 +651,18 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) goto out_disable_phy; } - err = ufs_qcom_phy_enable_ref_clk(generic_phy); + err = ufs_qcom_phy_enable_iface_clk(phy_common); + if (err) { + dev_err(dev, "%s enable phy iface clock failed, err=%d\n", + __func__, err); + goto out_disable_pll; + } + + err = ufs_qcom_phy_enable_ref_clk(phy_common); if (err) { dev_err(dev, "%s enable phy ref clock failed, err=%d\n", __func__, err); - goto out_disable_pll; + goto out_disable_iface_clk; } /* enable device PHY ref_clk pad rail */ @@ -683,7 +680,9 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) goto out; out_disable_ref_clk: - ufs_qcom_phy_disable_ref_clk(generic_phy); + ufs_qcom_phy_disable_ref_clk(phy_common); +out_disable_iface_clk: + ufs_qcom_phy_disable_iface_clk(phy_common); out_disable_pll: ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_pll); out_disable_phy: @@ -702,7 +701,8 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) if (phy_common->vddp_ref_clk.reg) ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vddp_ref_clk); - ufs_qcom_phy_disable_ref_clk(generic_phy); + ufs_qcom_phy_disable_ref_clk(phy_common); + ufs_qcom_phy_disable_iface_clk(phy_common); ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll); ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy); diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 3c4f602eecd2..5f70a35c053f 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1114,17 +1114,8 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, return 0; if (on && (status == POST_CHANGE)) { - err = ufs_qcom_phy_enable_iface_clk(host->generic_phy); - if (err) - goto out; + phy_power_on(host->generic_phy); - err = ufs_qcom_phy_enable_ref_clk(host->generic_phy); - if (err) { - dev_err(hba->dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - goto out; - } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); @@ -1133,13 +1124,14 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, ufs_qcom_update_bus_bw_vote(host); } else if (!on && (status == PRE_CHANGE)) { - - /* M-PHY RMMI interface clocks can be turned off */ - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - if (!ufs_qcom_is_link_active(hba)) + if (!ufs_qcom_is_link_active(hba)) { /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); + /* powering off PHY during aggressive clk gating */ + phy_power_off(host->generic_phy); + } + vote = host->bus_vote.min_bw_vote; } @@ -1148,7 +1140,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, dev_err(hba->dev, "%s: set bus vote failed %d\n", __func__, err); -out: return err; } diff --git a/include/linux/phy/phy-qcom-ufs.h b/include/linux/phy/phy-qcom-ufs.h index 9d18e9f948e9..35c070ea6ea3 100644 --- a/include/linux/phy/phy-qcom-ufs.h +++ b/include/linux/phy/phy-qcom-ufs.h @@ -17,22 +17,6 @@ #include "phy.h" -/** - * ufs_qcom_phy_enable_ref_clk() - Enable the phy - * ref clock. - * @phy: reference to a generic phy - * - * returns 0 for success, and non-zero for error. - */ -int ufs_qcom_phy_enable_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_disable_ref_clk() - Disable the phy - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_disable_ref_clk(struct phy *phy); - /** * ufs_qcom_phy_enable_dev_ref_clk() - Enable the device * ref clock. @@ -47,8 +31,6 @@ void ufs_qcom_phy_enable_dev_ref_clk(struct phy *phy); */ void ufs_qcom_phy_disable_dev_ref_clk(struct phy *phy); -int ufs_qcom_phy_enable_iface_clk(struct phy *phy); -void ufs_qcom_phy_disable_iface_clk(struct phy *phy); int ufs_qcom_phy_start_serdes(struct phy *phy); int ufs_qcom_phy_set_tx_lane_enable(struct phy *phy, u32 tx_lanes); int ufs_qcom_phy_calibrate_phy(struct phy *phy, bool is_rate_B); From 3d4640f1cf84c6f40af356d6682205bf8d491731 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:49 +0530 Subject: [PATCH 152/256] phy: qcom-ufs: Remove common layer phy exit callback The common layer phy exit callback ufs_qcom_phy_exit() calls phy_power_off() that has no meaning when phy_power_off() callback is already registered with the phy provider and the consumer makes use of the same. Instead, add a no-op specific phy_exit() callback for now to add the exit sequence at a later point. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/phy/phy-qcom-ufs-i.h | 1 - drivers/phy/phy-qcom-ufs-qmp-14nm.c | 7 ++++++- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 7 ++++++- drivers/phy/phy-qcom-ufs.c | 17 ++++++----------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h index 69e836d0ec3e..d505d98cf5f8 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/phy-qcom-ufs-i.h @@ -141,7 +141,6 @@ struct ufs_qcom_phy_specific_ops { struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); int ufs_qcom_phy_power_on(struct phy *generic_phy); int ufs_qcom_phy_power_off(struct phy *generic_phy); -int ufs_qcom_phy_exit(struct phy *generic_phy); int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common); int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common); int ufs_qcom_phy_remove(struct phy *generic_phy, diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index ae74614baeb2..c71c84734916 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -47,6 +47,11 @@ static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) return 0; } +static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy) +{ + return 0; +} + static void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool val) { @@ -94,7 +99,7 @@ static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = { .init = ufs_qcom_phy_qmp_14nm_init, - .exit = ufs_qcom_phy_exit, + .exit = ufs_qcom_phy_qmp_14nm_exit, .power_on = ufs_qcom_phy_power_on, .power_off = ufs_qcom_phy_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index dfc51755d661..1a26a64e06d3 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -66,6 +66,11 @@ static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) return 0; } +static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy) +{ + return 0; +} + static void ufs_qcom_phy_qmp_20nm_power_control(struct ufs_qcom_phy *phy, bool val) { @@ -152,7 +157,7 @@ static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = { .init = ufs_qcom_phy_qmp_20nm_init, - .exit = ufs_qcom_phy_exit, + .exit = ufs_qcom_phy_qmp_20nm_exit, .power_on = ufs_qcom_phy_power_on, .power_off = ufs_qcom_phy_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index fdd9b901983f..c69568b8543d 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -602,17 +602,6 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) } EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy); -int ufs_qcom_phy_exit(struct phy *generic_phy) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - - if (ufs_qcom_phy->is_powered_on) - phy_power_off(generic_phy); - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit); - int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy) { struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); @@ -634,6 +623,9 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy) struct device *dev = phy_common->dev; int err; + if (phy_common->is_powered_on) + return 0; + err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy); if (err) { dev_err(dev, "%s enable vdda_phy failed, err=%d\n", @@ -696,6 +688,9 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) { struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); + if (!phy_common->is_powered_on) + return 0; + phy_common->phy_spec_ops->power_control(phy_common, false); if (phy_common->vddp_ref_clk.reg) From d7fe6b661abc2d034a0ad7d582a630f347d56a7b Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:50 +0530 Subject: [PATCH 153/256] scsi: ufs: qcom: Add phy_exit call in hcd exit path Do a phy_exit() over the ufs phy in the ufs qcom exit path to de-initialize the phy. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 5f70a35c053f..31df7838f790 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1280,6 +1280,7 @@ static void ufs_qcom_exit(struct ufs_hba *hba) ufs_qcom_disable_lane_clks(host); phy_power_off(host->generic_phy); + phy_exit(host->generic_phy); } static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, From 41e1d60ea50a97fe1c3f8075a13761ddc17dd45a Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Tue, 8 Nov 2016 15:37:51 +0530 Subject: [PATCH 154/256] scsi: ufs: qcom: Don't free resource-managed kmalloc element Host is allocated by managed kmalloc (devm_kmalloc). The memory allocated with this function is automatically freed on driver detach. So, no need to make an exclusive free call over it. Signed-off-by: Vivek Gautam Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 31df7838f790..804f4e70c771 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1268,7 +1268,6 @@ out_disable_phy: out_unregister_bus: phy_exit(host->generic_phy); out_host_free: - devm_kfree(dev, host); ufshcd_set_variant(hba, NULL); out: return err; From 6c7abffc7ff0125106fb79e0520b501c759aa9ed Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 31 Oct 2016 09:34:46 -0600 Subject: [PATCH 155/256] scsi: mpt3sas: fix some spelling mistakes in message and comments Trivial fixes, minor spelling mistakes in comments and in a KERN_INFO message. [mkp: fixed spelling mistake in patch description] Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 981be7b1df6a..4f28963b5074 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -423,7 +423,7 @@ _scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle, return 0; } - /* we hit this becuase the given parent handle doesn't exist */ + /* we hit this because the given parent handle doesn't exist */ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) return -ENXIO; @@ -1523,7 +1523,7 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, /* * raid transport support - * Enabled for SLES11 and newer, in older kernels the driver will panic when - * unloading the driver followed by a load - I beleive that the subroutine + * unloading the driver followed by a load - I believe that the subroutine * raid_class_release() is not cleaning up properly. */ @@ -2948,7 +2948,7 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) * @ioc: per adapter object * @handle: device handle * - * During device pull we need to appropiately set the sdev state. + * During device pull we need to appropriately set the sdev state. */ static void _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) @@ -2977,7 +2977,7 @@ _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) * @ioc: per adapter object * @handle: device handle * - * During device pull we need to appropiately set the sdev state. + * During device pull we need to appropriately set the sdev state. */ static void _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) @@ -3936,7 +3936,7 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc) * _scsih_setup_eedp - setup MPI request for EEDP transfer * @ioc: per adapter object * @scmd: pointer to scsi command object - * @mpi_request: pointer to the SCSI_IO reqest message frame + * @mpi_request: pointer to the SCSI_IO request message frame * * Supporting protection 1 and 3. * @@ -4088,7 +4088,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); return 0; - /* device busy with task managment */ + /* device busy with task management */ } else if (sas_target_priv_data->tm_busy || sas_device_priv_data->block) return SCSI_MLQUEUE_DEVICE_BUSY; @@ -6327,7 +6327,7 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) { sdev->no_uld_attach = no_uld_attach ? 1 : 0; sdev_printk(KERN_INFO, sdev, "%s raid component\n", - sdev->no_uld_attach ? "hidding" : "exposing"); + sdev->no_uld_attach ? "hiding" : "exposing"); WARN_ON(scsi_device_reprobe(sdev)); } @@ -9217,7 +9217,7 @@ scsih_init(void) /* queuecommand callback hander */ scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done); - /* task managment callback handler */ + /* task management callback handler */ tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done); /* base internal commands callback handler */ From d0799621349dedc8c866d6405302df8eba38f410 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 7 Nov 2016 16:38:57 +0000 Subject: [PATCH 156/256] scsi: fix spelling mistake in error message Trivial fix to spelling mistake "operatio" to "operation" in critical error message Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 21c8d210c456..d84004b5d3e0 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -3350,7 +3350,7 @@ static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, if (opblk_va == NULL) { dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), resblk_va, resblk_pa); - printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n", + printk(KERN_CRIT "%s: query operation failed; Out of memory.\n", pHba->name); return -ENOMEM; } From 4861ee15f2b7dee17a869d9edd3463b812f77636 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 8 Nov 2016 18:13:28 +0900 Subject: [PATCH 157/256] scsi: ufs: Use the resource-managed function to add devfreq device This patch uses the resource-managed to add the devfreq device. This function will make it easy to handle the devfreq device. - struct devfreq *devm_devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile, const char *governor_name, void *data); Cc: Vinayak Holikatti Cc: James E.J. Bottomley Cc: Martin K. Petersen Cc: linux-scsi@vger.kernel.org Signed-off-by: Chanwoo Choi Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 8cf5d8f7683b..9ca041b131e9 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6250,8 +6250,6 @@ void ufshcd_remove(struct ufs_hba *hba) ufshcd_hba_stop(hba, true); ufshcd_exit_clk_gating(hba); - if (ufshcd_is_clkscaling_enabled(hba)) - devfreq_remove_device(hba->devfreq); ufshcd_hba_exit(hba); } EXPORT_SYMBOL_GPL(ufshcd_remove); @@ -6579,7 +6577,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) } if (ufshcd_is_clkscaling_enabled(hba)) { - hba->devfreq = devfreq_add_device(dev, &ufs_devfreq_profile, + hba->devfreq = devm_devfreq_add_device(dev, &ufs_devfreq_profile, "simple_ondemand", NULL); if (IS_ERR(hba->devfreq)) { dev_err(hba->dev, "Unable to register with devfreq %ld\n", From bc2bb1543e62a5d0ae51ccdfde697dc97957f2a1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 9 Nov 2016 10:42:22 -0800 Subject: [PATCH 158/256] scsi: hpsa: use pci_alloc_irq_vectors and automatic irq affinity This patch converts over hpsa to use the pci_alloc_irq_vectors including the PCI_IRQ_AFFINITY flag that automatically assigns spread out irq affinity to the I/O queues. It also cleans up the per-ctrl interrupt state due to the use of the pci_irq_vector and pci_free_irq_vectors helpers that don't need to know the exact irq type. Additionally it changes a little oddity in the existing code that was using different array indixes into the per-vector arrays depending on whether a controller is using a single INTx or single MSI irq. [mkp: fixed typo] Signed-off-by: Christoph Hellwig Acked-by: Don Brace Tested-by: Don Brace Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 143 ++++++++++++++++---------------------------- drivers/scsi/hpsa.h | 6 +- 2 files changed, 52 insertions(+), 97 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4e82b692298e..9459925566f2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1001,7 +1001,7 @@ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c, { if (likely(h->transMethod & CFGTBL_Trans_Performant)) { c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); - if (unlikely(!h->msix_vector)) + if (unlikely(!h->msix_vectors)) return; if (likely(reply_queue == DEFAULT_REPLY_QUEUE)) c->Header.ReplyQueue = @@ -5618,7 +5618,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) sh->sg_tablesize = h->maxsgentries; sh->transportt = hpsa_sas_transport_template; sh->hostdata[0] = (unsigned long) h; - sh->irq = h->intr[h->intr_mode]; + sh->irq = pci_irq_vector(h->pdev, 0); sh->unique_id = sh->irq; h->scsi_host = sh; @@ -7651,67 +7651,41 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) static void hpsa_disable_interrupt_mode(struct ctlr_info *h) { - if (h->msix_vector) { - if (h->pdev->msix_enabled) - pci_disable_msix(h->pdev); - h->msix_vector = 0; - } else if (h->msi_vector) { - if (h->pdev->msi_enabled) - pci_disable_msi(h->pdev); - h->msi_vector = 0; - } + pci_free_irq_vectors(h->pdev); + h->msix_vectors = 0; } /* If MSI/MSI-X is supported by the kernel we will try to enable it on * controllers that are capable. If not, we use legacy INTx mode. */ -static void hpsa_interrupt_mode(struct ctlr_info *h) +static int hpsa_interrupt_mode(struct ctlr_info *h) { -#ifdef CONFIG_PCI_MSI - int err, i; - struct msix_entry hpsa_msix_entries[MAX_REPLY_QUEUES]; - - for (i = 0; i < MAX_REPLY_QUEUES; i++) { - hpsa_msix_entries[i].vector = 0; - hpsa_msix_entries[i].entry = i; - } + unsigned int flags = PCI_IRQ_LEGACY; + int ret; /* Some boards advertise MSI but don't really support it */ - if ((h->board_id == 0x40700E11) || (h->board_id == 0x40800E11) || - (h->board_id == 0x40820E11) || (h->board_id == 0x40830E11)) - goto default_int_mode; - if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) { - dev_info(&h->pdev->dev, "MSI-X capable controller\n"); - h->msix_vector = MAX_REPLY_QUEUES; - if (h->msix_vector > num_online_cpus()) - h->msix_vector = num_online_cpus(); - err = pci_enable_msix_range(h->pdev, hpsa_msix_entries, - 1, h->msix_vector); - if (err < 0) { - dev_warn(&h->pdev->dev, "MSI-X init failed %d\n", err); - h->msix_vector = 0; - goto single_msi_mode; - } else if (err < h->msix_vector) { - dev_warn(&h->pdev->dev, "only %d MSI-X vectors " - "available\n", err); + switch (h->board_id) { + case 0x40700E11: + case 0x40800E11: + case 0x40820E11: + case 0x40830E11: + break; + default: + ret = pci_alloc_irq_vectors(h->pdev, 1, MAX_REPLY_QUEUES, + PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); + if (ret > 0) { + h->msix_vectors = ret; + return 0; } - h->msix_vector = err; - for (i = 0; i < h->msix_vector; i++) - h->intr[i] = hpsa_msix_entries[i].vector; - return; + + flags |= PCI_IRQ_MSI; + break; } -single_msi_mode: - if (pci_find_capability(h->pdev, PCI_CAP_ID_MSI)) { - dev_info(&h->pdev->dev, "MSI capable controller\n"); - if (!pci_enable_msi(h->pdev)) - h->msi_vector = 1; - else - dev_warn(&h->pdev->dev, "MSI init failed\n"); - } -default_int_mode: -#endif /* CONFIG_PCI_MSI */ - /* if we get here we're going to use the default interrupt mode */ - h->intr[h->intr_mode] = h->pdev->irq; + + ret = pci_alloc_irq_vectors(h->pdev, 1, 1, flags); + if (ret < 0) + return ret; + return 0; } static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) @@ -8067,7 +8041,9 @@ static int hpsa_pci_init(struct ctlr_info *h) pci_set_master(h->pdev); - hpsa_interrupt_mode(h); + err = hpsa_interrupt_mode(h); + if (err) + goto clean1; err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr); if (err) goto clean2; /* intmode+region, pci */ @@ -8103,6 +8079,7 @@ clean3: /* vaddr, intmode+region, pci */ h->vaddr = NULL; clean2: /* intmode+region, pci */ hpsa_disable_interrupt_mode(h); +clean1: /* * call pci_disable_device before pci_release_regions per * Documentation/PCI/pci.txt @@ -8236,34 +8213,20 @@ clean_up: return -ENOMEM; } -static void hpsa_irq_affinity_hints(struct ctlr_info *h) -{ - int i, cpu; - - cpu = cpumask_first(cpu_online_mask); - for (i = 0; i < h->msix_vector; i++) { - irq_set_affinity_hint(h->intr[i], get_cpu_mask(cpu)); - cpu = cpumask_next(cpu, cpu_online_mask); - } -} - /* clear affinity hints and free MSI-X, MSI, or legacy INTx vectors */ static void hpsa_free_irqs(struct ctlr_info *h) { int i; - if (!h->msix_vector || h->intr_mode != PERF_MODE_INT) { + if (!h->msix_vectors || h->intr_mode != PERF_MODE_INT) { /* Single reply queue, only one irq to free */ - i = h->intr_mode; - irq_set_affinity_hint(h->intr[i], NULL); - free_irq(h->intr[i], &h->q[i]); - h->q[i] = 0; + free_irq(pci_irq_vector(h->pdev, 0), &h->q[i]); + h->q[h->intr_mode] = 0; return; } - for (i = 0; i < h->msix_vector; i++) { - irq_set_affinity_hint(h->intr[i], NULL); - free_irq(h->intr[i], &h->q[i]); + for (i = 0; i < h->msix_vectors; i++) { + free_irq(pci_irq_vector(h->pdev, i), &h->q[i]); h->q[i] = 0; } for (; i < MAX_REPLY_QUEUES; i++) @@ -8284,11 +8247,11 @@ static int hpsa_request_irqs(struct ctlr_info *h, for (i = 0; i < MAX_REPLY_QUEUES; i++) h->q[i] = (u8) i; - if (h->intr_mode == PERF_MODE_INT && h->msix_vector > 0) { + if (h->intr_mode == PERF_MODE_INT && h->msix_vectors > 0) { /* If performant mode and MSI-X, use multiple reply queues */ - for (i = 0; i < h->msix_vector; i++) { + for (i = 0; i < h->msix_vectors; i++) { sprintf(h->intrname[i], "%s-msix%d", h->devname, i); - rc = request_irq(h->intr[i], msixhandler, + rc = request_irq(pci_irq_vector(h->pdev, i), msixhandler, 0, h->intrname[i], &h->q[i]); if (rc) { @@ -8296,9 +8259,9 @@ static int hpsa_request_irqs(struct ctlr_info *h, dev_err(&h->pdev->dev, "failed to get irq %d for %s\n", - h->intr[i], h->devname); + pci_irq_vector(h->pdev, i), h->devname); for (j = 0; j < i; j++) { - free_irq(h->intr[j], &h->q[j]); + free_irq(pci_irq_vector(h->pdev, j), &h->q[j]); h->q[j] = 0; } for (; j < MAX_REPLY_QUEUES; j++) @@ -8306,33 +8269,27 @@ static int hpsa_request_irqs(struct ctlr_info *h, return rc; } } - hpsa_irq_affinity_hints(h); } else { /* Use single reply pool */ - if (h->msix_vector > 0 || h->msi_vector) { - if (h->msix_vector) - sprintf(h->intrname[h->intr_mode], - "%s-msix", h->devname); - else - sprintf(h->intrname[h->intr_mode], - "%s-msi", h->devname); - rc = request_irq(h->intr[h->intr_mode], + if (h->msix_vectors > 0 || h->pdev->msi_enabled) { + sprintf(h->intrname[0], "%s-msi%s", h->devname, + h->msix_vectors ? "x" : ""); + rc = request_irq(pci_irq_vector(h->pdev, 0), msixhandler, 0, - h->intrname[h->intr_mode], + h->intrname[0], &h->q[h->intr_mode]); } else { sprintf(h->intrname[h->intr_mode], "%s-intx", h->devname); - rc = request_irq(h->intr[h->intr_mode], + rc = request_irq(pci_irq_vector(h->pdev, 0), intxhandler, IRQF_SHARED, - h->intrname[h->intr_mode], + h->intrname[0], &h->q[h->intr_mode]); } - irq_set_affinity_hint(h->intr[h->intr_mode], NULL); } if (rc) { dev_err(&h->pdev->dev, "failed to get irq %d for %s\n", - h->intr[h->intr_mode], h->devname); + pci_irq_vector(h->pdev, 0), h->devname); hpsa_free_irqs(h); return -ENODEV; } @@ -9518,7 +9475,7 @@ static int hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) return rc; } - h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1; + h->nreply_queues = h->msix_vectors > 0 ? h->msix_vectors : 1; hpsa_get_max_perf_mode_cmds(h); /* Performant mode ring buffer and supporting data structures */ h->reply_queue_size = h->max_commands * sizeof(u64); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 82cdfad874f3..3faf6cff95ee 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -175,9 +175,7 @@ struct ctlr_info { # define DOORBELL_INT 1 # define SIMPLE_MODE_INT 2 # define MEMQ_MODE_INT 3 - unsigned int intr[MAX_REPLY_QUEUES]; - unsigned int msix_vector; - unsigned int msi_vector; + unsigned int msix_vectors; int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ struct access_method access; @@ -464,7 +462,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q) unsigned long register_value = FIFO_EMPTY; /* msi auto clears the interrupt pending bit. */ - if (unlikely(!(h->msi_vector || h->msix_vector))) { + if (unlikely(!(h->pdev->msi_enabled || h->msix_vectors))) { /* flush the controller write of the reply queue by reading * outbound doorbell status register. */ From 0e675efa9e9edef113bb55b25d1f22b1ae8225f4 Mon Sep 17 00:00:00 2001 From: Kiwoong Kim Date: Thu, 10 Nov 2016 21:14:36 +0900 Subject: [PATCH 159/256] scsi: ufs: introduce setup_xfer_req callback Some UFS host controller may need to configure some things before any transfer request is issued. Signed-off-by: Kiwoong Kim Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 ++ drivers/scsi/ufs/ufshcd.h | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9ca041b131e9..5d83f55edbde 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1516,6 +1516,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) /* issue command to the controller */ spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); ufshcd_send_command(hba, tag); out_unlock: spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -1727,6 +1728,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, /* Make sure descriptors are ready before ringing the doorbell */ wmb(); spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); ufshcd_send_command(hba, tag); spin_unlock_irqrestore(hba->host->host_lock, flags); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index afff7f4de81b..e935fd1b6b3a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -261,6 +261,8 @@ struct ufs_pwr_mode_info { * @pwr_change_notify: called before and after a power mode change * is carried out to allow vendor spesific capabilities * to be set. + * @setup_xfer_req: called before any transfer request is issued + * to set some things * @suspend: called during host controller PM callback * @resume: called during host controller PM callback * @dbg_register_dump: used to dump controller debug information @@ -284,6 +286,7 @@ struct ufs_hba_variant_ops { enum ufs_notify_change_status status, struct ufs_pa_layer_attr *, struct ufs_pa_layer_attr *); + void (*setup_xfer_req)(struct ufs_hba *, int, bool); int (*suspend)(struct ufs_hba *, enum ufs_pm_op); int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); @@ -801,6 +804,13 @@ static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba, return -ENOTSUPP; } +static inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag, + bool is_scsi_cmd) +{ + if (hba->vops && hba->vops->setup_xfer_req) + return hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd); +} + static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) { if (hba->vops && hba->vops->suspend) From d2877be42f35a8420dc452cf775b5f99b55169aa Mon Sep 17 00:00:00 2001 From: Kiwoong Kim Date: Thu, 10 Nov 2016 21:16:15 +0900 Subject: [PATCH 160/256] scsi: ufs: introduce setup_task_mgmt Some UFS host controller may need to configure some things before any task management request is issued Signed-off-by: Kiwoong Kim Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 ++ drivers/scsi/ufs/ufshcd.h | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5d83f55edbde..043e777712ae 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4357,6 +4357,8 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, task_req_upiup->input_param1 = cpu_to_be32(lun_id); task_req_upiup->input_param2 = cpu_to_be32(task_id); + ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); + /* send command to the controller */ __set_bit(free_slot, &hba->outstanding_tasks); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index e935fd1b6b3a..05d8384a9b2a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -263,6 +263,8 @@ struct ufs_pwr_mode_info { * to be set. * @setup_xfer_req: called before any transfer request is issued * to set some things + * @setup_task_mgmt: called before any task management request is issued + * to set some things * @suspend: called during host controller PM callback * @resume: called during host controller PM callback * @dbg_register_dump: used to dump controller debug information @@ -287,6 +289,7 @@ struct ufs_hba_variant_ops { struct ufs_pa_layer_attr *, struct ufs_pa_layer_attr *); void (*setup_xfer_req)(struct ufs_hba *, int, bool); + void (*setup_task_mgmt)(struct ufs_hba *, int, u8); int (*suspend)(struct ufs_hba *, enum ufs_pm_op); int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); @@ -811,6 +814,13 @@ static inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag, return hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd); } +static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba, + int tag, u8 tm_function) +{ + if (hba->vops && hba->vops->setup_task_mgmt) + return hba->vops->setup_task_mgmt(hba, tag, tm_function); +} + static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) { if (hba->vops && hba->vops->suspend) From ee32c9098f2eff12c0e020aac2acade8250c80e4 Mon Sep 17 00:00:00 2001 From: Kiwoong Kim Date: Thu, 10 Nov 2016 21:17:43 +0900 Subject: [PATCH 161/256] scsi: ufs: introduce hibern8_notify callback Some UFS host controller may need to configure some things around hibern8 enter/exit Signed-off-by: Kiwoong Kim Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 12 ++++++++++-- drivers/scsi/ufs/ufshcd.h | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 043e777712ae..576b29c11d7a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2697,6 +2697,8 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba) int ret; struct uic_command uic_cmd = {0}; + ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, PRE_CHANGE); + uic_cmd.command = UIC_CMD_DME_HIBER_ENTER; ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); @@ -2710,7 +2712,9 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba) */ if (ufshcd_link_recovery(hba)) ret = -ENOLINK; - } + } else + ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, + POST_CHANGE); return ret; } @@ -2733,13 +2737,17 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) struct uic_command uic_cmd = {0}; int ret; + ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, PRE_CHANGE); + uic_cmd.command = UIC_CMD_DME_HIBER_EXIT; ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); if (ret) { dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n", __func__, ret); ret = ufshcd_link_recovery(hba); - } + } else + ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, + POST_CHANGE); return ret; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 05d8384a9b2a..8e76501144d6 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -265,6 +265,8 @@ struct ufs_pwr_mode_info { * to set some things * @setup_task_mgmt: called before any task management request is issued * to set some things + * @hibern8_notify: called around hibern8 enter/exit + * to configure some things * @suspend: called during host controller PM callback * @resume: called during host controller PM callback * @dbg_register_dump: used to dump controller debug information @@ -290,6 +292,8 @@ struct ufs_hba_variant_ops { struct ufs_pa_layer_attr *); void (*setup_xfer_req)(struct ufs_hba *, int, bool); void (*setup_task_mgmt)(struct ufs_hba *, int, u8); + void (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme, + enum ufs_notify_change_status); int (*suspend)(struct ufs_hba *, enum ufs_pm_op); int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); @@ -821,6 +825,14 @@ static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba, return hba->vops->setup_task_mgmt(hba, tag, tm_function); } +static inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba, + enum uic_cmd_dme cmd, + enum ufs_notify_change_status status) +{ + if (hba->vops && hba->vops->hibern8_notify) + return hba->vops->hibern8_notify(hba, cmd, status); +} + static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) { if (hba->vops && hba->vops->suspend) From 7b93ca43b7e21fbe6fb1a6f4ecce4a2f70f424a0 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 11 Nov 2016 10:00:20 +1100 Subject: [PATCH 162/256] scsi: g_NCR5380: Fix release_region in error handling When a SW-configurable card is specified but not found, the driver releases wrong region, causing the following message in kernel log: Trying to free nonexistent resource <0000000000000000-000000000000000f> Fix it by assigning base earlier. Signed-off-by: Ondrej Zary Fixes: a8cfbcaec0c1 ("scsi: g_NCR5380: Stop using scsi_module.c") Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen --- drivers/scsi/g_NCR5380.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 7299ad9889c9..de5147a8c959 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -164,12 +164,12 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, if (ports[i]) { /* At this point we have our region reserved */ magic_configure(i, 0, magic); /* no IRQ yet */ - outb(0xc0, ports[i] + 9); - if (inb(ports[i] + 9) != 0x80) { + base = ports[i]; + outb(0xc0, base + 9); + if (inb(base + 9) != 0x80) { ret = -ENODEV; goto out_release; } - base = ports[i]; port_idx = i; } else return -EINVAL; From 378eeade1fa907ab6f6795560d94d9e67ca9353d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 11 Nov 2016 16:55:50 -0800 Subject: [PATCH 163/256] scsi: scsi_transport_fc: Hold queue lock while calling blk_run_queue_async() It is required to hold the queue lock when calling blk_run_queue_async() to avoid that a race between blk_run_queue_async() and blk_cleanup_queue() is triggered. Additionally, remove the get_device() and put_device() calls from fc_bsg_goose_queue. It is namely the responsibility of the caller of fc_bsg_goose_queue() to ensure that the bsg queue does not disappear while fc_bsg_goose_queue() is in progress. Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: James Smart Reviewed-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 45340857f240..e05c07f25bc3 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3855,15 +3855,15 @@ fail_host_msg: static void fc_bsg_goose_queue(struct fc_rport *rport) { - if (!rport->rqst_q) + struct request_queue *q = rport->rqst_q; + unsigned long flags; + + if (!q) return; - /* - * This get/put dance makes no sense - */ - get_device(&rport->dev); - blk_run_queue_async(rport->rqst_q); - put_device(&rport->dev); + spin_lock_irqsave(q->queue_lock, flags); + blk_run_queue_async(q); + spin_unlock_irqrestore(q->queue_lock, flags); } /** From 644da3c39aaa9fac630ecb2657b43adf0c8e97fc Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 12 Nov 2016 16:25:24 +0000 Subject: [PATCH 164/256] scsi: megaraid_sas: add in missing white spaces in error messages text A couple of dev_printk messages spans two lines and the literal string is missing a white space between words. Add the white space. Signed-off-by: Colin Ian King Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f6db7abf150d..d8eaf533b407 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -6788,8 +6788,7 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { spin_unlock_irqrestore(&instance->hba_lock, flags); - dev_err(&instance->pdev->dev, "timed out while" - "waiting for HBA to recover\n"); + dev_err(&instance->pdev->dev, "timed out while waiting for HBA to recover\n"); error = -ENODEV; goto out_up; } @@ -6857,8 +6856,7 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) spin_lock_irqsave(&instance->hba_lock, flags); if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { spin_unlock_irqrestore(&instance->hba_lock, flags); - dev_err(&instance->pdev->dev, "timed out while waiting" - "for HBA to recover\n"); + dev_err(&instance->pdev->dev, "timed out while waiting for HBA to recover\n"); return -ENODEV; } spin_unlock_irqrestore(&instance->hba_lock, flags); From 99c7b6aec1d25c987ef9d4a34e34278b43b35f17 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 12 Nov 2016 16:49:50 +0000 Subject: [PATCH 165/256] scsi: isci: fix spelling mistakes in dev_warn messages Trivial fix to spelling mistake "suspeneded" to "suspended" in dev_warn messages. [mkp: corrected description. Patch is against the isci driver, not iscsi] Signed-off-by: Colin Ian King Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/remote_node_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 1910100638a2..30bd80052e03 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -454,7 +454,7 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con * the device since it's being invalidated anyway */ dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p was " - "suspeneded by hardware while being " + "suspended by hardware while being " "invalidated.\n", __func__, sci_rnc); break; default: @@ -473,7 +473,7 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con * the device since it's being resumed anyway */ dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p was " - "suspeneded by hardware while being resumed.\n", + "suspended by hardware while being resumed.\n", __func__, sci_rnc); break; default: From 63eb7b6bc7a35ce66dbf829850ad9b46fb3ecf5e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 12 Nov 2016 18:30:26 +0000 Subject: [PATCH 166/256] scsi: isci: fix typo in deg_dbg message Trivial fix to typo "repsonse" to "response" in dev_dbg message. Signed-off-by: Colin Ian King Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index b709d2b20880..47f66e949745 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2473,7 +2473,7 @@ static void isci_request_process_response_iu( "%s: resp_iu = %p " "resp_iu->status = 0x%x,\nresp_iu->datapres = %d " "resp_iu->response_data_len = %x, " - "resp_iu->sense_data_len = %x\nrepsonse data: ", + "resp_iu->sense_data_len = %x\nresponse data: ", __func__, resp_iu, resp_iu->status, From 7dc62d935459fc48778d9306f2094a8fd16614dd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 14 Nov 2016 12:59:35 +0000 Subject: [PATCH 167/256] scsi: hpsa: free irq on q indexed by h->intr_mode and not i Use correct index on q, use h->intr_mode instead of i. Issue detected using static analysis with cppcheck Fixes: bc2bb1543e62a5d0 ("scsi: hpsa: use pci_alloc_irq_vectors and automatic irq affinity") Signed-off-by: Colin Ian King Reviewed-by: Christoph Hellwig Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9459925566f2..0d4f21c95a40 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8220,7 +8220,7 @@ static void hpsa_free_irqs(struct ctlr_info *h) if (!h->msix_vectors || h->intr_mode != PERF_MODE_INT) { /* Single reply queue, only one irq to free */ - free_irq(pci_irq_vector(h->pdev, 0), &h->q[i]); + free_irq(pci_irq_vector(h->pdev, 0), &h->q[h->intr_mode]); h->q[h->intr_mode] = 0; return; } From 18103efcacee0563d57c3b7af8d849faae62a117 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Tue, 1 Nov 2016 17:32:02 +0100 Subject: [PATCH 168/256] scsi: megaraid-sas: request irqs later It is not good when an irq arrives before driver structures are allocated. Signed-off-by: Tomas Henzl Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index d8eaf533b407..546267698486 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5149,11 +5149,6 @@ static int megasas_init_fw(struct megasas_instance *instance) tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, (unsigned long)instance); - if (instance->msix_vectors ? - megasas_setup_irqs_msix(instance, 1) : - megasas_setup_irqs_ioapic(instance)) - goto fail_setup_irqs; - instance->ctrl_info = kzalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); if (instance->ctrl_info == NULL) @@ -5169,6 +5164,10 @@ static int megasas_init_fw(struct megasas_instance *instance) if (instance->instancet->init_adapter(instance)) goto fail_init_adapter; + if (instance->msix_vectors ? + megasas_setup_irqs_msix(instance, 1) : + megasas_setup_irqs_ioapic(instance)) + goto fail_init_adapter; instance->instancet->enable_intr(instance); @@ -5308,9 +5307,8 @@ static int megasas_init_fw(struct megasas_instance *instance) fail_get_pd_list: instance->instancet->disable_intr(instance); -fail_init_adapter: megasas_destroy_irqs(instance); -fail_setup_irqs: +fail_init_adapter: if (instance->msix_vectors) pci_disable_msix(instance->pdev); instance->msix_vectors = 0; From bfd7546cd19abf0f8a08c1339a917fe326fcfc71 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Tue, 15 Nov 2016 14:45:32 -0600 Subject: [PATCH 169/256] scsi: hpsa: correct logical resets - driver was not calling done in some cases which causes the volume to be offlined. - avoid doing rescan during a reset. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0d4f21c95a40..5b1ba5861275 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -276,6 +276,9 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev, unsigned long *memory_bar); static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id); +static int wait_for_device_to_become_ready(struct ctlr_info *h, + unsigned char lunaddr[], + int reply_queue); static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr, int wait_for_ready); static inline void finish_cmd(struct CommandList *c); @@ -2540,7 +2543,7 @@ static void complete_scsi_command(struct CommandList *cp) if ((unlikely(hpsa_is_pending_event(cp)))) { if (cp->reset_pending) - return hpsa_cmd_resolve_and_free(h, cp); + return hpsa_cmd_free_and_done(h, cp, cmd); if (cp->abort_pending) return hpsa_cmd_abort_and_free(h, cp, cmd); } @@ -3079,6 +3082,8 @@ static int hpsa_do_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, if (unlikely(rc)) atomic_set(&dev->reset_cmds_out, 0); + else + wait_for_device_to_become_ready(h, scsi3addr, 0); mutex_unlock(&h->reset_mutex); return rc; @@ -5563,6 +5568,14 @@ static void hpsa_scan_start(struct Scsi_Host *sh) if (unlikely(lockup_detected(h))) return hpsa_scan_complete(h); + /* + * Do the scan after a reset completion + */ + if (h->reset_in_progress) { + h->drv_req_rescan = 1; + return; + } + hpsa_update_scsi_devices(h); hpsa_scan_complete(h); @@ -8590,6 +8603,14 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work) if (h->remove_in_progress) return; + /* + * Do the scan after the reset + */ + if (h->reset_in_progress) { + h->drv_req_rescan = 1; + return; + } + if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) { scsi_host_get(h->scsi_host); hpsa_ack_ctlr_events(h); From 6593ccd8002ca00a35e71aceb067aebeef165718 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Tue, 15 Nov 2016 12:39:29 -0800 Subject: [PATCH 170/256] MAINTAINERS: Updating maintainers list for Cisco FNI and SNIC drivers Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index b3a77741da80..11fdf455c614 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3149,15 +3149,15 @@ S: Supported F: drivers/clocksource CISCO FCOE HBA DRIVER -M: Hiral Patel -M: Suma Ramars -M: Brian Uchino +M: Satish Kharat +M: Sesidhar Baddela +M: Karan Tilak Kumar L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/fnic/ CISCO SCSI HBA DRIVER -M: Narsimhulu Musini +M: Karan Tilak Kumar M: Sesidhar Baddela L: linux-scsi@vger.kernel.org S: Supported From 141f81651037ea109188a6bafdc5c9a318bd5a46 Mon Sep 17 00:00:00 2001 From: Zang Leigang Date: Wed, 16 Nov 2016 11:29:37 +0800 Subject: [PATCH 171/256] scsi: ufs: introduce a new ufshcd_statea UFSHCD_STATE_EH_SCHEDULED Add a new ufshcd_state, indicats that an err handler may get to run immediately. Use UFSHCD_STATE_ERROR here looks not literaly correct. Signed-off-by: Zang Leigang Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 576b29c11d7a..421488161cf3 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -125,6 +125,7 @@ enum { UFSHCD_STATE_RESET, UFSHCD_STATE_ERROR, UFSHCD_STATE_OPERATIONAL, + UFSHCD_STATE_EH_SCHEDULED, }; /* UFSHCD error handling flags */ @@ -1450,6 +1451,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) switch (hba->ufshcd_state) { case UFSHCD_STATE_OPERATIONAL: break; + case UFSHCD_STATE_EH_SCHEDULED: case UFSHCD_STATE_RESET: err = SCSI_MLQUEUE_HOST_BUSY; goto out_unlock; @@ -4212,7 +4214,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba) /* block commands from scsi mid-layer */ scsi_block_requests(hba->host); - hba->ufshcd_state = UFSHCD_STATE_ERROR; + hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED; schedule_work(&hba->eh_work); } } From 6008e96b8107a4e30a97de947bd0fac239836b58 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Wed, 16 Nov 2016 00:54:01 -0800 Subject: [PATCH 172/256] scsi: fnic: Correcting rport check location in fnic_queuecommand_lck Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_scsi.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index bfaba069937f..2544a37ece0a 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -441,30 +441,38 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ unsigned long ptr; spinlock_t *io_lock = NULL; int io_lock_acquired = 0; + struct fc_rport_libfc_priv *rp; if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) return SCSI_MLQUEUE_HOST_BUSY; rport = starget_to_rport(scsi_target(sc->device)); + if (!rport) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "returning DID_NO_CONNECT for IO as rport is NULL\n"); + sc->result = DID_NO_CONNECT << 16; + done(sc); + return 0; + } + ret = fc_remote_port_chkready(rport); if (ret) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "rport is not ready\n"); atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); sc->result = ret; done(sc); return 0; } - if (rport) { - struct fc_rport_libfc_priv *rp = rport->dd_data; - - if (!rp || rp->rp_state != RPORT_ST_READY) { - FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + rp = rport->dd_data; + if (!rp || rp->rp_state != RPORT_ST_READY) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "returning DID_NO_CONNECT for IO as rport is removed\n"); - atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); - sc->result = DID_NO_CONNECT<<16; - done(sc); - return 0; - } + atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); + sc->result = DID_NO_CONNECT<<16; + done(sc); + return 0; } if (lp->state != LPORT_ST_READY || !(lp->link_up)) From 5e315016d04c01b9aaaf45857eca6d7129c833fb Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 16 Nov 2016 21:00:58 +0800 Subject: [PATCH 173/256] scsi: dmx3191d: use module_pci_driver Use module_pci_driver() helper to simplify the code. Signed-off-by: Geliang Tang Acked-by: Finn Thain Signed-off-by: Martin K. Petersen --- drivers/scsi/dmx3191d.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 3aa4657478e8..6af3394d051d 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -153,18 +153,7 @@ static struct pci_driver dmx3191d_pci_driver = { .remove = dmx3191d_remove_one, }; -static int __init dmx3191d_init(void) -{ - return pci_register_driver(&dmx3191d_pci_driver); -} - -static void __exit dmx3191d_exit(void) -{ - pci_unregister_driver(&dmx3191d_pci_driver); -} - -module_init(dmx3191d_init); -module_exit(dmx3191d_exit); +module_pci_driver(dmx3191d_pci_driver); MODULE_AUTHOR("Massimo Piccioni "); MODULE_DESCRIPTION("Domex DMX3191D SCSI driver"); From af15769ffab13d777e55fdef09d0762bf0c249c4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 16 Nov 2016 16:08:34 +0100 Subject: [PATCH 174/256] scsi: mvsas: fix command_active typo gcc-7 notices that the condition in mvs_94xx_command_active looks suspicious: drivers/scsi/mvsas/mv_94xx.c: In function 'mvs_94xx_command_active': drivers/scsi/mvsas/mv_94xx.c:671:15: error: '<<' in boolean context, did you mean '<' ? [-Werror=int-in-bool-context] This was introduced when the mv_printk() statement got added, and leads to the condition being ignored. This is probably harmless. Changing '&&' to '&' makes the code look reasonable, as we check the command bit before setting and printing it. Fixes: a4632aae8b66 ("[SCSI] mvsas: Add new macros and functions") Signed-off-by: Arnd Bergmann Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/mvsas/mv_94xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 4c57d9abce7b..7de5d8d75480 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -668,7 +668,7 @@ static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx) { u32 tmp; tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3)); - if (tmp && 1 << (slot_idx % 32)) { + if (tmp & 1 << (slot_idx % 32)) { mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx); mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3), 1 << (slot_idx % 32)); From eb34094820c5dcfc8fa0bf68382e08ebac743dc2 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:11 +0100 Subject: [PATCH 175/256] scsi: Get rid of struct fc_bsg_buffer struct fc_bsg_buffer is just a clone of struct bsg_buffer from bsg-lib, so use this one instead. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 3 ++- drivers/scsi/scsi_transport_fc.c | 2 +- include/scsi/scsi_transport_fc.h | 12 +++--------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index e6a5254abd4f..0148ee3ef70b 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -211,7 +212,7 @@ lpfc_alloc_bsg_buffers(struct lpfc_hba *phba, unsigned int size, static unsigned int lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers, - struct fc_bsg_buffer *bsg_buffers, + struct bsg_buffer *bsg_buffers, unsigned int bytes_to_transfer, int to_buffers) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index e05c07f25bc3..dbb9bdd569af 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3671,7 +3671,7 @@ fc_bsg_job_timeout(struct request *req) } static int -fc_bsg_map_buffer(struct fc_bsg_buffer *buf, struct request *req) +fc_bsg_map_buffer(struct bsg_buffer *buf, struct request *req) { size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments); diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index bf66ea6bed2b..921b097f039b 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -28,6 +28,7 @@ #define SCSI_TRANSPORT_FC_H #include +#include #include #include #include @@ -624,13 +625,6 @@ struct fc_host_attrs { #define fc_host_dev_loss_tmo(x) \ (((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo) - -struct fc_bsg_buffer { - unsigned int payload_len; - int sg_cnt; - struct scatterlist *sg_list; -}; - /* Values for fc_bsg_job->state_flags (bitflags) */ #define FC_RQST_STATE_INPROGRESS 0 #define FC_RQST_STATE_DONE 1 @@ -659,8 +653,8 @@ struct fc_bsg_job { */ /* DMA payloads for the request/response */ - struct fc_bsg_buffer request_payload; - struct fc_bsg_buffer reply_payload; + struct bsg_buffer request_payload; + struct bsg_buffer reply_payload; void *dd_data; /* Used for driver-specific storage */ }; From 01e0e15c8b3b32e006e5cccac10c8b377ac3d803 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:12 +0100 Subject: [PATCH 176/256] scsi: don't use fc_bsg_job::request and fc_bsg_job::reply directly Don't use fc_bsg_job::request and fc_bsg_job::reply directly, but use helper variables bsg_request and bsg_reply. This will be helpful when transitioning to bsg-lib. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fc.c | 9 +- drivers/scsi/bfa/bfad_bsg.c | 40 +++-- drivers/scsi/ibmvscsi/ibmvfc.c | 22 +-- drivers/scsi/libfc/fc_lport.c | 23 +-- drivers/scsi/lpfc/lpfc_bsg.c | 199 ++++++++++++++--------- drivers/scsi/qla2xxx/qla_bsg.c | 264 ++++++++++++++++++------------- drivers/scsi/qla2xxx/qla_iocb.c | 5 +- drivers/scsi/qla2xxx/qla_isr.c | 46 +++--- drivers/scsi/qla2xxx/qla_mr.c | 10 +- drivers/scsi/scsi_transport_fc.c | 55 ++++--- 10 files changed, 398 insertions(+), 275 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 237688af179b..4c4023fc6ad8 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -900,8 +900,9 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job) u32 preamble_word1; u8 gs_type; struct zfcp_adapter *adapter; + struct fc_bsg_request *bsg_request = job->request; - preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; + preamble_word1 = bsg_request->rqst_data.r_ct.preamble_word1; gs_type = (preamble_word1 & 0xff000000) >> 24; adapter = (struct zfcp_adapter *) job->shost->hostdata[0]; @@ -938,6 +939,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, { struct zfcp_fsf_ct_els *els = job->dd_data; struct fc_rport *rport = job->rport; + struct fc_bsg_request *bsg_request = job->request; struct zfcp_port *port; u32 d_id; @@ -949,7 +951,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, d_id = port->d_id; put_device(&port->dev); } else - d_id = ntoh24(job->request->rqst_data.h_els.port_id); + d_id = ntoh24(bsg_request->rqst_data.h_els.port_id); els->handler = zfcp_fc_ct_els_job_handler; return zfcp_fsf_send_els(adapter, d_id, els, job->req->timeout / HZ); @@ -983,6 +985,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) struct Scsi_Host *shost; struct zfcp_adapter *adapter; struct zfcp_fsf_ct_els *ct_els = job->dd_data; + struct fc_bsg_request *bsg_request = job->request; shost = job->rport ? rport_to_shost(job->rport) : job->shost; adapter = (struct zfcp_adapter *)shost->hostdata[0]; @@ -994,7 +997,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) ct_els->resp = job->reply_payload.sg_list; ct_els->handler_data = job; - switch (job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: case FC_BSG_HST_ELS_NOLOGIN: return zfcp_fc_exec_els_job(job, adapter); diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index d1ad0208dfe7..48366d8ad0d9 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3132,7 +3132,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, static int bfad_im_bsg_vendor_request(struct fc_bsg_job *job) { - uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0]; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; + uint32_t vendor_cmd = bsg_request->rqst_data.h_vendor.vendor_cmd[0]; struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) job->shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; @@ -3175,8 +3177,8 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job) /* Fill the BSG job reply data */ job->reply_len = job->reply_payload.payload_len; - job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; - job->reply->result = rc; + bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; + bsg_reply->result = rc; job->job_done(job); return rc; @@ -3184,9 +3186,9 @@ error: /* free the command buffer */ kfree(payload_kbuf); out: - job->reply->result = rc; + bsg_reply->result = rc; job->reply_len = sizeof(uint32_t); - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; return rc; } @@ -3362,18 +3364,20 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job) struct bfad_fcxp *drv_fcxp; struct bfa_fcs_lport_s *fcs_port; struct bfa_fcs_rport_s *fcs_rport; - uint32_t command_type = job->request->msgcode; + struct fc_bsg_request *bsg_request = bsg_request; + struct fc_bsg_reply *bsg_reply = job->reply; + uint32_t command_type = bsg_request->msgcode; unsigned long flags; struct bfad_buf_info *rsp_buf_info; void *req_kbuf = NULL, *rsp_kbuf = NULL; int rc = -EINVAL; job->reply_len = sizeof(uint32_t); /* Atleast uint32_t reply_len */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; /* Get the payload passed in from userspace */ - bsg_data = (struct bfa_bsg_data *) (((char *)job->request) + - sizeof(struct fc_bsg_request)); + bsg_data = (struct bfa_bsg_data *) (((char *)bsg_request) + + sizeof(struct fc_bsg_request)); if (bsg_data == NULL) goto out; @@ -3517,13 +3521,13 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job) /* fill the job->reply data */ if (drv_fcxp->req_status == BFA_STATUS_OK) { job->reply_len = drv_fcxp->rsp_len; - job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len; - job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; + bsg_reply->reply_payload_rcv_len = drv_fcxp->rsp_len; + bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; } else { - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sizeof(struct fc_bsg_ctels_reply); job->reply_len = sizeof(uint32_t); - job->reply->reply_data.ctels_reply.status = + bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT; } @@ -3549,7 +3553,7 @@ out_free_mem: kfree(bsg_fcpt); kfree(drv_fcxp); out: - job->reply->result = rc; + bsg_reply->result = rc; if (rc == BFA_STATUS_OK) job->job_done(job); @@ -3560,9 +3564,11 @@ out: int bfad_im_bsg_request(struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; uint32_t rc = BFA_STATUS_OK; - switch (job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_HST_VENDOR: /* Process BSG HST Vendor requests */ rc = bfad_im_bsg_vendor_request(job); @@ -3575,8 +3581,8 @@ bfad_im_bsg_request(struct fc_bsg_job *job) rc = bfad_im_bsg_els_ct_request(job); break; default: - job->reply->result = rc = -EINVAL; - job->reply->reply_payload_rcv_len = 0; + bsg_reply->result = rc = -EINVAL; + bsg_reply->reply_payload_rcv_len = 0; break; } diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 7e487c78279c..7c17a7e73eb9 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1827,28 +1827,30 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job) struct ibmvfc_event *evt; union ibmvfc_iu rsp_iu; unsigned long flags, port_id = -1; - unsigned int code = job->request->msgcode; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; + unsigned int code = bsg_request->msgcode; int rc = 0, req_seg, rsp_seg, issue_login = 0; u32 fc_flags, rsp_len; ENTER; - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (rport) port_id = rport->port_id; switch (code) { case FC_BSG_HST_ELS_NOLOGIN: - port_id = (job->request->rqst_data.h_els.port_id[0] << 16) | - (job->request->rqst_data.h_els.port_id[1] << 8) | - job->request->rqst_data.h_els.port_id[2]; + port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | + (bsg_request->rqst_data.h_els.port_id[1] << 8) | + bsg_request->rqst_data.h_els.port_id[2]; case FC_BSG_RPT_ELS: fc_flags = IBMVFC_FC_ELS; break; case FC_BSG_HST_CT: issue_login = 1; - port_id = (job->request->rqst_data.h_ct.port_id[0] << 16) | - (job->request->rqst_data.h_ct.port_id[1] << 8) | - job->request->rqst_data.h_ct.port_id[2]; + port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | + (bsg_request->rqst_data.h_ct.port_id[1] << 8) | + bsg_request->rqst_data.h_ct.port_id[2]; case FC_BSG_RPT_CT: fc_flags = IBMVFC_FC_CT_IU; break; @@ -1937,12 +1939,12 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job) if (rsp_iu.passthru.common.status) rc = -EIO; else - job->reply->reply_payload_rcv_len = rsp_len; + bsg_reply->reply_payload_rcv_len = rsp_len; spin_lock_irqsave(vhost->host->host_lock, flags); ibmvfc_free_event(evt); spin_unlock_irqrestore(vhost->host->host_lock, flags); - job->reply->result = rc; + bsg_reply->result = rc; job->job_done(job); rc = 0; out: diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2d3133f62463..2de6093b3c04 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1902,13 +1902,14 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, { struct fc_bsg_info *info = info_arg; struct fc_bsg_job *job = info->job; + struct fc_bsg_reply *bsg_reply = job->reply; struct fc_lport *lport = info->lport; struct fc_frame_header *fh; size_t len; void *buf; if (IS_ERR(fp)) { - job->reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? + bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); job->state_flags |= FC_RQST_STATE_DONE; @@ -1929,23 +1930,23 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, (unsigned short)fc_frame_payload_op(fp); /* Save the reply status of the job */ - job->reply->reply_data.ctels_reply.status = + bsg_reply->reply_data.ctels_reply.status = (cmd == info->rsp_code) ? FC_CTELS_STATUS_OK : FC_CTELS_STATUS_REJECT; } - job->reply->reply_payload_rcv_len += + bsg_reply->reply_payload_rcv_len += fc_copy_buffer_to_sglist(buf, len, info->sg, &info->nents, &info->offset, NULL); if (fr_eof(fp) == FC_EOF_T && (ntoh24(fh->fh_f_ctl) & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { - if (job->reply->reply_payload_rcv_len > + if (bsg_reply->reply_payload_rcv_len > job->reply_payload.payload_len) - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; - job->reply->result = 0; + bsg_reply->result = 0; job->state_flags |= FC_RQST_STATE_DONE; job->job_done(job); kfree(info); @@ -2082,6 +2083,8 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, */ int fc_lport_bsg_request(struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct request *rsp = job->req->next_rq; struct Scsi_Host *shost = job->shost; struct fc_lport *lport = shost_priv(shost); @@ -2090,13 +2093,13 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) int rc = -EINVAL; u32 did, tov; - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (rsp) rsp->resid_len = job->reply_payload.payload_len; mutex_lock(&lport->lp_mutex); - switch (job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: rport = job->rport; if (!rport) @@ -2118,7 +2121,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; case FC_BSG_HST_CT: - did = ntoh24(job->request->rqst_data.h_ct.port_id); + did = ntoh24(bsg_request->rqst_data.h_ct.port_id); if (did == FC_FID_DIR_SERV) { rdata = lport->dns_rdata; if (!rdata) @@ -2136,7 +2139,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; case FC_BSG_HST_ELS_NOLOGIN: - did = ntoh24(job->request->rqst_data.h_els.port_id); + did = ntoh24(bsg_request->rqst_data.h_els.port_id); rc = fc_lport_els_request(job, lport, did, lport->e_d_tov); break; } diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 0148ee3ef70b..f09a32501f69 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -299,6 +299,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, { struct bsg_job_data *dd_data; struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp, *rmp; struct lpfc_nodelist *ndlp; @@ -313,6 +314,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, spin_lock_irqsave(&phba->ct_ev_lock, flags); job = dd_data->set_job; if (job) { + bsg_reply = job->reply; /* Prevent timeout handling from trying to abort job */ job->dd_data = NULL; } @@ -351,7 +353,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, } } else { rsp_size = rsp->un.genreq64.bdl.bdeSize; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = lpfc_bsg_copy_data(rmp, &job->reply_payload, rsp_size, 0); } @@ -368,7 +370,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, /* Complete the job if the job is still active */ if (job) { - job->reply->result = rc; + bsg_reply->result = rc; job->job_done(job); } return; @@ -385,6 +387,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) struct lpfc_hba *phba = vport->phba; struct lpfc_rport_data *rdata = job->rport->dd_data; struct lpfc_nodelist *ndlp = rdata->pnode; + struct fc_bsg_reply *bsg_reply = job->reply; struct ulp_bde64 *bpl = NULL; uint32_t timeout; struct lpfc_iocbq *cmdiocbq = NULL; @@ -399,7 +402,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) int iocb_stat; /* in case no data is transferred */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; /* allocate our bsg tracking structure */ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); @@ -543,7 +546,7 @@ no_ndlp: kfree(dd_data); no_dd_data: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; job->dd_data = NULL; return rc; } @@ -572,6 +575,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, { struct bsg_job_data *dd_data; struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_nodelist *ndlp; struct lpfc_dmabuf *pcmd = NULL, *prsp = NULL; @@ -589,6 +593,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, spin_lock_irqsave(&phba->ct_ev_lock, flags); job = dd_data->set_job; if (job) { + bsg_reply = job->reply; /* Prevent timeout handling from trying to abort job */ job->dd_data = NULL; } @@ -610,17 +615,17 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, if (job) { if (rsp->ulpStatus == IOSTAT_SUCCESS) { rsp_size = rsp->un.elsreq64.bdl.bdeSize; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, prsp->virt, rsp_size); } else if (rsp->ulpStatus == IOSTAT_LS_RJT) { - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sizeof(struct fc_bsg_ctels_reply); /* LS_RJT data returned in word 4 */ rjt_data = (uint8_t *)&rsp->un.ulpWord[4]; - els_reply = &job->reply->reply_data.ctels_reply; + els_reply = &bsg_reply->reply_data.ctels_reply; els_reply->status = FC_CTELS_STATUS_REJECT; els_reply->rjt_data.action = rjt_data[3]; els_reply->rjt_data.reason_code = rjt_data[2]; @@ -638,7 +643,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, /* Complete the job if the job is still active */ if (job) { - job->reply->result = rc; + bsg_reply->result = rc; job->job_done(job); } return; @@ -655,6 +660,8 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) struct lpfc_hba *phba = vport->phba; struct lpfc_rport_data *rdata = job->rport->dd_data; struct lpfc_nodelist *ndlp = rdata->pnode; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; uint32_t elscmd; uint32_t cmdsize; struct lpfc_iocbq *cmdiocbq; @@ -665,7 +672,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) int rc = 0; /* in case no data is transferred */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; /* verify the els command is not greater than the * maximum ELS transfer size. @@ -685,7 +692,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) goto no_dd_data; } - elscmd = job->request->rqst_data.r_els.els_code; + elscmd = bsg_request->rqst_data.r_els.els_code; cmdsize = job->request_payload.payload_len; if (!lpfc_nlp_get(ndlp)) { @@ -772,7 +779,7 @@ free_dd_data: no_dd_data: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; job->dd_data = NULL; return rc; } @@ -919,6 +926,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_hbq_entry *hbqe; struct lpfc_sli_ct_request *ct_req; struct fc_bsg_job *job = NULL; + struct fc_bsg_reply *bsg_reply; struct bsg_job_data *dd_data = NULL; unsigned long flags; int size = 0; @@ -1121,9 +1129,10 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, dd_data->set_job = NULL; lpfc_bsg_event_unref(evt); if (job) { - job->reply->reply_payload_rcv_len = size; + bsg_reply = job->reply; + bsg_reply->reply_payload_rcv_len = size; /* make error code available to userspace */ - job->reply->result = 0; + bsg_reply->result = 0; job->dd_data = NULL; /* complete the job back to userspace */ spin_unlock_irqrestore(&phba->ct_ev_lock, flags); @@ -1192,6 +1201,7 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; struct lpfc_hba *phba = vport->phba; + struct fc_bsg_request *bsg_request = job->request; struct set_ct_event *event_req; struct lpfc_bsg_event *evt; int rc = 0; @@ -1209,7 +1219,7 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job) } event_req = (struct set_ct_event *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; ev_mask = ((uint32_t)(unsigned long)event_req->type_mask & FC_REG_EVENT_MASK); spin_lock_irqsave(&phba->ct_ev_lock, flags); @@ -1276,6 +1286,8 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; struct lpfc_hba *phba = vport->phba; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct get_ct_event *event_req; struct get_ct_event_reply *event_reply; struct lpfc_bsg_event *evt, *evt_next; @@ -1293,10 +1305,10 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) } event_req = (struct get_ct_event *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; event_reply = (struct get_ct_event_reply *) - job->reply->reply_data.vendor_reply.vendor_rsp; + bsg_reply->reply_data.vendor_reply.vendor_rsp; spin_lock_irqsave(&phba->ct_ev_lock, flags); list_for_each_entry_safe(evt, evt_next, &phba->ct_ev_waiters, node) { if (evt->reg_id == event_req->ev_reg_id) { @@ -1316,7 +1328,7 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) * an error indicating that there isn't anymore */ if (evt_dat == NULL) { - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; rc = -ENOENT; goto job_error; } @@ -1332,12 +1344,12 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) event_reply->type = evt_dat->type; event_reply->immed_data = evt_dat->immed_dat; if (evt_dat->len > 0) - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, evt_dat->data, evt_dat->len); else - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (evt_dat) { kfree(evt_dat->data); @@ -1348,13 +1360,13 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) lpfc_bsg_event_unref(evt); spin_unlock_irqrestore(&phba->ct_ev_lock, flags); job->dd_data = NULL; - job->reply->result = 0; + bsg_reply->result = 0; job->job_done(job); return 0; job_error: job->dd_data = NULL; - job->reply->result = rc; + bsg_reply->result = rc; return rc; } @@ -1382,6 +1394,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, { struct bsg_job_data *dd_data; struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp; struct lpfc_nodelist *ndlp; @@ -1412,6 +1425,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, /* Copy the completed job data or set the error status */ if (job) { + bsg_reply = job->reply; if (rsp->ulpStatus) { if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) { switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) { @@ -1429,7 +1443,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, rc = -EACCES; } } else { - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; } } @@ -1443,7 +1457,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, /* Complete the job if the job is still active */ if (job) { - job->reply->result = rc; + bsg_reply->result = rc; job->job_done(job); } return; @@ -1608,8 +1622,10 @@ lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; struct lpfc_hba *phba = vport->phba; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct send_mgmt_resp *mgmt_resp = (struct send_mgmt_resp *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; struct ulp_bde64 *bpl; struct lpfc_dmabuf *bmp = NULL, *cmp = NULL; int bpl_entries; @@ -1619,7 +1635,7 @@ lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job) int rc = 0; /* in case no data is transferred */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (!reqbfrcnt || (reqbfrcnt > (80 * BUF_SZ_4K))) { rc = -ERANGE; @@ -1665,7 +1681,7 @@ send_mgmt_rsp_free_bmp: kfree(bmp); send_mgmt_rsp_exit: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; job->dd_data = NULL; return rc; } @@ -1763,6 +1779,8 @@ lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba) static int lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct diag_mode_set *loopback_mode; uint32_t link_flags; uint32_t timeout; @@ -1772,7 +1790,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) int rc = 0; /* no data to return just the return code */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (job->request_len < sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_set)) { @@ -1792,7 +1810,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) /* bring the link to diagnostic mode */ loopback_mode = (struct diag_mode_set *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; link_flags = loopback_mode->type; timeout = loopback_mode->timeout * 100; @@ -1865,7 +1883,7 @@ loopback_mode_exit: job_error: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) job->job_done(job); @@ -2018,12 +2036,14 @@ lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba) static int lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct diag_mode_set *loopback_mode; uint32_t link_flags, timeout; int i, rc = 0; /* no data to return just the return code */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (job->request_len < sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_set)) { @@ -2055,7 +2075,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, "3129 Bring link to diagnostic state.\n"); loopback_mode = (struct diag_mode_set *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; link_flags = loopback_mode->type; timeout = loopback_mode->timeout * 100; @@ -2152,7 +2172,7 @@ loopback_mode_exit: job_error: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) job->job_done(job); @@ -2205,6 +2225,8 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) static int lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct Scsi_Host *shost; struct lpfc_vport *vport; struct lpfc_hba *phba; @@ -2233,7 +2255,7 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) phba->link_flag &= ~LS_LOOPBACK_MODE; spin_unlock_irq(&phba->hbalock); loopback_mode_end_cmd = (struct diag_mode_set *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; timeout = loopback_mode_end_cmd->timeout * 100; rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); @@ -2264,7 +2286,7 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) loopback_mode_end_exit: /* make return code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) job->job_done(job); @@ -2281,6 +2303,8 @@ loopback_mode_end_exit: static int lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct Scsi_Host *shost; struct lpfc_vport *vport; struct lpfc_hba *phba; @@ -2336,7 +2360,7 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) goto job_error; link_diag_test_cmd = (struct sli4_link_diag *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); @@ -2386,7 +2410,7 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) } diag_status_reply = (struct diag_status *) - job->reply->reply_data.vendor_reply.vendor_rsp; + bsg_reply->reply_data.vendor_reply.vendor_rsp; if (job->reply_len < sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) { @@ -2414,7 +2438,7 @@ link_diag_test_exit: job_error: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) job->job_done(job); @@ -2986,6 +3010,7 @@ static int lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; struct lpfc_bsg_event *evt; struct event_data *evdat; @@ -3013,7 +3038,7 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) uint32_t total_mem; /* in case no data is returned return just the return code */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (job->request_len < sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_test)) { @@ -3238,11 +3263,11 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) rc = IOCB_SUCCESS; /* skip over elx loopback header */ rx_databuf += ELX_LOOPBACK_HEADER_SZ; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, rx_databuf, size); - job->reply->reply_payload_rcv_len = size; + bsg_reply->reply_payload_rcv_len = size; } } @@ -3272,7 +3297,7 @@ err_loopback_test_exit: loopback_test_exit: kfree(dataout); /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; job->dd_data = NULL; /* complete the job back to userspace if no error */ if (rc == IOCB_SUCCESS) @@ -3288,6 +3313,7 @@ static int lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; struct get_mgmt_rev_reply *event_reply; int rc = 0; @@ -3302,7 +3328,7 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job) } event_reply = (struct get_mgmt_rev_reply *) - job->reply->reply_data.vendor_reply.vendor_rsp; + bsg_reply->reply_data.vendor_reply.vendor_rsp; if (job->reply_len < sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev_reply)) { @@ -3316,7 +3342,7 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job) event_reply->info.a_Major = MANAGEMENT_MAJOR_REV; event_reply->info.a_Minor = MANAGEMENT_MINOR_REV; job_error: - job->reply->result = rc; + bsg_reply->result = rc; if (rc == 0) job->job_done(job); return rc; @@ -3337,6 +3363,7 @@ static void lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { struct bsg_job_data *dd_data; + struct fc_bsg_reply *bsg_reply; struct fc_bsg_job *job; uint32_t size; unsigned long flags; @@ -3365,8 +3392,9 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /* Copy the mailbox data to the job if it is still active */ if (job) { + bsg_reply = job->reply; size = job->reply_payload.payload_len; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, pmb_buf, size); @@ -3380,7 +3408,7 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /* Complete the job if the job is still active */ if (job) { - job->reply->result = 0; + bsg_reply->result = 0; job->job_done(job); } return; @@ -3516,6 +3544,7 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { struct bsg_job_data *dd_data; struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; uint8_t *pmb, *pmb_buf; unsigned long flags; uint32_t size; @@ -3530,6 +3559,7 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) spin_lock_irqsave(&phba->ct_ev_lock, flags); job = dd_data->set_job; if (job) { + bsg_reply = job->reply; /* Prevent timeout handling from trying to abort job */ job->dd_data = NULL; } @@ -3560,13 +3590,13 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) if (job) { size = job->reply_payload.payload_len; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, pmb_buf, size); /* result for successful */ - job->reply->result = 0; + bsg_reply->result = 0; lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, "2937 SLI_CONFIG ext-buffer maibox command " @@ -3773,6 +3803,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, enum nemb_type nemb_tp, struct lpfc_dmabuf *dmabuf) { + struct fc_bsg_request *bsg_request = job->request; struct lpfc_sli_config_mbox *sli_cfg_mbx; struct dfc_mbox_req *mbox_req; struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf; @@ -3785,7 +3816,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, int rc, i; mbox_req = - (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; + (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd; /* pointer to the start of mailbox command */ sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; @@ -3960,6 +3991,8 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, enum nemb_type nemb_tp, struct lpfc_dmabuf *dmabuf) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct dfc_mbox_req *mbox_req; struct lpfc_sli_config_mbox *sli_cfg_mbx; uint32_t ext_buf_cnt; @@ -3970,7 +4003,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, int rc = SLI_CONFIG_NOT_HANDLED, i; mbox_req = - (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; + (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd; /* pointer to the start of mailbox command */ sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; @@ -4097,7 +4130,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, /* wait for additoinal external buffers */ - job->reply->result = 0; + bsg_reply->result = 0; job->job_done(job); return SLI_CONFIG_HANDLED; @@ -4271,6 +4304,7 @@ lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba) static int lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) { + struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_sli_config_mbox *sli_cfg_mbx; struct lpfc_dmabuf *dmabuf; uint8_t *pbuf; @@ -4308,7 +4342,7 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) dmabuf, index); pbuf = (uint8_t *)dmabuf->virt; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, pbuf, size); @@ -4322,7 +4356,7 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) lpfc_bsg_mbox_ext_session_reset(phba); } - job->reply->result = 0; + bsg_reply->result = 0; job->job_done(job); return SLI_CONFIG_HANDLED; @@ -4340,6 +4374,7 @@ static int lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, struct lpfc_dmabuf *dmabuf) { + struct fc_bsg_reply *bsg_reply = job->reply; struct bsg_job_data *dd_data = NULL; LPFC_MBOXQ_t *pmboxq = NULL; MAILBOX_t *pmb; @@ -4437,7 +4472,7 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, } /* wait for additoinal external buffers */ - job->reply->result = 0; + bsg_reply->result = 0; job->job_done(job); return SLI_CONFIG_HANDLED; @@ -4506,11 +4541,12 @@ static int lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, struct lpfc_dmabuf *dmabuf) { + struct fc_bsg_request *bsg_request = job->request; struct dfc_mbox_req *mbox_req; int rc = SLI_CONFIG_NOT_HANDLED; mbox_req = - (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; + (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd; /* mbox command with/without single external buffer */ if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0) @@ -4583,6 +4619,8 @@ static int lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, struct lpfc_vport *vport) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */ MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */ /* a 4k buffer to hold the mb and extended data from/to the bsg */ @@ -4601,7 +4639,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t size; /* in case no data is transferred */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; /* sanity check to protect driver */ if (job->reply_payload.payload_len > BSG_MBOX_SIZE || @@ -4620,7 +4658,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, } mbox_req = - (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; + (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd; /* check if requested extended data lengths are valid */ if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || @@ -4842,7 +4880,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, /* job finished, copy the data */ memcpy(pmbx, pmb, sizeof(*pmb)); - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(job->reply_payload.sg_list, job->reply_payload.sg_cnt, pmbx, size); @@ -4874,12 +4912,14 @@ static int lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; struct dfc_mbox_req *mbox_req; int rc = 0; /* mix-and-match backward compatibility */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (job->request_len < sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) { lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, @@ -4890,7 +4930,7 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) sizeof(struct fc_bsg_request)), (int)sizeof(struct dfc_mbox_req)); mbox_req = (struct dfc_mbox_req *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; mbox_req->extMboxTag = 0; mbox_req->extSeqNum = 0; } @@ -4899,7 +4939,7 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) if (rc == 0) { /* job done */ - job->reply->result = 0; + bsg_reply->result = 0; job->dd_data = NULL; job->job_done(job); } else if (rc == 1) @@ -4907,7 +4947,7 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) rc = 0; /* return zero, no error */ else { /* some error occurred */ - job->reply->result = rc; + bsg_reply->result = rc; job->dd_data = NULL; } @@ -4938,6 +4978,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, { struct bsg_job_data *dd_data; struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp, *rmp; struct lpfc_bsg_menlo *menlo; @@ -4957,6 +4998,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, spin_lock_irqsave(&phba->ct_ev_lock, flags); job = dd_data->set_job; if (job) { + bsg_reply = job->reply; /* Prevent timeout handling from trying to abort job */ job->dd_data = NULL; } @@ -4971,7 +5013,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, */ menlo_resp = (struct menlo_response *) - job->reply->reply_data.vendor_reply.vendor_rsp; + bsg_reply->reply_data.vendor_reply.vendor_rsp; menlo_resp->xri = rsp->ulpContext; if (rsp->ulpStatus) { if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) { @@ -4991,7 +5033,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, } } else { rsp_size = rsp->un.genreq64.bdl.bdeSize; - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = lpfc_bsg_copy_data(rmp, &job->reply_payload, rsp_size, 0); } @@ -5008,7 +5050,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, /* Complete the job if active */ if (job) { - job->reply->result = rc; + bsg_reply->result = rc; job->job_done(job); } @@ -5028,6 +5070,8 @@ static int lpfc_menlo_cmd(struct fc_bsg_job *job) { struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocbq; IOCB_t *cmd; @@ -5040,7 +5084,7 @@ lpfc_menlo_cmd(struct fc_bsg_job *job) struct ulp_bde64 *bpl = NULL; /* in case no data is returned return just the return code */ - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (job->request_len < sizeof(struct fc_bsg_request) + @@ -5070,7 +5114,7 @@ lpfc_menlo_cmd(struct fc_bsg_job *job) } menlo_cmd = (struct menlo_command *) - job->request->rqst_data.h_vendor.vendor_cmd; + bsg_request->rqst_data.h_vendor.vendor_cmd; /* allocate our bsg tracking structure */ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); @@ -5181,7 +5225,7 @@ free_dd: kfree(dd_data); no_dd_data: /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; job->dd_data = NULL; return rc; } @@ -5192,6 +5236,7 @@ lpfc_forced_link_speed(struct fc_bsg_job *job) struct Scsi_Host *shost = job->shost; struct lpfc_vport *vport = shost_priv(shost); struct lpfc_hba *phba = vport->phba; + struct fc_bsg_reply *bsg_reply = job->reply; struct forced_link_speed_support_reply *forced_reply; int rc = 0; @@ -5206,7 +5251,7 @@ lpfc_forced_link_speed(struct fc_bsg_job *job) } forced_reply = (struct forced_link_speed_support_reply *) - job->reply->reply_data.vendor_reply.vendor_rsp; + bsg_reply->reply_data.vendor_reply.vendor_rsp; if (job->reply_len < sizeof(struct fc_bsg_request) + @@ -5222,7 +5267,7 @@ lpfc_forced_link_speed(struct fc_bsg_job *job) ? LPFC_FORCED_LINK_SPEED_SUPPORTED : LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED; job_error: - job->reply->result = rc; + bsg_reply->result = rc; if (rc == 0) job->job_done(job); return rc; @@ -5235,7 +5280,9 @@ job_error: static int lpfc_bsg_hst_vendor(struct fc_bsg_job *job) { - int command = job->request->rqst_data.h_vendor.vendor_cmd[0]; + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; + int command = bsg_request->rqst_data.h_vendor.vendor_cmd[0]; int rc; switch (command) { @@ -5275,9 +5322,9 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) break; default: rc = -EINVAL; - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; break; } @@ -5291,10 +5338,12 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) int lpfc_bsg_request(struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; uint32_t msgcode; int rc; - msgcode = job->request->msgcode; + msgcode = bsg_request->msgcode; switch (msgcode) { case FC_BSG_HST_VENDOR: rc = lpfc_bsg_hst_vendor(job); @@ -5307,9 +5356,9 @@ lpfc_bsg_request(struct fc_bsg_job *job) break; default: rc = -EINVAL; - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; /* make error code available to userspace */ - job->reply->result = rc; + bsg_reply->result = rc; break; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 643014f82f7d..40f7c1081e8d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -17,8 +17,9 @@ qla2x00_bsg_job_done(void *data, void *ptr, int res) srb_t *sp = (srb_t *)ptr; struct scsi_qla_host *vha = (scsi_qla_host_t *)data; struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; - bsg_job->reply->result = res; + bsg_reply->result = res; bsg_job->job_done(bsg_job); sp->free(vha, sp); } @@ -29,12 +30,14 @@ qla2x00_bsg_sp_free(void *data, void *ptr) srb_t *sp = (srb_t *)ptr; struct scsi_qla_host *vha = sp->fcport->vha; struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct fc_bsg_request *bsg_request = bsg_job->request; + struct qla_hw_data *ha = vha->hw; struct qla_mt_iocb_rqst_fx00 *piocb_rqst; if (sp->type == SRB_FXIOCB_BCMD) { piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *) - &bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + &bsg_request->rqst_data.h_vendor.vendor_cmd[1]; if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) dma_unmap_sg(&ha->pdev->dev, @@ -119,6 +122,8 @@ static int qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) { struct Scsi_Host *host = bsg_job->shost; + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int ret = 0; @@ -131,7 +136,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) } /* Get the sub command */ - oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + oper = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; /* Only set config is allowed if config memory is not allocated */ if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) { @@ -145,10 +150,10 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) ha->fcp_prio_cfg->attributes &= ~FCP_PRIO_ATTR_ENABLE; qla24xx_update_all_fcp_prio(vha); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; } else { ret = -EINVAL; - bsg_job->reply->result = (DID_ERROR << 16); + bsg_reply->result = (DID_ERROR << 16); goto exit_fcp_prio_cfg; } break; @@ -160,10 +165,10 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) ha->fcp_prio_cfg->attributes |= FCP_PRIO_ATTR_ENABLE; qla24xx_update_all_fcp_prio(vha); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; } else { ret = -EINVAL; - bsg_job->reply->result = (DID_ERROR << 16); + bsg_reply->result = (DID_ERROR << 16); goto exit_fcp_prio_cfg; } } @@ -173,12 +178,12 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) len = bsg_job->reply_payload.payload_len; if (!len || len > FCP_PRIO_CFG_SIZE) { ret = -EINVAL; - bsg_job->reply->result = (DID_ERROR << 16); + bsg_reply->result = (DID_ERROR << 16); goto exit_fcp_prio_cfg; } - bsg_job->reply->result = DID_OK; - bsg_job->reply->reply_payload_rcv_len = + bsg_reply->result = DID_OK; + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer( bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg, @@ -189,7 +194,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) case QLFC_FCP_PRIO_SET_CONFIG: len = bsg_job->request_payload.payload_len; if (!len || len > FCP_PRIO_CFG_SIZE) { - bsg_job->reply->result = (DID_ERROR << 16); + bsg_reply->result = (DID_ERROR << 16); ret = -EINVAL; goto exit_fcp_prio_cfg; } @@ -200,7 +205,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) ql_log(ql_log_warn, vha, 0x7050, "Unable to allocate memory for fcp prio " "config data (%x).\n", FCP_PRIO_CFG_SIZE); - bsg_job->reply->result = (DID_ERROR << 16); + bsg_reply->result = (DID_ERROR << 16); ret = -ENOMEM; goto exit_fcp_prio_cfg; } @@ -215,7 +220,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) if (!qla24xx_fcp_prio_cfg_valid(vha, (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) { - bsg_job->reply->result = (DID_ERROR << 16); + bsg_reply->result = (DID_ERROR << 16); ret = -EINVAL; /* If buffer was invalidatic int * fcp_prio_cfg is of no use @@ -229,7 +234,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE) ha->flags.fcp_prio_enabled = 1; qla24xx_update_all_fcp_prio(vha); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; break; default: ret = -EINVAL; @@ -244,6 +249,7 @@ exit_fcp_prio_cfg: static int qla2x00_process_els(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_rport *rport; fc_port_t *fcport = NULL; struct Scsi_Host *host; @@ -255,7 +261,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) int rval = (DRIVER_ERROR << 16); uint16_t nextlid = 0; - if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { + if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = bsg_job->rport; fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); @@ -296,7 +302,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) } /* ELS request for rport */ - if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { + if (bsg_request->msgcode == FC_BSG_RPT_ELS) { /* make sure the rport is logged in, * if not perform fabric login */ @@ -322,11 +328,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) /* Initialize all required fields of fcport */ fcport->vha = vha; fcport->d_id.b.al_pa = - bsg_job->request->rqst_data.h_els.port_id[0]; + bsg_request->rqst_data.h_els.port_id[0]; fcport->d_id.b.area = - bsg_job->request->rqst_data.h_els.port_id[1]; + bsg_request->rqst_data.h_els.port_id[1]; fcport->d_id.b.domain = - bsg_job->request->rqst_data.h_els.port_id[2]; + bsg_request->rqst_data.h_els.port_id[2]; fcport->loop_id = (fcport->d_id.b.al_pa == 0xFD) ? NPH_FABRIC_CONTROLLER : NPH_F_PORT; @@ -366,11 +372,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) } sp->type = - (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? - SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); + (bsg_request->msgcode == FC_BSG_RPT_ELS ? + SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); sp->name = - (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? - "bsg_els_rpt" : "bsg_els_hst"); + (bsg_request->msgcode == FC_BSG_RPT_ELS ? + "bsg_els_rpt" : "bsg_els_hst"); sp->u.bsg_job = bsg_job; sp->free = qla2x00_bsg_sp_free; sp->done = qla2x00_bsg_job_done; @@ -378,7 +384,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) ql_dbg(ql_dbg_user, vha, 0x700a, "bsg rqst type: %s els type: %x - loop-id=%x " "portid=%-2x%02x%02x.\n", type, - bsg_job->request->rqst_data.h_els.command_code, fcport->loop_id, + bsg_request->rqst_data.h_els.command_code, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); rval = qla2x00_start_sp(sp); @@ -399,7 +405,7 @@ done_unmap_sg: goto done_free_fcport; done_free_fcport: - if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) + if (bsg_request->msgcode == FC_BSG_RPT_ELS) kfree(fcport); done: return rval; @@ -423,6 +429,7 @@ static int qla2x00_process_ct(struct fc_bsg_job *bsg_job) { srb_t *sp; + struct fc_bsg_request *bsg_request = bsg_job->request; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -469,7 +476,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) } loop_id = - (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) + (bsg_request->rqst_data.h_ct.preamble_word1 & 0xFF000000) >> 24; switch (loop_id) { case 0xFC: @@ -500,9 +507,9 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) /* Initialize all required fields of fcport */ fcport->vha = vha; - fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; - fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; - fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; + fcport->d_id.b.al_pa = bsg_request->rqst_data.h_ct.port_id[0]; + fcport->d_id.b.area = bsg_request->rqst_data.h_ct.port_id[1]; + fcport->d_id.b.domain = bsg_request->rqst_data.h_ct.port_id[2]; fcport->loop_id = loop_id; /* Alloc SRB structure */ @@ -524,7 +531,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) ql_dbg(ql_dbg_user, vha, 0x7016, "bsg rqst type: %s else type: %x - " "loop-id=%x portid=%02x%02x%02x.\n", type, - (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16), + (bsg_request->rqst_data.h_ct.preamble_word2 >> 16), fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); @@ -699,6 +706,8 @@ done_set_internal: static int qla2x00_process_loopback(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -780,9 +789,9 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) elreq.rcv_dma = rsp_data_dma; elreq.transfer_size = req_data_len; - elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + elreq.options = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; elreq.iteration_count = - bsg_job->request->rqst_data.h_vendor.vendor_cmd[2]; + bsg_request->rqst_data.h_vendor.vendor_cmd[2]; if (atomic_read(&vha->loop_state) == LOOP_READY && (ha->current_topology == ISP_CFG_F || @@ -896,12 +905,12 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) "Vendor request %s failed.\n", type); rval = 0; - bsg_job->reply->result = (DID_ERROR << 16); - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->result = (DID_ERROR << 16); + bsg_reply->reply_payload_rcv_len = 0; } else { ql_dbg(ql_dbg_user, vha, 0x702d, "Vendor request %s completed.\n", type); - bsg_job->reply->result = (DID_OK << 16); + bsg_reply->result = (DID_OK << 16); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, rsp_data, rsp_data_len); @@ -937,7 +946,9 @@ done_unmap_req_sg: static int qla84xx_reset(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; struct Scsi_Host *host = bsg_job->shost; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -948,7 +959,7 @@ qla84xx_reset(struct fc_bsg_job *bsg_job) return -EINVAL; } - flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW); @@ -960,7 +971,7 @@ qla84xx_reset(struct fc_bsg_job *bsg_job) } else { ql_dbg(ql_dbg_user, vha, 0x7031, "Vendor request 84xx reset completed.\n"); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; bsg_job->job_done(bsg_job); } @@ -970,6 +981,8 @@ qla84xx_reset(struct fc_bsg_job *bsg_job) static int qla84xx_updatefw(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1027,7 +1040,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job) goto done_free_fw_buf; } - flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2))); memset(mn, 0, sizeof(struct access_chip_84xx)); @@ -1059,7 +1072,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job) "Vendor request 84xx updatefw completed.\n"); bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; } dma_pool_free(ha->s_dma_pool, mn, mn_dma); @@ -1079,6 +1092,8 @@ done_unmap_sg: static int qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1107,7 +1122,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) memset(mn, 0, sizeof(struct access_chip_84xx)); mn->entry_type = ACCESS_CHIP_IOCB_TYPE; mn->entry_count = 1; - ql84_mgmt = (void *)bsg_job->request + sizeof(struct fc_bsg_request); + ql84_mgmt = (void *)bsg_request + sizeof(struct fc_bsg_request); switch (ql84_mgmt->mgmt.cmd) { case QLA84_MGMT_READ_MEM: case QLA84_MGMT_GET_INFO: @@ -1239,11 +1254,11 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) "Vendor request 84xx mgmt completed.\n"); bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) || (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) { - bsg_job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; sg_copy_from_buffer(bsg_job->reply_payload.sg_list, @@ -1274,6 +1289,8 @@ exit_mgmt: static int qla24xx_iidma(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); int rval = 0; @@ -1288,7 +1305,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) return -EINVAL; } - port_param = (void *)bsg_job->request + sizeof(struct fc_bsg_request); + port_param = (void *)bsg_request + sizeof(struct fc_bsg_request); if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) { ql_log(ql_log_warn, vha, 0x7048, "Invalid destination type.\n"); @@ -1343,14 +1360,14 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(struct qla_port_param); - rsp_ptr = ((uint8_t *)bsg_job->reply) + + rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct fc_bsg_reply); memcpy(rsp_ptr, port_param, sizeof(struct qla_port_param)); } - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; bsg_job->job_done(bsg_job); } @@ -1361,6 +1378,7 @@ static int qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha, uint8_t is_update) { + struct fc_bsg_request *bsg_request = bsg_job->request; uint32_t start = 0; int valid = 0; struct qla_hw_data *ha = vha->hw; @@ -1368,7 +1386,7 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha, if (unlikely(pci_channel_offline(ha->pdev))) return -EINVAL; - start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + start = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; if (start > ha->optrom_size) { ql_log(ql_log_warn, vha, 0x7055, "start %d > optrom_size %d.\n", start, ha->optrom_size); @@ -1429,6 +1447,7 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha, static int qla2x00_read_optrom(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1451,8 +1470,8 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job) bsg_job->reply_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); - bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size; - bsg_job->reply->result = DID_OK; + bsg_reply->reply_payload_rcv_len = ha->optrom_region_size; + bsg_reply->result = DID_OK; vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; @@ -1464,6 +1483,7 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job) static int qla2x00_update_optrom(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1486,7 +1506,7 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job) ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); - bsg_job->reply->result = DID_OK; + bsg_reply->result = DID_OK; vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; @@ -1498,6 +1518,7 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job) static int qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1509,7 +1530,7 @@ qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job) dma_addr_t sfp_dma; void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); if (!sfp) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; goto done; } @@ -1525,21 +1546,21 @@ qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job) image->field_address.device, image->field_address.offset, sizeof(image->field_info), image->field_address.option); if (rval) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_MAILBOX; goto dealloc; } image++; } - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0; dealloc: dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; @@ -1548,6 +1569,7 @@ done: static int qla2x00_read_fru_status(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1557,7 +1579,7 @@ qla2x00_read_fru_status(struct fc_bsg_job *bsg_job) dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); if (!sfp) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; goto done; } @@ -1571,7 +1593,7 @@ qla2x00_read_fru_status(struct fc_bsg_job *bsg_job) sr->status_reg = *sfp; if (rval) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_MAILBOX; goto dealloc; } @@ -1579,15 +1601,15 @@ qla2x00_read_fru_status(struct fc_bsg_job *bsg_job) sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr)); - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0; dealloc: dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->reply_payload_rcv_len = sizeof(*sr); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->reply_payload_rcv_len = sizeof(*sr); + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; @@ -1596,6 +1618,7 @@ done: static int qla2x00_write_fru_status(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1605,7 +1628,7 @@ qla2x00_write_fru_status(struct fc_bsg_job *bsg_job) dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); if (!sfp) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; goto done; } @@ -1619,19 +1642,19 @@ qla2x00_write_fru_status(struct fc_bsg_job *bsg_job) sizeof(sr->status_reg), sr->field_address.option); if (rval) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_MAILBOX; goto dealloc; } - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0; dealloc: dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; @@ -1640,6 +1663,7 @@ done: static int qla2x00_write_i2c(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1649,7 +1673,7 @@ qla2x00_write_i2c(struct fc_bsg_job *bsg_job) dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); if (!sfp) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; goto done; } @@ -1662,19 +1686,19 @@ qla2x00_write_i2c(struct fc_bsg_job *bsg_job) i2c->device, i2c->offset, i2c->length, i2c->option); if (rval) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_MAILBOX; goto dealloc; } - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0; dealloc: dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; @@ -1683,6 +1707,7 @@ done: static int qla2x00_read_i2c(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1692,7 +1717,7 @@ qla2x00_read_i2c(struct fc_bsg_job *bsg_job) dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); if (!sfp) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; goto done; } @@ -1704,7 +1729,7 @@ qla2x00_read_i2c(struct fc_bsg_job *bsg_job) i2c->device, i2c->offset, i2c->length, i2c->option); if (rval) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_MAILBOX; goto dealloc; } @@ -1713,15 +1738,15 @@ qla2x00_read_i2c(struct fc_bsg_job *bsg_job) sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, i2c, sizeof(*i2c)); - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0; dealloc: dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->reply_payload_rcv_len = sizeof(*i2c); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->reply_payload_rcv_len = sizeof(*i2c); + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; @@ -1730,6 +1755,7 @@ done: static int qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1895,10 +1921,10 @@ done: /* Return an error vendor specific response * and complete the bsg request */ - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = rval; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval; bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->reply_payload_rcv_len = 0; - bsg_job->reply->result = (DID_OK) << 16; + bsg_reply->reply_payload_rcv_len = 0; + bsg_reply->result = (DID_OK) << 16; bsg_job->job_done(bsg_job); /* Always return success, vendor rsp carries correct status */ return 0; @@ -1907,6 +1933,7 @@ done: static int qlafx00_mgmt_cmd(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -1919,7 +1946,7 @@ qlafx00_mgmt_cmd(struct fc_bsg_job *bsg_job) /* Copy the IOCB specific information */ piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *) - &bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + &bsg_request->rqst_data.h_vendor.vendor_cmd[1]; /* Dump the vendor information */ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf, @@ -2029,6 +2056,7 @@ done: static int qla26xx_serdes_op(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); int rval = 0; @@ -2042,13 +2070,13 @@ qla26xx_serdes_op(struct fc_bsg_job *bsg_job) switch (sr.cmd) { case INT_SC_SERDES_WRITE_REG: rval = qla2x00_write_serdes_word(vha, sr.addr, sr.val); - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; break; case INT_SC_SERDES_READ_REG: rval = qla2x00_read_serdes_word(vha, sr.addr, &sr.val); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr)); - bsg_job->reply->reply_payload_rcv_len = sizeof(sr); + bsg_reply->reply_payload_rcv_len = sizeof(sr); break; default: ql_dbg(ql_dbg_user, vha, 0x708c, @@ -2057,11 +2085,11 @@ qla26xx_serdes_op(struct fc_bsg_job *bsg_job) break; } - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval ? EXT_STATUS_MAILBOX : 0; bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; } @@ -2069,6 +2097,7 @@ qla26xx_serdes_op(struct fc_bsg_job *bsg_job) static int qla8044_serdes_op(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); int rval = 0; @@ -2082,13 +2111,13 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job) switch (sr.cmd) { case INT_SC_SERDES_WRITE_REG: rval = qla8044_write_serdes_word(vha, sr.addr, sr.val); - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; break; case INT_SC_SERDES_READ_REG: rval = qla8044_read_serdes_word(vha, sr.addr, &sr.val); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr)); - bsg_job->reply->reply_payload_rcv_len = sizeof(sr); + bsg_reply->reply_payload_rcv_len = sizeof(sr); break; default: ql_dbg(ql_dbg_user, vha, 0x70cf, @@ -2097,11 +2126,11 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job) break; } - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval ? EXT_STATUS_MAILBOX : 0; bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; } @@ -2109,6 +2138,7 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job) static int qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -2125,13 +2155,13 @@ qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap)); - bsg_job->reply->reply_payload_rcv_len = sizeof(cap); + bsg_reply->reply_payload_rcv_len = sizeof(cap); - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; } @@ -2139,6 +2169,7 @@ qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) static int qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -2158,24 +2189,24 @@ qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) (uint64_t)ha->fw_attributes; if (online_fw_attr != cap.capabilities) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_INVALID_PARAM; return -EINVAL; } if (cap.outage_duration < MAX_LOOP_TIMEOUT) { - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_INVALID_PARAM; return -EINVAL; } - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; } @@ -2183,6 +2214,7 @@ qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) static int qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -2227,12 +2259,12 @@ qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job) done: sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, &bbcr, sizeof(bbcr)); - bsg_job->reply->reply_payload_rcv_len = sizeof(bbcr); + bsg_reply->reply_payload_rcv_len = sizeof(bbcr); - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_job->reply->result = DID_OK << 16; + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); return 0; } @@ -2240,6 +2272,8 @@ done: static int qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -2247,7 +2281,7 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) struct link_statistics *stats = NULL; dma_addr_t stats_dma; int rval; - uint32_t *cmd = bsg_job->request->rqst_data.h_vendor.vendor_cmd; + uint32_t *cmd = bsg_request->rqst_data.h_vendor.vendor_cmd; uint options = cmd[0] == QL_VND_GET_PRIV_STATS_EX ? cmd[1] : 0; if (test_bit(UNLOADING, &vha->dpc_flags)) @@ -2281,12 +2315,12 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats)); } - bsg_job->reply->reply_payload_rcv_len = sizeof(*stats); - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_payload_rcv_len = sizeof(*stats); + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK; - bsg_job->reply_len = sizeof(*bsg_job->reply); - bsg_job->reply->result = DID_OK << 16; + bsg_job->reply_len = sizeof(*bsg_reply); + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); dma_free_coherent(&ha->pdev->dev, sizeof(*stats), @@ -2298,6 +2332,7 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) static int qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); int rval; @@ -2323,12 +2358,12 @@ qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd)); } - bsg_job->reply->reply_payload_rcv_len = sizeof(*dd); - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + bsg_reply->reply_payload_rcv_len = sizeof(*dd); + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK; - bsg_job->reply_len = sizeof(*bsg_job->reply); - bsg_job->reply->result = DID_OK << 16; + bsg_job->reply_len = sizeof(*bsg_reply); + bsg_reply->result = DID_OK << 16; bsg_job->job_done(bsg_job); kfree(dd); @@ -2339,7 +2374,9 @@ qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) static int qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) { - switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { + struct fc_bsg_request *bsg_request = bsg_job->request; + + switch (bsg_request->rqst_data.h_vendor.vendor_cmd[0]) { case QL_VND_LOOPBACK: return qla2x00_process_loopback(bsg_job); @@ -2415,15 +2452,17 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) int qla24xx_bsg_request(struct fc_bsg_job *bsg_job) { + struct fc_bsg_request *bsg_request = bsg_job->request; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; int ret = -EINVAL; struct fc_rport *rport; struct Scsi_Host *host; scsi_qla_host_t *vha; /* In case no data transferred. */ - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; - if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { + if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = bsg_job->rport; host = rport_to_shost(rport); vha = shost_priv(host); @@ -2435,14 +2474,14 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) if (qla2x00_reset_active(vha)) { ql_dbg(ql_dbg_user, vha, 0x709f, "BSG: ISP abort active/needed -- cmd=%d.\n", - bsg_job->request->msgcode); + bsg_request->msgcode); return -EBUSY; } ql_dbg(ql_dbg_user, vha, 0x7000, - "Entered %s msgcode=0x%x.\n", __func__, bsg_job->request->msgcode); + "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode); - switch (bsg_job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: case FC_BSG_HST_ELS_NOLOGIN: ret = qla2x00_process_els(bsg_job); @@ -2466,6 +2505,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) int qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) { + struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(bsg_job->shost); struct qla_hw_data *ha = vha->hw; srb_t *sp; @@ -2494,13 +2534,13 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) "mbx abort_command " "failed.\n"); bsg_job->req->errors = - bsg_job->reply->result = -EIO; + bsg_reply->result = -EIO; } else { ql_dbg(ql_dbg_user, vha, 0x708a, "mbx abort_command " "success.\n"); bsg_job->req->errors = - bsg_job->reply->result = 0; + bsg_reply->result = 0; } spin_lock_irqsave(&ha->hardware_lock, flags); goto done; @@ -2510,7 +2550,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) } spin_unlock_irqrestore(&ha->hardware_lock, flags); ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n"); - bsg_job->req->errors = bsg_job->reply->result = -ENXIO; + bsg_job->req->errors = bsg_reply->result = -ENXIO; return 0; done: diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index b41265a75ed5..6929fda544a0 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2198,6 +2198,7 @@ static void qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct fc_bsg_request *bsg_request = bsg_job->request; els_iocb->entry_type = ELS_IOCB_TYPE; els_iocb->entry_count = 1; @@ -2212,8 +2213,8 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->opcode = sp->type == SRB_ELS_CMD_RPT ? - bsg_job->request->rqst_data.r_els.els_code : - bsg_job->request->rqst_data.h_els.command_code; + bsg_request->rqst_data.r_els.els_code : + bsg_request->rqst_data.h_els.command_code; els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; els_iocb->port_id[1] = sp->fcport->d_id.b.area; els_iocb->port_id[2] = sp->fcport->d_id.b.domain; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 068c4e47fac9..d83e08312af2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1357,6 +1357,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, const char *type; srb_t *sp; struct fc_bsg_job *bsg_job; + struct fc_bsg_reply *bsg_reply; uint16_t comp_status; int res; @@ -1365,6 +1366,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, return; bsg_job = sp->u.bsg_job; + bsg_reply = bsg_job->reply; type = "ct pass-through"; @@ -1373,32 +1375,32 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT * fc payload to the caller */ - bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; + bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; bsg_job->reply_len = sizeof(struct fc_bsg_reply); if (comp_status != CS_COMPLETE) { if (comp_status == CS_DATA_UNDERRUN) { res = DID_OK << 16; - bsg_job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len); ql_log(ql_log_warn, vha, 0x5048, "CT pass-through-%s error " "comp_status-status=0x%x total_byte = 0x%x.\n", type, comp_status, - bsg_job->reply->reply_payload_rcv_len); + bsg_reply->reply_payload_rcv_len); } else { ql_log(ql_log_warn, vha, 0x5049, "CT pass-through-%s error " "comp_status-status=0x%x.\n", type, comp_status); res = DID_ERROR << 16; - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; } ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035, (uint8_t *)pkt, sizeof(*pkt)); } else { res = DID_OK << 16; - bsg_job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; bsg_job->reply_len = 0; } @@ -1414,6 +1416,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, const char *type; srb_t *sp; struct fc_bsg_job *bsg_job; + struct fc_bsg_reply *bsg_reply; uint16_t comp_status; uint32_t fw_status[3]; uint8_t* fw_sts_ptr; @@ -1423,6 +1426,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, if (!sp) return; bsg_job = sp->u.bsg_job; + bsg_reply = bsg_job->reply; type = NULL; switch (sp->type) { @@ -1452,13 +1456,13 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT * fc payload to the caller */ - bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; + bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status); if (comp_status != CS_COMPLETE) { if (comp_status == CS_DATA_UNDERRUN) { res = DID_OK << 16; - bsg_job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->total_byte_count); ql_dbg(ql_dbg_user, vha, 0x503f, @@ -1480,7 +1484,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, le16_to_cpu(((struct els_sts_entry_24xx *) pkt)->error_subcode_2)); res = DID_ERROR << 16; - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); } @@ -1489,7 +1493,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, } else { res = DID_OK << 16; - bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; + bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; bsg_job->reply_len = 0; } @@ -1905,6 +1909,8 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, uint16_t thread_id; uint32_t rval = EXT_STATUS_OK; struct fc_bsg_job *bsg_job = NULL; + struct fc_bsg_request *bsg_request; + struct fc_bsg_reply *bsg_reply; sts_entry_t *sts; struct sts_entry_24xx *sts24; sts = (sts_entry_t *) pkt; @@ -1919,11 +1925,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, } sp = req->outstanding_cmds[index]; - if (sp) { - /* Free outstanding command slot. */ - req->outstanding_cmds[index] = NULL; - bsg_job = sp->u.bsg_job; - } else { + if (!sp) { ql_log(ql_log_warn, vha, 0x70b0, "Req:%d: Invalid ISP SCSI completion handle(0x%x)\n", req->id, index); @@ -1932,6 +1934,12 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, return; } + /* Free outstanding command slot. */ + req->outstanding_cmds[index] = NULL; + bsg_job = sp->u.bsg_job; + bsg_request = bsg_job->request; + bsg_reply = bsg_job->reply; + if (IS_FWI2_CAPABLE(ha)) { comp_status = le16_to_cpu(sts24->comp_status); scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; @@ -1940,14 +1948,14 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; } - thread_id = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + thread_id = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; switch (comp_status) { case CS_COMPLETE: if (scsi_status == 0) { - bsg_job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; vha->qla_stats.input_bytes += - bsg_job->reply->reply_payload_rcv_len; + bsg_reply->reply_payload_rcv_len; vha->qla_stats.input_requests++; rval = EXT_STATUS_OK; } @@ -2028,11 +2036,11 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, rval = EXT_STATUS_ERR; break; } - bsg_job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; done: /* Return the vendor specific reply to API */ - bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = rval; + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval; bsg_job->reply_len = sizeof(struct fc_bsg_reply); /* Always return DID_OK, bsg will send the vendor specific response * in this case only */ diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 15dff7099955..b597d04f654e 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -2207,6 +2207,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, const char func[] = "IOSB_IOCB"; srb_t *sp; struct fc_bsg_job *bsg_job; + struct fc_bsg_reply *bsg_reply; struct srb_iocb *iocb_job; int res; struct qla_mt_iocb_rsp_fx00 fstatus; @@ -2226,6 +2227,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, pkt->dataword_r; } else { bsg_job = sp->u.bsg_job; + bsg_reply = bsg_job->reply; memset(&fstatus, 0, sizeof(struct qla_mt_iocb_rsp_fx00)); @@ -2257,8 +2259,8 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, sp->fcport->vha, 0x5074, (uint8_t *)fw_sts_ptr, sizeof(struct qla_mt_iocb_rsp_fx00)); - res = bsg_job->reply->result = DID_OK << 16; - bsg_job->reply->reply_payload_rcv_len = + res = bsg_reply->result = DID_OK << 16; + bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; } sp->done(vha, sp, res); @@ -3253,6 +3255,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) struct srb_iocb *fxio = &sp->u.iocb_cmd; struct qla_mt_iocb_rqst_fx00 *piocb_rqst; struct fc_bsg_job *bsg_job; + struct fc_bsg_request *bsg_request; struct fxdisc_entry_fx00 fx_iocb; uint8_t entry_cnt = 1; @@ -3301,8 +3304,9 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) } else { struct scatterlist *sg; bsg_job = sp->u.bsg_job; + bsg_request = bsg_job->request; piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *) - &bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; + &bsg_request->rqst_data.h_vendor.vendor_cmd[1]; fx_iocb.func_num = piocb_rqst->func_type; fx_iocb.adapid = piocb_rqst->adapid; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index dbb9bdd569af..b23f05f765f5 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3588,9 +3588,10 @@ fc_bsg_jobdone(struct fc_bsg_job *job) { struct request *req = job->req; struct request *rsp = req->next_rq; + struct fc_bsg_reply *bsg_reply = job->reply; int err; - err = job->req->errors = job->reply->result; + err = job->req->errors = bsg_reply->result; if (err < 0) /* we're only returning the result field in the reply */ @@ -3602,10 +3603,10 @@ fc_bsg_jobdone(struct fc_bsg_job *job) req->resid_len = 0; if (rsp) { - WARN_ON(job->reply->reply_payload_rcv_len > rsp->resid_len); + WARN_ON(bsg_reply->reply_payload_rcv_len > rsp->resid_len); /* set reply (bidi) residual */ - rsp->resid_len -= min(job->reply->reply_payload_rcv_len, + rsp->resid_len -= min(bsg_reply->reply_payload_rcv_len, rsp->resid_len); } blk_complete_request(req); @@ -3779,11 +3780,19 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, struct fc_bsg_job *job) { struct fc_internal *i = to_fc_internal(shost->transportt); + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; int cmdlen = sizeof(uint32_t); /* start with length of msgcode */ int ret; + /* check if we really have all the request data needed */ + if (job->request_len < cmdlen) { + ret = -ENOMSG; + goto fail_host_msg; + } + /* Validate the host command */ - switch (job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_HST_ADD_RPORT: cmdlen += sizeof(struct fc_bsg_host_add_rport); break; @@ -3815,7 +3824,7 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, case FC_BSG_HST_VENDOR: cmdlen += sizeof(struct fc_bsg_host_vendor); if ((shost->hostt->vendor_id == 0L) || - (job->request->rqst_data.h_vendor.vendor_id != + (bsg_request->rqst_data.h_vendor.vendor_id != shost->hostt->vendor_id)) { ret = -ESRCH; goto fail_host_msg; @@ -3827,12 +3836,6 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, goto fail_host_msg; } - /* check if we really have all the request data needed */ - if (job->request_len < cmdlen) { - ret = -ENOMSG; - goto fail_host_msg; - } - ret = i->f->bsg_request(job); if (!ret) return FC_DISPATCH_UNLOCKED; @@ -3840,8 +3843,8 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, fail_host_msg: /* return the errno failure code as the only status */ BUG_ON(job->reply_len < sizeof(uint32_t)); - job->reply->reply_payload_rcv_len = 0; - job->reply->result = ret; + bsg_reply->reply_payload_rcv_len = 0; + bsg_reply->result = ret; job->reply_len = sizeof(uint32_t); fc_bsg_jobdone(job); return FC_DISPATCH_UNLOCKED; @@ -3878,11 +3881,19 @@ fc_bsg_rport_dispatch(struct request_queue *q, struct Scsi_Host *shost, struct fc_rport *rport, struct fc_bsg_job *job) { struct fc_internal *i = to_fc_internal(shost->transportt); + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; int cmdlen = sizeof(uint32_t); /* start with length of msgcode */ int ret; + /* check if we really have all the request data needed */ + if (job->request_len < cmdlen) { + ret = -ENOMSG; + goto fail_rport_msg; + } + /* Validate the rport command */ - switch (job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: cmdlen += sizeof(struct fc_bsg_rport_els); goto check_bidi; @@ -3902,12 +3913,6 @@ check_bidi: goto fail_rport_msg; } - /* check if we really have all the request data needed */ - if (job->request_len < cmdlen) { - ret = -ENOMSG; - goto fail_rport_msg; - } - ret = i->f->bsg_request(job); if (!ret) return FC_DISPATCH_UNLOCKED; @@ -3915,8 +3920,8 @@ check_bidi: fail_rport_msg: /* return the errno failure code as the only status */ BUG_ON(job->reply_len < sizeof(uint32_t)); - job->reply->reply_payload_rcv_len = 0; - job->reply->result = ret; + bsg_reply->reply_payload_rcv_len = 0; + bsg_reply->result = ret; job->reply_len = sizeof(uint32_t); fc_bsg_jobdone(job); return FC_DISPATCH_UNLOCKED; @@ -3937,6 +3942,7 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, struct request *req; struct fc_bsg_job *job; enum fc_dispatch_result ret; + struct fc_bsg_reply *bsg_reply; if (!get_device(dev)) return; @@ -3973,8 +3979,9 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, /* check if we have the msgcode value at least */ if (job->request_len < sizeof(uint32_t)) { BUG_ON(job->reply_len < sizeof(uint32_t)); - job->reply->reply_payload_rcv_len = 0; - job->reply->result = -ENOMSG; + bsg_reply = job->reply; + bsg_reply->reply_payload_rcv_len = 0; + bsg_reply->result = -ENOMSG; job->reply_len = sizeof(uint32_t); fc_bsg_jobdone(job); spin_lock_irq(q->queue_lock); From 1abaede71560fa98b97d8e6b172a14e6383f633d Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:13 +0100 Subject: [PATCH 177/256] scsi: fc: Export fc_bsg_jobdone and use it in FC drivers Export fc_bsg_jobdone so drivers can use it directly instead of doing the round-trip via struct fc_bsg_job::job_done() and use it in the LLDDs. That way we can also unify the interfaces of fc_bsg_jobdone and bsg_job_done. As we've converted all LLDDs over to use fc_bsg_jobdone() directly, we can remove the function pointer from struct fc_bsg_job as well. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fc.c | 2 +- drivers/scsi/bfa/bfad_bsg.c | 6 ++- drivers/scsi/ibmvscsi/ibmvfc.c | 3 +- drivers/scsi/libfc/fc_lport.c | 6 ++- drivers/scsi/lpfc/lpfc_bsg.c | 71 +++++++++++++++++++++----------- drivers/scsi/qla2xxx/qla_bsg.c | 66 +++++++++++++++++++---------- drivers/scsi/scsi_transport_fc.c | 25 ++++++----- include/scsi/scsi_transport_fc.h | 3 +- 8 files changed, 119 insertions(+), 63 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 4c4023fc6ad8..87f6330df300 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -892,7 +892,7 @@ static void zfcp_fc_ct_els_job_handler(void *data) jr->reply_payload_rcv_len = job->reply_payload.payload_len; jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; jr->result = zfcp_ct_els->status ? -EIO : 0; - job->job_done(job); + fc_bsg_jobdone(job, jr->result, jr->reply_payload_rcv_len); } static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job) diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 48366d8ad0d9..e49a6c813ca9 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3180,7 +3180,8 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job) bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; bsg_reply->result = rc; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; error: /* free the command buffer */ @@ -3556,7 +3557,8 @@ out: bsg_reply->result = rc; if (rc == BFA_STATUS_OK) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 7c17a7e73eb9..607036174a99 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1945,7 +1945,8 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job) ibmvfc_free_event(evt); spin_unlock_irqrestore(vhost->host->host_lock, flags); bsg_reply->result = rc; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); rc = 0; out: dma_unmap_sg(vhost->dev, job->request_payload.sg_list, diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2de6093b3c04..8ea6e9322ad1 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1913,7 +1913,8 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); job->state_flags |= FC_RQST_STATE_DONE; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); kfree(info); return; } @@ -1948,7 +1949,8 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, job->reply_payload.payload_len; bsg_reply->result = 0; job->state_flags |= FC_RQST_STATE_DONE; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); kfree(info); } fc_frame_free(fp); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index f09a32501f69..46f0b8ff1e00 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -371,7 +371,8 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return; } @@ -644,7 +645,8 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return; } @@ -1136,7 +1138,8 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, job->dd_data = NULL; /* complete the job back to userspace */ spin_unlock_irqrestore(&phba->ct_ev_lock, flags); - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); spin_lock_irqsave(&phba->ct_ev_lock, flags); } } @@ -1361,7 +1364,8 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) spin_unlock_irqrestore(&phba->ct_ev_lock, flags); job->dd_data = NULL; bsg_reply->result = 0; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; job_error: @@ -1458,7 +1462,8 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return; } @@ -1886,7 +1891,8 @@ job_error: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -2175,7 +2181,8 @@ job_error: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -2289,7 +2296,8 @@ loopback_mode_end_exit: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -2441,7 +2449,8 @@ job_error: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -3301,7 +3310,8 @@ loopback_test_exit: job->dd_data = NULL; /* complete the job back to userspace if no error */ if (rc == IOCB_SUCCESS) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -3344,7 +3354,8 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job) job_error: bsg_reply->result = rc; if (rc == 0) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -3409,7 +3420,8 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) if (job) { bsg_reply->result = 0; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return; } @@ -3635,6 +3647,7 @@ static void lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); @@ -3654,9 +3667,11 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) mempool_free(pmboxq, phba->mbox_mem_pool); /* if the job is still active, call job done */ - if (job) - job->job_done(job); - + if (job) { + bsg_reply = job->reply; + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + } return; } @@ -3672,6 +3687,7 @@ static void lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { struct fc_bsg_job *job; + struct fc_bsg_reply *bsg_reply; job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); @@ -3689,8 +3705,11 @@ lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) lpfc_bsg_mbox_ext_session_reset(phba); /* if the job is still active, call job done */ - if (job) - job->job_done(job); + if (job) { + bsg_reply = job->reply; + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + } return; } @@ -4131,7 +4150,8 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, /* wait for additoinal external buffers */ bsg_reply->result = 0; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return SLI_CONFIG_HANDLED; job_error: @@ -4357,7 +4377,8 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) } bsg_reply->result = 0; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return SLI_CONFIG_HANDLED; } @@ -4473,7 +4494,8 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, /* wait for additoinal external buffers */ bsg_reply->result = 0; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return SLI_CONFIG_HANDLED; job_error: @@ -4941,7 +4963,8 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) /* job done */ bsg_reply->result = 0; job->dd_data = NULL; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } else if (rc == 1) /* job submitted, will complete later*/ rc = 0; /* return zero, no error */ @@ -5051,7 +5074,8 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return; @@ -5269,7 +5293,8 @@ lpfc_forced_link_speed(struct fc_bsg_job *job) job_error: bsg_reply->result = rc; if (rc == 0) - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 40f7c1081e8d..9293d5a279f7 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -20,7 +20,8 @@ qla2x00_bsg_job_done(void *data, void *ptr, int res) struct fc_bsg_reply *bsg_reply = bsg_job->reply; bsg_reply->result = res; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); sp->free(vha, sp); } @@ -242,7 +243,8 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) } exit_fcp_prio_cfg: if (!ret) - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return ret; } @@ -939,7 +941,8 @@ done_unmap_req_sg: bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); if (!rval) - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rval; } @@ -972,7 +975,8 @@ qla84xx_reset(struct fc_bsg_job *bsg_job) ql_dbg(ql_dbg_user, vha, 0x7031, "Vendor request 84xx reset completed.\n"); bsg_reply->result = DID_OK; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return rval; @@ -1085,7 +1089,8 @@ done_unmap_sg: bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); if (!rval) - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rval; } @@ -1282,7 +1287,8 @@ exit_mgmt: dma_pool_free(ha->s_dma_pool, mn, mn_dma); if (!rval) - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rval; } @@ -1368,7 +1374,8 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) } bsg_reply->result = DID_OK; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); } return rval; @@ -1476,7 +1483,8 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job) ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; mutex_unlock(&ha->optrom_mutex); - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rval; } @@ -1511,7 +1519,8 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job) ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; mutex_unlock(&ha->optrom_mutex); - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rval; } @@ -1561,7 +1570,8 @@ dealloc: done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -1610,7 +1620,8 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = sizeof(*sr); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -1655,7 +1666,8 @@ dealloc: done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -1699,7 +1711,8 @@ dealloc: done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -1747,7 +1760,8 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = sizeof(*i2c); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -1925,7 +1939,8 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = (DID_OK) << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); /* Always return success, vendor rsp carries correct status */ return 0; } @@ -2090,7 +2105,8 @@ qla26xx_serdes_op(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -2131,7 +2147,8 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -2162,7 +2179,8 @@ qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -2207,7 +2225,8 @@ qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -2265,7 +2284,8 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return 0; } @@ -2321,7 +2341,8 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(*bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); dma_free_coherent(&ha->pdev->dev, sizeof(*stats), stats, stats_dma); @@ -2364,7 +2385,8 @@ qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) bsg_job->reply_len = sizeof(*bsg_reply); bsg_reply->result = DID_OK << 16; - bsg_job->job_done(bsg_job); + fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); kfree(dd); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index b23f05f765f5..9f20b05f0023 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3582,16 +3582,17 @@ fc_destroy_bsgjob(struct fc_bsg_job *job) * fc_bsg_jobdone - completion routine for bsg requests that the LLD has * completed * @job: fc_bsg_job that is complete + * @result: job reply result + * @reply_payload_rcv_len: length of payload received */ -static void -fc_bsg_jobdone(struct fc_bsg_job *job) +void fc_bsg_jobdone(struct fc_bsg_job *job, int result, + unsigned int reply_payload_rcv_len) { struct request *req = job->req; struct request *rsp = req->next_rq; - struct fc_bsg_reply *bsg_reply = job->reply; int err; - err = job->req->errors = bsg_reply->result; + err = job->req->errors = result; if (err < 0) /* we're only returning the result field in the reply */ @@ -3603,14 +3604,14 @@ fc_bsg_jobdone(struct fc_bsg_job *job) req->resid_len = 0; if (rsp) { - WARN_ON(bsg_reply->reply_payload_rcv_len > rsp->resid_len); + WARN_ON(reply_payload_rcv_len > rsp->resid_len); /* set reply (bidi) residual */ - rsp->resid_len -= min(bsg_reply->reply_payload_rcv_len, - rsp->resid_len); + rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len); } blk_complete_request(req); } +EXPORT_SYMBOL_GPL(fc_bsg_jobdone); /** * fc_bsg_softirq_done - softirq done routine for destroying the bsg requests @@ -3742,7 +3743,6 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport, if (ret) goto failjob_rls_rqst_payload; } - job->job_done = fc_bsg_jobdone; if (rport) job->dev = &rport->dev; else @@ -3846,7 +3846,8 @@ fail_host_msg: bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = ret; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return FC_DISPATCH_UNLOCKED; } @@ -3923,7 +3924,8 @@ fail_rport_msg: bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = ret; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return FC_DISPATCH_UNLOCKED; } @@ -3983,7 +3985,8 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = -ENOMSG; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); spin_lock_irq(q->queue_lock); continue; } diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 921b097f039b..eca8ed787b8a 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -637,7 +637,6 @@ struct fc_bsg_job { spinlock_t job_lock; unsigned int state_flags; unsigned int ref_cnt; - void (*job_done)(struct fc_bsg_job *); struct fc_bsg_request *request; struct fc_bsg_reply *reply; @@ -842,5 +841,7 @@ struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, struct fc_vport_identifiers *); int fc_vport_terminate(struct fc_vport *vport); int fc_block_scsi_eh(struct scsi_cmnd *cmnd); +void fc_bsg_jobdone(struct fc_bsg_job *job, int result, + unsigned int reply_payload_rcv_len); #endif /* SCSI_TRANSPORT_FC_H */ From cd21c605b2cf1cf4e698eb4f043f6a7f72b55691 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:14 +0100 Subject: [PATCH 178/256] scsi: fc: provide fc_bsg_to_shost() helper Provide fc_bsg_to_shost() helper that will become handy when we're moving from struct fc_bsg_job to a plain struct bsg_job. Also use this little helper in the LLDDs. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fc.c | 6 ++-- drivers/scsi/bfa/bfad_bsg.c | 6 ++-- drivers/scsi/ibmvscsi/ibmvfc.c | 4 +-- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/lpfc/lpfc_bsg.c | 34 ++++++++++---------- drivers/scsi/qla2xxx/qla_bsg.c | 54 ++++++++++++++++---------------- drivers/scsi/scsi_transport_fc.c | 2 +- include/scsi/scsi_transport_fc.h | 5 +++ 8 files changed, 59 insertions(+), 54 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 87f6330df300..3937debf7cb5 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -901,11 +901,13 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job) u8 gs_type; struct zfcp_adapter *adapter; struct fc_bsg_request *bsg_request = job->request; + struct Scsi_Host *shost; preamble_word1 = bsg_request->rqst_data.r_ct.preamble_word1; gs_type = (preamble_word1 & 0xff000000) >> 24; - adapter = (struct zfcp_adapter *) job->shost->hostdata[0]; + shost = fc_bsg_to_shost(job); + adapter = (struct zfcp_adapter *) shost->hostdata[0]; switch (gs_type) { case FC_FST_ALIAS: @@ -987,7 +989,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) struct zfcp_fsf_ct_els *ct_els = job->dd_data; struct fc_bsg_request *bsg_request = job->request; - shost = job->rport ? rport_to_shost(job->rport) : job->shost; + shost = job->rport ? rport_to_shost(job->rport) : fc_bsg_to_shost(job); adapter = (struct zfcp_adapter *)shost->hostdata[0]; if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index e49a6c813ca9..d3094270b02a 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3135,8 +3135,7 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job) struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; uint32_t vendor_cmd = bsg_request->rqst_data.h_vendor.vendor_cmd[0]; - struct bfad_im_port_s *im_port = - (struct bfad_im_port_s *) job->shost->hostdata[0]; + struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job)); struct bfad_s *bfad = im_port->bfad; struct request_queue *request_q = job->req->q; void *payload_kbuf; @@ -3358,8 +3357,7 @@ int bfad_im_bsg_els_ct_request(struct fc_bsg_job *job) { struct bfa_bsg_data *bsg_data; - struct bfad_im_port_s *im_port = - (struct bfad_im_port_s *) job->shost->hostdata[0]; + struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job)); struct bfad_s *bfad = im_port->bfad; bfa_bsg_fcpt_t *bsg_fcpt; struct bfad_fcxp *drv_fcxp; diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 607036174a99..02df1f156f1b 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1708,7 +1708,7 @@ static void ibmvfc_bsg_timeout_done(struct ibmvfc_event *evt) **/ static int ibmvfc_bsg_timeout(struct fc_bsg_job *job) { - struct ibmvfc_host *vhost = shost_priv(job->shost); + struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job)); unsigned long port_id = (unsigned long)job->dd_data; struct ibmvfc_event *evt; struct ibmvfc_tmf *tmf; @@ -1821,7 +1821,7 @@ unlock_out: **/ static int ibmvfc_bsg_request(struct fc_bsg_job *job) { - struct ibmvfc_host *vhost = shost_priv(job->shost); + struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job)); struct fc_rport *rport = job->rport; struct ibmvfc_passthru_mad *mad; struct ibmvfc_event *evt; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 8ea6e9322ad1..3e3afe6e0cde 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2088,7 +2088,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; struct request *rsp = job->req->next_rq; - struct Scsi_Host *shost = job->shost; + struct Scsi_Host *shost = fc_bsg_to_shost(job); struct fc_lport *lport = shost_priv(shost); struct fc_rport *rport; struct fc_rport_priv *rdata; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 46f0b8ff1e00..45184ee5fbaa 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -384,7 +384,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, static int lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; struct lpfc_rport_data *rdata = job->rport->dd_data; struct lpfc_nodelist *ndlp = rdata->pnode; @@ -658,7 +658,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, static int lpfc_bsg_rport_els(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; struct lpfc_rport_data *rdata = job->rport->dd_data; struct lpfc_nodelist *ndlp = rdata->pnode; @@ -1202,7 +1202,7 @@ lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf) static int lpfc_bsg_hba_set_event(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; struct fc_bsg_request *bsg_request = job->request; struct set_ct_event *event_req; @@ -1287,7 +1287,7 @@ job_error: static int lpfc_bsg_hba_get_event(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -1625,7 +1625,7 @@ no_dd_data: static int lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -2201,10 +2201,10 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) struct lpfc_hba *phba; int rc; - shost = job->shost; + shost = fc_bsg_to_shost(job); if (!shost) return -ENODEV; - vport = (struct lpfc_vport *)job->shost->hostdata; + vport = shost_priv(shost); if (!vport) return -ENODEV; phba = vport->phba; @@ -2241,10 +2241,10 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) uint32_t timeout; int rc, i; - shost = job->shost; + shost = fc_bsg_to_shost(job); if (!shost) return -ENODEV; - vport = (struct lpfc_vport *)job->shost->hostdata; + vport = shost_priv(shost); if (!vport) return -ENODEV; phba = vport->phba; @@ -2325,12 +2325,12 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) struct diag_status *diag_status_reply; int mbxstatus, rc = 0; - shost = job->shost; + shost = fc_bsg_to_shost(job); if (!shost) { rc = -ENODEV; goto job_error; } - vport = (struct lpfc_vport *)job->shost->hostdata; + vport = shost_priv(shost); if (!vport) { rc = -ENODEV; goto job_error; @@ -3018,7 +3018,7 @@ err_post_rxbufs_exit: static int lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; struct lpfc_bsg_event *evt; @@ -3322,7 +3322,7 @@ loopback_test_exit: static int lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; struct get_mgmt_rev_reply *event_reply; @@ -4933,7 +4933,7 @@ job_cont: static int lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; @@ -5093,7 +5093,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, static int lpfc_menlo_cmd(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_hba *phba = vport->phba; @@ -5257,7 +5257,7 @@ no_dd_data: static int lpfc_forced_link_speed(struct fc_bsg_job *job) { - struct Scsi_Host *shost = job->shost; + struct Scsi_Host *shost = fc_bsg_to_shost(job); struct lpfc_vport *vport = shost_priv(shost); struct lpfc_hba *phba = vport->phba; struct fc_bsg_reply *bsg_reply = job->reply; @@ -5400,7 +5400,7 @@ lpfc_bsg_request(struct fc_bsg_job *job) int lpfc_bsg_timeout(struct fc_bsg_job *job) { - struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; + struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 9293d5a279f7..109b852daada 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1,4 +1,4 @@ -/* + /* * QLogic Fibre Channel HBA Driver * Copyright (c) 2003-2014 QLogic Corporation * @@ -122,7 +122,7 @@ qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha, static int qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) { - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(host); @@ -271,7 +271,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) ha = vha->hw; type = "FC_BSG_RPT_ELS"; } else { - host = bsg_job->shost; + host = fc_bsg_to_shost(bsg_job); vha = shost_priv(host); ha = vha->hw; type = "FC_BSG_HST_ELS_NOLOGIN"; @@ -432,7 +432,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) { srb_t *sp; struct fc_bsg_request *bsg_request = bsg_job->request; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = (DRIVER_ERROR << 16); @@ -710,7 +710,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval; @@ -950,7 +950,7 @@ static int qla84xx_reset(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; @@ -987,7 +987,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; struct verify_chip_entry_84xx *mn = NULL; @@ -1099,7 +1099,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; struct access_chip_84xx *mn = NULL; @@ -1297,7 +1297,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); int rval = 0; struct qla_port_param *port_param = NULL; @@ -1455,7 +1455,7 @@ static int qla2x00_read_optrom(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1492,7 +1492,7 @@ static int qla2x00_update_optrom(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1528,7 +1528,7 @@ static int qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1580,7 +1580,7 @@ static int qla2x00_read_fru_status(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1630,7 +1630,7 @@ static int qla2x00_write_fru_status(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1676,7 +1676,7 @@ static int qla2x00_write_i2c(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1721,7 +1721,7 @@ static int qla2x00_read_i2c(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = 0; @@ -1770,7 +1770,7 @@ static int qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; uint32_t rval = EXT_STATUS_OK; @@ -1949,7 +1949,7 @@ static int qlafx00_mgmt_cmd(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; int rval = (DRIVER_ERROR << 16); @@ -2072,7 +2072,7 @@ static int qla26xx_serdes_op(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); int rval = 0; struct qla_serdes_reg sr; @@ -2114,7 +2114,7 @@ static int qla8044_serdes_op(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); int rval = 0; struct qla_serdes_reg_ex sr; @@ -2156,7 +2156,7 @@ static int qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; struct qla_flash_update_caps cap; @@ -2188,7 +2188,7 @@ static int qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; uint64_t online_fw_attr = 0; @@ -2234,7 +2234,7 @@ static int qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; struct qla_bbcr_data bbcr; @@ -2294,7 +2294,7 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); @@ -2354,7 +2354,7 @@ static int qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct Scsi_Host *host = bsg_job->shost; + struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); int rval; struct qla_dport_diag *dd; @@ -2489,7 +2489,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) host = rport_to_shost(rport); vha = shost_priv(host); } else { - host = bsg_job->shost; + host = fc_bsg_to_shost(bsg_job); vha = shost_priv(host); } @@ -2528,7 +2528,7 @@ int qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; - scsi_qla_host_t *vha = shost_priv(bsg_job->shost); + scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); struct qla_hw_data *ha = vha->hw; srb_t *sp; int cnt, que; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 9f20b05f0023..53a59daddfb5 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3639,7 +3639,7 @@ static enum blk_eh_timer_return fc_bsg_job_timeout(struct request *req) { struct fc_bsg_job *job = (void *) req->special; - struct Scsi_Host *shost = job->shost; + struct Scsi_Host *shost = fc_bsg_to_shost(job); struct fc_internal *i = to_fc_internal(shost->transportt); unsigned long flags; int err = 0, done = 0; diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index eca8ed787b8a..efb948816f5d 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -819,6 +819,11 @@ fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state) vport->vport_state = new_state; } +static inline struct Scsi_Host *fc_bsg_to_shost(struct fc_bsg_job *job) +{ + return job->shost; +} + struct scsi_transport_template *fc_attach_transport( struct fc_function_template *); void fc_release_transport(struct scsi_transport_template *); From 1d69b1222abcba58e567bc99b0b76b7857dc5031 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:15 +0100 Subject: [PATCH 179/256] scsi: fc: provide fc_bsg_to_rport() helper Provide fc_bsg_to_rport() helper that will become handy when we're moving from struct fc_bsg_job to a plain struct bsg_job. Also move all LLDDs to use the new helper. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fc.c | 8 +++++--- drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- drivers/scsi/libfc/fc_lport.c | 4 ++-- drivers/scsi/lpfc/lpfc_bsg.c | 4 ++-- drivers/scsi/qla2xxx/qla_bsg.c | 4 ++-- drivers/scsi/scsi_transport_fc.c | 3 ++- include/scsi/scsi_transport_fc.h | 5 +++++ 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 3937debf7cb5..c751003aea61 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -901,12 +901,13 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job) u8 gs_type; struct zfcp_adapter *adapter; struct fc_bsg_request *bsg_request = job->request; + struct fc_rport *rport = fc_bsg_to_rport(job); struct Scsi_Host *shost; preamble_word1 = bsg_request->rqst_data.r_ct.preamble_word1; gs_type = (preamble_word1 & 0xff000000) >> 24; - shost = fc_bsg_to_shost(job); + shost = rport ? rport_to_shost(rport) : fc_bsg_to_shost(job); adapter = (struct zfcp_adapter *) shost->hostdata[0]; switch (gs_type) { @@ -940,7 +941,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, struct zfcp_adapter *adapter) { struct zfcp_fsf_ct_els *els = job->dd_data; - struct fc_rport *rport = job->rport; + struct fc_rport *rport = fc_bsg_to_rport(job); struct fc_bsg_request *bsg_request = job->request; struct zfcp_port *port; u32 d_id; @@ -988,8 +989,9 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) struct zfcp_adapter *adapter; struct zfcp_fsf_ct_els *ct_els = job->dd_data; struct fc_bsg_request *bsg_request = job->request; + struct fc_rport *rport = fc_bsg_to_rport(job); - shost = job->rport ? rport_to_shost(job->rport) : fc_bsg_to_shost(job); + shost = rport ? rport_to_shost(rport) : fc_bsg_to_shost(job); adapter = (struct zfcp_adapter *)shost->hostdata[0]; if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 02df1f156f1b..4c73fc735b13 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1822,7 +1822,7 @@ unlock_out: static int ibmvfc_bsg_request(struct fc_bsg_job *job) { struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job)); - struct fc_rport *rport = job->rport; + struct fc_rport *rport = fc_bsg_to_rport(job); struct ibmvfc_passthru_mad *mad; struct ibmvfc_event *evt; union ibmvfc_iu rsp_iu; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 3e3afe6e0cde..5e24ca3118c3 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2103,7 +2103,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: - rport = job->rport; + rport = fc_bsg_to_rport(job); if (!rport) break; @@ -2113,7 +2113,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; case FC_BSG_RPT_CT: - rport = job->rport; + rport = fc_bsg_to_rport(job); if (!rport) break; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 45184ee5fbaa..19847d7d4177 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -386,7 +386,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; - struct lpfc_rport_data *rdata = job->rport->dd_data; + struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data; struct lpfc_nodelist *ndlp = rdata->pnode; struct fc_bsg_reply *bsg_reply = job->reply; struct ulp_bde64 *bpl = NULL; @@ -660,7 +660,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; - struct lpfc_rport_data *rdata = job->rport->dd_data; + struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data; struct lpfc_nodelist *ndlp = rdata->pnode; struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 109b852daada..917eafecc435 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -264,7 +264,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) uint16_t nextlid = 0; if (bsg_request->msgcode == FC_BSG_RPT_ELS) { - rport = bsg_job->rport; + rport = fc_bsg_to_rport(bsg_job); fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); @@ -2485,7 +2485,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) bsg_reply->reply_payload_rcv_len = 0; if (bsg_request->msgcode == FC_BSG_RPT_ELS) { - rport = bsg_job->rport; + rport = fc_bsg_to_rport(bsg_job); host = rport_to_shost(rport); vha = shost_priv(host); } else { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 53a59daddfb5..45954a6edd94 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3640,11 +3640,12 @@ fc_bsg_job_timeout(struct request *req) { struct fc_bsg_job *job = (void *) req->special; struct Scsi_Host *shost = fc_bsg_to_shost(job); + struct fc_rport *rport = fc_bsg_to_rport(job); struct fc_internal *i = to_fc_internal(shost->transportt); unsigned long flags; int err = 0, done = 0; - if (job->rport && job->rport->port_state == FC_PORTSTATE_BLOCKED) + if (rport && rport->port_state == FC_PORTSTATE_BLOCKED) return BLK_EH_RESET_TIMER; spin_lock_irqsave(&job->job_lock, flags); diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index efb948816f5d..9f53fe3fa249 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -824,6 +824,11 @@ static inline struct Scsi_Host *fc_bsg_to_shost(struct fc_bsg_job *job) return job->shost; } +static inline struct fc_rport *fc_bsg_to_rport(struct fc_bsg_job *job) +{ + return job->rport; +} + struct scsi_transport_template *fc_attach_transport( struct fc_function_template *); void fc_release_transport(struct scsi_transport_template *); From 7ac65007c285e377a31107fe2e13afacf47400f2 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:16 +0100 Subject: [PATCH 180/256] scsi: libfc: don't set FC_RQST_STATE_DONE before calling fc_bsg_jobdone() Don't set FC_RQST_STATE_DONE before calling fc_bsg_jobdone() as fc_bsg_jobdone() calls blk_complete_requeust() which raises a soft-IRQ that ends up in fc_bsg_sofirq_done() and fc_bsg_softirq_done() sets the FC_RQST_STATE_DONE flag. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 5e24ca3118c3..cc98ebc9d0af 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1912,7 +1912,6 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); - job->state_flags |= FC_RQST_STATE_DONE; fc_bsg_jobdone(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); @@ -1948,7 +1947,6 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; bsg_reply->result = 0; - job->state_flags |= FC_RQST_STATE_DONE; fc_bsg_jobdone(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); From ad7660cc1ef13551e3d0a649aaba7c728b8c0ac0 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:17 +0100 Subject: [PATCH 181/256] scsi: fc: implement kref backed reference counting Implement kref backed reference counting instead of rolling our own. This elimnates the need of the following fields in 'struct fc_bsg_job': * ref_cnt * state_flags * job_lock bringing us close to unification of 'struct fc_bsg_job' and 'struct bsg_job'. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 40 +++++++++----------------------- include/scsi/scsi_transport_fc.h | 4 +--- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 45954a6edd94..9009acc27aed 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3560,16 +3560,12 @@ fc_vport_sched_delete(struct work_struct *work) * @job: fc_bsg_job that is to be torn down */ static void -fc_destroy_bsgjob(struct fc_bsg_job *job) +fc_destroy_bsgjob(struct kref *kref) { - unsigned long flags; + struct fc_bsg_job *job = container_of(kref, struct fc_bsg_job, kref); + struct request *rq = job->req; - spin_lock_irqsave(&job->job_lock, flags); - if (job->ref_cnt) { - spin_unlock_irqrestore(&job->job_lock, flags); - return; - } - spin_unlock_irqrestore(&job->job_lock, flags); + blk_end_request_all(rq, rq->errors); put_device(job->dev); /* release reference for the request */ @@ -3620,15 +3616,8 @@ EXPORT_SYMBOL_GPL(fc_bsg_jobdone); static void fc_bsg_softirq_done(struct request *rq) { struct fc_bsg_job *job = rq->special; - unsigned long flags; - spin_lock_irqsave(&job->job_lock, flags); - job->state_flags |= FC_RQST_STATE_DONE; - job->ref_cnt--; - spin_unlock_irqrestore(&job->job_lock, flags); - - blk_end_request_all(rq, rq->errors); - fc_destroy_bsgjob(job); + kref_put(&job->kref, fc_destroy_bsgjob); } /** @@ -3642,24 +3631,18 @@ fc_bsg_job_timeout(struct request *req) struct Scsi_Host *shost = fc_bsg_to_shost(job); struct fc_rport *rport = fc_bsg_to_rport(job); struct fc_internal *i = to_fc_internal(shost->transportt); - unsigned long flags; - int err = 0, done = 0; + int err = 0, inflight = 0; if (rport && rport->port_state == FC_PORTSTATE_BLOCKED) return BLK_EH_RESET_TIMER; - spin_lock_irqsave(&job->job_lock, flags); - if (job->state_flags & FC_RQST_STATE_DONE) - done = 1; - else - job->ref_cnt++; - spin_unlock_irqrestore(&job->job_lock, flags); + inflight = kref_get_unless_zero(&job->kref); - if (!done && i->f->bsg_timeout) { + if (inflight && i->f->bsg_timeout) { /* call LLDD to abort the i/o as it has timed out */ err = i->f->bsg_timeout(job); if (err == -EAGAIN) { - job->ref_cnt--; + kref_put(&job->kref, fc_destroy_bsgjob); return BLK_EH_RESET_TIMER; } else if (err) printk(KERN_ERR "ERROR: FC BSG request timeout - LLD " @@ -3667,7 +3650,7 @@ fc_bsg_job_timeout(struct request *req) } /* the blk_end_sync_io() doesn't check the error */ - if (done) + if (!inflight) return BLK_EH_NOT_HANDLED; else return BLK_EH_HANDLED; @@ -3728,7 +3711,6 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport, job->req = req; if (i->f->dd_bsg_size) job->dd_data = (void *)&job[1]; - spin_lock_init(&job->job_lock); job->request = (struct fc_bsg_request *)req->cmd; job->request_len = req->cmd_len; job->reply = req->sense; @@ -3750,7 +3732,7 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport, job->dev = &shost->shost_gendev; get_device(job->dev); /* take a reference for the request */ - job->ref_cnt = 1; + kref_init(&job->kref); return 0; diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 9f53fe3fa249..8ae5680f2216 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -634,9 +634,7 @@ struct fc_bsg_job { struct fc_rport *rport; struct device *dev; struct request *req; - spinlock_t job_lock; - unsigned int state_flags; - unsigned int ref_cnt; + struct kref kref; struct fc_bsg_request *request; struct fc_bsg_reply *reply; From bf0f2d380f15f1fa05254b000ddeeb560dfb8638 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:18 +0100 Subject: [PATCH 182/256] block: add reference counting for struct bsg_job Add reference counting to 'struct bsg_job' so we can implement a reuqest timeout handler for bsg_jobs, which is needed for Fibre Channel. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- block/bsg-lib.c | 7 +++++-- include/linux/bsg-lib.h | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/block/bsg-lib.c b/block/bsg-lib.c index 650f427d915b..632fb4006c40 100644 --- a/block/bsg-lib.c +++ b/block/bsg-lib.c @@ -32,8 +32,10 @@ * bsg_destroy_job - routine to teardown/delete a bsg job * @job: bsg_job that is to be torn down */ -static void bsg_destroy_job(struct bsg_job *job) +static void bsg_destroy_job(struct kref *kref) { + struct bsg_job *job = container_of(kref, struct bsg_job, kref); + put_device(job->dev); /* release reference for the request */ kfree(job->request_payload.sg_list); @@ -84,7 +86,7 @@ static void bsg_softirq_done(struct request *rq) struct bsg_job *job = rq->special; blk_end_request_all(rq, rq->errors); - bsg_destroy_job(job); + kref_put(&job->kref, bsg_destroy_job); } static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req) @@ -142,6 +144,7 @@ static int bsg_create_job(struct device *dev, struct request *req) job->dev = dev; /* take a reference for the request */ get_device(job->dev); + kref_init(&job->kref); return 0; failjob_rls_rqst_payload: diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h index a226652a5a6c..58e0717fda6e 100644 --- a/include/linux/bsg-lib.h +++ b/include/linux/bsg-lib.h @@ -40,6 +40,8 @@ struct bsg_job { struct device *dev; struct request *req; + struct kref kref; + /* Transport/driver specific request/reply structs */ void *request; void *reply; From 75cc8cfc6e13d42d50c2bf4307d0a68c2a70f709 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:19 +0100 Subject: [PATCH 183/256] scsi: change FC drivers to use 'struct bsg_job' Change FC drivers to use 'struct bsg_job' from bsg-lib.h instead of 'struct fc_bsg_job' from scsi_transport_fc.h and remove 'struct fc_bsg_job'. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_ext.h | 4 +- drivers/s390/scsi/zfcp_fc.c | 15 ++++--- drivers/scsi/bfa/bfad_bsg.c | 10 ++--- drivers/scsi/bfa/bfad_im.h | 4 +- drivers/scsi/ibmvscsi/ibmvfc.c | 9 ++-- drivers/scsi/libfc/fc_lport.c | 10 ++--- drivers/scsi/lpfc/lpfc_bsg.c | 76 ++++++++++++++++---------------- drivers/scsi/lpfc/lpfc_crtn.h | 4 +- drivers/scsi/qla2xxx/qla_bsg.c | 61 ++++++++++++------------- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/scsi/qla2xxx/qla_gbl.h | 4 +- drivers/scsi/qla2xxx/qla_iocb.c | 8 ++-- drivers/scsi/qla2xxx/qla_isr.c | 6 +-- drivers/scsi/qla2xxx/qla_mr.c | 5 ++- drivers/scsi/scsi_transport_fc.c | 20 ++++----- include/scsi/libfc.h | 2 +- include/scsi/scsi_transport_fc.h | 63 ++++++++------------------ 17 files changed, 139 insertions(+), 164 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c8fed9fa1cca..968a0ab4b398 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -84,8 +84,8 @@ extern void zfcp_fc_link_test_work(struct work_struct *); extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *); extern int zfcp_fc_gs_setup(struct zfcp_adapter *); extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); -extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); -extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *); +extern int zfcp_fc_exec_bsg_job(struct bsg_job *); +extern int zfcp_fc_timeout_bsg_job(struct bsg_job *); extern void zfcp_fc_sym_name_update(struct work_struct *); extern unsigned int zfcp_fc_port_scan_backoff(void); extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index c751003aea61..f01b9a45d82e 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "zfcp_ext.h" @@ -885,7 +886,7 @@ out_free: static void zfcp_fc_ct_els_job_handler(void *data) { - struct fc_bsg_job *job = data; + struct bsg_job *job = data; struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data; struct fc_bsg_reply *jr = job->reply; @@ -895,7 +896,7 @@ static void zfcp_fc_ct_els_job_handler(void *data) fc_bsg_jobdone(job, jr->result, jr->reply_payload_rcv_len); } -static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job) +static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct bsg_job *job) { u32 preamble_word1; u8 gs_type; @@ -928,7 +929,7 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job) static void zfcp_fc_ct_job_handler(void *data) { - struct fc_bsg_job *job = data; + struct bsg_job *job = data; struct zfcp_fc_wka_port *wka_port; wka_port = zfcp_fc_job_wka_port(job); @@ -937,7 +938,7 @@ static void zfcp_fc_ct_job_handler(void *data) zfcp_fc_ct_els_job_handler(data); } -static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, +static int zfcp_fc_exec_els_job(struct bsg_job *job, struct zfcp_adapter *adapter) { struct zfcp_fsf_ct_els *els = job->dd_data; @@ -960,7 +961,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, return zfcp_fsf_send_els(adapter, d_id, els, job->req->timeout / HZ); } -static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job, +static int zfcp_fc_exec_ct_job(struct bsg_job *job, struct zfcp_adapter *adapter) { int ret; @@ -983,7 +984,7 @@ static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job, return ret; } -int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) +int zfcp_fc_exec_bsg_job(struct bsg_job *job) { struct Scsi_Host *shost; struct zfcp_adapter *adapter; @@ -1013,7 +1014,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) } } -int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *job) +int zfcp_fc_timeout_bsg_job(struct bsg_job *job) { /* hardware tracks timeout, reset bsg timeout to not interfere */ return -EAGAIN; diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index d3094270b02a..cdc25e6572a4 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3130,7 +3130,7 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, } static int -bfad_im_bsg_vendor_request(struct fc_bsg_job *job) +bfad_im_bsg_vendor_request(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -3314,7 +3314,7 @@ bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base, } int -bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp, +bfad_fcxp_bsg_send(struct bsg_job *job, struct bfad_fcxp *drv_fcxp, bfa_bsg_fcpt_t *bsg_fcpt) { struct bfa_fcxp_s *hal_fcxp; @@ -3354,7 +3354,7 @@ bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp, } int -bfad_im_bsg_els_ct_request(struct fc_bsg_job *job) +bfad_im_bsg_els_ct_request(struct bsg_job *job) { struct bfa_bsg_data *bsg_data; struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job)); @@ -3562,7 +3562,7 @@ out: } int -bfad_im_bsg_request(struct fc_bsg_job *job) +bfad_im_bsg_request(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -3590,7 +3590,7 @@ bfad_im_bsg_request(struct fc_bsg_job *job) } int -bfad_im_bsg_timeout(struct fc_bsg_job *job) +bfad_im_bsg_timeout(struct bsg_job *job) { /* Don't complete the BSG job request - return -EAGAIN * to reset bsg job timeout : for ELS/CT pass thru we diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h index 836fdc221edd..c81ec2a77ef5 100644 --- a/drivers/scsi/bfa/bfad_im.h +++ b/drivers/scsi/bfa/bfad_im.h @@ -166,8 +166,8 @@ extern struct device_attribute *bfad_im_vport_attrs[]; irqreturn_t bfad_intx(int irq, void *dev_id); -int bfad_im_bsg_request(struct fc_bsg_job *job); -int bfad_im_bsg_timeout(struct fc_bsg_job *job); +int bfad_im_bsg_request(struct bsg_job *job); +int bfad_im_bsg_timeout(struct bsg_job *job); /* * Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 4c73fc735b13..f59b0a1e205e 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1701,12 +1702,12 @@ static void ibmvfc_bsg_timeout_done(struct ibmvfc_event *evt) /** * ibmvfc_bsg_timeout - Handle a BSG timeout - * @job: struct fc_bsg_job that timed out + * @job: struct bsg_job that timed out * * Returns: * 0 on success / other on failure **/ -static int ibmvfc_bsg_timeout(struct fc_bsg_job *job) +static int ibmvfc_bsg_timeout(struct bsg_job *job) { struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job)); unsigned long port_id = (unsigned long)job->dd_data; @@ -1814,12 +1815,12 @@ unlock_out: /** * ibmvfc_bsg_request - Handle a BSG request - * @job: struct fc_bsg_job to be executed + * @job: struct bsg_job to be executed * * Returns: * 0 on success / other on failure **/ -static int ibmvfc_bsg_request(struct fc_bsg_job *job) +static int ibmvfc_bsg_request(struct bsg_job *job) { struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job)); struct fc_rport *rport = fc_bsg_to_rport(job); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index cc98ebc9d0af..c428ce389a5b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -149,7 +149,7 @@ static const char *fc_lport_state_names[] = { * @offset: The offset into the response data */ struct fc_bsg_info { - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_lport *lport; u16 rsp_code; struct scatterlist *sg; @@ -1901,7 +1901,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, void *info_arg) { struct fc_bsg_info *info = info_arg; - struct fc_bsg_job *job = info->job; + struct bsg_job *job = info->job; struct fc_bsg_reply *bsg_reply = job->reply; struct fc_lport *lport = info->lport; struct fc_frame_header *fh; @@ -1964,7 +1964,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, * Locking Note: The lport lock is expected to be held before calling * this routine. */ -static int fc_lport_els_request(struct fc_bsg_job *job, +static int fc_lport_els_request(struct bsg_job *job, struct fc_lport *lport, u32 did, u32 tov) { @@ -2025,7 +2025,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job, * Locking Note: The lport lock is expected to be held before calling * this routine. */ -static int fc_lport_ct_request(struct fc_bsg_job *job, +static int fc_lport_ct_request(struct bsg_job *job, struct fc_lport *lport, u32 did, u32 tov) { struct fc_bsg_info *info; @@ -2081,7 +2081,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, * FC Passthrough requests * @job: The BSG passthrough job */ -int fc_lport_bsg_request(struct fc_bsg_job *job) +int fc_lport_bsg_request(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 19847d7d4177..b19ad9e45702 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -98,7 +98,7 @@ struct lpfc_bsg_menlo { #define TYPE_MENLO 4 struct bsg_job_data { uint32_t type; - struct fc_bsg_job *set_job; /* job waiting for this iocb to finish */ + struct bsg_job *set_job; /* job waiting for this iocb to finish */ union { struct lpfc_bsg_event *evt; struct lpfc_bsg_iocb iocb; @@ -298,7 +298,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *rspiocbq) { struct bsg_job_data *dd_data; - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp, *rmp; @@ -382,7 +382,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, * @job: fc_bsg_job to handle **/ static int -lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) +lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; @@ -575,7 +575,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *rspiocbq) { struct bsg_job_data *dd_data; - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_nodelist *ndlp; @@ -656,7 +656,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, * @job: fc_bsg_job to handle **/ static int -lpfc_bsg_rport_els(struct fc_bsg_job *job) +lpfc_bsg_rport_els(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; @@ -927,7 +927,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_dmabuf *bdeBuf2 = piocbq->context3; struct lpfc_hbq_entry *hbqe; struct lpfc_sli_ct_request *ct_req; - struct fc_bsg_job *job = NULL; + struct bsg_job *job = NULL; struct fc_bsg_reply *bsg_reply; struct bsg_job_data *dd_data = NULL; unsigned long flags; @@ -1200,7 +1200,7 @@ lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf) * @job: SET_EVENT fc_bsg_job **/ static int -lpfc_bsg_hba_set_event(struct fc_bsg_job *job) +lpfc_bsg_hba_set_event(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; @@ -1285,7 +1285,7 @@ job_error: * @job: GET_EVENT fc_bsg_job **/ static int -lpfc_bsg_hba_get_event(struct fc_bsg_job *job) +lpfc_bsg_hba_get_event(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; @@ -1397,7 +1397,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *rspiocbq) { struct bsg_job_data *dd_data; - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp; @@ -1477,7 +1477,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, * @num_entry: Number of enties in the bde. **/ static int -lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, +lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp, int num_entry) { @@ -1623,7 +1623,7 @@ no_dd_data: * @job: SEND_MGMT_RESP fc_bsg_job **/ static int -lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job) +lpfc_bsg_send_mgmt_rsp(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; @@ -1782,7 +1782,7 @@ lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba) * All of this is done in-line. */ static int -lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) +lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -2040,7 +2040,7 @@ lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba) * loopback mode in order to perform a diagnostic loopback test. */ static int -lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) +lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -2194,7 +2194,7 @@ job_error: * command from the user to proper driver action routines. */ static int -lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) +lpfc_bsg_diag_loopback_mode(struct bsg_job *job) { struct Scsi_Host *shost; struct lpfc_vport *vport; @@ -2230,7 +2230,7 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) * command from the user to proper driver action routines. */ static int -lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) +lpfc_sli4_bsg_diag_mode_end(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -2309,7 +2309,7 @@ loopback_mode_end_exit: * applicaiton. */ static int -lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) +lpfc_sli4_bsg_link_diag_test(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -3016,7 +3016,7 @@ err_post_rxbufs_exit: * of loopback mode. **/ static int -lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) +lpfc_bsg_diag_loopback_run(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_reply *bsg_reply = job->reply; @@ -3320,7 +3320,7 @@ loopback_test_exit: * @job: GET_DFC_REV fc_bsg_job **/ static int -lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job) +lpfc_bsg_get_dfc_rev(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_reply *bsg_reply = job->reply; @@ -3375,7 +3375,7 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { struct bsg_job_data *dd_data; struct fc_bsg_reply *bsg_reply; - struct fc_bsg_job *job; + struct bsg_job *job; uint32_t size; unsigned long flags; uint8_t *pmb, *pmb_buf; @@ -3551,11 +3551,11 @@ lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba) * This is routine handles BSG job for mailbox commands completions with * multiple external buffers. **/ -static struct fc_bsg_job * +static struct bsg_job * lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { struct bsg_job_data *dd_data; - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; uint8_t *pmb, *pmb_buf; unsigned long flags; @@ -3646,7 +3646,7 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) static void lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); @@ -3686,7 +3686,7 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) static void lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); @@ -3818,7 +3818,7 @@ lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp, * non-embedded external bufffers. **/ static int -lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job, enum nemb_type nemb_tp, struct lpfc_dmabuf *dmabuf) { @@ -4006,7 +4006,7 @@ job_error: * non-embedded external bufffers. **/ static int -lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job, enum nemb_type nemb_tp, struct lpfc_dmabuf *dmabuf) { @@ -4173,7 +4173,7 @@ job_error: * with embedded sussystem 0x1 and opcodes with external HBDs. **/ static int -lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct bsg_job *job, struct lpfc_dmabuf *dmabuf) { struct lpfc_sli_config_mbox *sli_cfg_mbx; @@ -4322,7 +4322,7 @@ lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba) * user space through BSG. **/ static int -lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) +lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct bsg_job *job) { struct fc_bsg_reply *bsg_reply = job->reply; struct lpfc_sli_config_mbox *sli_cfg_mbx; @@ -4392,7 +4392,7 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) * from user space through BSG. **/ static int -lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job, struct lpfc_dmabuf *dmabuf) { struct fc_bsg_reply *bsg_reply = job->reply; @@ -4515,7 +4515,7 @@ job_error: * command with multiple non-embedded external buffers. **/ static int -lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct bsg_job *job, struct lpfc_dmabuf *dmabuf) { int rc; @@ -4560,7 +4560,7 @@ lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job, * (0x9B) mailbox commands and external buffers. **/ static int -lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct bsg_job *job, struct lpfc_dmabuf *dmabuf) { struct fc_bsg_request *bsg_request = job->request; @@ -4638,7 +4638,7 @@ sli_cfg_ext_error: * let our completion handler finish the command. **/ static int -lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, +lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct bsg_job *job, struct lpfc_vport *vport) { struct fc_bsg_request *bsg_request = job->request; @@ -4931,7 +4931,7 @@ job_cont: * @job: MBOX fc_bsg_job for LPFC_BSG_VENDOR_MBOX. **/ static int -lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) +lpfc_bsg_mbox_cmd(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_request *bsg_request = job->request; @@ -5000,7 +5000,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *rspiocbq) { struct bsg_job_data *dd_data; - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_bsg_reply *bsg_reply; IOCB_t *rsp; struct lpfc_dmabuf *bmp, *cmp, *rmp; @@ -5091,7 +5091,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, * supplied in the menlo request header xri field. **/ static int -lpfc_menlo_cmd(struct fc_bsg_job *job) +lpfc_menlo_cmd(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct fc_bsg_request *bsg_request = job->request; @@ -5255,7 +5255,7 @@ no_dd_data: } static int -lpfc_forced_link_speed(struct fc_bsg_job *job) +lpfc_forced_link_speed(struct bsg_job *job) { struct Scsi_Host *shost = fc_bsg_to_shost(job); struct lpfc_vport *vport = shost_priv(shost); @@ -5303,7 +5303,7 @@ job_error: * @job: fc_bsg_job to handle **/ static int -lpfc_bsg_hst_vendor(struct fc_bsg_job *job) +lpfc_bsg_hst_vendor(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -5361,7 +5361,7 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) * @job: fc_bsg_job to handle **/ int -lpfc_bsg_request(struct fc_bsg_job *job) +lpfc_bsg_request(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; @@ -5398,7 +5398,7 @@ lpfc_bsg_request(struct fc_bsg_job *job) * the waiting function which will handle passing the error back to userspace **/ int -lpfc_bsg_timeout(struct fc_bsg_job *job) +lpfc_bsg_timeout(struct bsg_job *job) { struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job)); struct lpfc_hba *phba = vport->phba; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 16195b73a536..15d2bfdf582d 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -429,8 +429,8 @@ struct lpfc_sglq *__lpfc_get_active_sglq(struct lpfc_hba *, uint16_t); #define HBA_EVENT_LINK_DOWN 3 /* functions to support SGIOv4/bsg interface */ -int lpfc_bsg_request(struct fc_bsg_job *); -int lpfc_bsg_timeout(struct fc_bsg_job *); +int lpfc_bsg_request(struct bsg_job *); +int lpfc_bsg_timeout(struct bsg_job *); int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); int lpfc_bsg_ct_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *); diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 917eafecc435..342e8a3d8c3b 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -9,6 +9,7 @@ #include #include #include +#include /* BSG support for ELS/CT pass through */ void @@ -16,7 +17,7 @@ qla2x00_bsg_job_done(void *data, void *ptr, int res) { srb_t *sp = (srb_t *)ptr; struct scsi_qla_host *vha = (scsi_qla_host_t *)data; - struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct bsg_job *bsg_job = sp->u.bsg_job; struct fc_bsg_reply *bsg_reply = bsg_job->reply; bsg_reply->result = res; @@ -30,7 +31,7 @@ qla2x00_bsg_sp_free(void *data, void *ptr) { srb_t *sp = (srb_t *)ptr; struct scsi_qla_host *vha = sp->fcport->vha; - struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct bsg_job *bsg_job = sp->u.bsg_job; struct fc_bsg_request *bsg_request = bsg_job->request; struct qla_hw_data *ha = vha->hw; @@ -120,7 +121,7 @@ qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha, } static int -qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) +qla24xx_proc_fcp_prio_cfg_cmd(struct bsg_job *bsg_job) { struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); struct fc_bsg_request *bsg_request = bsg_job->request; @@ -249,7 +250,7 @@ exit_fcp_prio_cfg: } static int -qla2x00_process_els(struct fc_bsg_job *bsg_job) +qla2x00_process_els(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_rport *rport; @@ -428,7 +429,7 @@ qla24xx_calc_ct_iocbs(uint16_t dsds) } static int -qla2x00_process_ct(struct fc_bsg_job *bsg_job) +qla2x00_process_ct(struct bsg_job *bsg_job) { srb_t *sp; struct fc_bsg_request *bsg_request = bsg_job->request; @@ -706,7 +707,7 @@ done_set_internal: } static int -qla2x00_process_loopback(struct fc_bsg_job *bsg_job) +qla2x00_process_loopback(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -947,7 +948,7 @@ done_unmap_req_sg: } static int -qla84xx_reset(struct fc_bsg_job *bsg_job) +qla84xx_reset(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -983,7 +984,7 @@ qla84xx_reset(struct fc_bsg_job *bsg_job) } static int -qla84xx_updatefw(struct fc_bsg_job *bsg_job) +qla84xx_updatefw(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -1095,7 +1096,7 @@ done_unmap_sg: } static int -qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) +qla84xx_mgmt_cmd(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -1293,7 +1294,7 @@ exit_mgmt: } static int -qla24xx_iidma(struct fc_bsg_job *bsg_job) +qla24xx_iidma(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -1382,7 +1383,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) } static int -qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha, +qla2x00_optrom_setup(struct bsg_job *bsg_job, scsi_qla_host_t *vha, uint8_t is_update) { struct fc_bsg_request *bsg_request = bsg_job->request; @@ -1452,7 +1453,7 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha, } static int -qla2x00_read_optrom(struct fc_bsg_job *bsg_job) +qla2x00_read_optrom(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1489,7 +1490,7 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job) } static int -qla2x00_update_optrom(struct fc_bsg_job *bsg_job) +qla2x00_update_optrom(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1525,7 +1526,7 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job) } static int -qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job) +qla2x00_update_fru_versions(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1577,7 +1578,7 @@ done: } static int -qla2x00_read_fru_status(struct fc_bsg_job *bsg_job) +qla2x00_read_fru_status(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1627,7 +1628,7 @@ done: } static int -qla2x00_write_fru_status(struct fc_bsg_job *bsg_job) +qla2x00_write_fru_status(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1673,7 +1674,7 @@ done: } static int -qla2x00_write_i2c(struct fc_bsg_job *bsg_job) +qla2x00_write_i2c(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1718,7 +1719,7 @@ done: } static int -qla2x00_read_i2c(struct fc_bsg_job *bsg_job) +qla2x00_read_i2c(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1767,7 +1768,7 @@ done: } static int -qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) +qla24xx_process_bidir_cmd(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -1946,7 +1947,7 @@ done: } static int -qlafx00_mgmt_cmd(struct fc_bsg_job *bsg_job) +qlafx00_mgmt_cmd(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2069,7 +2070,7 @@ done: } static int -qla26xx_serdes_op(struct fc_bsg_job *bsg_job) +qla26xx_serdes_op(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2111,7 +2112,7 @@ qla26xx_serdes_op(struct fc_bsg_job *bsg_job) } static int -qla8044_serdes_op(struct fc_bsg_job *bsg_job) +qla8044_serdes_op(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2153,7 +2154,7 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job) } static int -qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) +qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2185,7 +2186,7 @@ qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) } static int -qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) +qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2231,7 +2232,7 @@ qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) } static int -qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job) +qla27xx_get_bbcr_data(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2290,7 +2291,7 @@ done: } static int -qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) +qla2x00_get_priv_stats(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -2351,7 +2352,7 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) } static int -qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) +qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); @@ -2394,7 +2395,7 @@ qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job) } static int -qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) +qla2x00_process_vendor_specific(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; @@ -2472,7 +2473,7 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) } int -qla24xx_bsg_request(struct fc_bsg_job *bsg_job) +qla24xx_bsg_request(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -2525,7 +2526,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) } int -qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) +qla24xx_bsg_timeout(struct bsg_job *bsg_job) { struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 73b12e41d992..5236e3f2a06a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -403,7 +403,7 @@ typedef struct srb { int iocbs; union { struct srb_iocb iocb_cmd; - struct fc_bsg_job *bsg_job; + struct bsg_job *bsg_job; struct srb_cmd scmd; } u; void (*done)(void *, void *, int); diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 6ca00813c71f..c51d9f3359e3 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -733,8 +733,8 @@ extern int qla82xx_read_temperature(scsi_qla_host_t *); extern int qla8044_read_temperature(scsi_qla_host_t *); /* BSG related functions */ -extern int qla24xx_bsg_request(struct fc_bsg_job *); -extern int qla24xx_bsg_timeout(struct fc_bsg_job *); +extern int qla24xx_bsg_request(struct bsg_job *); +extern int qla24xx_bsg_timeout(struct bsg_job *); extern int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t); extern int qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t, uint32_t); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 6929fda544a0..221ad8907893 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2197,7 +2197,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) static void qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { - struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct bsg_job *bsg_job = sp->u.bsg_job; struct fc_bsg_request *bsg_request = bsg_job->request; els_iocb->entry_type = ELS_IOCB_TYPE; @@ -2251,7 +2251,7 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) uint16_t tot_dsds; scsi_qla_host_t *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; - struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct bsg_job *bsg_job = sp->u.bsg_job; int loop_iterartion = 0; int entry_count = 1; @@ -2328,7 +2328,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) uint16_t tot_dsds; scsi_qla_host_t *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; - struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct bsg_job *bsg_job = sp->u.bsg_job; int loop_iterartion = 0; int entry_count = 1; @@ -2834,7 +2834,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, struct scatterlist *sg; int index; int entry_count = 1; - struct fc_bsg_job *bsg_job = sp->u.bsg_job; + struct bsg_job *bsg_job = sp->u.bsg_job; /*Update entry type to indicate bidir command */ *((uint32_t *)(&cmd_pkt->entry_type)) = diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d83e08312af2..19f18485a854 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1356,7 +1356,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, const char func[] = "CT_IOCB"; const char *type; srb_t *sp; - struct fc_bsg_job *bsg_job; + struct bsg_job *bsg_job; struct fc_bsg_reply *bsg_reply; uint16_t comp_status; int res; @@ -1415,7 +1415,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, const char func[] = "ELS_CT_IOCB"; const char *type; srb_t *sp; - struct fc_bsg_job *bsg_job; + struct bsg_job *bsg_job; struct fc_bsg_reply *bsg_reply; uint16_t comp_status; uint32_t fw_status[3]; @@ -1908,7 +1908,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, uint16_t scsi_status; uint16_t thread_id; uint32_t rval = EXT_STATUS_OK; - struct fc_bsg_job *bsg_job = NULL; + struct bsg_job *bsg_job = NULL; struct fc_bsg_request *bsg_request; struct fc_bsg_reply *bsg_reply; sts_entry_t *sts; diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index b597d04f654e..02f1de18bc2b 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -2206,7 +2207,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, { const char func[] = "IOSB_IOCB"; srb_t *sp; - struct fc_bsg_job *bsg_job; + struct bsg_job *bsg_job; struct fc_bsg_reply *bsg_reply; struct srb_iocb *iocb_job; int res; @@ -3254,7 +3255,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) { struct srb_iocb *fxio = &sp->u.iocb_cmd; struct qla_mt_iocb_rqst_fx00 *piocb_rqst; - struct fc_bsg_job *bsg_job; + struct bsg_job *bsg_job; struct fc_bsg_request *bsg_request; struct fxdisc_entry_fx00 fx_iocb; uint8_t entry_cnt = 1; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 9009acc27aed..bb705e02374c 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3562,7 +3562,7 @@ fc_vport_sched_delete(struct work_struct *work) static void fc_destroy_bsgjob(struct kref *kref) { - struct fc_bsg_job *job = container_of(kref, struct fc_bsg_job, kref); + struct bsg_job *job = container_of(kref, struct bsg_job, kref); struct request *rq = job->req; blk_end_request_all(rq, rq->errors); @@ -3581,7 +3581,7 @@ fc_destroy_bsgjob(struct kref *kref) * @result: job reply result * @reply_payload_rcv_len: length of payload received */ -void fc_bsg_jobdone(struct fc_bsg_job *job, int result, +void fc_bsg_jobdone(struct bsg_job *job, int result, unsigned int reply_payload_rcv_len) { struct request *req = job->req; @@ -3615,7 +3615,7 @@ EXPORT_SYMBOL_GPL(fc_bsg_jobdone); */ static void fc_bsg_softirq_done(struct request *rq) { - struct fc_bsg_job *job = rq->special; + struct bsg_job *job = rq->special; kref_put(&job->kref, fc_destroy_bsgjob); } @@ -3627,7 +3627,7 @@ static void fc_bsg_softirq_done(struct request *rq) static enum blk_eh_timer_return fc_bsg_job_timeout(struct request *req) { - struct fc_bsg_job *job = (void *) req->special; + struct bsg_job *job = (void *) req->special; struct Scsi_Host *shost = fc_bsg_to_shost(job); struct fc_rport *rport = fc_bsg_to_rport(job); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -3686,12 +3686,12 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport, { struct fc_internal *i = to_fc_internal(shost->transportt); struct request *rsp = req->next_rq; - struct fc_bsg_job *job; + struct bsg_job *job; int ret; BUG_ON(req->special); - job = kzalloc(sizeof(struct fc_bsg_job) + i->f->dd_bsg_size, + job = kzalloc(sizeof(struct bsg_job) + i->f->dd_bsg_size, GFP_KERNEL); if (!job) return -ENOMEM; @@ -3706,8 +3706,6 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport, */ req->special = job; - job->shost = shost; - job->rport = rport; job->req = req; if (i->f->dd_bsg_size) job->dd_data = (void *)&job[1]; @@ -3760,7 +3758,7 @@ enum fc_dispatch_result { */ static enum fc_dispatch_result fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, - struct fc_bsg_job *job) + struct bsg_job *job) { struct fc_internal *i = to_fc_internal(shost->transportt); struct fc_bsg_request *bsg_request = job->request; @@ -3862,7 +3860,7 @@ fc_bsg_goose_queue(struct fc_rport *rport) */ static enum fc_dispatch_result fc_bsg_rport_dispatch(struct request_queue *q, struct Scsi_Host *shost, - struct fc_rport *rport, struct fc_bsg_job *job) + struct fc_rport *rport, struct bsg_job *job) { struct fc_internal *i = to_fc_internal(shost->transportt); struct fc_bsg_request *bsg_request = job->request; @@ -3925,7 +3923,7 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, struct fc_rport *rport, struct device *dev) { struct request *req; - struct fc_bsg_job *job; + struct bsg_job *job; enum fc_dispatch_result ret; struct fc_bsg_reply *bsg_reply; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 6f81b28364da..96dd0b3f70d7 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -912,7 +912,7 @@ void fc_lport_recv(struct fc_lport *lport, struct fc_frame *fp); int fc_set_mfs(struct fc_lport *, u32 mfs); struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); -int fc_lport_bsg_request(struct fc_bsg_job *); +int fc_lport_bsg_request(struct bsg_job *); void fc_lport_set_local_id(struct fc_lport *, u32 port_id); void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 8ae5680f2216..1da8b719abae 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -32,6 +32,7 @@ #include #include #include +#include struct scsi_transport_template; @@ -625,38 +626,6 @@ struct fc_host_attrs { #define fc_host_dev_loss_tmo(x) \ (((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo) -/* Values for fc_bsg_job->state_flags (bitflags) */ -#define FC_RQST_STATE_INPROGRESS 0 -#define FC_RQST_STATE_DONE 1 - -struct fc_bsg_job { - struct Scsi_Host *shost; - struct fc_rport *rport; - struct device *dev; - struct request *req; - struct kref kref; - - struct fc_bsg_request *request; - struct fc_bsg_reply *reply; - unsigned int request_len; - unsigned int reply_len; - /* - * On entry : reply_len indicates the buffer size allocated for - * the reply. - * - * Upon completion : the message handler must set reply_len - * to indicates the size of the reply to be returned to the - * caller. - */ - - /* DMA payloads for the request/response */ - struct bsg_buffer request_payload; - struct bsg_buffer reply_payload; - - void *dd_data; /* Used for driver-specific storage */ -}; - - /* The functions by which the transport class and the driver communicate */ struct fc_function_template { void (*get_rport_dev_loss_tmo)(struct fc_rport *); @@ -693,8 +662,8 @@ struct fc_function_template { int (* it_nexus_response)(struct Scsi_Host *, u64, int); /* bsg support */ - int (*bsg_request)(struct fc_bsg_job *); - int (*bsg_timeout)(struct fc_bsg_job *); + int (*bsg_request)(struct bsg_job *); + int (*bsg_timeout)(struct bsg_job *); /* allocation lengths for host-specific data */ u32 dd_fcrport_size; @@ -817,16 +786,6 @@ fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state) vport->vport_state = new_state; } -static inline struct Scsi_Host *fc_bsg_to_shost(struct fc_bsg_job *job) -{ - return job->shost; -} - -static inline struct fc_rport *fc_bsg_to_rport(struct fc_bsg_job *job) -{ - return job->rport; -} - struct scsi_transport_template *fc_attach_transport( struct fc_function_template *); void fc_release_transport(struct scsi_transport_template *); @@ -849,7 +808,21 @@ struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, struct fc_vport_identifiers *); int fc_vport_terminate(struct fc_vport *vport); int fc_block_scsi_eh(struct scsi_cmnd *cmnd); -void fc_bsg_jobdone(struct fc_bsg_job *job, int result, +void fc_bsg_jobdone(struct bsg_job *job, int result, unsigned int reply_payload_rcv_len); +static inline struct Scsi_Host *fc_bsg_to_shost(struct bsg_job *job) +{ + if (scsi_is_host_device(job->dev)) + return dev_to_shost(job->dev); + return rport_to_shost(dev_to_rport(job->dev)); +} + +static inline struct fc_rport *fc_bsg_to_rport(struct bsg_job *job) +{ + if (scsi_is_fc_rport(job->dev)) + return dev_to_rport(job->dev); + return NULL; +} + #endif /* SCSI_TRANSPORT_FC_H */ From c00da4c90ffd066cdfe7f53ff3529c8ab4a35db0 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:20 +0100 Subject: [PATCH 184/256] scsi: fc: Use bsg_destroy_job fc_destroy_bsgjob() and bsg_destroy_job() are now 1:1 copies, so use the latter. As bsg_destroy_job() comes from bsg-lib we need to select it in Kconfig once CONFOG_SCSI_FC_ATTRS is active. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- block/bsg-lib.c | 7 +++++-- drivers/scsi/Kconfig | 1 + drivers/scsi/scsi_transport_fc.c | 25 +++---------------------- include/linux/bsg-lib.h | 1 + 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/block/bsg-lib.c b/block/bsg-lib.c index 632fb4006c40..9f1e8fde924a 100644 --- a/block/bsg-lib.c +++ b/block/bsg-lib.c @@ -32,9 +32,12 @@ * bsg_destroy_job - routine to teardown/delete a bsg job * @job: bsg_job that is to be torn down */ -static void bsg_destroy_job(struct kref *kref) +void bsg_destroy_job(struct kref *kref) { struct bsg_job *job = container_of(kref, struct bsg_job, kref); + struct request *rq = job->req; + + blk_end_request_all(rq, rq->errors); put_device(job->dev); /* release reference for the request */ @@ -42,6 +45,7 @@ static void bsg_destroy_job(struct kref *kref) kfree(job->reply_payload.sg_list); kfree(job); } +EXPORT_SYMBOL_GPL(bsg_destroy_job); /** * bsg_job_done - completion routine for bsg requests @@ -85,7 +89,6 @@ static void bsg_softirq_done(struct request *rq) { struct bsg_job *job = rq->special; - blk_end_request_all(rq, rq->errors); kref_put(&job->kref, bsg_destroy_job); } diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3b416c9efe5e..dfa93347c752 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -263,6 +263,7 @@ config SCSI_SPI_ATTRS config SCSI_FC_ATTRS tristate "FiberChannel Transport Attributes" depends on SCSI && NET + select BLK_DEV_BSGLIB select SCSI_NETLINK help If you wish to export transport-specific information about diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index bb705e02374c..616c7e1cbab2 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -3554,26 +3555,6 @@ fc_vport_sched_delete(struct work_struct *work) * BSG support */ - -/** - * fc_destroy_bsgjob - routine to teardown/delete a fc bsg job - * @job: fc_bsg_job that is to be torn down - */ -static void -fc_destroy_bsgjob(struct kref *kref) -{ - struct bsg_job *job = container_of(kref, struct bsg_job, kref); - struct request *rq = job->req; - - blk_end_request_all(rq, rq->errors); - - put_device(job->dev); /* release reference for the request */ - - kfree(job->request_payload.sg_list); - kfree(job->reply_payload.sg_list); - kfree(job); -} - /** * fc_bsg_jobdone - completion routine for bsg requests that the LLD has * completed @@ -3617,7 +3598,7 @@ static void fc_bsg_softirq_done(struct request *rq) { struct bsg_job *job = rq->special; - kref_put(&job->kref, fc_destroy_bsgjob); + kref_put(&job->kref, bsg_destroy_job); } /** @@ -3642,7 +3623,7 @@ fc_bsg_job_timeout(struct request *req) /* call LLDD to abort the i/o as it has timed out */ err = i->f->bsg_timeout(job); if (err == -EAGAIN) { - kref_put(&job->kref, fc_destroy_bsgjob); + kref_put(&job->kref, bsg_destroy_job); return BLK_EH_RESET_TIMER; } else if (err) printk(KERN_ERR "ERROR: FC BSG request timeout - LLD " diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h index 58e0717fda6e..67f7de6146c9 100644 --- a/include/linux/bsg-lib.h +++ b/include/linux/bsg-lib.h @@ -69,5 +69,6 @@ void bsg_job_done(struct bsg_job *job, int result, int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name, bsg_job_fn *job_fn, int dd_job_size); void bsg_request_fn(struct request_queue *q); +void bsg_destroy_job(struct kref *kref); #endif From 6aa858cd335a94e2824ed542140ac9704c0a64e2 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:21 +0100 Subject: [PATCH 185/256] scsi: fc: use bsg_softirq_done bsg_softirq_done() and fc_bsg_softirq_done() are copies of each other, so ditch the fc specific one. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- block/bsg-lib.c | 3 ++- drivers/scsi/scsi_transport_fc.c | 15 ++------------- include/linux/bsg-lib.h | 1 + 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/block/bsg-lib.c b/block/bsg-lib.c index 9f1e8fde924a..6661f823db4c 100644 --- a/block/bsg-lib.c +++ b/block/bsg-lib.c @@ -85,12 +85,13 @@ EXPORT_SYMBOL_GPL(bsg_job_done); * bsg_softirq_done - softirq done routine for destroying the bsg requests * @rq: BSG request that holds the job to be destroyed */ -static void bsg_softirq_done(struct request *rq) +void bsg_softirq_done(struct request *rq) { struct bsg_job *job = rq->special; kref_put(&job->kref, bsg_destroy_job); } +EXPORT_SYMBOL_GPL(bsg_softirq_done); static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 616c7e1cbab2..1d959ae7d0c8 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3590,17 +3590,6 @@ void fc_bsg_jobdone(struct bsg_job *job, int result, } EXPORT_SYMBOL_GPL(fc_bsg_jobdone); -/** - * fc_bsg_softirq_done - softirq done routine for destroying the bsg requests - * @rq: BSG request that holds the job to be destroyed - */ -static void fc_bsg_softirq_done(struct request *rq) -{ - struct bsg_job *job = rq->special; - - kref_put(&job->kref, bsg_destroy_job); -} - /** * fc_bsg_job_timeout - handler for when a bsg request timesout * @req: request that timed out @@ -4033,7 +4022,7 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host) q->queuedata = shost; queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); - blk_queue_softirq_done(q, fc_bsg_softirq_done); + blk_queue_softirq_done(q, bsg_softirq_done); blk_queue_rq_timed_out(q, fc_bsg_job_timeout); blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT); @@ -4079,7 +4068,7 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport) q->queuedata = rport; queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); - blk_queue_softirq_done(q, fc_bsg_softirq_done); + blk_queue_softirq_done(q, bsg_softirq_done); blk_queue_rq_timed_out(q, fc_bsg_job_timeout); blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT); diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h index 67f7de6146c9..09f304437cd6 100644 --- a/include/linux/bsg-lib.h +++ b/include/linux/bsg-lib.h @@ -70,5 +70,6 @@ int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name, bsg_job_fn *job_fn, int dd_job_size); void bsg_request_fn(struct request_queue *q); void bsg_destroy_job(struct kref *kref); +void bsg_softirq_done(struct request *rq); #endif From 06548160dfecd1983ffd9d6795242a5cda095da5 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:22 +0100 Subject: [PATCH 186/256] scsi: fc: use bsg_job_done fc_bsg_jobdone() and bsg_job_done() are 1:1 copies now so use the bsg-lib one instead of the FC private implementation. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fc.c | 2 +- drivers/scsi/bfa/bfad_bsg.c | 4 +-- drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- drivers/scsi/libfc/fc_lport.c | 4 +-- drivers/scsi/lpfc/lpfc_bsg.c | 40 ++++++++++++++--------------- drivers/scsi/qla2xxx/qla_bsg.c | 44 ++++++++++++++++---------------- drivers/scsi/scsi_transport_fc.c | 41 +++-------------------------- include/scsi/scsi_transport_fc.h | 2 -- 8 files changed, 51 insertions(+), 88 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index f01b9a45d82e..7331eea67435 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -893,7 +893,7 @@ static void zfcp_fc_ct_els_job_handler(void *data) jr->reply_payload_rcv_len = job->reply_payload.payload_len; jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; jr->result = zfcp_ct_els->status ? -EIO : 0; - fc_bsg_jobdone(job, jr->result, jr->reply_payload_rcv_len); + bsg_job_done(job, jr->result, jr->reply_payload_rcv_len); } static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct bsg_job *job) diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index cdc25e6572a4..a9a00169ad91 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3179,7 +3179,7 @@ bfad_im_bsg_vendor_request(struct bsg_job *job) bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; bsg_reply->result = rc; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; error: @@ -3555,7 +3555,7 @@ out: bsg_reply->result = rc; if (rc == BFA_STATUS_OK) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index f59b0a1e205e..78b72c28a55d 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1946,7 +1946,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) ibmvfc_free_event(evt); spin_unlock_irqrestore(vhost->host->host_lock, flags); bsg_reply->result = rc; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); rc = 0; out: diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index c428ce389a5b..2be7015498fd 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1912,7 +1912,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); return; @@ -1947,7 +1947,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); } diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index b19ad9e45702..7dca4d6a8883 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -371,7 +371,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } return; @@ -645,7 +645,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } return; @@ -1138,7 +1138,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, job->dd_data = NULL; /* complete the job back to userspace */ spin_unlock_irqrestore(&phba->ct_ev_lock, flags); - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); spin_lock_irqsave(&phba->ct_ev_lock, flags); } @@ -1364,7 +1364,7 @@ lpfc_bsg_hba_get_event(struct bsg_job *job) spin_unlock_irqrestore(&phba->ct_ev_lock, flags); job->dd_data = NULL; bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; @@ -1462,7 +1462,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } return; @@ -1891,7 +1891,7 @@ job_error: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } @@ -2181,7 +2181,7 @@ job_error: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } @@ -2296,7 +2296,7 @@ loopback_mode_end_exit: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } @@ -2449,7 +2449,7 @@ job_error: bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } @@ -3310,7 +3310,7 @@ loopback_test_exit: job->dd_data = NULL; /* complete the job back to userspace if no error */ if (rc == IOCB_SUCCESS) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } @@ -3354,7 +3354,7 @@ lpfc_bsg_get_dfc_rev(struct bsg_job *job) job_error: bsg_reply->result = rc; if (rc == 0) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } @@ -3420,7 +3420,7 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) if (job) { bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } return; @@ -3669,7 +3669,7 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /* if the job is still active, call job done */ if (job) { bsg_reply = job->reply; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } return; @@ -3707,7 +3707,7 @@ lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /* if the job is still active, call job done */ if (job) { bsg_reply = job->reply; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } @@ -4150,7 +4150,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job, /* wait for additoinal external buffers */ bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return SLI_CONFIG_HANDLED; @@ -4377,7 +4377,7 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct bsg_job *job) } bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return SLI_CONFIG_HANDLED; @@ -4494,7 +4494,7 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job, /* wait for additoinal external buffers */ bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return SLI_CONFIG_HANDLED; @@ -4963,7 +4963,7 @@ lpfc_bsg_mbox_cmd(struct bsg_job *job) /* job done */ bsg_reply->result = 0; job->dd_data = NULL; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } else if (rc == 1) /* job submitted, will complete later*/ @@ -5074,7 +5074,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, if (job) { bsg_reply->result = rc; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } @@ -5293,7 +5293,7 @@ lpfc_forced_link_speed(struct bsg_job *job) job_error: bsg_reply->result = rc; if (rc == 0) - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rc; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 342e8a3d8c3b..1bf8061ff803 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -21,7 +21,7 @@ qla2x00_bsg_job_done(void *data, void *ptr, int res) struct fc_bsg_reply *bsg_reply = bsg_job->reply; bsg_reply->result = res; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); sp->free(vha, sp); } @@ -244,7 +244,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct bsg_job *bsg_job) } exit_fcp_prio_cfg: if (!ret) - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return ret; } @@ -942,7 +942,7 @@ done_unmap_req_sg: bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); if (!rval) - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rval; } @@ -976,7 +976,7 @@ qla84xx_reset(struct bsg_job *bsg_job) ql_dbg(ql_dbg_user, vha, 0x7031, "Vendor request 84xx reset completed.\n"); bsg_reply->result = DID_OK; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } @@ -1090,7 +1090,7 @@ done_unmap_sg: bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); if (!rval) - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rval; } @@ -1288,7 +1288,7 @@ exit_mgmt: dma_pool_free(ha->s_dma_pool, mn, mn_dma); if (!rval) - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rval; } @@ -1375,7 +1375,7 @@ qla24xx_iidma(struct bsg_job *bsg_job) } bsg_reply->result = DID_OK; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); } @@ -1484,7 +1484,7 @@ qla2x00_read_optrom(struct bsg_job *bsg_job) ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; mutex_unlock(&ha->optrom_mutex); - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rval; } @@ -1520,7 +1520,7 @@ qla2x00_update_optrom(struct bsg_job *bsg_job) ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; mutex_unlock(&ha->optrom_mutex); - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return rval; } @@ -1571,7 +1571,7 @@ dealloc: done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; @@ -1621,7 +1621,7 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = sizeof(*sr); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; @@ -1667,7 +1667,7 @@ dealloc: done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; @@ -1712,7 +1712,7 @@ dealloc: done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; @@ -1761,7 +1761,7 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = sizeof(*i2c); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; @@ -1940,7 +1940,7 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = (DID_OK) << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); /* Always return success, vendor rsp carries correct status */ return 0; @@ -2106,7 +2106,7 @@ qla26xx_serdes_op(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; } @@ -2148,7 +2148,7 @@ qla8044_serdes_op(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; } @@ -2180,7 +2180,7 @@ qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; } @@ -2226,7 +2226,7 @@ qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; } @@ -2285,7 +2285,7 @@ done: bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return 0; } @@ -2342,7 +2342,7 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(*bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); dma_free_coherent(&ha->pdev->dev, sizeof(*stats), @@ -2386,7 +2386,7 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(*bsg_reply); bsg_reply->result = DID_OK << 16; - fc_bsg_jobdone(bsg_job, bsg_reply->result, + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(dd); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 1d959ae7d0c8..ee1e812bad4c 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3555,41 +3555,6 @@ fc_vport_sched_delete(struct work_struct *work) * BSG support */ -/** - * fc_bsg_jobdone - completion routine for bsg requests that the LLD has - * completed - * @job: fc_bsg_job that is complete - * @result: job reply result - * @reply_payload_rcv_len: length of payload received - */ -void fc_bsg_jobdone(struct bsg_job *job, int result, - unsigned int reply_payload_rcv_len) -{ - struct request *req = job->req; - struct request *rsp = req->next_rq; - int err; - - err = job->req->errors = result; - - if (err < 0) - /* we're only returning the result field in the reply */ - job->req->sense_len = sizeof(uint32_t); - else - job->req->sense_len = job->reply_len; - - /* we assume all request payload was transferred, residual == 0 */ - req->resid_len = 0; - - if (rsp) { - WARN_ON(reply_payload_rcv_len > rsp->resid_len); - - /* set reply (bidi) residual */ - rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len); - } - blk_complete_request(req); -} -EXPORT_SYMBOL_GPL(fc_bsg_jobdone); - /** * fc_bsg_job_timeout - handler for when a bsg request timesout * @req: request that timed out @@ -3797,7 +3762,7 @@ fail_host_msg: bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = ret; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return FC_DISPATCH_UNLOCKED; } @@ -3875,7 +3840,7 @@ fail_rport_msg: bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = ret; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); return FC_DISPATCH_UNLOCKED; } @@ -3936,7 +3901,7 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, bsg_reply->reply_payload_rcv_len = 0; bsg_reply->result = -ENOMSG; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); spin_lock_irq(q->queue_lock); continue; diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 1da8b719abae..924c8e614b45 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -808,8 +808,6 @@ struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, struct fc_vport_identifiers *); int fc_vport_terminate(struct fc_vport *vport); int fc_block_scsi_eh(struct scsi_cmnd *cmnd); -void fc_bsg_jobdone(struct bsg_job *job, int result, - unsigned int reply_payload_rcv_len); static inline struct Scsi_Host *fc_bsg_to_shost(struct bsg_job *job) { From fb6f7c8d8a19e5543d5b4d44c58e2c4e5a82bb12 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:23 +0100 Subject: [PATCH 187/256] block: add bsg_job_put() and bsg_job_get() Add bsg_job_put() and bsg_job_get() so don't need to export bsg_destroy_job() any more. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- block/bsg-lib.c | 17 ++++++++++++++--- drivers/scsi/scsi_transport_fc.c | 4 ++-- include/linux/bsg-lib.h | 3 ++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/block/bsg-lib.c b/block/bsg-lib.c index 6661f823db4c..803ec40ebd6d 100644 --- a/block/bsg-lib.c +++ b/block/bsg-lib.c @@ -32,7 +32,7 @@ * bsg_destroy_job - routine to teardown/delete a bsg job * @job: bsg_job that is to be torn down */ -void bsg_destroy_job(struct kref *kref) +static void bsg_destroy_job(struct kref *kref) { struct bsg_job *job = container_of(kref, struct bsg_job, kref); struct request *rq = job->req; @@ -45,7 +45,18 @@ void bsg_destroy_job(struct kref *kref) kfree(job->reply_payload.sg_list); kfree(job); } -EXPORT_SYMBOL_GPL(bsg_destroy_job); + +void bsg_job_put(struct bsg_job *job) +{ + kref_put(&job->kref, bsg_destroy_job); +} +EXPORT_SYMBOL_GPL(bsg_job_put); + +int bsg_job_get(struct bsg_job *job) +{ + return kref_get_unless_zero(&job->kref); +} +EXPORT_SYMBOL_GPL(bsg_job_get); /** * bsg_job_done - completion routine for bsg requests @@ -89,7 +100,7 @@ void bsg_softirq_done(struct request *rq) { struct bsg_job *job = rq->special; - kref_put(&job->kref, bsg_destroy_job); + bsg_job_put(job); } EXPORT_SYMBOL_GPL(bsg_softirq_done); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index ee1e812bad4c..23e1eed932b5 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3571,13 +3571,13 @@ fc_bsg_job_timeout(struct request *req) if (rport && rport->port_state == FC_PORTSTATE_BLOCKED) return BLK_EH_RESET_TIMER; - inflight = kref_get_unless_zero(&job->kref); + inflight = bsg_job_get(job); if (inflight && i->f->bsg_timeout) { /* call LLDD to abort the i/o as it has timed out */ err = i->f->bsg_timeout(job); if (err == -EAGAIN) { - kref_put(&job->kref, bsg_destroy_job); + bsg_job_put(job); return BLK_EH_RESET_TIMER; } else if (err) printk(KERN_ERR "ERROR: FC BSG request timeout - LLD " diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h index 09f304437cd6..b708db91618f 100644 --- a/include/linux/bsg-lib.h +++ b/include/linux/bsg-lib.h @@ -69,7 +69,8 @@ void bsg_job_done(struct bsg_job *job, int result, int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name, bsg_job_fn *job_fn, int dd_job_size); void bsg_request_fn(struct request_queue *q); -void bsg_destroy_job(struct kref *kref); void bsg_softirq_done(struct request *rq); +void bsg_job_put(struct bsg_job *job); +int __must_check bsg_job_get(struct bsg_job *job); #endif From a0f4bd7f2a5be485747aa438cea38f69e3ae8962 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:24 +0100 Subject: [PATCH 188/256] scsi: fc: move FC transport's bsg code to bsg-lib Now that all conversions are done, move the FibreChannel bsg code over to the bsg library. This patch is derived from work done by Mike Christie in 2011 [1] but only the iscsi parts got merged back then. [1] http://marc.info/?l=linux-scsi&m=131149780921009&w=2 Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- block/bsg-lib.c | 3 +- drivers/scsi/scsi_transport_fc.c | 285 +++++-------------------------- include/linux/bsg-lib.h | 1 - 3 files changed, 44 insertions(+), 245 deletions(-) diff --git a/block/bsg-lib.c b/block/bsg-lib.c index 803ec40ebd6d..2d1df5cc0507 100644 --- a/block/bsg-lib.c +++ b/block/bsg-lib.c @@ -96,13 +96,12 @@ EXPORT_SYMBOL_GPL(bsg_job_done); * bsg_softirq_done - softirq done routine for destroying the bsg requests * @rq: BSG request that holds the job to be destroyed */ -void bsg_softirq_done(struct request *rq) +static void bsg_softirq_done(struct request *rq) { struct bsg_job *job = rq->special; bsg_job_put(job); } -EXPORT_SYMBOL_GPL(bsg_softirq_done); static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 23e1eed932b5..03577bde6ac5 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3591,109 +3591,12 @@ fc_bsg_job_timeout(struct request *req) return BLK_EH_HANDLED; } -static int -fc_bsg_map_buffer(struct bsg_buffer *buf, struct request *req) -{ - size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments); - - BUG_ON(!req->nr_phys_segments); - - buf->sg_list = kzalloc(sz, GFP_KERNEL); - if (!buf->sg_list) - return -ENOMEM; - sg_init_table(buf->sg_list, req->nr_phys_segments); - buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list); - buf->payload_len = blk_rq_bytes(req); - return 0; -} - - -/** - * fc_req_to_bsgjob - Allocate/create the fc_bsg_job structure for the - * bsg request - * @shost: SCSI Host corresponding to the bsg object - * @rport: (optional) FC Remote Port corresponding to the bsg object - * @req: BSG request that needs a job structure - */ -static int -fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport, - struct request *req) -{ - struct fc_internal *i = to_fc_internal(shost->transportt); - struct request *rsp = req->next_rq; - struct bsg_job *job; - int ret; - - BUG_ON(req->special); - - job = kzalloc(sizeof(struct bsg_job) + i->f->dd_bsg_size, - GFP_KERNEL); - if (!job) - return -ENOMEM; - - /* - * Note: this is a bit silly. - * The request gets formatted as a SGIO v4 ioctl request, which - * then gets reformatted as a blk request, which then gets - * reformatted as a fc bsg request. And on completion, we have - * to wrap return results such that SGIO v4 thinks it was a scsi - * status. I hope this was all worth it. - */ - - req->special = job; - job->req = req; - if (i->f->dd_bsg_size) - job->dd_data = (void *)&job[1]; - job->request = (struct fc_bsg_request *)req->cmd; - job->request_len = req->cmd_len; - job->reply = req->sense; - job->reply_len = SCSI_SENSE_BUFFERSIZE; /* Size of sense buffer - * allocated */ - if (req->bio) { - ret = fc_bsg_map_buffer(&job->request_payload, req); - if (ret) - goto failjob_rls_job; - } - if (rsp && rsp->bio) { - ret = fc_bsg_map_buffer(&job->reply_payload, rsp); - if (ret) - goto failjob_rls_rqst_payload; - } - if (rport) - job->dev = &rport->dev; - else - job->dev = &shost->shost_gendev; - get_device(job->dev); /* take a reference for the request */ - - kref_init(&job->kref); - - return 0; - - -failjob_rls_rqst_payload: - kfree(job->request_payload.sg_list); -failjob_rls_job: - kfree(job); - return -ENOMEM; -} - - -enum fc_dispatch_result { - FC_DISPATCH_BREAK, /* on return, q is locked, break from q loop */ - FC_DISPATCH_LOCKED, /* on return, q is locked, continue on */ - FC_DISPATCH_UNLOCKED, /* on return, q is unlocked, continue on */ -}; - - /** * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD - * @q: fc host request queue * @shost: scsi host rport attached to * @job: bsg job to be processed */ -static enum fc_dispatch_result -fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, - struct bsg_job *job) +static int fc_bsg_host_dispatch(struct Scsi_Host *shost, struct bsg_job *job) { struct fc_internal *i = to_fc_internal(shost->transportt); struct fc_bsg_request *bsg_request = job->request; @@ -3754,7 +3657,7 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost, ret = i->f->bsg_request(job); if (!ret) - return FC_DISPATCH_UNLOCKED; + return 0; fail_host_msg: /* return the errno failure code as the only status */ @@ -3764,7 +3667,7 @@ fail_host_msg: job->reply_len = sizeof(uint32_t); bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); - return FC_DISPATCH_UNLOCKED; + return 0; } @@ -3788,14 +3691,10 @@ fc_bsg_goose_queue(struct fc_rport *rport) /** * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD - * @q: rport request queue * @shost: scsi host rport attached to - * @rport: rport request destined to * @job: bsg job to be processed */ -static enum fc_dispatch_result -fc_bsg_rport_dispatch(struct request_queue *q, struct Scsi_Host *shost, - struct fc_rport *rport, struct bsg_job *job) +static int fc_bsg_rport_dispatch(struct Scsi_Host *shost, struct bsg_job *job) { struct fc_internal *i = to_fc_internal(shost->transportt); struct fc_bsg_request *bsg_request = job->request; @@ -3832,7 +3731,7 @@ check_bidi: ret = i->f->bsg_request(job); if (!ret) - return FC_DISPATCH_UNLOCKED; + return 0; fail_rport_msg: /* return the errno failure code as the only status */ @@ -3842,119 +3741,19 @@ fail_rport_msg: job->reply_len = sizeof(uint32_t); bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); - return FC_DISPATCH_UNLOCKED; + return 0; } - -/** - * fc_bsg_request_handler - generic handler for bsg requests - * @q: request queue to manage - * @shost: Scsi_Host related to the bsg object - * @rport: FC remote port related to the bsg object (optional) - * @dev: device structure for bsg object - */ -static void -fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, - struct fc_rport *rport, struct device *dev) +static int fc_bsg_dispatch(struct bsg_job *job) { - struct request *req; - struct bsg_job *job; - enum fc_dispatch_result ret; - struct fc_bsg_reply *bsg_reply; + struct Scsi_Host *shost = fc_bsg_to_shost(job); - if (!get_device(dev)) - return; - - while (1) { - if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) && - !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) - break; - - req = blk_fetch_request(q); - if (!req) - break; - - if (rport && (rport->port_state != FC_PORTSTATE_ONLINE)) { - req->errors = -ENXIO; - spin_unlock_irq(q->queue_lock); - blk_end_request_all(req, -ENXIO); - spin_lock_irq(q->queue_lock); - continue; - } - - spin_unlock_irq(q->queue_lock); - - ret = fc_req_to_bsgjob(shost, rport, req); - if (ret) { - req->errors = ret; - blk_end_request_all(req, ret); - spin_lock_irq(q->queue_lock); - continue; - } - - job = req->special; - - /* check if we have the msgcode value at least */ - if (job->request_len < sizeof(uint32_t)) { - BUG_ON(job->reply_len < sizeof(uint32_t)); - bsg_reply = job->reply; - bsg_reply->reply_payload_rcv_len = 0; - bsg_reply->result = -ENOMSG; - job->reply_len = sizeof(uint32_t); - bsg_job_done(job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); - spin_lock_irq(q->queue_lock); - continue; - } - - /* the dispatch routines will unlock the queue_lock */ - if (rport) - ret = fc_bsg_rport_dispatch(q, shost, rport, job); - else - ret = fc_bsg_host_dispatch(q, shost, job); - - /* did dispatcher hit state that can't process any more */ - if (ret == FC_DISPATCH_BREAK) - break; - - /* did dispatcher had released the lock */ - if (ret == FC_DISPATCH_UNLOCKED) - spin_lock_irq(q->queue_lock); - } - - spin_unlock_irq(q->queue_lock); - put_device(dev); - spin_lock_irq(q->queue_lock); + if (scsi_is_fc_rport(job->dev)) + return fc_bsg_rport_dispatch(shost, job); + else + return fc_bsg_host_dispatch(shost, job); } - -/** - * fc_bsg_host_handler - handler for bsg requests for a fc host - * @q: fc host request queue - */ -static void -fc_bsg_host_handler(struct request_queue *q) -{ - struct Scsi_Host *shost = q->queuedata; - - fc_bsg_request_handler(q, shost, NULL, &shost->shost_gendev); -} - - -/** - * fc_bsg_rport_handler - handler for bsg requests for a fc rport - * @q: rport request queue - */ -static void -fc_bsg_rport_handler(struct request_queue *q) -{ - struct fc_rport *rport = q->queuedata; - struct Scsi_Host *shost = rport_to_shost(rport); - - fc_bsg_request_handler(q, shost, rport, &rport->dev); -} - - /** * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests * @shost: shost for fc_host @@ -3977,33 +3776,42 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host) snprintf(bsg_name, sizeof(bsg_name), "fc_host%d", shost->host_no); - q = __scsi_alloc_queue(shost, fc_bsg_host_handler); + q = __scsi_alloc_queue(shost, bsg_request_fn); if (!q) { - printk(KERN_ERR "fc_host%d: bsg interface failed to " - "initialize - no request queue\n", - shost->host_no); + dev_err(dev, + "fc_host%d: bsg interface failed to initialize - no request queue\n", + shost->host_no); return -ENOMEM; } - q->queuedata = shost; - queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); - blk_queue_softirq_done(q, bsg_softirq_done); - blk_queue_rq_timed_out(q, fc_bsg_job_timeout); - blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT); - - err = bsg_register_queue(q, dev, bsg_name, NULL); + err = bsg_setup_queue(dev, q, bsg_name, fc_bsg_dispatch, + i->f->dd_bsg_size); if (err) { - printk(KERN_ERR "fc_host%d: bsg interface failed to " - "initialize - register queue\n", - shost->host_no); + dev_err(dev, + "fc_host%d: bsg interface failed to initialize - setup queue\n", + shost->host_no); blk_cleanup_queue(q); return err; } - + blk_queue_rq_timed_out(q, fc_bsg_job_timeout); + blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT); fc_host->rqst_q = q; return 0; } +static int fc_bsg_rport_prep(struct request_queue *q, struct request *req) +{ + struct fc_rport *rport = dev_to_rport(q->queuedata); + + if (rport->port_state == FC_PORTSTATE_BLOCKED && + !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) + return BLKPREP_DEFER; + + if (rport->port_state != FC_PORTSTATE_ONLINE) + return BLKPREP_KILL; + + return BLKPREP_OK; +} /** * fc_bsg_rportadd - Create and add the bsg hooks so we can receive requests @@ -4023,29 +3831,22 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport) if (!i->f->bsg_request) return -ENOTSUPP; - q = __scsi_alloc_queue(shost, fc_bsg_rport_handler); + q = __scsi_alloc_queue(shost, bsg_request_fn); if (!q) { - printk(KERN_ERR "%s: bsg interface failed to " - "initialize - no request queue\n", - dev->kobj.name); + dev_err(dev, "bsg interface failed to initialize - no request queue\n"); return -ENOMEM; } - q->queuedata = rport; - queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); - blk_queue_softirq_done(q, bsg_softirq_done); - blk_queue_rq_timed_out(q, fc_bsg_job_timeout); - blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT); - - err = bsg_register_queue(q, dev, NULL, NULL); + err = bsg_setup_queue(dev, q, NULL, fc_bsg_dispatch, i->f->dd_bsg_size); if (err) { - printk(KERN_ERR "%s: bsg interface failed to " - "initialize - register queue\n", - dev->kobj.name); + dev_err(dev, "failed to setup bsg queue\n"); blk_cleanup_queue(q); return err; } + blk_queue_prep_rq(q, fc_bsg_rport_prep); + blk_queue_rq_timed_out(q, fc_bsg_job_timeout); + blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT); rport->rqst_q = q; return 0; } diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h index b708db91618f..657a718c27d2 100644 --- a/include/linux/bsg-lib.h +++ b/include/linux/bsg-lib.h @@ -69,7 +69,6 @@ void bsg_job_done(struct bsg_job *job, int result, int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name, bsg_job_fn *job_fn, int dd_job_size); void bsg_request_fn(struct request_queue *q); -void bsg_softirq_done(struct request *rq); void bsg_job_put(struct bsg_job *job); int __must_check bsg_job_get(struct bsg_job *job); From 0910d8bbdd99856af1394d3d8830955abdefee4a Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 8 Nov 2016 08:11:30 +0100 Subject: [PATCH 189/256] scsi: aacraid: switch to pci_alloc_irq_vectors Use pci_alloc_irq_vectors and drop the hand-crafted interrupt affinity routines. Signed-off-by: Hannes Reinecke Cc: Adaptec OEM Raid Solutions Reviewed-by: Raghava Aditya Renukunta Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 1 - drivers/scsi/aacraid/comminit.c | 10 +++------- drivers/scsi/aacraid/commsup.c | 25 +++++-------------------- drivers/scsi/aacraid/linit.c | 20 ++++---------------- 4 files changed, 12 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 969c312de1be..f059c14efa0c 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1246,7 +1246,6 @@ struct aac_dev u32 max_msix; /* max. MSI-X vectors */ u32 vector_cap; /* MSI-X vector capab.*/ int msi_enabled; /* MSI/MSI-X enabled */ - struct msix_entry msixentry[AAC_MAX_MSIX]; struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ u8 adapter_shutdown; u32 handle_pci_error; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 341ea327ae79..4f56b1003cc7 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -378,16 +378,12 @@ void aac_define_int_mode(struct aac_dev *dev) if (msi_count > AAC_MAX_MSIX) msi_count = AAC_MAX_MSIX; - for (i = 0; i < msi_count; i++) - dev->msixentry[i].entry = i; - if (msi_count > 1 && pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) { min_msix = 2; - i = pci_enable_msix_range(dev->pdev, - dev->msixentry, - min_msix, - msi_count); + i = pci_alloc_irq_vectors(dev->pdev, + min_msix, msi_count, + PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); if (i > 0) { dev->msi_enabled = 1; msi_count = i; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 0aeecec1f5ea..9e7551fe4b19 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -2043,30 +2043,22 @@ int aac_acquire_irq(struct aac_dev *dev) int i; int j; int ret = 0; - int cpu; - cpu = cpumask_first(cpu_online_mask); if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) { for (i = 0; i < dev->max_msix; i++) { dev->aac_msix[i].vector_no = i; dev->aac_msix[i].dev = dev; - if (request_irq(dev->msixentry[i].vector, + if (request_irq(pci_irq_vector(dev->pdev, i), dev->a_ops.adapter_intr, 0, "aacraid", &(dev->aac_msix[i]))) { printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n", dev->name, dev->id, i); for (j = 0 ; j < i ; j++) - free_irq(dev->msixentry[j].vector, + free_irq(pci_irq_vector(dev->pdev, j), &(dev->aac_msix[j])); pci_disable_msix(dev->pdev); ret = -1; } - if (irq_set_affinity_hint(dev->msixentry[i].vector, - get_cpu_mask(cpu))) { - printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n", - dev->name, dev->id, cpu); - } - cpu = cpumask_next(cpu, cpu_online_mask); } } else { dev->aac_msix[0].vector_no = 0; @@ -2096,16 +2088,9 @@ void aac_free_irq(struct aac_dev *dev) dev->pdev->device == PMC_DEVICE_S8 || dev->pdev->device == PMC_DEVICE_S9) { if (dev->max_msix > 1) { - for (i = 0; i < dev->max_msix; i++) { - if (irq_set_affinity_hint( - dev->msixentry[i].vector, NULL)) { - printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n", - dev->name, dev->id, cpu); - } - cpu = cpumask_next(cpu, cpu_online_mask); - free_irq(dev->msixentry[i].vector, - &(dev->aac_msix[i])); - } + for (i = 0; i < dev->max_msix; i++) + free_irq(pci_irq_vector(dev->pdev, i), + &(dev->aac_msix[i])); } else { free_irq(dev->pdev->irq, &(dev->aac_msix[0])); } diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 79871f3519ff..e4f3e22fcbd9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1071,7 +1071,6 @@ static struct scsi_host_template aac_driver_template = { static void __aac_shutdown(struct aac_dev * aac) { int i; - int cpu; aac_send_shutdown(aac); @@ -1087,24 +1086,13 @@ static void __aac_shutdown(struct aac_dev * aac) kthread_stop(aac->thread); } aac_adapter_disable_int(aac); - cpu = cpumask_first(cpu_online_mask); if (aac->pdev->device == PMC_DEVICE_S6 || aac->pdev->device == PMC_DEVICE_S7 || aac->pdev->device == PMC_DEVICE_S8 || aac->pdev->device == PMC_DEVICE_S9) { if (aac->max_msix > 1) { for (i = 0; i < aac->max_msix; i++) { - if (irq_set_affinity_hint( - aac->msixentry[i].vector, - NULL)) { - printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n", - aac->name, - aac->id, - cpu); - } - cpu = cpumask_next(cpu, - cpu_online_mask); - free_irq(aac->msixentry[i].vector, + free_irq(pci_irq_vector(aac->pdev, i), &(aac->aac_msix[i])); } } else { @@ -1350,7 +1338,7 @@ static void aac_release_resources(struct aac_dev *aac) aac->pdev->device == PMC_DEVICE_S9) { if (aac->max_msix > 1) { for (i = 0; i < aac->max_msix; i++) - free_irq(aac->msixentry[i].vector, + free_irq(pci_irq_vector(aac->pdev, i), &(aac->aac_msix[i])); } else { free_irq(aac->pdev->irq, &(aac->aac_msix[0])); @@ -1396,13 +1384,13 @@ static int aac_acquire_resources(struct aac_dev *dev) dev->aac_msix[i].vector_no = i; dev->aac_msix[i].dev = dev; - if (request_irq(dev->msixentry[i].vector, + if (request_irq(pci_irq_vector(dev->pdev, i), dev->a_ops.adapter_intr, 0, "aacraid", &(dev->aac_msix[i]))) { printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n", name, instance, i); for (j = 0 ; j < i ; j++) - free_irq(dev->msixentry[j].vector, + free_irq(pci_irq_vector(dev->pdev, j), &(dev->aac_msix[j])); pci_disable_msix(dev->pdev); goto error_iounmap; From 4aaa4065f762514c38aba1f1193d200c7140d1c0 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 17 Nov 2016 21:46:20 +0100 Subject: [PATCH 190/256] scsi: mptfusion: Fix printk continuations Fix the printk continuations when running the mptfusion driver. This patch brings the capabilities into one single syslog line again: mptbase: ioc1: Initiating bringup ioc1: LSI53C1030 B2: Capabilities={Initiator,Target} scsi host3: ioc1: LSI53C1030 B2, FwRev=01032341h, Ports=1, MaxQ=255, IRQ=67 Tested on a parisc C8000 machine. Signed-off-by: Helge Deller Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptbase.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index f82745c6cdf7..1e73064b0fb2 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -2865,21 +2865,21 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc) printk(KERN_INFO "%s: ", ioc->name); if (ioc->prod_name) - printk("%s: ", ioc->prod_name); - printk("Capabilities={"); + pr_cont("%s: ", ioc->prod_name); + pr_cont("Capabilities={"); if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { - printk("Initiator"); + pr_cont("Initiator"); i++; } if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { - printk("%sTarget", i ? "," : ""); + pr_cont("%sTarget", i ? "," : ""); i++; } if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { - printk("%sLAN", i ? "," : ""); + pr_cont("%sLAN", i ? "," : ""); i++; } @@ -2888,12 +2888,12 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc) * This would probably evoke more questions than it's worth */ if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { - printk("%sLogBusAddr", i ? "," : ""); + pr_cont("%sLogBusAddr", i ? "," : ""); i++; } #endif - printk("}\n"); + pr_cont("}\n"); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ From 2244459070c8080bffcd9f9916ee45b9463b6b6d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 16 Nov 2016 16:14:27 +0100 Subject: [PATCH 191/256] scsi: bfa: turn bfa_mem_{kva,dma}_setup into inline functions These two macros cause lots of warnings with gcc-7: drivers/scsi/bfa/bfa_svc.c: In function 'bfa_fcxp_meminfo': drivers/scsi/bfa/bfa_svc.c:521:103: error: '*' in boolean context, suggest '&&' instead [-Werror=int-in-bool-context] Using inline functions makes them much more readable and avoids the warnings. Signed-off-by: Arnd Bergmann Reviewed-by: Johannes Thumshirn Acked by: Anil Gurumurthy Signed-off-by: Martin K. Petersen --- drivers/scsi/bfa/bfa_ioc.h | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 713745da44c6..0f9fab770339 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -111,20 +111,24 @@ struct bfa_meminfo_s { struct bfa_mem_kva_s kva_info; }; -/* BFA memory segment setup macros */ -#define bfa_mem_dma_setup(_meminfo, _dm_ptr, _seg_sz) do { \ - ((bfa_mem_dma_t *)(_dm_ptr))->mem_len = (_seg_sz); \ - if (_seg_sz) \ - list_add_tail(&((bfa_mem_dma_t *)_dm_ptr)->qe, \ - &(_meminfo)->dma_info.qe); \ -} while (0) +/* BFA memory segment setup helpers */ +static inline void bfa_mem_dma_setup(struct bfa_meminfo_s *meminfo, + struct bfa_mem_dma_s *dm_ptr, + size_t seg_sz) +{ + dm_ptr->mem_len = seg_sz; + if (seg_sz) + list_add_tail(&dm_ptr->qe, &meminfo->dma_info.qe); +} -#define bfa_mem_kva_setup(_meminfo, _kva_ptr, _seg_sz) do { \ - ((bfa_mem_kva_t *)(_kva_ptr))->mem_len = (_seg_sz); \ - if (_seg_sz) \ - list_add_tail(&((bfa_mem_kva_t *)_kva_ptr)->qe, \ - &(_meminfo)->kva_info.qe); \ -} while (0) +static inline void bfa_mem_kva_setup(struct bfa_meminfo_s *meminfo, + struct bfa_mem_kva_s *kva_ptr, + size_t seg_sz) +{ + kva_ptr->mem_len = seg_sz; + if (seg_sz) + list_add_tail(&kva_ptr->qe, &meminfo->kva_info.qe); +} /* BFA dma memory segments iterator */ #define bfa_mem_dma_sptr(_mod, _i) (&(_mod)->dma_seg[(_i)]) From a6854dff635ddde8403ae1dce4c6772eb1031827 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 19 Nov 2016 22:34:51 -0800 Subject: [PATCH 192/256] scsi: ufs: qcom: Properly clear hba priv on failure ufs_qcom_init() sets the hba priv data before attempting to acquire the phy handle, so make sure to clear this in the case of an error. Failing to do this will make ufs_qcom_setup_clocks() operate on the uninitalized host object. Signed-off-by: Bjorn Andersson Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 804f4e70c771..aa43bfea0d00 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1197,12 +1197,12 @@ static int ufs_qcom_init(struct ufs_hba *hba) if (IS_ERR(host->generic_phy)) { err = PTR_ERR(host->generic_phy); dev_err(dev, "%s: PHY get failed %d\n", __func__, err); - goto out; + goto out_variant_clear; } err = ufs_qcom_bus_register(host); if (err) - goto out_host_free; + goto out_variant_clear; ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, &host->hw_ver.minor, &host->hw_ver.step); @@ -1267,7 +1267,7 @@ out_disable_phy: phy_power_off(host->generic_phy); out_unregister_bus: phy_exit(host->generic_phy); -out_host_free: +out_variant_clear: ufshcd_set_variant(hba, NULL); out: return err; From 75b1cc4ad63afa28c1a045b5157c008f405f06a9 Mon Sep 17 00:00:00 2001 From: Kiwoong Kim Date: Tue, 22 Nov 2016 17:06:59 +0900 Subject: [PATCH 193/256] scsi: ufs: introduce UFSHCD_QUIRK_PRDT_BYTE_GRAN quirk Some UFS host controllers may think granularities of PRDT length and offset as bytes, not double words. Signed-off-by: Kiwoong Kim Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 28 +++++++++++++++++++++------- drivers/scsi/ufs/ufshcd.h | 6 ++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 421488161cf3..f91e50bf1a43 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1129,7 +1129,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) * * Returns 0 in case of success, non-zero value in case of failure */ -static int ufshcd_map_sg(struct ufshcd_lrb *lrbp) +static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { struct ufshcd_sg_entry *prd_table; struct scatterlist *sg; @@ -1143,8 +1143,13 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp) return sg_segments; if (sg_segments) { - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((u16) (sg_segments)); + if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) + lrbp->utr_descriptor_ptr->prd_table_length = + cpu_to_le16((u16)(sg_segments * + sizeof(struct ufshcd_sg_entry))); + else + lrbp->utr_descriptor_ptr->prd_table_length = + cpu_to_le16((u16) (sg_segments)); prd_table = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr; @@ -1507,7 +1512,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) ufshcd_comp_scsi_upiu(hba, lrbp); - err = ufshcd_map_sg(lrbp); + err = ufshcd_map_sg(hba, lrbp); if (err) { lrbp->cmd = NULL; clear_bit_unlock(tag, &hba->lrb_in_use); @@ -2368,12 +2373,21 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) cpu_to_le32(upper_32_bits(cmd_desc_element_addr)); /* Response upiu and prdt offset should be in double words */ - utrdlp[i].response_upiu_offset = + if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) { + utrdlp[i].response_upiu_offset = + cpu_to_le16(response_offset); + utrdlp[i].prd_table_offset = + cpu_to_le16(prdt_offset); + utrdlp[i].response_upiu_length = + cpu_to_le16(ALIGNED_UPIU_SIZE); + } else { + utrdlp[i].response_upiu_offset = cpu_to_le16((response_offset >> 2)); - utrdlp[i].prd_table_offset = + utrdlp[i].prd_table_offset = cpu_to_le16((prdt_offset >> 2)); - utrdlp[i].response_upiu_length = + utrdlp[i].response_upiu_length = cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); + } hba->lrb[i].utr_descriptor_ptr = (utrdlp + i); hba->lrb[i].ucd_req_ptr = diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8e76501144d6..7d9ff22acfea 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -485,6 +485,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION UFS_BIT(5) + /* + * This quirk needs to be enabled if the host contoller regards + * resolution of the values of PRDTO and PRDTL in UTRD as byte. + */ + #define UFSHCD_QUIRK_PRDT_BYTE_GRAN UFS_BIT(7) + unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ From 2d76a2478bb8c54d241b23a699d55f90b7efd036 Mon Sep 17 00:00:00 2001 From: Quentin Lambert Date: Sat, 19 Nov 2016 18:43:18 +0100 Subject: [PATCH 194/256] scsi: pmcraid: Add missing resource releases Most error branches following the call to pmcraid_get_free_cmd contain a call to pmcraid_return_cmd. This patch add these calls where they are missing. Moreover, most error branches following the call to class_create contain a call to class_destroy. This patch add these calls where they are missing. This issue was found with Hector. Signed-off-by: Quentin Lambert Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 68a5c347fae9..cb12b7bad8e6 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3792,11 +3792,11 @@ static long pmcraid_ioctl_passthrough( direction); if (rc) { pmcraid_err("couldn't build passthrough ioadls\n"); - goto out_free_buffer; + goto out_free_cmd; } } else if (request_size < 0) { rc = -EINVAL; - goto out_free_buffer; + goto out_free_cmd; } /* If data is being written into the device, copy the data from user @@ -3913,6 +3913,8 @@ out_handle_response: out_free_sglist: pmcraid_release_passthrough_ioadls(cmd, request_size, direction); + +out_free_cmd: pmcraid_return_cmd(cmd); out_free_buffer: @@ -6023,8 +6025,10 @@ static int __init pmcraid_init(void) error = pmcraid_netlink_init(); - if (error) + if (error) { + class_destroy(pmcraid_class); goto out_unreg_chrdev; + } error = pci_register_driver(&pmcraid_driver); From d3b688d3c69d318177c104f451b9064831da42b9 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:30 +0800 Subject: [PATCH 195/256] scsi: hisi_sas: add v2 hw support for ECC and AXI bus fatal error For ECC 1bit error, logic can recover it, so we only print a warning. For ECC multi-bit and AXI bus fatal error, we panic. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 425 ++++++++++++++++++++++++- 1 file changed, 420 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 0763b4764ad5..9e70e6d64724 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -55,10 +55,44 @@ #define HGC_DFX_CFG2 0xc0 #define HGC_IOMB_PROC1_STATUS 0x104 #define CFG_1US_TIMER_TRSH 0xcc +#define HGC_LM_DFX_STATUS2 0x128 +#define HGC_LM_DFX_STATUS2_IOSTLIST_OFF 0 +#define HGC_LM_DFX_STATUS2_IOSTLIST_MSK (0xfff << \ + HGC_LM_DFX_STATUS2_IOSTLIST_OFF) +#define HGC_LM_DFX_STATUS2_ITCTLIST_OFF 12 +#define HGC_LM_DFX_STATUS2_ITCTLIST_MSK (0x7ff << \ + HGC_LM_DFX_STATUS2_ITCTLIST_OFF) +#define HGC_CQE_ECC_ADDR 0x13c +#define HGC_CQE_ECC_1B_ADDR_OFF 0 +#define HGC_CQE_ECC_1B_ADDR_MSK (0x3f < HGC_CQE_ECC_1B_ADDR_OFF) +#define HGC_CQE_ECC_MB_ADDR_OFF 8 +#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f < HGC_CQE_ECC_MB_ADDR_OFF) +#define HGC_IOST_ECC_ADDR 0x140 +#define HGC_IOST_ECC_1B_ADDR_OFF 0 +#define HGC_IOST_ECC_1B_ADDR_MSK (0x3ff < HGC_IOST_ECC_1B_ADDR_OFF) +#define HGC_IOST_ECC_MB_ADDR_OFF 16 +#define HGC_IOST_ECC_MB_ADDR_MSK (0x3ff < HGC_IOST_ECC_MB_ADDR_OFF) +#define HGC_DQE_ECC_ADDR 0x144 +#define HGC_DQE_ECC_1B_ADDR_OFF 0 +#define HGC_DQE_ECC_1B_ADDR_MSK (0xfff < HGC_DQE_ECC_1B_ADDR_OFF) +#define HGC_DQE_ECC_MB_ADDR_OFF 16 +#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff < HGC_DQE_ECC_MB_ADDR_OFF) #define HGC_INVLD_DQE_INFO 0x148 #define HGC_INVLD_DQE_INFO_FB_CH0_OFF 9 #define HGC_INVLD_DQE_INFO_FB_CH0_MSK (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF) #define HGC_INVLD_DQE_INFO_FB_CH3_OFF 18 +#define HGC_ITCT_ECC_ADDR 0x150 +#define HGC_ITCT_ECC_1B_ADDR_OFF 0 +#define HGC_ITCT_ECC_1B_ADDR_MSK (0x3ff << \ + HGC_ITCT_ECC_1B_ADDR_OFF) +#define HGC_ITCT_ECC_MB_ADDR_OFF 16 +#define HGC_ITCT_ECC_MB_ADDR_MSK (0x3ff << \ + HGC_ITCT_ECC_MB_ADDR_OFF) +#define HGC_AXI_FIFO_ERR_INFO 0x154 +#define AXI_ERR_INFO_OFF 0 +#define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF) +#define FIFO_ERR_INFO_OFF 8 +#define FIFO_ERR_INFO_MSK (0xff << FIFO_ERR_INFO_OFF) #define INT_COAL_EN 0x19c #define OQ_INT_COAL_TIME 0x1a0 #define OQ_INT_COAL_CNT 0x1a4 @@ -73,13 +107,41 @@ #define ENT_INT_SRC1_D2H_FIS_CH1_MSK (0x1 << ENT_INT_SRC1_D2H_FIS_CH1_OFF) #define ENT_INT_SRC2 0x1bc #define ENT_INT_SRC3 0x1c0 +#define ENT_INT_SRC3_WP_DEPTH_OFF 8 +#define ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF 9 +#define ENT_INT_SRC3_RP_DEPTH_OFF 10 +#define ENT_INT_SRC3_AXI_OFF 11 +#define ENT_INT_SRC3_FIFO_OFF 12 +#define ENT_INT_SRC3_LM_OFF 14 #define ENT_INT_SRC3_ITC_INT_OFF 15 #define ENT_INT_SRC3_ITC_INT_MSK (0x1 << ENT_INT_SRC3_ITC_INT_OFF) +#define ENT_INT_SRC3_ABT_OFF 16 #define ENT_INT_SRC_MSK1 0x1c4 #define ENT_INT_SRC_MSK2 0x1c8 #define ENT_INT_SRC_MSK3 0x1cc #define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31 #define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF) +#define SAS_ECC_INTR 0x1e8 +#define SAS_ECC_INTR_DQE_ECC_1B_OFF 0 +#define SAS_ECC_INTR_DQE_ECC_MB_OFF 1 +#define SAS_ECC_INTR_IOST_ECC_1B_OFF 2 +#define SAS_ECC_INTR_IOST_ECC_MB_OFF 3 +#define SAS_ECC_INTR_ITCT_ECC_MB_OFF 4 +#define SAS_ECC_INTR_ITCT_ECC_1B_OFF 5 +#define SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF 6 +#define SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF 7 +#define SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF 8 +#define SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF 9 +#define SAS_ECC_INTR_CQE_ECC_1B_OFF 10 +#define SAS_ECC_INTR_CQE_ECC_MB_OFF 11 +#define SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF 12 +#define SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF 13 +#define SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF 14 +#define SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF 15 +#define SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF 16 +#define SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF 17 +#define SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF 18 +#define SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF 19 #define SAS_ECC_INTR_MSK 0x1ec #define HGC_ERR_STAT_EN 0x238 #define DLVRY_Q_0_BASE_ADDR_LO 0x260 @@ -94,7 +156,20 @@ #define COMPL_Q_0_DEPTH 0x4e8 #define COMPL_Q_0_WR_PTR 0x4ec #define COMPL_Q_0_RD_PTR 0x4f0 - +#define HGC_RXM_DFX_STATUS14 0xae8 +#define HGC_RXM_DFX_STATUS14_MEM0_OFF 0 +#define HGC_RXM_DFX_STATUS14_MEM0_MSK (0x1ff << \ + HGC_RXM_DFX_STATUS14_MEM0_OFF) +#define HGC_RXM_DFX_STATUS14_MEM1_OFF 9 +#define HGC_RXM_DFX_STATUS14_MEM1_MSK (0x1ff << \ + HGC_RXM_DFX_STATUS14_MEM1_OFF) +#define HGC_RXM_DFX_STATUS14_MEM2_OFF 18 +#define HGC_RXM_DFX_STATUS14_MEM2_MSK (0x1ff << \ + HGC_RXM_DFX_STATUS14_MEM2_OFF) +#define HGC_RXM_DFX_STATUS15 0xaec +#define HGC_RXM_DFX_STATUS15_MEM3_OFF 0 +#define HGC_RXM_DFX_STATUS15_MEM3_MSK (0x1ff << \ + HGC_RXM_DFX_STATUS15_MEM3_OFF) /* phy registers need init */ #define PORT_BASE (0x2000) @@ -267,6 +342,8 @@ #define ITCT_HDR_RTOLT_OFF 48 #define ITCT_HDR_RTOLT_MSK (0xffffULL << ITCT_HDR_RTOLT_OFF) +#define HISI_SAS_FATAL_INT_NR 2 + struct hisi_sas_complete_v2_hdr { __le32 dw0; __le32 dw1; @@ -808,7 +885,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0x7efefefe); hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0x7efefefe); hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0x7ffffffe); - hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xfffff3c0); + hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xfff00c30); for (i = 0; i < hisi_hba->queue_count; i++) hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0); @@ -824,7 +901,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x10); hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); 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, CHL_INT2, 0xfff87fff); hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000); hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff); @@ -2007,8 +2084,9 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) if (irq_value1) { if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK | CHL_INT1_DMAC_TX_ECC_ERR_MSK)) - panic("%s: DMAC RX/TX ecc bad error! (0x%x)", - dev_name(dev), irq_value1); + panic("%s: DMAC RX/TX ecc bad error!\ + (0x%x)", + dev_name(dev), irq_value1); hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT1, irq_value1); @@ -2039,6 +2117,318 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) return IRQ_HANDLED; } +static void +one_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba, u32 irq_value) +{ + struct device *dev = &hisi_hba->pdev->dev; + u32 reg_val; + + if (irq_value & BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_DQE_ECC_ADDR); + dev_warn(dev, "hgc_dqe_acc1b_intr found: \ + Ram address is 0x%08X\n", + (reg_val & HGC_DQE_ECC_1B_ADDR_MSK) >> + HGC_DQE_ECC_1B_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_IOST_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_IOST_ECC_ADDR); + dev_warn(dev, "hgc_iost_acc1b_intr found: \ + Ram address is 0x%08X\n", + (reg_val & HGC_IOST_ECC_1B_ADDR_MSK) >> + HGC_IOST_ECC_1B_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_ITCT_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_ITCT_ECC_ADDR); + dev_warn(dev, "hgc_itct_acc1b_intr found: \ + Ram address is 0x%08X\n", + (reg_val & HGC_ITCT_ECC_1B_ADDR_MSK) >> + HGC_ITCT_ECC_1B_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_LM_DFX_STATUS2); + dev_warn(dev, "hgc_iostl_acc1b_intr found: \ + memory address is 0x%08X\n", + (reg_val & HGC_LM_DFX_STATUS2_IOSTLIST_MSK) >> + HGC_LM_DFX_STATUS2_IOSTLIST_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_LM_DFX_STATUS2); + dev_warn(dev, "hgc_itctl_acc1b_intr found: \ + memory address is 0x%08X\n", + (reg_val & HGC_LM_DFX_STATUS2_ITCTLIST_MSK) >> + HGC_LM_DFX_STATUS2_ITCTLIST_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_CQE_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_CQE_ECC_ADDR); + dev_warn(dev, "hgc_cqe_acc1b_intr found: \ + Ram address is 0x%08X\n", + (reg_val & HGC_CQE_ECC_1B_ADDR_MSK) >> + HGC_CQE_ECC_1B_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS14); + dev_warn(dev, "rxm_mem0_acc1b_intr found: \ + memory address is 0x%08X\n", + (reg_val & HGC_RXM_DFX_STATUS14_MEM0_MSK) >> + HGC_RXM_DFX_STATUS14_MEM0_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS14); + dev_warn(dev, "rxm_mem1_acc1b_intr found: \ + memory address is 0x%08X\n", + (reg_val & HGC_RXM_DFX_STATUS14_MEM1_MSK) >> + HGC_RXM_DFX_STATUS14_MEM1_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS14); + dev_warn(dev, "rxm_mem2_acc1b_intr found: \ + memory address is 0x%08X\n", + (reg_val & HGC_RXM_DFX_STATUS14_MEM2_MSK) >> + HGC_RXM_DFX_STATUS14_MEM2_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS15); + dev_warn(dev, "rxm_mem3_acc1b_intr found: \ + memory address is 0x%08X\n", + (reg_val & HGC_RXM_DFX_STATUS15_MEM3_MSK) >> + HGC_RXM_DFX_STATUS15_MEM3_OFF); + } + +} + +static void multi_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba, + u32 irq_value) +{ + u32 reg_val; + struct device *dev = &hisi_hba->pdev->dev; + + if (irq_value & BIT(SAS_ECC_INTR_DQE_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_DQE_ECC_ADDR); + panic("%s: hgc_dqe_accbad_intr (0x%x) found: \ + Ram address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_DQE_ECC_MB_ADDR_MSK) >> + HGC_DQE_ECC_MB_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_IOST_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_IOST_ECC_ADDR); + panic("%s: hgc_iost_accbad_intr (0x%x) found: \ + Ram address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_IOST_ECC_MB_ADDR_MSK) >> + HGC_IOST_ECC_MB_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_ITCT_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_ITCT_ECC_ADDR); + panic("%s: hgc_itct_accbad_intr (0x%x) found: \ + Ram address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_ITCT_ECC_MB_ADDR_MSK) >> + HGC_ITCT_ECC_MB_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_LM_DFX_STATUS2); + panic("%s: hgc_iostl_accbad_intr (0x%x) found: \ + memory address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_LM_DFX_STATUS2_IOSTLIST_MSK) >> + HGC_LM_DFX_STATUS2_IOSTLIST_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_LM_DFX_STATUS2); + panic("%s: hgc_itctl_accbad_intr (0x%x) found: \ + memory address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_LM_DFX_STATUS2_ITCTLIST_MSK) >> + HGC_LM_DFX_STATUS2_ITCTLIST_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_CQE_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_CQE_ECC_ADDR); + panic("%s: hgc_cqe_accbad_intr (0x%x) found: \ + Ram address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_CQE_ECC_MB_ADDR_MSK) >> + HGC_CQE_ECC_MB_ADDR_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS14); + panic("%s: rxm_mem0_accbad_intr (0x%x) found: \ + memory address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_RXM_DFX_STATUS14_MEM0_MSK) >> + HGC_RXM_DFX_STATUS14_MEM0_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS14); + panic("%s: rxm_mem1_accbad_intr (0x%x) found: \ + memory address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_RXM_DFX_STATUS14_MEM1_MSK) >> + HGC_RXM_DFX_STATUS14_MEM1_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS14); + panic("%s: rxm_mem2_accbad_intr (0x%x) found: \ + memory address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_RXM_DFX_STATUS14_MEM2_MSK) >> + HGC_RXM_DFX_STATUS14_MEM2_OFF); + } + + if (irq_value & BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF)) { + reg_val = hisi_sas_read32(hisi_hba, HGC_RXM_DFX_STATUS15); + panic("%s: rxm_mem3_accbad_intr (0x%x) found: \ + memory address is 0x%08X\n", + dev_name(dev), irq_value, + (reg_val & HGC_RXM_DFX_STATUS15_MEM3_MSK) >> + HGC_RXM_DFX_STATUS15_MEM3_OFF); + } + +} + +static irqreturn_t fatal_ecc_int_v2_hw(int irq_no, void *p) +{ + struct hisi_hba *hisi_hba = p; + u32 irq_value, irq_msk; + + irq_msk = hisi_sas_read32(hisi_hba, SAS_ECC_INTR_MSK); + hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk | 0xffffffff); + + irq_value = hisi_sas_read32(hisi_hba, SAS_ECC_INTR); + if (irq_value) { + one_bit_ecc_error_process_v2_hw(hisi_hba, irq_value); + multi_bit_ecc_error_process_v2_hw(hisi_hba, irq_value); + } + + hisi_sas_write32(hisi_hba, SAS_ECC_INTR, irq_value); + hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk); + + return IRQ_HANDLED; +} + +#define AXI_ERR_NR 8 +static const char axi_err_info[AXI_ERR_NR][32] = { + "IOST_AXI_W_ERR", + "IOST_AXI_R_ERR", + "ITCT_AXI_W_ERR", + "ITCT_AXI_R_ERR", + "SATA_AXI_W_ERR", + "SATA_AXI_R_ERR", + "DQE_AXI_R_ERR", + "CQE_AXI_W_ERR" +}; + +#define FIFO_ERR_NR 5 +static const char fifo_err_info[FIFO_ERR_NR][32] = { + "CQE_WINFO_FIFO", + "CQE_MSG_FIFIO", + "GETDQE_FIFO", + "CMDP_FIFO", + "AWTCTRL_FIFO" +}; + +static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) +{ + struct hisi_hba *hisi_hba = p; + u32 irq_value, irq_msk, err_value; + struct device *dev = &hisi_hba->pdev->dev; + + irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0xfffffffe); + + irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3); + if (irq_value) { + if (irq_value & BIT(ENT_INT_SRC3_WP_DEPTH_OFF)) { + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, + 1 << ENT_INT_SRC3_WP_DEPTH_OFF); + panic("%s: write pointer and depth error (0x%x) \ + found!\n", + dev_name(dev), irq_value); + } + + if (irq_value & BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF)) { + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, + 1 << + ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF); + panic("%s: iptt no match slot error (0x%x) found!\n", + dev_name(dev), irq_value); + } + + if (irq_value & BIT(ENT_INT_SRC3_RP_DEPTH_OFF)) + panic("%s: read pointer and depth error (0x%x) \ + found!\n", + dev_name(dev), irq_value); + + if (irq_value & BIT(ENT_INT_SRC3_AXI_OFF)) { + int i; + + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, + 1 << ENT_INT_SRC3_AXI_OFF); + err_value = hisi_sas_read32(hisi_hba, + HGC_AXI_FIFO_ERR_INFO); + + for (i = 0; i < AXI_ERR_NR; i++) { + if (err_value & BIT(i)) + panic("%s: %s (0x%x) found!\n", + dev_name(dev), + axi_err_info[i], irq_value); + } + } + + if (irq_value & BIT(ENT_INT_SRC3_FIFO_OFF)) { + int i; + + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, + 1 << ENT_INT_SRC3_FIFO_OFF); + err_value = hisi_sas_read32(hisi_hba, + HGC_AXI_FIFO_ERR_INFO); + + for (i = 0; i < FIFO_ERR_NR; i++) { + if (err_value & BIT(AXI_ERR_NR + i)) + panic("%s: %s (0x%x) found!\n", + dev_name(dev), + fifo_err_info[i], irq_value); + } + + } + + if (irq_value & BIT(ENT_INT_SRC3_LM_OFF)) { + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, + 1 << ENT_INT_SRC3_LM_OFF); + panic("%s: LM add/fetch list error (0x%x) found!\n", + dev_name(dev), irq_value); + } + + if (irq_value & BIT(ENT_INT_SRC3_ABT_OFF)) { + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, + 1 << ENT_INT_SRC3_ABT_OFF); + panic("%s: SAS_HGC_ABT fetch LM list error (0x%x) found!\n", + dev_name(dev), irq_value); + } + } + + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk); + + return IRQ_HANDLED; +} + static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) { struct hisi_sas_cq *cq = p; @@ -2192,6 +2582,11 @@ static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = { int_chnl_int_v2_hw, }; +static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = { + fatal_ecc_int_v2_hw, + fatal_axi_int_v2_hw +}; + /** * There is a limitation in the hip06 chipset that we need * to map in all mbigen interrupts, even if they are not used. @@ -2247,6 +2642,26 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) } } + for (i = 0; i < HISI_SAS_FATAL_INT_NR; i++) { + int idx = i; + + irq = irq_map[idx + 81]; + if (!irq) { + dev_err(dev, "irq init: fail map fatal interrupt %d\n", + idx); + return -ENOENT; + } + + rc = devm_request_irq(dev, irq, fatal_interrupts[i], 0, + DRV_NAME " fatal", hisi_hba); + if (rc) { + dev_err(dev, + "irq init: could not request fatal interrupt %d, rc=%d\n", + irq, rc); + return -ENOENT; + } + } + for (i = 0; i < hisi_hba->queue_count; i++) { int idx = i + 96; /* First cq interrupt is irq96 */ From c70f1fb7558f0b3c8f63c3e8a2caeb08eb1f8274 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:31 +0800 Subject: [PATCH 196/256] scsi: hisi_sas: alloc queue id of slot according to device id Currently slots are allocated from queues in a round-robin fashion. This causes a problem for internal commands in device mode. For this mode, we should ensure that the internal abort command is the last command seen in the host for that device. We can only ensure this when we place the internal abort command after the preceding commands for device that in the same queue, as there is no order in which the host will select a queue to execute the next command. This queue restriction makes supporting scsi mq more tricky in the future, but should not be a blocker. Note: Even though v1 hw does not support internal abort, the allocation method is chosen to be the same for consistency. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 4 ++-- drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +++---- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 28 ++++++++++--------------- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 29 +++++++++++--------------- 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 64046c5853a5..bf59fab77765 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -150,7 +150,8 @@ struct hisi_sas_hw { struct domain_device *device); struct hisi_sas_device *(*alloc_dev)(struct domain_device *device); void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no); - int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s); + int (*get_free_slot)(struct hisi_hba *hisi_hba, u32 dev_id, + int *q, int *s); void (*start_delivery)(struct hisi_hba *hisi_hba); int (*prep_ssp)(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, int is_tmf, @@ -207,7 +208,6 @@ struct hisi_hba { struct hisi_sas_port port[HISI_SAS_MAX_PHYS]; int queue_count; - int queue; struct hisi_sas_slot *slot_prep; struct dma_pool *sge_page_pool; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9afc6978cb77..9f5ccc59075a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -232,8 +232,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); if (rc) goto err_out; - rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue, - &dlvry_queue_slot); + rc = hisi_hba->hw->get_free_slot(hisi_hba, sas_dev->device_id, + &dlvry_queue, &dlvry_queue_slot); if (rc) goto err_out_tag; @@ -987,8 +987,8 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id, rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); if (rc) goto err_out; - rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue, - &dlvry_queue_slot); + rc = hisi_hba->hw->get_free_slot(hisi_hba, sas_dev->device_id, + &dlvry_queue, &dlvry_queue_slot); if (rc) goto err_out_tag; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index c0ac49d8bc8d..bbc5760dfaf4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -862,29 +862,23 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) * The callpath to this function and upto writing the write * queue pointer should be safe from interruption. */ -static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s) +static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, u32 dev_id, + int *q, int *s) { struct device *dev = &hisi_hba->pdev->dev; struct hisi_sas_dq *dq; u32 r, w; - int queue = hisi_hba->queue; + int queue = dev_id % hisi_hba->queue_count; - while (1) { - dq = &hisi_hba->dq[queue]; - w = dq->wr_point; - r = hisi_sas_read32_relaxed(hisi_hba, - DLVRY_Q_0_RD_PTR + (queue * 0x14)); - if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { - queue = (queue + 1) % hisi_hba->queue_count; - if (queue == hisi_hba->queue) { - dev_warn(dev, "could not find free slot\n"); - return -EAGAIN; - } - continue; - } - break; + dq = &hisi_hba->dq[queue]; + w = dq->wr_point; + r = hisi_sas_read32_relaxed(hisi_hba, + DLVRY_Q_0_RD_PTR + (queue * 0x14)); + if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { + dev_warn(dev, "could not find free slot\n"); + return -EAGAIN; } - hisi_hba->queue = (queue + 1) % hisi_hba->queue_count; + *q = queue; *s = w; return 0; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 9e70e6d64724..cb19e73457c8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1089,29 +1089,24 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) * The callpath to this function and upto writing the write * queue pointer should be safe from interruption. */ -static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s) +static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, u32 dev_id, + int *q, int *s) { struct device *dev = &hisi_hba->pdev->dev; struct hisi_sas_dq *dq; u32 r, w; - int queue = hisi_hba->queue; + int queue = dev_id % hisi_hba->queue_count; - while (1) { - dq = &hisi_hba->dq[queue]; - w = dq->wr_point; - r = hisi_sas_read32_relaxed(hisi_hba, - DLVRY_Q_0_RD_PTR + (queue * 0x14)); - if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { - queue = (queue + 1) % hisi_hba->queue_count; - if (queue == hisi_hba->queue) { - dev_warn(dev, "could not find free slot\n"); - return -EAGAIN; - } - continue; - } - break; + dq = &hisi_hba->dq[queue]; + w = dq->wr_point; + r = hisi_sas_read32_relaxed(hisi_hba, + DLVRY_Q_0_RD_PTR + (queue * 0x14)); + if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { + dev_warn(dev, "full queue=%d r=%d w=%d\n\n", + queue, r, w); + return -EAGAIN; } - hisi_hba->queue = (queue + 1) % hisi_hba->queue_count; + *q = queue; *s = w; return 0; From 85080a253a188d76933f15426c49e97f63797d6c Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:32 +0800 Subject: [PATCH 197/256] scsi: hisi_sas: only process broadcast change in phy_bcast_v2_hw() There are many BROADCAST primitives generated by the host. We are only interested in BROADCAST (CHANGE) primitives currently, so only process this. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cb19e73457c8..75671936e4cc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -194,6 +194,9 @@ #define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF) #define SL_CONTROL_CTA_OFF 17 #define SL_CONTROL_CTA_MSK (0x1 << SL_CONTROL_CTA_OFF) +#define RX_PRIMS_STATUS (PORT_BASE + 0x98) +#define RX_BCAST_CHG_OFF 1 +#define RX_BCAST_CHG_MSK (0x1 << RX_BCAST_CHG_OFF) #define TX_ID_DWORD0 (PORT_BASE + 0x9c) #define TX_ID_DWORD1 (PORT_BASE + 0xa0) #define TX_ID_DWORD2 (PORT_BASE + 0xa4) @@ -2044,9 +2047,12 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba) struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct sas_ha_struct *sas_ha = &hisi_hba->sha; + u32 bcast_status; hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); + if (bcast_status & RX_BCAST_CHG_MSK) + sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_SL_RX_BCST_ACK_MSK); hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); From 1d7e9469ef0e10d20f92fa36dee41c0fa7fc91e8 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:33 +0800 Subject: [PATCH 198/256] scsi: hisi_sas: fix port form bug in hisi_sas_port_notify_formed() When we form a wideport, we should use hardware PHY port_id instead of sas_phy->id. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9f5ccc59075a..486aa927f92e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -537,7 +537,7 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy) struct hisi_hba *hisi_hba = sas_ha->lldd_ha; struct hisi_sas_phy *phy = sas_phy->lldd_phy; struct asd_sas_port *sas_port = sas_phy->port; - struct hisi_sas_port *port = &hisi_hba->port[sas_phy->id]; + struct hisi_sas_port *port = &hisi_hba->port[phy->port_id]; unsigned long flags; if (!sas_port) From d2d7e7a03eb3c38c5680f0d18244887c255c7bf3 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:34 +0800 Subject: [PATCH 199/256] scsi: hisi_sas: replace WARN_ON() with dev_warn() for internal abort Replace WARN_ON() with dev_warn() print when internal abort fails. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 486aa927f92e..9133238810ee 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -764,7 +764,8 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, task = NULL; } ex_err: - WARN_ON(retry == TASK_RETRY); + if (retry == TASK_RETRY) + dev_warn(dev, "abort tmf: executing internal task failed!\n"); sas_free_task(task); return res; } From 997ee43c3a7554c21848aaf734d7014253787091 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:35 +0800 Subject: [PATCH 200/256] scsi: hisi_sas: modify return value of hisi_sas_query_task() sas_scsi_find_task() only deals with return value TMF_RESP_FUNC_FAILED/TMF_RESP_FUNC_SUCC/TMF_RESP_FUNC_COMPLETE of query task. So for LLDD errors just return TMF_RESP_FUNC_FAILED. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9133238810ee..504cbcff45a6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -961,6 +961,9 @@ static int hisi_sas_query_task(struct sas_task *task) case TMF_RESP_FUNC_FAILED: case TMF_RESP_FUNC_COMPLETE: break; + default: + rc = TMF_RESP_FUNC_FAILED; + break; } } return rc; From 04b7f431da23241e3beaa61883fb6b74627bc5ac Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:36 +0800 Subject: [PATCH 201/256] scsi: hisi_sas: delete repeated configuration in free_device_v2_hw() Delete repeated configuration items for hisi_sas_device() when we free a device. These items are now only set in hisi_sas_dev_gone(). Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 75671936e4cc..3081eec77eb4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -739,8 +739,6 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba, qw0 &= ~(1 << ITCT_HDR_VALID_OFF); hisi_sas_write32(hisi_hba, ENT_INT_SRC3, ENT_INT_SRC3_ITC_INT_MSK); - hisi_hba->devices[dev_id].dev_type = SAS_PHY_UNUSED; - hisi_hba->devices[dev_id].dev_status = HISI_SAS_DEV_NORMAL; /* clear the itct */ hisi_sas_write32(hisi_hba, ITCT_CLR, 0); From ee44bfe45769b3c73b995438f63e31363953933c Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:37 +0800 Subject: [PATCH 202/256] scsi: hisi_sas: modify some values in get_ata_protocol() Modify and add some SATA commands according to SATA protocol. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 3081eec77eb4..a5faa4d9a48b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1750,6 +1750,7 @@ static u8 get_ata_protocol(u8 cmd, int direction) case ATA_CMD_NCQ_NON_DATA: return SATA_PROTOCOL_FPDMA; + case ATA_CMD_DOWNLOAD_MICRO: case ATA_CMD_ID_ATA: case ATA_CMD_PMP_READ: case ATA_CMD_READ_LOG_EXT: @@ -1761,18 +1762,27 @@ static u8 get_ata_protocol(u8 cmd, int direction) case ATA_CMD_PIO_WRITE_EXT: return SATA_PROTOCOL_PIO; + case ATA_CMD_DSM: + case ATA_CMD_DOWNLOAD_MICRO_DMA: + case ATA_CMD_PMP_READ_DMA: + case ATA_CMD_PMP_WRITE_DMA: case ATA_CMD_READ: case ATA_CMD_READ_EXT: case ATA_CMD_READ_LOG_DMA_EXT: + case ATA_CMD_READ_STREAM_DMA_EXT: + case ATA_CMD_TRUSTED_RCV_DMA: + case ATA_CMD_TRUSTED_SND_DMA: case ATA_CMD_WRITE: case ATA_CMD_WRITE_EXT: + case ATA_CMD_WRITE_FUA_EXT: case ATA_CMD_WRITE_QUEUED: case ATA_CMD_WRITE_LOG_DMA_EXT: + case ATA_CMD_WRITE_STREAM_DMA_EXT: return SATA_PROTOCOL_DMA; - case ATA_CMD_DOWNLOAD_MICRO: - case ATA_CMD_DEV_RESET: case ATA_CMD_CHK_POWER: + case ATA_CMD_DEV_RESET: + case ATA_CMD_EDD: case ATA_CMD_FLUSH: case ATA_CMD_FLUSH_EXT: case ATA_CMD_VERIFY: From 04708ff4c29522927de46424637e5a7c835a2e88 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:38 +0800 Subject: [PATCH 203/256] scsi: hisi_sas: check SATA FIS when directly attaching SATA device Check ERR bit of status to decide whether there is something wrong with initial register-D2H FIS. If error exists, PHY reset the channel to restart OOB. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index a5faa4d9a48b..cda3baf9423d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2537,6 +2537,16 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) goto end; } + /* check ERR bit of Status Register */ + if (fis->status & ATA_ERR) { + dev_warn(dev, "sata int: phy%d FIS status: 0x%x\n", phy_no, + fis->status); + disable_phy_v2_hw(hisi_hba, phy_no); + enable_phy_v2_hw(hisi_hba, phy_no); + res = IRQ_NONE; + goto end; + } + if (unlikely(phy_no == 8)) { u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE); From f696cc32b5984eb73f6b1ff81929ca9e5ea22d6d Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 7 Nov 2016 20:48:39 +0800 Subject: [PATCH 204/256] scsi: hisi_sas: use atomic64_t for hisi_sas_device.running_req Sometimes the value of hisi_sas_device.running_req would go negative unless we have the check for running_req >= 0 before trying to decrement. This is because using running_req is not thread-safe. As such, the value for running_req may be actually incorrect, so use atomic64_t instead. Signed-off-by: John Garry Reviewed-by: Xiang Chen Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 2 +- drivers/scsi/hisi_sas/hisi_sas_main.c | 9 +++++---- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 ++-- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index bf59fab77765..8b5ecc697fee 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -111,7 +111,7 @@ struct hisi_sas_device { struct domain_device *sas_device; u64 attached_phy; u64 device_id; - u64 running_req; + atomic64_t running_req; u8 dev_status; }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 504cbcff45a6..18e219408b76 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -162,8 +162,8 @@ out: hisi_sas_slot_task_free(hisi_hba, task, abort_slot); if (task->task_done) task->task_done(task); - if (sas_dev && sas_dev->running_req) - sas_dev->running_req--; + if (sas_dev) + atomic64_dec(&sas_dev->running_req); } static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, @@ -303,7 +303,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, hisi_hba->slot_prep = slot; - sas_dev->running_req++; + atomic64_inc(&sas_dev->running_req); ++(*pass); return 0; @@ -1027,7 +1027,8 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id, hisi_hba->slot_prep = slot; - sas_dev->running_req++; + atomic64_inc(&sas_dev->running_req); + /* send abort command to our chip */ hisi_hba->hw->start_delivery(hisi_hba); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index bbc5760dfaf4..05177fcb5179 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1366,8 +1366,8 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, } out: - if (sas_dev && sas_dev->running_req) - sas_dev->running_req--; + if (sas_dev) + atomic64_dec(&sas_dev->running_req); hisi_sas_slot_task_free(hisi_hba, task, slot); sts = ts->stat; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cda3baf9423d..e88113aff396 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1728,8 +1728,8 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, } out: - if (sas_dev && sas_dev->running_req) - sas_dev->running_req--; + if (sas_dev) + atomic64_dec(&sas_dev->running_req); hisi_sas_slot_task_free(hisi_hba, task, slot); sts = ts->stat; From 2ae757871f48c7d361e093e50d686aba1e47c3d2 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 7 Nov 2016 20:48:40 +0800 Subject: [PATCH 205/256] scsi: hisi_sas: add PHY set linkrate support for v1 and v2 hw Add the function to set PHY min and max linkrate through sysfs interface. Signed-off-by: Xiang Chen Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 3 ++ drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +++++-- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 45 ++++++++++++++++++++++++++ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 45 ++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 8b5ecc697fee..c0cd505a9ef7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -168,6 +168,9 @@ struct hisi_sas_hw { void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no); void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no); void (*phy_hard_reset)(struct hisi_hba *hisi_hba, int phy_no); + void (*phy_set_linkrate)(struct hisi_hba *hisi_hba, int phy_no, + struct sas_phy_linkrates *linkrates); + enum sas_linkrate (*phy_get_max_linkrate)(void); void (*free_device)(struct hisi_hba *hisi_hba, struct hisi_sas_device *dev); int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 18e219408b76..6d6f150d8aed 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -369,9 +369,14 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) struct sas_phy *sphy = sas_phy->phy; sphy->negotiated_linkrate = sas_phy->linkrate; - sphy->minimum_linkrate = phy->minimum_linkrate; sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; - sphy->maximum_linkrate = phy->maximum_linkrate; + sphy->maximum_linkrate_hw = + hisi_hba->hw->phy_get_max_linkrate(); + if (sphy->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) + sphy->minimum_linkrate = phy->minimum_linkrate; + + if (sphy->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) + sphy->maximum_linkrate = phy->maximum_linkrate; } if (phy->phy_type & PORT_TYPE_SAS) { @@ -645,6 +650,9 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, break; case PHY_FUNC_SET_LINK_RATE: + hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, funcdata); + break; + case PHY_FUNC_RELEASE_SPINUP_HOLD: default: return -EOPNOTSUPP; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 05177fcb5179..8a1be0ba8a22 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -843,6 +843,49 @@ static void sl_notify_v1_hw(struct hisi_hba *hisi_hba, int phy_no) hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control); } +static enum sas_linkrate phy_get_max_linkrate_v1_hw(void) +{ + return SAS_LINK_RATE_6_0_GBPS; +} + +static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no, + struct sas_phy_linkrates *r) +{ + u32 prog_phy_link_rate = + hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE); + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + int i; + enum sas_linkrate min, max; + u32 rate_mask = 0; + + if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) { + max = sas_phy->phy->maximum_linkrate; + min = r->minimum_linkrate; + } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) { + max = r->maximum_linkrate; + min = sas_phy->phy->minimum_linkrate; + } else + return; + + sas_phy->phy->maximum_linkrate = max; + sas_phy->phy->minimum_linkrate = min; + + min -= SAS_LINK_RATE_1_5_GBPS; + max -= SAS_LINK_RATE_1_5_GBPS; + + for (i = 0; i <= max; i++) + rate_mask |= 1 << (i * 2); + + prog_phy_link_rate &= ~0xff; + prog_phy_link_rate |= rate_mask; + + hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, + prog_phy_link_rate); + + phy_hard_reset_v1_hw(hisi_hba, phy_no); +} + static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) { int i, bitmap = 0; @@ -1818,6 +1861,8 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = { .phy_enable = enable_phy_v1_hw, .phy_disable = disable_phy_v1_hw, .phy_hard_reset = phy_hard_reset_v1_hw, + .phy_set_linkrate = phy_set_linkrate_v1_hw, + .phy_get_max_linkrate = phy_get_max_linkrate_v1_hw, .get_wideport_bitmap = get_wideport_bitmap_v1_hw, .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V1_HW, .complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr), diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index e88113aff396..15487f2bd141 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1060,6 +1060,49 @@ static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int phy_no) hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control); } +static enum sas_linkrate phy_get_max_linkrate_v2_hw(void) +{ + return SAS_LINK_RATE_12_0_GBPS; +} + +static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no, + struct sas_phy_linkrates *r) +{ + u32 prog_phy_link_rate = + hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE); + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + int i; + enum sas_linkrate min, max; + u32 rate_mask = 0; + + if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) { + max = sas_phy->phy->maximum_linkrate; + min = r->minimum_linkrate; + } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) { + max = r->maximum_linkrate; + min = sas_phy->phy->minimum_linkrate; + } else + return; + + sas_phy->phy->maximum_linkrate = max; + sas_phy->phy->minimum_linkrate = min; + + min -= SAS_LINK_RATE_1_5_GBPS; + max -= SAS_LINK_RATE_1_5_GBPS; + + for (i = 0; i <= max; i++) + rate_mask |= 1 << (i * 2); + + prog_phy_link_rate &= ~0xff; + prog_phy_link_rate |= rate_mask; + + hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, + prog_phy_link_rate); + + phy_hard_reset_v2_hw(hisi_hba, phy_no); +} + static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) { int i, bitmap = 0; @@ -2739,6 +2782,8 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .phy_enable = enable_phy_v2_hw, .phy_disable = disable_phy_v2_hw, .phy_hard_reset = phy_hard_reset_v2_hw, + .phy_set_linkrate = phy_set_linkrate_v2_hw, + .phy_get_max_linkrate = phy_get_max_linkrate_v2_hw, .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW, .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr), }; From 679882ae580554d3c6627e66291c72b348656382 Mon Sep 17 00:00:00 2001 From: Santosh Y Date: Thu, 24 Nov 2016 12:58:51 +0800 Subject: [PATCH 206/256] scsi: ufs: Add missing UFS_MASK macro definition Reported-by: Venkatraman S Reviewed-by: Vinayak Holikatti Signed-off-by: Santosh Y Signed-off-by: Zhangfei Gao Reviewed-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 9599741ff606..bbd8df96d249 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -83,6 +83,8 @@ enum { MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, }; +#define UFS_MASK(mask, offset) ((mask) << (offset)) + /* UFS Version 08h */ #define MINOR_VERSION_NUM_MASK UFS_MASK(0xFFFF, 0) #define MAJOR_VERSION_NUM_MASK UFS_MASK(0xFFFF, 16) From 27c3d76821a5f563cd3d760bfa7c8deb43f8d874 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2016 13:52:38 +0300 Subject: [PATCH 207/256] scsi: libfc: Remove an unneeded condition We verified that resp_code is FC_SPP_RESP_ACK earlier so we don't need to check again here. Signed-off-by: Dan Carpenter Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 110a707d8e82..c991f3b822f8 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1196,7 +1196,6 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, * Check if the image pair could be established */ if (rdata->spp_type != FC_TYPE_FCP || - resp_code != FC_SPP_RESP_ACK || !(pp->spp.spp_flags & FC_SPP_EST_IMG_PAIR)) { /* * Nope; we can't use this port as a target. From 669f044170d8933c3d66d231b69ea97cb8447338 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 22 Nov 2016 16:17:13 -0800 Subject: [PATCH 208/256] scsi: srp_transport: Move queuecommand() wait code to SCSI core Additionally, rename srp_wait_for_queuecommand() into scsi_wait_for_queuecommand() and add a comment about the queuecommand() call from scsi_send_eh_cmnd(). Note: this patch changes scsi_internal_device_block from a function that did not sleep into a function that may sleep. This is fine for all callers of this function: * scsi_internal_device_block() is called from the mpt3sas device while that driver holds the ioc->dm_cmds.mutex. This means that the mpt3sas driver calls this function from thread context. * scsi_target_block() is called by __iscsi_block_session() from kernel thread context and with IRQs enabled. * The SRP transport code also calls scsi_target_block() from kernel thread context while sleeping is allowed. * The snic driver also calls scsi_target_block() from a context from which sleeping is allowed. The scsi_target_block() call namely occurs immediately after a scsi_flush_work() call. [mkp: s/shost/sdev/] Signed-off-by: Bart Van Assche Reviewed-by: Sagi Grimberg Reviewed-by: Martin K. Petersen Cc: James Bottomley Cc: Christoph Hellwig Cc: Doug Ledford Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 41 +++++++++++++++++++++++++++++-- drivers/scsi/scsi_transport_srp.c | 41 +++++-------------------------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f23ec240cab0..0f81add6025e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2733,6 +2733,39 @@ void sdev_evt_send_simple(struct scsi_device *sdev, } EXPORT_SYMBOL_GPL(sdev_evt_send_simple); +/** + * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn() + * @sdev: SCSI device to count the number of scsi_request_fn() callers for. + */ +static int scsi_request_fn_active(struct scsi_device *sdev) +{ + struct request_queue *q = sdev->request_queue; + int request_fn_active; + + WARN_ON_ONCE(sdev->host->use_blk_mq); + + spin_lock_irq(q->queue_lock); + request_fn_active = q->request_fn_active; + spin_unlock_irq(q->queue_lock); + + return request_fn_active; +} + +/** + * scsi_wait_for_queuecommand() - wait for ongoing queuecommand() calls + * @sdev: SCSI device pointer. + * + * Wait until the ongoing shost->hostt->queuecommand() calls that are + * invoked from scsi_request_fn() have finished. + */ +static void scsi_wait_for_queuecommand(struct scsi_device *sdev) +{ + WARN_ON_ONCE(sdev->host->use_blk_mq); + + while (scsi_request_fn_active(sdev)) + msleep(20); +} + /** * scsi_device_quiesce - Block user issued commands. * @sdev: scsi device to quiesce. @@ -2817,8 +2850,7 @@ EXPORT_SYMBOL(scsi_target_resume); * @sdev: device to block * * Block request made by scsi lld's to temporarily stop all - * scsi commands on the specified device. Called from interrupt - * or normal process context. + * scsi commands on the specified device. May sleep. * * Returns zero if successful or error if not * @@ -2827,6 +2859,10 @@ EXPORT_SYMBOL(scsi_target_resume); * (which must be a legal transition). When the device is in this * state, all commands are deferred until the scsi lld reenables * the device with scsi_device_unblock or device_block_tmo fires. + * + * To do: avoid that scsi_send_eh_cmnd() calls queuecommand() after + * scsi_internal_device_block() has blocked a SCSI device and also + * remove the rport mutex lock and unlock calls from srp_queuecommand(). */ int scsi_internal_device_block(struct scsi_device *sdev) @@ -2854,6 +2890,7 @@ scsi_internal_device_block(struct scsi_device *sdev) spin_lock_irqsave(q->queue_lock, flags); blk_stop_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); + scsi_wait_for_queuecommand(sdev); } return 0; diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 02cfc6b1ee5a..b87a78673f65 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -393,36 +392,6 @@ static void srp_reconnect_work(struct work_struct *work) } } -/** - * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn() - * @shost: SCSI host for which to count the number of scsi_request_fn() callers. - * - * To do: add support for scsi-mq in this function. - */ -static int scsi_request_fn_active(struct Scsi_Host *shost) -{ - struct scsi_device *sdev; - struct request_queue *q; - int request_fn_active = 0; - - shost_for_each_device(sdev, shost) { - q = sdev->request_queue; - - spin_lock_irq(q->queue_lock); - request_fn_active += q->request_fn_active; - spin_unlock_irq(q->queue_lock); - } - - return request_fn_active; -} - -/* Wait until ongoing shost->hostt->queuecommand() calls have finished. */ -static void srp_wait_for_queuecommand(struct Scsi_Host *shost) -{ - while (scsi_request_fn_active(shost)) - msleep(20); -} - static void __rport_fail_io_fast(struct srp_rport *rport) { struct Scsi_Host *shost = rport_to_shost(rport); @@ -432,14 +401,17 @@ static void __rport_fail_io_fast(struct srp_rport *rport) if (srp_rport_set_state(rport, SRP_RPORT_FAIL_FAST)) return; + /* + * Call scsi_target_block() to wait for ongoing shost->queuecommand() + * calls before invoking i->f->terminate_rport_io(). + */ + scsi_target_block(rport->dev.parent); scsi_target_unblock(rport->dev.parent, SDEV_TRANSPORT_OFFLINE); /* Involve the LLD if possible to terminate all I/O on the rport. */ i = to_srp_internal(shost->transportt); - if (i->f->terminate_rport_io) { - srp_wait_for_queuecommand(shost); + if (i->f->terminate_rport_io) i->f->terminate_rport_io(rport); - } } /** @@ -567,7 +539,6 @@ int srp_reconnect_rport(struct srp_rport *rport) if (res) goto out; scsi_target_block(&shost->shost_gendev); - srp_wait_for_queuecommand(shost); res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; pr_debug("%s (state %d): transport.reconnect() returned %d\n", dev_name(&shost->shost_gendev), rport->state, res); From 1ccde7004ff66cdcbe4c8005f3bb44dda6ab0b99 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 18 Nov 2016 08:32:47 +0100 Subject: [PATCH 209/256] scsi: hpsa: use correct DID_NO_CONNECT hostbyte NOT_READY is a sense key, not a legit scsi hostbyte value. Use DID_NO_CONNECT instead. Signed-off-by: Hannes Reinecke Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5b1ba5861275..b9f1bab4dfb7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -5487,7 +5487,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) dev = cmd->device->hostdata; if (!dev) { - cmd->result = NOT_READY << 16; /* host byte */ + cmd->result = DID_NO_CONNECT << 16; cmd->scsi_done(cmd); return 0; } From 16961204a0ebcb87b89ed3be14b0a484c754d7e4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 18 Nov 2016 08:32:49 +0100 Subject: [PATCH 210/256] scsi: hpsa: add 'ctlr_num' sysfs attribute Add a sysfs attribute 'ctlr_num' holding the current HPSA controller number. This is required to construct compability 'cciss' links. [mkp: fixed typo] Signed-off-by: Hannes Reinecke Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b9f1bab4dfb7..216c137d96ea 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -867,6 +867,16 @@ static ssize_t path_info_show(struct device *dev, return output_len; } +static ssize_t host_show_ctlr_num(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctlr_info *h; + struct Scsi_Host *shost = class_to_shost(dev); + + h = shost_to_hba(shost); + return snprintf(buf, 20, "%d\n", h->ctlr); +} + static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); @@ -890,6 +900,8 @@ static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL); static DEVICE_ATTR(lockup_detected, S_IRUGO, host_show_lockup_detected, NULL); +static DEVICE_ATTR(ctlr_num, S_IRUGO, + host_show_ctlr_num, NULL); static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_raid_level, @@ -910,6 +922,7 @@ static struct device_attribute *hpsa_shost_attrs[] = { &dev_attr_hp_ssd_smart_path_status, &dev_attr_raid_offload_debug, &dev_attr_lockup_detected, + &dev_attr_ctlr_num, NULL, }; From aa8c65a4fdc881b32c012c45f985617659aef1a9 Mon Sep 17 00:00:00 2001 From: Quentin Lambert Date: Fri, 25 Nov 2016 13:23:51 +0100 Subject: [PATCH 211/256] scsi: aic94xx: Add a missing call to kfree Most error branches following the call to kzalloc contain a call to kfree. This patch add these calls where they are missing and set the relevant pointers to NULL. This issue was found with Hector. Signed-off-by: Quentin Lambert Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/aic94xx/aic94xx_hwi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 7c713f797535..f2671a8fa7e3 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -228,8 +228,11 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha) bitmap_bytes = (asd_ha->seq.tc_index_bitmap_bits+7)/8; bitmap_bytes = BITS_TO_LONGS(bitmap_bytes*8)*sizeof(unsigned long); asd_ha->seq.tc_index_bitmap = kzalloc(bitmap_bytes, GFP_KERNEL); - if (!asd_ha->seq.tc_index_bitmap) + if (!asd_ha->seq.tc_index_bitmap) { + kfree(asd_ha->seq.tc_index_array); + asd_ha->seq.tc_index_array = NULL; return -ENOMEM; + } spin_lock_init(&seq->tc_index_lock); From ce41b41e190b04a0c147fbde02c04379a6331d0a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Nov 2016 13:47:25 +0300 Subject: [PATCH 212/256] scsi: hisi_sas: shift vs compare typos There are some typos where we intended "<<" but have "<". Seems likely to cause a bunch of problems. Fixes: d3b688d3c69d ("scsi: hisi_sas: add v2 hw support for ECC and AXI bus fatal error") Signed-off-by: Dan Carpenter Acked-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 15487f2bd141..93876c0137eb 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -64,19 +64,19 @@ HGC_LM_DFX_STATUS2_ITCTLIST_OFF) #define HGC_CQE_ECC_ADDR 0x13c #define HGC_CQE_ECC_1B_ADDR_OFF 0 -#define HGC_CQE_ECC_1B_ADDR_MSK (0x3f < HGC_CQE_ECC_1B_ADDR_OFF) +#define HGC_CQE_ECC_1B_ADDR_MSK (0x3f << HGC_CQE_ECC_1B_ADDR_OFF) #define HGC_CQE_ECC_MB_ADDR_OFF 8 -#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f < HGC_CQE_ECC_MB_ADDR_OFF) +#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f << HGC_CQE_ECC_MB_ADDR_OFF) #define HGC_IOST_ECC_ADDR 0x140 #define HGC_IOST_ECC_1B_ADDR_OFF 0 -#define HGC_IOST_ECC_1B_ADDR_MSK (0x3ff < HGC_IOST_ECC_1B_ADDR_OFF) +#define HGC_IOST_ECC_1B_ADDR_MSK (0x3ff << HGC_IOST_ECC_1B_ADDR_OFF) #define HGC_IOST_ECC_MB_ADDR_OFF 16 -#define HGC_IOST_ECC_MB_ADDR_MSK (0x3ff < HGC_IOST_ECC_MB_ADDR_OFF) +#define HGC_IOST_ECC_MB_ADDR_MSK (0x3ff << HGC_IOST_ECC_MB_ADDR_OFF) #define HGC_DQE_ECC_ADDR 0x144 #define HGC_DQE_ECC_1B_ADDR_OFF 0 -#define HGC_DQE_ECC_1B_ADDR_MSK (0xfff < HGC_DQE_ECC_1B_ADDR_OFF) +#define HGC_DQE_ECC_1B_ADDR_MSK (0xfff << HGC_DQE_ECC_1B_ADDR_OFF) #define HGC_DQE_ECC_MB_ADDR_OFF 16 -#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff < HGC_DQE_ECC_MB_ADDR_OFF) +#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF) #define HGC_INVLD_DQE_INFO 0x148 #define HGC_INVLD_DQE_INFO_FB_CH0_OFF 9 #define HGC_INVLD_DQE_INFO_FB_CH0_MSK (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF) From 5cfa2a3c7342bd0b50716c8bb32ee491af43c785 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 18 Nov 2016 17:14:01 +0100 Subject: [PATCH 213/256] scsi: isci: avoid array subscript warning I'm getting a new warning with gcc-7: isci/remote_node_context.c: In function 'sci_remote_node_context_destruct': isci/remote_node_context.c:69:16: error: array subscript is above array bounds [-Werror=array-bounds] This is odd, since we clearly cover all values for enum scis_sds_remote_node_context_states here. Anyway, checking for an array overflow can't harm and it makes the warning go away. Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/remote_node_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 30bd80052e03..e3f2a5359d71 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -66,6 +66,9 @@ const char *rnc_state_name(enum scis_sds_remote_node_context_states state) { static const char * const strings[] = RNC_STATES; + if (state >= ARRAY_SIZE(strings)) + return "UNKNOWN"; + return strings[state]; } #undef C From b1509e5d2b478f362dbadfe721d5efc0162e3c8e Mon Sep 17 00:00:00 2001 From: Quentin Lambert Date: Sat, 19 Nov 2016 18:43:40 +0100 Subject: [PATCH 214/256] scsi: isci: Add a missing call to pci_unmap_biosrom Most error branches following the call to pci_map_biosrom contain a call to pci_unmap_biosrom. This patch add these calls where they are missing. This issue was found with Hector. Signed-off-by: Quentin Lambert Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/probe_roms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 8ac646e5eddc..a2bbe46f8ccb 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -54,6 +54,7 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) len = pci_biosrom_size(pdev); rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); if (!rom) { + pci_unmap_biosrom(oprom); dev_warn(&pdev->dev, "Unable to allocate memory for orom\n"); return NULL; From 021e2927586dafc0a682b7f95d75bd06cc4fb703 Mon Sep 17 00:00:00 2001 From: Quentin Lambert Date: Sat, 19 Nov 2016 18:42:34 +0100 Subject: [PATCH 215/256] scsi: dpt_i2o: Add a missing call to kfree Most error branches following the call to kzalloc contain a call to kfree. This patch add these calls where they are missing. This issue was found with Hector. Signed-off-by: Quentin Lambert Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index d84004b5d3e0..f88b3d216a88 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -1754,8 +1754,10 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) sg_offset = (msg[0]>>4)&0xf; msg[2] = 0x40000000; // IOCTL context msg[3] = adpt_ioctl_to_context(pHba, reply); - if (msg[3] == (u32)-1) + if (msg[3] == (u32)-1) { + kfree(reply); return -EBUSY; + } memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize); if(sg_offset) { From 61e073590b82a539654626ecae91b8fab11db3f3 Mon Sep 17 00:00:00 2001 From: Dolev Raviv Date: Wed, 23 Nov 2016 16:30:49 -0800 Subject: [PATCH 216/256] scsi: ufs: add queries retry mechanism Some of the queries might fail during init. To avoid system failure, we add retry mechanism to issue queries several times. Signed-off-by: Dolev Raviv Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 54 ++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index f91e50bf1a43..0b278a1596c5 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2141,7 +2141,18 @@ static inline int ufshcd_read_power_desc(struct ufs_hba *hba, u8 *buf, u32 size) { - return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size); + int err = 0; + int retries; + + for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { + /* Read descriptor*/ + err = ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size); + if (!err) + break; + dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err); + } + + return err; } int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size) @@ -3251,16 +3262,24 @@ static void ufshcd_set_queue_depth(struct scsi_device *sdev) { int ret = 0; u8 lun_qdepth; + int retries; struct ufs_hba *hba; hba = shost_priv(sdev->host); lun_qdepth = hba->nutrs; - ret = ufshcd_read_unit_desc_param(hba, - ufshcd_scsi_to_upiu_lun(sdev->lun), - UNIT_DESC_PARAM_LU_Q_DEPTH, - &lun_qdepth, - sizeof(lun_qdepth)); + for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { + /* Read descriptor*/ + ret = ufshcd_read_unit_desc_param(hba, + ufshcd_scsi_to_upiu_lun(sdev->lun), + UNIT_DESC_PARAM_LU_Q_DEPTH, + &lun_qdepth, + sizeof(lun_qdepth)); + if (!ret || ret == -ENOTSUPP) + break; + + dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, ret); + } /* Some WLUN doesn't support unit descriptor */ if (ret == -EOPNOTSUPP) @@ -4796,6 +4815,24 @@ out: return icc_level; } +static int ufshcd_set_icc_levels_attr(struct ufs_hba *hba, u32 icc_level) +{ + int ret = 0; + int retries; + + for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { + /* write attribute */ + ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, + QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, &icc_level); + if (!ret) + break; + + dev_dbg(hba->dev, "%s: failed with error %d\n", __func__, ret); + } + + return ret; +} + static void ufshcd_init_icc_levels(struct ufs_hba *hba) { int ret; @@ -4816,9 +4853,8 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, hba->init_prefetch_data.icc_level); - ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, - QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, - &hba->init_prefetch_data.icc_level); + ret = ufshcd_set_icc_levels_attr(hba, + hba->init_prefetch_data.icc_level); if (ret) dev_err(hba->dev, From 4b761b580150b081e6829885afd3d540b746ccf0 Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Wed, 23 Nov 2016 16:31:18 -0800 Subject: [PATCH 217/256] scsi: ufs: add index details to query error messages When sending query to the device, the index of the failure is additional useful information that should be printed out as it might specify the logical unit (LU) where the error occurred. Signed-off-by: Yaniv Gardi Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0b278a1596c5..9abc11e77a55 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1914,8 +1914,8 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); if (err) { - dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", - __func__, opcode, idn, err); + dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, index %d, err = %d\n", + __func__, opcode, idn, index, err); goto out_unlock; } @@ -2014,8 +2014,8 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); if (err) { - dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", - __func__, opcode, idn, err); + dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, index %d, err = %d\n", + __func__, opcode, idn, index, err); goto out_unlock; } @@ -2112,8 +2112,9 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba, (desc_buf[QUERY_DESC_LENGTH_OFFSET] != ufs_query_desc_max_size[desc_id]) || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) { - dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d", - __func__, desc_id, param_offset, buff_len, ret); + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, param_offset %d, buff_len %d ,index %d, ret %d", + __func__, desc_id, param_offset, buff_len, + desc_index, ret); if (!ret) ret = -EINVAL; From 24d6243204633be4b710754f279b3ca57c69ceec Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Wed, 23 Nov 2016 16:31:30 -0800 Subject: [PATCH 218/256] scsi: ufs: update device descriptor maximum size According to JESD220B - UFS v2.0, the maximum size of device descriptor has changed from 0x1F to 0x40. This patch updates the maximum size of this descriptor. Signed-off-by: Yaniv Gardi Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 7a6ccb680049..8e6709a3fb6b 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -163,7 +163,7 @@ enum desc_header_offset { }; enum ufs_desc_max_size { - QUERY_DESC_DEVICE_MAX_SIZE = 0x1F, + QUERY_DESC_DEVICE_MAX_SIZE = 0x40, QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90, QUERY_DESC_UNIT_MAX_SIZE = 0x23, QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06, From bde44bb665d049468b6a1a2fa7d666434de4f83f Mon Sep 17 00:00:00 2001 From: "subhashj@codeaurora.org" Date: Wed, 23 Nov 2016 16:31:41 -0800 Subject: [PATCH 219/256] scsi: ufs: fix failure to read the string descriptor While reading variable size descriptors (like string descriptor), some UFS devices may report the "LENGTH" (field in "Transaction Specific fields" of Query Response UPIU) same as what was requested in Query Request UPIU instead of reporting the actual size of the variable size descriptor. Although it's safe to ignore the "LENGTH" field for variable size descriptors as we can always derive the length of the descriptor from the descriptor header fields. Hence this change impose the length match check only for fixed size descriptors (for which we always request the correct size as part of Query Request UPIU). Reviewed-by: Venkat Gopalakrishnan Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 40 ++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9abc11e77a55..d6e87dc472c4 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2108,19 +2108,41 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba, desc_id, desc_index, 0, desc_buf, &buff_len); - if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) || - (desc_buf[QUERY_DESC_LENGTH_OFFSET] != - ufs_query_desc_max_size[desc_id]) - || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) { - dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, param_offset %d, buff_len %d ,index %d, ret %d", - __func__, desc_id, param_offset, buff_len, - desc_index, ret); - if (!ret) - ret = -EINVAL; + if (ret) { + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", + __func__, desc_id, desc_index, param_offset, ret); goto out; } + /* Sanity check */ + if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) { + dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header", + __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]); + ret = -EINVAL; + goto out; + } + + /* + * While reading variable size descriptors (like string descriptor), + * some UFS devices may report the "LENGTH" (field in "Transaction + * Specific fields" of Query Response UPIU) same as what was requested + * in Query Request UPIU instead of reporting the actual size of the + * variable size descriptor. + * Although it's safe to ignore the "LENGTH" field for variable size + * descriptors as we can always derive the length of the descriptor from + * the descriptor header fields. Hence this change impose the length + * match check only for fixed size descriptors (for which we always + * request the correct size as part of Query Request UPIU). + */ + if ((desc_id != QUERY_DESC_IDN_STRING) && + (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) { + dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d", + __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]); + ret = -EINVAL; + goto out; + } + if (is_kmalloc) memcpy(param_read_buf, &desc_buf[param_offset], param_size); out: From 10fe5888a40e6afbf1f3166c212c685624cae26b Mon Sep 17 00:00:00 2001 From: "subhashj@codeaurora.org" Date: Wed, 23 Nov 2016 16:31:52 -0800 Subject: [PATCH 220/256] scsi: ufs: increase the scsi query response timeout It is found thats UFS device may take longer than 30ms to respond to query requests and in this case we might run into following scenario: 1. UFS host SW sends a query request to UFS device to read an attribute value. SW uses tag #31 for this purpose. 2. UFS host SW waits for 30ms to get the query response (and doorbell to be cleared by UFS host HW). 3. UFS device doesn't respond back within 30ms hence UFS host SW times out waiting for the query response. 4. UFS host SW clears the tag#31 from UTRLCLR register. 5. UFS host SW waits until UFS host HW to clear tag#31 from the doorbell register. 6. UFS host SW retries the same query request on same tag#31 (sends a query request to device to read an attribute value). 7. UFS host HW gets the query response from the device but this was intended as a query response for the 1st query request sent (step-1). 8. Now UFS device sends another query response to host (for query request sent @step-6). Now there are 2 issues that could happen with above scenario: 1. UFS device should have actually responded back with only one query response but it is found that device may respond back with 2 query responses. 2. If UFS device responds back with 2 resposes on same tag, host HW/SW behaviour isn't predictable. To avoid running into above scenario, we would basically allow device to take longer (upto 1.5 seconds) for query response. Reviewed-by: Gilad Broner Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d6e87dc472c4..393f6d55df5a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -59,15 +59,9 @@ #define NOP_OUT_TIMEOUT 30 /* msecs */ /* Query request retries */ -#define QUERY_REQ_RETRIES 10 +#define QUERY_REQ_RETRIES 3 /* Query request timeout */ -#define QUERY_REQ_TIMEOUT 30 /* msec */ -/* - * Query request timeout for fDeviceInit flag - * fDeviceInit query response time for some devices is too large that default - * QUERY_REQ_TIMEOUT may not be enough for such devices. - */ -#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */ +#define QUERY_REQ_TIMEOUT 1500 /* 1.5 seconds */ /* Task management command timeout */ #define TM_CMD_TIMEOUT 100 /* msecs */ @@ -1842,9 +1836,6 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, goto out_unlock; } - if (idn == QUERY_FLAG_IDN_FDEVICEINIT) - timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT; - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout); if (err) { From c6a6db439868c7ba5cc90d4c461d9697ec731fa1 Mon Sep 17 00:00:00 2001 From: "subhashj@codeaurora.org" Date: Wed, 23 Nov 2016 16:32:08 -0800 Subject: [PATCH 221/256] scsi: ufs: ensure that host pa_tactivate is higher than device Some UFS devices require host PA_TACTIVATE to be higher than device PA_TACTIVATE otherwise it may get stuck during hibern8 sequence. This change allows this by using quirk. Reviewed-by: Venkat Gopalakrishnan Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs_quirks.h | 9 +++++ drivers/scsi/ufs/ufshcd.c | 73 +++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/unipro.h | 4 ++ 3 files changed, 86 insertions(+) diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index 22f881e9253a..f7983058f3f7 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -128,6 +128,13 @@ struct ufs_dev_fix { */ #define UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM (1 << 6) +/* + * Some UFS devices require host PA_TACTIVATE to be lower than device + * PA_TACTIVATE, enabling this quirk ensure this. + */ +#define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 7) + + struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); @@ -140,6 +147,8 @@ static struct ufs_dev_fix ufs_fixups[] = { UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS), UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_FASTAUTO), + UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, + UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG", diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 393f6d55df5a..28cbca21c4dd 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5089,6 +5089,76 @@ out: return ret; } +/** + * ufshcd_quirk_tune_host_pa_tactivate - Ensures that host PA_TACTIVATE is + * less than device PA_TACTIVATE time. + * @hba: per-adapter instance + * + * Some UFS devices require host PA_TACTIVATE to be lower than device + * PA_TACTIVATE, we need to enable UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE quirk + * for such devices. + * + * Returns zero on success, non-zero error value on failure. + */ +static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba) +{ + int ret = 0; + u32 granularity, peer_granularity; + u32 pa_tactivate, peer_pa_tactivate; + u32 pa_tactivate_us, peer_pa_tactivate_us; + u8 gran_to_us_table[] = {1, 4, 8, 16, 32, 100}; + + ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY), + &granularity); + if (ret) + goto out; + + ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY), + &peer_granularity); + if (ret) + goto out; + + if ((granularity < PA_GRANULARITY_MIN_VAL) || + (granularity > PA_GRANULARITY_MAX_VAL)) { + dev_err(hba->dev, "%s: invalid host PA_GRANULARITY %d", + __func__, granularity); + return -EINVAL; + } + + if ((peer_granularity < PA_GRANULARITY_MIN_VAL) || + (peer_granularity > PA_GRANULARITY_MAX_VAL)) { + dev_err(hba->dev, "%s: invalid device PA_GRANULARITY %d", + __func__, peer_granularity); + return -EINVAL; + } + + ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &pa_tactivate); + if (ret) + goto out; + + ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_TACTIVATE), + &peer_pa_tactivate); + if (ret) + goto out; + + pa_tactivate_us = pa_tactivate * gran_to_us_table[granularity - 1]; + peer_pa_tactivate_us = peer_pa_tactivate * + gran_to_us_table[peer_granularity - 1]; + + if (pa_tactivate_us > peer_pa_tactivate_us) { + u32 new_peer_pa_tactivate; + + new_peer_pa_tactivate = pa_tactivate_us / + gran_to_us_table[peer_granularity - 1]; + new_peer_pa_tactivate++; + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TACTIVATE), + new_peer_pa_tactivate); + } + +out: + return ret; +} + static void ufshcd_tune_unipro_params(struct ufs_hba *hba) { if (ufshcd_is_unipro_pa_params_tuning_req(hba)) { @@ -5099,6 +5169,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE) /* set 1ms timeout for PA_TACTIVATE */ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10); + + if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) + ufshcd_quirk_tune_host_pa_tactivate(hba); } /** diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h index eff8b5675575..23129d7b2678 100644 --- a/drivers/scsi/ufs/unipro.h +++ b/drivers/scsi/ufs/unipro.h @@ -123,6 +123,7 @@ #define PA_MAXRXHSGEAR 0x1587 #define PA_RXHSUNTERMCAP 0x15A5 #define PA_RXLSTERMCAP 0x15A6 +#define PA_GRANULARITY 0x15AA #define PA_PACPREQTIMEOUT 0x1590 #define PA_PACPREQEOBTIMEOUT 0x1591 #define PA_HIBERN8TIME 0x15A7 @@ -158,6 +159,9 @@ #define VS_DEBUGOMC 0xD09E #define VS_POWERSTATE 0xD083 +#define PA_GRANULARITY_MIN_VAL 1 +#define PA_GRANULARITY_MAX_VAL 6 + /* PHY Adapter Protocol Constants */ #define PA_MAXDATALANES 4 From 7caf489b99a42a9017ef3d733912aea8794677e7 Mon Sep 17 00:00:00 2001 From: "subhashj@codeaurora.org" Date: Wed, 23 Nov 2016 16:32:20 -0800 Subject: [PATCH 222/256] scsi: ufs: issue link starup 2 times if device isn't active If we issue the link startup to the device while its UniPro state is LinkDown (and device state is sleep/power-down) then link startup will not move the device state to Active. Device will only move to active state if the link starup is issued when its UniPro state is LinkUp. So in this case, we would have to issue the link startup 2 times to make sure that device moves to active state. Reviewed-by: Gilad Broner Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 28cbca21c4dd..16c5c50d054d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3185,7 +3185,16 @@ static int ufshcd_link_startup(struct ufs_hba *hba) { int ret; int retries = DME_LINKSTARTUP_RETRIES; + bool link_startup_again = false; + /* + * If UFS device isn't active then we will have to issue link startup + * 2 times to make sure the device state move to active. + */ + if (!ufshcd_is_ufs_dev_active(hba)) + link_startup_again = true; + +link_startup: do { ufshcd_vops_link_startup_notify(hba, PRE_CHANGE); @@ -3211,6 +3220,12 @@ static int ufshcd_link_startup(struct ufs_hba *hba) /* failed to get the link up... retire */ goto out; + if (link_startup_again) { + link_startup_again = false; + retries = DME_LINKSTARTUP_RETRIES; + goto link_startup; + } + if (hba->quirks & UFSHCD_QUIRK_BROKEN_LCC) { ret = ufshcd_disable_device_tx_lcc(hba); if (ret) @@ -6744,10 +6759,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) pm_runtime_get_sync(dev); /* - * The device-initialize-sequence hasn't been invoked yet. - * Set the device to power-off state + * We are assuming that device wasn't put in sleep/power-down + * state exclusively during the boot stage before kernel. + * This assumption helps avoid doing link startup twice during + * ufshcd_probe_hba(). */ - ufshcd_set_ufs_dev_poweroff(hba); + ufshcd_set_ufs_dev_active(hba); async_schedule(ufshcd_async_scan, hba); From fb7b45f0462f144e1924a357995552f24f0c9d0c Mon Sep 17 00:00:00 2001 From: Dolev Raviv Date: Wed, 23 Nov 2016 16:32:32 -0800 Subject: [PATCH 223/256] scsi: ufs: handle errors from PHY_ADAPTER_ERROR register The PHY_ADAPTER_ERROR status register indicates PHY lane errors reported by the M-PHY layer. In some occasions the controller can recover from such errors. When the error is not recoverable, a stuck DB error will occur. Since the stuck DB error is spotted separately, no action other than clearing the register is necessary. Signed-off-by: Dolev Raviv Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 11 +++++++++++ drivers/scsi/ufs/ufshci.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 16c5c50d054d..ec4c99ab6a91 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4215,6 +4215,17 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba) { u32 reg; + /* PHY layer lane error */ + reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER); + /* Ignore LINERESET indication, as this is not an error */ + if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) && + (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)) + /* + * To know whether this error is fatal or not, DB timeout + * must be checked but this error is handled separately. + */ + dev_dbg(hba->dev, "%s: UIC Lane error reported\n", __func__); + /* PA_INIT_ERROR is fatal and needs UIC reset */ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER); if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index bbd8df96d249..5d978867be57 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -168,6 +168,7 @@ enum { /* UECPA - Host UIC Error Code PHY Adapter Layer 38h */ #define UIC_PHY_ADAPTER_LAYER_ERROR UFS_BIT(31) #define UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK 0x1F +#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF /* UECDL - Host UIC Error Code Data Link Layer 3Ch */ #define UIC_DATA_LINK_LAYER_ERROR UFS_BIT(31) From f37e9f8cf8bc681250880f8c1372fb882c9379b8 Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Wed, 23 Nov 2016 16:32:49 -0800 Subject: [PATCH 224/256] scsi: ufs: fix condition in which DME command failure msg is printed out The condition in which error message is printed out was incorrect and resulted error message only if retries exhausted. But retries happens only if DME command is a peer command, and thus DME commands which are not peer commands and fail are not printed out. This change fixes this issue. Signed-off-by: Yaniv Gardi Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ec4c99ab6a91..b82607856607 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2516,10 +2516,10 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret); } while (ret && peer && --retries); - if (!retries) + if (ret) dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x failed %d retries\n", - set, UIC_GET_ATTR_ID(attr_sel), mib_val, - retries); + set, UIC_GET_ATTR_ID(attr_sel), mib_val, + UFS_UIC_COMMAND_RETRIES - retries); return ret; } @@ -2583,9 +2583,10 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, get, UIC_GET_ATTR_ID(attr_sel), ret); } while (ret && peer && --retries); - if (!retries) + if (ret) dev_err(hba->dev, "%s: attr-id 0x%x failed %d retries\n", - get, UIC_GET_ATTR_ID(attr_sel), retries); + get, UIC_GET_ATTR_ID(attr_sel), + UFS_UIC_COMMAND_RETRIES - retries); if (mib_val && !ret) *mib_val = uic_cmd.argument3; From 0b257734344aa89b565bd148ff94f29aa873ffa6 Mon Sep 17 00:00:00 2001 From: "subhashj@codeaurora.org" Date: Wed, 23 Nov 2016 16:33:08 -0800 Subject: [PATCH 225/256] scsi: ufs: optimize system suspend handling Consider following sequence of events: 1. UFS is runtime suspended, link_state = Hibern8, device_state = sleep 2. System goes into system suspend, ufshcd_system_suspend() brings both link and device to active state and then puts the device in Power_Down state and link in OFF state. 3. System resumes at some later point in time, ufshcd_system_resume() doesn't do anything as UFS state is runtime suspended. Note that link is still on OFF state and device is in Power_Down state. 4. Now system again goes into suspend without any UFS accesses before it. ufshcd_system_suspend() again brings both link and device to active state and then puts the device in Power_Down state and link if OFF state. But it's unnecessary to bring the link & device in active state as both link and device are already in desired low power states. This change fixes this issue by adding proper state checks in ufshcd_system_suspend(). Reviewed-by: Gilad Broner Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b82607856607..4b6cc0773681 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6272,16 +6272,13 @@ int ufshcd_system_suspend(struct ufs_hba *hba) if (!hba || !hba->is_powered) return 0; - if (pm_runtime_suspended(hba->dev)) { - if (hba->rpm_lvl == hba->spm_lvl) - /* - * There is possibility that device may still be in - * active state during the runtime suspend. - */ - if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == - hba->curr_dev_pwr_mode) && !hba->auto_bkops_enabled) - goto out; + if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == + hba->curr_dev_pwr_mode) && + (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == + hba->uic_link_state)) + goto out; + if (pm_runtime_suspended(hba->dev)) { /* * UFS device and/or UFS link low power states during runtime * suspend seems to be different than what is expected during From 2349b533167315199b00b15db891ddc45b2c909d Mon Sep 17 00:00:00 2001 From: "subhashj@codeaurora.org" Date: Wed, 23 Nov 2016 16:33:19 -0800 Subject: [PATCH 226/256] scsi: ufs: fix default power mode to FAST/SLOW We would by default like to run in FAST/SLOW mode instead of FASTAUTO/SLOWAUTO mode for performance reasons. This change sets the default speed mode to FAST/SLOW mode. Reviewed-by: Venkat Gopalakrishnan Signed-off-by: Subhash Jadavani Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4b6cc0773681..0c75c75217f8 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2821,8 +2821,8 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) if (hba->max_pwr_info.is_valid) return 0; - pwr_info->pwr_tx = FASTAUTO_MODE; - pwr_info->pwr_rx = FASTAUTO_MODE; + pwr_info->pwr_tx = FAST_MODE; + pwr_info->pwr_rx = FAST_MODE; pwr_info->hs_rate = PA_HS_MODE_B; /* Get the connected lane count */ @@ -2853,7 +2853,7 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) __func__, pwr_info->gear_rx); return -EINVAL; } - pwr_info->pwr_rx = SLOWAUTO_MODE; + pwr_info->pwr_rx = SLOW_MODE; } ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), @@ -2866,7 +2866,7 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) __func__, pwr_info->gear_tx); return -EINVAL; } - pwr_info->pwr_tx = SLOWAUTO_MODE; + pwr_info->pwr_tx = SLOW_MODE; } hba->max_pwr_info.is_valid = true; From 68ab2d76e4be785a7003fdb42b7c4ed8bba56ae2 Mon Sep 17 00:00:00 2001 From: Uma Krishnan Date: Mon, 28 Nov 2016 18:41:06 -0600 Subject: [PATCH 227/256] scsi: cxlflash: Set sg_tablesize to 1 instead of SG_NONE The following Oops is encountered when blk_mq is enabled with the cxlflash driver: [ 2960.817172] Oops: Kernel access of bad area, sig: 11 [#5] [ 2960.817309] NIP __blk_mq_run_hw_queue+0x278/0x4c0 [ 2960.817313] LR __blk_mq_run_hw_queue+0x2bc/0x4c0 [ 2960.817314] Call Trace: [ 2960.817320] __blk_mq_run_hw_queue+0x2bc/0x4c0 (unreliable) [ 2960.817324] blk_mq_run_hw_queue+0xd8/0x100 [ 2960.817329] blk_mq_insert_requests+0x14c/0x1f0 [ 2960.817333] blk_mq_flush_plug_list+0x150/0x190 [ 2960.817338] blk_flush_plug_list+0x11c/0x2b0 [ 2960.817344] blk_finish_plug+0x58/0x80 [ 2960.817348] __do_page_cache_readahead+0x1c0/0x2e0 [ 2960.817352] force_page_cache_readahead+0x68/0xd0 [ 2960.817356] generic_file_read_iter+0x43c/0x6a0 [ 2960.817359] blkdev_read_iter+0x68/0xa0 [ 2960.817361] __vfs_read+0x11c/0x180 [ 2960.817364] vfs_read+0xa4/0x1c0 [ 2960.817366] SyS_read+0x6c/0x110 [ 2960.817369] system_call+0x38/0xb4 The SCSI blk_mq stack assumes that sg_tablesize is always a non-zero value with scsi_mq_setup_tags() allocating tags using sg_tablesize. The cxlflash driver currently uses SG_NONE (0) for the sg_tablesize as the devices it supports are not capable of scatter gather. This mismatch of values results in the Oops above. To resolve this issue, sg_tablesize for cxlflash can simply be set to 1, a value which satisfies the constraints in cxlflash and the lack of support of SG_NONE in SCSI blk_mq. Signed-off-by: Uma Krishnan Acked-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index b301655f91cd..600486066a9f 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -2377,7 +2377,7 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = CXLFLASH_MAX_CMDS_PER_LUN, .can_queue = CXLFLASH_MAX_CMDS, .this_id = -1, - .sg_tablesize = SG_NONE, /* No scatter gather support */ + .sg_tablesize = 1, /* No scatter gather support */ .max_sectors = CXLFLASH_MAX_SECTORS, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = cxlflash_host_attrs, From 8a2605430a64bdf0361af5a18043717a2c59972f Mon Sep 17 00:00:00 2001 From: Uma Krishnan Date: Mon, 28 Nov 2016 18:41:19 -0600 Subject: [PATCH 228/256] scsi: cxlflash: Fix crash in cxlflash_restore_luntable() During test, the following crash was observed: [34538.981505] Faulting instruction address: 0xd000000007c9c870 cpu 0x9: Vector: 300 (Data Access) at [c0000007f1e8f590] pc: d000000007c9c870: cxlflash_restore_luntable+0x70/0x1d0 [cxlflash] lr: d000000007c9c84c: cxlflash_restore_luntable+0x4c/0x1d0 [cxlflash] sp: c0000007f1e8f810 msr: 9000000100009033 dar: c00000171d637438 dsisr: 40000000 current = 0xc0000007f1e43f90 paca = 0xc000000007b25100 softe: 0 irq_happened: 0x01 pid = 493, comm = eehd enter ? for help [c0000007f1e8f8a0] d000000007c940b0 init_afu+0xd60/0x1200 [cxlflash] [c0000007f1e8f9a0] d000000007c945a8 cxlflash_pci_slot_reset+0x58/0xe0 [cxlflash] [c0000007f1e8fa20] d00000000715f790 cxl_pci_slot_reset+0x230/0x340 [cxl] [c0000007f1e8fae0] c000000000040dd4 eeh_report_reset+0x144/0x180 [c0000007f1e8fb20] c00000000003f708 eeh_pe_dev_traverse+0x98/0x170 [c0000007f1e8fbb0] c000000000041618 eeh_handle_normal_event+0x328/0x410 [c0000007f1e8fc30] c000000000041db8 eeh_handle_event+0x178/0x330 [c0000007f1e8fce0] c000000000042118 eeh_event_handler+0x1a8/0x1b0 [c0000007f1e8fd80] c00000000011420c kthread+0xec/0x100 [c0000007f1e8fe30] c00000000000a47c ret_from_kernel_thread+0x5c/0xe0 When superpipe mode is disabled for a LUN, the references for the local lun are deleted but the LUN is still identified as being present in the LUN table. This mismatched state can result in the above crash when the LUN table is restored during an error recovery operation. To fix this issue, the local LUN information structure is updated to reflect the LUN is no longer in the LUN table once all references to the LUN are gone. Signed-off-by: Uma Krishnan Acked-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/lunmgt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/cxlflash/lunmgt.c b/drivers/scsi/cxlflash/lunmgt.c index a0923cade6f3..6c318db90c85 100644 --- a/drivers/scsi/cxlflash/lunmgt.c +++ b/drivers/scsi/cxlflash/lunmgt.c @@ -254,8 +254,14 @@ int cxlflash_manage_lun(struct scsi_device *sdev, if (lli->parent->mode != MODE_NONE) rc = -EBUSY; else { + /* + * Clean up local LUN for this port and reset table + * tracking when no more references exist. + */ sdev->hostdata = NULL; lli->port_sel &= ~CHAN2PORT(chan); + if (lli->port_sel == 0U) + lli->in_table = false; } } From 3d2f617d448f5e1d15d2844b803c13763ed51f1f Mon Sep 17 00:00:00 2001 From: Uma Krishnan Date: Mon, 28 Nov 2016 18:41:36 -0600 Subject: [PATCH 229/256] scsi: cxlflash: Improve context_reset() logic Currently, the context reset routine waits for command room to be available before sending the reset request. Per review of the SISLite specification and clarifications from the CXL Flash AFU designers, this wait is unnecessary. The reset request can be sent anytime regardless of command room, so long as only a single reset request is active at any one point in time. This commit simplifies the reset routine by removing the wait for command room. Additionally it adds a debug trace to help pinpoint hardware errors when a context reset does not complete. Signed-off-by: Uma Krishnan Acked-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 600486066a9f..6d33d8c3a9fc 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -263,8 +263,9 @@ static void context_reset(struct afu_cmd *cmd) { int nretry = 0; u64 rrin = 0x1; - u64 room = 0; struct afu *afu = cmd->parent; + struct cxlflash_cfg *cfg = afu->parent; + struct device *dev = &cfg->dev->dev; ulong lock_flags; pr_debug("%s: cmd=%p\n", __func__, cmd); @@ -280,23 +281,6 @@ static void context_reset(struct afu_cmd *cmd) cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT); spin_unlock_irqrestore(&cmd->slock, lock_flags); - /* - * We really want to send this reset at all costs, so spread - * out wait time on successive retries for available room. - */ - do { - room = readq_be(&afu->host_map->cmd_room); - atomic64_set(&afu->room, room); - if (room) - goto write_rrin; - udelay(1 << nretry); - } while (nretry++ < MC_ROOM_RETRY_CNT); - - pr_err("%s: no cmd_room to send reset\n", __func__); - return; - -write_rrin: - nretry = 0; writeq_be(rrin, &afu->host_map->ioarrin); do { rrin = readq_be(&afu->host_map->ioarrin); @@ -305,6 +289,9 @@ write_rrin: /* Double delay each time */ udelay(1 << nretry); } while (nretry++ < MC_ROOM_RETRY_CNT); + + dev_dbg(dev, "%s: returning rrin=0x%016llX nretry=%d\n", + __func__, rrin, nretry); } /** From 11f7b1844ac01d0298aad6a0ec2591bef4a1c3a2 Mon Sep 17 00:00:00 2001 From: Uma Krishnan Date: Mon, 28 Nov 2016 18:41:45 -0600 Subject: [PATCH 230/256] scsi: cxlflash: Avoid command room violation During test, a command room violation interrupt is occasionally seen for the master context when the CXL flash devices are stressed. After studying the code, there could be gaps in the way command room value is being cached in cxlflash. When the cached command room is zero the thread attempting to send becomes burdened with updating the cached value with the actual value from the AFU. Today, this is handled with an atomic set operation of the raw value read. Following the atomic update, the thread proceeds to send. This behavior is incorrect on two counts: - The update fails to take into account the current thread and its consumption of one of the hardware commands. - The update does not take into account other threads also atomically updating. Per design, a worker thread updates the cached value when a send thread times out. By not protecting the update with a lock, the cached value can be incorrectly clobbered. To correct these issues, the update of the cached command room has been simplified and also protected using a spin lock which is held until the MMIO is complete. This ensures the command room is properly consumed by the same thread. Update of cached value also takes into account the current thread consuming a hardware command. Signed-off-by: Uma Krishnan Acked-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 4 +-- drivers/scsi/cxlflash/main.c | 66 ++++++++++------------------------ 2 files changed, 20 insertions(+), 50 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 6e6815545a71..ef2943d0f75c 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -173,8 +173,8 @@ struct afu { u64 *hrrq_end; u64 *hrrq_curr; bool toggle; - bool read_room; - atomic64_t room; + s64 room; + spinlock_t rrin_slock; /* Lock to rrin queuing and cmd_room updates */ u64 hb; u32 cmd_couts; /* Number of command checkouts */ u32 internal_lun; /* User-desired LUN mode for this AFU */ diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 6d33d8c3a9fc..1292a74ee5d1 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -306,59 +306,34 @@ static int send_cmd(struct afu *afu, struct afu_cmd *cmd) { struct cxlflash_cfg *cfg = afu->parent; struct device *dev = &cfg->dev->dev; - int nretry = 0; int rc = 0; - u64 room; - long newval; + s64 room; + ulong lock_flags; /* - * This routine is used by critical users such an AFU sync and to - * send a task management function (TMF). Thus we want to retry a - * bit before returning an error. To avoid the performance penalty - * of MMIO, we spread the update of 'room' over multiple commands. + * To avoid the performance penalty of MMIO, spread the update of + * 'room' over multiple commands. */ -retry: - newval = atomic64_dec_if_positive(&afu->room); - if (!newval) { - do { - room = readq_be(&afu->host_map->cmd_room); - atomic64_set(&afu->room, room); - if (room) - goto write_ioarrin; - udelay(1 << nretry); - } while (nretry++ < MC_ROOM_RETRY_CNT); - - dev_err(dev, "%s: no cmd_room to send 0x%X\n", - __func__, cmd->rcb.cdb[0]); - - goto no_room; - } else if (unlikely(newval < 0)) { - /* This should be rare. i.e. Only if two threads race and - * decrement before the MMIO read is done. In this case - * just benefit from the other thread having updated - * afu->room. - */ - if (nretry++ < MC_ROOM_RETRY_CNT) { - udelay(1 << nretry); - goto retry; + spin_lock_irqsave(&afu->rrin_slock, lock_flags); + if (--afu->room < 0) { + room = readq_be(&afu->host_map->cmd_room); + if (room <= 0) { + dev_dbg_ratelimited(dev, "%s: no cmd_room to send " + "0x%02X, room=0x%016llX\n", + __func__, cmd->rcb.cdb[0], room); + afu->room = 0; + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; } - - goto no_room; + afu->room = room - 1; } -write_ioarrin: writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin); out: + spin_unlock_irqrestore(&afu->rrin_slock, lock_flags); pr_devel("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd, cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc); return rc; - -no_room: - afu->read_room = true; - kref_get(&cfg->afu->mapcount); - schedule_work(&cfg->work_q); - rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; } /** @@ -1827,7 +1802,8 @@ static int init_afu(struct cxlflash_cfg *cfg) } afu_err_intr_init(cfg->afu); - atomic64_set(&afu->room, readq_be(&afu->host_map->cmd_room)); + spin_lock_init(&afu->rrin_slock); + afu->room = readq_be(&afu->host_map->cmd_room); /* Restore the LUN mappings */ cxlflash_restore_luntable(cfg); @@ -2399,7 +2375,6 @@ MODULE_DEVICE_TABLE(pci, cxlflash_pci_table); * Handles the following events: * - Link reset which cannot be performed on interrupt context due to * blocking up to a few seconds - * - Read AFU command room * - Rescan the host */ static void cxlflash_worker_thread(struct work_struct *work) @@ -2436,11 +2411,6 @@ static void cxlflash_worker_thread(struct work_struct *work) cfg->lr_state = LINK_RESET_COMPLETE; } - if (afu->read_room) { - atomic64_set(&afu->room, readq_be(&afu->host_map->cmd_room)); - afu->read_room = false; - } - spin_unlock_irqrestore(cfg->host->host_lock, lock_flags); if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0) From 338be07233813d5be8f44d393d6c16f631c3254d Mon Sep 17 00:00:00 2001 From: Quentin Lambert Date: Sat, 19 Nov 2016 18:42:14 +0100 Subject: [PATCH 231/256] scsi: cxgb4i: Add a missing call to neigh_release Most error branches following the call to dst_neigh_lookup contain a call to neigh_release. This patch add these calls where they are missing. This issue was found with Hector. Signed-off-by: Quentin Lambert Acked-by: Varun Prakash Signed-off-by: Martin K. Petersen --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 0039bebaa9e2..688fde61d12a 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -1410,7 +1410,7 @@ static int init_act_open(struct cxgbi_sock *csk) csk->atid = cxgb4_alloc_atid(lldi->tids, csk); if (csk->atid < 0) { pr_err("%s, NO atid available.\n", ndev->name); - return -EINVAL; + goto rel_resource_without_clip; } cxgbi_sock_set_flag(csk, CTPF_HAS_ATID); cxgbi_sock_get(csk); From b0120d9906253570f593daf82016a5331bbee2b8 Mon Sep 17 00:00:00 2001 From: Cathy Avery Date: Wed, 23 Nov 2016 08:46:33 -0500 Subject: [PATCH 232/256] scsi: storvsc: Payload buffer incorrectly sized for 32 bit kernels. On a 32 bit kernel sizeof(void *) is not 64 bits as hv_mpb_array requires. Also the buffer needs to be cleared or the upper bytes will contain junk. Suggested-by: Vitaly Kuznetsov Signed-off-by: Cathy Avery Reviewed-by: K. Y. Srinivasan Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 8ccfc9ea874b..05526b71541b 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1495,9 +1495,9 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) if (sg_count) { if (sg_count > MAX_PAGE_BUFFER_COUNT) { - payload_sz = (sg_count * sizeof(void *) + + payload_sz = (sg_count * sizeof(u64) + sizeof(struct vmbus_packet_mpb_array)); - payload = kmalloc(payload_sz, GFP_ATOMIC); + payload = kzalloc(payload_sz, GFP_ATOMIC); if (!payload) return SCSI_MLQUEUE_DEVICE_BUSY; } From b4b22a012ef96dac5244e9003b99924d94f899d3 Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Mon, 28 Nov 2016 15:22:37 +0530 Subject: [PATCH 233/256] scsi: lpfc: Replace pci_pool_alloc by pci_pool_zalloc In lpfc_new_scsi_buf_s3() and lpfc_new_scsi_buf_s4() pci_pool_alloc followed by memset will be replaced by pci_pool_zalloc() Signed-off-by: Souptick joarder Reviewed-by: Johannes Thumshirn Acked-by: Dick Kennedy Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 1b0ef79d0821..ad350d969bdc 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -413,15 +413,13 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) * struct fcp_cmnd, struct fcp_rsp and the number of bde's * necessary to support the sg_tablesize. */ - psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool, + psb->data = pci_pool_zalloc(phba->lpfc_scsi_dma_buf_pool, GFP_KERNEL, &psb->dma_handle); if (!psb->data) { kfree(psb); break; } - /* Initialize virtual ptrs to dma_buf region. */ - memset(psb->data, 0, phba->cfg_sg_dma_buf_size); /* Allocate iotag for psb->cur_iocbq. */ iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); @@ -821,13 +819,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) * for the struct fcp_cmnd, struct fcp_rsp and the number * of bde's necessary to support the sg_tablesize. */ - psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool, + psb->data = pci_pool_zalloc(phba->lpfc_scsi_dma_buf_pool, GFP_KERNEL, &psb->dma_handle); if (!psb->data) { kfree(psb); break; } - memset(psb->data, 0, phba->cfg_sg_dma_buf_size); /* * 4K Page alignment is CRITICAL to BlockGuard, double check From e7ab2d401dbf633eaafe5bd1f39e84492848668f Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:01 -0600 Subject: [PATCH 234/256] scsi: cxlflash: Remove unused buffer from AFU command The cxlflash driver originally required a per-command 4K buffer that hosted data passed to the AFU. When the routines that initiate AFU and internal SCSI commands were refactored to use scsi_execute(), the need for this buffer became obsolete. As it is no longer necessary, the buffer is removed. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 1 - drivers/scsi/cxlflash/main.c | 28 ++-------------------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index ef2943d0f75c..45255145ecd9 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -134,7 +134,6 @@ struct afu_cmd { struct sisl_ioasa sa; /* IOASA must follow IOARCB */ spinlock_t slock; struct completion cevent; - char *buf; /* per command buffer */ struct afu *parent; int slot; atomic_t free; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 1292a74ee5d1..9f2821d69e38 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -41,8 +41,7 @@ MODULE_LICENSE("GPL"); * Commands are checked out in a round-robin fashion. Note that since * the command pool is larger than the hardware queue, the majority of * times we will only loop once or twice before getting a command. The - * buffer and CDB within the command are initialized (zeroed) prior to - * returning. + * CDB within the command is initialized (zeroed) prior to returning. * * Return: The checked out command or NULL when command pool is empty. */ @@ -59,7 +58,6 @@ static struct afu_cmd *cmd_checkout(struct afu *afu) if (!atomic_dec_if_positive(&cmd->free)) { pr_devel("%s: returning found index=%d cmd=%p\n", __func__, cmd->slot, cmd); - memset(cmd->buf, 0, CMD_BUFSIZE); memset(cmd->rcb.cdb, 0, sizeof(cmd->rcb.cdb)); return cmd; } @@ -590,17 +588,9 @@ static void cxlflash_wait_for_pci_err_recovery(struct cxlflash_cfg *cfg) */ static void free_mem(struct cxlflash_cfg *cfg) { - int i; - char *buf = NULL; struct afu *afu = cfg->afu; if (cfg->afu) { - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { - buf = afu->cmd[i].buf; - if (!((u64)buf & (PAGE_SIZE - 1))) - free_page((ulong)buf); - } - free_pages((ulong)afu, get_order(sizeof(struct afu))); cfg->afu = NULL; } @@ -849,7 +839,6 @@ static int alloc_mem(struct cxlflash_cfg *cfg) { int rc = 0; int i; - char *buf = NULL; struct device *dev = &cfg->dev->dev; /* AFU is ~12k, i.e. only one 64k page or up to four 4k pages */ @@ -864,20 +853,7 @@ static int alloc_mem(struct cxlflash_cfg *cfg) cfg->afu->parent = cfg; cfg->afu->afu_map = NULL; - for (i = 0; i < CXLFLASH_NUM_CMDS; buf += CMD_BUFSIZE, i++) { - if (!((u64)buf & (PAGE_SIZE - 1))) { - buf = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); - if (unlikely(!buf)) { - dev_err(dev, - "%s: Allocate command buffers fail!\n", - __func__); - rc = -ENOMEM; - free_mem(cfg); - goto out; - } - } - - cfg->afu->cmd[i].buf = buf; + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { atomic_set(&cfg->afu->cmd[i].free, 1); cfg->afu->cmd[i].slot = i; } From 350bb478f57387df1e0b830fc64be2d1c3d55b6b Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:11 -0600 Subject: [PATCH 235/256] scsi: cxlflash: Allocate memory instead of using command pool for AFU sync As staging for the removal of the AFU command pool, remove the reliance upon the pool for the internal AFU sync command. Instead of obtaining an AFU command from the pool, dynamically allocate memory with the appropriate alignment requirements. Since the AFU sync service is only executed from the process environment, blocking is acceptable. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 9f2821d69e38..0f13b4de448a 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -1823,8 +1823,8 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, struct cxlflash_cfg *cfg = afu->parent; struct device *dev = &cfg->dev->dev; struct afu_cmd *cmd = NULL; + char *buf = NULL; int rc = 0; - int retry_cnt = 0; static DEFINE_MUTEX(sync_active); if (cfg->state != STATE_NORMAL) { @@ -1833,23 +1833,23 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, } mutex_lock(&sync_active); -retry: - cmd = cmd_checkout(afu); - if (unlikely(!cmd)) { - retry_cnt++; - udelay(1000 * retry_cnt); - if (retry_cnt < MC_RETRY_CNT) - goto retry; - dev_err(dev, "%s: could not get a free command\n", __func__); + buf = kzalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL); + if (unlikely(!buf)) { + dev_err(dev, "%s: no memory for command\n", __func__); rc = -1; goto out; } + cmd = (struct afu_cmd *)PTR_ALIGN(buf, __alignof__(*cmd)); + init_completion(&cmd->cevent); + spin_lock_init(&cmd->slock); + cmd->parent = afu; + pr_debug("%s: afu=%p cmd=%p %d\n", __func__, afu, cmd, ctx_hndl_u); - memset(cmd->rcb.cdb, 0, sizeof(cmd->rcb.cdb)); - cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD; + cmd->rcb.ctx_id = afu->ctx_hndl; + cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; cmd->rcb.port_sel = 0x0; /* NA */ cmd->rcb.lun_id = 0x0; /* NA */ cmd->rcb.data_len = 0x0; @@ -1875,8 +1875,7 @@ retry: rc = -1; out: mutex_unlock(&sync_active); - if (cmd) - cmd_checkin(cmd); + kfree(buf); pr_debug("%s: returning rc=%d\n", __func__, rc); return rc; } From 5fbb96c8f1ba89fb220efb7e4eeed7cb5112becd Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:19 -0600 Subject: [PATCH 236/256] scsi: cxlflash: Use cmd_size for private commands Instead of using a private pool of AFU commands, use cmd_size to prime the private pool of SCSI commands such that they are allocated with a size large enough to contain an aligned AFU command. Use scsi_cmd_priv() to derive the aligned/zeroed private command on queuecommand and TMF paths. Remove cmd_checkout() as it is no longer required. The remaining AFU private command infrastructure will be removed in a cleanup commit. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 14 ++++++++ drivers/scsi/cxlflash/main.c | 65 ++++++---------------------------- 2 files changed, 25 insertions(+), 54 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 45255145ecd9..539908f65cc4 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -19,6 +19,7 @@ #include #include #include +#include #include extern const struct file_operations cxlflash_cxl_fops; @@ -146,6 +147,19 @@ struct afu_cmd { */ } __aligned(cache_line_size()); +static inline struct afu_cmd *sc_to_afuc(struct scsi_cmnd *sc) +{ + return PTR_ALIGN(scsi_cmd_priv(sc), __alignof__(struct afu_cmd)); +} + +static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc) +{ + struct afu_cmd *afuc = sc_to_afuc(sc); + + memset(afuc, 0, sizeof(*afuc)); + return afuc; +} + struct afu { /* Stuff requiring alignment go first. */ diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 0f13b4de448a..43140ce3163d 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -34,38 +34,6 @@ MODULE_AUTHOR("Manoj N. Kumar "); MODULE_AUTHOR("Matthew R. Ochs "); MODULE_LICENSE("GPL"); -/** - * cmd_checkout() - checks out an AFU command - * @afu: AFU to checkout from. - * - * Commands are checked out in a round-robin fashion. Note that since - * the command pool is larger than the hardware queue, the majority of - * times we will only loop once or twice before getting a command. The - * CDB within the command is initialized (zeroed) prior to returning. - * - * Return: The checked out command or NULL when command pool is empty. - */ -static struct afu_cmd *cmd_checkout(struct afu *afu) -{ - int k, dec = CXLFLASH_NUM_CMDS; - struct afu_cmd *cmd; - - while (dec--) { - k = (afu->cmd_couts++ & (CXLFLASH_NUM_CMDS - 1)); - - cmd = &afu->cmd[k]; - - if (!atomic_dec_if_positive(&cmd->free)) { - pr_devel("%s: returning found index=%d cmd=%p\n", - __func__, cmd->slot, cmd); - memset(cmd->rcb.cdb, 0, sizeof(cmd->rcb.cdb)); - return cmd; - } - } - - return NULL; -} - /** * cmd_checkin() - checks in an AFU command * @cmd: AFU command to checkin. @@ -232,7 +200,6 @@ static void cmd_complete(struct afu_cmd *cmd) scp->result = (DID_OK << 16); cmd_is_tmf = cmd->cmd_tmf; - cmd_checkin(cmd); /* Don't use cmd after here */ pr_debug_ratelimited("%s: calling scsi_done scp=%p result=%X " "ioasc=%d\n", __func__, scp, scp->result, @@ -365,7 +332,7 @@ static void wait_resp(struct afu *afu, struct afu_cmd *cmd) */ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) { - struct afu_cmd *cmd; + struct afu_cmd *cmd = sc_to_afucz(scp); u32 port_sel = scp->device->channel + 1; short lflag = 0; @@ -376,13 +343,6 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) int rc = 0; ulong to; - cmd = cmd_checkout(afu); - if (unlikely(!cmd)) { - dev_err(dev, "%s: could not get a free command\n", __func__); - rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } - /* When Task Management Function is active do not send another */ spin_lock_irqsave(&cfg->tmf_slock, lock_flags); if (cfg->tmf_active) @@ -394,6 +354,7 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags); cmd->rcb.ctx_id = afu->ctx_hndl; + cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; cmd->rcb.port_sel = port_sel; cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); @@ -402,8 +363,10 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) cmd->rcb.req_flags = (SISL_REQ_FLAGS_PORT_LUN_ID | SISL_REQ_FLAGS_SUP_UNDERRUN | lflag); - /* Stash the scp in the reserved field, for reuse during interrupt */ + /* Stash the scp in the command, for reuse during interrupt */ cmd->rcb.scp = scp; + cmd->parent = afu; + spin_lock_init(&cmd->slock); /* Copy the CDB from the cmd passed in */ memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd)); @@ -411,7 +374,6 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) /* Send the command */ rc = send_cmd(afu, cmd); if (unlikely(rc)) { - cmd_checkin(cmd); spin_lock_irqsave(&cfg->tmf_slock, lock_flags); cfg->tmf_active = false; spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags); @@ -467,7 +429,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; struct afu *afu = cfg->afu; struct device *dev = &cfg->dev->dev; - struct afu_cmd *cmd; + struct afu_cmd *cmd = sc_to_afucz(scp); u32 port_sel = scp->device->channel + 1; int nseg, i, ncount; struct scatterlist *sg; @@ -512,17 +474,11 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) break; } - cmd = cmd_checkout(afu); - if (unlikely(!cmd)) { - dev_err(dev, "%s: could not get a free command\n", __func__); - rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } - kref_get(&cfg->afu->mapcount); kref_got = 1; cmd->rcb.ctx_id = afu->ctx_hndl; + cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; cmd->rcb.port_sel = port_sel; cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); @@ -536,6 +492,8 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) /* Stash the scp in the reserved field, for reuse during interrupt */ cmd->rcb.scp = scp; + cmd->parent = afu; + spin_lock_init(&cmd->slock); nseg = scsi_dma_map(scp); if (unlikely(nseg < 0)) { @@ -556,10 +514,8 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) /* Send the command */ rc = send_cmd(afu, cmd); - if (unlikely(rc)) { - cmd_checkin(cmd); + if (unlikely(rc)) scsi_dma_unmap(scp); - } out: if (kref_got) @@ -2314,6 +2270,7 @@ static struct scsi_host_template driver_template = { .change_queue_depth = cxlflash_change_queue_depth, .cmd_per_lun = CXLFLASH_MAX_CMDS_PER_LUN, .can_queue = CXLFLASH_MAX_CMDS, + .cmd_size = sizeof(struct afu_cmd) + __alignof__(struct afu_cmd) - 1, .this_id = -1, .sg_tablesize = 1, /* No scatter gather support */ .max_sectors = CXLFLASH_MAX_SECTORS, From 25bced2b61b43b6372a73008dafa2183c5d53c39 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:27 -0600 Subject: [PATCH 237/256] scsi: cxlflash: Remove private command pool Clean up and remove the remaining private command pool infrastructure that is no longer required. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 7 ---- drivers/scsi/cxlflash/main.c | 68 ---------------------------------- 2 files changed, 75 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 539908f65cc4..7e4ba31935b5 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -136,8 +136,6 @@ struct afu_cmd { spinlock_t slock; struct completion cevent; struct afu *parent; - int slot; - atomic_t free; u8 cmd_tmf:1; @@ -164,10 +162,6 @@ struct afu { /* Stuff requiring alignment go first. */ u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */ - /* - * Command & data for AFU commands. - */ - struct afu_cmd cmd[CXLFLASH_NUM_CMDS]; /* Beware of alignment till here. Preferably introduce new * fields after this point @@ -189,7 +183,6 @@ struct afu { s64 room; spinlock_t rrin_slock; /* Lock to rrin queuing and cmd_room updates */ u64 hb; - u32 cmd_couts; /* Number of command checkouts */ u32 internal_lun; /* User-desired LUN mode for this AFU */ char version[16]; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 43140ce3163d..19156adb0b69 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -34,33 +34,6 @@ MODULE_AUTHOR("Manoj N. Kumar "); MODULE_AUTHOR("Matthew R. Ochs "); MODULE_LICENSE("GPL"); -/** - * cmd_checkin() - checks in an AFU command - * @cmd: AFU command to checkin. - * - * Safe to pass commands that have already been checked in. Several - * internal tracking fields are reset as part of the checkin. Note - * that these are intentionally reset prior to toggling the free bit - * to avoid clobbering values in the event that the command is checked - * out right away. - */ -static void cmd_checkin(struct afu_cmd *cmd) -{ - cmd->rcb.scp = NULL; - cmd->rcb.timeout = 0; - cmd->sa.ioasc = 0; - cmd->cmd_tmf = false; - cmd->sa.host_use[0] = 0; /* clears both completion and retry bytes */ - - if (unlikely(atomic_inc_return(&cmd->free) != 1)) { - pr_err("%s: Freeing cmd (%d) that is not in use!\n", - __func__, cmd->slot); - return; - } - - pr_devel("%s: released cmd %p index=%d\n", __func__, cmd, cmd->slot); -} - /** * process_cmd_err() - command error handler * @cmd: AFU command that experienced the error. @@ -560,28 +533,12 @@ static void free_mem(struct cxlflash_cfg *cfg) * * Cleans up all state associated with the command queue, and unmaps * the MMIO space. - * - * - complete() will take care of commands we initiated (they'll be checked - * in as part of the cleanup that occurs after the completion) - * - * - cmd_checkin() will take care of entries that we did not initiate and that - * have not (and will not) complete because they are sitting on a [now stale] - * hardware queue */ static void stop_afu(struct cxlflash_cfg *cfg) { - int i; struct afu *afu = cfg->afu; - struct afu_cmd *cmd; if (likely(afu)) { - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { - cmd = &afu->cmd[i]; - complete(&cmd->cevent); - if (!atomic_read(&cmd->free)) - cmd_checkin(cmd); - } - if (likely(afu->afu_map)) { cxl_psa_unmap((void __iomem *)afu->afu_map); afu->afu_map = NULL; @@ -794,7 +751,6 @@ static void cxlflash_remove(struct pci_dev *pdev) static int alloc_mem(struct cxlflash_cfg *cfg) { int rc = 0; - int i; struct device *dev = &cfg->dev->dev; /* AFU is ~12k, i.e. only one 64k page or up to four 4k pages */ @@ -808,12 +764,6 @@ static int alloc_mem(struct cxlflash_cfg *cfg) } cfg->afu->parent = cfg; cfg->afu->afu_map = NULL; - - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { - atomic_set(&cfg->afu->cmd[i].free, 1); - cfg->afu->cmd[i].slot = i; - } - out: return rc; } @@ -1443,13 +1393,6 @@ static void init_pcr(struct cxlflash_cfg *cfg) /* Program the Endian Control for the master context */ writeq_be(SISL_ENDIAN_CTRL, &afu->host_map->endian_ctrl); - - /* Initialize cmd fields that never change */ - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { - afu->cmd[i].rcb.ctx_id = afu->ctx_hndl; - afu->cmd[i].rcb.msi = SISL_MSI_RRQ_UPDATED; - afu->cmd[i].rcb.rrq = 0x0; - } } /** @@ -1538,19 +1481,8 @@ out: static int start_afu(struct cxlflash_cfg *cfg) { struct afu *afu = cfg->afu; - struct afu_cmd *cmd; - - int i = 0; int rc = 0; - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { - cmd = &afu->cmd[i]; - - init_completion(&cmd->cevent); - spin_lock_init(&cmd->slock); - cmd->parent = afu; - } - init_pcr(cfg); /* After an AFU reset, RRQ entries are stale, clear them */ From de01283baa334b1d938cfd9121198c517ad6dc89 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:33 -0600 Subject: [PATCH 238/256] scsi: cxlflash: Wait for active AFU commands to timeout upon tear down With the removal of the static private command pool, the ability to 'complete' outstanding commands was lost. While not an issue for the commands originating outside the driver, internal AFU commands are synchronous and therefore have a timeout associated with them. To avoid a stale memory access, the tear down sequence needs to ensure that there are not any active commands before proceeding. As these internal AFU commands are rare events, the simplest way to accomplish this is detecting the activity and waiting for it to timeout. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 1 + drivers/scsi/cxlflash/main.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 7e4ba31935b5..621167794026 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -180,6 +180,7 @@ struct afu { u64 *hrrq_end; u64 *hrrq_curr; bool toggle; + atomic_t cmds_active; /* Number of currently active AFU commands */ s64 room; spinlock_t rrin_slock; /* Lock to rrin queuing and cmd_room updates */ u64 hb; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 19156adb0b69..839eca4c4e02 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -531,7 +531,7 @@ static void free_mem(struct cxlflash_cfg *cfg) * * Safe to call with AFU in a partially allocated/initialized state. * - * Cleans up all state associated with the command queue, and unmaps + * Waits for any active internal AFU commands to timeout and then unmaps * the MMIO space. */ static void stop_afu(struct cxlflash_cfg *cfg) @@ -539,6 +539,8 @@ static void stop_afu(struct cxlflash_cfg *cfg) struct afu *afu = cfg->afu; if (likely(afu)) { + while (atomic_read(&afu->cmds_active)) + ssleep(1); if (likely(afu->afu_map)) { cxl_psa_unmap((void __iomem *)afu->afu_map); afu->afu_map = NULL; @@ -1721,6 +1723,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, } mutex_lock(&sync_active); + atomic_inc(&afu->cmds_active); buf = kzalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL); if (unlikely(!buf)) { dev_err(dev, "%s: no memory for command\n", __func__); @@ -1762,6 +1765,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, (cmd->sa.host_use_b[0] & B_ERROR))) rc = -1; out: + atomic_dec(&afu->cmds_active); mutex_unlock(&sync_active); kfree(buf); pr_debug("%s: returning rc=%d\n", __func__, rc); From 9ba848acbf4fbc6d99a0992df9ef5eb1b4842ba9 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:42 -0600 Subject: [PATCH 239/256] scsi: cxlflash: Remove AFU command lock The original design of the cxlflash driver required AFU commands to convey state information across multiple threads. The IOASA "host use" byte was used to track if a command was done, errored, or timed out. A per-command spin lock was used to serialize access to this byte. As this is no longer required with the introduction of completions and various refactoring over time, the spin lock, state tracking, and associated code can be removed. To support the simplification, the wait_resp() routine is refactored to return a success or failure. Additionally, as the simplification to the AFU internal command routine, explicit assignments of AFU command fields to zero are removed as the memory is zeroed upon allocation. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 8 +----- drivers/scsi/cxlflash/main.c | 46 +++++++++++----------------------- 2 files changed, 16 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 621167794026..bed8e60f312e 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -63,11 +63,6 @@ static inline void check_sizes(void) /* AFU defines a fixed size of 4K for command buffers (borrow 4K page define) */ #define CMD_BUFSIZE SIZE_4K -/* flags in IOA status area for host use */ -#define B_DONE 0x01 -#define B_ERROR 0x02 /* set with B_DONE */ -#define B_TIMEOUT 0x04 /* set with B_DONE & B_ERROR */ - enum cxlflash_lr_state { LINK_RESET_INVALID, LINK_RESET_REQUIRED, @@ -133,9 +128,8 @@ struct cxlflash_cfg { struct afu_cmd { struct sisl_ioarcb rcb; /* IOARCB (cache line aligned) */ struct sisl_ioasa sa; /* IOASA must follow IOARCB */ - spinlock_t slock; - struct completion cevent; struct afu *parent; + struct completion cevent; u8 cmd_tmf:1; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 839eca4c4e02..db770301c30a 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -161,10 +161,6 @@ static void cmd_complete(struct afu_cmd *cmd) struct cxlflash_cfg *cfg = afu->parent; bool cmd_is_tmf; - spin_lock_irqsave(&cmd->slock, lock_flags); - cmd->sa.host_use_b[0] |= B_DONE; - spin_unlock_irqrestore(&cmd->slock, lock_flags); - if (cmd->rcb.scp) { scp = cmd->rcb.scp; if (unlikely(cmd->sa.ioasc)) @@ -204,21 +200,9 @@ static void context_reset(struct afu_cmd *cmd) struct afu *afu = cmd->parent; struct cxlflash_cfg *cfg = afu->parent; struct device *dev = &cfg->dev->dev; - ulong lock_flags; pr_debug("%s: cmd=%p\n", __func__, cmd); - spin_lock_irqsave(&cmd->slock, lock_flags); - - /* Already completed? */ - if (cmd->sa.host_use_b[0] & B_DONE) { - spin_unlock_irqrestore(&cmd->slock, lock_flags); - return; - } - - cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT); - spin_unlock_irqrestore(&cmd->slock, lock_flags); - writeq_be(rrin, &afu->host_map->ioarrin); do { rrin = readq_be(&afu->host_map->ioarrin); @@ -278,20 +262,30 @@ out: * wait_resp() - polls for a response or timeout to a sent AFU command * @afu: AFU associated with the host. * @cmd: AFU command that was sent. + * + * Return: + * 0 on success, -1 on timeout/error */ -static void wait_resp(struct afu *afu, struct afu_cmd *cmd) +static int wait_resp(struct afu *afu, struct afu_cmd *cmd) { + int rc = 0; ulong timeout = msecs_to_jiffies(cmd->rcb.timeout * 2 * 1000); timeout = wait_for_completion_timeout(&cmd->cevent, timeout); - if (!timeout) + if (!timeout) { context_reset(cmd); + rc = -1; + } - if (unlikely(cmd->sa.ioasc != 0)) + if (unlikely(cmd->sa.ioasc != 0)) { pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, " "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0], cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc, cmd->sa.rc.fc_rc); + rc = -1; + } + + return rc; } /** @@ -339,7 +333,6 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) /* Stash the scp in the command, for reuse during interrupt */ cmd->rcb.scp = scp; cmd->parent = afu; - spin_lock_init(&cmd->slock); /* Copy the CDB from the cmd passed in */ memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd)); @@ -466,7 +459,6 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) /* Stash the scp in the reserved field, for reuse during interrupt */ cmd->rcb.scp = scp; cmd->parent = afu; - spin_lock_init(&cmd->slock); nseg = scsi_dma_map(scp); if (unlikely(nseg < 0)) { @@ -1733,7 +1725,6 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, cmd = (struct afu_cmd *)PTR_ALIGN(buf, __alignof__(*cmd)); init_completion(&cmd->cevent); - spin_lock_init(&cmd->slock); cmd->parent = afu; pr_debug("%s: afu=%p cmd=%p %d\n", __func__, afu, cmd, ctx_hndl_u); @@ -1741,10 +1732,6 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD; cmd->rcb.ctx_id = afu->ctx_hndl; cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; - cmd->rcb.port_sel = 0x0; /* NA */ - cmd->rcb.lun_id = 0x0; /* NA */ - cmd->rcb.data_len = 0x0; - cmd->rcb.data_ea = 0x0; cmd->rcb.timeout = MC_AFU_SYNC_TIMEOUT; cmd->rcb.cdb[0] = 0xC0; /* AFU Sync */ @@ -1758,11 +1745,8 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, if (unlikely(rc)) goto out; - wait_resp(afu, cmd); - - /* Set on timeout */ - if (unlikely((cmd->sa.ioasc != 0) || - (cmd->sa.host_use_b[0] & B_ERROR))) + rc = wait_resp(afu, cmd); + if (unlikely(rc)) rc = -1; out: atomic_dec(&afu->cmds_active); From d4ace35166e55e73afe72a05d166342996063d35 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:42:50 -0600 Subject: [PATCH 240/256] scsi: cxlflash: Cleanup send_tmf() The send_tmf() routine includes some copy/paste cruft that can be removed as well as the setting of an AFU command-specific while holding the tmf_slock. While not a bug, it is out of place and should be shifted down alongside the other command initialization statements for clarity. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index db770301c30a..b7636993a097 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -299,12 +299,10 @@ static int wait_resp(struct afu *afu, struct afu_cmd *cmd) */ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) { - struct afu_cmd *cmd = sc_to_afucz(scp); - u32 port_sel = scp->device->channel + 1; - short lflag = 0; struct Scsi_Host *host = scp->device->host; struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; + struct afu_cmd *cmd = sc_to_afucz(scp); struct device *dev = &cfg->dev->dev; ulong lock_flags; int rc = 0; @@ -317,27 +315,21 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) !cfg->tmf_active, cfg->tmf_slock); cfg->tmf_active = true; - cmd->cmd_tmf = true; spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags); + cmd->rcb.scp = scp; + cmd->parent = afu; + cmd->cmd_tmf = true; + cmd->rcb.ctx_id = afu->ctx_hndl; cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; cmd->rcb.port_sel = port_sel; cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); - - lflag = SISL_REQ_FLAGS_TMF_CMD; - cmd->rcb.req_flags = (SISL_REQ_FLAGS_PORT_LUN_ID | - SISL_REQ_FLAGS_SUP_UNDERRUN | lflag); - - /* Stash the scp in the command, for reuse during interrupt */ - cmd->rcb.scp = scp; - cmd->parent = afu; - - /* Copy the CDB from the cmd passed in */ + SISL_REQ_FLAGS_SUP_UNDERRUN | + SISL_REQ_FLAGS_TMF_CMD); memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd)); - /* Send the command */ rc = send_cmd(afu, cmd); if (unlikely(rc)) { spin_lock_irqsave(&cfg->tmf_slock, lock_flags); From 9d89326c6660bc287b74983b51239460da10e189 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:43:01 -0600 Subject: [PATCH 241/256] scsi: cxlflash: Cleanup queuecommand() The queuecommand routine is disorganized where it populates the private command and also contains some logic/statements that are not needed given that cxlflash devices do not (and likely never will) support scatter-gather. Restructure the code to remove the unnecessary logic and create an organized flow: handle state -> DMA map -> populate command -> send command Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 50 +++++++++++++++--------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index b7636993a097..4e70c9a30afc 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -388,11 +388,11 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) struct afu *afu = cfg->afu; struct device *dev = &cfg->dev->dev; struct afu_cmd *cmd = sc_to_afucz(scp); + struct scatterlist *sg = scsi_sglist(scp); u32 port_sel = scp->device->channel + 1; - int nseg, i, ncount; - struct scatterlist *sg; + u16 req_flags = SISL_REQ_FLAGS_SUP_UNDERRUN; ulong lock_flags; - short lflag = 0; + int nseg = 0; int rc = 0; int kref_got = 0; @@ -435,45 +435,35 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) kref_get(&cfg->afu->mapcount); kref_got = 1; + if (likely(sg)) { + nseg = scsi_dma_map(scp); + if (unlikely(nseg < 0)) { + dev_err(dev, "%s: Fail DMA map!\n", __func__); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + + cmd->rcb.data_len = sg_dma_len(sg); + cmd->rcb.data_ea = sg_dma_address(sg); + } + + cmd->rcb.scp = scp; + cmd->parent = afu; + cmd->rcb.ctx_id = afu->ctx_hndl; cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; cmd->rcb.port_sel = port_sel; cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); if (scp->sc_data_direction == DMA_TO_DEVICE) - lflag = SISL_REQ_FLAGS_HOST_WRITE; - else - lflag = SISL_REQ_FLAGS_HOST_READ; + req_flags |= SISL_REQ_FLAGS_HOST_WRITE; - cmd->rcb.req_flags = (SISL_REQ_FLAGS_PORT_LUN_ID | - SISL_REQ_FLAGS_SUP_UNDERRUN | lflag); - - /* Stash the scp in the reserved field, for reuse during interrupt */ - cmd->rcb.scp = scp; - cmd->parent = afu; - - nseg = scsi_dma_map(scp); - if (unlikely(nseg < 0)) { - dev_err(dev, "%s: Fail DMA map! nseg=%d\n", - __func__, nseg); - rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } - - ncount = scsi_sg_count(scp); - scsi_for_each_sg(scp, sg, ncount, i) { - cmd->rcb.data_len = sg_dma_len(sg); - cmd->rcb.data_ea = sg_dma_address(sg); - } - - /* Copy the CDB from the scsi_cmnd passed in */ + cmd->rcb.req_flags = req_flags; memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb)); - /* Send the command */ rc = send_cmd(afu, cmd); if (unlikely(rc)) scsi_dma_unmap(scp); - out: if (kref_got) kref_put(&afu->mapcount, afu_unmap); From 48b4be36edf8a2cb0dedcb2d28f598e51249e805 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:43:09 -0600 Subject: [PATCH 242/256] scsi: cxlflash: Migrate IOARRIN specific routines to function pointers As staging for supporting hardware with a different queuing mechanism, move the send_cmd() and context_reset() routines to function pointers that are configured when the AFU is initialized. In addition, rename the existing routines to better reflect the queue model they support. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 3 +++ drivers/scsi/cxlflash/main.c | 21 +++++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index bed8e60f312e..6b8d1d3d45ee 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -161,6 +161,9 @@ struct afu { * fields after this point */ + int (*send_cmd)(struct afu *, struct afu_cmd *); + void (*context_reset)(struct afu_cmd *); + /* AFU HW */ struct cxl_ioctl_start_work work; struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */ diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 4e70c9a30afc..d2d2d836c079 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -188,12 +188,10 @@ static void cmd_complete(struct afu_cmd *cmd) } /** - * context_reset() - timeout handler for AFU commands + * context_reset_ioarrin() - reset command owner context via IOARRIN register * @cmd: AFU command that timed out. - * - * Sends a reset to the AFU. */ -static void context_reset(struct afu_cmd *cmd) +static void context_reset_ioarrin(struct afu_cmd *cmd) { int nretry = 0; u64 rrin = 0x1; @@ -217,14 +215,14 @@ static void context_reset(struct afu_cmd *cmd) } /** - * send_cmd() - sends an AFU command + * send_cmd_ioarrin() - sends an AFU command via IOARRIN register * @afu: AFU associated with the host. * @cmd: AFU command to send. * * Return: * 0 on success, SCSI_MLQUEUE_HOST_BUSY on failure */ -static int send_cmd(struct afu *afu, struct afu_cmd *cmd) +static int send_cmd_ioarrin(struct afu *afu, struct afu_cmd *cmd) { struct cxlflash_cfg *cfg = afu->parent; struct device *dev = &cfg->dev->dev; @@ -273,7 +271,7 @@ static int wait_resp(struct afu *afu, struct afu_cmd *cmd) timeout = wait_for_completion_timeout(&cmd->cevent, timeout); if (!timeout) { - context_reset(cmd); + afu->context_reset(cmd); rc = -1; } @@ -330,7 +328,7 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) SISL_REQ_FLAGS_TMF_CMD); memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd)); - rc = send_cmd(afu, cmd); + rc = afu->send_cmd(afu, cmd); if (unlikely(rc)) { spin_lock_irqsave(&cfg->tmf_slock, lock_flags); cfg->tmf_active = false; @@ -461,7 +459,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) cmd->rcb.req_flags = req_flags; memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb)); - rc = send_cmd(afu, cmd); + rc = afu->send_cmd(afu, cmd); if (unlikely(rc)) scsi_dma_unmap(scp); out: @@ -1631,6 +1629,9 @@ static int init_afu(struct cxlflash_cfg *cfg) goto err2; } + afu->send_cmd = send_cmd_ioarrin; + afu->context_reset = context_reset_ioarrin; + pr_debug("%s: afu version %s, interface version 0x%llX\n", __func__, afu->version, afu->interface_version); @@ -1723,7 +1724,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, *((__be16 *)&cmd->rcb.cdb[2]) = cpu_to_be16(ctx_hndl_u); *((__be32 *)&cmd->rcb.cdb[4]) = cpu_to_be32(res_hndl_u); - rc = send_cmd(afu, cmd); + rc = afu->send_cmd(afu, cmd); if (unlikely(rc)) goto out; From fe7f96982a4e7103ffab45fba34c57ee19b62639 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Mon, 28 Nov 2016 18:43:18 -0600 Subject: [PATCH 243/256] scsi: cxlflash: Migrate scsi command pointer to AFU command Currently, when sending a SCSI command, the pointer is stored in a reserved field of the AFU command descriptor for retrieval once the SCSI command has completed. In order to support new descriptor formats that make use of the reserved field, the pointer is migrated to outside the descriptor where it can still be found during completion processing. Signed-off-by: Matthew R. Ochs Acked-by: Uma Krishnan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/common.h | 1 + drivers/scsi/cxlflash/main.c | 10 +++++----- drivers/scsi/cxlflash/sislite.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 6b8d1d3d45ee..0e9de5d62da2 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -129,6 +129,7 @@ struct afu_cmd { struct sisl_ioarcb rcb; /* IOARCB (cache line aligned) */ struct sisl_ioasa sa; /* IOASA must follow IOARCB */ struct afu *parent; + struct scsi_cmnd *scp; struct completion cevent; u8 cmd_tmf:1; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index d2d2d836c079..b17ebf6d0a7e 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -151,7 +151,7 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp) * * Prepares and submits command that has either completed or timed out to * the SCSI stack. Checks AFU command back into command pool for non-internal - * (rcb.scp populated) commands. + * (cmd->scp populated) commands. */ static void cmd_complete(struct afu_cmd *cmd) { @@ -161,8 +161,8 @@ static void cmd_complete(struct afu_cmd *cmd) struct cxlflash_cfg *cfg = afu->parent; bool cmd_is_tmf; - if (cmd->rcb.scp) { - scp = cmd->rcb.scp; + if (cmd->scp) { + scp = cmd->scp; if (unlikely(cmd->sa.ioasc)) process_cmd_err(cmd, scp); else @@ -315,7 +315,7 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) cfg->tmf_active = true; spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags); - cmd->rcb.scp = scp; + cmd->scp = scp; cmd->parent = afu; cmd->cmd_tmf = true; @@ -445,7 +445,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) cmd->rcb.data_ea = sg_dma_address(sg); } - cmd->rcb.scp = scp; + cmd->scp = scp; cmd->parent = afu; cmd->rcb.ctx_id = afu->ctx_hndl; diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h index 347fc1671975..1a2d09c148b3 100644 --- a/drivers/scsi/cxlflash/sislite.h +++ b/drivers/scsi/cxlflash/sislite.h @@ -72,7 +72,7 @@ struct sisl_ioarcb { u16 timeout; /* in units specified by req_flags */ u32 rsvd1; u8 cdb[16]; /* must be in big endian */ - struct scsi_cmnd *scp; + u64 reserved; /* Reserved area */ } __packed; struct sisl_rc { From af25756de972d0f05246f9e6869f395ee0302c02 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 30 Nov 2016 22:36:48 +0300 Subject: [PATCH 244/256] scsi: dpt_i2o: double free on error path We recently introduced a kfree() in the caller for this function. That's where, logically, you would think the kfree() should be. Unfortunately the code was just ugly and not buggy so the static checker warning was a false postive and introduced a double free. I've removed the old kfree() and left the new one. Fixes: 021e2927586d ("scsi: dpt_i2o: Add a missing call to kfree") Signed-off-by: Dan Carpenter Reviewed-by: Quentin Lambert Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index f88b3d216a88..27c0dce22e72 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -651,7 +651,6 @@ static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply) } spin_unlock_irqrestore(pHba->host->host_lock, flags); if (i >= nr) { - kfree (reply); printk(KERN_WARNING"%s: Too many outstanding " "ioctl commands\n", pHba->name); return (u32)-1; From 9dadfb973f0d9396ef18f7ee0867fe9a165c03f4 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 30 Nov 2016 15:28:55 -0600 Subject: [PATCH 245/256] scsi: ipr: Fix runaway IRQs when falling back from MSI to LSI LSIs must be ack'ed with an MMIO otherwise they remain asserted forever. This is controlled by the "clear_isr" flag. While we set that flag properly when deciding initially whether to use LSIs or MSIs, we fail to set it if we first chose MSIs, the test fails, then fallback to LSIs. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Brian King Signed-off-by: Martin K. Petersen --- drivers/scsi/ipr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 534dc3c877da..835c59c777f2 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -10157,6 +10157,7 @@ static int ipr_probe_ioa(struct pci_dev *pdev, pci_free_irq_vectors(pdev); ioa_cfg->nvectors = 1; + ioa_cfg->clear_isr = 1; break; default: goto out_msi_disable; From e3cb0e47b9233a42f8c5865ad748666b6bbbc12f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 30 Nov 2016 17:21:01 +0100 Subject: [PATCH 246/256] scsi: isci: switch to pci_alloc_irq_vectors Signed-off-by: Christoph Hellwig Reviewed-by: Artur Paszkiewicz Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/init.c | 23 ++++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 22a9bb1abae1..b3539928073c 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -295,7 +295,6 @@ enum sci_controller_states { #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS) struct isci_pci_info { - struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; struct isci_host *hosts[SCI_MAX_CONTROLLERS]; struct isci_orom *orom; }; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 77128d680e3b..0b5b5db0d0f8 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -350,16 +350,12 @@ static int isci_setup_interrupts(struct pci_dev *pdev) */ num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT; - for (i = 0; i < num_msix; i++) - pci_info->msix_entries[i].entry = i; - - err = pci_enable_msix_exact(pdev, pci_info->msix_entries, num_msix); - if (err) + err = pci_alloc_irq_vectors(pdev, num_msix, num_msix, PCI_IRQ_MSIX); + if (err < 0) goto intx; for (i = 0; i < num_msix; i++) { int id = i / SCI_NUM_MSI_X_INT; - struct msix_entry *msix = &pci_info->msix_entries[i]; irq_handler_t isr; ihost = pci_info->hosts[id]; @@ -369,8 +365,8 @@ static int isci_setup_interrupts(struct pci_dev *pdev) else isr = isci_msix_isr; - err = devm_request_irq(&pdev->dev, msix->vector, isr, 0, - DRV_NAME"-msix", ihost); + err = devm_request_irq(&pdev->dev, pci_irq_vector(pdev, i), + isr, 0, DRV_NAME"-msix", ihost); if (!err) continue; @@ -378,18 +374,19 @@ static int isci_setup_interrupts(struct pci_dev *pdev) while (i--) { id = i / SCI_NUM_MSI_X_INT; ihost = pci_info->hosts[id]; - msix = &pci_info->msix_entries[i]; - devm_free_irq(&pdev->dev, msix->vector, ihost); + devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), + ihost); } - pci_disable_msix(pdev); + pci_free_irq_vectors(pdev); goto intx; } return 0; intx: for_each_isci_host(i, ihost, pdev) { - err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr, - IRQF_SHARED, DRV_NAME"-intx", ihost); + err = devm_request_irq(&pdev->dev, pci_irq_vector(pdev, 0), + isci_intx_isr, IRQF_SHARED, DRV_NAME"-intx", + ihost); if (err) break; } From d37a0082919360dda828679cccb5c4e8e83ec199 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Tue, 29 Nov 2016 23:45:57 +0800 Subject: [PATCH 247/256] scsi: hisi_sas: fix free'ing in probe and remove This patch addresses 4 problems in the module probe/remove: - When hisi_sas_shost_alloc() fails after we alloc shost memory, we should free shost memory before the function returns. - When hisi_sas_probe() fails after we alloc the HBA memories, we should also free the HBA memories. - We should free shost memory at the end of hisi_sas_remove(). - sha->core.shost is set twice, so remove extra set. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Reviewed-by: Quentin Lambert Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 6d6f150d8aed..d50e9cfefd24 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1412,8 +1412,10 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, struct clk *refclk; shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba)); - if (!shost) - goto err_out; + if (!shost) { + dev_err(dev, "scsi host alloc failed\n"); + return NULL; + } hisi_hba = shost_priv(shost); hisi_hba->hw = hw; @@ -1477,6 +1479,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, return shost; err_out: + kfree(shost); dev_err(dev, "shost alloc failed\n"); return NULL; } @@ -1503,10 +1506,8 @@ int hisi_sas_probe(struct platform_device *pdev, int rc, phy_nr, port_nr, i; shost = hisi_sas_shost_alloc(pdev, hw); - if (!shost) { - rc = -ENOMEM; - goto err_out_ha; - } + if (!shost) + return -ENOMEM; sha = SHOST_TO_SAS_HA(shost); hisi_hba = shost_priv(shost); @@ -1516,12 +1517,13 @@ int hisi_sas_probe(struct platform_device *pdev, arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL); arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL); - if (!arr_phy || !arr_port) - return -ENOMEM; + if (!arr_phy || !arr_port) { + rc = -ENOMEM; + goto err_out_ha; + } sha->sas_phy = arr_phy; sha->sas_port = arr_port; - sha->core.shost = shost; sha->lldd_ha = hisi_hba; shost->transportt = hisi_sas_stt; @@ -1566,6 +1568,7 @@ int hisi_sas_probe(struct platform_device *pdev, err_out_register_ha: scsi_remove_host(shost); err_out_ha: + hisi_sas_free(hisi_hba); kfree(shost); return rc; } @@ -1575,12 +1578,14 @@ int hisi_sas_remove(struct platform_device *pdev) { struct sas_ha_struct *sha = platform_get_drvdata(pdev); struct hisi_hba *hisi_hba = sha->lldd_ha; + struct Scsi_Host *shost = sha->core.shost; scsi_remove_host(sha->core.shost); sas_unregister_ha(sha); sas_remove_host(sha->core.shost); hisi_sas_free(hisi_hba); + kfree(shost); return 0; } EXPORT_SYMBOL_GPL(hisi_sas_remove); From 609a70df07af1ff857257fb2e93c3ef281e30710 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 30 Nov 2016 23:35:47 +0100 Subject: [PATCH 248/256] scsi: hpsa: use %phN for short hex dumps Passing one instead of 8 or 16 arguments reduces the size of the generated code somewhat: add/remove: 2/3 grow/shrink: 1/4 up/down: 1772/-2137 (-365) There's one more candidate, unique_id_show, but that uses %02X, and I'm not sure it would be ok to start using lowercase there, so I've left it alone for now. Signed-off-by: Rasmus Villemoes Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 216c137d96ea..220ccd40dcbc 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -703,9 +703,7 @@ static ssize_t lunid_show(struct device *dev, } memcpy(lunid, hdev->scsi3addr, sizeof(lunid)); spin_unlock_irqrestore(&h->lock, flags); - return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - lunid[0], lunid[1], lunid[2], lunid[3], - lunid[4], lunid[5], lunid[6], lunid[7]); + return snprintf(buf, 20, "0x%8phN\n", lunid); } static ssize_t unique_id_show(struct device *dev, @@ -2839,14 +2837,8 @@ static void hpsa_print_cmd(struct ctlr_info *h, char *txt, const u8 *cdb = c->Request.CDB; const u8 *lun = c->Header.LUN.LunAddrBytes; - dev_warn(&h->pdev->dev, "%s: LUN:%02x%02x%02x%02x%02x%02x%02x%02x" - " CDB:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", - txt, lun[0], lun[1], lun[2], lun[3], - lun[4], lun[5], lun[6], lun[7], - cdb[0], cdb[1], cdb[2], cdb[3], - cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11], - cdb[12], cdb[13], cdb[14], cdb[15]); + dev_warn(&h->pdev->dev, "%s: LUN:%8phN CDB:%16phN\n", + txt, lun, cdb); } static void hpsa_scsi_interpret_error(struct ctlr_info *h, @@ -6019,11 +6011,9 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h, if (h->raid_offload_debug > 0) dev_info(&h->pdev->dev, - "scsi %d:%d:%d:%d %s scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + "scsi %d:%d:%d:%d %s scsi3addr 0x%8phN\n", h->scsi_host->host_no, dev->bus, dev->target, dev->lun, - "Reset as abort", - scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3], - scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); + "Reset as abort", scsi3addr); if (!dev->offload_enabled) { dev_warn(&h->pdev->dev, @@ -6040,32 +6030,28 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h, /* send the reset */ if (h->raid_offload_debug > 0) dev_info(&h->pdev->dev, - "Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - psa[0], psa[1], psa[2], psa[3], - psa[4], psa[5], psa[6], psa[7]); + "Reset as abort: Resetting physical device at scsi3addr 0x%8phN\n", + psa); rc = hpsa_do_reset(h, dev, psa, HPSA_PHYS_TARGET_RESET, reply_queue); if (rc != 0) { dev_warn(&h->pdev->dev, - "Reset as abort: Failed on physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - psa[0], psa[1], psa[2], psa[3], - psa[4], psa[5], psa[6], psa[7]); + "Reset as abort: Failed on physical device at scsi3addr 0x%8phN\n", + psa); return rc; /* failed to reset */ } /* wait for device to recover */ if (wait_for_device_to_become_ready(h, psa, reply_queue) != 0) { dev_warn(&h->pdev->dev, - "Reset as abort: Failed: Device never recovered from reset: 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - psa[0], psa[1], psa[2], psa[3], - psa[4], psa[5], psa[6], psa[7]); + "Reset as abort: Failed: Device never recovered from reset: 0x%8phN\n", + psa); return -1; /* failed to recover */ } /* device recovered */ dev_info(&h->pdev->dev, - "Reset as abort: Device recovered from reset: scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - psa[0], psa[1], psa[2], psa[3], - psa[4], psa[5], psa[6], psa[7]); + "Reset as abort: Device recovered from reset: scsi3addr 0x%8phN\n", + psa); return rc; /* success */ } From d29425b065cdab5c5e65a48108adde5ea72d4656 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Dec 2016 11:30:50 -0800 Subject: [PATCH 249/256] scsi: scsi_dh_alua: Fix RCU annotations This patch avoids that sparse complains about RCU pointer dereferences. Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: tang.junhui Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 241829e59668..32e48cc4cf71 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -95,7 +95,7 @@ struct alua_port_group { struct alua_dh_data { struct list_head node; - struct alua_port_group *pg; + struct alua_port_group __rcu *pg; int group_id; spinlock_t pg_lock; struct scsi_device *sdev; @@ -369,7 +369,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h, /* Check for existing port group references */ spin_lock(&h->pg_lock); - old_pg = h->pg; + old_pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock)); if (old_pg != pg) { /* port group has changed. Update to new port group */ if (h->pg) { @@ -388,7 +388,9 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h, list_add_rcu(&h->node, &pg->dh_list); spin_unlock_irqrestore(&pg->lock, flags); - alua_rtpg_queue(h->pg, sdev, NULL, true); + alua_rtpg_queue(rcu_dereference_protected(h->pg, + lockdep_is_held(&h->pg_lock)), + sdev, NULL, true); spin_unlock(&h->pg_lock); if (old_pg) @@ -937,7 +939,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) static int alua_set_params(struct scsi_device *sdev, const char *params) { struct alua_dh_data *h = sdev->handler_data; - struct alua_port_group __rcu *pg = NULL; + struct alua_port_group *pg = NULL; unsigned int optimize = 0, argc; const char *p = params; int result = SCSI_DH_OK; @@ -984,7 +986,7 @@ static int alua_activate(struct scsi_device *sdev, struct alua_dh_data *h = sdev->handler_data; int err = SCSI_DH_OK; struct alua_queue_data *qdata; - struct alua_port_group __rcu *pg; + struct alua_port_group *pg; qdata = kzalloc(sizeof(*qdata), GFP_KERNEL); if (!qdata) { @@ -1048,7 +1050,7 @@ static void alua_check(struct scsi_device *sdev, bool force) static int alua_prep_fn(struct scsi_device *sdev, struct request *req) { struct alua_dh_data *h = sdev->handler_data; - struct alua_port_group __rcu *pg; + struct alua_port_group *pg; unsigned char state = SCSI_ACCESS_STATE_OPTIMAL; int ret = BLKPREP_OK; @@ -1118,7 +1120,7 @@ static void alua_bus_detach(struct scsi_device *sdev) struct alua_port_group *pg; spin_lock(&h->pg_lock); - pg = h->pg; + pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock)); rcu_assign_pointer(h->pg, NULL); h->sdev = NULL; spin_unlock(&h->pg_lock); From 2a80d5458a027f6d514987c09f0b51f45c3a5be4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 2 Dec 2016 11:36:13 +0100 Subject: [PATCH 250/256] scsi: hpsa: fallback to use legacy REPORT PHYS command Older SmartArray controllers (eg SmartArray 64xx) do not support the extended REPORT PHYS command, so fallback to use the legacy version here. Signed-off-by: Hannes Reinecke Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 220ccd40dcbc..f5ab690b3091 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3632,8 +3632,32 @@ out: static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, struct ReportExtendedLUNdata *buf, int bufsize) { - return hpsa_scsi_do_report_luns(h, 0, buf, bufsize, - HPSA_REPORT_PHYS_EXTENDED); + int rc; + struct ReportLUNdata *lbuf; + + rc = hpsa_scsi_do_report_luns(h, 0, buf, bufsize, + HPSA_REPORT_PHYS_EXTENDED); + if (!rc || !hpsa_allow_any) + return rc; + + /* REPORT PHYS EXTENDED is not supported */ + lbuf = kzalloc(sizeof(*lbuf), GFP_KERNEL); + if (!lbuf) + return -ENOMEM; + + rc = hpsa_scsi_do_report_luns(h, 0, lbuf, sizeof(*lbuf), 0); + if (!rc) { + int i; + u32 nphys; + + /* Copy ReportLUNdata header */ + memcpy(buf, lbuf, 8); + nphys = be32_to_cpu(*((__be32 *)lbuf->LUNListLength)) / 8; + for (i = 0; i < nphys; i++) + memcpy(buf->LUN[i].lunid, lbuf->LUN[i], 8); + } + kfree(lbuf); + return rc; } static inline int hpsa_scsi_do_report_log_luns(struct ctlr_info *h, From 29b33252751b430e400a987667a826ffcd2741f4 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Sun, 4 Dec 2016 13:21:42 +0800 Subject: [PATCH 251/256] scsi: be2iscsi: set errno on error path Variable ret is reset in the loop, and its value will be 0 during the second and after repeat of the loop. If pci_alloc_consistent() returns a NULL pointer then, it will leaves with return value 0. 0 means no error, which is contrary to the fact. This patches fixes the bug, explicitly assigning "-ENOMEM" to return variable ret on the path that the call to pci_alloc_consistent() fails. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188941 Signed-off-by: Pan Bian Reviewed-by: Jitendra Bhivare Signed-off-by: Martin K. Petersen --- drivers/scsi/be2iscsi/be_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index d9239c2d49b1..b6c5791060e5 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3113,8 +3113,10 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, cq_vaddress = pci_alloc_consistent(phba->pcidev, num_cq_pages * PAGE_SIZE, &paddr); - if (!cq_vaddress) + if (!cq_vaddress) { + ret = -ENOMEM; goto create_cq_error; + } ret = be_fill_queue(cq, phba->params.num_cq_entries, sizeof(struct sol_cqe), cq_vaddress); From 84a261ff76544a7968e184eac4213b24e8bbd81a Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Sun, 4 Dec 2016 13:23:04 +0800 Subject: [PATCH 252/256] scsi: be2iscsi: set errno on error path Variable ret is reset in the loop, and its value will be 0 during the second and after repeat of the loop. If pci_alloc_consistent() returns a NULL pointer then, it will leaves with return value 0. 0 means no error, which is contrary to the fact. This patches fixes the bug, explicitly assigning "-ENOMEM" to return variable ret on the path that the call to pci_alloc_consistent() fails. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188951 Signed-off-by: Pan Bian Reviewed-by: Jitendra Bhivare Signed-off-by: Martin K. Petersen --- drivers/scsi/be2iscsi/be_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index b6c5791060e5..b5112d6d7e73 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3049,8 +3049,10 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, eq_vaddress = pci_alloc_consistent(phba->pcidev, num_eq_pages * PAGE_SIZE, &paddr); - if (!eq_vaddress) + if (!eq_vaddress) { + ret = -ENOMEM; goto create_eq_error; + } mem->va = eq_vaddress; ret = be_fill_queue(eq, phba->params.num_eq_entries, From 9c58b395563b15866c9fd9bb7e6f7f8db12ac3ae Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Fri, 11 Nov 2016 17:49:49 +0100 Subject: [PATCH 253/256] scsi: scsi_devinfo: remove synchronous ALUA for NETAPP devices NetApp did confirm this is not required. Cc: Martin George Cc: Robert Stankey Cc: Steven Schremmer Cc: Sean Stewart Cc: Hannes Reinecke Cc: Christophe Varoqui Cc: James E.J. Bottomley Cc: Martin K. Petersen Cc: SCSI ML Cc: device-mapper development Signed-off-by: Xose Vazquez Perez Reviewed-by: Sean Stewart Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 246456925335..28fea83ae2fe 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -220,8 +220,6 @@ static struct { {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"NEC", "iStorage", NULL, BLIST_REPORTLUN2}, - {"NETAPP", "LUN C-Mode", NULL, BLIST_SYNC_ALUA}, - {"NETAPP", "INF-01-00", NULL, BLIST_SYNC_ALUA}, {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, From fad119b707f8cc01b259b8585af4f9688e57c9a7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 2 Dec 2016 12:52:23 +0100 Subject: [PATCH 254/256] scsi: megaraid_sas: switch to pci_alloc_irq_vectors [mkp: fixed bad indentation] Signed-off-by: Hannes Reinecke Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 1 - drivers/scsi/megaraid/megaraid_sas_base.c | 78 +++++++++++------------ 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 74c7b441aace..757ddda1d63e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2120,7 +2120,6 @@ struct megasas_instance { u32 ctrl_context_pages; struct megasas_ctrl_info *ctrl_info; unsigned int msix_vectors; - struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES]; struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES]; u64 map_id; u64 pd_seq_map_id; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 546267698486..6484c382f670 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4837,7 +4837,7 @@ fail_alloc_cmds: } /* - * megasas_setup_irqs_msix - register legacy interrupts. + * megasas_setup_irqs_ioapic - register legacy interrupts. * @instance: Adapter soft state * * Do not enable interrupt, only setup ISRs. @@ -4852,8 +4852,9 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance) pdev = instance->pdev; instance->irq_context[0].instance = instance; instance->irq_context[0].MSIxIndex = 0; - if (request_irq(pdev->irq, instance->instancet->service_isr, - IRQF_SHARED, "megasas", &instance->irq_context[0])) { + if (request_irq(pci_irq_vector(pdev, 0), + instance->instancet->service_isr, IRQF_SHARED, + "megasas", &instance->irq_context[0])) { dev_err(&instance->pdev->dev, "Failed to register IRQ from %s %d\n", __func__, __LINE__); @@ -4874,28 +4875,23 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance) static int megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) { - int i, j, cpu; + int i, j; struct pci_dev *pdev; pdev = instance->pdev; /* Try MSI-x */ - cpu = cpumask_first(cpu_online_mask); for (i = 0; i < instance->msix_vectors; i++) { instance->irq_context[i].instance = instance; instance->irq_context[i].MSIxIndex = i; - if (request_irq(instance->msixentry[i].vector, + if (request_irq(pci_irq_vector(pdev, i), instance->instancet->service_isr, 0, "megasas", &instance->irq_context[i])) { dev_err(&instance->pdev->dev, "Failed to register IRQ for vector %d.\n", i); - for (j = 0; j < i; j++) { - if (smp_affinity_enable) - irq_set_affinity_hint( - instance->msixentry[j].vector, NULL); - free_irq(instance->msixentry[j].vector, - &instance->irq_context[j]); - } + for (j = 0; j < i; j++) + free_irq(pci_irq_vector(pdev, j), + &instance->irq_context[j]); /* Retry irq register for IO_APIC*/ instance->msix_vectors = 0; if (is_probe) @@ -4903,14 +4899,6 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) else return -1; } - if (smp_affinity_enable) { - if (irq_set_affinity_hint(instance->msixentry[i].vector, - get_cpu_mask(cpu))) - dev_err(&instance->pdev->dev, - "Failed to set affinity hint" - " for cpu %d\n", cpu); - cpu = cpumask_next(cpu, cpu_online_mask); - } } return 0; } @@ -4927,14 +4915,12 @@ megasas_destroy_irqs(struct megasas_instance *instance) { if (instance->msix_vectors) for (i = 0; i < instance->msix_vectors; i++) { - if (smp_affinity_enable) - irq_set_affinity_hint( - instance->msixentry[i].vector, NULL); - free_irq(instance->msixentry[i].vector, + free_irq(pci_irq_vector(instance->pdev, i), &instance->irq_context[i]); } else - free_irq(instance->pdev->irq, &instance->irq_context[0]); + free_irq(pci_irq_vector(instance->pdev, 0), + &instance->irq_context[0]); } /** @@ -5092,6 +5078,8 @@ static int megasas_init_fw(struct megasas_instance *instance) msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & 0x4000000) >> 0x1a; if (msix_enable && !msix_disable) { + int irq_flags = PCI_IRQ_MSIX; + scratch_pad_2 = readl (&instance->reg_set->outbound_scratch_pad_2); /* Check max MSI-X vectors */ @@ -5128,15 +5116,18 @@ static int megasas_init_fw(struct megasas_instance *instance) /* Don't bother allocating more MSI-X vectors than cpus */ instance->msix_vectors = min(instance->msix_vectors, (unsigned int)num_online_cpus()); - for (i = 0; i < instance->msix_vectors; i++) - instance->msixentry[i].entry = i; - i = pci_enable_msix_range(instance->pdev, instance->msixentry, - 1, instance->msix_vectors); + if (smp_affinity_enable) + irq_flags |= PCI_IRQ_AFFINITY; + i = pci_alloc_irq_vectors(instance->pdev, 1, + instance->msix_vectors, irq_flags); if (i > 0) instance->msix_vectors = i; else instance->msix_vectors = 0; } + i = pci_alloc_irq_vectors(instance->pdev, 1, 1, PCI_IRQ_LEGACY); + if (i < 0) + goto fail_setup_irqs; dev_info(&instance->pdev->dev, "firmware supports msix\t: (%d)", fw_msix_count); @@ -5307,10 +5298,11 @@ static int megasas_init_fw(struct megasas_instance *instance) fail_get_pd_list: instance->instancet->disable_intr(instance); - megasas_destroy_irqs(instance); fail_init_adapter: + megasas_destroy_irqs(instance); +fail_setup_irqs: if (instance->msix_vectors) - pci_disable_msix(instance->pdev); + pci_free_irq_vectors(instance->pdev); instance->msix_vectors = 0; fail_ready_state: kfree(instance->ctrl_info); @@ -5579,7 +5571,6 @@ static int megasas_io_attach(struct megasas_instance *instance) /* * Export parameters required by SCSI mid-layer */ - host->irq = instance->pdev->irq; host->unique_id = instance->unique_id; host->can_queue = instance->max_scsi_cmds; host->this_id = instance->init_id; @@ -5942,7 +5933,7 @@ fail_io_attach: else megasas_release_mfi(instance); if (instance->msix_vectors) - pci_disable_msix(instance->pdev); + pci_free_irq_vectors(instance->pdev); fail_init_mfi: fail_alloc_dma_buf: if (instance->evt_detail) @@ -6100,7 +6091,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) megasas_destroy_irqs(instance); if (instance->msix_vectors) - pci_disable_msix(instance->pdev); + pci_free_irq_vectors(instance->pdev); pci_save_state(pdev); pci_disable_device(pdev); @@ -6120,6 +6111,7 @@ megasas_resume(struct pci_dev *pdev) int rval; struct Scsi_Host *host; struct megasas_instance *instance; + int irq_flags = PCI_IRQ_LEGACY; instance = pci_get_drvdata(pdev); host = instance->host; @@ -6155,9 +6147,15 @@ megasas_resume(struct pci_dev *pdev) goto fail_ready_state; /* Now re-enable MSI-X */ - if (instance->msix_vectors && - pci_enable_msix_exact(instance->pdev, instance->msixentry, - instance->msix_vectors)) + if (instance->msix_vectors) { + irq_flags = PCI_IRQ_MSIX; + if (smp_affinity_enable) + irq_flags |= PCI_IRQ_AFFINITY; + } + rval = pci_alloc_irq_vectors(instance->pdev, 1, + instance->msix_vectors ? + instance->msix_vectors : 1, irq_flags); + if (rval < 0) goto fail_reenable_msix; if (instance->ctrl_context) { @@ -6330,7 +6328,7 @@ skip_firing_dcmds: megasas_destroy_irqs(instance); if (instance->msix_vectors) - pci_disable_msix(instance->pdev); + pci_free_irq_vectors(instance->pdev); if (instance->ctrl_context) { megasas_release_fusion(instance); @@ -6425,7 +6423,7 @@ skip_firing_dcmds: megasas_destroy_irqs(instance); if (instance->msix_vectors) - pci_disable_msix(instance->pdev); + pci_free_irq_vectors(instance->pdev); } /** From 26f3ba9600e5d4437bb7299d2b01003b0d93e853 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 6 Dec 2016 20:44:07 +0800 Subject: [PATCH 255/256] scsi: hisi_sas: support deferred probe for v2 hw In the hip06 and hip07 SoCs, the interrupt lines from the SAS controllers are connected to mbigen hw module [1]. The mbigen module is probed with module_init, and, as such, is not guaranteed to probe before the SAS driver. So we need to support deferred probe. We check for probe deferral in the hw layer probe, so we not probe into the main layer and allocate shost, memories, etc., to later learn that we need to defer the probe. [1] ./Documentation/devicetree/bindings/interrupt-controller/hisilicon,mbigen-v2.txt Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 93876c0137eb..b934aec1eebb 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2790,6 +2790,18 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { static int hisi_sas_v2_probe(struct platform_device *pdev) { + /* + * Check if we should defer the probe before we probe the + * upper layer, as it's hard to defer later on. + */ + int ret = platform_get_irq(pdev, 0); + + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "cannot obtain irq\n"); + return ret; + } + return hisi_sas_probe(pdev, &hisi_sas_v2_hw); } From f5b893c947151d424a4ab55ea3a8544b81974b31 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Dec 2016 14:56:50 +0100 Subject: [PATCH 256/256] scsi: qla4xxx: switch to pci_alloc_irq_vectors And simplify the MSI-X logic in general - just request the two vectors directly instead of going through an indirection table. Signed-off-by: Christoph Hellwig Reviewed-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_def.h | 18 +------ drivers/scsi/qla4xxx/ql4_glbl.h | 1 - drivers/scsi/qla4xxx/ql4_isr.c | 27 +++++----- drivers/scsi/qla4xxx/ql4_nx.c | 87 +++++++++------------------------ 4 files changed, 36 insertions(+), 97 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a7cfc270bd08..aeebefb1e9f8 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -409,18 +409,9 @@ struct qla4_8xxx_legacy_intr_set { /* MSI-X Support */ -#define QLA_MSIX_DEFAULT 0x00 -#define QLA_MSIX_RSP_Q 0x01 - +#define QLA_MSIX_DEFAULT 0 +#define QLA_MSIX_RSP_Q 1 #define QLA_MSIX_ENTRIES 2 -#define QLA_MIDX_DEFAULT 0 -#define QLA_MIDX_RSP_Q 1 - -struct ql4_msix_entry { - int have_irq; - uint16_t msix_vector; - uint16_t msix_entry; -}; /* * ISP Operations @@ -572,9 +563,6 @@ struct scsi_qla_host { #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ #define AF_HA_REMOVAL 12 /* 0x00001000 */ -#define AF_INTx_ENABLED 15 /* 0x00008000 */ -#define AF_MSI_ENABLED 16 /* 0x00010000 */ -#define AF_MSIX_ENABLED 17 /* 0x00020000 */ #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ #define AF_FW_RECOVERY 19 /* 0x00080000 */ #define AF_EEH_BUSY 20 /* 0x00100000 */ @@ -762,8 +750,6 @@ struct scsi_qla_host { struct isp_operations *isp_ops; struct ql82xx_hw_data hw; - struct ql4_msix_entry msix_entries[QLA_MSIX_ENTRIES]; - uint32_t nx_dev_init_timeout; uint32_t nx_reset_timeout; void *fw_dump; diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 2559144f5475..bce96a58f14e 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -134,7 +134,6 @@ int qla4_8xxx_get_flash_info(struct scsi_qla_host *ha); void qla4_82xx_enable_intrs(struct scsi_qla_host *ha); void qla4_82xx_disable_intrs(struct scsi_qla_host *ha); int qla4_8xxx_enable_msix(struct scsi_qla_host *ha); -void qla4_8xxx_disable_msix(struct scsi_qla_host *ha); irqreturn_t qla4_8xxx_msi_handler(int irq, void *dev_id); irqreturn_t qla4_8xxx_default_intr_handler(int irq, void *dev_id); irqreturn_t qla4_8xxx_msix_rsp_q(int irq, void *dev_id); diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 4f9c0f2be89d..d2cd33d8d67f 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -1107,7 +1107,7 @@ static void qla4_82xx_spurious_interrupt(struct scsi_qla_host *ha, DEBUG2(ql4_printk(KERN_INFO, ha, "Spurious Interrupt\n")); if (is_qla8022(ha)) { writel(0, &ha->qla4_82xx_reg->host_int); - if (test_bit(AF_INTx_ENABLED, &ha->flags)) + if (!ha->pdev->msi_enabled && !ha->pdev->msix_enabled) qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); } @@ -1564,19 +1564,18 @@ int qla4xxx_request_irqs(struct scsi_qla_host *ha) try_msi: /* Trying MSI */ - ret = pci_enable_msi(ha->pdev); - if (!ret) { + ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI); + if (ret > 0) { ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler, 0, DRIVER_NAME, ha); if (!ret) { DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n")); - set_bit(AF_MSI_ENABLED, &ha->flags); goto irq_attached; } else { ql4_printk(KERN_WARNING, ha, "MSI: Failed to reserve interrupt %d " "already in use.\n", ha->pdev->irq); - pci_disable_msi(ha->pdev); + pci_free_irq_vectors(ha->pdev); } } @@ -1592,7 +1591,6 @@ try_intx: IRQF_SHARED, DRIVER_NAME, ha); if (!ret) { DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n")); - set_bit(AF_INTx_ENABLED, &ha->flags); goto irq_attached; } else { @@ -1614,14 +1612,11 @@ irq_not_attached: void qla4xxx_free_irqs(struct scsi_qla_host *ha) { - if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) { - if (test_bit(AF_MSIX_ENABLED, &ha->flags)) { - qla4_8xxx_disable_msix(ha); - } else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) { - free_irq(ha->pdev->irq, ha); - pci_disable_msi(ha->pdev); - } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags)) { - free_irq(ha->pdev->irq, ha); - } - } + if (!test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) + return; + + if (ha->pdev->msix_enabled) + free_irq(pci_irq_vector(ha->pdev, 1), ha); + free_irq(pci_irq_vector(ha->pdev, 0), ha); + pci_free_irq_vectors(ha->pdev); } diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index bccd8b674234..e91abb327745 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -3945,7 +3945,7 @@ void qla4_82xx_process_mbox_intr(struct scsi_qla_host *ha, int out_count) ha->isp_ops->interrupt_service_routine(ha, intr_status); if (test_bit(AF_INTERRUPTS_ON, &ha->flags) && - test_bit(AF_INTx_ENABLED, &ha->flags)) + (!ha->pdev->msi_enabled && !ha->pdev->msix_enabled)) qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); } @@ -4174,78 +4174,37 @@ qla4_82xx_disable_intrs(struct scsi_qla_host *ha) spin_unlock_irq(&ha->hardware_lock); } -struct ql4_init_msix_entry { - uint16_t entry; - uint16_t index; - const char *name; - irq_handler_t handler; -}; - -static struct ql4_init_msix_entry qla4_8xxx_msix_entries[QLA_MSIX_ENTRIES] = { - { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, - "qla4xxx (default)", - (irq_handler_t)qla4_8xxx_default_intr_handler }, - { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, - "qla4xxx (rsp_q)", (irq_handler_t)qla4_8xxx_msix_rsp_q }, -}; - -void -qla4_8xxx_disable_msix(struct scsi_qla_host *ha) -{ - int i; - struct ql4_msix_entry *qentry; - - for (i = 0; i < QLA_MSIX_ENTRIES; i++) { - qentry = &ha->msix_entries[qla4_8xxx_msix_entries[i].index]; - if (qentry->have_irq) { - free_irq(qentry->msix_vector, ha); - DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %s\n", - __func__, qla4_8xxx_msix_entries[i].name)); - } - } - pci_disable_msix(ha->pdev); - clear_bit(AF_MSIX_ENABLED, &ha->flags); -} - int qla4_8xxx_enable_msix(struct scsi_qla_host *ha) { - int i, ret; - struct msix_entry entries[QLA_MSIX_ENTRIES]; - struct ql4_msix_entry *qentry; + int ret; - for (i = 0; i < QLA_MSIX_ENTRIES; i++) - entries[i].entry = qla4_8xxx_msix_entries[i].entry; - - ret = pci_enable_msix_exact(ha->pdev, entries, ARRAY_SIZE(entries)); - if (ret) { + ret = pci_alloc_irq_vectors(ha->pdev, QLA_MSIX_ENTRIES, + QLA_MSIX_ENTRIES, PCI_IRQ_MSIX); + if (ret < 0) { ql4_printk(KERN_WARNING, ha, "MSI-X: Failed to enable support -- %d/%d\n", QLA_MSIX_ENTRIES, ret); - goto msix_out; + return ret; } - set_bit(AF_MSIX_ENABLED, &ha->flags); - for (i = 0; i < QLA_MSIX_ENTRIES; i++) { - qentry = &ha->msix_entries[qla4_8xxx_msix_entries[i].index]; - qentry->msix_vector = entries[i].vector; - qentry->msix_entry = entries[i].entry; - qentry->have_irq = 0; - ret = request_irq(qentry->msix_vector, - qla4_8xxx_msix_entries[i].handler, 0, - qla4_8xxx_msix_entries[i].name, ha); - if (ret) { - ql4_printk(KERN_WARNING, ha, - "MSI-X: Unable to register handler -- %x/%d.\n", - qla4_8xxx_msix_entries[i].index, ret); - qla4_8xxx_disable_msix(ha); - goto msix_out; - } - qentry->have_irq = 1; - DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %s\n", - __func__, qla4_8xxx_msix_entries[i].name)); - } -msix_out: + ret = request_irq(pci_irq_vector(ha->pdev, 0), + qla4_8xxx_default_intr_handler, 0, "qla4xxx (default)", + ha); + if (ret) + goto out_free_vectors; + + ret = request_irq(pci_irq_vector(ha->pdev, 1), + qla4_8xxx_msix_rsp_q, 0, "qla4xxx (rsp_q)", ha); + if (ret) + goto out_free_default_irq; + + return 0; + +out_free_default_irq: + free_irq(pci_irq_vector(ha->pdev, 0), ha); +out_free_vectors: + pci_free_irq_vectors(ha->pdev); return ret; }