From 62ce94a7a5a54aac80975f5e6731707225d4077e Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Wed, 12 Jul 2017 00:04:14 -0400 Subject: PCI: Mark Broadcom HT2100 Root Port Extended Tags as broken Per PCIe r3.1, sec 2.2.6.2 and 7.8.4, a Requester may not use 8-bit Tags unless its Extended Tag Field Enable is set, but all Receivers/Completers must handle 8-bit Tags correctly regardless of their Extended Tag Field Enable. Some devices do not handle 8-bit Tags as Completers, so add a quirk for them. If we find such a device, we disable Extended Tags for the entire hierarchy to make peer-to-peer DMA possible. The Broadcom HT2100 seems to have issues with handling 8-bit tags. Mark it as broken. The pci_walk_bus() in the quirk handles devices we've enumerated in the past, and pci_configure_device() handles devices we enumerate in the future. Fixes: 60db3a4d8cc9 ("PCI: Enable PCIe Extended Tags if supported") Link: https://bugzilla.redhat.com/show_bug.cgi?id=1467674 Reported-and-tested-by: Wim ten Have Signed-off-by: Sinan Kaya [bhelgaas: changelog, tweak messages, rename bit and quirk] 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 4869e66dd659..3b968d435895 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -451,6 +451,7 @@ struct pci_host_bridge { void *release_data; struct msi_controller *msi; unsigned int ignore_reset_delay:1; /* for entire hierarchy */ + unsigned int no_ext_tags:1; /* no Extended Tags */ /* Resource alignment requirements */ resource_size_t (*align_resource)(struct pci_dev *dev, const struct resource *res, -- cgit v1.2.1 From 004cb784018eaa2a078912180bd9999707c3c483 Mon Sep 17 00:00:00 2001 From: Matthew Minter Date: Mon, 31 Jul 2017 17:37:57 +0100 Subject: PCI: Remove unused pci_fixup_irqs() function Now we have removed all callers of pci_fixup_irqs() and migrated everything to pci_assign_irq(), delete the pci_fixup_irqs() function completely. Signed-off-by: Matthew Minter [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index 4869e66dd659..69034ab8a68e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1160,8 +1160,6 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus); void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus); void pdev_enable_device(struct pci_dev *); int pci_enable_resources(struct pci_dev *, int mask); -void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), - int (*)(const struct pci_dev *, u8, u8)); void pci_assign_irq(struct pci_dev *dev); struct resource *pci_find_resource(struct pci_dev *dev, struct resource *res); #define HAVE_PCI_REQ_REGIONS 2 -- cgit v1.2.1 From 606799cc5049ae4ccb51ba3242365ca2d411da13 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 10 Aug 2017 12:49:57 -0500 Subject: PCI: Inline and remove pcibios_update_irq() pcibios_update_irq() was a weak function with only one trivial implementation. Inline it and remove the weak function. Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index 69034ab8a68e..a9e8d2f3bd91 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -844,7 +844,6 @@ char *pcibios_setup(char *str); resource_size_t pcibios_align_resource(void *, const struct resource *, resource_size_t, resource_size_t); -void pcibios_update_irq(struct pci_dev *, int irq); /* Weak but can be overriden by arch */ void pci_fixup_cardbus(struct pci_bus *); -- cgit v1.2.1 From b352baf15b66c5799018104d38f9eb77c7445a34 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 15 Aug 2017 12:02:16 -0700 Subject: PCI: Move enum pci_interrupt_pin to linux/pci.h We currently have a definition of enum pci_interrupt_pin in a header specific to PCI endpoints - linux/pci-epf.h. In order to allow for use of this enum from PCI host code in a future commit, move its definition to linux/pci.h & include that from linux/pci-epf.h. Additionally we add a PCI_NUM_INTX macro which indicates the number of PCI INTx interrupts, and will be used alongside enum pci_interrupt_pin in further patches. Signed-off-by: Paul Burton [bhelgaas: move enum pci_interrupt_pin outside #ifdef CONFIG_PCI] Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index 4869e66dd659..bb9c367c85f0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -102,6 +102,28 @@ enum { DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES, }; +/** + * enum pci_interrupt_pin - PCI INTx interrupt values + * @PCI_INTERRUPT_UNKNOWN: Unknown or unassigned interrupt + * @PCI_INTERRUPT_INTA: PCI INTA pin + * @PCI_INTERRUPT_INTB: PCI INTB pin + * @PCI_INTERRUPT_INTC: PCI INTC pin + * @PCI_INTERRUPT_INTD: PCI INTD pin + * + * Corresponds to values for legacy PCI INTx interrupts, as can be found in the + * PCI_INTERRUPT_PIN register. + */ +enum pci_interrupt_pin { + PCI_INTERRUPT_UNKNOWN, + PCI_INTERRUPT_INTA, + PCI_INTERRUPT_INTB, + PCI_INTERRUPT_INTC, + PCI_INTERRUPT_INTD, +}; + +/* The number of legacy PCI INTx interrupts */ +#define PCI_NUM_INTX 4 + /* * pci_power_t values must match the bits in the Capabilities PME_Support * and Control/Status PowerState fields in the Power Management capability. -- cgit v1.2.1 From 0d58e6c1b19b30623b5f0a053818bd2c32d61166 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 15 Aug 2017 12:02:17 -0700 Subject: PCI: Add pci_irqd_intx_xlate() Legacy PCI INTx interrupts are represented in the PCI_INTERRUPT_PIN register using the range 1-4, which matches our enum pci_interrupt_pin. This is however not ideal for an IRQ domain, where with 4 interrupts we would ideally have a domain of size 4 & hwirq numbers in the range 0-3. Different PCI host controller drivers have handled this in different ways. Of those under drivers/pci/ which register an INTx IRQ domain, we have: - pcie-altera uses the range 1-4 in device trees and an IRQ domain of size 5 to cover that range, with entry 0 wasted. - pcie-xilinx & pcie-xilinx-nwl use the range 1-4 in device trees but register an IRQ domain of size 4, which doesn't cover the hwirq=4/INTD case leading to that interrupt being broken. - pci-ftpci100 & pci-aardvark use the range 0-3 in both device trees & as hwirq numbering in the driver & IRQ domain. In order to introduce some level of consistency in at least the hwirq numbering used by the drivers & IRQ domains, this patch introduces a new pci_irqd_intx_xlate() helper function which drivers using the 1-4 range in device trees can assign as the xlate callback for their INTx IRQ domain. This translates the 1-4 range into a 0-3 range, allowing us to use an IRQ domain of size 4 & avoid a wasted entry. Further patches will make use of this in drivers to allow them to use an IRQ domain of size 4 for legacy INTx interrupts without breaking INTD. Signed-off-by: Paul Burton Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index bb9c367c85f0..bbc2a991b63f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1416,6 +1416,38 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, NULL); } +/** + * pci_irqd_intx_xlate() - Translate PCI INTx value to an IRQ domain hwirq + * @d: the INTx IRQ domain + * @node: the DT node for the device whose interrupt we're translating + * @intspec: the interrupt specifier data from the DT + * @intsize: the number of entries in @intspec + * @out_hwirq: pointer at which to write the hwirq number + * @out_type: pointer at which to write the interrupt type + * + * Translate a PCI INTx interrupt number from device tree in the range 1-4, as + * stored in the standard PCI_INTERRUPT_PIN register, to a value in the range + * 0-3 suitable for use in a 4 entry IRQ domain. That is, subtract one from the + * INTx value to obtain the hwirq number. + * + * Returns 0 on success, or -EINVAL if the interrupt specifier is out of range. + */ +static inline int pci_irqd_intx_xlate(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + const u32 intx = intspec[0]; + + if (intx < PCI_INTERRUPT_INTA || intx > PCI_INTERRUPT_INTD) + return -EINVAL; + + *out_hwirq = intx - PCI_INTERRUPT_INTA; + return 0; +} + #ifdef CONFIG_PCIEPORTBUS extern bool pcie_ports_disabled; extern bool pcie_ports_auto; -- cgit v1.2.1 From 0142626d08223b0f6ad04859301b53178f11c317 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 1 Sep 2017 16:35:20 -0500 Subject: PCI: Correct kernel-doc of pci_vpd_srdt_size(), pci_vpd_srdt_tag() The kernel-doc comments don't match the arguments, so fix the comments. Signed-off-by: Shawn Lin 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 4869e66dd659..7950fc697394 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2059,7 +2059,7 @@ static inline u16 pci_vpd_lrdt_tag(const u8 *lrdt) /** * pci_vpd_srdt_size - Extracts the Small Resource Data Type length - * @lrdt: Pointer to the beginning of the Small Resource Data Type tag + * @srdt: Pointer to the beginning of the Small Resource Data Type tag * * Returns the extracted Small Resource Data Type length. */ @@ -2070,7 +2070,7 @@ static inline u8 pci_vpd_srdt_size(const u8 *srdt) /** * pci_vpd_srdt_tag - Extracts the Small Resource Data Type Tag Item - * @lrdt: Pointer to the beginning of the Small Resource Data Type tag + * @srdt: Pointer to the beginning of the Small Resource Data Type tag * * Returns the extracted Small Resource Data Type Tag Item. */ -- cgit v1.2.1