summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:12 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:12 +0000
commit8665bd53f2f2e27e5511d90428cb3f60e6d0ce15 (patch)
tree8d58900dc0ebd4a3011f92c128d2fe45bc7c4bf2 /drivers/scsi
parentAdding debian version 6.7.12-1. (diff)
downloadlinux-8665bd53f2f2e27e5511d90428cb3f60e6d0ce15.tar.xz
linux-8665bd53f2f2e27e5511d90428cb3f60e6d0ce15.zip
Merging upstream version 6.8.9.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-sas.c3
-rw-r--r--drivers/scsi/a3000.c5
-rw-r--r--drivers/scsi/a4000t.c5
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c6
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c3
-rw-r--r--drivers/scsi/arcmsr/arcmsr.h25
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c90
-rw-r--r--drivers/scsi/atari_scsi.c5
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c14
-rw-r--r--drivers/scsi/bvme6000_scsi.c6
-rw-r--r--drivers/scsi/ch.c12
-rw-r--r--drivers/scsi/csiostor/csio_init.c3
-rw-r--r--drivers/scsi/dc395x.c2
-rw-r--r--drivers/scsi/elx/libefc/efc_node.h12
-rw-r--r--drivers/scsi/fcoe/fcoe_sysfs.c28
-rw-r--r--drivers/scsi/fnic/fnic.h71
-rw-r--r--drivers/scsi/fnic/fnic_fcs.c68
-rw-r--r--drivers/scsi/fnic/fnic_isr.c168
-rw-r--r--drivers/scsi/fnic/fnic_main.c145
-rw-r--r--drivers/scsi/fnic/fnic_res.c48
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c873
-rw-r--r--drivers/scsi/fnic/fnic_stats.h3
-rw-r--r--drivers/scsi/fnic/fnic_trace.c11
-rw-r--r--drivers/scsi/fnic/vnic_dev.c4
-rw-r--r--drivers/scsi/fnic/vnic_scsi.h13
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c12
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/initio.c3
-rw-r--r--drivers/scsi/ipr.c55
-rw-r--r--drivers/scsi/isci/request.c5
-rw-r--r--drivers/scsi/isci/request.h2
-rw-r--r--drivers/scsi/isci/task.c4
-rw-r--r--drivers/scsi/jazz_esp.c6
-rw-r--r--drivers/scsi/libfc/fc_fcp.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c12
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c49
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c47
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c22
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h10
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/mac_esp.c6
-rw-r--r--drivers/scsi/mac_scsi.c5
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_ioc.h1
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr.h33
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_app.c520
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c117
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c1
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_transport.c21
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h231
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_image.h32
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_ioc.h27
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c35
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h3
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_config.c6
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c42
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c56
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_transport.c9
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h44
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_warpdrive.c3
-rw-r--r--drivers/scsi/mvme16x_scsi.c6
-rw-r--r--drivers/scsi/myrb.c20
-rw-r--r--drivers/scsi/myrs.c24
-rw-r--r--drivers/scsi/qla2xxx/qla_edif.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/qlogicpti.c6
-rw-r--r--drivers/scsi/scsi_debug.c27
-rw-r--r--drivers/scsi/scsi_error.c1
-rw-r--r--drivers/scsi/scsi_lib.c7
-rw-r--r--drivers/scsi/sd.c51
-rw-r--r--drivers/scsi/sd_zbc.c16
-rw-r--r--drivers/scsi/sg.c20
-rw-r--r--drivers/scsi/sgiwd93.c5
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c6
-rw-r--r--drivers/scsi/sni_53c710.c6
-rw-r--r--drivers/scsi/sun3_scsi.c5
-rw-r--r--drivers/scsi/sun3x_esp.c6
-rw-r--r--drivers/scsi/sun_esp.c6
-rw-r--r--drivers/scsi/virtio_scsi.c80
83 files changed, 2045 insertions, 1319 deletions
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 55989eaa2d..9bdb75dfdc 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -1326,7 +1326,8 @@ static int twl_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
}
/* Load rest of compatibility struct */
- strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
+ strscpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION,
+ sizeof(tw_dev->tw_compat_info.driver_version));
tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index c3028726bb..378906f779 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -282,7 +282,7 @@ fail_alloc:
return error;
}
-static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
+static void __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
{
struct Scsi_Host *instance = platform_get_drvdata(pdev);
struct a3000_hostdata *hdata = shost_priv(instance);
@@ -293,11 +293,10 @@ static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
free_irq(IRQ_AMIGA_PORTS, instance);
scsi_host_put(instance);
release_mem_region(res->start, resource_size(res));
- return 0;
}
static struct platform_driver amiga_a3000_scsi_driver = {
- .remove = __exit_p(amiga_a3000_scsi_remove),
+ .remove_new = __exit_p(amiga_a3000_scsi_remove),
.driver = {
.name = "amiga-a3000-scsi",
},
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index 5e575afce1..e435fc06a6 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -95,7 +95,7 @@ static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
return -ENODEV;
}
-static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
+static void __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
{
struct Scsi_Host *host = platform_get_drvdata(pdev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
@@ -106,11 +106,10 @@ static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
kfree(hostdata);
free_irq(host->irq, host);
release_mem_region(res->start, resource_size(res));
- return 0;
}
static struct platform_driver amiga_a4000t_scsi_driver = {
- .remove = __exit_p(amiga_a4000t_scsi_remove),
+ .remove_new = __exit_p(amiga_a4000t_scsi_remove),
.driver = {
.name = "amiga-a4000t-scsi",
},
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index bdd177e3d7..a19cdd87c4 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -87,17 +87,17 @@ aic7770_probe(struct device *dev)
sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
name = kstrdup(buf, GFP_ATOMIC);
if (name == NULL)
- return (ENOMEM);
+ return -ENOMEM;
ahc = ahc_alloc(&aic7xxx_driver_template, name);
if (ahc == NULL)
- return (ENOMEM);
+ return -ENOMEM;
ahc->dev = dev;
error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data,
eisaBase);
if (error != 0) {
ahc->bsh.ioport = 0;
ahc_free(ahc);
- return (error);
+ return error < 0 ? error : -error;
}
dev_set_drvdata(dev, ahc);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 4ae0a1c4d3..b0c4f23453 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1085,7 +1085,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
template->name = ahc->description;
host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
if (host == NULL)
- return (ENOMEM);
+ return -ENOMEM;
*((struct ahc_softc **)host->hostdata) = ahc;
ahc->platform_data->host = host;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index a07e94fac6..198440dc09 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -241,8 +241,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc_linux_pci_inherit_flags(ahc);
pci_set_drvdata(pdev, ahc);
- ahc_linux_register_host(ahc, &aic7xxx_driver_template);
- return (0);
+ return ahc_linux_register_host(ahc, &aic7xxx_driver_template);
}
/******************************* PCI Routines *********************************/
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index 3819d559eb..12c4148fe1 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -50,7 +50,7 @@ struct device_attribute;
#define ARCMSR_MAX_OUTSTANDING_CMD 1024
#define ARCMSR_DEFAULT_OUTSTANDING_CMD 128
#define ARCMSR_MIN_OUTSTANDING_CMD 32
-#define ARCMSR_DRIVER_VERSION "v1.50.00.13-20230206"
+#define ARCMSR_DRIVER_VERSION "v1.51.00.14-20230915"
#define ARCMSR_SCSI_INITIATOR_ID 255
#define ARCMSR_MAX_XFER_SECTORS 512
#define ARCMSR_MAX_XFER_SECTORS_B 4096
@@ -822,6 +822,23 @@ typedef struct deliver_completeQ {
uint16_t cmdLMID; // reserved (0)
uint16_t cmdFlag2; // reserved (0)
} DeliverQ, CompletionQ, *pDeliver_Q, *pCompletion_Q;
+
+#define ARCMSR_XOR_SEG_SIZE (1024 * 1024)
+struct HostRamBuf {
+ uint32_t hrbSignature; // must be "HRBS"
+ uint32_t hrbSize; // total sg size, be multiples of MB
+ uint32_t hrbRes[2]; // reserved, must be set to 0
+};
+struct Xor_sg {
+ dma_addr_t xorPhys;
+ uint64_t xorBufLen;
+};
+struct XorHandle {
+ dma_addr_t xorPhys;
+ uint64_t xorBufLen;
+ void *xorVirt;
+};
+
/*
*******************************************************************************
** Adapter Control Block
@@ -933,6 +950,7 @@ struct AdapterControlBlock
char firm_model[12];
char firm_version[20];
char device_map[20]; /*21,84-99*/
+ uint32_t firm_PicStatus;
struct work_struct arcmsr_do_message_isr_bh;
struct timer_list eternal_timer;
unsigned short fw_flag;
@@ -941,6 +959,7 @@ struct AdapterControlBlock
#define FW_DEADLOCK 0x0010
uint32_t maxOutstanding;
int vector_count;
+ int xor_mega;
uint32_t maxFreeCCB;
struct timer_list refresh_timer;
uint32_t doneq_index;
@@ -950,6 +969,10 @@ struct AdapterControlBlock
uint32_t completionQ_entry;
pCompletion_Q pCompletionQ;
uint32_t completeQ_size;
+ void *xorVirt;
+ dma_addr_t xorPhys;
+ unsigned int init2cfg_size;
+ unsigned int xorVirtOffset;
};/* HW_DEVICE_EXTENSION */
/*
*******************************************************************************
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 01fb1396e1..ad227e6cb1 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -751,6 +751,57 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
return rtn;
}
+static int arcmsr_alloc_xor_buffer(struct AdapterControlBlock *acb)
+{
+ int rc = 0;
+ struct pci_dev *pdev = acb->pdev;
+ void *dma_coherent;
+ dma_addr_t dma_coherent_handle;
+ int i, xor_ram;
+ struct Xor_sg *pXorPhys;
+ void **pXorVirt;
+ struct HostRamBuf *pRamBuf;
+
+ // allocate 1 MB * N physically continuous memory for XOR engine.
+ xor_ram = (acb->firm_PicStatus >> 24) & 0x0f;
+ acb->xor_mega = (xor_ram - 1) * 32 + 128 + 3;
+ acb->init2cfg_size = sizeof(struct HostRamBuf) +
+ (sizeof(struct XorHandle) * acb->xor_mega);
+ dma_coherent = dma_alloc_coherent(&pdev->dev, acb->init2cfg_size,
+ &dma_coherent_handle, GFP_KERNEL);
+ acb->xorVirt = dma_coherent;
+ acb->xorPhys = dma_coherent_handle;
+ pXorPhys = (struct Xor_sg *)((unsigned long)dma_coherent +
+ sizeof(struct HostRamBuf));
+ acb->xorVirtOffset = sizeof(struct HostRamBuf) +
+ (sizeof(struct Xor_sg) * acb->xor_mega);
+ pXorVirt = (void **)((unsigned long)dma_coherent +
+ (unsigned long)acb->xorVirtOffset);
+ for (i = 0; i < acb->xor_mega; i++) {
+ dma_coherent = dma_alloc_coherent(&pdev->dev,
+ ARCMSR_XOR_SEG_SIZE,
+ &dma_coherent_handle, GFP_KERNEL);
+ if (dma_coherent) {
+ pXorPhys->xorPhys = dma_coherent_handle;
+ pXorPhys->xorBufLen = ARCMSR_XOR_SEG_SIZE;
+ *pXorVirt = dma_coherent;
+ pXorPhys++;
+ pXorVirt++;
+ } else {
+ pr_info("arcmsr%d: alloc max XOR buffer = 0x%x MB\n",
+ acb->host->host_no, i);
+ rc = -ENOMEM;
+ break;
+ }
+ }
+ pRamBuf = (struct HostRamBuf *)acb->xorVirt;
+ pRamBuf->hrbSignature = 0x53425248; //HRBS
+ pRamBuf->hrbSize = i * ARCMSR_XOR_SEG_SIZE;
+ pRamBuf->hrbRes[0] = 0;
+ pRamBuf->hrbRes[1] = 0;
+ return rc;
+}
+
static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
{
struct pci_dev *pdev = acb->pdev;
@@ -840,7 +891,11 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
acb->completionQ_entry = acb->ioqueue_size / sizeof(struct deliver_completeQ);
acb->doneq_index = 0;
break;
- }
+ }
+ if ((acb->firm_PicStatus >> 24) & 0x0f) {
+ if (arcmsr_alloc_xor_buffer(acb))
+ return -ENOMEM;
+ }
return 0;
}
@@ -2026,6 +2081,29 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
{
+ if (acb->xor_mega) {
+ struct Xor_sg *pXorPhys;
+ void **pXorVirt;
+ int i;
+
+ pXorPhys = (struct Xor_sg *)(acb->xorVirt +
+ sizeof(struct HostRamBuf));
+ pXorVirt = (void **)((unsigned long)acb->xorVirt +
+ (unsigned long)acb->xorVirtOffset);
+ for (i = 0; i < acb->xor_mega; i++) {
+ if (pXorPhys->xorPhys) {
+ dma_free_coherent(&acb->pdev->dev,
+ ARCMSR_XOR_SEG_SIZE,
+ *pXorVirt, pXorPhys->xorPhys);
+ pXorPhys->xorPhys = 0;
+ *pXorVirt = NULL;
+ }
+ pXorPhys++;
+ pXorVirt++;
+ }
+ dma_free_coherent(&acb->pdev->dev, acb->init2cfg_size,
+ acb->xorVirt, acb->xorPhys);
+ }
dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle);
}
@@ -3313,6 +3391,10 @@ static void arcmsr_get_adapter_config(struct AdapterControlBlock *pACB, uint32_t
pACB->firm_sdram_size = readl(&rwbuffer[3]);
pACB->firm_hd_channels = readl(&rwbuffer[4]);
pACB->firm_cfg_version = readl(&rwbuffer[25]);
+ if (pACB->adapter_type == ACB_ADAPTER_TYPE_F)
+ pACB->firm_PicStatus = readl(&rwbuffer[30]);
+ else
+ pACB->firm_PicStatus = 0;
pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
pACB->host->host_no,
pACB->firm_model,
@@ -4100,6 +4182,12 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
acb->msgcode_rwbuffer[5] = lower_32_bits(acb->dma_coherent_handle2);
acb->msgcode_rwbuffer[6] = upper_32_bits(acb->dma_coherent_handle2);
acb->msgcode_rwbuffer[7] = acb->completeQ_size;
+ if (acb->xor_mega) {
+ acb->msgcode_rwbuffer[8] = 0x455AA; //Linux init 2
+ acb->msgcode_rwbuffer[9] = 0;
+ acb->msgcode_rwbuffer[10] = lower_32_bits(acb->xorPhys);
+ acb->msgcode_rwbuffer[11] = upper_32_bits(acb->xorPhys);
+ }
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, &reg->inbound_msgaddr0);
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
writel(acb->out_doorbell, &reg->iobound_doorbell);
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index d401cf2711..d99e709148 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -865,7 +865,7 @@ fail_alloc:
return error;
}
-static int __exit atari_scsi_remove(struct platform_device *pdev)
+static void __exit atari_scsi_remove(struct platform_device *pdev)
{
struct Scsi_Host *instance = platform_get_drvdata(pdev);
@@ -876,11 +876,10 @@ static int __exit atari_scsi_remove(struct platform_device *pdev)
scsi_host_put(instance);
if (atari_dma_buffer)
atari_stram_free(atari_dma_buffer);
- return 0;
}
static struct platform_driver atari_scsi_driver = {
- .remove = __exit_p(atari_scsi_remove),
+ .remove_new = __exit_p(atari_scsi_remove),
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 451a58e0fd..1078c20c5e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -1734,32 +1734,32 @@ static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
switch (pdev->device) {
case PCI_DEVICE_ID_NX2_57710:
- strncpy(hba->chip_num, "BCM57710", BCM_CHIP_LEN);
+ strscpy(hba->chip_num, "BCM57710", sizeof(hba->chip_num));
break;
case PCI_DEVICE_ID_NX2_57711:
- strncpy(hba->chip_num, "BCM57711", BCM_CHIP_LEN);
+ strscpy(hba->chip_num, "BCM57711", sizeof(hba->chip_num));
break;
case PCI_DEVICE_ID_NX2_57712:
case PCI_DEVICE_ID_NX2_57712_MF:
case PCI_DEVICE_ID_NX2_57712_VF:
- strncpy(hba->chip_num, "BCM57712", BCM_CHIP_LEN);
+ strscpy(hba->chip_num, "BCM57712", sizeof(hba->chip_num));
break;
case PCI_DEVICE_ID_NX2_57800:
case PCI_DEVICE_ID_NX2_57800_MF:
case PCI_DEVICE_ID_NX2_57800_VF:
- strncpy(hba->chip_num, "BCM57800", BCM_CHIP_LEN);
+ strscpy(hba->chip_num, "BCM57800", sizeof(hba->chip_num));
break;
case PCI_DEVICE_ID_NX2_57810:
case PCI_DEVICE_ID_NX2_57810_MF:
case PCI_DEVICE_ID_NX2_57810_VF:
- strncpy(hba->chip_num, "BCM57810", BCM_CHIP_LEN);
+ strscpy(hba->chip_num, "BCM57810", sizeof(hba->chip_num));
break;
case PCI_DEVICE_ID_NX2_57840:
case PCI_DEVICE_ID_NX2_57840_MF:
case PCI_DEVICE_ID_NX2_57840_VF:
case PCI_DEVICE_ID_NX2_57840_2_20:
case PCI_DEVICE_ID_NX2_57840_4_10:
- strncpy(hba->chip_num, "BCM57840", BCM_CHIP_LEN);
+ strscpy(hba->chip_num, "BCM57840", sizeof(hba->chip_num));
break;
default:
pr_err(PFX "Unknown device id 0x%x\n", pdev->device);
@@ -1797,7 +1797,7 @@ static int bnx2fc_ulp_get_stats(void *handle)
if (!stats_addr)
return -EINVAL;
- strncpy(stats_addr->version, BNX2FC_VERSION,
+ strscpy(stats_addr->version, BNX2FC_VERSION,
sizeof(stats_addr->version));
stats_addr->txq_size = BNX2FC_SQ_WQES_MAX;
stats_addr->rxq_size = BNX2FC_CQ_WQES_MAX;
diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c
index 8d72b25535..f893e9779e 100644
--- a/drivers/scsi/bvme6000_scsi.c
+++ b/drivers/scsi/bvme6000_scsi.c
@@ -89,7 +89,7 @@ bvme6000_probe(struct platform_device *dev)
return -ENODEV;
}
-static int
+static void
bvme6000_device_remove(struct platform_device *dev)
{
struct Scsi_Host *host = platform_get_drvdata(dev);
@@ -99,8 +99,6 @@ bvme6000_device_remove(struct platform_device *dev)
NCR_700_release(host);
kfree(hostdata);
free_irq(host->irq, host);
-
- return 0;
}
static struct platform_driver bvme6000_scsi_driver = {
@@ -108,7 +106,7 @@ static struct platform_driver bvme6000_scsi_driver = {
.name = "bvme6000-scsi",
},
.probe = bvme6000_probe,
- .remove = bvme6000_device_remove,
+ .remove_new = bvme6000_device_remove,
};
static int __init bvme6000_scsi_init(void)
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index cb0a399be1..2b864061e0 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -659,19 +659,23 @@ static long ch_ioctl(struct file *file,
memset(&vparams,0,sizeof(vparams));
if (ch->counts[CHET_V1]) {
vparams.cvp_n1 = ch->counts[CHET_V1];
- strncpy(vparams.cvp_label1,vendor_labels[0],16);
+ strscpy(vparams.cvp_label1, vendor_labels[0],
+ sizeof(vparams.cvp_label1));
}
if (ch->counts[CHET_V2]) {
vparams.cvp_n2 = ch->counts[CHET_V2];
- strncpy(vparams.cvp_label2,vendor_labels[1],16);
+ strscpy(vparams.cvp_label2, vendor_labels[1],
+ sizeof(vparams.cvp_label2));
}
if (ch->counts[CHET_V3]) {
vparams.cvp_n3 = ch->counts[CHET_V3];
- strncpy(vparams.cvp_label3,vendor_labels[2],16);
+ strscpy(vparams.cvp_label3, vendor_labels[2],
+ sizeof(vparams.cvp_label3));
}
if (ch->counts[CHET_V4]) {
vparams.cvp_n4 = ch->counts[CHET_V4];
- strncpy(vparams.cvp_label4,vendor_labels[3],16);
+ strscpy(vparams.cvp_label4, vendor_labels[3],
+ sizeof(vparams.cvp_label4));
}
if (copy_to_user(argp, &vparams, sizeof(vparams)))
return -EFAULT;
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
index 0c32faefad..d649b7a2a8 100644
--- a/drivers/scsi/csiostor/csio_init.c
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -521,7 +521,8 @@ static struct csio_hw *csio_hw_alloc(struct pci_dev *pdev)
goto err;
hw->pdev = pdev;
- strncpy(hw->drv_version, CSIO_DRV_VERSION, 32);
+ strscpy(hw->drv_version, CSIO_DRV_VERSION,
+ sizeof(hw->drv_version));
/* memory pool/DMA pool allocation */
if (csio_resource_alloc(hw))
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index c8e86f8a63..d108a86e19 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1366,7 +1366,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
"command while another command (0x%p) is active.",
srb->cmd,
acb->active_dcb->active_srb ?
- acb->active_dcb->active_srb->cmd : 0);
+ acb->active_dcb->active_srb->cmd : NULL);
return 1;
}
if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) {
diff --git a/drivers/scsi/elx/libefc/efc_node.h b/drivers/scsi/elx/libefc/efc_node.h
index e9c600ac45..e57579988b 100644
--- a/drivers/scsi/elx/libefc/efc_node.h
+++ b/drivers/scsi/elx/libefc/efc_node.h
@@ -26,13 +26,13 @@ efc_node_evt_set(struct efc_sm_ctx *ctx, enum efc_sm_event evt,
struct efc_node *node = ctx->app;
if (evt == EFC_EVT_ENTER) {
- strncpy(node->current_state_name, handler,
- sizeof(node->current_state_name));
+ strscpy_pad(node->current_state_name, handler,
+ sizeof(node->current_state_name));
} else if (evt == EFC_EVT_EXIT) {
- strncpy(node->prev_state_name, node->current_state_name,
- sizeof(node->prev_state_name));
- strncpy(node->current_state_name, "invalid",
- sizeof(node->current_state_name));
+ memcpy(node->prev_state_name, node->current_state_name,
+ sizeof(node->prev_state_name));
+ strscpy_pad(node->current_state_name, "invalid",
+ sizeof(node->current_state_name));
}
node->prev_evt = node->current_evt;
node->current_evt = evt;
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index e17957f808..c64a085a7e 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/ctype.h>
+#include <linux/string.h>
#include <scsi/fcoe_sysfs.h>
#include <scsi/libfcoe.h>
@@ -214,25 +215,13 @@ static const char *get_fcoe_##title##_name(enum table_type table_key) \
return table[table_key]; \
}
-static char *fip_conn_type_names[] = {
+static const char * const fip_conn_type_names[] = {
[ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
[ FIP_CONN_TYPE_FABRIC ] = "Fabric",
[ FIP_CONN_TYPE_VN2VN ] = "VN2VN",
};
fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
-static enum fip_conn_type fcoe_parse_mode(const char *buf)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(fip_conn_type_names); i++) {
- if (strcasecmp(buf, fip_conn_type_names[i]) == 0)
- return i;
- }
-
- return FIP_CONN_TYPE_UNKNOWN;
-}
-
static char *fcf_state_names[] = {
[ FCOE_FCF_STATE_UNKNOWN ] = "Unknown",
[ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
@@ -274,17 +263,11 @@ static ssize_t store_ctlr_mode(struct device *dev,
const char *buf, size_t count)
{
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
- char mode[FCOE_MAX_MODENAME_LEN + 1];
+ int res;
if (count > FCOE_MAX_MODENAME_LEN)
return -EINVAL;
- strncpy(mode, buf, count);
-
- if (mode[count - 1] == '\n')
- mode[count - 1] = '\0';
- else
- mode[count] = '\0';
switch (ctlr->enabled) {
case FCOE_CTLR_ENABLED:
@@ -297,12 +280,13 @@ static ssize_t store_ctlr_mode(struct device *dev,
return -ENOTSUPP;
}
- ctlr->mode = fcoe_parse_mode(mode);
- if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
+ res = sysfs_match_string(fip_conn_type_names, buf);
+ if (res < 0 || res == FIP_CONN_TYPE_UNKNOWN) {
LIBFCOE_SYSFS_DBG(ctlr, "Unknown mode %s provided.\n",
buf);
return -EINVAL;
}
+ ctlr->mode = res;
ctlr->f->set_fcoe_ctlr_mode(ctlr);
LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.\n", buf);
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 22cef283b2..ce73f08ee8 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -27,7 +27,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.6.0.57"
+#define DRV_VERSION "1.7.0.0"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
@@ -36,7 +36,6 @@
#define FNIC_MIN_IO_REQ 256 /* Min IO throttle count */
#define FNIC_MAX_IO_REQ 1024 /* scsi_cmnd tag map entries */
#define FNIC_DFLT_IO_REQ 256 /* Default scsi_cmnd tag map entries */
-#define FNIC_IO_LOCKS 64 /* IO locks: power of 2 */
#define FNIC_DFLT_QUEUE_DEPTH 256
#define FNIC_STATS_RATE_LIMIT 4 /* limit rate at which stats are pulled up */
@@ -109,7 +108,7 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)
#define FNIC_ABT_TERM_DELAY_TIMEOUT 500 /* mSec */
#define FNIC_MAX_FCP_TARGET 256
-
+#define FNIC_PCI_OFFSET 2
/**
* state_flags to identify host state along along with fnic's state
**/
@@ -144,31 +143,48 @@ do { \
} while (0); \
} while (0)
-#define FNIC_MAIN_DBG(kern_level, host, fmt, args...) \
+#define FNIC_MAIN_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_MAIN_LOGGING, \
- shost_printk(kern_level, host, fmt, ##args);)
+ shost_printk(kern_level, host, \
+ "fnic<%d>: %s: %d: " fmt, fnic_num,\
+ __func__, __LINE__, ##args);)
-#define FNIC_FCS_DBG(kern_level, host, fmt, args...) \
+#define FNIC_FCS_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
- shost_printk(kern_level, host, fmt, ##args);)
+ shost_printk(kern_level, host, \
+ "fnic<%d>: %s: %d: " fmt, fnic_num,\
+ __func__, __LINE__, ##args);)
-#define FNIC_SCSI_DBG(kern_level, host, fmt, args...) \
+#define FNIC_SCSI_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
- shost_printk(kern_level, host, fmt, ##args);)
+ shost_printk(kern_level, host, \
+ "fnic<%d>: %s: %d: " fmt, fnic_num,\
+ __func__, __LINE__, ##args);)
-#define FNIC_ISR_DBG(kern_level, host, fmt, args...) \
+#define FNIC_ISR_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_ISR_LOGGING, \
- shost_printk(kern_level, host, fmt, ##args);)
+ shost_printk(kern_level, host, \
+ "fnic<%d>: %s: %d: " fmt, fnic_num,\
+ __func__, __LINE__, ##args);)
#define FNIC_MAIN_NOTE(kern_level, host, fmt, args...) \
shost_printk(kern_level, host, fmt, ##args)
+#define FNIC_WQ_COPY_MAX 64
+#define FNIC_WQ_MAX 1
+#define FNIC_RQ_MAX 1
+#define FNIC_CQ_MAX (FNIC_WQ_COPY_MAX + FNIC_WQ_MAX + FNIC_RQ_MAX)
+#define FNIC_DFLT_IO_COMPLETIONS 256
+
+#define FNIC_MQ_CQ_INDEX 2
+
extern const char *fnic_state_str[];
enum fnic_intx_intr_index {
FNIC_INTX_WQ_RQ_COPYWQ,
- FNIC_INTX_ERR,
+ FNIC_INTX_DUMMY,
FNIC_INTX_NOTIFY,
+ FNIC_INTX_ERR,
FNIC_INTX_INTR_MAX,
};
@@ -176,7 +192,7 @@ enum fnic_msix_intr_index {
FNIC_MSIX_RQ,
FNIC_MSIX_WQ,
FNIC_MSIX_WQ_COPY,
- FNIC_MSIX_ERR_NOTIFY,
+ FNIC_MSIX_ERR_NOTIFY = FNIC_MSIX_WQ_COPY + FNIC_WQ_COPY_MAX,
FNIC_MSIX_INTR_MAX,
};
@@ -185,6 +201,7 @@ struct fnic_msix_entry {
char devname[IFNAMSIZ + 11];
irqreturn_t (*isr)(int, void *);
void *devid;
+ int irq_num;
};
enum fnic_state {
@@ -194,12 +211,6 @@ enum fnic_state {
FNIC_IN_ETH_TRANS_FC_MODE,
};
-#define FNIC_WQ_COPY_MAX 1
-#define FNIC_WQ_MAX 1
-#define FNIC_RQ_MAX 1
-#define FNIC_CQ_MAX (FNIC_WQ_COPY_MAX + FNIC_WQ_MAX + FNIC_RQ_MAX)
-#define FNIC_DFLT_IO_COMPLETIONS 256
-
struct mempool;
enum fnic_evt {
@@ -214,8 +225,16 @@ struct fnic_event {
enum fnic_evt event;
};
+struct fnic_cpy_wq {
+ unsigned long hw_lock_flags;
+ u16 active_ioreq_count;
+ u16 ioreq_table_size;
+ ____cacheline_aligned struct fnic_io_req **io_req_table;
+};
+
/* Per-instance private data structure */
struct fnic {
+ int fnic_num;
struct fc_lport *lport;
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
struct vnic_dev_bar bar0;
@@ -282,10 +301,11 @@ struct fnic {
struct fnic_host_tag *tags;
mempool_t *io_req_pool;
mempool_t *io_sgl_pool[FNIC_SGL_NUM_CACHES];
- spinlock_t io_req_lock[FNIC_IO_LOCKS]; /* locks for scsi cmnds */
+ unsigned int copy_wq_base;
struct work_struct link_work;
struct work_struct frame_work;
+ struct work_struct flush_work;
struct sk_buff_head frame_queue;
struct sk_buff_head tx_queue;
@@ -302,7 +322,9 @@ struct fnic {
/*** FIP related data members -- end ***/
/* copy work queue cache line section */
- ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX];
+ ____cacheline_aligned struct vnic_wq_copy hw_copy_wq[FNIC_WQ_COPY_MAX];
+ ____cacheline_aligned struct fnic_cpy_wq sw_copy_wq[FNIC_WQ_COPY_MAX];
+
/* completion queue cache line section */
____cacheline_aligned struct vnic_cq cq[FNIC_CQ_MAX];
@@ -330,6 +352,7 @@ extern const struct attribute_group *fnic_host_groups[];
void fnic_clear_intr_mode(struct fnic *fnic);
int fnic_set_intr_mode(struct fnic *fnic);
+int fnic_set_intr_mode_msix(struct fnic *fnic);
void fnic_free_intr(struct fnic *fnic);
int fnic_request_intr(struct fnic *fnic);
@@ -341,7 +364,7 @@ void fnic_handle_event(struct work_struct *work);
int fnic_rq_cmpl_handler(struct fnic *fnic, int);
int fnic_alloc_rq_frame(struct vnic_rq *rq);
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
-void fnic_flush_tx(struct fnic *);
+void fnic_flush_tx(struct work_struct *work);
void fnic_eth_send(struct fcoe_ctlr *, struct sk_buff *skb);
void fnic_set_port_id(struct fc_lport *, u32, struct fc_frame *);
void fnic_update_mac(struct fc_lport *, u8 *new);
@@ -356,7 +379,7 @@ void fnic_scsi_cleanup(struct fc_lport *);
void fnic_scsi_abort_io(struct fc_lport *);
void fnic_empty_scsi_cleanup(struct fc_lport *);
void fnic_exch_mgr_reset(struct fc_lport *, u32, u32);
-int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int);
+int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned int cq_index);
int fnic_wq_cmpl_handler(struct fnic *fnic, int);
int fnic_flogi_reg_handler(struct fnic *fnic, u32);
void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
@@ -364,7 +387,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
int fnic_fw_reset_handler(struct fnic *fnic);
void fnic_terminate_rport_io(struct fc_rport *);
const char *fnic_state_to_str(unsigned int state);
-
+void fnic_mq_map_queues_cpus(struct Scsi_Host *host);
void fnic_log_q_error(struct fnic *fnic);
void fnic_handle_link_event(struct fnic *fnic);
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 55632c67a8..a08293b2ad 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -63,8 +63,8 @@ void fnic_handle_link(struct work_struct *work)
atomic64_set(&fnic->fnic_stats.misc_stats.current_port_speed,
new_port_speed);
if (old_port_speed != new_port_speed)
- FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host,
- "Current vnic speed set to : %llu\n",
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Current vnic speed set to: %llu\n",
new_port_speed);
switch (vnic_dev_port_speed(fnic->vdev)) {
@@ -102,6 +102,8 @@ void fnic_handle_link(struct work_struct *work)
fnic_fc_trace_set_data(fnic->lport->host->host_no,
FNIC_FC_LE, "Link Status: DOWN->DOWN",
strlen("Link Status: DOWN->DOWN"));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "down->down\n");
} else {
if (old_link_down_cnt != fnic->link_down_cnt) {
/* UP -> DOWN -> UP */
@@ -113,7 +115,7 @@ void fnic_handle_link(struct work_struct *work)
"Link Status:UP_DOWN_UP",
strlen("Link_Status:UP_DOWN_UP")
);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"link down\n");
fcoe_ctlr_link_down(&fnic->ctlr);
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
@@ -128,8 +130,8 @@ void fnic_handle_link(struct work_struct *work)
fnic_fcoe_send_vlan_req(fnic);
return;
}
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
- "link up\n");
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "up->down->up: Link up\n");
fcoe_ctlr_link_up(&fnic->ctlr);
} else {
/* UP -> UP */
@@ -138,6 +140,8 @@ void fnic_handle_link(struct work_struct *work)
fnic->lport->host->host_no, FNIC_FC_LE,
"Link Status: UP_UP",
strlen("Link Status: UP_UP"));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "up->up\n");
}
}
} else if (fnic->link_status) {
@@ -153,7 +157,8 @@ void fnic_handle_link(struct work_struct *work)
return;
}
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n");
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "down->up: Link up\n");
fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_LE,
"Link Status: DOWN_UP", strlen("Link Status: DOWN_UP"));
fcoe_ctlr_link_up(&fnic->ctlr);
@@ -161,13 +166,14 @@ void fnic_handle_link(struct work_struct *work)
/* UP -> DOWN */
fnic->lport->host_stats.link_failure_count++;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link down\n");
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "up->down: Link down\n");
fnic_fc_trace_set_data(
fnic->lport->host->host_no, FNIC_FC_LE,
"Link Status: UP_DOWN",
strlen("Link Status: UP_DOWN"));
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"deleting fip-timer during link-down\n");
del_timer_sync(&fnic->fip_timer);
}
@@ -270,12 +276,12 @@ void fnic_handle_event(struct work_struct *work)
spin_lock_irqsave(&fnic->fnic_lock, flags);
break;
case FNIC_EVT_START_FCF_DISC:
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Start FCF Discovery\n");
fnic_fcoe_start_fcf_disc(fnic);
break;
default:
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Unknown event 0x%x\n", fevt->event);
break;
}
@@ -370,7 +376,7 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
fnic->set_vlan(fnic, 0);
if (printk_ratelimit())
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Sending VLAN request...\n");
skb = dev_alloc_skb(sizeof(struct fip_vlan));
@@ -423,12 +429,12 @@ static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
u64 sol_time;
unsigned long flags;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Received VLAN response...\n");
fiph = (struct fip_header *) skb->data;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Received VLAN response... OP 0x%x SUB_OP 0x%x\n",
ntohs(fiph->fip_op), fiph->fip_subcode);
@@ -463,7 +469,7 @@ static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
if (list_empty(&fnic->vlans)) {
/* retry from timer */
atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"No VLAN descriptors in FIP VLAN response\n");
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
goto out;
@@ -721,7 +727,8 @@ void fnic_update_mac_locked(struct fnic *fnic, u8 *new)
new = ctl;
if (ether_addr_equal(data, new))
return;
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "update_mac %pM\n", new);
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "update_mac %pM\n", new);
if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl))
vnic_dev_del_addr(fnic->vdev, data);
memcpy(data, new, ETH_ALEN);
@@ -763,8 +770,9 @@ void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp)
u8 *mac;
int ret;
- FNIC_FCS_DBG(KERN_DEBUG, lport->host, "set port_id %x fp %p\n",
- port_id, fp);
+ FNIC_FCS_DBG(KERN_DEBUG, lport->host, fnic->fnic_num,
+ "set port_id 0x%x fp 0x%p\n",
+ port_id, fp);
/*
* If we're clearing the FC_ID, change to use the ctl_src_addr.
@@ -790,10 +798,9 @@ void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp)
if (fnic->state == FNIC_IN_ETH_MODE || fnic->state == FNIC_IN_FC_MODE)
fnic->state = FNIC_IN_ETH_TRANS_FC_MODE;
else {
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
- "Unexpected fnic state %s while"
- " processing flogi resp\n",
- fnic_state_to_str(fnic->state));
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Unexpected fnic state: %s processing FLOGI response",
+ fnic_state_to_str(fnic->state));
spin_unlock_irq(&fnic->fnic_lock);
return;
}
@@ -870,7 +877,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
skb_trim(skb, bytes_written);
if (!fcs_ok) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fcs error. dropping packet.\n");
goto drop;
}
@@ -886,7 +893,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic rq_cmpl fcoe x%x fcsok x%x"
" pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err"
" x%x\n",
@@ -967,7 +974,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
len = FC_FRAME_HEADROOM + FC_MAX_FRAME + FC_FRAME_TAILROOM;
skb = dev_alloc_skb(len);
if (!skb) {
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Unable to allocate RQ sk_buff\n");
return -ENOMEM;
}
@@ -1175,7 +1182,7 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
/**
* fnic_flush_tx() - send queued frames.
- * @fnic: fnic device
+ * @work: pointer to work element
*
* Send frames that were waiting to go out in FC or Ethernet mode.
* Whenever changing modes we purge queued frames, so these frames should
@@ -1183,8 +1190,9 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
*
* Called without fnic_lock held.
*/
-void fnic_flush_tx(struct fnic *fnic)
+void fnic_flush_tx(struct work_struct *work)
{
+ struct fnic *fnic = container_of(work, struct fnic, flush_work);
struct sk_buff *skb;
struct fc_frame *fp;
@@ -1341,12 +1349,12 @@ void fnic_handle_fip_timer(struct fnic *fnic)
}
vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fip_timer: vlan %d state %d sol_count %d\n",
vlan->vid, vlan->state, vlan->sol_count);
switch (vlan->state) {
case FIP_VLAN_USED:
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"FIP VLAN is selected for FC transaction\n");
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
break;
@@ -1365,7 +1373,7 @@ void fnic_handle_fip_timer(struct fnic *fnic)
* no response on this vlan, remove from the list.
* Try the next vlan
*/
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Dequeue this VLAN ID %d from list\n",
vlan->vid);
list_del(&vlan->list);
@@ -1375,7 +1383,7 @@ void fnic_handle_fip_timer(struct fnic *fnic)
/* we exhausted all vlans, restart vlan disc */
spin_unlock_irqrestore(&fnic->vlans_lock,
flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"fip_timer: vlan list empty, "
"trigger vlan disc\n");
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c
index 8896758fed..ff85441c6c 100644
--- a/drivers/scsi/fnic/fnic_isr.c
+++ b/drivers/scsi/fnic/fnic_isr.c
@@ -38,8 +38,13 @@ static irqreturn_t fnic_isr_legacy(int irq, void *data)
fnic_log_q_error(fnic);
}
+ if (pba & (1 << FNIC_INTX_DUMMY)) {
+ atomic64_inc(&fnic->fnic_stats.misc_stats.intx_dummy);
+ vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_DUMMY]);
+ }
+
if (pba & (1 << FNIC_INTX_WQ_RQ_COPYWQ)) {
- work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
+ work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions, FNIC_MQ_CQ_INDEX);
work_done += fnic_wq_cmpl_handler(fnic, -1);
work_done += fnic_rq_cmpl_handler(fnic, -1);
@@ -60,7 +65,7 @@ static irqreturn_t fnic_isr_msi(int irq, void *data)
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
- work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
+ work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions, FNIC_MQ_CQ_INDEX);
work_done += fnic_wq_cmpl_handler(fnic, -1);
work_done += fnic_rq_cmpl_handler(fnic, -1);
@@ -109,12 +114,22 @@ static irqreturn_t fnic_isr_msix_wq_copy(int irq, void *data)
{
struct fnic *fnic = data;
unsigned long wq_copy_work_done = 0;
+ int i;
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
- wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions);
- vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ_COPY],
+ i = irq - fnic->msix[0].irq_num;
+ if (i >= fnic->wq_copy_count + fnic->copy_wq_base ||
+ i < 0 || fnic->msix[i].irq_num != irq) {
+ for (i = fnic->copy_wq_base; i < fnic->wq_copy_count + fnic->copy_wq_base ; i++) {
+ if (fnic->msix[i].irq_num == irq)
+ break;
+ }
+ }
+
+ wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions, i);
+ vnic_intr_return_credits(&fnic->intr[i],
wq_copy_work_done,
1 /* unmask intr */,
1 /* reset intr timer */);
@@ -128,7 +143,7 @@ static irqreturn_t fnic_isr_msix_err_notify(int irq, void *data)
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
- vnic_intr_return_all_credits(&fnic->intr[FNIC_MSIX_ERR_NOTIFY]);
+ vnic_intr_return_all_credits(&fnic->intr[fnic->err_intr_offset]);
fnic_log_q_error(fnic);
fnic_handle_link_event(fnic);
@@ -186,26 +201,30 @@ int fnic_request_intr(struct fnic *fnic)
fnic->msix[FNIC_MSIX_WQ].isr = fnic_isr_msix_wq;
fnic->msix[FNIC_MSIX_WQ].devid = fnic;
- sprintf(fnic->msix[FNIC_MSIX_WQ_COPY].devname,
- "%.11s-scsi-wq", fnic->name);
- fnic->msix[FNIC_MSIX_WQ_COPY].isr = fnic_isr_msix_wq_copy;
- fnic->msix[FNIC_MSIX_WQ_COPY].devid = fnic;
+ for (i = fnic->copy_wq_base; i < fnic->wq_copy_count + fnic->copy_wq_base; i++) {
+ sprintf(fnic->msix[i].devname,
+ "%.11s-scsi-wq-%d", fnic->name, i-FNIC_MSIX_WQ_COPY);
+ fnic->msix[i].isr = fnic_isr_msix_wq_copy;
+ fnic->msix[i].devid = fnic;
+ }
- sprintf(fnic->msix[FNIC_MSIX_ERR_NOTIFY].devname,
+ sprintf(fnic->msix[fnic->err_intr_offset].devname,
"%.11s-err-notify", fnic->name);
- fnic->msix[FNIC_MSIX_ERR_NOTIFY].isr =
+ fnic->msix[fnic->err_intr_offset].isr =
fnic_isr_msix_err_notify;
- fnic->msix[FNIC_MSIX_ERR_NOTIFY].devid = fnic;
+ fnic->msix[fnic->err_intr_offset].devid = fnic;
- for (i = 0; i < ARRAY_SIZE(fnic->msix); i++) {
- err = request_irq(pci_irq_vector(fnic->pdev, i),
- fnic->msix[i].isr, 0,
- fnic->msix[i].devname,
- fnic->msix[i].devid);
+ for (i = 0; i < fnic->intr_count; i++) {
+ fnic->msix[i].irq_num = pci_irq_vector(fnic->pdev, i);
+
+ err = request_irq(fnic->msix[i].irq_num,
+ fnic->msix[i].isr, 0,
+ fnic->msix[i].devname,
+ fnic->msix[i].devid);
if (err) {
- shost_printk(KERN_ERR, fnic->lport->host,
- "MSIX: request_irq"
- " failed %d\n", err);
+ FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "request_irq failed with error: %d\n",
+ err);
fnic_free_intr(fnic);
break;
}
@@ -220,44 +239,99 @@ int fnic_request_intr(struct fnic *fnic)
return err;
}
-int fnic_set_intr_mode(struct fnic *fnic)
+int fnic_set_intr_mode_msix(struct fnic *fnic)
{
unsigned int n = ARRAY_SIZE(fnic->rq);
unsigned int m = ARRAY_SIZE(fnic->wq);
- unsigned int o = ARRAY_SIZE(fnic->wq_copy);
+ unsigned int o = ARRAY_SIZE(fnic->hw_copy_wq);
+ unsigned int min_irqs = n + m + 1 + 1; /*rq, raw wq, wq, err*/
/*
- * Set interrupt mode (INTx, MSI, MSI-X) depending
- * system capabilities.
- *
- * Try MSI-X first
- *
* We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
* (last INTR is used for WQ/RQ errors and notification area)
*/
- if (fnic->rq_count >= n &&
- fnic->raw_wq_count >= m &&
- fnic->wq_copy_count >= o &&
- fnic->cq_count >= n + m + o) {
- int vecs = n + m + o + 1;
-
- if (pci_alloc_irq_vectors(fnic->pdev, vecs, vecs,
- PCI_IRQ_MSIX) == vecs) {
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "rq-array size: %d wq-array size: %d copy-wq array size: %d\n",
+ n, m, o);
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "rq_count: %d raw_wq_count: %d wq_copy_count: %d cq_count: %d\n",
+ fnic->rq_count, fnic->raw_wq_count,
+ fnic->wq_copy_count, fnic->cq_count);
+
+ if (fnic->rq_count <= n && fnic->raw_wq_count <= m &&
+ fnic->wq_copy_count <= o) {
+ int vec_count = 0;
+ int vecs = fnic->rq_count + fnic->raw_wq_count + fnic->wq_copy_count + 1;
+
+ vec_count = pci_alloc_irq_vectors(fnic->pdev, min_irqs, vecs,
+ PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "allocated %d MSI-X vectors\n",
+ vec_count);
+
+ if (vec_count > 0) {
+ if (vec_count < vecs) {
+ FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "interrupts number mismatch: vec_count: %d vecs: %d\n",
+ vec_count, vecs);
+ if (vec_count < min_irqs) {
+ FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "no interrupts for copy wq\n");
+ return 1;
+ }
+ }
+
fnic->rq_count = n;
fnic->raw_wq_count = m;
- fnic->wq_copy_count = o;
- fnic->wq_count = m + o;
- fnic->cq_count = n + m + o;
- fnic->intr_count = vecs;
- fnic->err_intr_offset = FNIC_MSIX_ERR_NOTIFY;
-
- FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
- "Using MSI-X Interrupts\n");
- vnic_dev_set_intr_mode(fnic->vdev,
- VNIC_DEV_INTR_MODE_MSIX);
+ fnic->copy_wq_base = fnic->rq_count + fnic->raw_wq_count;
+ fnic->wq_copy_count = vec_count - n - m - 1;
+ fnic->wq_count = fnic->raw_wq_count + fnic->wq_copy_count;
+ if (fnic->cq_count != vec_count - 1) {
+ FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "CQ count: %d does not match MSI-X vector count: %d\n",
+ fnic->cq_count, vec_count);
+ fnic->cq_count = vec_count - 1;
+ }
+ fnic->intr_count = vec_count;
+ fnic->err_intr_offset = fnic->rq_count + fnic->wq_count;
+
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "rq_count: %d raw_wq_count: %d copy_wq_base: %d\n",
+ fnic->rq_count,
+ fnic->raw_wq_count, fnic->copy_wq_base);
+
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "wq_copy_count: %d wq_count: %d cq_count: %d\n",
+ fnic->wq_copy_count,
+ fnic->wq_count, fnic->cq_count);
+
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "intr_count: %d err_intr_offset: %u",
+ fnic->intr_count,
+ fnic->err_intr_offset);
+
+ vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSIX);
+ FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic using MSI-X\n");
return 0;
}
}
+ return 1;
+}
+
+int fnic_set_intr_mode(struct fnic *fnic)
+{
+ int ret_status = 0;
+
+ /*
+ * Set interrupt mode (INTx, MSI, MSI-X) depending
+ * system capabilities.
+ *
+ * Try MSI-X first
+ */
+ ret_status = fnic_set_intr_mode_msix(fnic);
+ if (ret_status == 0)
+ return ret_status;
/*
* Next try MSI
@@ -277,7 +351,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
fnic->intr_count = 1;
fnic->err_intr_offset = 0;
- FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Using MSI Interrupts\n");
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSI);
@@ -303,7 +377,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
fnic->cq_count = 3;
fnic->intr_count = 3;
- FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Using Legacy Interrupts\n");
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index f27f9319e0..29eead383e 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -12,9 +12,11 @@
#include <linux/pci.h>
#include <linux/skbuff.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/if_ether.h>
+#include <linux/blk-mq-pci.h>
#include <scsi/fc/fc_fip.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
@@ -39,6 +41,7 @@ static struct kmem_cache *fnic_sgl_cache[FNIC_SGL_NUM_CACHES];
static struct kmem_cache *fnic_io_req_cache;
static LIST_HEAD(fnic_list);
static DEFINE_SPINLOCK(fnic_list_lock);
+static DEFINE_IDA(fnic_ida);
/* Supported devices by fnic module */
static struct pci_device_id fnic_id_table[] = {
@@ -113,6 +116,7 @@ static const struct scsi_host_template fnic_host_template = {
.shost_groups = fnic_host_groups,
.track_queue_depth = 1,
.cmd_size = sizeof(struct fnic_cmd_priv),
+ .map_queues = fnic_mq_map_queues_cpus,
};
static void
@@ -209,7 +213,7 @@ static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
if (ret) {
- FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic: Get vnic stats failed"
" 0x%x", ret);
return stats;
@@ -321,7 +325,7 @@ static void fnic_reset_host_stats(struct Scsi_Host *host)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
if (ret) {
- FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic: Reset vnic stats failed"
" 0x%x", ret);
return;
@@ -354,7 +358,7 @@ void fnic_log_q_error(struct fnic *fnic)
}
for (i = 0; i < fnic->wq_copy_count; i++) {
- error_status = ioread32(&fnic->wq_copy[i].ctrl->error_status);
+ error_status = ioread32(&fnic->hw_copy_wq[i].ctrl->error_status);
if (error_status)
shost_printk(KERN_ERR, fnic->lport->host,
"CWQ[%d] error_status"
@@ -389,7 +393,7 @@ static int fnic_notify_set(struct fnic *fnic)
err = vnic_dev_notify_set(fnic->vdev, -1);
break;
case VNIC_DEV_INTR_MODE_MSIX:
- err = vnic_dev_notify_set(fnic->vdev, FNIC_MSIX_ERR_NOTIFY);
+ err = vnic_dev_notify_set(fnic->vdev, fnic->wq_copy_count + fnic->copy_wq_base);
break;
default:
shost_printk(KERN_ERR, fnic->lport->host,
@@ -475,6 +479,7 @@ static int fnic_cleanup(struct fnic *fnic)
{
unsigned int i;
int err;
+ int raw_wq_rq_counts;
vnic_dev_disable(fnic->vdev);
for (i = 0; i < fnic->intr_count; i++)
@@ -491,13 +496,14 @@ static int fnic_cleanup(struct fnic *fnic)
return err;
}
for (i = 0; i < fnic->wq_copy_count; i++) {
- err = vnic_wq_copy_disable(&fnic->wq_copy[i]);
+ err = vnic_wq_copy_disable(&fnic->hw_copy_wq[i]);
if (err)
return err;
+ raw_wq_rq_counts = fnic->raw_wq_count + fnic->rq_count;
+ fnic_wq_copy_cmpl_handler(fnic, -1, i + raw_wq_rq_counts);
}
/* Clean up completed IOs and FCS frames */
- fnic_wq_copy_cmpl_handler(fnic, io_completions);
fnic_wq_cmpl_handler(fnic, -1);
fnic_rq_cmpl_handler(fnic, -1);
@@ -507,7 +513,7 @@ static int fnic_cleanup(struct fnic *fnic)
for (i = 0; i < fnic->rq_count; i++)
vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf);
for (i = 0; i < fnic->wq_copy_count; i++)
- vnic_wq_copy_clean(&fnic->wq_copy[i],
+ vnic_wq_copy_clean(&fnic->hw_copy_wq[i],
fnic_wq_copy_cleanup_handler);
for (i = 0; i < fnic->cq_count; i++)
@@ -560,11 +566,6 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
host->max_cmd_len = FCOE_MAX_CMD_LEN;
host->nr_hw_queues = fnic->wq_copy_count;
- if (host->nr_hw_queues > 1)
- shost_printk(KERN_ERR, host,
- "fnic: blk-mq is not supported");
-
- host->nr_hw_queues = fnic->wq_copy_count = 1;
shost_printk(KERN_INFO, host,
"fnic: can_queue: %d max_lun: %llu",
@@ -577,15 +578,43 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
return 0;
}
+void fnic_mq_map_queues_cpus(struct Scsi_Host *host)
+{
+ struct fc_lport *lp = shost_priv(host);
+ struct fnic *fnic = lport_priv(lp);
+ struct pci_dev *l_pdev = fnic->pdev;
+ int intr_mode = fnic->config.intr_mode;
+ struct blk_mq_queue_map *qmap = &host->tag_set.map[HCTX_TYPE_DEFAULT];
+
+ if (intr_mode == VNIC_DEV_INTR_MODE_MSI || intr_mode == VNIC_DEV_INTR_MODE_INTX) {
+ FNIC_MAIN_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "intr_mode is not msix\n");
+ return;
+ }
+
+ FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "qmap->nr_queues: %d\n", qmap->nr_queues);
+
+ if (l_pdev == NULL) {
+ FNIC_MAIN_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "l_pdev is null\n");
+ return;
+ }
+
+ blk_mq_pci_map_queues(qmap, l_pdev, FNIC_PCI_OFFSET);
+}
+
static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct Scsi_Host *host;
struct fc_lport *lp;
struct fnic *fnic;
mempool_t *pool;
- int err;
+ int err = 0;
+ int fnic_id = 0;
int i;
unsigned long flags;
+ int hwq;
/*
* Allocate SCSI Host and set up association between host,
@@ -597,25 +626,28 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = -ENOMEM;
goto err_out;
}
+
host = lp->host;
fnic = lport_priv(lp);
+
+ fnic_id = ida_alloc(&fnic_ida, GFP_KERNEL);
+ if (fnic_id < 0) {
+ pr_err("Unable to alloc fnic ID\n");
+ err = fnic_id;
+ goto err_out_ida_alloc;
+ }
fnic->lport = lp;
fnic->ctlr.lp = lp;
-
fnic->link_events = 0;
+ fnic->pdev = pdev;
snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME,
host->host_no);
host->transportt = fnic_fc_transport;
-
+ fnic->fnic_num = fnic_id;
fnic_stats_debugfs_init(fnic);
- /* Setup PCI resources */
- pci_set_drvdata(pdev, fnic);
-
- fnic->pdev = pdev;
-
err = pci_enable_device(pdev);
if (err) {
shost_printk(KERN_ERR, fnic->lport->host,
@@ -717,7 +749,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_dev_close;
}
- fnic_scsi_drv_init(fnic);
+ /* Setup PCI resources */
+ pci_set_drvdata(pdev, fnic);
fnic_get_res_counts(fnic);
@@ -737,6 +770,16 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_clear_intr;
}
+ fnic_scsi_drv_init(fnic);
+
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++) {
+ fnic->sw_copy_wq[hwq].ioreq_table_size = fnic->fnic_max_tag_id;
+ fnic->sw_copy_wq[hwq].io_req_table =
+ kzalloc((fnic->sw_copy_wq[hwq].ioreq_table_size + 1) *
+ sizeof(struct fnic_io_req *), GFP_KERNEL);
+ }
+ shost_printk(KERN_INFO, fnic->lport->host, "fnic copy wqs: %d, Q0 ioreq table size: %d\n",
+ fnic->wq_copy_count, fnic->sw_copy_wq[0].ioreq_table_size);
/* initialize all fnic locks */
spin_lock_init(&fnic->fnic_lock);
@@ -751,11 +794,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic->fw_ack_index[i] = -1;
}
- for (i = 0; i < FNIC_IO_LOCKS; i++)
- spin_lock_init(&fnic->io_req_lock[i]);
-
- spin_lock_init(&fnic->sgreset_lock);
-
err = -ENOMEM;
fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
if (!fnic->io_req_pool)
@@ -792,6 +830,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&fnic->vlans_lock);
INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
INIT_WORK(&fnic->event_work, fnic_handle_event);
+ INIT_WORK(&fnic->flush_work, fnic_flush_tx);
skb_queue_head_init(&fnic->fip_frame_queue);
INIT_LIST_HEAD(&fnic->evlist);
INIT_LIST_HEAD(&fnic->vlans);
@@ -823,16 +862,32 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* allocate RQ buffers and post them to RQ*/
for (i = 0; i < fnic->rq_count; i++) {
- vnic_rq_enable(&fnic->rq[i]);
err = vnic_rq_fill(&fnic->rq[i], fnic_alloc_rq_frame);
if (err) {
shost_printk(KERN_ERR, fnic->lport->host,
"fnic_alloc_rq_frame can't alloc "
"frame\n");
- goto err_out_free_rq_buf;
+ goto err_out_rq_buf;
}
}
+ /* Enable all queues */
+ for (i = 0; i < fnic->raw_wq_count; i++)
+ vnic_wq_enable(&fnic->wq[i]);
+ for (i = 0; i < fnic->rq_count; i++) {
+ if (!ioread32(&fnic->rq[i].ctrl->enable))
+ vnic_rq_enable(&fnic->rq[i]);
+ }
+ for (i = 0; i < fnic->wq_copy_count; i++)
+ vnic_wq_copy_enable(&fnic->hw_copy_wq[i]);
+
+ err = fnic_request_intr(fnic);
+ if (err) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "Unable to request irq.\n");
+ goto err_out_request_intr;
+ }
+
/*
* Initialization done with PCI system, hardware, firmware.
* Add host to SCSI
@@ -841,9 +896,10 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) {
shost_printk(KERN_ERR, fnic->lport->host,
"fnic: scsi_add_host failed...exiting\n");
- goto err_out_free_rq_buf;
+ goto err_out_scsi_add_host;
}
+
/* Start local port initiatialization */
lp->link_up = 0;
@@ -867,7 +923,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START,
FCPIO_HOST_EXCH_RANGE_END, NULL)) {
err = -ENOMEM;
- goto err_out_remove_scsi_host;
+ goto err_out_fc_exch_mgr_alloc;
}
fc_lport_init_stats(lp);
@@ -895,21 +951,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
skb_queue_head_init(&fnic->frame_queue);
skb_queue_head_init(&fnic->tx_queue);
- /* Enable all queues */
- for (i = 0; i < fnic->raw_wq_count; i++)
- vnic_wq_enable(&fnic->wq[i]);
- for (i = 0; i < fnic->wq_copy_count; i++)
- vnic_wq_copy_enable(&fnic->wq_copy[i]);
-
fc_fabric_login(lp);
- err = fnic_request_intr(fnic);
- if (err) {
- shost_printk(KERN_ERR, fnic->lport->host,
- "Unable to request irq.\n");
- goto err_out_free_exch_mgr;
- }
-
vnic_dev_enable(fnic->vdev);
for (i = 0; i < fnic->intr_count; i++)
@@ -921,12 +964,15 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_free_exch_mgr:
fc_exch_mgr_free(lp);
-err_out_remove_scsi_host:
+err_out_fc_exch_mgr_alloc:
fc_remove_host(lp->host);
scsi_remove_host(lp->host);
-err_out_free_rq_buf:
+err_out_scsi_add_host:
+ fnic_free_intr(fnic);
+err_out_request_intr:
for (i = 0; i < fnic->rq_count; i++)
vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf);
+err_out_rq_buf:
vnic_dev_notify_unset(fnic->vdev);
err_out_free_max_pool:
mempool_destroy(fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX]);
@@ -935,6 +981,8 @@ err_out_free_dflt_pool:
err_out_free_ioreq_pool:
mempool_destroy(fnic->io_req_pool);
err_out_free_resources:
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
+ kfree(fnic->sw_copy_wq[hwq].io_req_table);
fnic_free_vnic_resources(fnic);
err_out_clear_intr:
fnic_clear_intr_mode(fnic);
@@ -951,6 +999,8 @@ err_out_disable_device:
pci_disable_device(pdev);
err_out_free_hba:
fnic_stats_debugfs_remove(fnic);
+ ida_free(&fnic_ida, fnic->fnic_num);
+err_out_ida_alloc:
scsi_host_put(lp->host);
err_out:
return err;
@@ -961,6 +1011,7 @@ static void fnic_remove(struct pci_dev *pdev)
struct fnic *fnic = pci_get_drvdata(pdev);
struct fc_lport *lp = fnic->lport;
unsigned long flags;
+ int hwq;
/*
* Mark state so that the workqueue thread stops forwarding
@@ -1021,6 +1072,8 @@ static void fnic_remove(struct pci_dev *pdev)
fc_remove_host(fnic->lport->host);
scsi_remove_host(fnic->lport->host);
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
+ kfree(fnic->sw_copy_wq[hwq].io_req_table);
fc_exch_mgr_free(fnic->lport);
vnic_dev_notify_unset(fnic->vdev);
fnic_free_intr(fnic);
@@ -1031,6 +1084,7 @@ static void fnic_remove(struct pci_dev *pdev)
fnic_iounmap(fnic);
pci_release_regions(pdev);
pci_disable_device(pdev);
+ ida_free(&fnic_ida, fnic->fnic_num);
scsi_host_put(lp->host);
}
@@ -1168,6 +1222,7 @@ static void __exit fnic_cleanup_module(void)
fnic_trace_free();
fnic_fc_trace_free();
fnic_debugfs_terminate();
+ ida_destroy(&fnic_ida);
}
module_init(fnic_init_module);
diff --git a/drivers/scsi/fnic/fnic_res.c b/drivers/scsi/fnic/fnic_res.c
index a1c9cfcace..33dd27f6f2 100644
--- a/drivers/scsi/fnic/fnic_res.c
+++ b/drivers/scsi/fnic/fnic_res.c
@@ -57,6 +57,8 @@ int fnic_get_vnic_config(struct fnic *fnic)
GET_CONFIG(port_down_timeout);
GET_CONFIG(port_down_io_retries);
GET_CONFIG(luns_per_tgt);
+ GET_CONFIG(intr_mode);
+ GET_CONFIG(wq_copy_count);
c->wq_enet_desc_count =
min_t(u32, VNIC_FNIC_WQ_DESCS_MAX,
@@ -131,6 +133,12 @@ int fnic_get_vnic_config(struct fnic *fnic)
c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
c->intr_timer_type = c->intr_timer_type;
+ /* for older firmware, GET_CONFIG will not return anything */
+ if (c->wq_copy_count == 0)
+ c->wq_copy_count = 1;
+
+ c->wq_copy_count = min_t(u16, FNIC_WQ_COPY_MAX, c->wq_copy_count);
+
shost_printk(KERN_INFO, fnic->lport->host,
"vNIC MAC addr %pM "
"wq/wq_copy/rq %d/%d/%d\n",
@@ -161,6 +169,10 @@ int fnic_get_vnic_config(struct fnic *fnic)
shost_printk(KERN_INFO, fnic->lport->host,
"vNIC port dn io retries %d port dn timeout %d\n",
c->port_down_io_retries, c->port_down_timeout);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC wq_copy_count: %d\n", c->wq_copy_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC intr mode: %d\n", c->intr_mode);
return 0;
}
@@ -187,12 +199,25 @@ int fnic_set_nic_config(struct fnic *fnic, u8 rss_default_cpu,
void fnic_get_res_counts(struct fnic *fnic)
{
fnic->wq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_WQ);
- fnic->raw_wq_count = fnic->wq_count - 1;
- fnic->wq_copy_count = fnic->wq_count - fnic->raw_wq_count;
+ fnic->raw_wq_count = 1;
+ fnic->wq_copy_count = fnic->config.wq_copy_count;
fnic->rq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_RQ);
fnic->cq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_CQ);
fnic->intr_count = vnic_dev_get_res_count(fnic->vdev,
RES_TYPE_INTR_CTRL);
+
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC fw resources wq_count: %d\n", fnic->wq_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC fw resources raw_wq_count: %d\n", fnic->raw_wq_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC fw resources wq_copy_count: %d\n", fnic->wq_copy_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC fw resources rq_count: %d\n", fnic->rq_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC fw resources cq_count: %d\n", fnic->cq_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC fw resources intr_count: %d\n", fnic->intr_count);
}
void fnic_free_vnic_resources(struct fnic *fnic)
@@ -203,7 +228,7 @@ void fnic_free_vnic_resources(struct fnic *fnic)
vnic_wq_free(&fnic->wq[i]);
for (i = 0; i < fnic->wq_copy_count; i++)
- vnic_wq_copy_free(&fnic->wq_copy[i]);
+ vnic_wq_copy_free(&fnic->hw_copy_wq[i]);
for (i = 0; i < fnic->rq_count; i++)
vnic_rq_free(&fnic->rq[i]);
@@ -234,10 +259,15 @@ int fnic_alloc_vnic_resources(struct fnic *fnic)
intr_mode == VNIC_DEV_INTR_MODE_MSIX ?
"MSI-X" : "unknown");
- shost_printk(KERN_INFO, fnic->lport->host, "vNIC resources avail: "
- "wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
- fnic->wq_count, fnic->wq_copy_count, fnic->raw_wq_count,
- fnic->rq_count, fnic->cq_count, fnic->intr_count);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC resources avail: wq %d cp_wq %d raw_wq %d rq %d",
+ fnic->wq_count, fnic->wq_copy_count,
+ fnic->raw_wq_count, fnic->rq_count);
+
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "vNIC resources avail: cq %d intr %d cpy-wq desc count %d\n",
+ fnic->cq_count, fnic->intr_count,
+ fnic->config.wq_copy_desc_count);
/* Allocate Raw WQ used for FCS frames */
for (i = 0; i < fnic->raw_wq_count; i++) {
@@ -250,7 +280,7 @@ int fnic_alloc_vnic_resources(struct fnic *fnic)
/* Allocate Copy WQs used for SCSI IOs */
for (i = 0; i < fnic->wq_copy_count; i++) {
- err = vnic_wq_copy_alloc(fnic->vdev, &fnic->wq_copy[i],
+ err = vnic_wq_copy_alloc(fnic->vdev, &fnic->hw_copy_wq[i],
(fnic->raw_wq_count + i),
fnic->config.wq_copy_desc_count,
sizeof(struct fcpio_host_req));
@@ -357,7 +387,7 @@ int fnic_alloc_vnic_resources(struct fnic *fnic)
}
for (i = 0; i < fnic->wq_copy_count; i++) {
- vnic_wq_copy_init(&fnic->wq_copy[i],
+ vnic_wq_copy_init(&fnic->hw_copy_wq[i],
0 /* cq_index 0 - always */,
error_interrupt_enable,
error_interrupt_offset);
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 416d819548..fc4cee91b1 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -92,20 +92,6 @@ static const char *fnic_fcpio_status_to_str(unsigned int status)
static void fnic_cleanup_io(struct fnic *fnic);
-static inline spinlock_t *fnic_io_lock_hash(struct fnic *fnic,
- struct scsi_cmnd *sc)
-{
- u32 hash = scsi_cmd_to_rq(sc)->tag & (FNIC_IO_LOCKS - 1);
-
- return &fnic->io_req_lock[hash];
-}
-
-static inline spinlock_t *fnic_io_lock_tag(struct fnic *fnic,
- int tag)
-{
- return &fnic->io_req_lock[tag & (FNIC_IO_LOCKS - 1)];
-}
-
/*
* Unmap the data buffer and sense buffer for an io_req,
* also unmap and free the device-private scatter/gather list.
@@ -129,23 +115,23 @@ static void fnic_release_ioreq_buf(struct fnic *fnic,
}
/* Free up Copy Wq descriptors. Called with copy_wq lock held */
-static int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq)
+static int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq, unsigned int hwq)
{
/* if no Ack received from firmware, then nothing to clean */
- if (!fnic->fw_ack_recd[0])
+ if (!fnic->fw_ack_recd[hwq])
return 1;
/*
* Update desc_available count based on number of freed descriptors
* Account for wraparound
*/
- if (wq->to_clean_index <= fnic->fw_ack_index[0])
- wq->ring.desc_avail += (fnic->fw_ack_index[0]
+ if (wq->to_clean_index <= fnic->fw_ack_index[hwq])
+ wq->ring.desc_avail += (fnic->fw_ack_index[hwq]
- wq->to_clean_index + 1);
else
wq->ring.desc_avail += (wq->ring.desc_count
- wq->to_clean_index
- + fnic->fw_ack_index[0] + 1);
+ + fnic->fw_ack_index[hwq] + 1);
/*
* just bump clean index to ack_index+1 accounting for wraparound
@@ -153,10 +139,10 @@ static int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq)
* to_clean_index and fw_ack_index, both inclusive
*/
wq->to_clean_index =
- (fnic->fw_ack_index[0] + 1) % wq->ring.desc_count;
+ (fnic->fw_ack_index[hwq] + 1) % wq->ring.desc_count;
/* we have processed the acks received so far */
- fnic->fw_ack_recd[0] = 0;
+ fnic->fw_ack_recd[hwq] = 0;
return 0;
}
@@ -170,17 +156,14 @@ __fnic_set_state_flags(struct fnic *fnic, unsigned long st_flags,
unsigned long clearbits)
{
unsigned long flags = 0;
- unsigned long host_lock_flags = 0;
spin_lock_irqsave(&fnic->fnic_lock, flags);
- spin_lock_irqsave(fnic->lport->host->host_lock, host_lock_flags);
if (clearbits)
fnic->state_flags &= ~st_flags;
else
fnic->state_flags |= st_flags;
- spin_unlock_irqrestore(fnic->lport->host->host_lock, host_lock_flags);
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return;
@@ -193,7 +176,7 @@ __fnic_set_state_flags(struct fnic *fnic, unsigned long st_flags,
*/
int fnic_fw_reset_handler(struct fnic *fnic)
{
- struct vnic_wq_copy *wq = &fnic->wq_copy[0];
+ struct vnic_wq_copy *wq = &fnic->hw_copy_wq[0];
int ret = 0;
unsigned long flags;
@@ -210,7 +193,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);
if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
- free_wq_copy_descs(fnic, wq);
+ free_wq_copy_descs(fnic, wq, 0);
if (!vnic_wq_copy_desc_avail(wq))
ret = -EAGAIN;
@@ -228,12 +211,12 @@ int fnic_fw_reset_handler(struct fnic *fnic)
if (!ret) {
atomic64_inc(&fnic->fnic_stats.reset_stats.fw_resets);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Issued fw reset\n");
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Issued fw reset\n");
} else {
fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Failed to issue fw reset\n");
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Failed to issue fw reset\n");
}
return ret;
@@ -246,7 +229,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
*/
int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id)
{
- struct vnic_wq_copy *wq = &fnic->wq_copy[0];
+ struct vnic_wq_copy *wq = &fnic->hw_copy_wq[0];
enum fcpio_flogi_reg_format_type format;
struct fc_lport *lp = fnic->lport;
u8 gw_mac[ETH_ALEN];
@@ -256,7 +239,7 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id)
spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);
if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
- free_wq_copy_descs(fnic, wq);
+ free_wq_copy_descs(fnic, wq, 0);
if (!vnic_wq_copy_desc_avail(wq)) {
ret = -EAGAIN;
@@ -276,15 +259,15 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id)
fc_id, gw_mac,
fnic->data_src_addr,
lp->r_a_tov, lp->e_d_tov);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"FLOGI FIP reg issued fcid %x src %pM dest %pM\n",
fc_id, fnic->data_src_addr, gw_mac);
} else {
fnic_queue_wq_copy_desc_flogi_reg(wq, SCSI_NO_TAG,
format, fc_id, gw_mac);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "FLOGI reg issued fcid %x map %d dest %pM\n",
- fc_id, fnic->ctlr.map_dest, gw_mac);
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI reg issued fcid 0x%x map %d dest 0x%p\n",
+ fc_id, fnic->ctlr.map_dest, gw_mac);
}
atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs);
@@ -306,7 +289,9 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
struct vnic_wq_copy *wq,
struct fnic_io_req *io_req,
struct scsi_cmnd *sc,
- int sg_count)
+ int sg_count,
+ uint32_t mqtag,
+ uint16_t hwq)
{
struct scatterlist *sg;
struct fc_rport *rport = starget_to_rport(scsi_target(sc->device));
@@ -314,7 +299,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
struct host_sg_desc *desc;
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
unsigned int i;
- unsigned long intr_flags;
int flags;
u8 exch_flags;
struct scsi_lun fc_lun;
@@ -354,14 +338,11 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
int_to_scsilun(sc->device->lun, &fc_lun);
/* Enqueue the descriptor in the Copy WQ */
- spin_lock_irqsave(&fnic->wq_copy_lock[0], intr_flags);
-
- if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
- free_wq_copy_descs(fnic, wq);
+ if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[hwq])
+ free_wq_copy_descs(fnic, wq, hwq);
if (unlikely(!vnic_wq_copy_desc_avail(wq))) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags);
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"fnic_queue_wq_copy_desc failure - no descriptors\n");
atomic64_inc(&misc_stats->io_cpwq_alloc_failures);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -378,7 +359,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
(rp->flags & FC_RP_FLAGS_RETRY))
exch_flags |= FCPIO_ICMND_SRFLAG_RETRY;
- fnic_queue_wq_copy_desc_icmnd_16(wq, scsi_cmd_to_rq(sc)->tag,
+ fnic_queue_wq_copy_desc_icmnd_16(wq, mqtag,
0, exch_flags, io_req->sgl_cnt,
SCSI_SENSE_BUFFERSIZE,
io_req->sgl_list_pa,
@@ -399,43 +380,52 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs,
atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs));
- spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags);
return 0;
}
-/*
- * fnic_queuecommand
- * Routine to send a scsi cdb
- * Called with host_lock held and interrupts disabled.
- */
-static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
+int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
{
+ struct request *const rq = scsi_cmd_to_rq(sc);
+ uint32_t mqtag = 0;
void (*done)(struct scsi_cmnd *) = scsi_done;
- const int tag = scsi_cmd_to_rq(sc)->tag;
struct fc_lport *lp = shost_priv(sc->device->host);
struct fc_rport *rport;
struct fnic_io_req *io_req = NULL;
struct fnic *fnic = lport_priv(lp);
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
struct vnic_wq_copy *wq;
- int ret;
+ int ret = 1;
u64 cmd_trace;
int sg_count = 0;
unsigned long flags = 0;
unsigned long ptr;
- spinlock_t *io_lock = NULL;
int io_lock_acquired = 0;
struct fc_rport_libfc_priv *rp;
+ uint16_t hwq = 0;
+
+ mqtag = blk_mq_unique_tag(rq);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
+ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "fnic IO blocked flags: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
+ fnic->state_flags);
return SCSI_MLQUEUE_HOST_BUSY;
+ }
- if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET)))
+ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "fnic flags: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
+ fnic->state_flags);
return SCSI_MLQUEUE_HOST_BUSY;
+ }
rport = starget_to_rport(scsi_target(sc->device));
if (!rport) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"returning DID_NO_CONNECT for IO as rport is NULL\n");
sc->result = DID_NO_CONNECT << 16;
done(sc);
@@ -444,7 +434,8 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
ret = fc_remote_port_chkready(rport);
if (ret) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"rport is not ready\n");
atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
sc->result = ret;
@@ -454,7 +445,8 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
rp = rport->dd_data;
if (!rp || rp->rp_state == RPORT_ST_DELETE) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"rport 0x%x removed, returning DID_NO_CONNECT\n",
rport->port_id);
@@ -465,7 +457,8 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
}
if (rp->rp_state != RPORT_ST_READY) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"rport 0x%x in state 0x%x, returning DID_IMM_RETRY\n",
rport->port_id, rp->rp_state);
@@ -474,17 +467,17 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
return 0;
}
- if (lp->state != LPORT_ST_READY || !(lp->link_up))
+ if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "state not ready: %d/link not up: %d Returning HOST_BUSY\n",
+ lp->state, lp->link_up);
return SCSI_MLQUEUE_HOST_BUSY;
+ }
atomic_inc(&fnic->in_flight);
- /*
- * Release host lock, use driver resource specific locks from here.
- * Don't re-enable interrupts in case they were disabled prior to the
- * caller disabling them.
- */
- spin_unlock(lp->host->host_lock);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
fnic_priv(sc)->state = FNIC_IOREQ_NOT_INITED;
fnic_priv(sc)->flags = FNIC_NO_FLAGS;
@@ -501,7 +494,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
sg_count = scsi_dma_map(sc);
if (sg_count < 0) {
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
- tag, sc, 0, sc->cmnd[0], sg_count, fnic_priv(sc)->state);
+ mqtag, sc, 0, sc->cmnd[0], sg_count, fnic_priv(sc)->state);
mempool_free(io_req, fnic->io_req_pool);
goto out;
}
@@ -536,11 +529,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
}
/*
- * Will acquire lock defore setting to IO initialized.
+ * Will acquire lock before setting to IO initialized.
*/
-
- io_lock = fnic_io_lock_hash(fnic, sc);
- spin_lock_irqsave(io_lock, flags);
+ hwq = blk_mq_unique_tag_to_hwq(mqtag);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
/* initialize rest of io_req */
io_lock_acquired = 1;
@@ -549,28 +541,40 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc)
fnic_priv(sc)->state = FNIC_IOREQ_CMD_PENDING;
fnic_priv(sc)->io_req = io_req;
fnic_priv(sc)->flags |= FNIC_IO_INITIALIZED;
+ io_req->sc = sc;
+
+ if (fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] != NULL) {
+ WARN(1, "fnic<%d>: %s: hwq: %d tag 0x%x already exists\n",
+ fnic->fnic_num, __func__, hwq, blk_mq_unique_tag_to_tag(mqtag));
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] = io_req;
+ io_req->tag = mqtag;
/* create copy wq desc and enqueue it */
- wq = &fnic->wq_copy[0];
- ret = fnic_queue_wq_copy_desc(fnic, wq, io_req, sc, sg_count);
+ wq = &fnic->hw_copy_wq[hwq];
+ atomic64_inc(&fnic_stats->io_stats.ios[hwq]);
+ ret = fnic_queue_wq_copy_desc(fnic, wq, io_req, sc, sg_count, mqtag, hwq);
if (ret) {
/*
* In case another thread cancelled the request,
* refetch the pointer under the lock.
*/
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
- tag, sc, 0, 0, 0, fnic_flags_and_state(sc));
+ mqtag, sc, 0, 0, 0, fnic_flags_and_state(sc));
io_req = fnic_priv(sc)->io_req;
fnic_priv(sc)->io_req = NULL;
+ if (io_req)
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] = NULL;
fnic_priv(sc)->state = FNIC_IOREQ_CMD_COMPLETE;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if (io_req) {
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
}
atomic_dec(&fnic->in_flight);
- /* acquire host lock before returning to SCSI */
- spin_lock(lp->host->host_lock);
return ret;
} else {
atomic64_inc(&fnic_stats->io_stats.active_ios);
@@ -590,20 +594,17 @@ out:
sc->cmnd[5]);
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
- tag, sc, io_req, sg_count, cmd_trace,
+ mqtag, sc, io_req, sg_count, cmd_trace,
fnic_flags_and_state(sc));
/* if only we issued IO, will we have the io lock */
if (io_lock_acquired)
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic_dec(&fnic->in_flight);
- /* acquire host lock before returning to SCSI */
- spin_lock(lp->host->host_lock);
return ret;
}
-DEF_SCSI_QCMD(fnic_queuecommand)
/*
* fnic_fcpio_fw_reset_cmpl_handler
@@ -636,15 +637,14 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) {
/* Check status of reset completion */
if (!hdr_status) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "reset cmpl success\n");
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "reset cmpl success\n");
/* Ready to send flogi out */
fnic->state = FNIC_IN_ETH_MODE;
} else {
- FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host,
- "fnic fw_reset : failed %s\n",
- fnic_fcpio_status_to_str(hdr_status));
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "reset failed with header status: %s\n",
+ fnic_fcpio_status_to_str(hdr_status));
/*
* Unable to change to eth mode, cannot send out flogi
@@ -657,10 +657,9 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
ret = -1;
}
} else {
- FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host,
- "Unexpected state %s while processing"
- " reset cmpl\n", fnic_state_to_str(fnic->state));
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Unexpected state while processing reset completion: %s\n",
+ fnic_state_to_str(fnic->state));
atomic64_inc(&reset_stats->fw_reset_failures);
ret = -1;
}
@@ -681,7 +680,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fnic_flush_tx(fnic);
+ queue_work(fnic_event_queue, &fnic->flush_work);
reset_cmpl_handler_end:
fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
@@ -711,19 +710,19 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic,
/* Check flogi registration completion status */
if (!hdr_status) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"flog reg succeeded\n");
fnic->state = FNIC_IN_FC_MODE;
} else {
FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host,
+ fnic->lport->host, fnic->fnic_num,
"fnic flogi reg :failed %s\n",
fnic_fcpio_status_to_str(hdr_status));
fnic->state = FNIC_IN_ETH_MODE;
ret = -1;
}
} else {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Unexpected fnic state %s while"
" processing flogi reg completion\n",
fnic_state_to_str(fnic->state));
@@ -737,7 +736,7 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic,
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fnic_flush_tx(fnic);
+ queue_work(fnic_event_queue, &fnic->flush_work);
queue_work(fnic_event_queue, &fnic->frame_work);
} else {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@@ -780,20 +779,21 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
u16 request_out = desc->u.ack.request_out;
unsigned long flags;
u64 *ox_id_tag = (u64 *)(void *)desc;
+ unsigned int wq_index = cq_index;
/* mark the ack state */
- wq = &fnic->wq_copy[cq_index - fnic->raw_wq_count - fnic->rq_count];
- spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);
+ wq = &fnic->hw_copy_wq[cq_index];
+ spin_lock_irqsave(&fnic->wq_copy_lock[wq_index], flags);
fnic->fnic_stats.misc_stats.last_ack_time = jiffies;
if (is_ack_index_in_range(wq, request_out)) {
- fnic->fw_ack_index[0] = request_out;
- fnic->fw_ack_recd[0] = 1;
+ fnic->fw_ack_index[wq_index] = request_out;
+ fnic->fw_ack_recd[wq_index] = 1;
} else
atomic64_inc(
&fnic->fnic_stats.misc_stats.ack_index_out_of_range);
- spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[wq_index], flags);
FNIC_TRACE(fnic_fcpio_ack_handler,
fnic->lport->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3],
ox_id_tag[4], ox_id_tag[5]);
@@ -803,12 +803,12 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
* fnic_fcpio_icmnd_cmpl_handler
* Routine to handle icmnd completions
*/
-static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
+static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_index,
struct fcpio_fw_req *desc)
{
u8 type;
u8 hdr_status;
- struct fcpio_tag tag;
+ struct fcpio_tag ftag;
u32 id;
u64 xfer_len = 0;
struct fcpio_icmnd_cmpl *icmnd_cmpl;
@@ -816,27 +816,47 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
struct scsi_cmnd *sc;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
unsigned long flags;
- spinlock_t *io_lock;
u64 cmd_trace;
unsigned long start_time;
unsigned long io_duration_time;
+ unsigned int hwq = 0;
+ unsigned int mqtag = 0;
+ unsigned int tag = 0;
/* Decode the cmpl description to get the io_req id */
- fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
- fcpio_tag_id_dec(&tag, &id);
+ fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
+ fcpio_tag_id_dec(&ftag, &id);
icmnd_cmpl = &desc->u.icmnd_cmpl;
- if (id >= fnic->fnic_max_tag_id) {
- shost_printk(KERN_ERR, fnic->lport->host,
- "Tag out of range tag %x hdr status = %s\n",
- id, fnic_fcpio_status_to_str(hdr_status));
+ mqtag = id;
+ tag = blk_mq_unique_tag_to_tag(mqtag);
+ hwq = blk_mq_unique_tag_to_hwq(mqtag);
+
+ if (hwq != cq_index) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
+ hwq, mqtag, tag, cq_index);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hdr status: %s icmnd completion on the wrong queue\n",
+ fnic_fcpio_status_to_str(hdr_status));
+ }
+
+ if (tag >= fnic->fnic_max_tag_id) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
+ hwq, mqtag, tag, cq_index);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hdr status: %s Out of range tag\n",
+ fnic_fcpio_status_to_str(hdr_status));
return;
}
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
sc = scsi_host_find_tag(fnic->lport->host, id);
WARN_ON_ONCE(!sc);
if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_ERR, fnic->lport->host,
"icmnd_cmpl sc is null - "
"hdr status = %s tag = 0x%x desc = 0x%p\n",
@@ -852,14 +872,19 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
return;
}
- io_lock = fnic_io_lock_hash(fnic, sc);
- spin_lock_irqsave(io_lock, flags);
io_req = fnic_priv(sc)->io_req;
+ if (fnic->sw_copy_wq[hwq].io_req_table[tag] != io_req) {
+ WARN(1, "%s: %d: hwq: %d mqtag: 0x%x tag: 0x%x io_req tag mismatch\n",
+ __func__, __LINE__, hwq, mqtag, tag);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ return;
+ }
+
WARN_ON_ONCE(!io_req);
if (!io_req) {
atomic64_inc(&fnic_stats->io_stats.ioreq_null);
fnic_priv(sc)->flags |= FNIC_IO_REQ_NULL;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_ERR, fnic->lport->host,
"icmnd_cmpl io_req is null - "
"hdr status = %s tag = 0x%x sc 0x%p\n",
@@ -883,11 +908,11 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
*/
fnic_priv(sc)->flags |= FNIC_IO_DONE;
fnic_priv(sc)->flags |= FNIC_IO_ABTS_PENDING;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if(FCPIO_ABORTED == hdr_status)
fnic_priv(sc)->flags |= FNIC_IO_ABORTED;
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"icmnd_cmpl abts pending "
"hdr status = %s tag = 0x%x sc = 0x%p "
"scsi_status = %x residual = %d\n",
@@ -971,7 +996,11 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
/* Break link with the SCSI command */
fnic_priv(sc)->io_req = NULL;
+ io_req->sc = NULL;
fnic_priv(sc)->flags |= FNIC_IO_DONE;
+ fnic->sw_copy_wq[hwq].io_req_table[tag] = NULL;
+
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if (hdr_status != FCPIO_SUCCESS) {
atomic64_inc(&fnic_stats->io_stats.io_failures);
@@ -1005,7 +1034,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
/* Call SCSI completion function to complete the IO */
scsi_done(sc);
- spin_unlock_irqrestore(io_lock, flags);
mempool_free(io_req, fnic->io_req_pool);
@@ -1042,7 +1070,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
/* fnic_fcpio_itmf_cmpl_handler
* Routine to handle itmf completions
*/
-static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
+static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_index,
struct fcpio_fw_req *desc)
{
u8 type;
@@ -1056,51 +1084,73 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
unsigned long flags;
- spinlock_t *io_lock;
unsigned long start_time;
+ unsigned int hwq = cq_index;
+ unsigned int mqtag;
unsigned int tag;
fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
fcpio_tag_id_dec(&ftag, &id);
- tag = id & FNIC_TAG_MASK;
- if (tag == fnic->fnic_max_tag_id) {
- if (!(id & FNIC_TAG_DEV_RST)) {
- shost_printk(KERN_ERR, fnic->lport->host,
- "Tag out of range id 0x%x hdr status = %s\n",
- id, fnic_fcpio_status_to_str(hdr_status));
- return;
- }
- } else if (tag > fnic->fnic_max_tag_id) {
- shost_printk(KERN_ERR, fnic->lport->host,
- "Tag out of range tag 0x%x hdr status = %s\n",
- tag, fnic_fcpio_status_to_str(hdr_status));
+ mqtag = id & FNIC_TAG_MASK;
+ tag = blk_mq_unique_tag_to_tag(id & FNIC_TAG_MASK);
+ hwq = blk_mq_unique_tag_to_hwq(id & FNIC_TAG_MASK);
+
+ if (hwq != cq_index) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
+ hwq, mqtag, tag, cq_index);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hdr status: %s ITMF completion on the wrong queue\n",
+ fnic_fcpio_status_to_str(hdr_status));
+ }
+
+ if (tag > fnic->fnic_max_tag_id) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
+ hwq, mqtag, tag, cq_index);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hdr status: %s Tag out of range\n",
+ fnic_fcpio_status_to_str(hdr_status));
+ return;
+ } else if ((tag == fnic->fnic_max_tag_id) && !(id & FNIC_TAG_DEV_RST)) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
+ hwq, mqtag, tag, cq_index);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hdr status: %s Tag out of range\n",
+ fnic_fcpio_status_to_str(hdr_status));
return;
}
- if ((tag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) {
- sc = fnic->sgreset_sc;
- io_lock = &fnic->sgreset_lock;
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+
+ /* If it is sg3utils allocated SC then tag_id
+ * is max_tag_id and SC is retrieved from io_req
+ */
+ if ((mqtag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) {
+ io_req = fnic->sw_copy_wq[hwq].io_req_table[tag];
+ if (io_req)
+ sc = io_req->sc;
} else {
sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
- io_lock = fnic_io_lock_hash(fnic, sc);
}
WARN_ON_ONCE(!sc);
if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_ERR, fnic->lport->host,
"itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
fnic_fcpio_status_to_str(hdr_status), tag);
return;
}
- spin_lock_irqsave(io_lock, flags);
io_req = fnic_priv(sc)->io_req;
WARN_ON_ONCE(!io_req);
if (!io_req) {
atomic64_inc(&fnic_stats->io_stats.ioreq_null);
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_IO_ABT_TERM_REQ_NULL;
shost_printk(KERN_ERR, fnic->lport->host,
"itmf_cmpl io_req is null - "
@@ -1113,17 +1163,22 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
if ((id & FNIC_TAG_ABORT) && (id & FNIC_TAG_DEV_RST)) {
/* Abort and terminate completion of device reset req */
/* REVISIT : Add asserts about various flags */
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "dev reset abts cmpl recd. id %x status %s\n",
- id, fnic_fcpio_status_to_str(hdr_status));
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Abt/term completion received\n",
+ hwq, mqtag, tag,
+ fnic_fcpio_status_to_str(hdr_status));
fnic_priv(sc)->state = FNIC_IOREQ_ABTS_COMPLETE;
fnic_priv(sc)->abts_status = hdr_status;
fnic_priv(sc)->flags |= FNIC_DEV_RST_DONE;
if (io_req->abts_done)
complete(io_req->abts_done);
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
} else if (id & FNIC_TAG_ABORT) {
/* Completion of abort cmd */
+ shost_printk(KERN_DEBUG, fnic->lport->host,
+ "hwq: %d mqtag: 0x%x tag: 0x%x Abort header status: %s\n",
+ hwq, mqtag, tag,
+ fnic_fcpio_status_to_str(hdr_status));
switch (hdr_status) {
case FCPIO_SUCCESS:
break;
@@ -1135,7 +1190,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
&term_stats->terminate_fw_timeouts);
break;
case FCPIO_ITMF_REJECTED:
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"abort reject recd. id %d\n",
(int)(id & FNIC_TAG_MASK));
break;
@@ -1156,7 +1211,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
}
if (fnic_priv(sc)->state != FNIC_IOREQ_ABTS_PENDING) {
/* This is a late completion. Ignore it */
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return;
}
@@ -1170,7 +1225,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
if (!(fnic_priv(sc)->flags & (FNIC_IO_ABORTED | FNIC_IO_DONE)))
atomic64_inc(&misc_stats->no_icmnd_itmf_cmpls);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"abts cmpl recd. id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
fnic_fcpio_status_to_str(hdr_status));
@@ -1182,14 +1237,19 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
*/
if (io_req->abts_done) {
complete(io_req->abts_done);
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "hwq: %d mqtag: 0x%x tag: 0x%x Waking up abort thread\n",
+ hwq, mqtag, tag);
} else {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "abts cmpl, completing IO\n");
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Completing IO\n",
+ hwq, mqtag,
+ tag, fnic_fcpio_status_to_str(hdr_status));
fnic_priv(sc)->io_req = NULL;
sc->result = (DID_ERROR << 16);
-
- spin_unlock_irqrestore(io_lock, flags);
+ fnic->sw_copy_wq[hwq].io_req_table[tag] = NULL;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
@@ -1213,29 +1273,32 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
}
} else if (id & FNIC_TAG_DEV_RST) {
/* Completion of device reset */
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "hwq: %d mqtag: 0x%x tag: 0x%x DR hst: %s\n",
+ hwq, mqtag,
+ tag, fnic_fcpio_status_to_str(hdr_status));
fnic_priv(sc)->lr_status = hdr_status;
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_DEV_RST_ABTS_PENDING;
FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
sc->device->host->host_no, id, sc,
jiffies_to_msecs(jiffies - start_time),
desc, 0, fnic_flags_and_state(sc));
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Terminate pending "
- "dev reset cmpl recd. id %d status %s\n",
- (int)(id & FNIC_TAG_MASK),
- fnic_fcpio_status_to_str(hdr_status));
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Terminate pending\n",
+ hwq, mqtag,
+ tag, fnic_fcpio_status_to_str(hdr_status));
return;
}
if (fnic_priv(sc)->flags & FNIC_DEV_RST_TIMED_OUT) {
/* Need to wait for terminate completion */
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
sc->device->host->host_no, id, sc,
jiffies_to_msecs(jiffies - start_time),
desc, 0, fnic_flags_and_state(sc));
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"dev reset cmpl recd after time out. "
"id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
@@ -1244,19 +1307,19 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
}
fnic_priv(sc)->state = FNIC_IOREQ_CMD_COMPLETE;
fnic_priv(sc)->flags |= FNIC_DEV_RST_DONE;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "dev reset cmpl recd. id %d status %s\n",
- (int)(id & FNIC_TAG_MASK),
- fnic_fcpio_status_to_str(hdr_status));
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x hst: %s DR completion received\n",
+ hwq, mqtag,
+ tag, fnic_fcpio_status_to_str(hdr_status));
if (io_req->dr_done)
complete(io_req->dr_done);
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
} else {
shost_printk(KERN_ERR, fnic->lport->host,
- "Unexpected itmf io state %s tag %x\n",
- fnic_ioreq_state_to_str(fnic_priv(sc)->state), id);
- spin_unlock_irqrestore(io_lock, flags);
+ "%s: Unexpected itmf io state: hwq: %d tag 0x%x %s\n",
+ __func__, hwq, id, fnic_ioreq_state_to_str(fnic_priv(sc)->state));
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
}
}
@@ -1283,17 +1346,19 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
break;
}
+ cq_index -= fnic->copy_wq_base;
+
switch (desc->hdr.type) {
case FCPIO_ACK: /* fw copied copy wq desc to its queue */
fnic_fcpio_ack_handler(fnic, cq_index, desc);
break;
case FCPIO_ICMND_CMPL: /* fw completed a command */
- fnic_fcpio_icmnd_cmpl_handler(fnic, desc);
+ fnic_fcpio_icmnd_cmpl_handler(fnic, cq_index, desc);
break;
case FCPIO_ITMF_CMPL: /* fw completed itmf (abort cmd, lun reset)*/
- fnic_fcpio_itmf_cmpl_handler(fnic, desc);
+ fnic_fcpio_itmf_cmpl_handler(fnic, cq_index, desc);
break;
case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */
@@ -1306,7 +1371,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
break;
default:
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"firmware completion type %d\n",
desc->hdr.type);
break;
@@ -1319,10 +1384,8 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
* fnic_wq_copy_cmpl_handler
* Routine to process wq copy
*/
-int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do)
+int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned int cq_index)
{
- unsigned int wq_work_done = 0;
- unsigned int i, cq_index;
unsigned int cur_work_done;
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
u64 start_jiffies = 0;
@@ -1330,44 +1393,51 @@ int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do)
u64 delta_jiffies = 0;
u64 delta_ms = 0;
- for (i = 0; i < fnic->wq_copy_count; i++) {
- cq_index = i + fnic->raw_wq_count + fnic->rq_count;
-
- start_jiffies = jiffies;
- cur_work_done = vnic_cq_copy_service(&fnic->cq[cq_index],
- fnic_fcpio_cmpl_handler,
- copy_work_to_do);
- end_jiffies = jiffies;
-
- wq_work_done += cur_work_done;
- delta_jiffies = end_jiffies - start_jiffies;
- if (delta_jiffies >
- (u64) atomic64_read(&misc_stats->max_isr_jiffies)) {
- atomic64_set(&misc_stats->max_isr_jiffies,
- delta_jiffies);
- delta_ms = jiffies_to_msecs(delta_jiffies);
- atomic64_set(&misc_stats->max_isr_time_ms, delta_ms);
- atomic64_set(&misc_stats->corr_work_done,
- cur_work_done);
- }
+ start_jiffies = jiffies;
+ cur_work_done = vnic_cq_copy_service(&fnic->cq[cq_index],
+ fnic_fcpio_cmpl_handler,
+ copy_work_to_do);
+ end_jiffies = jiffies;
+ delta_jiffies = end_jiffies - start_jiffies;
+ if (delta_jiffies > (u64) atomic64_read(&misc_stats->max_isr_jiffies)) {
+ atomic64_set(&misc_stats->max_isr_jiffies, delta_jiffies);
+ delta_ms = jiffies_to_msecs(delta_jiffies);
+ atomic64_set(&misc_stats->max_isr_time_ms, delta_ms);
+ atomic64_set(&misc_stats->corr_work_done, cur_work_done);
}
- return wq_work_done;
+
+ return cur_work_done;
}
static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
{
- const int tag = scsi_cmd_to_rq(sc)->tag;
+ struct request *const rq = scsi_cmd_to_rq(sc);
struct fnic *fnic = data;
struct fnic_io_req *io_req;
unsigned long flags = 0;
- spinlock_t *io_lock;
unsigned long start_time = 0;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+ uint16_t hwq = 0;
+ int tag;
+ int mqtag;
- io_lock = fnic_io_lock_tag(fnic, tag);
- spin_lock_irqsave(io_lock, flags);
+ mqtag = blk_mq_unique_tag(rq);
+ hwq = blk_mq_unique_tag_to_hwq(mqtag);
+ tag = blk_mq_unique_tag_to_tag(mqtag);
+
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+
+ fnic->sw_copy_wq[hwq].io_req_table[tag] = NULL;
io_req = fnic_priv(sc)->io_req;
+ if (!io_req) {
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d mqtag: 0x%x tag: 0x%x flags: 0x%x No ioreq. Returning\n",
+ hwq, mqtag, tag, fnic_priv(sc)->flags);
+ return true;
+ }
+
if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
!(fnic_priv(sc)->flags & FNIC_DEV_RST_DONE)) {
/*
@@ -1379,20 +1449,16 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
complete(io_req->dr_done);
else if (io_req && io_req->abts_done)
complete(io_req->abts_done);
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
} else if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
- if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
- goto cleanup_scsi_cmd;
- }
fnic_priv(sc)->io_req = NULL;
-
- spin_unlock_irqrestore(io_lock, flags);
+ io_req->sc = NULL;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
/*
* If there is a scsi_cmnd associated with this io_req, then
@@ -1402,23 +1468,16 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
-cleanup_scsi_cmd:
sc->result = DID_TRANSPORT_DISRUPTED << 16;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "fnic_cleanup_io: tag:0x%x : sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
- tag, sc, jiffies - start_time);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "mqtag:0x%x tag: 0x%x sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
+ mqtag, tag, sc, (jiffies - start_time));
if (atomic64_read(&fnic->io_cmpl_skip))
atomic64_dec(&fnic->io_cmpl_skip);
else
atomic64_inc(&fnic_stats->io_stats.io_completions);
- /* Complete the command to SCSI */
- if (!(fnic_priv(sc)->flags & FNIC_IO_ISSUED))
- shost_printk(KERN_ERR, fnic->lport->host,
- "Calling done for IO not issued to fw: tag:0x%x sc:0x%p\n",
- tag, sc);
-
FNIC_TRACE(fnic_cleanup_io,
sc->device->host->host_no, tag, sc,
jiffies_to_msecs(jiffies - start_time),
@@ -1447,8 +1506,8 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
struct fnic_io_req *io_req;
struct scsi_cmnd *sc;
unsigned long flags;
- spinlock_t *io_lock;
unsigned long start_time = 0;
+ uint16_t hwq;
/* get the tag reference */
fcpio_tag_id_dec(&desc->hdr.tag, &id);
@@ -1461,8 +1520,8 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
if (!sc)
return;
- io_lock = fnic_io_lock_hash(fnic, sc);
- spin_lock_irqsave(io_lock, flags);
+ hwq = blk_mq_unique_tag_to_hwq(id);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
/* Get the IO context which this desc refers to */
io_req = fnic_priv(sc)->io_req;
@@ -1470,13 +1529,15 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
/* fnic interrupts are turned off by now */
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
goto wq_copy_cleanup_scsi_cmd;
}
fnic_priv(sc)->io_req = NULL;
+ io_req->sc = NULL;
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(id)] = NULL;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
start_time = io_req->start_time;
fnic_release_ioreq_buf(fnic, io_req, sc);
@@ -1484,7 +1545,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
wq_copy_cleanup_scsi_cmd:
sc->result = DID_NO_CONNECT << 16;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "wq_copy_cleanup_handler:"
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num, "wq_copy_cleanup_handler:"
" DID_NO_CONNECT\n");
FNIC_TRACE(fnic_wq_copy_cleanup_handler,
@@ -1500,31 +1561,31 @@ wq_copy_cleanup_scsi_cmd:
static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
u32 task_req, u8 *fc_lun,
- struct fnic_io_req *io_req)
+ struct fnic_io_req *io_req,
+ unsigned int hwq)
{
- struct vnic_wq_copy *wq = &fnic->wq_copy[0];
- struct Scsi_Host *host = fnic->lport->host;
+ struct vnic_wq_copy *wq = &fnic->hw_copy_wq[hwq];
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
unsigned long flags;
- spin_lock_irqsave(host->host_lock, flags);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
if (unlikely(fnic_chk_state_flags_locked(fnic,
FNIC_FLAGS_IO_BLOCKED))) {
- spin_unlock_irqrestore(host->host_lock, flags);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return 1;
} else
atomic_inc(&fnic->in_flight);
- spin_unlock_irqrestore(host->host_lock, flags);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
- if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
- free_wq_copy_descs(fnic, wq);
+ if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[hwq])
+ free_wq_copy_descs(fnic, wq, hwq);
if (!vnic_wq_copy_desc_avail(wq)) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic_dec(&fnic->in_flight);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic_queue_abort_io_req: failure: no descriptors\n");
atomic64_inc(&misc_stats->abts_cpwq_alloc_failures);
return 1;
@@ -1539,7 +1600,7 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs,
atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs));
- spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic_dec(&fnic->in_flight);
return 0;
@@ -1553,33 +1614,36 @@ struct fnic_rport_abort_io_iter_data {
static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
{
+ struct request *const rq = scsi_cmd_to_rq(sc);
struct fnic_rport_abort_io_iter_data *iter_data = data;
struct fnic *fnic = iter_data->fnic;
- int abt_tag = scsi_cmd_to_rq(sc)->tag;
+ int abt_tag = 0;
struct fnic_io_req *io_req;
- spinlock_t *io_lock;
unsigned long flags;
struct reset_stats *reset_stats = &fnic->fnic_stats.reset_stats;
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
struct scsi_lun fc_lun;
enum fnic_ioreq_state old_ioreq_state;
+ uint16_t hwq = 0;
- io_lock = fnic_io_lock_tag(fnic, abt_tag);
- spin_lock_irqsave(io_lock, flags);
+ abt_tag = blk_mq_unique_tag(rq);
+ hwq = blk_mq_unique_tag_to_hwq(abt_tag);
+
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req || io_req->port_id != iter_data->port_id) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
!(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED)) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "fnic_rport_exch_reset dev rst not pending sc 0x%p\n",
- sc);
- spin_unlock_irqrestore(io_lock, flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d abt_tag: 0x%x flags: 0x%x Device reset is not pending\n",
+ hwq, abt_tag, fnic_priv(sc)->flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
@@ -1588,7 +1652,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
* belongs to rport that went away
*/
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
if (io_req->abts_done) {
@@ -1612,38 +1676,41 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
atomic64_inc(&reset_stats->device_reset_terminates);
abt_tag |= FNIC_TAG_DEV_RST;
}
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic_rport_exch_reset dev rst sc 0x%p\n", sc);
BUG_ON(io_req->abts_done);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic_rport_reset_exch: Issuing abts\n");
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
if (fnic_queue_abort_io_req(fnic, abt_tag,
FCPIO_ITMF_ABT_TASK_TERM,
- fc_lun.scsi_lun, io_req)) {
+ fc_lun.scsi_lun, io_req, hwq)) {
/*
* Revert the cmd state back to old state, if
* it hasn't changed in between. This cmd will get
* aborted later by scsi_eh, or cleaned up during
* lun reset
*/
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d abt_tag: 0x%x flags: 0x%x Queuing abort failed\n",
+ hwq, abt_tag, fnic_priv(sc)->flags);
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING)
fnic_priv(sc)->state = old_ioreq_state;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
} else {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET)
fnic_priv(sc)->flags |= FNIC_DEV_RST_TERM_ISSUED;
else
fnic_priv(sc)->flags |= FNIC_IO_INTERNAL_TERM_ISSUED;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic64_inc(&term_stats->terminates);
iter_data->term_cnt++;
}
@@ -1660,7 +1727,7 @@ static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
};
FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host,
+ fnic->lport->host, fnic->fnic_num,
"fnic_rport_exch_reset called portid 0x%06x\n",
port_id);
@@ -1697,9 +1764,8 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
return;
}
fnic = lport_priv(lport);
- FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host, "fnic_terminate_rport_io called"
- " wwpn 0x%llx, wwnn0x%llx, rport 0x%p, portid 0x%06x\n",
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "wwpn 0x%llx, wwnn0x%llx, rport 0x%p, portid 0x%06x\n",
rport->port_name, rport->node_name, rport,
rport->port_id);
@@ -1721,7 +1787,6 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
struct fnic *fnic;
struct fnic_io_req *io_req = NULL;
struct fc_rport *rport;
- spinlock_t *io_lock;
unsigned long flags;
unsigned long start_time = 0;
int ret = SUCCESS;
@@ -1731,8 +1796,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
struct abort_stats *abts_stats;
struct terminate_stats *term_stats;
enum fnic_ioreq_state old_ioreq_state;
- const int tag = rq->tag;
+ int mqtag;
unsigned long abt_issued_time;
+ uint16_t hwq = 0;
+
DECLARE_COMPLETION_ONSTACK(tm_done);
/* Wait for rport to unblock */
@@ -1742,23 +1809,25 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
lp = shost_priv(sc->device->host);
fnic = lport_priv(lp);
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
fnic_stats = &fnic->fnic_stats;
abts_stats = &fnic->fnic_stats.abts_stats;
term_stats = &fnic->fnic_stats.term_stats;
rport = starget_to_rport(scsi_target(sc->device));
- FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host,
- "Abort Cmd called FCID 0x%x, LUN 0x%llx TAG %x flags %x\n",
- rport->port_id, sc->device->lun, tag, fnic_priv(sc)->flags);
+ mqtag = blk_mq_unique_tag(rq);
+ hwq = blk_mq_unique_tag_to_hwq(mqtag);
fnic_priv(sc)->flags = FNIC_NO_FLAGS;
if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
ret = FAILED;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_abort_cmd_end;
}
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
/*
* Avoid a race between SCSI issuing the abort and the device
* completing the command.
@@ -1771,18 +1840,17 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
*
* .io_req will not be cleared except while holding io_req_lock.
*/
- io_lock = fnic_io_lock_hash(fnic, sc);
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
goto fnic_abort_cmd_end;
}
io_req->abts_done = &tm_done;
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
goto wait_pending;
}
@@ -1802,8 +1870,9 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
else
atomic64_inc(&abts_stats->abort_issued_greater_than_60_sec);
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
- "CBD Opcode: %02x Abort issued time: %lu msec\n", sc->cmnd[0], abt_issued_time);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "CDB Opcode: 0x%02x Abort issued time: %lu msec\n",
+ sc->cmnd[0], abt_issued_time);
/*
* Command is still pending, need to abort it
* If the firmware completes the command after this point,
@@ -1814,7 +1883,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
fnic_priv(sc)->abts_status = FCPIO_INVALID_CODE;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
/*
* Check readiness of the remote port. If the path to remote
@@ -1831,15 +1900,15 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
- if (fnic_queue_abort_io_req(fnic, tag, task_req, fc_lun.scsi_lun,
- io_req)) {
- spin_lock_irqsave(io_lock, flags);
+ if (fnic_queue_abort_io_req(fnic, mqtag, task_req, fc_lun.scsi_lun,
+ io_req, hwq)) {
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING)
fnic_priv(sc)->state = old_ioreq_state;
io_req = fnic_priv(sc)->io_req;
if (io_req)
io_req->abts_done = NULL;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
ret = FAILED;
goto fnic_abort_cmd_end;
}
@@ -1863,12 +1932,12 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
fnic->config.ed_tov));
/* Check the abort status */
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
atomic64_inc(&fnic_stats->io_stats.ioreq_null);
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_IO_ABT_TERM_REQ_NULL;
ret = FAILED;
goto fnic_abort_cmd_end;
@@ -1877,7 +1946,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
/* fw did not complete abort, timed out */
if (fnic_priv(sc)->abts_status == FCPIO_INVALID_CODE) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if (task_req == FCPIO_ITMF_ABT_TASK) {
atomic64_inc(&abts_stats->abort_drv_timeouts);
} else {
@@ -1891,9 +1960,9 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
/* IO out of order */
if (!(fnic_priv(sc)->flags & (FNIC_IO_ABORTED | FNIC_IO_DONE))) {
- spin_unlock_irqrestore(io_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Issuing Host reset due to out of order IO\n");
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Issuing host reset due to out of order IO\n");
ret = FAILED;
goto fnic_abort_cmd_end;
@@ -1907,15 +1976,18 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
* free the io_req if successful. If abort fails,
* Device reset will clean the I/O.
*/
- if (fnic_priv(sc)->abts_status == FCPIO_SUCCESS) {
+ if (fnic_priv(sc)->abts_status == FCPIO_SUCCESS ||
+ (fnic_priv(sc)->abts_status == FCPIO_ABORTED)) {
fnic_priv(sc)->io_req = NULL;
+ io_req->sc = NULL;
} else {
ret = FAILED;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
goto fnic_abort_cmd_end;
}
- spin_unlock_irqrestore(io_lock, flags);
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] = NULL;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
@@ -1930,14 +2002,14 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
atomic64_inc(&fnic_stats->io_stats.io_completions);
fnic_abort_cmd_end:
- FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no, tag, sc,
+ FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no, mqtag, sc,
jiffies_to_msecs(jiffies - start_time),
0, ((u64)sc->cmnd[0] << 32 |
(u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
(u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
fnic_flags_and_state(sc));
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Returning from abort cmd type %x %s\n", task_req,
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
@@ -1948,33 +2020,34 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
struct scsi_cmnd *sc,
struct fnic_io_req *io_req)
{
- struct vnic_wq_copy *wq = &fnic->wq_copy[0];
- struct Scsi_Host *host = fnic->lport->host;
+ struct vnic_wq_copy *wq;
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
struct scsi_lun fc_lun;
int ret = 0;
- unsigned long intr_flags;
- unsigned int tag = scsi_cmd_to_rq(sc)->tag;
+ unsigned long flags;
+ uint16_t hwq = 0;
+ uint32_t tag = 0;
- if (tag == SCSI_NO_TAG)
- tag = io_req->tag;
+ tag = io_req->tag;
+ hwq = blk_mq_unique_tag_to_hwq(tag);
+ wq = &fnic->hw_copy_wq[hwq];
- spin_lock_irqsave(host->host_lock, intr_flags);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
if (unlikely(fnic_chk_state_flags_locked(fnic,
FNIC_FLAGS_IO_BLOCKED))) {
- spin_unlock_irqrestore(host->host_lock, intr_flags);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return FAILED;
} else
atomic_inc(&fnic->in_flight);
- spin_unlock_irqrestore(host->host_lock, intr_flags);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- spin_lock_irqsave(&fnic->wq_copy_lock[0], intr_flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
- if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
- free_wq_copy_descs(fnic, wq);
+ if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[hwq])
+ free_wq_copy_descs(fnic, wq, hwq);
if (!vnic_wq_copy_desc_avail(wq)) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"queue_dr_io_req failure - no descriptors\n");
atomic64_inc(&misc_stats->devrst_cpwq_alloc_failures);
ret = -EAGAIN;
@@ -1997,7 +2070,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs));
lr_io_req_end:
- spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic_dec(&fnic->in_flight);
return ret;
@@ -2012,12 +2085,13 @@ struct fnic_pending_aborts_iter_data {
static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
{
+ struct request *const rq = scsi_cmd_to_rq(sc);
struct fnic_pending_aborts_iter_data *iter_data = data;
struct fnic *fnic = iter_data->fnic;
struct scsi_device *lun_dev = iter_data->lun_dev;
- int abt_tag = scsi_cmd_to_rq(sc)->tag;
+ unsigned long abt_tag = 0;
+ uint16_t hwq = 0;
struct fnic_io_req *io_req;
- spinlock_t *io_lock;
unsigned long flags;
struct scsi_lun fc_lun;
DECLARE_COMPLETION_ONSTACK(tm_done);
@@ -2026,11 +2100,13 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
if (sc == iter_data->lr_sc || sc->device != lun_dev)
return true;
- io_lock = fnic_io_lock_tag(fnic, abt_tag);
- spin_lock_irqsave(io_lock, flags);
+ abt_tag = blk_mq_unique_tag(rq);
+ hwq = blk_mq_unique_tag_to_hwq(abt_tag);
+
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
@@ -2038,20 +2114,19 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
* Found IO that is still pending with firmware and
* belongs to the LUN that we are resetting
*/
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Found IO in %s on lun\n",
fnic_ioreq_state_to_str(fnic_priv(sc)->state));
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
(!(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED))) {
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
- "%s dev rst not pending sc 0x%p\n", __func__,
- sc);
- spin_unlock_irqrestore(io_lock, flags);
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "dev rst not pending sc 0x%p\n", sc);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
@@ -2072,35 +2147,37 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
BUG_ON(io_req->abts_done);
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
- abt_tag |= FNIC_TAG_DEV_RST;
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
- "%s: dev rst sc 0x%p\n", __func__, sc);
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "dev rst sc 0x%p\n", sc);
}
fnic_priv(sc)->abts_status = FCPIO_INVALID_CODE;
io_req->abts_done = &tm_done;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
if (fnic_queue_abort_io_req(fnic, abt_tag,
FCPIO_ITMF_ABT_TASK_TERM,
- fc_lun.scsi_lun, io_req)) {
- spin_lock_irqsave(io_lock, flags);
+ fc_lun.scsi_lun, io_req, hwq)) {
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (io_req)
io_req->abts_done = NULL;
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING)
fnic_priv(sc)->state = old_ioreq_state;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
iter_data->ret = FAILED;
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d abt_tag: 0x%lx Abort could not be queued\n",
+ hwq, abt_tag);
return false;
} else {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET)
fnic_priv(sc)->flags |= FNIC_DEV_RST_TERM_ISSUED;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
}
fnic_priv(sc)->flags |= FNIC_IO_INTERNAL_TERM_ISSUED;
@@ -2108,10 +2185,10 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
(fnic->config.ed_tov));
/* Recheck cmd state to check if it is now aborted */
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_IO_ABT_TERM_REQ_NULL;
return true;
}
@@ -2120,7 +2197,7 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
/* if abort is still pending with fw, fail */
if (fnic_priv(sc)->abts_status == FCPIO_INVALID_CODE) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_IO_ABT_TERM_DONE;
iter_data->ret = FAILED;
return false;
@@ -2128,9 +2205,11 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
fnic_priv(sc)->state = FNIC_IOREQ_ABTS_COMPLETE;
/* original sc used for lr is handled by dev reset code */
- if (sc != iter_data->lr_sc)
+ if (sc != iter_data->lr_sc) {
fnic_priv(sc)->io_req = NULL;
- spin_unlock_irqrestore(io_lock, flags);
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(abt_tag)] = NULL;
+ }
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
/* original sc used for lr is handled by dev reset code */
if (sc != iter_data->lr_sc) {
@@ -2182,8 +2261,8 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
ret = 1;
clean_pending_aborts_end:
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
- "%s: exit status: %d\n", __func__, ret);
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "exit status: %d\n", ret);
return ret;
}
@@ -2201,15 +2280,15 @@ int fnic_device_reset(struct scsi_cmnd *sc)
struct fc_rport *rport;
int status;
int ret = FAILED;
- spinlock_t *io_lock;
unsigned long flags;
unsigned long start_time = 0;
struct scsi_lun fc_lun;
struct fnic_stats *fnic_stats;
struct reset_stats *reset_stats;
- int tag = rq->tag;
+ int mqtag = rq->tag;
DECLARE_COMPLETION_ONSTACK(tm_done);
bool new_sc = 0;
+ uint16_t hwq = 0;
/* Wait for rport to unblock */
fc_block_scsi_eh(sc);
@@ -2224,9 +2303,10 @@ int fnic_device_reset(struct scsi_cmnd *sc)
atomic64_inc(&reset_stats->device_resets);
rport = starget_to_rport(scsi_target(sc->device));
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Device reset called FCID 0x%x, LUN 0x%llx sc 0x%p\n",
- rport->port_id, sc->device->lun, sc);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "fcid: 0x%x lun: 0x%llx hwq: %d mqtag: 0x%x flags: 0x%x Device reset\n",
+ rport->port_id, sc->device->lun, hwq, mqtag,
+ fnic_priv(sc)->flags);
if (lp->state != LPORT_ST_READY || !(lp->link_up))
goto fnic_device_reset_end;
@@ -2239,7 +2319,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
fnic_priv(sc)->flags = FNIC_DEVICE_RESET;
- if (unlikely(tag < 0)) {
+ if (unlikely(mqtag < 0)) {
/*
* For device reset issued through sg3utils, we let
* only one LUN_RESET to go through and use a special
@@ -2248,17 +2328,14 @@ int fnic_device_reset(struct scsi_cmnd *sc)
* allocated by mid layer.
*/
mutex_lock(&fnic->sgreset_mutex);
- tag = fnic->fnic_max_tag_id;
+ mqtag = fnic->fnic_max_tag_id;
new_sc = 1;
- fnic->sgreset_sc = sc;
- io_lock = &fnic->sgreset_lock;
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
- "fcid: 0x%x lun: 0x%llx flags: 0x%x tag: 0x%x Issuing sgreset\n",
- rport->port_id, sc->device->lun, fnic_priv(sc)->flags, tag);
- } else
- io_lock = fnic_io_lock_hash(fnic, sc);
+ } else {
+ mqtag = blk_mq_unique_tag(rq);
+ hwq = blk_mq_unique_tag_to_hwq(mqtag);
+ }
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
/*
@@ -2268,36 +2345,43 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if (!io_req) {
io_req = mempool_alloc(fnic->io_req_pool, GFP_ATOMIC);
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
goto fnic_device_reset_end;
}
memset(io_req, 0, sizeof(*io_req));
io_req->port_id = rport->port_id;
- io_req->tag = tag;
- io_req->sc = sc;
+ io_req->tag = mqtag;
fnic_priv(sc)->io_req = io_req;
+ io_req->sc = sc;
+
+ if (fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] != NULL)
+ WARN(1, "fnic<%d>: %s: tag 0x%x already exists\n",
+ fnic->fnic_num, __func__, blk_mq_unique_tag_to_tag(mqtag));
+
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] =
+ io_req;
}
io_req->dr_done = &tm_done;
fnic_priv(sc)->state = FNIC_IOREQ_CMD_PENDING;
fnic_priv(sc)->lr_status = FCPIO_INVALID_CODE;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "TAG %x\n", tag);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num, "TAG %x\n", mqtag);
/*
* issue the device reset, if enqueue failed, clean up the ioreq
* and break assoc with scsi cmd
*/
if (fnic_queue_dr_io_req(fnic, sc, io_req)) {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (io_req)
io_req->dr_done = NULL;
goto fnic_device_reset_clean;
}
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_DEV_RST_ISSUED;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
/*
* Wait on the local completion for LUN reset. The io_req may be
@@ -2306,12 +2390,12 @@ int fnic_device_reset(struct scsi_cmnd *sc)
wait_for_completion_timeout(&tm_done,
msecs_to_jiffies(FNIC_LUN_RESET_TIMEOUT));
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "io_req is null tag 0x%x sc 0x%p\n", tag, sc);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "io_req is null mqtag 0x%x sc 0x%p\n", mqtag, sc);
goto fnic_device_reset_end;
}
io_req->dr_done = NULL;
@@ -2324,44 +2408,44 @@ int fnic_device_reset(struct scsi_cmnd *sc)
*/
if (status == FCPIO_INVALID_CODE) {
atomic64_inc(&reset_stats->device_reset_timeouts);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Device reset timed out\n");
fnic_priv(sc)->flags |= FNIC_DEV_RST_TIMED_OUT;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
int_to_scsilun(sc->device->lun, &fc_lun);
/*
* Issue abort and terminate on device reset request.
* If q'ing of terminate fails, retry it after a delay.
*/
while (1) {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
if (fnic_priv(sc)->flags & FNIC_DEV_RST_TERM_ISSUED) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
break;
}
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if (fnic_queue_abort_io_req(fnic,
- tag | FNIC_TAG_DEV_RST,
+ mqtag | FNIC_TAG_DEV_RST,
FCPIO_ITMF_ABT_TASK_TERM,
- fc_lun.scsi_lun, io_req)) {
+ fc_lun.scsi_lun, io_req, hwq)) {
wait_for_completion_timeout(&tm_done,
msecs_to_jiffies(FNIC_ABT_TERM_DELAY_TIMEOUT));
} else {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_DEV_RST_TERM_ISSUED;
fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
io_req->abts_done = &tm_done;
- spin_unlock_irqrestore(io_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Abort and terminate issued on Device reset "
- "tag 0x%x sc 0x%p\n", tag, sc);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "Abort and terminate issued on Device reset mqtag 0x%x sc 0x%p\n",
+ mqtag, sc);
break;
}
}
while (1) {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
if (!(fnic_priv(sc)->flags & FNIC_DEV_RST_DONE)) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
wait_for_completion_timeout(&tm_done,
msecs_to_jiffies(FNIC_LUN_RESET_TIMEOUT));
break;
@@ -2372,14 +2456,14 @@ int fnic_device_reset(struct scsi_cmnd *sc)
}
}
} else {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
}
/* Completed, but not successful, clean up the io_req, return fail */
if (status != FCPIO_SUCCESS) {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host,
+ fnic->lport->host, fnic->fnic_num,
"Device reset completed - failed\n");
io_req = fnic_priv(sc)->io_req;
goto fnic_device_reset_clean;
@@ -2393,26 +2477,29 @@ int fnic_device_reset(struct scsi_cmnd *sc)
* succeeds
*/
if (fnic_clean_pending_aborts(fnic, sc, new_sc)) {
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Device reset failed"
" since could not abort all IOs\n");
goto fnic_device_reset_clean;
}
/* Clean lun reset command */
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (io_req)
/* Completed, and successful */
ret = SUCCESS;
fnic_device_reset_clean:
- if (io_req)
+ if (io_req) {
fnic_priv(sc)->io_req = NULL;
+ io_req->sc = NULL;
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(io_req->tag)] = NULL;
+ }
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if (io_req) {
start_time = io_req->start_time;
@@ -2433,7 +2520,7 @@ fnic_device_reset_end:
mutex_unlock(&fnic->sgreset_mutex);
}
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Returning from device reset %s\n",
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
@@ -2456,8 +2543,8 @@ int fnic_reset(struct Scsi_Host *shost)
fnic = lport_priv(lp);
reset_stats = &fnic->fnic_stats.reset_stats;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "fnic_reset called\n");
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Issuing fnic reset\n");
atomic64_inc(&reset_stats->fnic_resets);
@@ -2467,10 +2554,9 @@ int fnic_reset(struct Scsi_Host *shost)
*/
ret = fc_lport_reset(lp);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Returning from fnic reset %s\n",
- (ret == 0) ?
- "SUCCESS" : "FAILED");
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Returning from fnic reset with: %s\n",
+ (ret == 0) ? "SUCCESS" : "FAILED");
if (ret == 0)
atomic64_inc(&reset_stats->fnic_reset_completions);
@@ -2503,7 +2589,7 @@ int fnic_host_reset(struct scsi_cmnd *sc)
fnic->internal_reset_inprogress = true;
} else {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"host reset in progress skipping another host reset\n");
return SUCCESS;
}
@@ -2578,7 +2664,7 @@ retry_fw_reset:
spin_lock_irqsave(&fnic->fnic_lock, flags);
fnic->remove_wait = NULL;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"fnic_scsi_abort_io %s\n",
(fnic->state == FNIC_IN_ETH_MODE) ?
"SUCCESS" : "FAILED");
@@ -2652,12 +2738,17 @@ call_fc_exch_mgr_reset:
static bool fnic_abts_pending_iter(struct scsi_cmnd *sc, void *data)
{
+ struct request *const rq = scsi_cmd_to_rq(sc);
struct fnic_pending_aborts_iter_data *iter_data = data;
struct fnic *fnic = iter_data->fnic;
int cmd_state;
struct fnic_io_req *io_req;
- spinlock_t *io_lock;
unsigned long flags;
+ uint16_t hwq = 0;
+ int tag;
+
+ tag = blk_mq_unique_tag(rq);
+ hwq = blk_mq_unique_tag_to_hwq(tag);
/*
* ignore this lun reset cmd or cmds that do not belong to
@@ -2668,12 +2759,11 @@ static bool fnic_abts_pending_iter(struct scsi_cmnd *sc, void *data)
if (iter_data->lun_dev && sc->device != iter_data->lun_dev)
return true;
- io_lock = fnic_io_lock_hash(fnic, sc);
- spin_lock_irqsave(io_lock, flags);
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
@@ -2681,11 +2771,12 @@ static bool fnic_abts_pending_iter(struct scsi_cmnd *sc, void *data)
* Found IO that is still pending with firmware and
* belongs to the LUN that we are resetting
*/
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
- "Found IO in %s on lun\n",
- fnic_ioreq_state_to_str(fnic_priv(sc)->state));
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "hwq: %d tag: 0x%x Found IO in state: %s on lun\n",
+ hwq, tag,
+ fnic_ioreq_state_to_str(fnic_priv(sc)->state));
cmd_state = fnic_priv(sc)->state;
- spin_unlock_irqrestore(io_lock, flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
if (cmd_state == FNIC_IOREQ_ABTS_PENDING)
iter_data->ret = 1;
diff --git a/drivers/scsi/fnic/fnic_stats.h b/drivers/scsi/fnic/fnic_stats.h
index bdf639eef8..9d7f98c452 100644
--- a/drivers/scsi/fnic/fnic_stats.h
+++ b/drivers/scsi/fnic/fnic_stats.h
@@ -2,6 +2,7 @@
/* Copyright 2013 Cisco Systems, Inc. All rights reserved. */
#ifndef _FNIC_STATS_H_
#define _FNIC_STATS_H_
+#define FNIC_MQ_MAX_QUEUES 64
struct stats_timestamps {
struct timespec64 last_reset_time;
@@ -26,6 +27,7 @@ struct io_path_stats {
atomic64_t io_btw_10000_to_30000_msec;
atomic64_t io_greater_than_30000_msec;
atomic64_t current_max_io_time;
+ atomic64_t ios[FNIC_MQ_MAX_QUEUES];
};
struct abort_stats {
@@ -103,6 +105,7 @@ struct misc_stats {
atomic64_t rport_not_ready;
atomic64_t frame_errors;
atomic64_t current_port_speed;
+ atomic64_t intx_dummy;
};
struct fnic_stats {
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index be0d7c57b2..aaa4ea02fb 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -204,6 +204,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
int len = 0;
int buf_size = debug->buf_size;
struct timespec64 val1, val2;
+ int i = 0;
ktime_get_real_ts64(&val1);
len = scnprintf(debug->debug_buffer + len, buf_size - len,
@@ -267,6 +268,16 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
(u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
len += scnprintf(debug->debug_buffer + len, buf_size - len,
+ "------------------------------------------\n"
+ "\t\tIO Queues and cumulative IOs\n"
+ "------------------------------------------\n");
+
+ for (i = 0; i < FNIC_MQ_MAX_QUEUES; i++) {
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
+ "Q:%d -> %lld\n", i, (u64)atomic64_read(&stats->io_stats.ios[i]));
+ }
+
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\nCurrent Max IO time : %lld\n",
(u64)atomic64_read(&stats->io_stats.current_max_io_time));
diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c
index 3e5b437c04..e0b173cc9d 100644
--- a/drivers/scsi/fnic/vnic_dev.c
+++ b/drivers/scsi/fnic/vnic_dev.c
@@ -143,6 +143,10 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset;
}
+ pr_info("res_type_wq: %d res_type_rq: %d res_type_cq: %d res_type_intr_ctrl: %d\n",
+ vdev->res[RES_TYPE_WQ].count, vdev->res[RES_TYPE_RQ].count,
+ vdev->res[RES_TYPE_CQ].count, vdev->res[RES_TYPE_INTR_CTRL].count);
+
return 0;
}
diff --git a/drivers/scsi/fnic/vnic_scsi.h b/drivers/scsi/fnic/vnic_scsi.h
index 4e12f7b32d..f715f7942b 100644
--- a/drivers/scsi/fnic/vnic_scsi.h
+++ b/drivers/scsi/fnic/vnic_scsi.h
@@ -26,7 +26,7 @@
#define VNIC_FNIC_RATOV_MAX 255000
#define VNIC_FNIC_MAXDATAFIELDSIZE_MIN 256
-#define VNIC_FNIC_MAXDATAFIELDSIZE_MAX 2112
+#define VNIC_FNIC_MAXDATAFIELDSIZE_MAX 2048
#define VNIC_FNIC_FLOGI_RETRIES_MIN 0
#define VNIC_FNIC_FLOGI_RETRIES_MAX 0xffffffff
@@ -55,7 +55,7 @@
#define VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX 255
#define VNIC_FNIC_LUNS_PER_TARGET_MIN 1
-#define VNIC_FNIC_LUNS_PER_TARGET_MAX 1024
+#define VNIC_FNIC_LUNS_PER_TARGET_MAX 4096
/* Device-specific region: scsi configuration */
struct vnic_fc_config {
@@ -79,10 +79,19 @@ struct vnic_fc_config {
u16 ra_tov;
u16 intr_timer;
u8 intr_timer_type;
+ u8 intr_mode;
+ u8 lun_queue_depth;
+ u8 io_timeout_retry;
+ u16 wq_copy_count;
};
#define VFCF_FCP_SEQ_LVL_ERR 0x1 /* Enable FCP-2 Error Recovery */
#define VFCF_PERBI 0x2 /* persistent binding info available */
#define VFCF_FIP_CAPABLE 0x4 /* firmware can handle FIP */
+#define VFCF_FC_INITIATOR 0x20 /* FC Initiator Mode */
+#define VFCF_FC_TARGET 0x40 /* FC Target Mode */
+#define VFCF_FC_NVME_INITIATOR 0x80 /* FC-NVMe Initiator Mode */
+#define VFCF_FC_NVME_TARGET 0x100 /* FC-NVMe Target Mode */
+
#endif /* _VNIC_SCSI_H_ */
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 1abc62b07d..05c38e43f1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1792,7 +1792,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
if (dev_is_sata(device)) {
struct ata_link *link = &device->sata_dev.ap->link;
- rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT,
+ rc = ata_wait_after_reset(link, jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT,
smp_ata_check_ready_type);
} else {
msleep(2000);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 92c440f2e3..46d0b3a0e1 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1464,7 +1464,7 @@ static void ibmvfc_gather_partition_info(struct ibmvfc_host *vhost)
name = of_get_property(rootdn, "ibm,partition-name", NULL);
if (name)
- strncpy(vhost->partition_name, name, sizeof(vhost->partition_name));
+ strscpy(vhost->partition_name, name, sizeof(vhost->partition_name));
num = of_get_property(rootdn, "ibm,partition-no", NULL);
if (num)
vhost->partition_number = *num;
@@ -1513,13 +1513,15 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
login_info->async.len = cpu_to_be32(async_crq->size *
sizeof(*async_crq->msgs.async));
- strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
- strncpy(login_info->device_name,
- dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
+ strscpy(login_info->partition_name, vhost->partition_name,
+ sizeof(login_info->partition_name));
+
+ strscpy(login_info->device_name,
+ dev_name(&vhost->host->shost_gendev), sizeof(login_info->device_name));
location = of_get_property(of_node, "ibm,loc-code", NULL);
location = location ? location : dev_name(vhost->dev);
- strncpy(login_info->drc_name, location, IBMVFC_MAX_NAME);
+ strscpy(login_info->drc_name, location, sizeof(login_info->drc_name));
}
/**
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 5959929961..71f3e95635 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -266,7 +266,7 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
dev_info(hostdata->dev, "SRP_VERSION: %s\n", SRP_VERSION);
strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
- strncpy(hostdata->madapter_info.partition_name, partition_name,
+ strscpy(hostdata->madapter_info.partition_name, partition_name,
sizeof(hostdata->madapter_info.partition_name));
hostdata->madapter_info.partition_number =
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 2a50fda3a6..625fd547ee 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -371,7 +371,6 @@ static u16 initio_se2_rd(unsigned long base, u8 addr)
*/
static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
{
- u8 rb;
u8 instr;
int i;
@@ -400,7 +399,7 @@ static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
udelay(30);
outb(SE2CS, base + TUL_NVRAM); /* -CLK */
udelay(30);
- if ((rb = inb(base + TUL_NVRAM)) & SE2DI)
+ if (inb(base + TUL_NVRAM) & SE2DI)
break; /* write complete */
}
outb(0, base + TUL_NVRAM); /* -CS */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 81e3d464d1..3819f7c427 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -77,7 +77,6 @@
static LIST_HEAD(ipr_ioa_head);
static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;
static unsigned int ipr_max_speed = 1;
-static int ipr_testmode = 0;
static unsigned int ipr_fastfail = 0;
static unsigned int ipr_transop_timeout = 0;
static unsigned int ipr_debug = 0;
@@ -193,8 +192,6 @@ module_param_named(max_speed, ipr_max_speed, uint, 0);
MODULE_PARM_DESC(max_speed, "Maximum bus speed (0-2). Default: 1=U160. Speeds: 0=80 MB/s, 1=U160, 2=U320");
module_param_named(log_level, ipr_log_level, uint, 0);
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
-module_param_named(testmode, ipr_testmode, int, 0);
-MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");
module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
@@ -6416,45 +6413,6 @@ static const struct scsi_host_template driver_template = {
.proc_name = IPR_NAME,
};
-#ifdef CONFIG_PPC_PSERIES
-static const u16 ipr_blocked_processors[] = {
- PVR_NORTHSTAR,
- PVR_PULSAR,
- PVR_POWER4,
- PVR_ICESTAR,
- PVR_SSTAR,
- PVR_POWER4p,
- PVR_630,
- PVR_630p
-};
-
-/**
- * ipr_invalid_adapter - Determine if this adapter is supported on this hardware
- * @ioa_cfg: ioa cfg struct
- *
- * Adapters that use Gemstone revision < 3.1 do not work reliably on
- * certain pSeries hardware. This function determines if the given
- * adapter is in one of these confgurations or not.
- *
- * Return value:
- * 1 if adapter is not supported / 0 if adapter is supported
- **/
-static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
-{
- int i;
-
- if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
- for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++) {
- if (pvr_version_is(ipr_blocked_processors[i]))
- return 1;
- }
- }
- return 0;
-}
-#else
-#define ipr_invalid_adapter(ioa_cfg) 0
-#endif
-
/**
* ipr_ioa_bringdown_done - IOA bring down completion.
* @ipr_cmd: ipr command struct
@@ -7385,19 +7343,6 @@ static int ipr_ioafp_page0_inquiry(struct ipr_cmnd *ipr_cmd)
type[4] = '\0';
ioa_cfg->type = simple_strtoul((char *)type, NULL, 16);
- if (ipr_invalid_adapter(ioa_cfg)) {
- dev_err(&ioa_cfg->pdev->dev,
- "Adapter not supported in this hardware configuration.\n");
-
- if (!ipr_testmode) {
- ioa_cfg->reset_retries += IPR_NUM_RESET_RELOAD_RETRIES;
- ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
- list_add_tail(&ipr_cmd->queue,
- &ioa_cfg->hrrq->hrrq_free_q);
- return IPR_RC_JOB_RETURN;
- }
- }
-
ipr_cmd->job_step = ipr_ioafp_page3_inquiry;
ipr_ioafp_inquiry(ipr_cmd, 1, 0,
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 7162a5029b..355a0bc082 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -738,8 +738,7 @@ static enum sci_status sci_io_request_construct_basic_ssp(struct isci_request *i
return SCI_SUCCESS;
}
-enum sci_status sci_task_request_construct_ssp(
- struct isci_request *ireq)
+void sci_task_request_construct_ssp(struct isci_request *ireq)
{
/* Construct the SSP Task SCU Task Context */
scu_ssp_task_request_construct_task_context(ireq);
@@ -748,8 +747,6 @@ enum sci_status sci_task_request_construct_ssp(
sci_task_request_build_ssp_task_iu(ireq);
sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED);
-
- return SCI_SUCCESS;
}
static enum sci_status sci_io_request_construct_basic_sata(struct isci_request *ireq)
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 20b141739e..79ddfffbf7 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -300,7 +300,7 @@ sci_task_request_construct(struct isci_host *ihost,
struct isci_remote_device *idev,
u16 io_tag,
struct isci_request *ireq);
-enum sci_status sci_task_request_construct_ssp(struct isci_request *ireq);
+void sci_task_request_construct_ssp(struct isci_request *ireq);
void sci_smp_request_copy_response(struct isci_request *ireq);
static inline int isci_task_is_ncq_recovery(struct sas_task *task)
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index c514b20293..3a25b1a2c5 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -243,9 +243,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
/* XXX convert to get this from task->tproto like other drivers */
if (dev->dev_type == SAS_END_DEVICE) {
isci_tmf->proto = SAS_PROTOCOL_SSP;
- status = sci_task_request_construct_ssp(ireq);
- if (status != SCI_SUCCESS)
- return NULL;
+ sci_task_request_construct_ssp(ireq);
}
return ireq;
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 0c842fb29a..494a671fb5 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -176,7 +176,7 @@ fail:
return err;
}
-static int esp_jazz_remove(struct platform_device *dev)
+static void esp_jazz_remove(struct platform_device *dev)
{
struct esp *esp = dev_get_drvdata(&dev->dev);
unsigned int irq = esp->host->irq;
@@ -189,8 +189,6 @@ static int esp_jazz_remove(struct platform_device *dev)
esp->command_block_dma);
scsi_host_put(esp->host);
-
- return 0;
}
/* work with hotplug and coldplug */
@@ -198,7 +196,7 @@ MODULE_ALIAS("platform:jazz_esp");
static struct platform_driver esp_jazz_driver = {
.probe = esp_jazz_probe,
- .remove = esp_jazz_remove,
+ .remove_new = esp_jazz_remove,
.driver = {
.name = "jazz_esp",
},
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 05be0810b5..80be3a936d 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -2062,9 +2062,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
sc_cmd->result = (DID_PARITY << 16);
break;
case FC_TIMED_OUT:
- FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml "
+ FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml "
"due to FC_TIMED_OUT\n");
- sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
+ sc_cmd->result = (DID_TIME_OUT << 16);
break;
default:
FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index b1c9107d34..d3a5d6ecdf 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5905,11 +5905,11 @@ LPFC_ATTR_RW(ras_fwlog_level, 0, 0, 4, "Firmware Logging Level");
/*
* lpfc_ras_fwlog_func: Firmware logging enabled on function number
* Default function which has RAS support : 0
- * Value Range is [0..7].
+ * Value Range is [0..3].
* FW logging is a global action and enablement is via a specific
* port.
*/
-LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function");
+LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 3, "Firmware Logging Enabled on Function");
/*
* lpfc_enable_bbcr: Enable BB Credit Recovery
@@ -5954,7 +5954,7 @@ LPFC_ATTR_R(enable_mi, 1, 0, 1, "Enable MI");
* 4 - 255 = vmid support enabled for 4-255 VMs
* Value range is [4,255].
*/
-LPFC_ATTR_RW(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID,
+LPFC_ATTR_R(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID,
"Maximum number of VMs supported");
/*
@@ -5962,7 +5962,7 @@ LPFC_ATTR_RW(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID,
* 0 = Timeout is disabled
* Value range is [0,24].
*/
-LPFC_ATTR_RW(vmid_inactivity_timeout, 4, 0, 24,
+LPFC_ATTR_R(vmid_inactivity_timeout, 4, 0, 24,
"Inactivity timeout in hours");
/*
@@ -5971,7 +5971,7 @@ LPFC_ATTR_RW(vmid_inactivity_timeout, 4, 0, 24,
* 1 = Support is enabled
* Value range is [0,1].
*/
-LPFC_ATTR_RW(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE,
+LPFC_ATTR_R(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE,
LPFC_VMID_APP_HEADER_DISABLE, LPFC_VMID_APP_HEADER_ENABLE,
"Enable App Header VMID support");
@@ -5982,7 +5982,7 @@ LPFC_ATTR_RW(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE,
* 2 = Allow all targets
* Value range is [0,2].
*/
-LPFC_ATTR_RW(vmid_priority_tagging, LPFC_VMID_PRIO_TAG_DISABLE,
+LPFC_ATTR_R(vmid_priority_tagging, LPFC_VMID_PRIO_TAG_DISABLE,
LPFC_VMID_PRIO_TAG_DISABLE,
LPFC_VMID_PRIO_TAG_ALL_TARGETS,
"Enable Priority Tagging VMID support");
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 385e1636f1..4d72320069 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2062,8 +2062,9 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* PLOGI completes to NPort <nlp_DID> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0102 PLOGI completes to NPort x%06x "
- "Data: x%x x%x x%x x%x x%x\n",
- ndlp->nlp_DID, ndlp->nlp_fc4_type,
+ "IoTag x%x Data: x%x x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, iotag,
+ ndlp->nlp_fc4_type,
ulp_status, ulp_word4,
disc, vport->num_disc_nodes);
@@ -2362,9 +2363,10 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* PRLI completes to NPort <nlp_DID> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0103 PRLI completes to NPort x%06x "
- "Data: x%x x%x x%x x%x\n",
+ "Data: x%x x%x x%x x%x x%x\n",
ndlp->nlp_DID, ulp_status, ulp_word4,
- vport->num_disc_nodes, ndlp->fc4_prli_sent);
+ vport->num_disc_nodes, ndlp->fc4_prli_sent,
+ ndlp->fc4_xpt_flags);
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport))
@@ -2805,7 +2807,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
IOCB_t *irsp;
struct lpfc_nodelist *ndlp;
int disc;
- u32 ulp_status, ulp_word4, tmo;
+ u32 ulp_status, ulp_word4, tmo, iotag;
bool release_node = false;
/* we pass cmdiocb to state machine which needs rspiocb as well */
@@ -2818,9 +2820,11 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (phba->sli_rev == LPFC_SLI_REV4) {
tmo = get_wqe_tmo(cmdiocb);
+ iotag = get_wqe_reqtag(cmdiocb);
} else {
irsp = &rspiocb->iocb;
tmo = irsp->ulpTimeout;
+ iotag = irsp->ulpIoTag;
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
@@ -2838,9 +2842,11 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* ADISC completes to NPort <nlp_DID> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0104 ADISC completes to NPort x%x "
- "Data: x%x x%x x%x x%x x%x\n",
- ndlp->nlp_DID, ulp_status, ulp_word4,
+ "IoTag x%x Data: x%x x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, iotag,
+ ulp_status, ulp_word4,
tmo, disc, vport->num_disc_nodes);
+
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport)) {
spin_lock_irq(&ndlp->lock);
@@ -3001,7 +3007,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
int wake_up_waiter = 0;
u32 ulp_status;
u32 ulp_word4;
- u32 tmo;
+ u32 tmo, iotag;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->rsp_iocb = rspiocb;
@@ -3011,9 +3017,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (phba->sli_rev == LPFC_SLI_REV4) {
tmo = get_wqe_tmo(cmdiocb);
+ iotag = get_wqe_reqtag(cmdiocb);
} else {
irsp = &rspiocb->iocb;
tmo = irsp->ulpTimeout;
+ iotag = irsp->ulpIoTag;
}
spin_lock_irq(&ndlp->lock);
@@ -3032,9 +3040,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* LOGO completes to NPort <nlp_DID> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0105 LOGO completes to NPort x%x "
- "refcnt %d nflags x%x Data: x%x x%x x%x x%x\n",
- ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag,
- ulp_status, ulp_word4,
+ "IoTag x%x refcnt %d nflags x%x xflags x%x "
+ "Data: x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, iotag,
+ kref_read(&ndlp->kref), ndlp->nlp_flag,
+ ndlp->fc4_xpt_flags, ulp_status, ulp_word4,
tmo, vport->num_disc_nodes);
if (lpfc_els_chk_latt(vport)) {
@@ -5075,16 +5085,19 @@ out_retry:
if (logerr) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0137 No retry ELS command x%x to remote "
- "NPORT x%x: Out of Resources: Error:x%x/%x\n",
- cmd, did, ulp_status,
- ulp_word4);
+ "NPORT x%x: Out of Resources: Error:x%x/%x "
+ "IoTag x%x\n",
+ cmd, did, ulp_status, ulp_word4,
+ cmdiocb->iotag);
}
else {
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "0108 No retry ELS command x%x to remote "
- "NPORT x%x Retried:%d Error:x%x/%x\n",
- cmd, did, cmdiocb->retry, ulp_status,
- ulp_word4);
+ "0108 No retry ELS command x%x to remote "
+ "NPORT x%x Retried:%d Error:x%x/%x "
+ "IoTag x%x nflags x%x\n",
+ cmd, did, cmdiocb->retry, ulp_status,
+ ulp_word4, cmdiocb->iotag,
+ (ndlp ? ndlp->nlp_flag : 0));
}
return 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 7ef9841f07..f80bbc315f 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -411,7 +411,7 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
"port_state = x%x\n",
ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp,
ndlp->nlp_flag, vport->port_state);
- spin_lock_irqsave(&ndlp->lock, iflags);
+ return;
}
spin_unlock_irqrestore(&ndlp->lock, iflags);
}
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 0dfdc0c4c0..cadcd16494 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -1814,7 +1814,9 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE,
mbox->sge_array->addr[sgentry], phyaddr);
}
- /* Free the sge address array memory */
+ /* Reinitialize the context pointers to avoid stale usage. */
+ mbox->ctx_buf = NULL;
+ mbox->context3 = NULL;
kfree(mbox->sge_array);
/* Finally, free the mailbox command itself */
mempool_free(mbox, phba->mbox_mem_pool);
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 89cbeba06a..2697da3248 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2014 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -48,6 +48,29 @@
#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */
#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */
+/* lpfc_mbox_free_sli_mbox
+ *
+ * @phba: HBA to free memory for
+ * @mbox: mailbox command to free
+ *
+ * This routine detects the mbox type and calls the correct
+ * free routine to fully release all associated memory.
+ */
+static void
+lpfc_mem_free_sli_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
+{
+ /* Detect if the caller's mbox is an SLI4_CONFIG type. If so, this
+ * mailbox type requires a different cleanup routine. Otherwise, the
+ * mailbox is just an mbuf and mem_pool release.
+ */
+ if (phba->sli_rev == LPFC_SLI_REV4 &&
+ bf_get(lpfc_mqe_command, &mbox->u.mqe) == MBX_SLI4_CONFIG) {
+ lpfc_sli4_mbox_cmd_free(phba, mbox);
+ } else {
+ lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
+ }
+}
+
int
lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) {
size_t bytes;
@@ -288,27 +311,16 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
LPFC_MBOXQ_t *mbox, *next_mbox;
- struct lpfc_dmabuf *mp;
/* Free memory used in mailbox queue back to mailbox memory pool */
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
- mp = (struct lpfc_dmabuf *)(mbox->ctx_buf);
- if (mp) {
- lpfc_mbuf_free(phba, mp->virt, mp->phys);
- kfree(mp);
- }
list_del(&mbox->list);
- mempool_free(mbox, phba->mbox_mem_pool);
+ lpfc_mem_free_sli_mbox(phba, mbox);
}
/* Free memory used in mailbox cmpl list back to mailbox memory pool */
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
- mp = (struct lpfc_dmabuf *)(mbox->ctx_buf);
- if (mp) {
- lpfc_mbuf_free(phba, mp->virt, mp->phys);
- kfree(mp);
- }
list_del(&mbox->list);
- mempool_free(mbox, phba->mbox_mem_pool);
+ lpfc_mem_free_sli_mbox(phba, mbox);
}
/* Free the active mailbox command back to the mailbox memory pool */
spin_lock_irq(&phba->hbalock);
@@ -316,12 +328,7 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
if (psli->mbox_active) {
mbox = psli->mbox_active;
- mp = (struct lpfc_dmabuf *)(mbox->ctx_buf);
- if (mp) {
- lpfc_mbuf_free(phba, mp->virt, mp->phys);
- kfree(mp);
- }
- mempool_free(mbox, phba->mbox_mem_pool);
+ lpfc_mem_free_sli_mbox(phba, mbox);
psli->mbox_active = NULL;
}
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index d9074929fb..b147304b01 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -748,8 +748,10 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* Save the ELS cmd */
elsiocb->drvrTimeout = cmd;
- lpfc_sli4_resume_rpi(ndlp,
- lpfc_mbx_cmpl_resume_rpi, elsiocb);
+ if (lpfc_sli4_resume_rpi(ndlp,
+ lpfc_mbx_cmpl_resume_rpi,
+ elsiocb))
+ kfree(elsiocb);
goto out;
}
}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 9386e7b447..706985358c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -2995,8 +2995,9 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
LPFC_SLI_INTF_IF_TYPE_2)) {
if (ndlp) {
lpfc_printf_vlog(
- vport, KERN_INFO, LOG_MBOX | LOG_SLI,
- "0010 UNREG_LOGIN vpi:%x "
+ vport, KERN_INFO,
+ LOG_MBOX | LOG_SLI | LOG_NODE,
+ "0010 UNREG_LOGIN vpi:x%x "
"rpi:%x DID:%x defer x%x flg x%x "
"x%px\n",
vport->vpi, ndlp->nlp_rpi,
@@ -3012,7 +3013,8 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
(ndlp->nlp_defer_did !=
NLP_EVT_NOTHING_PENDING)) {
lpfc_printf_vlog(
- vport, KERN_INFO, LOG_DISCOVERY,
+ vport, KERN_INFO,
+ LOG_MBOX | LOG_SLI | LOG_NODE,
"4111 UNREG cmpl deferred "
"clr x%x on "
"NPort x%x Data: x%x x%px\n",
@@ -3938,6 +3940,9 @@ void lpfc_poll_eratt(struct timer_list *t)
if (!(phba->hba_flag & HBA_SETUP))
return;
+ if (phba->pport->load_flag & FC_UNLOADING)
+ return;
+
/* Here we will also keep track of interrupts per sec of the hba */
sli_intr = phba->sli.slistat.sli_intr;
@@ -4875,7 +4880,7 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
lockdep_assert_held(&phba->hbalock);
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
- if (hdrtype != 0x80 ||
+ if (hdrtype != PCI_HEADER_TYPE_MFD ||
(FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID &&
FC_JEDEC_ID(phba->vpd.rev.biuRev) != THOR_JEDEC_ID))
return;
@@ -10141,11 +10146,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
spin_unlock_irqrestore(&phba->hbalock, iflags);
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
"(%d):0354 Mbox cmd issue - Enqueue Data: "
- "x%x (x%x/x%x) x%x x%x x%x\n",
+ "x%x (x%x/x%x) x%x x%x x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0xffffff,
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
lpfc_sli_config_mbox_subsys_get(phba, mboxq),
lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+ mboxq->u.mb.un.varUnregLogin.rpi,
phba->pport->port_state,
psli->sli_flag, MBX_NOWAIT);
/* Wake up worker thread to transport mailbox command from head */
@@ -22167,6 +22173,12 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
* The data will be truncated if datasz is not large enough.
* Version 1 is not supported with Embedded mbox cmd, so we must use version 0.
* Returns the actual bytes read from the object.
+ *
+ * This routine is hard coded to use a poll completion. Unlike other
+ * sli4_config mailboxes, it uses lpfc_mbuf memory which is not
+ * cleaned up in lpfc_sli4_cmd_mbox_free. If this routine is modified
+ * to use interrupt-based completions, code is needed to fully cleanup
+ * the memory.
*/
int
lpfc_read_object(struct lpfc_hba *phba, char *rdobject, uint32_t *datap,
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index cd33dfec75..c911a39cb4 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -182,9 +182,11 @@ typedef struct lpfcMboxq {
struct lpfc_mqe mqe;
} u;
struct lpfc_vport *vport; /* virtual port pointer */
- void *ctx_ndlp; /* caller ndlp information */
- void *ctx_buf; /* caller buffer information */
- void *context3;
+ void *ctx_ndlp; /* an lpfc_nodelist pointer */
+ void *ctx_buf; /* an lpfc_dmabuf pointer */
+ void *context3; /* a generic pointer. Code must
+ * accommodate the actual datatype.
+ */
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
uint8_t mbox_flag;
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 88068834ca..aba1c1cee8 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "14.2.0.15"
+#define LPFC_DRIVER_VERSION "14.2.0.17"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 3f0061b004..187ae0a65d 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -407,7 +407,7 @@ fail:
return err;
}
-static int esp_mac_remove(struct platform_device *dev)
+static void esp_mac_remove(struct platform_device *dev)
{
struct mac_esp_priv *mep = platform_get_drvdata(dev);
struct esp *esp = mep->esp;
@@ -428,13 +428,11 @@ static int esp_mac_remove(struct platform_device *dev)
kfree(esp->command_block);
scsi_host_put(esp->host);
-
- return 0;
}
static struct platform_driver esp_mac_driver = {
.probe = esp_mac_probe,
- .remove = esp_mac_remove,
+ .remove_new = esp_mac_remove,
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 2e511697fc..181f16899f 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -523,7 +523,7 @@ fail_init:
return error;
}
-static int __exit mac_scsi_remove(struct platform_device *pdev)
+static void __exit mac_scsi_remove(struct platform_device *pdev)
{
struct Scsi_Host *instance = platform_get_drvdata(pdev);
@@ -532,11 +532,10 @@ static int __exit mac_scsi_remove(struct platform_device *pdev)
free_irq(instance->irq, instance);
NCR5380_exit(instance);
scsi_host_put(instance);
- return 0;
}
static struct platform_driver mac_scsi_driver = {
- .remove = __exit_p(mac_scsi_remove),
+ .remove_new = __exit_p(mac_scsi_remove),
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
index 1e4a60fc65..0cb24fc036 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
@@ -28,6 +28,7 @@ struct mpi3_ioc_init_request {
__le64 driver_information_address;
};
+#define MPI3_IOCINIT_MSGFLAGS_SCSIIOSTATUSREPLY_SUPPORTED (0x04)
#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_MASK (0x03)
#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_NOT_USED (0x00)
#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SEPARATED (0x01)
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index ae98d15c30..3de1ee05c4 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -55,8 +55,8 @@ extern struct list_head mrioc_list;
extern int prot_mask;
extern atomic64_t event_counter;
-#define MPI3MR_DRIVER_VERSION "8.5.0.0.0"
-#define MPI3MR_DRIVER_RELDATE "24-July-2023"
+#define MPI3MR_DRIVER_VERSION "8.5.1.0.0"
+#define MPI3MR_DRIVER_RELDATE "5-December-2023"
#define MPI3MR_DRIVER_NAME "mpi3mr"
#define MPI3MR_DRIVER_LICENSE "GPL"
@@ -218,14 +218,16 @@ extern atomic64_t event_counter;
* @length: SGE length
* @rsvd: Reserved
* @rsvd1: Reserved
- * @sgl_type: sgl type
+ * @sub_type: sgl sub type
+ * @type: sgl type
*/
struct mpi3mr_nvme_pt_sge {
- u64 base_addr;
- u32 length;
+ __le64 base_addr;
+ __le32 length;
u16 rsvd;
u8 rsvd1;
- u8 sgl_type;
+ u8 sub_type:4;
+ u8 type:4;
};
/**
@@ -247,6 +249,8 @@ struct mpi3mr_buf_map {
u32 kern_buf_len;
dma_addr_t kern_buf_dma;
u8 data_dir;
+ u16 num_dma_desc;
+ struct dma_memory_desc *dma_desc;
};
/* IOC State definitions */
@@ -477,6 +481,10 @@ struct mpi3mr_throttle_group_info {
/* HBA port flags */
#define MPI3MR_HBA_PORT_FLAG_DIRTY 0x01
+/* IOCTL data transfer sge*/
+#define MPI3MR_NUM_IOCTL_SGE 256
+#define MPI3MR_IOCTL_SGE_SIZE (8 * 1024)
+
/**
* struct mpi3mr_hba_port - HBA's port information
* @port_id: Port number
@@ -506,7 +514,7 @@ struct mpi3mr_sas_port {
u8 num_phys;
u8 marked_responding;
int lowest_phy;
- u32 phy_mask;
+ u64 phy_mask;
struct mpi3mr_hba_port *hba_port;
struct sas_identify remote_identify;
struct sas_rphy *rphy;
@@ -1042,6 +1050,11 @@ struct scmd_priv {
* @sas_node_lock: Lock to protect SAS node list
* @hba_port_table_list: List of HBA Ports
* @enclosure_list: List of Enclosure objects
+ * @ioctl_dma_pool: DMA pool for IOCTL data buffers
+ * @ioctl_sge: DMA buffer descriptors for IOCTL data
+ * @ioctl_chain_sge: DMA buffer descriptor for IOCTL chain
+ * @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response
+ * @ioctl_sges_allocated: Flag for IOCTL SGEs allocated or not
*/
struct mpi3mr_ioc {
struct list_head list;
@@ -1227,6 +1240,12 @@ struct mpi3mr_ioc {
spinlock_t sas_node_lock;
struct list_head hba_port_table_list;
struct list_head enclosure_list;
+
+ struct dma_pool *ioctl_dma_pool;
+ struct dma_memory_desc ioctl_sge[MPI3MR_NUM_IOCTL_SGE];
+ struct dma_memory_desc ioctl_chain_sge;
+ struct dma_memory_desc ioctl_resp_sge;
+ bool ioctl_sges_allocated;
};
/**
diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
index 9dacbb8570..0380996b5a 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
@@ -564,7 +564,36 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job)
}
/**
+ * mpi3mr_total_num_ioctl_sges - Count number of SGEs required
+ * @drv_bufs: DMA address of the buffers to be placed in sgl
+ * @bufcnt: Number of DMA buffers
+ *
+ * This function returns total number of data SGEs required
+ * including zero length SGEs and excluding management request
+ * and response buffer for the given list of data buffer
+ * descriptors
+ *
+ * Return: Number of SGE elements needed
+ */
+static inline u16 mpi3mr_total_num_ioctl_sges(struct mpi3mr_buf_map *drv_bufs,
+ u8 bufcnt)
+{
+ u16 i, sge_count = 0;
+
+ for (i = 0; i < bufcnt; i++, drv_bufs++) {
+ if (drv_bufs->data_dir == DMA_NONE ||
+ drv_bufs->kern_buf)
+ continue;
+ sge_count += drv_bufs->num_dma_desc;
+ if (!drv_bufs->num_dma_desc)
+ sge_count++;
+ }
+ return sge_count;
+}
+
+/**
* mpi3mr_bsg_build_sgl - SGL construction for MPI commands
+ * @mrioc: Adapter instance reference
* @mpi_req: MPI request
* @sgl_offset: offset to start sgl in the MPI request
* @drv_bufs: DMA address of the buffers to be placed in sgl
@@ -576,27 +605,45 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job)
* This function places the DMA address of the given buffers in
* proper format as SGEs in the given MPI request.
*
- * Return: Nothing
+ * Return: 0 on success,-1 on failure
*/
-static void mpi3mr_bsg_build_sgl(u8 *mpi_req, uint32_t sgl_offset,
- struct mpi3mr_buf_map *drv_bufs, u8 bufcnt, u8 is_rmc,
- u8 is_rmr, u8 num_datasges)
+static int mpi3mr_bsg_build_sgl(struct mpi3mr_ioc *mrioc, u8 *mpi_req,
+ u32 sgl_offset, struct mpi3mr_buf_map *drv_bufs,
+ u8 bufcnt, u8 is_rmc, u8 is_rmr, u8 num_datasges)
{
+ struct mpi3_request_header *mpi_header =
+ (struct mpi3_request_header *)mpi_req;
u8 *sgl = (mpi_req + sgl_offset), count = 0;
struct mpi3_mgmt_passthrough_request *rmgmt_req =
(struct mpi3_mgmt_passthrough_request *)mpi_req;
struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
- u8 sgl_flags, sgl_flags_last;
+ u8 flag, sgl_flags, sgl_flag_eob, sgl_flags_last, last_chain_sgl_flag;
+ u16 available_sges, i, sges_needed;
+ u32 sge_element_size = sizeof(struct mpi3_sge_common);
+ bool chain_used = false;
sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
- MPI3_SGE_FLAGS_DLAS_SYSTEM | MPI3_SGE_FLAGS_END_OF_BUFFER;
- sgl_flags_last = sgl_flags | MPI3_SGE_FLAGS_END_OF_LIST;
+ MPI3_SGE_FLAGS_DLAS_SYSTEM;
+ sgl_flag_eob = sgl_flags | MPI3_SGE_FLAGS_END_OF_BUFFER;
+ sgl_flags_last = sgl_flag_eob | MPI3_SGE_FLAGS_END_OF_LIST;
+ last_chain_sgl_flag = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN |
+ MPI3_SGE_FLAGS_DLAS_SYSTEM;
+
+ sges_needed = mpi3mr_total_num_ioctl_sges(drv_bufs, bufcnt);
if (is_rmc) {
mpi3mr_add_sg_single(&rmgmt_req->command_sgl,
sgl_flags_last, drv_buf_iter->kern_buf_len,
drv_buf_iter->kern_buf_dma);
- sgl = (u8 *)drv_buf_iter->kern_buf + drv_buf_iter->bsg_buf_len;
+ sgl = (u8 *)drv_buf_iter->kern_buf +
+ drv_buf_iter->bsg_buf_len;
+ available_sges = (drv_buf_iter->kern_buf_len -
+ drv_buf_iter->bsg_buf_len) / sge_element_size;
+
+ if (sges_needed > available_sges)
+ return -1;
+
+ chain_used = true;
drv_buf_iter++;
count++;
if (is_rmr) {
@@ -608,23 +655,95 @@ static void mpi3mr_bsg_build_sgl(u8 *mpi_req, uint32_t sgl_offset,
} else
mpi3mr_build_zero_len_sge(
&rmgmt_req->response_sgl);
+ if (num_datasges) {
+ i = 0;
+ goto build_sges;
+ }
+ } else {
+ if (sgl_offset >= MPI3MR_ADMIN_REQ_FRAME_SZ)
+ return -1;
+ available_sges = (MPI3MR_ADMIN_REQ_FRAME_SZ - sgl_offset) /
+ sge_element_size;
+ if (!available_sges)
+ return -1;
}
if (!num_datasges) {
mpi3mr_build_zero_len_sge(sgl);
- return;
+ return 0;
}
+ if (mpi_header->function == MPI3_BSG_FUNCTION_SMP_PASSTHROUGH) {
+ if ((sges_needed > 2) || (sges_needed > available_sges))
+ return -1;
+ for (; count < bufcnt; count++, drv_buf_iter++) {
+ if (drv_buf_iter->data_dir == DMA_NONE ||
+ !drv_buf_iter->num_dma_desc)
+ continue;
+ mpi3mr_add_sg_single(sgl, sgl_flags_last,
+ drv_buf_iter->dma_desc[0].size,
+ drv_buf_iter->dma_desc[0].dma_addr);
+ sgl += sge_element_size;
+ }
+ return 0;
+ }
+ i = 0;
+
+build_sges:
for (; count < bufcnt; count++, drv_buf_iter++) {
if (drv_buf_iter->data_dir == DMA_NONE)
continue;
- if (num_datasges == 1 || !is_rmc)
- mpi3mr_add_sg_single(sgl, sgl_flags_last,
- drv_buf_iter->kern_buf_len, drv_buf_iter->kern_buf_dma);
- else
- mpi3mr_add_sg_single(sgl, sgl_flags,
- drv_buf_iter->kern_buf_len, drv_buf_iter->kern_buf_dma);
- sgl += sizeof(struct mpi3_sge_common);
+ if (!drv_buf_iter->num_dma_desc) {
+ if (chain_used && !available_sges)
+ return -1;
+ if (!chain_used && (available_sges == 1) &&
+ (sges_needed > 1))
+ goto setup_chain;
+ flag = sgl_flag_eob;
+ if (num_datasges == 1)
+ flag = sgl_flags_last;
+ mpi3mr_add_sg_single(sgl, flag, 0, 0);
+ sgl += sge_element_size;
+ sges_needed--;
+ available_sges--;
+ num_datasges--;
+ continue;
+ }
+ for (; i < drv_buf_iter->num_dma_desc; i++) {
+ if (chain_used && !available_sges)
+ return -1;
+ if (!chain_used && (available_sges == 1) &&
+ (sges_needed > 1))
+ goto setup_chain;
+ flag = sgl_flags;
+ if (i == (drv_buf_iter->num_dma_desc - 1)) {
+ if (num_datasges == 1)
+ flag = sgl_flags_last;
+ else
+ flag = sgl_flag_eob;
+ }
+
+ mpi3mr_add_sg_single(sgl, flag,
+ drv_buf_iter->dma_desc[i].size,
+ drv_buf_iter->dma_desc[i].dma_addr);
+ sgl += sge_element_size;
+ available_sges--;
+ sges_needed--;
+ }
num_datasges--;
+ i = 0;
}
+ return 0;
+
+setup_chain:
+ available_sges = mrioc->ioctl_chain_sge.size / sge_element_size;
+ if (sges_needed > available_sges)
+ return -1;
+ mpi3mr_add_sg_single(sgl, last_chain_sgl_flag,
+ (sges_needed * sge_element_size),
+ mrioc->ioctl_chain_sge.dma_addr);
+ memset(mrioc->ioctl_chain_sge.addr, 0, mrioc->ioctl_chain_sge.size);
+ sgl = (u8 *)mrioc->ioctl_chain_sge.addr;
+ chain_used = true;
+ goto build_sges;
}
/**
@@ -664,14 +783,20 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt)
{
struct mpi3mr_nvme_pt_sge *nvme_sgl;
- u64 sgl_ptr;
+ __le64 sgl_dma;
u8 count;
size_t length = 0;
+ u16 available_sges = 0, i;
+ u32 sge_element_size = sizeof(struct mpi3mr_nvme_pt_sge);
struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
u64 sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) <<
mrioc->facts.sge_mod_shift) << 32);
u64 sgemod_val = ((u64)(mrioc->facts.sge_mod_value) <<
mrioc->facts.sge_mod_shift) << 32;
+ u32 size;
+
+ nvme_sgl = (struct mpi3mr_nvme_pt_sge *)
+ ((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET);
/*
* Not all commands require a data transfer. If no data, just return
@@ -680,27 +805,59 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
if (drv_buf_iter->data_dir == DMA_NONE)
continue;
- sgl_ptr = (u64)drv_buf_iter->kern_buf_dma;
length = drv_buf_iter->kern_buf_len;
break;
}
- if (!length)
+ if (!length || !drv_buf_iter->num_dma_desc)
return 0;
- if (sgl_ptr & sgemod_mask) {
+ if (drv_buf_iter->num_dma_desc == 1) {
+ available_sges = 1;
+ goto build_sges;
+ }
+
+ sgl_dma = cpu_to_le64(mrioc->ioctl_chain_sge.dma_addr);
+ if (sgl_dma & sgemod_mask) {
dprint_bsg_err(mrioc,
- "%s: SGL address collides with SGE modifier\n",
+ "%s: SGL chain address collides with SGE modifier\n",
__func__);
return -1;
}
- sgl_ptr &= ~sgemod_mask;
- sgl_ptr |= sgemod_val;
- nvme_sgl = (struct mpi3mr_nvme_pt_sge *)
- ((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET);
+ sgl_dma &= ~sgemod_mask;
+ sgl_dma |= sgemod_val;
+
+ memset(mrioc->ioctl_chain_sge.addr, 0, mrioc->ioctl_chain_sge.size);
+ available_sges = mrioc->ioctl_chain_sge.size / sge_element_size;
+ if (available_sges < drv_buf_iter->num_dma_desc)
+ return -1;
memset(nvme_sgl, 0, sizeof(struct mpi3mr_nvme_pt_sge));
- nvme_sgl->base_addr = sgl_ptr;
- nvme_sgl->length = length;
+ nvme_sgl->base_addr = sgl_dma;
+ size = drv_buf_iter->num_dma_desc * sizeof(struct mpi3mr_nvme_pt_sge);
+ nvme_sgl->length = cpu_to_le32(size);
+ nvme_sgl->type = MPI3MR_NVMESGL_LAST_SEGMENT;
+ nvme_sgl = (struct mpi3mr_nvme_pt_sge *)mrioc->ioctl_chain_sge.addr;
+
+build_sges:
+ for (i = 0; i < drv_buf_iter->num_dma_desc; i++) {
+ sgl_dma = cpu_to_le64(drv_buf_iter->dma_desc[i].dma_addr);
+ if (sgl_dma & sgemod_mask) {
+ dprint_bsg_err(mrioc,
+ "%s: SGL address collides with SGE modifier\n",
+ __func__);
+ return -1;
+ }
+
+ sgl_dma &= ~sgemod_mask;
+ sgl_dma |= sgemod_val;
+
+ nvme_sgl->base_addr = sgl_dma;
+ nvme_sgl->length = cpu_to_le32(drv_buf_iter->dma_desc[i].size);
+ nvme_sgl->type = MPI3MR_NVMESGL_DATA_SEGMENT;
+ nvme_sgl++;
+ available_sges--;
+ }
+
return 0;
}
@@ -728,7 +885,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
dma_addr_t prp_entry_dma, prp_page_dma, dma_addr;
u32 offset, entry_len, dev_pgsz;
u32 page_mask_result, page_mask;
- size_t length = 0;
+ size_t length = 0, desc_len;
u8 count;
struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
u64 sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) <<
@@ -737,6 +894,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
mrioc->facts.sge_mod_shift) << 32;
u16 dev_handle = nvme_encap_request->dev_handle;
struct mpi3mr_tgt_dev *tgtdev;
+ u16 desc_count = 0;
tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle);
if (!tgtdev) {
@@ -755,6 +913,21 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
dev_pgsz = 1 << (tgtdev->dev_spec.pcie_inf.pgsz);
mpi3mr_tgtdev_put(tgtdev);
+ page_mask = dev_pgsz - 1;
+
+ if (dev_pgsz > MPI3MR_IOCTL_SGE_SIZE) {
+ dprint_bsg_err(mrioc,
+ "%s: NVMe device page size(%d) is greater than ioctl data sge size(%d) for handle 0x%04x\n",
+ __func__, dev_pgsz, MPI3MR_IOCTL_SGE_SIZE, dev_handle);
+ return -1;
+ }
+
+ if (MPI3MR_IOCTL_SGE_SIZE % dev_pgsz) {
+ dprint_bsg_err(mrioc,
+ "%s: ioctl data sge size(%d) is not a multiple of NVMe device page size(%d) for handle 0x%04x\n",
+ __func__, MPI3MR_IOCTL_SGE_SIZE, dev_pgsz, dev_handle);
+ return -1;
+ }
/*
* Not all commands require a data transfer. If no data, just return
@@ -763,14 +936,26 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
if (drv_buf_iter->data_dir == DMA_NONE)
continue;
- dma_addr = drv_buf_iter->kern_buf_dma;
length = drv_buf_iter->kern_buf_len;
break;
}
- if (!length)
+ if (!length || !drv_buf_iter->num_dma_desc)
return 0;
+ for (count = 0; count < drv_buf_iter->num_dma_desc; count++) {
+ dma_addr = drv_buf_iter->dma_desc[count].dma_addr;
+ if (dma_addr & page_mask) {
+ dprint_bsg_err(mrioc,
+ "%s:dma_addr %pad is not aligned with page size 0x%x\n",
+ __func__, &dma_addr, dev_pgsz);
+ return -1;
+ }
+ }
+
+ dma_addr = drv_buf_iter->dma_desc[0].dma_addr;
+ desc_len = drv_buf_iter->dma_desc[0].size;
+
mrioc->prp_sz = 0;
mrioc->prp_list_virt = dma_alloc_coherent(&mrioc->pdev->dev,
dev_pgsz, &mrioc->prp_list_dma, GFP_KERNEL);
@@ -800,7 +985,6 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
* Check if we are within 1 entry of a page boundary we don't
* want our first entry to be a PRP List entry.
*/
- page_mask = dev_pgsz - 1;
page_mask_result = (uintptr_t)((u8 *)prp_page + prp_size) & page_mask;
if (!page_mask_result) {
dprint_bsg_err(mrioc, "%s: PRP page is not page aligned\n",
@@ -914,18 +1098,31 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
prp_entry_dma += prp_size;
}
- /*
- * Bump the phys address of the command's data buffer by the
- * entry_len.
- */
- dma_addr += entry_len;
-
/* decrement length accounting for last partial page. */
- if (entry_len > length)
+ if (entry_len >= length) {
length = 0;
- else
+ } else {
+ if (entry_len <= desc_len) {
+ dma_addr += entry_len;
+ desc_len -= entry_len;
+ }
+ if (!desc_len) {
+ if ((++desc_count) >=
+ drv_buf_iter->num_dma_desc) {
+ dprint_bsg_err(mrioc,
+ "%s: Invalid len %zd while building PRP\n",
+ __func__, length);
+ goto err_out;
+ }
+ dma_addr =
+ drv_buf_iter->dma_desc[desc_count].dma_addr;
+ desc_len =
+ drv_buf_iter->dma_desc[desc_count].size;
+ }
length -= entry_len;
+ }
}
+
return 0;
err_out:
if (mrioc->prp_list_virt) {
@@ -935,10 +1132,66 @@ err_out:
}
return -1;
}
+
+/**
+ * mpi3mr_map_data_buffer_dma - build dma descriptors for data
+ * buffers
+ * @mrioc: Adapter instance reference
+ * @drv_buf: buffer map descriptor
+ * @desc_count: Number of already consumed dma descriptors
+ *
+ * This function computes how many pre-allocated DMA descriptors
+ * are required for the given data buffer and if those number of
+ * descriptors are free, then setup the mapping of the scattered
+ * DMA address to the given data buffer, if the data direction
+ * of the buffer is DMA_TO_DEVICE then the actual data is copied to
+ * the DMA buffers
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static int mpi3mr_map_data_buffer_dma(struct mpi3mr_ioc *mrioc,
+ struct mpi3mr_buf_map *drv_buf,
+ u16 desc_count)
+{
+ u16 i, needed_desc = drv_buf->kern_buf_len / MPI3MR_IOCTL_SGE_SIZE;
+ u32 buf_len = drv_buf->kern_buf_len, copied_len = 0;
+
+ if (drv_buf->kern_buf_len % MPI3MR_IOCTL_SGE_SIZE)
+ needed_desc++;
+ if ((needed_desc + desc_count) > MPI3MR_NUM_IOCTL_SGE) {
+ dprint_bsg_err(mrioc, "%s: DMA descriptor mapping error %d:%d:%d\n",
+ __func__, needed_desc, desc_count, MPI3MR_NUM_IOCTL_SGE);
+ return -1;
+ }
+ drv_buf->dma_desc = kzalloc(sizeof(*drv_buf->dma_desc) * needed_desc,
+ GFP_KERNEL);
+ if (!drv_buf->dma_desc)
+ return -1;
+ for (i = 0; i < needed_desc; i++, desc_count++) {
+ drv_buf->dma_desc[i].addr = mrioc->ioctl_sge[desc_count].addr;
+ drv_buf->dma_desc[i].dma_addr =
+ mrioc->ioctl_sge[desc_count].dma_addr;
+ if (buf_len < mrioc->ioctl_sge[desc_count].size)
+ drv_buf->dma_desc[i].size = buf_len;
+ else
+ drv_buf->dma_desc[i].size =
+ mrioc->ioctl_sge[desc_count].size;
+ buf_len -= drv_buf->dma_desc[i].size;
+ memset(drv_buf->dma_desc[i].addr, 0,
+ mrioc->ioctl_sge[desc_count].size);
+ if (drv_buf->data_dir == DMA_TO_DEVICE) {
+ memcpy(drv_buf->dma_desc[i].addr,
+ drv_buf->bsg_buf + copied_len,
+ drv_buf->dma_desc[i].size);
+ copied_len += drv_buf->dma_desc[i].size;
+ }
+ }
+ drv_buf->num_dma_desc = needed_desc;
+ return 0;
+}
/**
* mpi3mr_bsg_process_mpt_cmds - MPI Pass through BSG handler
* @job: BSG job reference
- * @reply_payload_rcv_len: length of payload recvd
*
* This function is the top level handler for MPI Pass through
* command, this does basic validation of the input data buffers,
@@ -954,10 +1207,9 @@ err_out:
* Return: 0 on success and proper error codes on failure
*/
-static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply_payload_rcv_len)
+static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
{
long rval = -EINVAL;
-
struct mpi3mr_ioc *mrioc = NULL;
u8 *mpi_req = NULL, *sense_buff_k = NULL;
u8 mpi_msg_size = 0;
@@ -965,9 +1217,10 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
struct mpi3mr_bsg_mptcmd *karg;
struct mpi3mr_buf_entry *buf_entries = NULL;
struct mpi3mr_buf_map *drv_bufs = NULL, *drv_buf_iter = NULL;
- u8 count, bufcnt = 0, is_rmcb = 0, is_rmrb = 0, din_cnt = 0, dout_cnt = 0;
- u8 invalid_be = 0, erb_offset = 0xFF, mpirep_offset = 0xFF, sg_entries = 0;
- u8 block_io = 0, resp_code = 0, nvme_fmt = 0;
+ u8 count, bufcnt = 0, is_rmcb = 0, is_rmrb = 0;
+ u8 din_cnt = 0, dout_cnt = 0;
+ u8 invalid_be = 0, erb_offset = 0xFF, mpirep_offset = 0xFF;
+ u8 block_io = 0, nvme_fmt = 0, resp_code = 0;
struct mpi3_request_header *mpi_header = NULL;
struct mpi3_status_reply_descriptor *status_desc;
struct mpi3_scsi_task_mgmt_request *tm_req;
@@ -979,6 +1232,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
u32 din_size = 0, dout_size = 0;
u8 *din_buf = NULL, *dout_buf = NULL;
u8 *sgl_iter = NULL, *sgl_din_iter = NULL, *sgl_dout_iter = NULL;
+ u16 rmc_size = 0, desc_count = 0;
bsg_req = job->request;
karg = (struct mpi3mr_bsg_mptcmd *)&bsg_req->cmd.mptcmd;
@@ -987,6 +1241,12 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
if (!mrioc)
return -ENODEV;
+ if (!mrioc->ioctl_sges_allocated) {
+ dprint_bsg_err(mrioc, "%s: DMA memory was not allocated\n",
+ __func__);
+ return -ENOMEM;
+ }
+
if (karg->timeout < MPI3MR_APP_DEFAULT_TIMEOUT)
karg->timeout = MPI3MR_APP_DEFAULT_TIMEOUT;
@@ -1027,26 +1287,13 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
for (count = 0; count < bufcnt; count++, buf_entries++, drv_buf_iter++) {
- if (sgl_dout_iter > (dout_buf + job->request_payload.payload_len)) {
- dprint_bsg_err(mrioc, "%s: data_out buffer length mismatch\n",
- __func__);
- rval = -EINVAL;
- goto out;
- }
- if (sgl_din_iter > (din_buf + job->reply_payload.payload_len)) {
- dprint_bsg_err(mrioc, "%s: data_in buffer length mismatch\n",
- __func__);
- rval = -EINVAL;
- goto out;
- }
-
switch (buf_entries->buf_type) {
case MPI3MR_BSG_BUFTYPE_RAIDMGMT_CMD:
sgl_iter = sgl_dout_iter;
sgl_dout_iter += buf_entries->buf_len;
drv_buf_iter->data_dir = DMA_TO_DEVICE;
is_rmcb = 1;
- if (count != 0)
+ if ((count != 0) || !buf_entries->buf_len)
invalid_be = 1;
break;
case MPI3MR_BSG_BUFTYPE_RAIDMGMT_RESP:
@@ -1054,7 +1301,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
sgl_din_iter += buf_entries->buf_len;
drv_buf_iter->data_dir = DMA_FROM_DEVICE;
is_rmrb = 1;
- if (count != 1 || !is_rmcb)
+ if (count != 1 || !is_rmcb || !buf_entries->buf_len)
invalid_be = 1;
break;
case MPI3MR_BSG_BUFTYPE_DATA_IN:
@@ -1062,7 +1309,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
sgl_din_iter += buf_entries->buf_len;
drv_buf_iter->data_dir = DMA_FROM_DEVICE;
din_cnt++;
- din_size += drv_buf_iter->bsg_buf_len;
+ din_size += buf_entries->buf_len;
if ((din_cnt > 1) && !is_rmcb)
invalid_be = 1;
break;
@@ -1071,7 +1318,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
sgl_dout_iter += buf_entries->buf_len;
drv_buf_iter->data_dir = DMA_TO_DEVICE;
dout_cnt++;
- dout_size += drv_buf_iter->bsg_buf_len;
+ dout_size += buf_entries->buf_len;
if ((dout_cnt > 1) && !is_rmcb)
invalid_be = 1;
break;
@@ -1080,12 +1327,16 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
sgl_din_iter += buf_entries->buf_len;
drv_buf_iter->data_dir = DMA_NONE;
mpirep_offset = count;
+ if (!buf_entries->buf_len)
+ invalid_be = 1;
break;
case MPI3MR_BSG_BUFTYPE_ERR_RESPONSE:
sgl_iter = sgl_din_iter;
sgl_din_iter += buf_entries->buf_len;
drv_buf_iter->data_dir = DMA_NONE;
erb_offset = count;
+ if (!buf_entries->buf_len)
+ invalid_be = 1;
break;
case MPI3MR_BSG_BUFTYPE_MPI_REQUEST:
sgl_iter = sgl_dout_iter;
@@ -1112,21 +1363,31 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
goto out;
}
- drv_buf_iter->bsg_buf = sgl_iter;
- drv_buf_iter->bsg_buf_len = buf_entries->buf_len;
-
- }
- if (!is_rmcb && (dout_cnt || din_cnt)) {
- sg_entries = dout_cnt + din_cnt;
- if (((mpi_msg_size) + (sg_entries *
- sizeof(struct mpi3_sge_common))) > MPI3MR_ADMIN_REQ_FRAME_SZ) {
- dprint_bsg_err(mrioc,
- "%s:%d: invalid message size passed\n",
- __func__, __LINE__);
+ if (sgl_dout_iter > (dout_buf + job->request_payload.payload_len)) {
+ dprint_bsg_err(mrioc, "%s: data_out buffer length mismatch\n",
+ __func__);
rval = -EINVAL;
goto out;
}
+ if (sgl_din_iter > (din_buf + job->reply_payload.payload_len)) {
+ dprint_bsg_err(mrioc, "%s: data_in buffer length mismatch\n",
+ __func__);
+ rval = -EINVAL;
+ goto out;
+ }
+
+ drv_buf_iter->bsg_buf = sgl_iter;
+ drv_buf_iter->bsg_buf_len = buf_entries->buf_len;
+ }
+
+ if (is_rmcb && ((din_size + dout_size) > MPI3MR_MAX_APP_XFER_SIZE)) {
+ dprint_bsg_err(mrioc, "%s:%d: invalid data transfer size passed for function 0x%x din_size = %d, dout_size = %d\n",
+ __func__, __LINE__, mpi_header->function, din_size,
+ dout_size);
+ rval = -EINVAL;
+ goto out;
}
+
if (din_size > MPI3MR_MAX_APP_XFER_SIZE) {
dprint_bsg_err(mrioc,
"%s:%d: invalid data transfer size passed for function 0x%x din_size=%d\n",
@@ -1142,30 +1403,64 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
goto out;
}
+ if (mpi_header->function == MPI3_BSG_FUNCTION_SMP_PASSTHROUGH) {
+ if (din_size > MPI3MR_IOCTL_SGE_SIZE ||
+ dout_size > MPI3MR_IOCTL_SGE_SIZE) {
+ dprint_bsg_err(mrioc, "%s:%d: invalid message size passed:%d:%d:%d:%d\n",
+ __func__, __LINE__, din_cnt, dout_cnt, din_size,
+ dout_size);
+ rval = -EINVAL;
+ goto out;
+ }
+ }
+
drv_buf_iter = drv_bufs;
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
if (drv_buf_iter->data_dir == DMA_NONE)
continue;
drv_buf_iter->kern_buf_len = drv_buf_iter->bsg_buf_len;
- if (is_rmcb && !count)
- drv_buf_iter->kern_buf_len += ((dout_cnt + din_cnt) *
- sizeof(struct mpi3_sge_common));
-
- if (!drv_buf_iter->kern_buf_len)
- continue;
-
- drv_buf_iter->kern_buf = dma_alloc_coherent(&mrioc->pdev->dev,
- drv_buf_iter->kern_buf_len, &drv_buf_iter->kern_buf_dma,
- GFP_KERNEL);
- if (!drv_buf_iter->kern_buf) {
- rval = -ENOMEM;
- goto out;
- }
- if (drv_buf_iter->data_dir == DMA_TO_DEVICE) {
+ if (is_rmcb && !count) {
+ drv_buf_iter->kern_buf_len =
+ mrioc->ioctl_chain_sge.size;
+ drv_buf_iter->kern_buf =
+ mrioc->ioctl_chain_sge.addr;
+ drv_buf_iter->kern_buf_dma =
+ mrioc->ioctl_chain_sge.dma_addr;
+ drv_buf_iter->dma_desc = NULL;
+ drv_buf_iter->num_dma_desc = 0;
+ memset(drv_buf_iter->kern_buf, 0,
+ drv_buf_iter->kern_buf_len);
tmplen = min(drv_buf_iter->kern_buf_len,
- drv_buf_iter->bsg_buf_len);
+ drv_buf_iter->bsg_buf_len);
+ rmc_size = tmplen;
memcpy(drv_buf_iter->kern_buf, drv_buf_iter->bsg_buf, tmplen);
+ } else if (is_rmrb && (count == 1)) {
+ drv_buf_iter->kern_buf_len =
+ mrioc->ioctl_resp_sge.size;
+ drv_buf_iter->kern_buf =
+ mrioc->ioctl_resp_sge.addr;
+ drv_buf_iter->kern_buf_dma =
+ mrioc->ioctl_resp_sge.dma_addr;
+ drv_buf_iter->dma_desc = NULL;
+ drv_buf_iter->num_dma_desc = 0;
+ memset(drv_buf_iter->kern_buf, 0,
+ drv_buf_iter->kern_buf_len);
+ tmplen = min(drv_buf_iter->kern_buf_len,
+ drv_buf_iter->bsg_buf_len);
+ drv_buf_iter->kern_buf_len = tmplen;
+ memset(drv_buf_iter->bsg_buf, 0,
+ drv_buf_iter->bsg_buf_len);
+ } else {
+ if (!drv_buf_iter->kern_buf_len)
+ continue;
+ if (mpi3mr_map_data_buffer_dma(mrioc, drv_buf_iter, desc_count)) {
+ rval = -ENOMEM;
+ dprint_bsg_err(mrioc, "%s:%d: mapping data buffers failed\n",
+ __func__, __LINE__);
+ goto out;
+ }
+ desc_count += drv_buf_iter->num_dma_desc;
}
}
@@ -1235,9 +1530,14 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
goto out;
}
} else {
- mpi3mr_bsg_build_sgl(mpi_req, (mpi_msg_size),
- drv_bufs, bufcnt, is_rmcb, is_rmrb,
- (dout_cnt + din_cnt));
+ if (mpi3mr_bsg_build_sgl(mrioc, mpi_req, mpi_msg_size,
+ drv_bufs, bufcnt, is_rmcb, is_rmrb,
+ (dout_cnt + din_cnt))) {
+ dprint_bsg_err(mrioc, "%s: sgl build failed\n", __func__);
+ rval = -EAGAIN;
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
+ goto out;
+ }
}
if (mpi_header->function == MPI3_BSG_FUNCTION_SCSI_TASK_MGMT) {
@@ -1273,7 +1573,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
if (mpi_header->function == MPI3_BSG_FUNCTION_MGMT_PASSTHROUGH) {
drv_buf_iter = &drv_bufs[0];
dprint_dump(drv_buf_iter->kern_buf,
- drv_buf_iter->kern_buf_len, "mpi3_mgmt_req");
+ rmc_size, "mpi3_mgmt_req");
}
}
@@ -1308,10 +1608,9 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
MPI3_BSG_FUNCTION_MGMT_PASSTHROUGH) {
drv_buf_iter = &drv_bufs[0];
dprint_dump(drv_buf_iter->kern_buf,
- drv_buf_iter->kern_buf_len, "mpi3_mgmt_req");
+ rmc_size, "mpi3_mgmt_req");
}
}
-
if ((mpi_header->function == MPI3_BSG_FUNCTION_NVME_ENCAPSULATED) ||
(mpi_header->function == MPI3_BSG_FUNCTION_SCSI_IO))
mpi3mr_issue_tm(mrioc,
@@ -1382,17 +1681,27 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
if (drv_buf_iter->data_dir == DMA_NONE)
continue;
- if (drv_buf_iter->data_dir == DMA_FROM_DEVICE) {
- tmplen = min(drv_buf_iter->kern_buf_len,
- drv_buf_iter->bsg_buf_len);
+ if ((count == 1) && is_rmrb) {
memcpy(drv_buf_iter->bsg_buf,
- drv_buf_iter->kern_buf, tmplen);
+ drv_buf_iter->kern_buf,
+ drv_buf_iter->kern_buf_len);
+ } else if (drv_buf_iter->data_dir == DMA_FROM_DEVICE) {
+ tmplen = 0;
+ for (desc_count = 0;
+ desc_count < drv_buf_iter->num_dma_desc;
+ desc_count++) {
+ memcpy(((u8 *)drv_buf_iter->bsg_buf + tmplen),
+ drv_buf_iter->dma_desc[desc_count].addr,
+ drv_buf_iter->dma_desc[desc_count].size);
+ tmplen +=
+ drv_buf_iter->dma_desc[desc_count].size;
}
}
+ }
out_unlock:
if (din_buf) {
- *reply_payload_rcv_len =
+ job->reply_payload_rcv_len =
sg_copy_from_buffer(job->reply_payload.sg_list,
job->reply_payload.sg_cnt,
din_buf, job->reply_payload.payload_len);
@@ -1408,13 +1717,8 @@ out:
kfree(mpi_req);
if (drv_bufs) {
drv_buf_iter = drv_bufs;
- for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
- if (drv_buf_iter->kern_buf && drv_buf_iter->kern_buf_dma)
- dma_free_coherent(&mrioc->pdev->dev,
- drv_buf_iter->kern_buf_len,
- drv_buf_iter->kern_buf,
- drv_buf_iter->kern_buf_dma);
- }
+ for (count = 0; count < bufcnt; count++, drv_buf_iter++)
+ kfree(drv_buf_iter->dma_desc);
kfree(drv_bufs);
}
kfree(bsg_reply_buf);
@@ -1473,7 +1777,7 @@ static int mpi3mr_bsg_request(struct bsg_job *job)
rval = mpi3mr_bsg_process_drv_cmds(job);
break;
case MPI3MR_MPT_CMD:
- rval = mpi3mr_bsg_process_mpt_cmds(job, &reply_payload_rcv_len);
+ rval = mpi3mr_bsg_process_mpt_cmds(job);
break;
default:
pr_err("%s: unsupported BSG command(0x%08x)\n",
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 0d148c39eb..528f19f782 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -475,7 +475,7 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
* @op_reply_q: op_reply_qinfo object
* @reply_ci: operational reply descriptor's queue consumer index
*
- * Returns reply descriptor frame address
+ * Returns: reply descriptor frame address
*/
static inline struct mpi3_default_reply_descriptor *
mpi3mr_get_reply_desc(struct op_reply_qinfo *op_reply_q, u32 reply_ci)
@@ -1059,6 +1059,112 @@ enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc)
}
/**
+ * mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma
+ * @mrioc: Adapter instance reference
+ *
+ * Free the DMA memory allocated for IOCTL handling purpose.
+ *
+ * Return: None
+ */
+static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_ioc *mrioc)
+{
+ struct dma_memory_desc *mem_desc;
+ u16 i;
+
+ if (!mrioc->ioctl_dma_pool)
+ return;
+
+ for (i = 0; i < MPI3MR_NUM_IOCTL_SGE; i++) {
+ mem_desc = &mrioc->ioctl_sge[i];
+ if (mem_desc->addr) {
+ dma_pool_free(mrioc->ioctl_dma_pool,
+ mem_desc->addr,
+ mem_desc->dma_addr);
+ mem_desc->addr = NULL;
+ }
+ }
+ dma_pool_destroy(mrioc->ioctl_dma_pool);
+ mrioc->ioctl_dma_pool = NULL;
+ mem_desc = &mrioc->ioctl_chain_sge;
+
+ if (mem_desc->addr) {
+ dma_free_coherent(&mrioc->pdev->dev, mem_desc->size,
+ mem_desc->addr, mem_desc->dma_addr);
+ mem_desc->addr = NULL;
+ }
+ mem_desc = &mrioc->ioctl_resp_sge;
+ if (mem_desc->addr) {
+ dma_free_coherent(&mrioc->pdev->dev, mem_desc->size,
+ mem_desc->addr, mem_desc->dma_addr);
+ mem_desc->addr = NULL;
+ }
+
+ mrioc->ioctl_sges_allocated = false;
+}
+
+/**
+ * mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma
+ * @mrioc: Adapter instance reference
+ *
+ * This function allocates dmaable memory required to handle the
+ * application issued MPI3 IOCTL requests.
+ *
+ * Return: None
+ */
+static void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_ioc *mrioc)
+
+{
+ struct dma_memory_desc *mem_desc;
+ u16 i;
+
+ mrioc->ioctl_dma_pool = dma_pool_create("ioctl dma pool",
+ &mrioc->pdev->dev,
+ MPI3MR_IOCTL_SGE_SIZE,
+ MPI3MR_PAGE_SIZE_4K, 0);
+
+ if (!mrioc->ioctl_dma_pool) {
+ ioc_err(mrioc, "ioctl_dma_pool: dma_pool_create failed\n");
+ goto out_failed;
+ }
+
+ for (i = 0; i < MPI3MR_NUM_IOCTL_SGE; i++) {
+ mem_desc = &mrioc->ioctl_sge[i];
+ mem_desc->size = MPI3MR_IOCTL_SGE_SIZE;
+ mem_desc->addr = dma_pool_zalloc(mrioc->ioctl_dma_pool,
+ GFP_KERNEL,
+ &mem_desc->dma_addr);
+ if (!mem_desc->addr)
+ goto out_failed;
+ }
+
+ mem_desc = &mrioc->ioctl_chain_sge;
+ mem_desc->size = MPI3MR_PAGE_SIZE_4K;
+ mem_desc->addr = dma_alloc_coherent(&mrioc->pdev->dev,
+ mem_desc->size,
+ &mem_desc->dma_addr,
+ GFP_KERNEL);
+ if (!mem_desc->addr)
+ goto out_failed;
+
+ mem_desc = &mrioc->ioctl_resp_sge;
+ mem_desc->size = MPI3MR_PAGE_SIZE_4K;
+ mem_desc->addr = dma_alloc_coherent(&mrioc->pdev->dev,
+ mem_desc->size,
+ &mem_desc->dma_addr,
+ GFP_KERNEL);
+ if (!mem_desc->addr)
+ goto out_failed;
+
+ mrioc->ioctl_sges_allocated = true;
+
+ return;
+out_failed:
+ ioc_warn(mrioc, "cannot allocate DMA memory for the mpt commands\n"
+ "from the applications, application interface for MPT command is disabled\n");
+ mpi3mr_free_ioctl_dma_memory(mrioc);
+}
+
+/**
* mpi3mr_clear_reset_history - clear reset history
* @mrioc: Adapter instance reference
*
@@ -1133,7 +1239,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc,
* during reset/resume
* @mrioc: Adapter instance reference
*
- * Return zero if the new IOCFacts parameters value is compatible with
+ * Return: zero if the new IOCFacts parameters value is compatible with
* older values else return -EPERM
*/
static int
@@ -3194,6 +3300,9 @@ static int mpi3mr_issue_iocinit(struct mpi3mr_ioc *mrioc)
current_time = ktime_get_real();
iocinit_req.time_stamp = cpu_to_le64(ktime_to_ms(current_time));
+ iocinit_req.msg_flags |=
+ MPI3_IOCINIT_MSGFLAGS_SCSIIOSTATUSREPLY_SUPPORTED;
+
init_completion(&mrioc->init_cmds.done);
retval = mpi3mr_admin_request_post(mrioc, &iocinit_req,
sizeof(iocinit_req), 1);
@@ -3871,6 +3980,9 @@ retry_init:
}
}
+ dprint_init(mrioc, "allocating ioctl dma buffers\n");
+ mpi3mr_alloc_ioctl_dma_memory(mrioc);
+
if (!mrioc->init_cmds.reply) {
retval = mpi3mr_alloc_reply_sense_bufs(mrioc);
if (retval) {
@@ -4290,6 +4402,7 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
struct mpi3mr_intr_info *intr_info;
mpi3mr_free_enclosure_list(mrioc);
+ mpi3mr_free_ioctl_dma_memory(mrioc);
if (mrioc->sense_buf_pool) {
if (mrioc->sense_buf)
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index 872d4b809d..1bffd629c1 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -3205,6 +3205,7 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
tg = stgt_priv_data->throttle_group;
throttle_enabled_dev =
stgt_priv_data->io_throttle_enabled;
+ dev_handle = stgt_priv_data->dev_handle;
}
}
if (unlikely((data_len_blks >= mrioc->io_throttle_data_length) &&
diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c
index 82b55e9557..d32ad46318 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_transport.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c
@@ -1587,7 +1587,7 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
*/
struct host_port {
u64 sas_address;
- u32 phy_mask;
+ u64 phy_mask;
u16 handle;
u8 iounit_port_id;
u8 used;
@@ -1611,7 +1611,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
struct mpi3mr_sas_port *mr_sas_port)
{
struct mpi3mr_sas_phy *mr_sas_phy;
- u32 phy_mask_xor;
+ u64 phy_mask_xor;
u64 phys_to_be_added, phys_to_be_removed;
int i;
@@ -1619,7 +1619,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
mr_sas_port->marked_responding = 1;
dev_info(&mr_sas_port->port->dev,
- "sas_address(0x%016llx), old: port_id %d phy_mask 0x%x, new: port_id %d phy_mask:0x%x\n",
+ "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
mr_sas_port->remote_identify.sas_address,
mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
h_port->iounit_port_id, h_port->phy_mask);
@@ -1637,7 +1637,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
* if these phys are previously registered with another port
* then delete these phys from that port first.
*/
- for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u32)) {
+ for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
mr_sas_phy = &mrioc->sas_hba.phy[i];
if (mr_sas_phy->phy_belongs_to_port)
mpi3mr_del_phy_from_an_existing_port(mrioc,
@@ -1649,7 +1649,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
}
/* Delete the phys which are not part of current mr_sas_port's port. */
- for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u32)) {
+ for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) {
mr_sas_phy = &mrioc->sas_hba.phy[i];
if (mr_sas_phy->phy_belongs_to_port)
mpi3mr_del_phy_from_an_existing_port(mrioc,
@@ -1671,7 +1671,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
void
mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
{
- struct host_port h_port[32];
+ struct host_port *h_port = NULL;
int i, j, found, host_port_count = 0, port_idx;
u16 sz, attached_handle, ioc_status;
struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
@@ -1685,6 +1685,10 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
if (!sas_io_unit_pg0)
return;
+ h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
+ if (!h_port)
+ goto out;
+
if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
@@ -1742,7 +1746,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
port_list) {
ioc_info(mrioc,
- "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
+ "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
mr_sas_port->hba_port->port_id,
mr_sas_port->remote_identify.sas_address,
mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
@@ -1751,7 +1755,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
ioc_info(mrioc, "Host port details after reset\n");
for (i = 0; i < host_port_count; i++) {
ioc_info(mrioc,
- "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
+ "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
h_port[i].iounit_port_id, h_port[i].sas_address,
h_port[i].phy_mask, h_port[i].lowest_phy);
}
@@ -1814,6 +1818,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
}
}
out:
+ kfree(h_port);
kfree(sas_io_unit_pg0);
}
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index 4d0be5ab98..587f7d2482 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -643,18 +643,14 @@ typedef struct _MPI2_CHIP_REVISION_ID {
/*Manufacturing Page 2 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check Header.PageLength at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check Header.PageLength at
+ *runtime before using HwSettings[].
*/
-#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
-#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_MAN_2 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
MPI2_CHIP_REVISION_ID ChipId; /*0x04 */
- U32
- HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/*0x08 */
+ U32 HwSettings[]; /*0x08 */
} MPI2_CONFIG_PAGE_MAN_2,
*PTR_MPI2_CONFIG_PAGE_MAN_2,
Mpi2ManufacturingPage2_t,
@@ -666,18 +662,14 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_2 {
/*Manufacturing Page 3 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check Header.PageLength at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check Header.PageLength at
+ *runtime before using Info[].
*/
-#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
-#define MPI2_MAN_PAGE_3_INFO_WORDS (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_MAN_3 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
MPI2_CHIP_REVISION_ID ChipId; /*0x04 */
- U32
- Info[MPI2_MAN_PAGE_3_INFO_WORDS];/*0x08 */
+ U32 Info[]; /*0x08 */
} MPI2_CONFIG_PAGE_MAN_3,
*PTR_MPI2_CONFIG_PAGE_MAN_3,
Mpi2ManufacturingPage3_t,
@@ -765,12 +757,9 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_4 {
/*Manufacturing Page 5 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using Phy[].
*/
-#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
-#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1)
-#endif
typedef struct _MPI2_MANUFACTURING5_ENTRY {
U64 WWID; /*0x00 */
@@ -787,8 +776,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_5 {
U16 Reserved2; /*0x06 */
U32 Reserved3; /*0x08 */
U32 Reserved4; /*0x0C */
- MPI2_MANUFACTURING5_ENTRY
- Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/*0x08 */
+ MPI2_MANUFACTURING5_ENTRY Phy[]; /*0x10 */
} MPI2_CONFIG_PAGE_MAN_5,
*PTR_MPI2_CONFIG_PAGE_MAN_5,
Mpi2ManufacturingPage5_t,
@@ -864,12 +852,9 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
#define MPI2_MANPAGE7_SLOT_UNKNOWN (0xFFFF)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using ConnectorInfo[].
*/
-#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
-#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
@@ -880,8 +865,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
U8 NumPhys; /*0x20 */
U8 Reserved3; /*0x21 */
U16 Reserved4; /*0x22 */
- MPI2_MANPAGE7_CONNECTOR_INFO
- ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /*0x24 */
+ MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[]; /*0x24 */
} MPI2_CONFIG_PAGE_MAN_7,
*PTR_MPI2_CONFIG_PAGE_MAN_7,
Mpi2ManufacturingPage7_t,
@@ -990,7 +974,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for GPIOCount at runtime.
+ *36 and check the value returned for GPIOCount at runtime.
*/
#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (36)
@@ -1019,12 +1003,9 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
/*IO Unit Page 5 */
/*
- *Upper layer code (drivers, utilities, etc.) should leave this define set to
- *one and check the value returned for NumDmaEngines at runtime.
+ *Upper layer code (drivers, utilities, etc.) should check the value returned
+ *for NumDmaEngines at runtime before using DmaEngineCapabilities[].
*/
-#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
-#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
@@ -1042,7 +1023,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
U32 Reserved2; /*0x24 */
U32 Reserved3; /*0x28 */
U32
- DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /*0x2C */
+ DmaEngineCapabilities[]; /*0x2C */
} MPI2_CONFIG_PAGE_IO_UNIT_5,
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
Mpi2IOUnitPage5_t, *pMpi2IOUnitPage5_t;
@@ -1219,12 +1200,9 @@ typedef struct _MPI2_IOUNIT8_SENSOR {
#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumSensors at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumSensors at runtime before using Sensor[].
*/
-#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
-#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
@@ -1233,8 +1211,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
U8 NumSensors; /*0x0C */
U8 PollingInterval; /*0x0D */
U16 Reserved3; /*0x0E */
- MPI2_IOUNIT8_SENSOR
- Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/*0x10 */
+ MPI2_IOUNIT8_SENSOR Sensor[]; /*0x10 */
} MPI2_CONFIG_PAGE_IO_UNIT_8,
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
Mpi2IOUnitPage8_t, *pMpi2IOUnitPage8_t;
@@ -1259,12 +1236,9 @@ typedef struct _MPI2_IOUNIT9_SENSOR {
#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumSensors at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumSensors at runtime before using Sensor[].
*/
-#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
-#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
@@ -1273,8 +1247,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
U8 NumSensors; /*0x0C */
U8 Reserved4; /*0x0D */
U16 Reserved3; /*0x0E */
- MPI2_IOUNIT9_SENSOR
- Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/*0x10 */
+ MPI2_IOUNIT9_SENSOR Sensor[]; /*0x10 */
} MPI2_CONFIG_PAGE_IO_UNIT_9,
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
Mpi2IOUnitPage9_t, *pMpi2IOUnitPage9_t;
@@ -1294,12 +1267,9 @@ typedef struct _MPI2_IOUNIT10_FUNCTION {
*pMpi2IOUnit10Function_t;
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumFunctions at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumFunctions at runtime before using Function[].
*/
-#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
-#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
@@ -1308,8 +1278,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
U16 Reserved2; /*0x06 */
U32 Reserved3; /*0x08 */
U32 Reserved4; /*0x0C */
- MPI2_IOUNIT10_FUNCTION
- Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/*0x10 */
+ MPI2_IOUNIT10_FUNCTION Function[]; /*0x10 */
} MPI2_CONFIG_PAGE_IO_UNIT_10,
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
Mpi2IOUnitPage10_t, *pMpi2IOUnitPage10_t;
@@ -1764,12 +1733,9 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_3 {
/*BIOS Page 4 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using Phy[].
*/
-#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
-#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1)
-#endif
typedef struct _MPI2_BIOS4_ENTRY {
U64 ReassignmentWWID; /*0x00 */
@@ -1782,8 +1748,7 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_4 {
U8 NumPhys; /*0x04 */
U8 Reserved1; /*0x05 */
U16 Reserved2; /*0x06 */
- MPI2_BIOS4_ENTRY
- Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /*0x08 */
+ MPI2_BIOS4_ENTRY Phy[]; /*0x08 */
} MPI2_CONFIG_PAGE_BIOS_4, *PTR_MPI2_CONFIG_PAGE_BIOS_4,
Mpi2BiosPage4_t, *pMpi2BiosPage4_t;
@@ -1836,12 +1801,9 @@ typedef struct _MPI2_RAIDVOL0_SETTINGS {
#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhysDisks at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhysDisks at runtime before using PhysDisk[].
*/
-#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
-#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
@@ -1861,8 +1823,7 @@ typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 {
U8 Reserved2; /*0x25 */
U8 Reserved3; /*0x26 */
U8 InactiveStatus; /*0x27 */
- MPI2_RAIDVOL0_PHYS_DISK
- PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /*0x28 */
+ MPI2_RAIDVOL0_PHYS_DISK PhysDisk[]; /*0x28 */
} MPI2_CONFIG_PAGE_RAID_VOL_0,
*PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
Mpi2RaidVolPage0_t, *pMpi2RaidVolPage0_t;
@@ -2045,12 +2006,9 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 {
/*RAID Physical Disk Page 1 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhysDiskPaths at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhysDiskPaths at runtime before using PhysicalDiskPath[].
*/
-#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
-#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1)
-#endif
typedef struct _MPI2_RAIDPHYSDISK1_PATH {
U16 DevHandle; /*0x00 */
@@ -2075,8 +2033,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
U8 PhysDiskNum; /*0x05 */
U16 Reserved1; /*0x06 */
U32 Reserved2; /*0x08 */
- MPI2_RAIDPHYSDISK1_PATH
- PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/*0x0C */
+ MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[]; /*0x0C */
} MPI2_CONFIG_PAGE_RD_PDISK_1,
*PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
Mpi2RaidPhysDiskPage1_t,
@@ -2221,12 +2178,9 @@ typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA {
*pMpi2SasIOUnit0PhyData_t;
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using PhyData[].
*/
-#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
-#define MPI2_SAS_IOUNIT0_PHY_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -2234,8 +2188,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
U8 NumPhys; /*0x0C */
U8 Reserved2;/*0x0D */
U16 Reserved3;/*0x0E */
- MPI2_SAS_IO_UNIT0_PHY_DATA
- PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /*0x10 */
+ MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[];/*0x10 */
} MPI2_CONFIG_PAGE_SASIOUNIT_0,
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
Mpi2SasIOUnitPage0_t, *pMpi2SasIOUnitPage0_t;
@@ -2296,12 +2249,9 @@ typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA {
*pMpi2SasIOUnit1PhyData_t;
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using PhyData[].
*/
-#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
-#define MPI2_SAS_IOUNIT1_PHY_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -2322,7 +2272,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
U8
IODeviceMissingDelay; /*0x13 */
MPI2_SAS_IO_UNIT1_PHY_DATA
- PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /*0x14 */
+ PhyData[]; /*0x14 */
} MPI2_CONFIG_PAGE_SASIOUNIT_1,
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
Mpi2SasIOUnitPage1_t, *pMpi2SasIOUnitPage1_t;
@@ -2502,12 +2452,9 @@ typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS {
#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using SASPhyPowerManagementSettings[].
*/
-#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
-#define MPI2_SAS_IOUNIT5_PHY_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -2516,7 +2463,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
U16 Reserved2;/*0x0A */
U32 Reserved3;/*0x0C */
MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS
- SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];/*0x10 */
+ SASPhyPowerManagementSettings[]; /*0x10 */
} MPI2_CONFIG_PAGE_SASIOUNIT_5,
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
Mpi2SasIOUnitPage5_t, *pMpi2SasIOUnitPage5_t;
@@ -2554,12 +2501,9 @@ typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS {
#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumGroups at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumGroups at runtime before using PortWidthModulationGroupStatus[].
*/
-#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
-#define MPI2_SAS_IOUNIT6_GROUP_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -2569,7 +2513,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
U8 Reserved3; /*0x11 */
U16 Reserved4; /*0x12 */
MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
- PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /*0x14 */
+ PortWidthModulationGroupStatus[]; /*0x14 */
} MPI2_CONFIG_PAGE_SASIOUNIT_6,
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
Mpi2SasIOUnitPage6_t, *pMpi2SasIOUnitPage6_t;
@@ -2597,12 +2541,9 @@ typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS {
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumGroups at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumGroups at runtime before using PortWidthModulationGroupSettings[].
*/
-#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
-#define MPI2_SAS_IOUNIT7_GROUP_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -2615,7 +2556,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
U8 Reserved4; /*0x15 */
U16 Reserved5; /*0x16 */
MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
- PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX];/*0x18 */
+ PortWidthModulationGroupSettings[]; /*0x18 */
} MPI2_CONFIG_PAGE_SASIOUNIT_7,
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
Mpi2SasIOUnitPage7_t, *pMpi2SasIOUnitPage7_t;
@@ -3086,12 +3027,9 @@ typedef struct _MPI2_SASPHY2_PHY_EVENT {
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhyEvents at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhyEvents at runtime before using PhyEvent[].
*/
-#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
-#define MPI2_SASPHY2_PHY_EVENT_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER
@@ -3105,7 +3043,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
U16
Reserved3; /*0x0E */
MPI2_SASPHY2_PHY_EVENT
- PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /*0x10 */
+ PhyEvent[]; /*0x10 */
} MPI2_CONFIG_PAGE_SAS_PHY_2,
*PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
Mpi2SasPhyPage2_t,
@@ -3200,12 +3138,9 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhyEvents at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhyEvents at runtime before using PhyEventConfig[].
*/
-#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
-#define MPI2_SASPHY3_PHY_EVENT_MAX (1)
-#endif
typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER
@@ -3219,7 +3154,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
U16
Reserved3; /*0x0E */
MPI2_SASPHY3_PHY_EVENT_CONFIG
- PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /*0x10 */
+ PhyEventConfig[]; /*0x10 */
} MPI2_CONFIG_PAGE_SAS_PHY_3,
*PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
Mpi2SasPhyPage3_t, *pMpi2SasPhyPage3_t;
@@ -3358,12 +3293,9 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 {
/*Log Page 0 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumLogEntries at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumLogEntries at runtime before using LogEntry[].
*/
-#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
-#define MPI2_LOG_0_NUM_LOG_ENTRIES (1)
-#endif
#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C)
@@ -3393,8 +3325,7 @@ typedef struct _MPI2_CONFIG_PAGE_LOG_0 {
U32 Reserved2; /*0x0C */
U16 NumLogEntries;/*0x10 */
U16 Reserved3; /*0x12 */
- MPI2_LOG_0_ENTRY
- LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /*0x14 */
+ MPI2_LOG_0_ENTRY LogEntry[]; /*0x14 */
} MPI2_CONFIG_PAGE_LOG_0, *PTR_MPI2_CONFIG_PAGE_LOG_0,
Mpi2LogPage0_t, *pMpi2LogPage0_t;
@@ -3408,12 +3339,9 @@ typedef struct _MPI2_CONFIG_PAGE_LOG_0 {
/*RAID Page 0 */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumElements at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumElements at runtime before using ConfigElement[].
*/
-#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
-#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1)
-#endif
typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT {
U16 ElementFlags; /*0x00 */
@@ -3446,8 +3374,7 @@ typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 {
U8 NumElements; /*0x2C */
U8 Reserved2; /*0x2D */
U16 Reserved3; /*0x2E */
- MPI2_RAIDCONFIG0_CONFIG_ELEMENT
- ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /*0x30 */
+ MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[];/*0x30 */
} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
*PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
Mpi2RaidConfigurationPage0_t,
@@ -3687,12 +3614,9 @@ typedef struct _MPI26_PCIE_IO_UNIT0_PHY_DATA {
Mpi26PCIeIOUnit0PhyData_t, *pMpi26PCIeIOUnit0PhyData_t;
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using PhyData[].
*/
-#ifndef MPI26_PCIE_IOUNIT0_PHY_MAX
-#define MPI26_PCIE_IOUNIT0_PHY_MAX (1)
-#endif
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -3701,7 +3625,7 @@ typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_0 {
U8 InitStatus; /*0x0D */
U16 Reserved3; /*0x0E */
MPI26_PCIE_IO_UNIT0_PHY_DATA
- PhyData[MPI26_PCIE_IOUNIT0_PHY_MAX]; /*0x10 */
+ PhyData[]; /*0x10 */
} MPI26_CONFIG_PAGE_PIOUNIT_0,
*PTR_MPI26_CONFIG_PAGE_PIOUNIT_0,
Mpi26PCIeIOUnitPage0_t, *pMpi26PCIeIOUnitPage0_t;
@@ -3744,12 +3668,9 @@ typedef struct _MPI26_PCIE_IO_UNIT1_PHY_DATA {
#define MPI26_PCIEIOUNIT1_LINKFLAGS_SRNS_EN (0x02)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumPhys at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumPhys at runtime before using PhyData[].
*/
-#ifndef MPI26_PCIE_IOUNIT1_PHY_MAX
-#define MPI26_PCIE_IOUNIT1_PHY_MAX (1)
-#endif
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -3761,7 +3682,7 @@ typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1 {
U8 DMDReportPCIe; /*0x11 */
U16 Reserved2; /*0x12 */
MPI26_PCIE_IO_UNIT1_PHY_DATA
- PhyData[MPI26_PCIE_IOUNIT1_PHY_MAX];/*0x14 */
+ PhyData[]; /*0x14 */
} MPI26_CONFIG_PAGE_PIOUNIT_1,
*PTR_MPI26_CONFIG_PAGE_PIOUNIT_1,
Mpi26PCIeIOUnitPage1_t, *pMpi26PCIeIOUnitPage1_t;
@@ -3993,12 +3914,9 @@ typedef struct _MPI26_PCIELINK2_LINK_EVENT {
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumLinkEvents at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumLinkEvents at runtime before using LinkEvent[].
*/
-#ifndef MPI26_PCIELINK2_LINK_EVENT_MAX
-#define MPI26_PCIELINK2_LINK_EVENT_MAX (1)
-#endif
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -4009,7 +3927,7 @@ typedef struct _MPI26_CONFIG_PAGE_PCIELINK_2 {
U8 Reserved3; /*0x0D */
U16 Reserved4; /*0x0E */
MPI26_PCIELINK2_LINK_EVENT
- LinkEvent[MPI26_PCIELINK2_LINK_EVENT_MAX]; /*0x10 */
+ LinkEvent[]; /*0x10 */
} MPI26_CONFIG_PAGE_PCIELINK_2, *PTR_MPI26_CONFIG_PAGE_PCIELINK_2,
Mpi26PcieLinkPage2_t, *pMpi26PcieLinkPage2_t;
@@ -4067,12 +3985,9 @@ typedef struct _MPI26_PCIELINK3_LINK_EVENT_CONFIG {
#define MPI26_PCIELINK3_TFLAGS_EVENT_NOTIFY (0x0001)
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check the value returned for NumLinkEvents at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check the value returned
+ *for NumLinkEvents at runtime before using LinkEventConfig[].
*/
-#ifndef MPI26_PCIELINK3_LINK_EVENT_MAX
-#define MPI26_PCIELINK3_LINK_EVENT_MAX (1)
-#endif
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_3 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
@@ -4083,7 +3998,7 @@ typedef struct _MPI26_CONFIG_PAGE_PCIELINK_3 {
U8 Reserved3; /*0x0D */
U16 Reserved4; /*0x0E */
MPI26_PCIELINK3_LINK_EVENT_CONFIG
- LinkEventConfig[MPI26_PCIELINK3_LINK_EVENT_MAX]; /*0x10 */
+ LinkEventConfig[]; /*0x10 */
} MPI26_CONFIG_PAGE_PCIELINK_3, *PTR_MPI26_CONFIG_PAGE_PCIELINK_3,
Mpi26PcieLinkPage3_t, *pMpi26PcieLinkPage3_t;
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_image.h b/drivers/scsi/mpt3sas/mpi/mpi2_image.h
index 33b9c3a6fd..798ab6e33e 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_image.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_image.h
@@ -295,20 +295,9 @@ typedef struct _MPI2_EXT_IMAGE_HEADER {
/*FLASH Layout Extended Image Data */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check RegionsPerLayout at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check NumberOfLayouts and
+ *RegionsPerLayout at runtime before using Layout[] and Region[].
*/
-#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
-#define MPI2_FLASH_NUMBER_OF_REGIONS (1)
-#endif
-
-/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check NumberOfLayouts at runtime.
- */
-#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
-#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1)
-#endif
typedef struct _MPI2_FLASH_REGION {
U8 RegionType; /*0x00 */
@@ -325,7 +314,7 @@ typedef struct _MPI2_FLASH_LAYOUT {
U32 Reserved1; /*0x04 */
U32 Reserved2; /*0x08 */
U32 Reserved3; /*0x0C */
- MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS]; /*0x10 */
+ MPI2_FLASH_REGION Region[]; /*0x10 */
} MPI2_FLASH_LAYOUT, *PTR_MPI2_FLASH_LAYOUT,
Mpi2FlashLayout_t, *pMpi2FlashLayout_t;
@@ -339,7 +328,7 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA {
U16 MinimumSectorAlignment; /*0x08 */
U16 Reserved3; /*0x0A */
U32 Reserved4; /*0x0C */
- MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS]; /*0x10 */
+ MPI2_FLASH_LAYOUT Layout[]; /*0x10 */
} MPI2_FLASH_LAYOUT_DATA, *PTR_MPI2_FLASH_LAYOUT_DATA,
Mpi2FlashLayoutData_t, *pMpi2FlashLayoutData_t;
@@ -373,12 +362,9 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA {
/*Supported Devices Extended Image Data */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check NumberOfDevices at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check NumberOfDevices at
+ *runtime before using SupportedDevice[].
*/
-#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
-#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1)
-#endif
typedef struct _MPI2_SUPPORTED_DEVICE {
U16 DeviceID; /*0x00 */
@@ -399,7 +385,7 @@ typedef struct _MPI2_SUPPORTED_DEVICES_DATA {
U8 Reserved2; /*0x03 */
U32 Reserved3; /*0x04 */
MPI2_SUPPORTED_DEVICE
- SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES];/*0x08 */
+ SupportedDevice[]; /*0x08 */
} MPI2_SUPPORTED_DEVICES_DATA, *PTR_MPI2_SUPPORTED_DEVICES_DATA,
Mpi2SupportedDevicesData_t, *pMpi2SupportedDevicesData_t;
@@ -464,7 +450,7 @@ typedef struct _MPI25_ENCRYPTED_HASH_ENTRY {
U8 EncryptionAlgorithm; /*0x02 */
U8 Reserved1; /*0x03 */
U32 Reserved2; /*0x04 */
- U32 EncryptedHash[1]; /*0x08 */ /* variable length */
+ U32 EncryptedHash[]; /*0x08 */
} MPI25_ENCRYPTED_HASH_ENTRY, *PTR_MPI25_ENCRYPTED_HASH_ENTRY,
Mpi25EncryptedHashEntry_t, *pMpi25EncryptedHashEntry_t;
@@ -508,7 +494,7 @@ typedef struct _MPI25_ENCRYPTED_HASH_DATA {
U8 NumHash; /*0x01 */
U16 Reserved1; /*0x02 */
U32 Reserved2; /*0x04 */
- MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[1]; /*0x08 */
+ MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[]; /*0x08 */
} MPI25_ENCRYPTED_HASH_DATA, *PTR_MPI25_ENCRYPTED_HASH_DATA,
Mpi25EncryptedHashData_t, *pMpi25EncryptedHashData_t;
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
index 2c57115172..d928525911 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
@@ -808,12 +808,9 @@ typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK {
/*Integrated RAID Configuration Change List Event data */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check NumElements at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check NumElements at
+ *runtime before using ConfigElement[].
*/
-#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
-#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1)
-#endif
typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT {
U16 ElementFlags; /*0x00 */
@@ -848,7 +845,7 @@ typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST {
U8 ConfigNum; /*0x03 */
U32 Flags; /*0x04 */
MPI2_EVENT_IR_CONFIG_ELEMENT
- ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];/*0x08 */
+ ConfigElement[];/*0x08 */
} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
*PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
Mpi2EventDataIrConfigChangeList_t,
@@ -969,12 +966,9 @@ typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW {
/*SAS Topology Change List Event data */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check NumEntries at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check NumEntries at
+ *runtime before using PHY[].
*/
-#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
-#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1)
-#endif
typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY {
U16 AttachedDevHandle; /*0x00 */
@@ -994,7 +988,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST {
U8 ExpStatus; /*0x0A */
U8 PhysicalPort; /*0x0B */
MPI2_EVENT_SAS_TOPO_PHY_ENTRY
- PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /*0x0C */
+ PHY[]; /*0x0C */
} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
*PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
Mpi2EventDataSasTopologyChangeList_t,
@@ -1229,12 +1223,9 @@ typedef struct _MPI26_EVENT_DATA_PCIE_ENUMERATION {
/*PCIe Topology Change List Event data (MPI v2.6 and later) */
/*
- *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- *one and check NumEntries at runtime.
+ *Host code (drivers, BIOS, utilities, etc.) should check NumEntries at
+ *runtime before using PortEntry[].
*/
-#ifndef MPI26_EVENT_PCIE_TOPO_PORT_COUNT
-#define MPI26_EVENT_PCIE_TOPO_PORT_COUNT (1)
-#endif
typedef struct _MPI26_EVENT_PCIE_TOPO_PORT_ENTRY {
U16 AttachedDevHandle; /*0x00 */
@@ -1286,7 +1277,7 @@ typedef struct _MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST {
U8 SwitchStatus; /*0x0A */
U8 PhysicalPort; /*0x0B */
MPI26_EVENT_PCIE_TOPO_PORT_ENTRY
- PortEntry[MPI26_EVENT_PCIE_TOPO_PORT_COUNT]; /*0x0C */
+ PortEntry[]; /*0x0C */
} MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
*PTR_MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
Mpi26EventDataPCIeTopologyChangeList_t,
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index aa29e250cf..b8120ca93c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -4893,8 +4893,7 @@ mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
if (!num_phys)
return;
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
+ sz = struct_size(sas_iounit_pg1, PhyData, num_phys);
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg1) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -5044,7 +5043,7 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
{
Mpi26DriverTriggerPage2_t trigger_pg2;
struct SL_WH_EVENT_TRIGGER_T *event_tg;
- MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY *mpi_event_tg;
+ MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY *mpi_event_tg;
Mpi2ConfigReply_t mpi_reply;
int r = 0, i = 0;
u16 count = 0;
@@ -5096,7 +5095,7 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
{
Mpi26DriverTriggerPage3_t trigger_pg3;
struct SL_WH_SCSI_TRIGGER_T *scsi_tg;
- MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY *mpi_scsi_tg;
+ MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY *mpi_scsi_tg;
Mpi2ConfigReply_t mpi_reply;
int r = 0, i = 0;
u16 count = 0;
@@ -5148,7 +5147,7 @@ _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
{
Mpi26DriverTriggerPage4_t trigger_pg4;
struct SL_WH_MPI_TRIGGER_T *status_tg;
- MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY *mpi_status_tg;
+ MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY *mpi_status_tg;
Mpi2ConfigReply_t mpi_reply;
int r = 0, i = 0;
u16 count = 0;
@@ -5379,10 +5378,9 @@ _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc)
static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
{
Mpi2ConfigReply_t mpi_reply;
- Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+ Mpi2SasIOUnitPage1_t sas_iounit_pg1;
Mpi26PCIeIOUnitPage1_t pcie_iounit_pg1;
u16 depth;
- int sz;
int rc = 0;
ioc->max_wideport_qd = MPT3SAS_SAS_QUEUE_DEPTH;
@@ -5392,28 +5390,21 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
if (!ioc->is_gen35_ioc)
goto out;
/* sas iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData);
- sas_iounit_pg1 = kzalloc(sizeof(Mpi2SasIOUnitPage1_t), GFP_KERNEL);
- if (!sas_iounit_pg1) {
- pr_err("%s: failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return rc;
- }
rc = mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
- sas_iounit_pg1, sz);
+ &sas_iounit_pg1, sizeof(Mpi2SasIOUnitPage1_t));
if (rc) {
pr_err("%s: failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
goto out;
}
- depth = le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth);
+ depth = le16_to_cpu(sas_iounit_pg1.SASWideMaxQueueDepth);
ioc->max_wideport_qd = (depth ? depth : MPT3SAS_SAS_QUEUE_DEPTH);
- depth = le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth);
+ depth = le16_to_cpu(sas_iounit_pg1.SASNarrowMaxQueueDepth);
ioc->max_narrowport_qd = (depth ? depth : MPT3SAS_SAS_QUEUE_DEPTH);
- depth = sas_iounit_pg1->SATAMaxQDepth;
+ depth = sas_iounit_pg1.SATAMaxQDepth;
ioc->max_sata_qd = (depth ? depth : MPT3SAS_SATA_QUEUE_DEPTH);
/* pcie iounit page 1 */
@@ -5432,7 +5423,6 @@ out:
"MaxWidePortQD: 0x%x MaxNarrowPortQD: 0x%x MaxSataQD: 0x%x MaxNvmeQD: 0x%x\n",
ioc->max_wideport_qd, ioc->max_narrowport_qd,
ioc->max_sata_qd, ioc->max_nvme_qd));
- kfree(sas_iounit_pg1);
return rc;
}
@@ -5588,6 +5578,7 @@ out:
static int
_base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
{
+ Mpi2IOUnitPage8_t iounit_pg8;
Mpi2ConfigReply_t mpi_reply;
u32 iounit_pg1_flags;
int tg_flags = 0;
@@ -5684,7 +5675,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
rc = mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
if (rc)
return rc;
- rc = mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8);
+ rc = mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &iounit_pg8);
if (rc)
return rc;
_base_display_ioc_capabilities(ioc);
@@ -5706,8 +5697,8 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
if (rc)
return rc;
- if (ioc->iounit_pg8.NumSensors)
- ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors;
+ if (iounit_pg8.NumSensors)
+ ioc->temp_sensors_count = iounit_pg8.NumSensors;
if (ioc->is_aero_ioc) {
rc = _base_update_ioc_page1_inlinewith_perf_mode(ioc);
if (rc)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 1be0850ca1..6d0bc8c667 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1237,7 +1237,6 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @ioc_pg8: static ioc page 8
* @iounit_pg0: static iounit page 0
* @iounit_pg1: static iounit page 1
- * @iounit_pg8: static iounit page 8
* @sas_hba: sas host object
* @sas_expander_list: expander object list
* @enclosure_list: enclosure object list
@@ -1465,7 +1464,6 @@ struct MPT3SAS_ADAPTER {
Mpi2IOCPage8_t ioc_pg8;
Mpi2IOUnitPage0_t iounit_pg0;
Mpi2IOUnitPage1_t iounit_pg1;
- Mpi2IOUnitPage8_t iounit_pg8;
Mpi2IOCPage1_t ioc_pg1_copy;
struct _boot_device req_boot_device;
@@ -1983,6 +1981,7 @@ extern const struct attribute_group *mpt3sas_host_groups[];
extern const struct attribute_group *mpt3sas_dev_groups[];
void mpt3sas_ctl_init(ushort hbas_to_enumerate);
void mpt3sas_ctl_exit(ushort hbas_to_enumerate);
+void mpt3sas_ctl_release(struct MPT3SAS_ADAPTER *ioc);
u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
index d114ef381c..2e88f456fc 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -2334,7 +2334,7 @@ mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
tg_pg2.NumMPIEventTrigger = 0;
memset(&tg_pg2.MPIEventTriggers[0], 0,
NUM_VALID_ENTRIES * sizeof(
- MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
+ MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY));
}
rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
@@ -2493,7 +2493,7 @@ mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
tg_pg3.NumSCSISenseTrigger = 0;
memset(&tg_pg3.SCSISenseTriggers[0], 0,
NUM_VALID_ENTRIES * sizeof(
- MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
+ MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY));
}
rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
@@ -2649,7 +2649,7 @@ mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
tg_pg4.NumIOCStatusLogInfoTrigger = 0;
memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
NUM_VALID_ENTRIES * sizeof(
- MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
+ MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY));
}
rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index efdb8178db..147cb7088d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -4157,31 +4157,37 @@ mpt3sas_ctl_init(ushort hbas_to_enumerate)
}
/**
- * mpt3sas_ctl_exit - exit point for ctl
- * @hbas_to_enumerate: ?
+ * mpt3sas_ctl_release - release dma for ctl
+ * @ioc: per adapter object
*/
void
-mpt3sas_ctl_exit(ushort hbas_to_enumerate)
+mpt3sas_ctl_release(struct MPT3SAS_ADAPTER *ioc)
{
- struct MPT3SAS_ADAPTER *ioc;
int i;
- list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
+ /* free memory associated to diag buffers */
+ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+ if (!ioc->diag_buffer[i])
+ continue;
+ dma_free_coherent(&ioc->pdev->dev,
+ ioc->diag_buffer_sz[i],
+ ioc->diag_buffer[i],
+ ioc->diag_buffer_dma[i]);
+ ioc->diag_buffer[i] = NULL;
+ ioc->diag_buffer_status[i] = 0;
+ }
- /* free memory associated to diag buffers */
- for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
- if (!ioc->diag_buffer[i])
- continue;
- dma_free_coherent(&ioc->pdev->dev,
- ioc->diag_buffer_sz[i],
- ioc->diag_buffer[i],
- ioc->diag_buffer_dma[i]);
- ioc->diag_buffer[i] = NULL;
- ioc->diag_buffer_status[i] = 0;
- }
+ kfree(ioc->event_log);
+}
+
+/**
+ * mpt3sas_ctl_exit - exit point for ctl
+ * @hbas_to_enumerate: ?
+ */
+void
+mpt3sas_ctl_exit(ushort hbas_to_enumerate)
+{
- kfree(ioc->event_log);
- }
if (hbas_to_enumerate != 1)
misc_deregister(&ctl_dev);
if (hbas_to_enumerate != 2)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 605013d3ee..51b5788da0 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2431,8 +2431,7 @@ _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
}
raid_device->num_pds = num_pds;
- sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
- sizeof(Mpi2RaidVol0PhysDisk_t));
+ sz = struct_size(vol_pg0, PhysDisk, num_pds);
vol_pg0 = kzalloc(sz, GFP_KERNEL);
if (!vol_pg0) {
dfailprintk(ioc,
@@ -5966,8 +5965,7 @@ _scsih_update_vphys_after_reset(struct MPT3SAS_ADAPTER *ioc)
/*
* Read SASIOUnitPage0 to get each HBA Phy's data.
*/
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) +
- (ioc->sas_hba.num_phys * sizeof(Mpi2SasIOUnit0PhyData_t));
+ sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg0) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -6145,8 +6143,7 @@ _scsih_get_port_table_after_reset(struct MPT3SAS_ADAPTER *ioc,
u64 attached_sas_addr;
u8 found = 0, port_count = 0, port_id;
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
- * sizeof(Mpi2SasIOUnit0PhyData_t));
+ sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg0) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -6579,8 +6576,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n",
(u64)ioc->sas_hba.sas_address));
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
- * sizeof(Mpi2SasIOUnit0PhyData_t));
+ sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg0) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -6731,8 +6727,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
ioc->sas_hba.num_phys = num_phys;
/* sas_iounit page 0 */
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit0PhyData_t));
+ sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg0) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -6754,8 +6749,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
}
/* sas_iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
+ sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg1) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -10376,8 +10370,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
Mpi2ExpanderPage0_t expander_pg0;
Mpi2SasDevicePage0_t sas_device_pg0;
Mpi26PCIeDevicePage0_t pcie_device_pg0;
- Mpi2RaidVolPage1_t *volume_pg1;
- Mpi2RaidVolPage0_t *volume_pg0;
+ Mpi2RaidVolPage1_t volume_pg1;
+ Mpi2RaidVolPage0_t volume_pg0;
Mpi2RaidPhysDiskPage0_t pd_pg0;
Mpi2EventIrConfigElement_t element;
Mpi2ConfigReply_t mpi_reply;
@@ -10392,16 +10386,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
u8 retry_count;
unsigned long flags;
- volume_pg0 = kzalloc(sizeof(*volume_pg0), GFP_KERNEL);
- if (!volume_pg0)
- return;
-
- volume_pg1 = kzalloc(sizeof(*volume_pg1), GFP_KERNEL);
- if (!volume_pg1) {
- kfree(volume_pg0);
- return;
- }
-
ioc_info(ioc, "scan devices: start\n");
_scsih_sas_host_refresh(ioc);
@@ -10511,7 +10495,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
/* volumes */
handle = 0xFFFF;
while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
- volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+ &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
@@ -10519,15 +10503,15 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
ioc_status, le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
- handle = le16_to_cpu(volume_pg1->DevHandle);
+ handle = le16_to_cpu(volume_pg1.DevHandle);
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_wwid(ioc,
- le64_to_cpu(volume_pg1->WWID));
+ le64_to_cpu(volume_pg1.WWID));
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (raid_device)
continue;
if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
- volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+ &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t)))
continue;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
@@ -10537,17 +10521,17 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
ioc_status, le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
- if (volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
- volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
- volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
+ if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
+ volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
+ volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
- element.VolDevHandle = volume_pg1->DevHandle;
+ element.VolDevHandle = volume_pg1.DevHandle;
ioc_info(ioc, "\tBEFORE adding volume: handle (0x%04x)\n",
- volume_pg1->DevHandle);
+ volume_pg1.DevHandle);
_scsih_sas_volume_add(ioc, &element);
ioc_info(ioc, "\tAFTER adding volume: handle (0x%04x)\n",
- volume_pg1->DevHandle);
+ volume_pg1.DevHandle);
}
}
@@ -10636,9 +10620,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
handle, (u64)le64_to_cpu(pcie_device_pg0.WWID));
}
- kfree(volume_pg0);
- kfree(volume_pg1);
-
ioc_info(ioc, "\tpcie devices: pcie end devices complete\n");
ioc_info(ioc, "scan devices: complete\n");
}
@@ -11350,6 +11331,7 @@ static void scsih_remove(struct pci_dev *pdev)
}
mpt3sas_base_detach(ioc);
+ mpt3sas_ctl_release(ioc);
spin_lock(&gioc_lock);
list_del(&ioc->list);
spin_unlock(&gioc_lock);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index e8a4750f6e..421ea511b6 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -1792,8 +1792,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
/* handle hba phys */
/* read sas_iounit page 0 */
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit0PhyData_t));
+ sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg0) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -1833,8 +1832,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
}
/* read sas_iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
+ sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg1) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -1944,8 +1942,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
/* handle hba phys */
/* sas_iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
+ sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys);
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
if (!sas_iounit_pg1) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h
index 5f3328f011..edb8fe7090 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h
@@ -20,12 +20,12 @@
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER (0xE0)
#define MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION (0x01)
-typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0 {
+typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 TriggerFlags; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
U32 Reserved0xC[61]; /* 0x0C */
-} _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0, Mpi26DriverTriggerPage0_t;
+} _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_0, Mpi26DriverTriggerPage0_t;
/* Trigger Flags */
#define MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID (0x0001)
@@ -34,61 +34,61 @@ typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0 {
#define MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID (0x0008)
#define MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION (0x01)
-typedef struct _MPI26_DRIVER_MASTER_TIGGER_ENTRY {
+typedef struct _MPI26_DRIVER_MASTER_TRIGGER_ENTRY {
U32 MasterTriggerFlags;
-} MPI26_DRIVER_MASTER_TIGGER_ENTRY;
+} MPI26_DRIVER_MASTER_TRIGGER_ENTRY;
#define MPI26_MAX_MASTER_TRIGGERS (1)
-typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_1 {
+typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumMasterTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
- MPI26_DRIVER_MASTER_TIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */
-} MPI26_CONFIG_PAGE_DRIVER_TIGGER_1, Mpi26DriverTriggerPage1_t;
+ MPI26_DRIVER_MASTER_TRIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */
+} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_1, Mpi26DriverTriggerPage1_t;
#define MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION (0x01)
-typedef struct _MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY {
+typedef struct _MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY {
U16 MPIEventCode; /* 0x00 */
U16 MPIEventCodeSpecific; /* 0x02 */
-} MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY;
+} MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY;
#define MPI26_MAX_MPI_EVENT_TRIGGERS (20)
-typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_2 {
+typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumMPIEventTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
- MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */
-} MPI26_CONFIG_PAGE_DRIVER_TIGGER_2, Mpi26DriverTriggerPage2_t;
+ MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */
+} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_2, Mpi26DriverTriggerPage2_t;
#define MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION (0x01)
-typedef struct _MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY {
+typedef struct _MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY {
U8 ASCQ; /* 0x00 */
U8 ASC; /* 0x01 */
U8 SenseKey; /* 0x02 */
U8 Reserved; /* 0x03 */
-} MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY;
+} MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY;
#define MPI26_MAX_SCSI_SENSE_TRIGGERS (20)
-typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_3 {
+typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_3 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumSCSISenseTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
- MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */
-} MPI26_CONFIG_PAGE_DRIVER_TIGGER_3, Mpi26DriverTriggerPage3_t;
+ MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */
+} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_3, Mpi26DriverTriggerPage3_t;
#define MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION (0x01)
-typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY {
+typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY {
U16 IOCStatus; /* 0x00 */
U16 Reserved; /* 0x02 */
U32 LogInfo; /* 0x04 */
-} MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY;
+} MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY;
#define MPI26_MAX_LOGINFO_TRIGGERS (20)
-typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_4 {
+typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_4 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumIOCStatusLogInfoTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
- MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */
-} MPI26_CONFIG_PAGE_DRIVER_TIGGER_4, Mpi26DriverTriggerPage4_t;
+ MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */
+} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_4, Mpi26DriverTriggerPage4_t;
#endif
diff --git a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
index cc07ba41f5..1d64e5056a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
@@ -141,8 +141,7 @@ mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
return;
}
- sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
- sizeof(Mpi2RaidVol0PhysDisk_t));
+ sz = struct_size(vol_pg0, PhysDisk, num_pds);
vol_pg0 = kzalloc(sz, GFP_KERNEL);
if (!vol_pg0) {
ioc_info(ioc, "WarpDrive : Direct IO is disabled Memory allocation failure for RVPG0\n");
diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c
index 21d638299a..e08a38e2a4 100644
--- a/drivers/scsi/mvme16x_scsi.c
+++ b/drivers/scsi/mvme16x_scsi.c
@@ -103,7 +103,7 @@ static int mvme16x_probe(struct platform_device *dev)
return -ENODEV;
}
-static int mvme16x_device_remove(struct platform_device *dev)
+static void mvme16x_device_remove(struct platform_device *dev)
{
struct Scsi_Host *host = platform_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
@@ -120,8 +120,6 @@ static int mvme16x_device_remove(struct platform_device *dev)
NCR_700_release(host);
kfree(hostdata);
free_irq(host->irq, host);
-
- return 0;
}
static struct platform_driver mvme16x_scsi_driver = {
@@ -129,7 +127,7 @@ static struct platform_driver mvme16x_scsi_driver = {
.name = "mvme16x-scsi",
},
.probe = mvme16x_probe,
- .remove = mvme16x_device_remove,
+ .remove_new = mvme16x_device_remove,
};
static int __init mvme16x_scsi_init(void)
diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c
index ca2e932dd9..f684eb5e04 100644
--- a/drivers/scsi/myrb.c
+++ b/drivers/scsi/myrb.c
@@ -1775,9 +1775,9 @@ static ssize_t raid_state_show(struct device *dev,
name = myrb_devstate_name(ldev_info->state);
if (name)
- ret = snprintf(buf, 32, "%s\n", name);
+ ret = snprintf(buf, 64, "%s\n", name);
else
- ret = snprintf(buf, 32, "Invalid (%02X)\n",
+ ret = snprintf(buf, 64, "Invalid (%02X)\n",
ldev_info->state);
} else {
struct myrb_pdev_state *pdev_info = sdev->hostdata;
@@ -1796,9 +1796,9 @@ static ssize_t raid_state_show(struct device *dev,
else
name = myrb_devstate_name(pdev_info->state);
if (name)
- ret = snprintf(buf, 32, "%s\n", name);
+ ret = snprintf(buf, 64, "%s\n", name);
else
- ret = snprintf(buf, 32, "Invalid (%02X)\n",
+ ret = snprintf(buf, 64, "Invalid (%02X)\n",
pdev_info->state);
}
return ret;
@@ -1886,11 +1886,11 @@ static ssize_t raid_level_show(struct device *dev,
name = myrb_raidlevel_name(ldev_info->raid_level);
if (!name)
- return snprintf(buf, 32, "Invalid (%02X)\n",
+ return snprintf(buf, 64, "Invalid (%02X)\n",
ldev_info->state);
- return snprintf(buf, 32, "%s\n", name);
+ return snprintf(buf, 64, "%s\n", name);
}
- return snprintf(buf, 32, "Physical Drive\n");
+ return snprintf(buf, 64, "Physical Drive\n");
}
static DEVICE_ATTR_RO(raid_level);
@@ -1903,15 +1903,15 @@ static ssize_t rebuild_show(struct device *dev,
unsigned char status;
if (sdev->channel < myrb_logical_channel(sdev->host))
- return snprintf(buf, 32, "physical device - not rebuilding\n");
+ return snprintf(buf, 64, "physical device - not rebuilding\n");
status = myrb_get_rbld_progress(cb, &rbld_buf);
if (rbld_buf.ldev_num != sdev->id ||
status != MYRB_STATUS_SUCCESS)
- return snprintf(buf, 32, "not rebuilding\n");
+ return snprintf(buf, 64, "not rebuilding\n");
- return snprintf(buf, 32, "rebuilding block %u of %u\n",
+ return snprintf(buf, 64, "rebuilding block %u of %u\n",
rbld_buf.ldev_size - rbld_buf.blocks_left,
rbld_buf.ldev_size);
}
diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
index a1eec65a97..e824be9d9b 100644
--- a/drivers/scsi/myrs.c
+++ b/drivers/scsi/myrs.c
@@ -947,9 +947,9 @@ static ssize_t raid_state_show(struct device *dev,
name = myrs_devstate_name(ldev_info->dev_state);
if (name)
- ret = snprintf(buf, 32, "%s\n", name);
+ ret = snprintf(buf, 64, "%s\n", name);
else
- ret = snprintf(buf, 32, "Invalid (%02X)\n",
+ ret = snprintf(buf, 64, "Invalid (%02X)\n",
ldev_info->dev_state);
} else {
struct myrs_pdev_info *pdev_info;
@@ -958,9 +958,9 @@ static ssize_t raid_state_show(struct device *dev,
pdev_info = sdev->hostdata;
name = myrs_devstate_name(pdev_info->dev_state);
if (name)
- ret = snprintf(buf, 32, "%s\n", name);
+ ret = snprintf(buf, 64, "%s\n", name);
else
- ret = snprintf(buf, 32, "Invalid (%02X)\n",
+ ret = snprintf(buf, 64, "Invalid (%02X)\n",
pdev_info->dev_state);
}
return ret;
@@ -1066,13 +1066,13 @@ static ssize_t raid_level_show(struct device *dev,
ldev_info = sdev->hostdata;
name = myrs_raid_level_name(ldev_info->raid_level);
if (!name)
- return snprintf(buf, 32, "Invalid (%02X)\n",
+ return snprintf(buf, 64, "Invalid (%02X)\n",
ldev_info->dev_state);
} else
name = myrs_raid_level_name(MYRS_RAID_PHYSICAL);
- return snprintf(buf, 32, "%s\n", name);
+ return snprintf(buf, 64, "%s\n", name);
}
static DEVICE_ATTR_RO(raid_level);
@@ -1086,7 +1086,7 @@ static ssize_t rebuild_show(struct device *dev,
unsigned char status;
if (sdev->channel < cs->ctlr_info->physchan_present)
- return snprintf(buf, 32, "physical device - not rebuilding\n");
+ return snprintf(buf, 64, "physical device - not rebuilding\n");
ldev_info = sdev->hostdata;
ldev_num = ldev_info->ldev_num;
@@ -1098,11 +1098,11 @@ static ssize_t rebuild_show(struct device *dev,
return -EIO;
}
if (ldev_info->rbld_active) {
- return snprintf(buf, 32, "rebuilding block %zu of %zu\n",
+ return snprintf(buf, 64, "rebuilding block %zu of %zu\n",
(size_t)ldev_info->rbld_lba,
(size_t)ldev_info->cfg_devsize);
} else
- return snprintf(buf, 32, "not rebuilding\n");
+ return snprintf(buf, 64, "not rebuilding\n");
}
static ssize_t rebuild_store(struct device *dev,
@@ -1190,7 +1190,7 @@ static ssize_t consistency_check_show(struct device *dev,
unsigned short ldev_num;
if (sdev->channel < cs->ctlr_info->physchan_present)
- return snprintf(buf, 32, "physical device - not checking\n");
+ return snprintf(buf, 64, "physical device - not checking\n");
ldev_info = sdev->hostdata;
if (!ldev_info)
@@ -1198,11 +1198,11 @@ static ssize_t consistency_check_show(struct device *dev,
ldev_num = ldev_info->ldev_num;
myrs_get_ldev_info(cs, ldev_num, ldev_info);
if (ldev_info->cc_active)
- return snprintf(buf, 32, "checking block %zu of %zu\n",
+ return snprintf(buf, 64, "checking block %zu of %zu\n",
(size_t)ldev_info->cc_lba,
(size_t)ldev_info->cfg_devsize);
else
- return snprintf(buf, 32, "not checking\n");
+ return snprintf(buf, 64, "not checking\n");
}
static ssize_t consistency_check_store(struct device *dev,
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
index 26e6b3e3af..dcde55c8ee 100644
--- a/drivers/scsi/qla2xxx/qla_edif.c
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -1100,7 +1100,7 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
if (fcport->edif.enable) {
- if (pcnt > app_req.num_ports)
+ if (pcnt >= app_req.num_ports)
break;
app_reply->elem[pcnt].rekey_count =
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 931bdaeaee..1e2f52210f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2889,7 +2889,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
static void
qla_trace_init(void)
{
- qla_trc_array = trace_array_get_by_name("qla2xxx");
+ qla_trc_array = trace_array_get_by_name("qla2xxx", NULL);
if (!qla_trc_array) {
ql_log(ql_log_fatal, NULL, 0x0001,
"Unable to create qla2xxx trace instance, instance logging will be disabled.\n");
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 3b95f7a621..5d560d9b89 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1409,7 +1409,7 @@ fail_unlink:
return -ENODEV;
}
-static int qpti_sbus_remove(struct platform_device *op)
+static void qpti_sbus_remove(struct platform_device *op)
{
struct qlogicpti *qpti = dev_get_drvdata(&op->dev);
@@ -1438,8 +1438,6 @@ static int qpti_sbus_remove(struct platform_device *op)
of_iounmap(&op->resource[0], qpti->sreg, sizeof(unsigned char));
scsi_host_put(qpti->qhost);
-
- return 0;
}
static const struct of_device_id qpti_match[] = {
@@ -1465,7 +1463,7 @@ static struct platform_driver qpti_sbus_driver = {
.of_match_table = qpti_match,
},
.probe = qpti_sbus_probe,
- .remove = qpti_sbus_remove,
+ .remove_new = qpti_sbus_remove,
};
module_platform_driver(qpti_sbus_driver);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6d8218a441..d03d66f114 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -339,7 +339,7 @@ struct sdebug_dev_info {
bool used;
/* For ZBC devices */
- enum blk_zoned_model zmodel;
+ bool zoned;
unsigned int zcap;
unsigned int zsize;
unsigned int zsize_shift;
@@ -844,8 +844,11 @@ static bool write_since_sync;
static bool sdebug_statistics = DEF_STATISTICS;
static bool sdebug_wp;
static bool sdebug_allow_restart;
-/* Following enum: 0: no zbc, def; 1: host aware; 2: host managed */
-static enum blk_zoned_model sdeb_zbc_model = BLK_ZONED_NONE;
+static enum {
+ BLK_ZONED_NONE = 0,
+ BLK_ZONED_HA = 1,
+ BLK_ZONED_HM = 2,
+} sdeb_zbc_model = BLK_ZONED_NONE;
static char *sdeb_zbc_model_s;
enum sam_lun_addr_method {SAM_LUN_AM_PERIPHERAL = 0x0,
@@ -1815,8 +1818,6 @@ static int inquiry_vpd_b1(struct sdebug_dev_info *devip, unsigned char *arr)
arr[1] = 1; /* non rotating medium (e.g. solid state) */
arr[2] = 0;
arr[3] = 5; /* less than 1.8" */
- if (devip->zmodel == BLK_ZONED_HA)
- arr[4] = 1 << 4; /* zoned field = 01b */
return 0x3c;
}
@@ -1883,7 +1884,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
if (! arr)
return DID_REQUEUE << 16;
is_disk = (sdebug_ptype == TYPE_DISK);
- is_zbc = (devip->zmodel != BLK_ZONED_NONE);
+ is_zbc = devip->zoned;
is_disk_zbc = (is_disk || is_zbc);
have_wlun = scsi_is_wlun(scp->device->lun);
if (have_wlun)
@@ -2195,7 +2196,7 @@ static int resp_readcap16(struct scsi_cmnd *scp,
* Since the scsi_debug READ CAPACITY implementation always reports the
* total disk capacity, set RC BASIS = 1 for host-managed ZBC devices.
*/
- if (devip->zmodel == BLK_ZONED_HM)
+ if (devip->zoned)
arr[12] |= 1 << 4;
arr[15] = sdebug_lowest_aligned & 0xff;
@@ -2648,7 +2649,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
msense_6 = (MODE_SENSE == cmd[0]);
llbaa = msense_6 ? false : !!(cmd[1] & 0x10);
is_disk = (sdebug_ptype == TYPE_DISK);
- is_zbc = (devip->zmodel != BLK_ZONED_NONE);
+ is_zbc = devip->zoned;
if ((is_disk || is_zbc) && !dbd)
bd_len = llbaa ? 16 : 8;
else
@@ -3194,8 +3195,6 @@ static int check_zbc_access_params(struct scsi_cmnd *scp,
struct sdeb_zone_state *zsp_end = zbc_zone(devip, lba + num - 1);
if (!write) {
- if (devip->zmodel == BLK_ZONED_HA)
- return 0;
/* For host-managed, reads cannot cross zone types boundaries */
if (zsp->z_type != zsp_end->z_type) {
mk_sense_buffer(scp, ILLEGAL_REQUEST,
@@ -5322,7 +5321,7 @@ static int sdebug_device_create_zones(struct sdebug_dev_info *devip)
if (devip->zcap < devip->zsize)
devip->nr_zones += devip->nr_seq_zones;
- if (devip->zmodel == BLK_ZONED_HM) {
+ if (devip->zoned) {
/* zbc_max_open_zones can be 0, meaning "not reported" */
if (sdeb_zbc_max_open >= devip->nr_zones - 1)
devip->max_open = (devip->nr_zones - 1) / 2;
@@ -5347,7 +5346,7 @@ static int sdebug_device_create_zones(struct sdebug_dev_info *devip)
zsp->z_size =
min_t(u64, devip->zsize, capacity - zstart);
} else if ((zstart & (devip->zsize - 1)) == 0) {
- if (devip->zmodel == BLK_ZONED_HM)
+ if (devip->zoned)
zsp->z_type = ZBC_ZTYPE_SWR;
else
zsp->z_type = ZBC_ZTYPE_SWP;
@@ -5390,13 +5389,13 @@ static struct sdebug_dev_info *sdebug_device_create(
}
devip->sdbg_host = sdbg_host;
if (sdeb_zbc_in_use) {
- devip->zmodel = sdeb_zbc_model;
+ devip->zoned = sdeb_zbc_model == BLK_ZONED_HM;
if (sdebug_device_create_zones(devip)) {
kfree(devip);
return NULL;
}
} else {
- devip->zmodel = BLK_ZONED_NONE;
+ devip->zoned = false;
}
devip->create_ts = ktime_get_boottime();
atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0));
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 43eff11070..612489afe8 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -302,6 +302,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
int ret;
WARN_ON_ONCE(!shost->ehandler);
+ WARN_ON_ONCE(!test_bit(SCMD_STATE_INFLIGHT, &scmd->state));
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_RECOVERY)) {
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index df5ac03d5d..189dfeb378 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -543,10 +543,9 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
if (blk_queue_add_random(q))
add_disk_randomness(req->q->disk);
- if (!blk_rq_is_passthrough(req)) {
- WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
- cmd->flags &= ~SCMD_INITIALIZED;
- }
+ WARN_ON_ONCE(!blk_rq_is_passthrough(req) &&
+ !(cmd->flags & SCMD_INITIALIZED));
+ cmd->flags = 0;
/*
* Calling rcu_barrier() is not necessary here because the
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f76dbeade0..35200a7a73 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3117,7 +3117,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
struct request_queue *q = sdkp->disk->queue;
struct scsi_vpd *vpd;
u16 rot;
- u8 zoned;
rcu_read_lock();
vpd = rcu_dereference(sdkp->device->vpd_pgb1);
@@ -3128,7 +3127,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
}
rot = get_unaligned_be16(&vpd->data[4]);
- zoned = (vpd->data[8] >> 4) & 3;
+ sdkp->zoned = (vpd->data[8] >> 4) & 3;
rcu_read_unlock();
if (rot == 1) {
@@ -3136,39 +3135,37 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
}
+
+#ifdef CONFIG_BLK_DEV_ZONED /* sd_probe rejects ZBD devices early otherwise */
if (sdkp->device->type == TYPE_ZBC) {
/*
- * Host-managed: Per ZBC and ZAC specifications, writes in
- * sequential write required zones of host-managed devices must
- * be aligned to the device physical block size.
+ * Host-managed.
+ */
+ disk_set_zoned(sdkp->disk);
+
+ /*
+ * Per ZBC and ZAC specifications, writes in sequential write
+ * required zones of host-managed devices must be aligned to
+ * the device physical block size.
*/
- disk_set_zoned(sdkp->disk, BLK_ZONED_HM);
blk_queue_zone_write_granularity(q, sdkp->physical_block_size);
} else {
- sdkp->zoned = zoned;
- if (sdkp->zoned == 1) {
- /* Host-aware */
- disk_set_zoned(sdkp->disk, BLK_ZONED_HA);
- } else {
- /* Regular disk or drive managed disk */
- disk_set_zoned(sdkp->disk, BLK_ZONED_NONE);
- }
+ /*
+ * Host-aware devices are treated as conventional.
+ */
+ WARN_ON_ONCE(blk_queue_is_zoned(q));
}
+#endif /* CONFIG_BLK_DEV_ZONED */
if (!sdkp->first_scan)
return;
- if (blk_queue_is_zoned(q)) {
- sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
- q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware");
- } else {
- if (sdkp->zoned == 1)
- sd_printk(KERN_NOTICE, sdkp,
- "Host-aware SMR disk used as regular disk\n");
- else if (sdkp->zoned == 2)
- sd_printk(KERN_NOTICE, sdkp,
- "Drive-managed SMR disk\n");
- }
+ if (blk_queue_is_zoned(q))
+ sd_printk(KERN_NOTICE, sdkp, "Host-managed zoned block device\n");
+ else if (sdkp->zoned == 1)
+ sd_printk(KERN_NOTICE, sdkp, "Host-aware SMR disk used as regular disk\n");
+ else if (sdkp->zoned == 2)
+ sd_printk(KERN_NOTICE, sdkp, "Drive-managed SMR disk\n");
}
/**
@@ -3526,7 +3523,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
} else {
q->limits.io_opt = 0;
rw_max = min_not_zero(logical_to_sectors(sdp, dev_max),
- (sector_t)BLK_DEF_MAX_SECTORS);
+ (sector_t)BLK_DEF_MAX_SECTORS_CAP);
}
/*
@@ -3760,7 +3757,7 @@ static int sd_probe(struct device *dev)
error = device_add_disk(dev, gd, NULL);
if (error) {
- put_device(&sdkp->disk_dev);
+ device_unregister(&sdkp->disk_dev);
put_disk(gd);
goto out;
}
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index a252155076..26af5ab7d7 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -836,10 +836,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
/*
* For all zoned disks, initialize zone append emulation data if not
- * already done. This is necessary also for host-aware disks used as
- * regular disks due to the presence of partitions as these partitions
- * may be deleted and the disk zoned model changed back from
- * BLK_ZONED_NONE to BLK_ZONED_HA.
+ * already done.
*/
if (sd_is_zoned(sdkp) && !sdkp->zone_wp_update_buf) {
ret = sd_zbc_init_disk(sdkp);
@@ -932,17 +929,6 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
sdkp->device->use_10_for_rw = 0;
sdkp->device->use_16_for_sync = 1;
- if (!blk_queue_is_zoned(q)) {
- /*
- * This can happen for a host aware disk with partitions.
- * The block device zone model was already cleared by
- * disk_set_zoned(). Only free the scsi disk zone
- * information and exit early.
- */
- sd_zbc_free_zone_info(sdkp);
- return 0;
- }
-
/* Check zoned block device characteristics (unconstrained reads) */
ret = sd_zbc_check_zoned_characteristics(sdkp, buf);
if (ret)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 86210e4dd0..b2d02dacae 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -285,6 +285,7 @@ sg_open(struct inode *inode, struct file *filp)
int dev = iminor(inode);
int flags = filp->f_flags;
struct request_queue *q;
+ struct scsi_device *device;
Sg_device *sdp;
Sg_fd *sfp;
int retval;
@@ -301,11 +302,12 @@ sg_open(struct inode *inode, struct file *filp)
/* This driver's module count bumped by fops_get in <linux/fs.h> */
/* Prevent the device driver from vanishing while we sleep */
- retval = scsi_device_get(sdp->device);
+ device = sdp->device;
+ retval = scsi_device_get(device);
if (retval)
goto sg_put;
- retval = scsi_autopm_get_device(sdp->device);
+ retval = scsi_autopm_get_device(device);
if (retval)
goto sdp_put;
@@ -313,7 +315,7 @@ sg_open(struct inode *inode, struct file *filp)
* check if O_NONBLOCK. Permits SCSI commands to be issued
* during error recovery. Tread carefully. */
if (!((flags & O_NONBLOCK) ||
- scsi_block_when_processing_errors(sdp->device))) {
+ scsi_block_when_processing_errors(device))) {
retval = -ENXIO;
/* we are in error recovery for this device */
goto error_out;
@@ -344,7 +346,7 @@ sg_open(struct inode *inode, struct file *filp)
if (sdp->open_cnt < 1) { /* no existing opens */
sdp->sgdebug = 0;
- q = sdp->device->request_queue;
+ q = device->request_queue;
sdp->sg_tablesize = queue_max_segments(q);
}
sfp = sg_add_sfp(sdp);
@@ -370,10 +372,11 @@ out_undo:
error_mutex_locked:
mutex_unlock(&sdp->open_rel_lock);
error_out:
- scsi_autopm_put_device(sdp->device);
+ scsi_autopm_put_device(device);
sdp_put:
- scsi_device_put(sdp->device);
- goto sg_put;
+ kref_put(&sdp->d_ref, sg_device_destroy);
+ scsi_device_put(device);
+ return retval;
}
/* Release resources associated with a successful sg_open()
@@ -2207,6 +2210,7 @@ sg_remove_sfp_usercontext(struct work_struct *work)
{
struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
struct sg_device *sdp = sfp->parentdp;
+ struct scsi_device *device = sdp->device;
Sg_request *srp;
unsigned long iflags;
@@ -2232,8 +2236,8 @@ sg_remove_sfp_usercontext(struct work_struct *work)
"sg_remove_sfp: sfp=0x%p\n", sfp));
kfree(sfp);
- scsi_device_put(sdp->device);
kref_put(&sdp->d_ref, sg_device_destroy);
+ scsi_device_put(device);
module_put(THIS_MODULE);
}
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 88e2b5eb9c..b0bef83db7 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -291,7 +291,7 @@ out:
return err;
}
-static int sgiwd93_remove(struct platform_device *pdev)
+static void sgiwd93_remove(struct platform_device *pdev)
{
struct Scsi_Host *host = platform_get_drvdata(pdev);
struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata;
@@ -302,12 +302,11 @@ static int sgiwd93_remove(struct platform_device *pdev)
dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma,
DMA_TO_DEVICE);
scsi_host_put(host);
- return 0;
}
static struct platform_driver sgiwd93_driver = {
.probe = sgiwd93_probe,
- .remove = sgiwd93_remove,
+ .remove_new = sgiwd93_remove,
.driver = {
.name = "sgiwd93",
}
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 868453b18c..385180c98b 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -33,11 +33,11 @@
#define BUILD_TIMESTAMP
#endif
-#define DRIVER_VERSION "2.1.24-046"
+#define DRIVER_VERSION "2.1.26-030"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 1
-#define DRIVER_RELEASE 24
-#define DRIVER_REVISION 46
+#define DRIVER_RELEASE 26
+#define DRIVER_REVISION 30
#define DRIVER_NAME "Microchip SmartPQI Driver (v" \
DRIVER_VERSION BUILD_TIMESTAMP ")"
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index 678651b9b4..9df1c90a24 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -104,7 +104,7 @@ static int snirm710_probe(struct platform_device *dev)
return -ENODEV;
}
-static int snirm710_driver_remove(struct platform_device *dev)
+static void snirm710_driver_remove(struct platform_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
struct NCR_700_Host_Parameters *hostdata =
@@ -115,13 +115,11 @@ static int snirm710_driver_remove(struct platform_device *dev)
free_irq(host->irq, host);
iounmap(hostdata->base);
kfree(hostdata);
-
- return 0;
}
static struct platform_driver snirm710_driver = {
.probe = snirm710_probe,
- .remove = snirm710_driver_remove,
+ .remove_new = snirm710_driver_remove,
.driver = {
.name = "snirm_53c710",
},
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index abf229b847..4a8cc2e823 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -641,7 +641,7 @@ fail_alloc:
return error;
}
-static int __exit sun3_scsi_remove(struct platform_device *pdev)
+static void __exit sun3_scsi_remove(struct platform_device *pdev)
{
struct Scsi_Host *instance = platform_get_drvdata(pdev);
struct NCR5380_hostdata *hostdata = shost_priv(instance);
@@ -654,11 +654,10 @@ static int __exit sun3_scsi_remove(struct platform_device *pdev)
if (udc_regs)
dvma_free(udc_regs);
iounmap(ioaddr);
- return 0;
}
static struct platform_driver sun3_scsi_driver = {
- .remove = __exit_p(sun3_scsi_remove),
+ .remove_new = __exit_p(sun3_scsi_remove),
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 30f67cbf4a..09219c362a 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -243,7 +243,7 @@ fail:
return err;
}
-static int esp_sun3x_remove(struct platform_device *dev)
+static void esp_sun3x_remove(struct platform_device *dev)
{
struct esp *esp = dev_get_drvdata(&dev->dev);
unsigned int irq = esp->host->irq;
@@ -261,13 +261,11 @@ static int esp_sun3x_remove(struct platform_device *dev)
esp->command_block_dma);
scsi_host_put(esp->host);
-
- return 0;
}
static struct platform_driver esp_sun3x_driver = {
.probe = esp_sun3x_probe,
- .remove = esp_sun3x_remove,
+ .remove_new = esp_sun3x_remove,
.driver = {
.name = "sun3x_esp",
},
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index afa9d02a33..64a7c2c6c5 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -550,7 +550,7 @@ static int esp_sbus_probe(struct platform_device *op)
return ret;
}
-static int esp_sbus_remove(struct platform_device *op)
+static void esp_sbus_remove(struct platform_device *op)
{
struct esp *esp = dev_get_drvdata(&op->dev);
struct platform_device *dma_of = esp->dma;
@@ -581,8 +581,6 @@ static int esp_sbus_remove(struct platform_device *op)
dev_set_drvdata(&op->dev, NULL);
put_device(&dma_of->dev);
-
- return 0;
}
static const struct of_device_id esp_match[] = {
@@ -605,7 +603,7 @@ static struct platform_driver esp_sbus_driver = {
.of_match_table = esp_match,
},
.probe = esp_sbus_probe,
- .remove = esp_sbus_remove,
+ .remove_new = esp_sbus_remove,
};
module_platform_driver(esp_sbus_driver);
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 9d1bdcdc13..617eb892f4 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -37,6 +37,11 @@
#define VIRTIO_SCSI_EVENT_LEN 8
#define VIRTIO_SCSI_VQ_BASE 2
+static unsigned int virtscsi_poll_queues;
+module_param(virtscsi_poll_queues, uint, 0644);
+MODULE_PARM_DESC(virtscsi_poll_queues,
+ "The number of dedicated virtqueues for polling I/O");
+
/* Command queue element */
struct virtio_scsi_cmd {
struct scsi_cmnd *sc;
@@ -76,6 +81,7 @@ struct virtio_scsi {
struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
u32 num_queues;
+ int io_queues[HCTX_MAX_TYPES];
struct hlist_node node;
@@ -182,8 +188,6 @@ static void virtscsi_vq_done(struct virtio_scsi *vscsi,
while ((buf = virtqueue_get_buf(vq, &len)) != NULL)
fn(vscsi, buf);
- if (unlikely(virtqueue_is_broken(vq)))
- break;
} while (!virtqueue_enable_cb(vq));
spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags);
}
@@ -722,9 +726,49 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
static void virtscsi_map_queues(struct Scsi_Host *shost)
{
struct virtio_scsi *vscsi = shost_priv(shost);
- struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
+ int i, qoff;
+
+ for (i = 0, qoff = 0; i < shost->nr_maps; i++) {
+ struct blk_mq_queue_map *map = &shost->tag_set.map[i];
+
+ map->nr_queues = vscsi->io_queues[i];
+ map->queue_offset = qoff;
+ qoff += map->nr_queues;
+
+ if (map->nr_queues == 0)
+ continue;
+
+ /*
+ * Regular queues have interrupts and hence CPU affinity is
+ * defined by the core virtio code, but polling queues have
+ * no interrupts so we let the block layer assign CPU affinity.
+ */
+ if (i == HCTX_TYPE_POLL)
+ blk_mq_map_queues(map);
+ else
+ blk_mq_virtio_map_queues(map, vscsi->vdev, 2);
+ }
+}
+
+static int virtscsi_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
+{
+ struct virtio_scsi *vscsi = shost_priv(shost);
+ struct virtio_scsi_vq *virtscsi_vq = &vscsi->req_vqs[queue_num];
+ unsigned long flags;
+ unsigned int len;
+ int found = 0;
+ void *buf;
+
+ spin_lock_irqsave(&virtscsi_vq->vq_lock, flags);
+
+ while ((buf = virtqueue_get_buf(virtscsi_vq->vq, &len)) != NULL) {
+ virtscsi_complete_cmd(vscsi, buf);
+ found++;
+ }
+
+ spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags);
- blk_mq_virtio_map_queues(qmap, vscsi->vdev, 2);
+ return found;
}
static void virtscsi_commit_rqs(struct Scsi_Host *shost, u16 hwq)
@@ -751,6 +795,7 @@ static const struct scsi_host_template virtscsi_host_template = {
.this_id = -1,
.cmd_size = sizeof(struct virtio_scsi_cmd),
.queuecommand = virtscsi_queuecommand,
+ .mq_poll = virtscsi_mq_poll,
.commit_rqs = virtscsi_commit_rqs,
.change_queue_depth = virtscsi_change_queue_depth,
.eh_abort_handler = virtscsi_abort,
@@ -795,13 +840,14 @@ static int virtscsi_init(struct virtio_device *vdev,
{
int err;
u32 i;
- u32 num_vqs;
+ u32 num_vqs, num_poll_vqs, num_req_vqs;
vq_callback_t **callbacks;
const char **names;
struct virtqueue **vqs;
struct irq_affinity desc = { .pre_vectors = 2 };
- num_vqs = vscsi->num_queues + VIRTIO_SCSI_VQ_BASE;
+ num_req_vqs = vscsi->num_queues;
+ num_vqs = num_req_vqs + VIRTIO_SCSI_VQ_BASE;
vqs = kmalloc_array(num_vqs, sizeof(struct virtqueue *), GFP_KERNEL);
callbacks = kmalloc_array(num_vqs, sizeof(vq_callback_t *),
GFP_KERNEL);
@@ -812,15 +858,31 @@ static int virtscsi_init(struct virtio_device *vdev,
goto out;
}
+ num_poll_vqs = min_t(unsigned int, virtscsi_poll_queues,
+ num_req_vqs - 1);
+ vscsi->io_queues[HCTX_TYPE_DEFAULT] = num_req_vqs - num_poll_vqs;
+ vscsi->io_queues[HCTX_TYPE_READ] = 0;
+ vscsi->io_queues[HCTX_TYPE_POLL] = num_poll_vqs;
+
+ dev_info(&vdev->dev, "%d/%d/%d default/read/poll queues\n",
+ vscsi->io_queues[HCTX_TYPE_DEFAULT],
+ vscsi->io_queues[HCTX_TYPE_READ],
+ vscsi->io_queues[HCTX_TYPE_POLL]);
+
callbacks[0] = virtscsi_ctrl_done;
callbacks[1] = virtscsi_event_done;
names[0] = "control";
names[1] = "event";
- for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs; i++) {
+ for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs - num_poll_vqs; i++) {
callbacks[i] = virtscsi_req_done;
names[i] = "request";
}
+ for (; i < num_vqs; i++) {
+ callbacks[i] = NULL;
+ names[i] = "request_poll";
+ }
+
/* Discover virtqueues and write information to configuration. */
err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc);
if (err)
@@ -874,6 +936,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
shost->sg_tablesize = sg_elems;
+ shost->nr_maps = 1;
vscsi = shost_priv(shost);
vscsi->vdev = vdev;
vscsi->num_queues = num_queues;
@@ -883,6 +946,9 @@ static int virtscsi_probe(struct virtio_device *vdev)
if (err)
goto virtscsi_init_failed;
+ if (vscsi->io_queues[HCTX_TYPE_POLL])
+ shost->nr_maps = HCTX_TYPE_POLL + 1;
+
shost->can_queue = virtqueue_get_vring_size(vscsi->req_vqs[0].vq);
cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1;