All the flags defined in the enum pci_bus_flags are used to determine whether a particular feature of a PCI bus is available or not - features are also often disabled via architecture or device-specific quirk. These flags are tightly coupled with a PCI buses and PCI bridges and primarily used in simple binary on/off manner to check whether something is enabled or disabled, and have almost no other users (with an exception of the x86 architecture-specific quirk) outside of the PCI device drivers space. Therefore, convert enum pci_bus_flags into a set of bit fields in the struct pci_bus, and then drop said enum and the typedef pci_bus_flags_t. This will keep PCI device-specific features as part of the struct pci_dev and make the code that used to use flags simpler. Related: https://patchwork.kernel.org/patch/11772809 Suggested-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> Signed-off-by: Krzysztof Wilczyński <kw@xxxxxxxxx> --- arch/x86/pci/fixup.c | 6 +++--- drivers/pci/msi.c | 8 ++++---- drivers/pci/pci-sysfs.c | 14 ++++++-------- drivers/pci/pci.c | 2 +- drivers/pci/pcie/aer.c | 5 ++--- drivers/pci/probe.c | 13 +++++++++---- drivers/pci/quirks.c | 16 ++++++++-------- include/linux/pci.h | 20 ++++++++++---------- 8 files changed, 43 insertions(+), 41 deletions(-) diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index b8c9a5b87f37..50ff8aa542b8 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -641,14 +641,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff); * ID, the AER driver should traverse the child device tree, reading * AER registers to find the faulting device. */ -static void quirk_no_aersid(struct pci_dev *pdev) +static void quirk_no_aer_sid(struct pci_dev *pdev) { /* VMD Domain */ if (is_vmd(pdev->bus) && pci_is_root_bus(pdev->bus)) - pdev->bus->bus_flags |= PCI_BUS_FLAGS_NO_AERSID; + pdev->bus->no_aer_sid = 1; } DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, - PCI_CLASS_BRIDGE_PCI, 8, quirk_no_aersid); + PCI_CLASS_BRIDGE_PCI, 8, quirk_no_aer_sid); static void quirk_intel_th_dnv(struct pci_dev *dev) { diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 30ae4ffda5c1..01e4bdbc830e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -875,13 +875,13 @@ static int pci_msi_supported(struct pci_dev *dev, int nvec) /* * Any bridge which does NOT route MSI transactions from its - * secondary bus to its primary bus must set NO_MSI flag on - * the secondary pci_bus. + * secondary bus to its primary bus must enable "no_msi" on + * the secondary bus (pci_bus). * We expect only arch-specific PCI host bus controller driver - * or quirks for specific PCI bridges to be setting NO_MSI. + * or quirks for specific PCI bridges to enable "no_msi". */ for (bus = dev->bus; bus; bus = bus->parent) - if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + if (bus->no_msi) return 0; return 1; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6d78df981d41..eca214e45418 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -357,9 +357,7 @@ static ssize_t msi_bus_show(struct device *dev, struct device_attribute *attr, struct pci_dev *pdev = to_pci_dev(dev); struct pci_bus *subordinate = pdev->subordinate; - return sprintf(buf, "%u\n", subordinate ? - !(subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI) - : !pdev->no_msi); + return sprintf(buf, "%u\n", subordinate ? !subordinate->no_msi : !pdev->no_msi); } static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr, @@ -376,9 +374,9 @@ static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr, return -EPERM; /* - * "no_msi" and "bus_flags" only affect what happens when a driver - * requests MSI or MSI-X. They don't affect any drivers that have - * already requested MSI or MSI-X. + * "no_msi" enabled for device and bus only affect what happens + * when a driver requests MSI or MSI-X. They don't affect any + * drivers that have already requested MSI or MSI-X. */ if (!subordinate) { pdev->no_msi = !val; @@ -388,9 +386,9 @@ static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr, } if (val) - subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI; + subordinate->no_msi = 0; else - subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + subordinate->no_msi = 1; dev_info(&subordinate->dev, "MSI/MSI-X %s for future drivers of devices on this bus\n", val ? "allowed" : "disallowed"); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e39c5499770f..12d434eb1b97 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5657,7 +5657,7 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) o = (cmd & PCI_X_CMD_MAX_READ) >> 2; if (o != v) { - if (v > o && (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC)) + if (v > o && dev->bus->no_mmrbc) return -EIO; cmd &= ~PCI_X_CMD_MAX_READ; diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 65dff5f3457a..4272abab9695 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -827,8 +827,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) * When bus id is equal to 0, it might be a bad id * reported by root port. */ - if ((PCI_BUS_NUM(e_info->id) != 0) && - !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) { + if (PCI_BUS_NUM(e_info->id) != 0 && !dev->bus->no_aer_sid) { /* Device ID match? */ if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) return true; @@ -842,7 +841,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) * When either * 1) bus id is equal to 0. Some ports might lose the bus * id of error source id; - * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set + * 2) bus has "no_aer_sid" enabled * 3) There are multiple errors and prior ID comparing fails; * We check AER status registers to find possible reporter. */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 03d37128a24f..d3a92d60ae8f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1002,7 +1002,7 @@ static bool pci_bridge_child_ext_cfg_accessible(struct pci_dev *bridge) * If extended config space isn't accessible on a bridge's primary * bus, we certainly can't access it on the secondary bus. */ - if (bridge->bus->bus_flags & PCI_BUS_FLAGS_NO_EXTCFG) + if (bridge->bus->no_ext_cfg) return false; /* @@ -1048,7 +1048,12 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->ops = parent->ops; child->msi = parent->msi; child->sysdata = parent->sysdata; - child->bus_flags = parent->bus_flags; + + /* PCI bus flags */ + child->no_msi = parent->no_msi; + child->no_mmrbc = parent->no_mmrbc; + child->no_aer_sid = parent->no_aer_sid; + child->no_ext_cfg = parent->no_ext_cfg; /* * Initialize some portions of the bus device, but don't register @@ -1079,7 +1084,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, * the root bus. */ if (!pci_bridge_child_ext_cfg_accessible(bridge)) { - child->bus_flags |= PCI_BUS_FLAGS_NO_EXTCFG; + child->no_ext_cfg = 1; pci_info(child, "extended config space not accessible\n"); } @@ -1644,7 +1649,7 @@ int pci_cfg_space_size(struct pci_dev *dev) return PCI_CFG_SPACE_EXP_SIZE; #endif - if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_EXTCFG) + if (dev->bus->no_ext_cfg) return PCI_CFG_SPACE_SIZE; class = dev->class >> 8; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a589b6d6ed8..5fae54201b08 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1052,7 +1052,7 @@ static void quirk_amd_8131_mmrbc(struct pci_dev *dev) if (dev->subordinate && dev->revision <= 0x12) { pci_info(dev, "AMD8131 rev %x detected; disabling PCI-X MMRBC\n", dev->revision); - dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC; + dev->subordinate->no_mmrbc = 1; } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_mmrbc); @@ -2503,10 +2503,10 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB, #ifdef CONFIG_PCI_MSI /* - * Some chipsets do not support MSI. We cannot easily rely on setting - * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually some - * other buses controlled by the chipset even if Linux is not aware of it. - * Instead of setting the flag on all buses in the machine, simply disable + * Some chipsets do not support MSI. We cannot easily rely on enabling + * "no_msi" for its bus because there are actually some other buses + * controlled by the chipset even if Linux is not aware of it. Instead + * of enabling "no_msi" on all buses in the machine, simply disable * MSI globally. */ static void quirk_disable_all_msi(struct pci_dev *dev) @@ -2528,7 +2528,7 @@ static void quirk_disable_msi(struct pci_dev *dev) { if (dev->subordinate) { pci_warn(dev, "MSI quirk detected; subordinate MSI disabled\n"); - dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + dev->subordinate->no_msi = 1; } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); @@ -2586,7 +2586,7 @@ static void quirk_msi_ht_cap(struct pci_dev *dev) { if (dev->subordinate && !msi_ht_cap_enabled(dev)) { pci_warn(dev, "MSI quirk detected; subordinate MSI disabled\n"); - dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + dev->subordinate->no_msi = 1; } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE, @@ -2612,7 +2612,7 @@ static void quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) return; if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) { pci_warn(dev, "MSI quirk detected; subordinate MSI disabled\n"); - dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + dev->subordinate->no_msi = 1; } pci_dev_put(pdev); } diff --git a/include/linux/pci.h b/include/linux/pci.h index 835530605c0d..85204825d0a5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -234,14 +234,6 @@ enum pci_irq_reroute_variant { MAX_IRQ_REROUTE_VARIANTS = 3 }; -typedef unsigned short __bitwise pci_bus_flags_t; -enum pci_bus_flags { - PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, - PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, - PCI_BUS_FLAGS_NO_AERSID = (__force pci_bus_flags_t) 4, - PCI_BUS_FLAGS_NO_EXTCFG = (__force pci_bus_flags_t) 8, -}; - /* Values from Link Status register, PCIe r3.1, sec 7.8.8 */ enum pcie_link_width { PCIE_LNK_WIDTH_RESRV = 0x00, @@ -627,12 +619,20 @@ struct pci_bus { char name[48]; unsigned short bridge_ctl; /* Manage NO_ISA/FBB/et al behaviors */ - pci_bus_flags_t bus_flags; /* Inherited by child buses */ struct device *bridge; struct device dev; struct bin_attribute *legacy_io; /* Legacy I/O for this bus */ struct bin_attribute *legacy_mem; /* Legacy mem */ - unsigned int is_added:1; + unsigned int is_added:1; /* This bus has already been registered */ + + /* PCI bus flags are inherited by child buses */ + unsigned int no_msi:1; /* Don't use MSI/MSI-X for devices behind a bridge that does not route + MSI transactions from its secondary bus to its primary bus */ + unsigned int no_mmrbc:1; /* Disallow setting PCI-X Maximum Memory Read Byte Count on this bus */ + unsigned int no_aer_sid:1; /* Allow Root Port buses to skip the AER source ID matching when finding + the faulting device */ + unsigned int no_ext_cfg:1; /* Don't use PCIe/PCI-X Mode 2 Extended Configuration Space + when it isn't available on bridge's primary bus */ }; #define to_pci_bus(n) container_of(n, struct pci_bus, dev) -- 2.28.0