From 5396956cc7c6874180c9bfc1ceceb02b739a6a87 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 22 Jun 2020 19:12:48 +0300 Subject: PCI: Make pcie_find_root_port() work for Root Ports Commit 6ae72bfa656e ("PCI: Unify pcie_find_root_port() and pci_find_pcie_root_port()") broke acpi_pci_bridge_d3() because calling pcie_find_root_port() on a Root Port returned NULL when it should return the Root Port, which in turn broke power management of PCIe hierarchies. Rework pcie_find_root_port() so it returns its argument when it is already a Root Port. [bhelgaas: test device only once, test for PCIe] Fixes: 6ae72bfa656e ("PCI: Unify pcie_find_root_port() and pci_find_pcie_root_port()") Link: https://lore.kernel.org/r/20200622161248.51099-1-mika.westerberg@linux.intel.com Signed-off-by: Mika Westerberg Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index c79d83304e52..34c1c4f45288 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2169,12 +2169,11 @@ static inline int pci_pcie_type(const struct pci_dev *dev) */ static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev) { - struct pci_dev *bridge = pci_upstream_bridge(dev); - - while (bridge) { - if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) - return bridge; - bridge = pci_upstream_bridge(bridge); + while (dev) { + if (pci_is_pcie(dev) && + pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) + return dev; + dev = pci_upstream_bridge(dev); } return NULL; -- cgit From 16d79cd4e23b1964d36c041ab027505ceacbbeeb Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Thu, 2 Jul 2020 18:26:49 +0200 Subject: PCI: Use 'pci_channel_state_t' instead of 'enum pci_channel_state' The method struct pci_error_handlers.error_detected() is defined and documented as taking an 'enum pci_channel_state' for the second argument, but most drivers use 'pci_channel_state_t' instead. This 'pci_channel_state_t' is not a typedef for the enum but a typedef for a bitwise type in order to have better/stricter typechecking. Consolidate everything by using 'pci_channel_state_t' in the method's definition, in the related helpers and in the drivers. Enforce use of 'pci_channel_state_t' by replacing 'enum pci_channel_state' with an anonymous 'enum'. Note: Currently, from a typechecking point of view this patch changes nothing because only the constants defined by the enum are bitwise, not the enum itself (sparse doesn't have the notion of 'bitwise enum'). This may change in some not too far future, hence the patch. [bhelgaas: squash in https://lore.kernel.org/r/20200702162651.49526-3-luc.vanoostenryck@gmail.com https://lore.kernel.org/r/20200702162651.49526-4-luc.vanoostenryck@gmail.com] Link: https://lore.kernel.org/r/20200702162651.49526-2-luc.vanoostenryck@gmail.com Signed-off-by: Luc Van Oostenryck Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index c79d83304e52..adcee9e30bfa 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -179,7 +179,7 @@ static inline const char *pci_power_name(pci_power_t state) */ typedef unsigned int __bitwise pci_channel_state_t; -enum pci_channel_state { +enum { /* I/O channel is in normal state */ pci_channel_io_normal = (__force pci_channel_state_t) 1, @@ -785,7 +785,7 @@ enum pci_ers_result { struct pci_error_handlers { /* PCI bus error detected on this device */ pci_ers_result_t (*error_detected)(struct pci_dev *dev, - enum pci_channel_state error); + pci_channel_state_t error); /* MMIO has been re-enabled, but not DMA */ pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev); -- cgit From 52fbf5bdeeef415b28b8e6cdade1e48927927f60 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Tue, 7 Jul 2020 15:46:02 -0700 Subject: PCI: Cache ACS capability offset in device Currently the ACS capability is being looked up at a number of places. Read and store it once at enumeration so that it can be used by all later. No functional change intended. Link: https://lore.kernel.org/r/20200707224604.3737893-2-rajatja@google.com Signed-off-by: Rajat Jain Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index c79d83304e52..a26be5332bba 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -486,6 +486,7 @@ struct pci_dev { #ifdef CONFIG_PCI_P2PDMA struct pci_p2pdma *p2pdma; #endif + u16 acs_cap; /* ACS Capability offset */ phys_addr_t rom; /* Physical address if not from BAR */ size_t romlen; /* Length if not from BAR */ char *driver_override; /* Driver name to force a match */ -- cgit From 99b50be9d8ec9ef319cc7d5de07f4d405fac7764 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Tue, 7 Jul 2020 15:46:03 -0700 Subject: PCI: Treat "external-facing" devices themselves as internal "External-facing" devices are internal devices that expose PCIe hierarchies such as Thunderbolt outside the platform [1]. Previously these internal devices were marked as "untrusted" the same as devices downstream from them. Use the ACPI or DT information to identify external-facing devices, but only mark the devices *downstream* from them as "untrusted" [2]. The external-facing device itself is no longer marked as untrusted. [1] https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#identifying-externally-exposed-pcie-root-ports [2] https://lore.kernel.org/linux-pci/20200610230906.GA1528594@bjorn-Precision-5520/ Link: https://lore.kernel.org/r/20200707224604.3737893-3-rajatja@google.com Signed-off-by: Rajat Jain Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index a26be5332bba..7a40cd5caed0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -432,6 +432,12 @@ struct pci_dev { * mappings to make sure they cannot access arbitrary memory. */ unsigned int untrusted:1; + /* + * Info from the platform, e.g., ACPI or device tree, may mark a + * device as "external-facing". An external-facing device is + * itself internal but devices downstream from it are external. + */ + unsigned int external_facing:1; unsigned int broken_intx_masking:1; /* INTx masking can't be used */ unsigned int io_window_1k:1; /* Intel bridge 1K I/O windows */ unsigned int irq_managed:1; -- cgit From 2167c40657981f8a3d1ff1f04d4bda6b4a64f8e2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 28 Jul 2020 23:03:41 +0200 Subject: PCI: Remove unused pci_lost_interrupt() 388c8c16abaf ("PCI: add routines for debugging and handling lost interrupts") added pci_lost_interrupt() that apparently never has had a single user. Remove it. Link: https://lore.kernel.org/r/e328d059-3068-6a40-28df-f81f616d15a0@gmail.com Signed-off-by: Heiner Kallweit Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index c79d83304e52..2dcd67f509a8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1053,13 +1053,6 @@ void pci_sort_breadthfirst(void); /* Generic PCI functions exported to card drivers */ -enum pci_lost_interrupt_reason { - PCI_LOST_IRQ_NO_INFORMATION = 0, - PCI_LOST_IRQ_DISABLE_MSI, - PCI_LOST_IRQ_DISABLE_MSIX, - PCI_LOST_IRQ_DISABLE_ACPI, -}; -enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev); int pci_find_capability(struct pci_dev *dev, int cap); int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); int pci_find_ext_capability(struct pci_dev *dev, int cap); -- cgit From 669cbc708122fc7a02282058a09f096200cee090 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 21 Jul 2020 20:25:13 -0600 Subject: PCI: Move DT resource setup into devm_pci_alloc_host_bridge() Now that pci_parse_request_of_pci_ranges() callers just setup pci_host_bridge.windows and dma_ranges directly and don't need the bus range returned, we can just initialize them when allocating the pci_host_bridge struct. With this, pci_parse_request_of_pci_ranges() becomes a static function. Link: https://lore.kernel.org/r/20200722022514.1283916-19-robh@kernel.org Signed-off-by: Rob Herring Signed-off-by: Lorenzo Pieralisi Acked-by: Bjorn Helgaas Cc: Lorenzo Pieralisi Cc: Bjorn Helgaas --- include/linux/pci.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index c79d83304e52..2830799208fd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2303,10 +2303,6 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, struct device_node; struct irq_domain; struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus); -int pci_parse_request_of_pci_ranges(struct device *dev, - struct list_head *resources, - struct list_head *ib_resources, - struct resource **bus_range); /* Arch may override this (weak) */ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); @@ -2314,14 +2310,6 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); #else /* CONFIG_OF */ static inline struct irq_domain * pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; } -static inline int -pci_parse_request_of_pci_ranges(struct device *dev, - struct list_head *resources, - struct list_head *ib_resources, - struct resource **bus_range) -{ - return -EINVAL; -} #endif /* CONFIG_OF */ static inline struct device_node * -- cgit