Skip to content

Commit 85aabbd

Browse files
jpbruckerbjorn-helgaas
authored andcommitted
PCI/MSI: Fix MSIs for generic hosts that use device-tree's "msi-map"
Since commit 9ec37ef ("PCI/MSI: Make pci_host_common_probe() declare its reliance on MSI domains"), platforms that rely on the "msi-map" device-tree property don't get MSIs anymore. On the Arm Fast Model for example [1], the host bridge doesn't have a "msi-parent" property since it doesn't itself generate MSIs, and so doesn't get a MSI domain. It has an "msi-map" property instead to describe MSI controllers of child devices. As a result, due to the new msi_domain check in pci_register_host_bridge(), the whole bus gets PCI_BUS_FLAGS_NO_MSI. Check whether the root complex has an "msi-map" property before giving up on MSIs. [1] arch/arm64/boot/dts/arm/fvp-base-revc.dts Fixes: 9ec37ef ("PCI/MSI: Make pci_host_common_probe() declare its reliance on MSI domains") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jean-Philippe Brucker <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Acked-by: Marc Zyngier <[email protected]>
1 parent 2ee4c8a commit 85aabbd

File tree

3 files changed

+11
-1
lines changed

3 files changed

+11
-1
lines changed

drivers/pci/of.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
103103
#endif
104104
}
105105

106+
bool pci_host_of_has_msi_map(struct device *dev)
107+
{
108+
if (dev && dev->of_node)
109+
return of_get_property(dev->of_node, "msi-map", NULL);
110+
return false;
111+
}
112+
106113
static inline int __of_pci_pci_compare(struct device_node *node,
107114
unsigned int data)
108115
{

drivers/pci/probe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,8 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
925925
device_enable_async_suspend(bus->bridge);
926926
pci_set_bus_of_node(bus);
927927
pci_set_bus_msi_domain(bus);
928-
if (bridge->msi_domain && !dev_get_msi_domain(&bus->dev))
928+
if (bridge->msi_domain && !dev_get_msi_domain(&bus->dev) &&
929+
!pci_host_of_has_msi_map(parent))
929930
bus->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
930931

931932
if (!parent)

include/linux/pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,13 +2344,15 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
23442344
struct device_node;
23452345
struct irq_domain;
23462346
struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
2347+
bool pci_host_of_has_msi_map(struct device *dev);
23472348

23482349
/* Arch may override this (weak) */
23492350
struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
23502351

23512352
#else /* CONFIG_OF */
23522353
static inline struct irq_domain *
23532354
pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
2355+
static inline bool pci_host_of_has_msi_map(struct device *dev) { return false; }
23542356
#endif /* CONFIG_OF */
23552357

23562358
static inline struct device_node *

0 commit comments

Comments
 (0)