diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index c0430bb1c73ab..b0c4f8446d0c2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -58,23 +58,15 @@ struct iommu_group { void *iommu_data; void (*iommu_data_release)(void *iommu_data); char *name; + int id; struct iommu_domain *default_domain; struct iommu_domain *blocking_domain; struct iommu_domain *domain; struct list_head entry; - void *owner; unsigned int owner_cnt; - int id; - - /* Used by the device_group() callbacks */ - u32 bus_data; + void *owner; }; -/* - * Everything downstream of this group should share it. - */ -#define BUS_DATA_PCI_NON_ISOLATED BIT(0) - struct group_device { struct list_head list; struct device *dev; @@ -1389,376 +1381,210 @@ int iommu_group_id(struct iommu_group *group) } EXPORT_SYMBOL_GPL(iommu_group_id); +static struct iommu_group *get_pci_alias_group(struct pci_dev *pdev, + unsigned long *devfns); + /* - * Generic device_group call-back function. It just allocates one - * iommu-group per device. + * To consider a PCI device isolated, we require ACS to support Source + * Validation, Request Redirection, Completer Redirection, and Upstream + * Forwarding. This effectively means that devices cannot spoof their + * requester ID, requests and completions cannot be redirected, and all + * transactions are forwarded upstream, even as it passes through a + * bridge where the target device is downstream. */ -struct iommu_group *generic_device_group(struct device *dev) -{ - return iommu_group_alloc(); -} -EXPORT_SYMBOL_GPL(generic_device_group); +#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) /* - * Generic device_group call-back function. It just allocates one - * iommu-group per iommu driver instance shared by every device - * probed by that iommu driver. + * For multifunction devices which are not isolated from each other, find + * all the other non-isolated functions and look for existing groups. For + * each function, we also need to look for aliases to or from other devices + * that may already have a group. */ -struct iommu_group *generic_single_device_group(struct device *dev) +static struct iommu_group *get_pci_function_alias_group(struct pci_dev *pdev, + unsigned long *devfns) { - struct iommu_device *iommu = dev->iommu->iommu_dev; + struct pci_dev *tmp = NULL; + struct iommu_group *group; - if (!iommu->singleton_group) { - struct iommu_group *group; + if (!pdev->multifunction || pci_acs_enabled(pdev, REQ_ACS_FLAGS)) + return NULL; - group = iommu_group_alloc(); - if (IS_ERR(group)) + for_each_pci_dev(tmp) { + if (tmp == pdev || tmp->bus != pdev->bus || + PCI_SLOT(tmp->devfn) != PCI_SLOT(pdev->devfn) || + pci_acs_enabled(tmp, REQ_ACS_FLAGS)) + continue; + + group = get_pci_alias_group(tmp, devfns); + if (group) { + pci_dev_put(tmp); return group; - iommu->singleton_group = group; + } } - return iommu_group_ref_get(iommu->singleton_group); + + return NULL; } -EXPORT_SYMBOL_GPL(generic_single_device_group); -static struct iommu_group *pci_group_alloc_non_isolated(void) +/* + * Look for aliases to or from the given device for existing groups. DMA + * aliases are only supported on the same bus, therefore the search + * space is quite small (especially since we're really only looking at pcie + * device, and therefore only expect multiple slots on the root complex or + * downstream switch ports). It's conceivable though that a pair of + * multifunction devices could have aliases between them that would cause a + * loop. To prevent this, we use a bitmap to track where we've been. + */ +static struct iommu_group *get_pci_alias_group(struct pci_dev *pdev, + unsigned long *devfns) { + struct pci_dev *tmp = NULL; struct iommu_group *group; - group = iommu_group_alloc(); - if (IS_ERR(group)) + if (test_and_set_bit(pdev->devfn & 0xff, devfns)) + return NULL; + + group = iommu_group_get(&pdev->dev); + if (group) return group; - group->bus_data |= BUS_DATA_PCI_NON_ISOLATED; - return group; + + for_each_pci_dev(tmp) { + if (tmp == pdev || tmp->bus != pdev->bus) + continue; + + /* We alias them or they alias us */ + if (pci_devs_are_dma_aliases(pdev, tmp)) { + group = get_pci_alias_group(tmp, devfns); + if (group) { + pci_dev_put(tmp); + return group; + } + + group = get_pci_function_alias_group(tmp, devfns); + if (group) { + pci_dev_put(tmp); + return group; + } + } + } + + return NULL; } +struct group_for_pci_data { + struct pci_dev *pdev; + struct iommu_group *group; +}; + /* - * Ignoring quirks, all functions in the MFD need to be isolated from each other - * and get their own groups, otherwise the whole MFD will share a group. Any - * function that lacks explicit ACS isolation is assumed to be able to P2P - * access any other function in the MFD. + * DMA alias iterator callback, return the last seen device. Stop and return + * the IOMMU group if we find one along the way. */ -static bool pci_mfds_are_same_group(struct pci_dev *deva, struct pci_dev *devb) +static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque) { - /* Are deva/devb functions in the same MFD? */ - if (PCI_SLOT(deva->devfn) != PCI_SLOT(devb->devfn)) - return false; - /* Don't understand what is happening, be conservative */ - if (deva->multifunction != devb->multifunction) - return true; - if (!deva->multifunction) - return false; + struct group_for_pci_data *data = opaque; - /* Quirks can inhibit single MFD functions from combining into groups */ - if (pci_mfd_isolated(deva) || pci_mfd_isolated(devb)) - return false; + data->pdev = pdev; + data->group = iommu_group_get(&pdev->dev); - /* Can they reach each other's MMIO through P2P? */ - return !pci_acs_enabled(deva, PCI_ACS_ISOLATED) || - !pci_acs_enabled(devb, PCI_ACS_ISOLATED); + return data->group != NULL; } -static bool pci_devs_are_same_group(struct pci_dev *deva, struct pci_dev *devb) +/* + * Generic device_group call-back function. It just allocates one + * iommu-group per device. + */ +struct iommu_group *generic_device_group(struct device *dev) { - /* - * This is allowed to return cycles: a,b -> b,c -> c,a can be aliases. - */ - if (pci_devs_are_dma_aliases(deva, devb)) - return true; - - return pci_mfds_are_same_group(deva, devb); + return iommu_group_alloc(); } +EXPORT_SYMBOL_GPL(generic_device_group); -static struct iommu_group *pci_get_alias_group(struct pci_dev *pdev) +/* + * Generic device_group call-back function. It just allocates one + * iommu-group per iommu driver instance shared by every device + * probed by that iommu driver. + */ +struct iommu_group *generic_single_device_group(struct device *dev) { - struct pci_reachable_set devfns; - const unsigned int NR_DEVFNS = sizeof(devfns.devfns) * BITS_PER_BYTE; - unsigned int devfn; - - /* - * Look for existing groups on device aliases and multi-function ACS. If - * we alias another device or another device aliases us, use the same - * group. - * - * pci_reachable_set() should return the same bitmap if called for any - * device in the set and we want all devices in the set to have the same - * group. - */ - pci_reachable_set(pdev, &devfns, pci_devs_are_same_group); - /* start is known to have iommu_group_get() == NULL */ - __clear_bit(pdev->devfn, devfns.devfns); - - /* - * When MFD functions are included in the set due to ACS we assume that - * if ACS permits an internal loopback between functions it also permits - * the loopback to go downstream if any function is a bridge. - * - * It is less clear what aliases mean when applied to a bridge. For now - * be conservative and also propagate the group downstream. - */ - if (bitmap_empty(devfns.devfns, NR_DEVFNS)) - return NULL; + struct iommu_device *iommu = dev->iommu->iommu_dev; - for_each_set_bit(devfn, devfns.devfns, NR_DEVFNS) { + if (!iommu->singleton_group) { struct iommu_group *group; - struct pci_dev *pdev_slot; - pdev_slot = pci_get_slot(pdev->bus, devfn); - group = iommu_group_get(&pdev_slot->dev); - pci_dev_put(pdev_slot); - if (group) { - if (WARN_ON(!(group->bus_data & - BUS_DATA_PCI_NON_ISOLATED))) - group->bus_data |= BUS_DATA_PCI_NON_ISOLATED; + group = iommu_group_alloc(); + if (IS_ERR(group)) return group; - } - } - return pci_group_alloc_non_isolated(); -} - -static struct iommu_group *pci_hierarchy_group(struct pci_dev *pdev) -{ - /* - * SRIOV functions may resid on a virtual bus, jump directly to the PFs - * bus in all cases. - */ - struct pci_bus *bus = pci_physfn(pdev)->bus; - struct iommu_group *group; - - /* Nothing upstream of this */ - if (pci_is_root_bus(bus)) - return NULL; - - /* - * !self is only for SRIOV virtual busses which should have been - * excluded above. - */ - if (WARN_ON(!bus->self)) - return ERR_PTR(-EINVAL); - - group = iommu_group_get(&bus->self->dev); - if (!group) { - /* - * If the upstream bridge needs the same group as pdev then - * there is no way for it's pci_device_group() to discover it. - */ - dev_err(&pdev->dev, - "PCI device is probing out of order, upstream bridge device of %s is not probed yet\n", - pci_name(bus->self)); - return ERR_PTR(-EPROBE_DEFER); + iommu->singleton_group = group; } - if (group->bus_data & BUS_DATA_PCI_NON_ISOLATED) - return group; - iommu_group_put(group); - return NULL; + return iommu_group_ref_get(iommu->singleton_group); } +EXPORT_SYMBOL_GPL(generic_single_device_group); /* - * For legacy PCI we have two main considerations when forming groups: - * - * 1) In PCI we can loose the RID inside the fabric, or some devices will use - * the wrong RID. The PCI core calls this aliasing, but from an IOMMU - * perspective it means that a PCI device may have multiple RIDs and a - * single RID may represent many PCI devices. This effectively means all the - * aliases must share a translation, thus group, because the IOMMU cannot - * tell devices apart. - * - * 2) PCI permits a bus segment to claim an address even if the transaction - * originates from an end point not the CPU. When it happens it is called - * peer to peer. Claiming a transaction in the middle of the bus hierarchy - * bypasses the IOMMU translation. The IOMMU subsystem rules require these - * devices to be placed in the same group because they lack isolation from - * each other. In PCI Express the ACS system can be used to inhibit this and - * force transactions to go to the IOMMU. - * - * From a PCI perspective any given PCI bus is either isolating or - * non-isolating. Isolating means downstream originated transactions always - * progress toward the CPU and do not go to other devices on the bus - * segment, while non-isolating means downstream originated transactions can - * progress back downstream through another device on the bus segment. - * - * Beyond buses a multi-function device or bridge can also allow - * transactions to loop back internally from one function to another. - * - * Once a PCI bus becomes non isolating the entire downstream hierarchy of - * that bus becomes a single group. + * Use standard PCI bus topology, isolation features, and DMA alias quirks + * to find or create an IOMMU group for a device. */ -static struct iommu_group *__pci_device_group(struct device *dev) +struct iommu_group *pci_device_group(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct iommu_group *group; - struct pci_dev *real_pdev; + struct group_for_pci_data data; + struct pci_bus *bus; + struct iommu_group *group = NULL; + u64 devfns[4] = { 0 }; if (WARN_ON(!dev_is_pci(dev))) return ERR_PTR(-EINVAL); /* - * Arches can supply a completely different PCI device that actually - * does DMA. + * Find the upstream DMA alias for the device. A device must not + * be aliased due to topology in order to have its own IOMMU group. + * If we find an alias along the way that already belongs to a + * group, use it. */ - real_pdev = pci_real_dma_dev(pdev); - if (real_pdev != pdev) { - group = iommu_group_get(&real_pdev->dev); - if (!group) { - /* - * The real_pdev has not had an iommu probed to it. We - * can't create a new group here because there is no way - * for pci_device_group(real_pdev) to pick it up. - */ - dev_err(dev, - "PCI device is probing out of order, real device of %s is not probed yet\n", - pci_name(real_pdev)); - return ERR_PTR(-EPROBE_DEFER); - } - return group; - } + if (pci_for_each_dma_alias(pdev, get_pci_alias_or_group, &data)) + return data.group; - if (pdev->dev_flags & PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT) - return iommu_group_alloc(); + pdev = data.pdev; - /* Anything upstream of this enforcing non-isolated? */ - group = pci_hierarchy_group(pdev); - if (group) - return group; + /* + * Continue upstream from the point of minimum IOMMU granularity + * due to aliases to the point where devices are protected from + * peer-to-peer DMA by PCI ACS. Again, if we find an existing + * group, use it. + */ + for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) { + if (!bus->self) + continue; + + if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) + break; + + pdev = bus->self; - switch (pci_bus_isolated(pci_physfn(pdev)->bus)) { - case PCIE_ISOLATED: - /* Check multi-function groups and same-bus devfn aliases */ - group = pci_get_alias_group(pdev); + group = iommu_group_get(&pdev->dev); if (group) return group; - - /* No shared group found, allocate new */ - return iommu_group_alloc(); + } /* - * On legacy PCI there is no RID at an electrical level. On PCI-X the - * RID of the bridge may be used in some cases instead of the - * downstream's RID. This creates aliasing problems. PCI/PCI-X doesn't - * provide isolation either. The end result is that as soon as we hit a - * PCI/PCI-X bus we switch to non-isolated for the whole downstream for - * both aliasing and isolation reasons. The bridge has to be included in - * the group because of the aliasing. + * Look for existing groups on device aliases. If we alias another + * device or another device aliases us, use the same group. */ - case PCI_BRIDGE_NON_ISOLATED: - /* A PCIe switch where the USP has MMIO and is not isolated. */ - case PCIE_NON_ISOLATED: - group = iommu_group_get(&pdev->bus->self->dev); - if (WARN_ON(!group)) - return ERR_PTR(-EINVAL); - /* - * No need to be concerned with aliases here since we are going - * to put the entire downstream tree in the bridge/USP's group. - */ - group->bus_data |= BUS_DATA_PCI_NON_ISOLATED; + group = get_pci_alias_group(pdev, (unsigned long *)devfns); + if (group) return group; /* - * It is a PCI bus and the upstream bridge/port does not alias or allow - * P2P. - */ - case PCI_BUS_NON_ISOLATED: - /* - * It is a PCIe switch and the DSP cannot reach the USP. The DSP's - * are not isolated from each other and share a group. + * Look for existing groups on non-isolated functions on the same + * slot and aliases of those funcions, if any. No need to clear + * the search bitmap, the tested devfns are still valid. */ - case PCIE_SWITCH_DSP_NON_ISOLATED: { - struct pci_dev *piter = NULL; - - /* - * All the downstream devices on the bus share a group. If this - * is a PCIe switch then they will all be DSPs - */ - for_each_pci_dev(piter) { - if (piter->bus != pdev->bus) - continue; - group = iommu_group_get(&piter->dev); - if (group) { - pci_dev_put(piter); - if (WARN_ON(!(group->bus_data & - BUS_DATA_PCI_NON_ISOLATED))) - group->bus_data |= - BUS_DATA_PCI_NON_ISOLATED; - return group; - } - } - return pci_group_alloc_non_isolated(); - } - default: - break; - } - WARN_ON(true); - return ERR_PTR(-EINVAL); -} - -struct check_group_aliases_data { - struct pci_dev *pdev; - struct iommu_group *group; -}; - -static void pci_check_group(const struct check_group_aliases_data *data, - u16 alias, struct pci_dev *pdev) -{ - struct iommu_group *group; - - group = iommu_group_get(&pdev->dev); - if (!group) - return; - - if (group != data->group) - dev_err(&data->pdev->dev, - "During group construction alias processing needed dev %s alias %x to have the same group but %u != %u\n", - pci_name(pdev), alias, data->group->id, group->id); - iommu_group_put(group); -} - -static int pci_check_group_aliases(struct pci_dev *pdev, u16 alias, - void *opaque) -{ - const struct check_group_aliases_data *data = opaque; - - /* - * Sometimes when a PCIe-PCI bridge is performing transactions on behalf - * of its subordinate bus it uses devfn=0 on the subordinate bus as the - * alias. This means that 0 will alias with all devfns on the - * subordinate bus and so we expect to see those in the same group. pdev - * in this case is the bridge itself and pdev->bus is the primary bus of - * the bridge. - */ - if (pdev->bus->number != PCI_BUS_NUM(alias)) { - struct pci_dev *piter = NULL; - - for_each_pci_dev(piter) { - if (pci_domain_nr(pdev->bus) == - pci_domain_nr(piter->bus) && - PCI_BUS_NUM(alias) == pdev->bus->number) - pci_check_group(data, alias, piter); - } - } else { - pci_check_group(data, alias, pdev); - } - - return 0; -} - -struct iommu_group *pci_device_group(struct device *dev) -{ - struct iommu_group *group = __pci_device_group(dev); - - if (!IS_ERR(group)) { - struct check_group_aliases_data data = { - .pdev = to_pci_dev(dev), .group = group - }; + group = get_pci_function_alias_group(pdev, (unsigned long *)devfns); + if (group) + return group; - /* - * The IOMMU driver should use pci_for_each_dma_alias() to - * figure out what RIDs to program and the core requires all the - * RIDs to fall within the same group. Validate that everything - * worked properly. - */ - pci_for_each_dma_alias(data.pdev, pci_check_group_aliases, - &data); - } - return group; + /* No shared group found, allocate new */ + return iommu_group_alloc(); } EXPORT_SYMBOL_GPL(pci_device_group); diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 00603c2c4ff0e..ec6c8dbdc5e9c 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -416,9 +416,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features) if (!pasid) return -EINVAL; - if (!pci_acs_path_enabled(pdev, NULL, - PCI_ACS_RR | PCI_ACS_UF | PCI_ACS_USP_MT_RR | - PCI_ACS_DSP_MT_RR | PCI_ACS_UNCLAIMED_RR)) + if (!pci_acs_path_enabled(pdev, NULL, PCI_ACS_RR | PCI_ACS_UF)) return -EINVAL; pci_read_config_word(pdev, pasid + PCI_PASID_CAP, &supported); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index debbee30cab07..5d92089776652 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -957,7 +957,6 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, const char *p, const u16 acs_mask, const u16 acs_flags) { u16 flags = acs_flags; - u16 supported_flags; u16 mask = acs_mask; char *delimit; int ret = 0; @@ -1002,14 +1001,8 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, } } - supported_flags = PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | - PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_EC | - PCI_ACS_DT; - if (caps->cap & PCI_ACS_ENHANCED) - supported_flags |= PCI_ACS_USP_MT_RR | - PCI_ACS_DSP_MT_RR | - PCI_ACS_UNCLAIMED_RR; - if (mask & ~supported_flags) { + if (mask & ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | PCI_ACS_CR | + PCI_ACS_UF | PCI_ACS_EC | PCI_ACS_DT)) { pci_err(dev, "Invalid ACS flags specified\n"); return; } @@ -1069,14 +1062,6 @@ static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps) /* Upstream Forwarding */ caps->ctrl |= (caps->cap & PCI_ACS_UF); - /* - * USP/DSP Memory Target Access Control and Unclaimed Request Redirect - */ - if (caps->cap & PCI_ACS_ENHANCED) { - caps->ctrl |= PCI_ACS_USP_MT_RR | PCI_ACS_DSP_MT_RR | - PCI_ACS_UNCLAIMED_RR; - } - /* Enable Translation Blocking for external devices and noats */ if (pci_ats_disabled() || dev->external_facing || dev->untrusted) caps->ctrl |= (caps->cap & PCI_ACS_TB); @@ -3602,52 +3587,6 @@ void pci_configure_ari(struct pci_dev *dev) } } - -/* - * The spec is not clear what it means if the capability bit is 0. One view is - * that the device acts as though the ctrl bit is zero, another view is the - * device behavior is undefined. - * - * Historically Linux has taken the position that the capability bit as 0 means - * the device supports the most favorable interpritation of the spec - ie that - * things like P2P RR are always on. As this is security sensitive we expect - * devices that do not follow this rule to be quirked. - * - * ACS Enhanced eliminated undefined areas of the spec around MMIO in root ports - * and switch ports. If those ports have no MMIO then it is not relavent. - * PCI_ACS_UNCLAIMED_RR eliminates the undefined area around an upstream switch - * window that is not fully decoded by the downstream windows. - * - * This takes the same approach with ACS Enhanced, if the device does not - * support it then we assume the ACS P2P RR has all the enhanced behaviors too. - * - * Due to ACS Enhanced bits being force set to 0 by older Linux kernels, and - * those values would break old kernels on the edge cases they cover, the only - * compatible thing for a new device to implement is ACS Enhanced supported with - * the control bits (except PCI_ACS_IORB) wired to follow ACS_RR. - */ -static u16 pci_acs_ctrl_mask(struct pci_dev *pdev, u16 hw_cap) -{ - /* - * Egress Control enables use of the Egress Control Vector which is not - * present without the cap. - */ - u16 mask = PCI_ACS_EC; - - mask = hw_cap & (PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | - PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT); - - /* - * If ACS Enhanced is supported the device reports what it is doing - * through these bits which may not be settable. - */ - if (hw_cap & PCI_ACS_ENHANCED) - mask |= PCI_ACS_IORB | PCI_ACS_DSP_MT_RB | PCI_ACS_DSP_MT_RR | - PCI_ACS_USP_MT_RB | PCI_ACS_USP_MT_RR | - PCI_ACS_UNCLAIMED_RR; - return mask; -} - static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) { int pos; @@ -3657,9 +3596,15 @@ static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) if (!pos) return false; + /* + * Except for egress control, capabilities are either required + * or only required if controllable. Features missing from the + * capability field can therefore be assumed as hard-wired enabled. + */ pci_read_config_word(pdev, pos + PCI_ACS_CAP, &cap); + acs_flags &= (cap | PCI_ACS_EC); + pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); - acs_flags &= pci_acs_ctrl_mask(pdev, cap); return (ctrl & acs_flags) == acs_flags; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 69a7be7297282..bf23f4b96fb63 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -714,7 +714,6 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); int pci_dev_specific_enable_acs(struct pci_dev *dev); int pci_dev_specific_disable_acs_redir(struct pci_dev *dev); int pcie_failed_link_retrain(struct pci_dev *dev); -bool pci_dev_specific_mfd_isolated(struct pci_dev *dev); #else static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) @@ -733,10 +732,6 @@ static inline int pcie_failed_link_retrain(struct pci_dev *dev) { return -ENOTTY; } -static inline bool pci_dev_specific_mfd_isolated(struct pci_dev *dev) -{ - return false; -} #endif /* PCI error reporting and recovery */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f4f6a2f45733f..aad419b819a6d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4646,8 +4646,6 @@ static void quirk_chelsio_T5_disable_root_port_attributes(struct pci_dev *pdev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID, quirk_chelsio_T5_disable_root_port_attributes); -#define PCI_ACS_QUIRK_ACS_ISOLATED BIT(16) - /* * pci_acs_ctrl_enabled - compare desired ACS controls with those provided * by a device @@ -4659,21 +4657,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID, * in @acs_ctrl_ena, i.e., the device provides all the access controls the * caller desires. Return 0 otherwise. */ -static int pci_acs_ctrl_enabled(u32 acs_ctrl_req, u32 acs_ctrl_ena) +static int pci_acs_ctrl_enabled(u16 acs_ctrl_req, u16 acs_ctrl_ena) { if ((acs_ctrl_req & acs_ctrl_ena) == acs_ctrl_req) return 1; return 0; } -static int pci_acs_ctrl_isolated(u32 acs_flags) -{ - return pci_acs_ctrl_enabled(acs_flags, - PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); -} - -static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u32 acs_flags); - /* * AMD has indicated that the devices below do not support peer-to-peer * in any system where they are found in the southbridge with an AMD @@ -4699,7 +4689,7 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u32 acs_flags); * 1022:780f [AMD] FCH PCI Bridge * 1022:7809 [AMD] FCH USB OHCI Controller */ -static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags) { #ifdef CONFIG_ACPI struct acpi_table_header *header = NULL; @@ -4716,7 +4706,10 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u32 acs_flags) acpi_put_table(header); - return pci_quirk_mf_endpoint_acs(dev, acs_flags); + /* Filter out flags not applicable to multifunction */ + acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); + + return pci_acs_ctrl_enabled(acs_flags, PCI_ACS_RR | PCI_ACS_CR); #else return -ENODEV; #endif @@ -4741,7 +4734,7 @@ static bool pci_quirk_cavium_acs_match(struct pci_dev *dev) } } -static int pci_quirk_cavium_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags) { if (!pci_quirk_cavium_acs_match(dev)) return -ENOTTY; @@ -4754,17 +4747,19 @@ static int pci_quirk_cavium_acs(struct pci_dev *dev, u32 acs_flags) * hardware implements and enables equivalent ACS functionality for * these flags. */ - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } -static int pci_quirk_xgene_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags) { /* * X-Gene Root Ports matching this quirk do not allow peer-to-peer * transactions with others, allowing masking out these bits as if they * were unimplemented in the ACS capability. */ - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } /* @@ -4772,7 +4767,7 @@ static int pci_quirk_xgene_acs(struct pci_dev *dev, u32 acs_flags) * But the implementation could block peer-to-peer transactions between them * and provide ACS-like functionality. */ -static int pci_quirk_zhaoxin_pcie_ports_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_zhaoxin_pcie_ports_acs(struct pci_dev *dev, u16 acs_flags) { if (!pci_is_pcie(dev) || ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && @@ -4787,7 +4782,8 @@ static int pci_quirk_zhaoxin_pcie_ports_acs(struct pci_dev *dev, u32 acs_flags) case 0x0710 ... 0x071e: case 0x0721: case 0x0723 ... 0x0752: - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } return false; @@ -4842,13 +4838,14 @@ static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev) return false; } -static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags) { if (!pci_quirk_intel_pch_acs_match(dev)) return -ENOTTY; if (dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK) - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); return pci_acs_ctrl_enabled(acs_flags, 0); } @@ -4863,9 +4860,10 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u32 acs_flags) * Port to pass traffic to another Root Port. All PCIe transactions are * terminated inside the Root Port. */ -static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) { - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } /* @@ -4874,12 +4872,13 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u32 acs_flags) * and validate bus numbers in requests, but does not provide an ACS * capability. */ -static int pci_quirk_nxp_rp_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_nxp_rp_acs(struct pci_dev *dev, u16 acs_flags) { - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } -static int pci_quirk_al_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_al_acs(struct pci_dev *dev, u16 acs_flags) { if (pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) return -ENOTTY; @@ -4892,7 +4891,9 @@ static int pci_quirk_al_acs(struct pci_dev *dev, u32 acs_flags) * * Additionally, the root ports cannot send traffic to each other. */ - return pci_acs_ctrl_isolated(acs_flags); + acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); + + return acs_flags ? 0 : 1; } /* @@ -4957,7 +4958,7 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) #define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4) -static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags) { int pos; u32 cap, ctrl; @@ -4978,15 +4979,8 @@ static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u32 acs_flags) return pci_acs_ctrl_enabled(acs_flags, ctrl); } -static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags) { - /* - * The function cannot get P2P MMIO from the other functions in the MFD - * either even if the other functions do not have ACS or ACS quirks. - */ - if (acs_flags & PCI_ACS_QUIRK_ACS_ISOLATED) - return 1; - /* * SV, TB, and UF are not relevant to multifunction endpoints. * @@ -5001,7 +4995,7 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u32 acs_flags) PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT); } -static int pci_quirk_rciep_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_rciep_acs(struct pci_dev *dev, u16 acs_flags) { /* * Intel RCiEP's are required to allow p2p only on translated @@ -5011,10 +5005,11 @@ static int pci_quirk_rciep_acs(struct pci_dev *dev, u32 acs_flags) if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END) return -ENOTTY; - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } -static int pci_quirk_brcm_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags) { /* * iProc PAXB Root Ports don't advertise an ACS capability, but @@ -5022,7 +5017,8 @@ static int pci_quirk_brcm_acs(struct pci_dev *dev, u32 acs_flags) * Allow each Root Port to be in a separate IOMMU group by masking * SV/RR/CR/UF bits. */ - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } /* @@ -5034,14 +5030,15 @@ static int pci_quirk_brcm_acs(struct pci_dev *dev, u32 acs_flags) * RP1000/RP2000 10G NICs(sp). * FF5xxx 40G/25G/10G NICs(aml). */ -static int pci_quirk_wangxun_nic_acs(struct pci_dev *dev, u32 acs_flags) +static int pci_quirk_wangxun_nic_acs(struct pci_dev *dev, u16 acs_flags) { switch (dev->device) { case 0x0100 ... 0x010F: /* EM */ case 0x1001: case 0x2001: /* SP */ case 0x5010: case 0x5025: case 0x5040: /* AML */ case 0x5110: case 0x5125: case 0x5140: /* AML */ - return pci_acs_ctrl_isolated(acs_flags); + return pci_acs_ctrl_enabled(acs_flags, + PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); } return false; @@ -5050,7 +5047,7 @@ static int pci_quirk_wangxun_nic_acs(struct pci_dev *dev, u32 acs_flags) static const struct pci_dev_acs_enabled { u16 vendor; u16 device; - int (*acs_enabled)(struct pci_dev *dev, u32 acs_flags); + int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags); } pci_dev_acs_enabled[] = { { PCI_VENDOR_ID_ATI, 0x4385, pci_quirk_amd_sb_acs }, { PCI_VENDOR_ID_ATI, 0x439c, pci_quirk_amd_sb_acs }, @@ -5203,7 +5200,18 @@ static const struct pci_dev_acs_enabled { { 0 } }; -static int pci_dev_call_acs_enabled(struct pci_dev *dev, u32 acs_flags) +/* + * pci_dev_specific_acs_enabled - check whether device provides ACS controls + * @dev: PCI device + * @acs_flags: Bitmask of desired ACS controls + * + * Returns: + * -ENOTTY: No quirk applies to this device; we can't tell whether the + * device provides the desired controls + * 0: Device does not provide all the desired controls + * >0: Device provides all the controls in @acs_flags + */ +int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) { const struct pci_dev_acs_enabled *i; int ret; @@ -5228,42 +5236,6 @@ static int pci_dev_call_acs_enabled(struct pci_dev *dev, u32 acs_flags) return -ENOTTY; } -/* - * pci_dev_specific_acs_enabled - check whether device provides ACS controls - * @dev: PCI device - * @acs_flags: Bitmask of desired ACS controls - * - * Returns: - * -ENOTTY: No quirk applies to this device; we can't tell whether the - * device provides the desired controls - * 0: Device does not provide all the desired controls - * >0: Device provides all the controls in @acs_flags - */ -int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) -{ - return pci_dev_call_acs_enabled(dev, acs_flags); -} - -/* - * pci_dev_specific_mfd_isolated- check whether a MFD function is isolated - * @dev: PCI device - * - * pci_dev_specific_acs_enabled() emulates the ACS flags using a quirk however - * historically Linux has not quirked every function in a MFD. - * pci_dev_specific_mfd_isolated() overrides the other function MFD checks and - * can consider a single function fully isolated from all other functions both - * for egress and ingress directions. - * - * Returns: - * false: No override, use normal PCI defined mechanisms - * true: Function is isolated from P2P to other functions in the device - */ -bool pci_dev_specific_mfd_isolated(struct pci_dev *dev) -{ - return pci_dev_call_acs_enabled(dev, PCI_ACS_QUIRK_ACS_ISOLATED | - PCI_ACS_ISOLATED) > 0; -} - /* Config space offset of Root Complex Base Address register */ #define INTEL_LPC_RCBA_REG 0xf0 /* 31:14 RCBA address */ diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 7425680fe92d6..53840634fbfc2 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -113,210 +113,6 @@ int pci_for_each_dma_alias(struct pci_dev *pdev, return ret; } -static enum pci_bus_isolation pcie_switch_isolated(struct pci_bus *bus) -{ - struct pci_dev *pdev; - - /* - * Within a PCIe switch we have an interior bus that has the Upstream - * port as the bridge and a set of Downstream port bridging to the - * egress ports. - * - * Each DSP has an ACS setting which controls where its traffic is - * permitted to go. Any DSP with a permissive ACS setting can send - * traffic flowing upstream back downstream through another DSP. - * - * Thus any non-permissive DSP spoils the whole bus. - * PCI_ACS_UNCLAIMED_RR is not required since rejecting requests with - * error is still isolation. - */ - guard(rwsem_read)(&pci_bus_sem); - list_for_each_entry(pdev, &bus->devices, bus_list) { - /* Don't understand what this is, be conservative */ - if (!pci_is_pcie(pdev) || - pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM || - pdev->dma_alias_mask) - return PCIE_NON_ISOLATED; - - if (!pci_acs_enabled(pdev, PCI_ACS_ISOLATED | - PCI_ACS_DSP_MT_RR | - PCI_ACS_USP_MT_RR)) { - /* The USP is isolated from the DSP */ - if (!pci_acs_enabled(pdev, PCI_ACS_USP_MT_RR)) - return PCIE_NON_ISOLATED; - return PCIE_SWITCH_DSP_NON_ISOLATED; - } - } - return PCIE_ISOLATED; -} - -static bool pci_has_mmio(struct pci_dev *pdev) -{ - unsigned int i; - - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *res = pci_resource_n(pdev, i); - - if (resource_size(res) && resource_type(res) == IORESOURCE_MEM) - return true; - } - return false; -} - -/** - * pci_bus_isolated - Determine how isolated connected devices are - * @bus: The bus to check - * - * Isolation is the ability of devices to talk to each other. Full isolation - * means that a device can only communicate with the IOMMU and can not do peer - * to peer within the fabric. - * - * We consider isolation on a bus by bus basis. If the bus will permit a - * transaction originated downstream to complete on anything other than the - * IOMMU then the bus is not isolated. - * - * Non-isolation includes all the downstream devices on this bus, and it may - * include the upstream bridge or port that is creating this bus. - * - * The various cases are returned in an enum. - * - * Broadly speaking this function evaluates the ACS settings in a PCI switch to - * determine if a PCI switch is configured to have full isolation. - * - * Old PCI/PCI-X busses cannot have isolation due to their physical properties, - * but they do have some aliasing properties that effect group creation. - * - * pci_bus_isolated() does not consider loopback internal to devices, like - * multi-function devices performing a self-loopback. The caller must check - * this separately. It does not considering alasing within the bus. - * - * It does not currently support the ACS P2P Egress Control Vector, Linux does - * not yet have any way to enable this feature. EC will create subsets of the - * bus that are isolated from other subsets. - */ -enum pci_bus_isolation pci_bus_isolated(struct pci_bus *bus) -{ - struct pci_dev *bridge = bus->self; - int type; - - /* - * This bus was created by pci_register_host_bridge(). The spec provides - * no way to tell what kind of bus this is, for PCIe we expect this to - * be internal to the root complex and not covered by any spec behavior. - * Linux has historically been optimistic about this bus and treated it - * as isolating. Given that the behavior of the root complex and the ACS - * behavior of RCiEP's is explicitly not specified we hope that the - * implementation is directing everything that reaches the root bus to - * the IOMMU. - */ - if (pci_is_root_bus(bus)) - return PCIE_ISOLATED; - - /* - * bus->self is only NULL for SRIOV VFs, it represents a "virtual" bus - * within Linux to hold any bus numbers consumed by VF RIDs. Caller must - * use pci_physfn() to get the bus for calling this function. - */ - if (WARN_ON(!bridge)) - return PCI_BRIDGE_NON_ISOLATED; - - /* - * The bridge is not a PCIe bridge therefore this bus is PCI/PCI-X. - * - * PCI does not have anything like ACS. Any down stream device can bus - * master an address that any other downstream device can claim. No - * isolation is possible. - */ - if (!pci_is_pcie(bridge)) { - if (bridge->dev_flags & PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS) - type = PCI_EXP_TYPE_PCI_BRIDGE; - else - return PCI_BRIDGE_NON_ISOLATED; - } else { - type = pci_pcie_type(bridge); - } - - switch (type) { - /* - * Since PCIe links are point to point root and downstream ports are - * isolated if their own MMIO cannot be reached. The root port - * uses DSP_MT_RR for its own MMIO. - */ - case PCI_EXP_TYPE_ROOT_PORT: - case PCI_EXP_TYPE_DOWNSTREAM: - if (!pci_acs_enabled(bridge, - PCI_ACS_ISOLATED | PCI_ACS_DSP_MT_RR)) - return PCIE_NON_ISOLATED; - return PCIE_ISOLATED; - - /* - * bus is the interior bus of a PCI-E switch where ACS rules apply. - */ - case PCI_EXP_TYPE_UPSTREAM: - return pcie_switch_isolated(bus); - - /* - * PCIe to PCI/PCI-X - this bus is PCI. - */ - case PCI_EXP_TYPE_PCI_BRIDGE: - /* - * A PCIe express bridge will use the subordinate bus number - * with a 0 devfn as the RID in some cases. This causes all - * subordinate devfns to alias with 0, which is the same - * grouping as PCI_BUS_NON_ISOLATED. The RID of the bridge - * itself is only used by the bridge. - * - * However, if the bridge has MMIO then we will assume the MMIO - * is not isolated due to no ACS controls on this bridge type. - */ - if (pci_has_mmio(bridge)) - return PCI_BRIDGE_NON_ISOLATED; - return PCI_BUS_NON_ISOLATED; - - /* - * PCI/PCI-X to PCIe - this bus is PCIe. We already know there must be a - * PCI bus upstream of this bus, so just return non-isolated. If - * upstream is PCI-X the PCIe RID should be preserved, but for PCI the - * RID will be lost. - */ - case PCI_EXP_TYPE_PCIE_BRIDGE: - return PCI_BRIDGE_NON_ISOLATED; - - default: - return PCI_BRIDGE_NON_ISOLATED; - } -} - -/* - * pci_mfd_isolated- check whether a MFD function is isolated - * @dev: PCI device - * - * True if the dev function on a MFD should be considered isolated from all - * other functions in the MFD. This is used to override ACS checks that might - * otherwise indicate the MFD function participates in an internal loopback. - * - * Returns: - * false: No override, use normal PCI defined mechanisms - * true: Function is isolated from P2P to other functions in the device - */ -bool pci_mfd_isolated(struct pci_dev *dev) -{ - /* - * For some reason AMD likes to put "dummy functions" in their PCI - * hierarchy as part of a multi function device. These are notable - * because they can't do anything. No BARs and no downstream bus. Since - * they cannot accept P2P or initiate any MMIO we consider them to be - * isolated from the rest of MFD. Since they often accompany a real PCI - * bridge with downstream devices it is important that the MFD be - * considered isolated. Annoyingly there is no ACS capability reported - * so we assume that a host bridge in a MFD with no MMIO has the special - * property of never accepting or initiating P2P operations. - */ - if (dev->class >> 8 == PCI_CLASS_BRIDGE_HOST && !pci_has_mmio(dev)) - return true; - return pci_dev_specific_mfd_isolated(dev); -} - static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) { struct pci_bus *child; @@ -625,93 +421,3 @@ int pci_dev_present(const struct pci_device_id *ids) return 0; } EXPORT_SYMBOL(pci_dev_present); - -/** - * pci_reachable_set - Generate a bitmap of devices within a reachability set - * @start: First device in the set - * @devfns: The set of devices on the bus - * @reachable: Callback to tell if two devices can reach each other - * - * Compute a bitmap where every set bit is a device on the bus that is reachable - * from the start device, including the start device. Reachability between two - * devices is determined by a callback function. - * - * This is a non-recursive implementation that invokes the callback once per - * pair. The callback must be commutative: - * reachable(a, b) == reachable(b, a) - * reachable() can form a cyclic graph: - * reachable(a,b) == reachable(b,c) == reachable(c,a) == true - * - * Since this function is limited to a single bus the largest set can be 256 - * devices large. - */ -void pci_reachable_set(struct pci_dev *start, struct pci_reachable_set *devfns, - bool (*reachable)(struct pci_dev *deva, - struct pci_dev *devb)) -{ - struct pci_reachable_set todo_devfns = {}; - struct pci_reachable_set next_devfns = {}; - struct pci_bus *bus = start->bus; - bool again; - - /* Assume devfn of all PCI devices is bounded by MAX_NR_DEVFNS */ - static_assert(sizeof(next_devfns.devfns) * BITS_PER_BYTE >= - MAX_NR_DEVFNS); - - memset(devfns, 0, sizeof(devfns->devfns)); - __set_bit(start->devfn, devfns->devfns); - __set_bit(start->devfn, next_devfns.devfns); - - down_read(&pci_bus_sem); - while (true) { - unsigned int devfna; - unsigned int i; - - /* - * For each device that hasn't been checked compare every - * device on the bus against it. - */ - again = false; - for_each_set_bit(devfna, next_devfns.devfns, MAX_NR_DEVFNS) { - struct pci_dev *deva = NULL; - struct pci_dev *devb; - - list_for_each_entry(devb, &bus->devices, bus_list) { - if (devb->devfn == devfna) - deva = devb; - - if (test_bit(devb->devfn, devfns->devfns)) - continue; - - if (!deva) { - deva = devb; - list_for_each_entry_continue( - deva, &bus->devices, bus_list) - if (deva->devfn == devfna) - break; - } - - if (!reachable(deva, devb)) - continue; - - __set_bit(devb->devfn, todo_devfns.devfns); - again = true; - } - } - - if (!again) - break; - - /* - * Every new bit adds a new deva to check, reloop the whole - * thing. Expect this to be rare. - */ - for (i = 0; i != ARRAY_SIZE(devfns->devfns); i++) { - devfns->devfns[i] |= todo_devfns.devfns[i]; - next_devfns.devfns[i] = todo_devfns.devfns[i]; - todo_devfns.devfns[i] = 0; - } - } - up_read(&pci_bus_sem); -} -EXPORT_SYMBOL_GPL(pci_reachable_set); diff --git a/include/linux/pci.h b/include/linux/pci.h index 60e862dbb6bde..4b30e824eaf76 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -834,36 +834,6 @@ struct pci_dynids { struct list_head list; /* For IDs added at runtime */ }; -struct pci_reachable_set { - DECLARE_BITMAP(devfns, 256); -}; - -enum pci_bus_isolation { - /* - * The bus is off a root port and the root port has isolated ACS flags - * or the bus is part of a PCIe switch and the switch has isolated ACS - * flags. - */ - PCIE_ISOLATED, - /* - * The switch's DSP's are not isolated from each other but are isolated - * from the USP. - */ - PCIE_SWITCH_DSP_NON_ISOLATED, - /* The above and the USP's MMIO is not isolated. */ - PCIE_NON_ISOLATED, - /* - * A PCI/PCI-X bus, no isolation. This is like - * PCIE_SWITCH_DSP_NON_ISOLATED in that the upstream bridge is isolated - * from the bus. The bus itself may also have a shared alias of devfn=0. - */ - PCI_BUS_NON_ISOLATED, - /* - * The above and the bridge's MMIO is not isolated and the bridge's RID - * may be an alias. - */ - PCI_BRIDGE_NON_ISOLATED, -}; /* * PCI Error Recovery System (PCI-ERS). If a PCI device driver provides @@ -1255,12 +1225,6 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from); struct pci_dev *pci_get_base_class(unsigned int class, struct pci_dev *from); -void pci_reachable_set(struct pci_dev *start, struct pci_reachable_set *devfns, - bool (*reachable)(struct pci_dev *deva, - struct pci_dev *devb)); -enum pci_bus_isolation pci_bus_isolated(struct pci_bus *bus); -bool pci_mfd_isolated(struct pci_dev *dev); - int pci_dev_present(const struct pci_device_id *ids); int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, @@ -2025,26 +1989,12 @@ static inline struct pci_dev *pci_get_base_class(unsigned int class, struct pci_dev *from) { return NULL; } -static inline void -pci_reachable_set(struct pci_dev *start, struct pci_reachable_set *devfns, - bool (*reachable)(struct pci_dev *deva, struct pci_dev *devb)) -{ } - -static inline enum pci_bus_isolation pci_bus_isolated(struct pci_bus *bus) -{ return PCIE_NON_ISOLATED; } - -static inline bool pci_mfd_isolated(struct pci_dev *dev) -{ return false; } - static inline int pci_dev_present(const struct pci_device_id *ids) { return 0; } #define no_pci_devices() (1) #define pci_dev_put(dev) do { } while (0) -static inline struct pci_dev *pci_real_dma_dev(struct pci_dev *dev) -{ return dev; } - static inline void pci_set_master(struct pci_dev *dev) { } static inline void pci_clear_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 58626694dac63..3445c4970e4d8 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -1000,28 +1000,10 @@ #define PCI_ACS_UF 0x0010 /* Upstream Forwarding */ #define PCI_ACS_EC 0x0020 /* P2P Egress Control */ #define PCI_ACS_DT 0x0040 /* Direct Translated P2P */ -#define PCI_ACS_ENHANCED 0x0080 /* IORB, DSP_MT_xx, USP_MT_XX. Capability only */ -#define PCI_ACS_EGRESS_CTL_SZ GENMASK(15, 8) /* Egress Control Vector Size */ #define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */ #define PCI_ACS_CTRL 0x06 /* ACS Control Register */ -#define PCI_ACS_IORB 0x0080 /* I/O Request Blocking */ -#define PCI_ACS_DSP_MT_RB 0x0100 /* DSP Memory Target Access Control Request Blocking */ -#define PCI_ACS_DSP_MT_RR 0x0200 /* DSP Memory Target Access Control Request Redirect */ -#define PCI_ACS_USP_MT_RB 0x0400 /* USP Memory Target Access Control Request Blocking */ -#define PCI_ACS_USP_MT_RR 0x0800 /* USP Memory Target Access Control Request Redirect */ -#define PCI_ACS_UNCLAIMED_RR 0x1000 /* Unclaimed Request Redirect Control */ #define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */ -/* - * To consider a PCI device isolated, we require ACS to support Source - * Validation, Request Redirection, Completer Redirection, and Upstream - * Forwarding. This effectively means that devices cannot spoof their - * requester ID, requests and completions cannot be redirected, and all - * transactions are forwarded upstream, even as it passes through a - * bridge where the target device is downstream. - */ -#define PCI_ACS_ISOLATED (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) - /* SATA capability */ #define PCI_SATA_REGS 4 /* SATA REGs specifier */ #define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */