From 7ce3f912ae0a79e5d738a3ae1f158b281973e849 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Sat, 30 Jun 2018 11:24:24 -0400 Subject: PCI: Enable PASID only if entire path supports End-End TLP prefixes A PCIe endpoint carries the process address space identifier (PASID) in the TLP prefix as part of the memory read/write transaction. The address information in the TLP is relevant only for a given PASID context. An IOMMU takes PASID value and the address information from the TLP to look up the physical address in the system. PASID is an End-End TLP Prefix (PCIe r4.0, sec 6.20). Sec 2.2.10.2 says It is an error to receive a TLP with an End-End TLP Prefix by a Receiver that does not support End-End TLP Prefixes. A TLP in violation of this rule is handled as a Malformed TLP. This is a reported error associated with the Receiving Port (see Section 6.2). Prevent error condition by proactively requiring End-End TLP prefix to be supported on the entire data path between the endpoint and the root port before enabling PASID. Signed-off-by: Sinan Kaya Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index 340029b2fb38..6ba818449095 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -350,6 +350,7 @@ struct pci_dev { unsigned int ltr_path:1; /* Latency Tolerance Reporting supported from root to here */ #endif + unsigned int eetlp_prefix_path:1; /* End-to-End TLP Prefix */ pci_channel_state_t error_state; /* Current connectivity state */ struct device dev; /* Generic device interface */ -- cgit v1.2.3 From 381634cad15b711e033a2638d558232b60f753f6 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 19 Jul 2018 18:04:11 -0500 Subject: PCI: Hide pci_reset_bridge_secondary_bus() from drivers Rename pci_reset_bridge_secondary_bus() to pci_bridge_secondary_bus_reset() and move the declaration from linux/pci.h to drivers/pci.h to be used internally in PCI directory only. Signed-off-by: Sinan Kaya Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 2 +- drivers/pci/pci.c | 11 +++++------ drivers/pci/pci.h | 1 + drivers/pci/pcie/aer.c | 2 +- drivers/pci/pcie/err.c | 2 +- include/linux/pci.h | 1 - 6 files changed, 9 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index bbaa2114f953..8dae23221344 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -746,7 +746,7 @@ int pciehp_reset_slot(struct slot *slot, int probe) if (pciehp_poll_mode) del_timer_sync(&ctrl->poll_timer); - rc = pci_reset_bridge_secondary_bus(ctrl->pcie->port); + rc = pci_bridge_secondary_bus_reset(ctrl->pcie->port); pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask); pcie_write_cmd_nowait(ctrl, ctrl_mask, ctrl_mask); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 98d149070205..236220cb0f77 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4224,19 +4224,18 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev) } /** - * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge. + * pci_bridge_secondary_bus_reset - Reset the secondary bus on a PCI bridge. * @dev: Bridge device * * Use the bridge control register to assert reset on the secondary bus. * Devices on the secondary bus are left in power-on state. */ -int pci_reset_bridge_secondary_bus(struct pci_dev *dev) +int pci_bridge_secondary_bus_reset(struct pci_dev *dev) { pcibios_reset_secondary_bus(dev); return pci_dev_wait(dev, "bus reset", PCIE_RESET_READY_POLL_MS); } -EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus); static int pci_parent_bus_reset(struct pci_dev *dev, int probe) { @@ -4253,7 +4252,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) if (probe) return 0; - return pci_reset_bridge_secondary_bus(dev->bus->self); + return pci_bridge_secondary_bus_reset(dev->bus->self); } static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, int probe) @@ -4860,7 +4859,7 @@ static int pci_bus_reset(struct pci_bus *bus, int probe) might_sleep(); - ret = pci_reset_bridge_secondary_bus(bus->self); + ret = pci_bridge_secondary_bus_reset(bus->self); pci_bus_unlock(bus); @@ -4924,7 +4923,7 @@ int pci_try_reset_bus(struct pci_bus *bus) if (pci_bus_trylock(bus)) { might_sleep(); - rc = pci_reset_bridge_secondary_bus(bus->self); + rc = pci_bridge_secondary_bus_reset(bus->self); pci_bus_unlock(bus); } else rc = -EAGAIN; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c358e7a07f3f..f784263ad587 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -33,6 +33,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai, enum pci_mmap_api mmap_api); int pci_probe_reset_function(struct pci_dev *dev); +int pci_bridge_secondary_bus_reset(struct pci_dev *dev); /** * struct pci_platform_pm_ops - Firmware PM callbacks diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index bde723db3d65..8c12efca9259 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -1314,7 +1314,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); - rc = pci_reset_bridge_secondary_bus(dev); + rc = pci_bridge_secondary_bus_reset(dev); pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n"); /* Clear Root Error Status */ diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 03075cff86f4..ae72f88d3ca2 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -177,7 +177,7 @@ static pci_ers_result_t default_reset_link(struct pci_dev *dev) { int rc; - rc = pci_reset_bridge_secondary_bus(dev); + rc = pci_bridge_secondary_bus_reset(dev); pci_printk(KERN_DEBUG, dev, "downstream link has been reset\n"); return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; } diff --git a/include/linux/pci.h b/include/linux/pci.h index 6ba818449095..03520ff23d73 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1103,7 +1103,6 @@ int pci_reset_bus(struct pci_bus *bus); int pci_try_reset_bus(struct pci_bus *bus); void pci_reset_secondary_bus(struct pci_dev *dev); void pcibios_reset_secondary_bus(struct pci_dev *dev); -int pci_reset_bridge_secondary_bus(struct pci_dev *dev); void pci_update_resource(struct pci_dev *dev, int resno); int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); -- cgit v1.2.3 From 811c5cb37df46b0cd714dbd053d19cdb97d08cff Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 19 Jul 2018 18:04:12 -0500 Subject: PCI: Unify try slot and bus reset API Drivers are expected to call pci_try_reset_slot() or pci_try_reset_bus() by querying if a system supports hotplug or not. A survey showed that most drivers don't do this and we are leaking hotplug capability to the user. Hide pci_try_slot_reset() from drivers and embed into pci_try_bus_reset(). Change pci_try_reset_bus() parameter from struct pci_bus to struct pci_dev. Signed-off-by: Sinan Kaya Signed-off-by: Bjorn Helgaas --- drivers/infiniband/hw/hfi1/pcie.c | 2 +- drivers/pci/pci.c | 21 ++++++++++++++++----- drivers/vfio/pci/vfio_pci.c | 6 ++---- include/linux/pci.h | 3 +-- 4 files changed, 20 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index 4570c4dc93d9..df4f2d390be8 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c @@ -905,7 +905,7 @@ static int trigger_sbr(struct hfi1_devdata *dd) * delay after a reset is required. Per spec requirements, * the link is either working or not after that point. */ - return pci_try_reset_bus(dev->bus); + return pci_try_reset_bus(dev); } /* diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 236220cb0f77..a31e6dbf21c3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4817,12 +4817,12 @@ int pci_reset_slot(struct pci_slot *slot) EXPORT_SYMBOL_GPL(pci_reset_slot); /** - * pci_try_reset_slot - Try to reset a PCI slot + * __pci_try_reset_slot - Try to reset a PCI slot * @slot: PCI slot to reset * * Same as above except return -EAGAIN if the slot cannot be locked */ -int pci_try_reset_slot(struct pci_slot *slot) +static int __pci_try_reset_slot(struct pci_slot *slot) { int rc; @@ -4843,7 +4843,6 @@ int pci_try_reset_slot(struct pci_slot *slot) return rc; } -EXPORT_SYMBOL_GPL(pci_try_reset_slot); static int pci_bus_reset(struct pci_bus *bus, int probe) { @@ -4906,12 +4905,12 @@ int pci_reset_bus(struct pci_bus *bus) EXPORT_SYMBOL_GPL(pci_reset_bus); /** - * pci_try_reset_bus - Try to reset a PCI bus + * __pci_try_reset_bus - Try to reset a PCI bus * @bus: top level PCI bus to reset * * Same as above except return -EAGAIN if the bus cannot be locked */ -int pci_try_reset_bus(struct pci_bus *bus) +static int __pci_try_reset_bus(struct pci_bus *bus) { int rc; @@ -4932,6 +4931,18 @@ int pci_try_reset_bus(struct pci_bus *bus) return rc; } + +/** + * pci_try_reset_bus - Try to reset a PCI bus + * @pdev: top level PCI device to reset via slot/bus + * + * Same as above except return -EAGAIN if the bus cannot be locked + */ +int pci_try_reset_bus(struct pci_dev *pdev) +{ + return pci_probe_reset_slot(pdev->slot) ? + __pci_try_reset_slot(pdev->slot) : __pci_try_reset_bus(pdev->bus); +} EXPORT_SYMBOL_GPL(pci_try_reset_bus); /** diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index b423a309a6e0..71018ec9065b 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -1010,8 +1010,7 @@ reset_info_exit: &info, slot); if (!ret) /* User has access, do the reset */ - ret = slot ? pci_try_reset_slot(vdev->pdev->slot) : - pci_try_reset_bus(vdev->pdev->bus); + ret = pci_try_reset_bus(vdev->pdev); hot_reset_release: for (i--; i >= 0; i--) @@ -1373,8 +1372,7 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev) } if (needs_reset) - ret = slot ? pci_try_reset_slot(vdev->pdev->slot) : - pci_try_reset_bus(vdev->pdev->bus); + ret = pci_try_reset_bus(vdev->pdev); put_devs: for (i = 0; i < devs.cur_index; i++) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 03520ff23d73..19fb82559145 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1097,10 +1097,9 @@ int pci_reset_function_locked(struct pci_dev *dev); int pci_try_reset_function(struct pci_dev *dev); int pci_probe_reset_slot(struct pci_slot *slot); int pci_reset_slot(struct pci_slot *slot); -int pci_try_reset_slot(struct pci_slot *slot); int pci_probe_reset_bus(struct pci_bus *bus); int pci_reset_bus(struct pci_bus *bus); -int pci_try_reset_bus(struct pci_bus *bus); +int pci_try_reset_bus(struct pci_dev *dev); void pci_reset_secondary_bus(struct pci_dev *dev); void pcibios_reset_secondary_bus(struct pci_dev *dev); void pci_update_resource(struct pci_dev *dev, int resno); -- cgit v1.2.3 From fe32e2fa656c29d5d25f959f8e6168ac405d9ab4 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 19 Jul 2018 18:04:14 -0500 Subject: PCI: Deprecate pci_reset_bus() and pci_reset_slot() functions pci_reset_bus() and pci_reset_slot() functions are not being used by any code. Remove them from the kernel in favor of pci_try_reset_bus() and pci_try_reset_slot() functions. Signed-off-by: Sinan Kaya Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 53 +---------------------------------------------------- include/linux/pci.h | 2 -- 2 files changed, 1 insertion(+), 54 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index a31e6dbf21c3..8ee9f386c1ee 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4784,7 +4784,7 @@ int pci_probe_reset_slot(struct pci_slot *slot) EXPORT_SYMBOL_GPL(pci_probe_reset_slot); /** - * pci_reset_slot - reset a PCI slot + * __pci_try_reset_slot - Try to reset a PCI slot * @slot: PCI slot to reset * * A PCI bus may host multiple slots, each slot may support a reset mechanism @@ -4796,30 +4796,6 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_slot); * through this function. PCI config space of all devices in the slot and * behind the slot is saved before and restored after reset. * - * Return 0 on success, non-zero on error. - */ -int pci_reset_slot(struct pci_slot *slot) -{ - int rc; - - rc = pci_slot_reset(slot, 1); - if (rc) - return rc; - - pci_slot_save_and_disable(slot); - - rc = pci_slot_reset(slot, 0); - - pci_slot_restore(slot); - - return rc; -} -EXPORT_SYMBOL_GPL(pci_reset_slot); - -/** - * __pci_try_reset_slot - Try to reset a PCI slot - * @slot: PCI slot to reset - * * Same as above except return -EAGAIN if the slot cannot be locked */ static int __pci_try_reset_slot(struct pci_slot *slot) @@ -4877,33 +4853,6 @@ int pci_probe_reset_bus(struct pci_bus *bus) } EXPORT_SYMBOL_GPL(pci_probe_reset_bus); -/** - * pci_reset_bus - reset a PCI bus - * @bus: top level PCI bus to reset - * - * Do a bus reset on the given bus and any subordinate buses, saving - * and restoring state of all devices. - * - * Return 0 on success, non-zero on error. - */ -int pci_reset_bus(struct pci_bus *bus) -{ - int rc; - - rc = pci_bus_reset(bus, 1); - if (rc) - return rc; - - pci_bus_save_and_disable(bus); - - rc = pci_bus_reset(bus, 0); - - pci_bus_restore(bus); - - return rc; -} -EXPORT_SYMBOL_GPL(pci_reset_bus); - /** * __pci_try_reset_bus - Try to reset a PCI bus * @bus: top level PCI bus to reset diff --git a/include/linux/pci.h b/include/linux/pci.h index 19fb82559145..cf53ecb50789 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1096,9 +1096,7 @@ int pci_reset_function(struct pci_dev *dev); int pci_reset_function_locked(struct pci_dev *dev); int pci_try_reset_function(struct pci_dev *dev); int pci_probe_reset_slot(struct pci_slot *slot); -int pci_reset_slot(struct pci_slot *slot); int pci_probe_reset_bus(struct pci_bus *bus); -int pci_reset_bus(struct pci_bus *bus); int pci_try_reset_bus(struct pci_dev *dev); void pci_reset_secondary_bus(struct pci_dev *dev); void pcibios_reset_secondary_bus(struct pci_dev *dev); -- cgit v1.2.3 From c6a44ba950d147e15fe6dab6455a52f91d8fe625 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 19 Jul 2018 18:04:15 -0500 Subject: PCI: Rename pci_try_reset_bus() to pci_reset_bus() Now that the old implementation of pci_reset_bus() is gone, replace pci_try_reset_bus() with pci_reset_bus(). Compared to the old implementation, new code will fail immmediately with -EAGAIN if object lock cannot be obtained. Signed-off-by: Sinan Kaya Signed-off-by: Bjorn Helgaas --- drivers/infiniband/hw/hfi1/pcie.c | 2 +- drivers/pci/pci.c | 16 ++++++++-------- drivers/vfio/pci/vfio_pci.c | 4 ++-- include/linux/pci.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index df4f2d390be8..baf7c324f7b8 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c @@ -905,7 +905,7 @@ static int trigger_sbr(struct hfi1_devdata *dd) * delay after a reset is required. Per spec requirements, * the link is either working or not after that point. */ - return pci_try_reset_bus(dev); + return pci_reset_bus(dev); } /* diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8ee9f386c1ee..d123c2b173da 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4784,7 +4784,7 @@ int pci_probe_reset_slot(struct pci_slot *slot) EXPORT_SYMBOL_GPL(pci_probe_reset_slot); /** - * __pci_try_reset_slot - Try to reset a PCI slot + * __pci_reset_slot - Try to reset a PCI slot * @slot: PCI slot to reset * * A PCI bus may host multiple slots, each slot may support a reset mechanism @@ -4798,7 +4798,7 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_slot); * * Same as above except return -EAGAIN if the slot cannot be locked */ -static int __pci_try_reset_slot(struct pci_slot *slot) +static int __pci_reset_slot(struct pci_slot *slot) { int rc; @@ -4854,12 +4854,12 @@ int pci_probe_reset_bus(struct pci_bus *bus) EXPORT_SYMBOL_GPL(pci_probe_reset_bus); /** - * __pci_try_reset_bus - Try to reset a PCI bus + * __pci_reset_bus - Try to reset a PCI bus * @bus: top level PCI bus to reset * * Same as above except return -EAGAIN if the bus cannot be locked */ -static int __pci_try_reset_bus(struct pci_bus *bus) +static int __pci_reset_bus(struct pci_bus *bus) { int rc; @@ -4882,17 +4882,17 @@ static int __pci_try_reset_bus(struct pci_bus *bus) } /** - * pci_try_reset_bus - Try to reset a PCI bus + * pci_reset_bus - Try to reset a PCI bus * @pdev: top level PCI device to reset via slot/bus * * Same as above except return -EAGAIN if the bus cannot be locked */ -int pci_try_reset_bus(struct pci_dev *pdev) +int pci_reset_bus(struct pci_dev *pdev) { return pci_probe_reset_slot(pdev->slot) ? - __pci_try_reset_slot(pdev->slot) : __pci_try_reset_bus(pdev->bus); + __pci_reset_slot(pdev->slot) : __pci_reset_bus(pdev->bus); } -EXPORT_SYMBOL_GPL(pci_try_reset_bus); +EXPORT_SYMBOL_GPL(pci_reset_bus); /** * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 71018ec9065b..345c0dc8a6dc 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -1010,7 +1010,7 @@ reset_info_exit: &info, slot); if (!ret) /* User has access, do the reset */ - ret = pci_try_reset_bus(vdev->pdev); + ret = pci_reset_bus(vdev->pdev); hot_reset_release: for (i--; i >= 0; i--) @@ -1372,7 +1372,7 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev) } if (needs_reset) - ret = pci_try_reset_bus(vdev->pdev); + ret = pci_reset_bus(vdev->pdev); put_devs: for (i = 0; i < devs.cur_index; i++) { diff --git a/include/linux/pci.h b/include/linux/pci.h index cf53ecb50789..307b336496f6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1097,7 +1097,7 @@ int pci_reset_function_locked(struct pci_dev *dev); int pci_try_reset_function(struct pci_dev *dev); int pci_probe_reset_slot(struct pci_slot *slot); int pci_probe_reset_bus(struct pci_bus *bus); -int pci_try_reset_bus(struct pci_dev *dev); +int pci_reset_bus(struct pci_dev *dev); void pci_reset_secondary_bus(struct pci_dev *dev); void pcibios_reset_secondary_bus(struct pci_dev *dev); void pci_update_resource(struct pci_dev *dev, int resno); -- cgit v1.2.3 From 2d2917f7747805a1f4188672f308d82a8ba01700 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 9 Aug 2018 14:04:14 -0600 Subject: PCI: Export pcie_has_flr() pcie_flr() suggests pcie_has_flr() to ensure that PCIe FLR support is present prior to calling. pcie_flr() is exported while pcie_has_flr() is not. Resolve this. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 3 ++- include/linux/pci.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d123c2b173da..85e5b80a69a7 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4039,7 +4039,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) * Returns true if the device advertises support for PCIe function level * resets. */ -static bool pcie_has_flr(struct pci_dev *dev) +bool pcie_has_flr(struct pci_dev *dev) { u32 cap; @@ -4049,6 +4049,7 @@ static bool pcie_has_flr(struct pci_dev *dev) pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); return cap & PCI_EXP_DEVCAP_FLR; } +EXPORT_SYMBOL_GPL(pcie_has_flr); /** * pcie_flr - initiate a PCIe function level reset diff --git a/include/linux/pci.h b/include/linux/pci.h index 307b336496f6..bace761deff2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1090,6 +1090,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev, enum pci_bus_speed *speed, enum pcie_link_width *width); void pcie_print_link_status(struct pci_dev *dev); +bool pcie_has_flr(struct pci_dev *dev); int pcie_flr(struct pci_dev *dev); int __pci_reset_function_locked(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev); -- cgit v1.2.3