From c6635792737b881021ead417b281067d56ed3380 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 13:32:36 +0300 Subject: PCI: Allocate dma_alias_mask with bitmap_zalloc() Switch to bitmap_zalloc() to show clearly what we are allocating. Besides that it returns pointer of bitmap type ("unsigned long *") instead of the opaque "void *". Signed-off-by: Andy Shevchenko Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/probe.c') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 201f9e5ff55c..7c422ccbf9b4 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2143,7 +2143,7 @@ static void pci_release_dev(struct device *dev) pcibios_release_device(pci_dev); pci_bus_put(pci_dev->bus); kfree(pci_dev->driver_override); - kfree(pci_dev->dma_alias_mask); + bitmap_free(pci_dev->dma_alias_mask); kfree(pci_dev); } -- cgit v1.2.3 From f0157160b359b1d263ee9d4e0a435a7ad85bbcea Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 20 Sep 2018 10:27:17 -0600 Subject: PCI: Make link active reporting detection generic The spec has timing requirements when waiting for a link to become active after a conventional reset. Implement those hard delays when waiting for an active link so pciehp and dpc drivers don't need to duplicate this. For devices that don't support data link layer active reporting, wait the fixed time recommended by the PCIe spec. Signed-off-by: Keith Busch [bhelgaas: changelog] Signed-off-by: Bjorn Helgaas Reviewed-by: Sinan Kaya --- drivers/pci/hotplug/pciehp.h | 6 ------ drivers/pci/hotplug/pciehp_hpc.c | 22 ++-------------------- drivers/pci/pci.c | 33 +++++++++++++++++++++++++++------ drivers/pci/pcie/dpc.c | 4 +++- drivers/pci/probe.c | 1 + include/linux/pci.h | 1 + 6 files changed, 34 insertions(+), 33 deletions(-) (limited to 'drivers/pci/probe.c') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 3740f1a759c5..75fd52571107 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -62,11 +62,6 @@ do { \ * struct controller - PCIe hotplug controller * @pcie: pointer to the controller's PCIe port service device * @slot_cap: cached copy of the Slot Capabilities register - * @link_active_reporting: cached copy of Data Link Layer Link Active Reporting - * Capable bit in Link Capabilities register; if this bit is zero, the - * Data Link Layer Link Active bit in the Link Status register will never - * be set and the driver is thus confined to wait 1 second before assuming - * the link to a hotplugged device is up and accessing it * @slot_ctrl: cached copy of the Slot Control register * @ctrl_lock: serializes writes to the Slot Control register * @cmd_started: jiffies when the Slot Control register was last written; @@ -103,7 +98,6 @@ struct controller { struct pcie_device *pcie; u32 slot_cap; /* capabilities and quirks */ - unsigned int link_active_reporting:1; u16 slot_ctrl; /* control register access */ struct mutex ctrl_lock; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7b5f9db60d9a..f0f3f4a3dac4 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -214,13 +214,6 @@ bool pciehp_check_link_active(struct controller *ctrl) return ret; } -static void pcie_wait_link_active(struct controller *ctrl) -{ - struct pci_dev *pdev = ctrl_dev(ctrl); - - pcie_wait_for_link(pdev, true); -} - static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) { u32 l; @@ -253,18 +246,9 @@ int pciehp_check_link_status(struct controller *ctrl) bool found; u16 lnk_status; - /* - * Data Link Layer Link Active Reporting must be capable for - * hot-plug capable downstream port. But old controller might - * not implement it. In this case, we wait for 1000 ms. - */ - if (ctrl->link_active_reporting) - pcie_wait_link_active(ctrl); - else - msleep(1000); + if (!pcie_wait_for_link(pdev, true)) + return -1; - /* wait 100ms before read pci conf, and try in 1s */ - msleep(100); found = pci_bus_check_dev(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); @@ -865,8 +849,6 @@ struct controller *pcie_init(struct pcie_device *dev) /* Check if Data Link Layer Link Active Reporting is implemented */ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); - if (link_cap & PCI_EXP_LNKCAP_DLLLARC) - ctrl->link_active_reporting = 1; /* Clear all remaining event bits in Slot Status register. */ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6916af269b19..4b0b1d0548f0 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4489,21 +4489,42 @@ bool pcie_wait_for_link(struct pci_dev *pdev, bool active) bool ret; u16 lnk_status; + /* + * Some controllers might not implement link active reporting. In this + * case, we wait for 1000 + 100 ms. + */ + if (!pdev->link_active_reporting) { + msleep(1100); + return true; + } + + /* + * PCIe r4.0 sec 6.6.1, a component must enter LTSSM Detect within 20ms, + * after which we should expect an link active if the reset was + * successful. If so, software must wait a minimum 100ms before sending + * configuration requests to devices downstream this port. + * + * If the link fails to activate, either the device was physically + * removed or the link is permanently failed. + */ + if (active) + msleep(20); for (;;) { pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); if (ret == active) - return true; + break; if (timeout <= 0) break; msleep(10); timeout -= 10; } - - pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n", - active ? "set" : "cleared"); - - return false; + if (active && ret) + msleep(100); + else if (ret != active) + pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n", + active ? "set" : "cleared"); + return ret == active; } void pci_reset_secondary_bus(struct pci_dev *dev) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 23e063aefddf..e435d12e61a0 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -140,10 +140,12 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); + if (!pcie_wait_for_link(pdev, true)) + return PCI_ERS_RESULT_DISCONNECT; + return PCI_ERS_RESULT_RECOVERED; } - static void dpc_process_rp_pio_error(struct dpc_dev *dpc) { struct device *dev = &dpc->dev->device; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 201f9e5ff55c..bb2999d1b199 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -713,6 +713,7 @@ static void pci_set_bus_speed(struct pci_bus *bus) pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS]; + bridge->link_active_reporting = !!(linkcap & PCI_EXP_LNKCAP_DLLLARC); pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); pcie_update_link_speed(bus, linksta); diff --git a/include/linux/pci.h b/include/linux/pci.h index 6925828f9f25..896b42032ec5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -402,6 +402,7 @@ struct pci_dev { unsigned int has_secondary_link:1; unsigned int non_compliant_bars:1; /* Broken BARs; ignore them */ unsigned int is_probed:1; /* Device probing in progress */ + unsigned int link_active_reporting:1;/* Device capable of reporting link active */ pci_dev_flags_t dev_flags; atomic_t enable_cnt; /* pci_enable_device has been called */ -- cgit v1.2.3 From a6f44cf9f5cc60471cf06f3d5391fc6041eb37a5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:08:23 +0200 Subject: PCI: Remove pci_set_dma_seg_boundary() The two callers can just use dma_set_seg_boundary() directly. Signed-off-by: Christoph Hellwig Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 2 +- drivers/s390/net/ism_drv.c | 2 +- include/linux/pci-dma-compat.h | 9 --------- 3 files changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/pci/probe.c') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 7c422ccbf9b4..72dd926680be 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2398,7 +2398,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dev->dev.coherent_dma_mask = 0xffffffffull; pci_set_dma_max_seg_size(dev, 65536); - pci_set_dma_seg_boundary(dev, 0xffffffff); + dma_set_seg_boundary(&dev->dev, 0xffffffff); /* Fix up broken headers */ pci_fixup_device(pci_fixup_header, dev); diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index c0631895154e..8688c0fff761 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -515,7 +515,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_unmap; - pci_set_dma_seg_boundary(pdev, SZ_1M - 1); + dma_set_seg_boundary(&pdev->dev, SZ_1M - 1); pci_set_dma_max_seg_size(pdev, SZ_1M); pci_set_master(pdev); diff --git a/include/linux/pci-dma-compat.h b/include/linux/pci-dma-compat.h index c3f1b44ade29..558a109ab497 100644 --- a/include/linux/pci-dma-compat.h +++ b/include/linux/pci-dma-compat.h @@ -125,12 +125,6 @@ static inline int pci_set_dma_max_seg_size(struct pci_dev *dev, { return dma_set_max_seg_size(&dev->dev, size); } - -static inline int pci_set_dma_seg_boundary(struct pci_dev *dev, - unsigned long mask) -{ - return dma_set_seg_boundary(&dev->dev, mask); -} #else static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } @@ -139,9 +133,6 @@ static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) static inline int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) { return -EIO; } -static inline int pci_set_dma_seg_boundary(struct pci_dev *dev, - unsigned long mask) -{ return -EIO; } #endif #endif -- cgit v1.2.3 From b0da3498c587c20e64799c4c7ba65a31314b2182 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:08:24 +0200 Subject: PCI: Remove pci_set_dma_max_seg_size() The few callers can just use dma_set_max_seg_size ()directly. Signed-off-by: Christoph Hellwig Signed-off-by: Bjorn Helgaas --- drivers/ata/sata_inic162x.c | 2 +- drivers/block/rsxx/core.c | 2 +- drivers/pci/probe.c | 2 +- drivers/s390/net/ism_drv.c | 2 +- drivers/scsi/aacraid/linit.c | 2 +- include/linux/pci-dma-compat.h | 9 --------- 6 files changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers/pci/probe.c') diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 9b6d7930d1c7..e0bcf9b2dab0 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -873,7 +873,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * like others but it will lock up the whole machine HARD if * 65536 byte PRD entry is fed. Reduce maximum segment size. */ - rc = pci_set_dma_max_seg_size(pdev, 65536 - 512); + rc = dma_set_max_seg_size(&pdev->dev, 65536 - 512); if (rc) { dev_err(&pdev->dev, "failed to set the maximum segment size\n"); return rc; diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index f2c631ce793c..37df486c7c3c 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c @@ -780,7 +780,7 @@ static int rsxx_pci_probe(struct pci_dev *dev, goto failed_enable; pci_set_master(dev); - pci_set_dma_max_seg_size(dev, RSXX_HW_BLK_SIZE); + dma_set_max_seg_size(&dev->dev, RSXX_HW_BLK_SIZE); st = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); if (st) { diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 72dd926680be..75d896549360 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2397,7 +2397,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dev->dev.dma_parms = &dev->dma_parms; dev->dev.coherent_dma_mask = 0xffffffffull; - pci_set_dma_max_seg_size(dev, 65536); + dma_set_max_seg_size(&dev->dev, 65536); dma_set_seg_boundary(&dev->dev, 0xffffffff); /* Fix up broken headers */ diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index 8688c0fff761..f96ec68af2e5 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -516,7 +516,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_unmap; dma_set_seg_boundary(&pdev->dev, SZ_1M - 1); - pci_set_dma_max_seg_size(pdev, SZ_1M); + dma_set_max_seg_size(&pdev->dev, SZ_1M); pci_set_master(pdev); ism->smcd = smcd_alloc_dev(&pdev->dev, dev_name(&pdev->dev), &ism_ops, diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 04443577d48b..53eb2e9569b9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1747,7 +1747,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) shost->max_sectors = (shost->sg_tablesize * 8) + 112; } - error = pci_set_dma_max_seg_size(pdev, + error = dma_set_max_seg_size(&pdev->dev, (aac->adapter_info.options & AAC_OPT_NEW_COMM) ? (shost->max_sectors << 9) : 65536); if (error) diff --git a/include/linux/pci-dma-compat.h b/include/linux/pci-dma-compat.h index 558a109ab497..cb1adf0b78a9 100644 --- a/include/linux/pci-dma-compat.h +++ b/include/linux/pci-dma-compat.h @@ -119,20 +119,11 @@ static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) { return dma_set_coherent_mask(&dev->dev, mask); } - -static inline int pci_set_dma_max_seg_size(struct pci_dev *dev, - unsigned int size) -{ - return dma_set_max_seg_size(&dev->dev, size); -} #else static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } -static inline int pci_set_dma_max_seg_size(struct pci_dev *dev, - unsigned int size) -{ return -EIO; } #endif #endif -- cgit v1.2.3 From 975bb8b4dc93364bb47fcdb58812fa6cb0accc81 Mon Sep 17 00:00:00 2001 From: KarimAllah Ahmed Date: Thu, 11 Oct 2018 11:49:58 -0500 Subject: PCI/IOV: Use VF0 cached config space size for other VFs Cache the config space size from VF0 and use it for all other VFs instead of reading it from the config space of each VF. We assume that it will be the same across all associated VFs. This is an optimization when enabling SR-IOV on a device with many VFs. Signed-off-by: KarimAllah Ahmed [bhelgaas: use CONFIG_PCI_IOV (not CONFIG_PCI_ATS)] Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 2 ++ drivers/pci/pci.h | 1 + drivers/pci/probe.c | 17 +++++++++++++++++ 3 files changed, 20 insertions(+) (limited to 'drivers/pci/probe.c') diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index c5f3cd4ed766..4238b539f9d8 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -133,6 +133,8 @@ static void pci_read_vf_config_common(struct pci_dev *virtfn) &physfn->sriov->subsystem_vendor); pci_read_config_word(virtfn, PCI_SUBSYSTEM_ID, &physfn->sriov->subsystem_device); + + physfn->sriov->cfg_size = pci_cfg_space_size(virtfn); } int pci_iov_add_virtfn(struct pci_dev *dev, int id) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6e0d1528d471..2f1454209257 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -285,6 +285,7 @@ struct pci_sriov { u16 driver_max_VFs; /* Max num VFs driver supports */ struct pci_dev *dev; /* Lowest numbered PF */ struct pci_dev *self; /* This PF */ + u32 cfg_size; /* VF config space size */ u32 class; /* VF device */ u8 hdr_type; /* VF header type */ u16 subsystem_vendor; /* VF subsystem vendor */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 201f9e5ff55c..575315bb7c4c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1438,12 +1438,29 @@ static int pci_cfg_space_size_ext(struct pci_dev *dev) return PCI_CFG_SPACE_EXP_SIZE; } +#ifdef CONFIG_PCI_IOV +static bool is_vf0(struct pci_dev *dev) +{ + if (pci_iov_virtfn_devfn(dev->physfn, 0) == dev->devfn && + pci_iov_virtfn_bus(dev->physfn, 0) == dev->bus->number) + return true; + + return false; +} +#endif + int pci_cfg_space_size(struct pci_dev *dev) { int pos; u32 status; u16 class; +#ifdef CONFIG_PCI_IOV + /* Read cached value for all VFs except for VF0 */ + if (dev->is_virtfn && !is_vf0(dev)) + return dev->physfn->sriov->cfg_size; +#endif + if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_EXTCFG) return PCI_CFG_SPACE_SIZE; -- cgit v1.2.3