@@ -321,9 +321,14 @@ void pci_bus_add_device(struct pci_dev *dev)
pci_bridge_d3_update(dev);
dev->match_driver = true;
- retval = device_attach(&dev->dev);
- if (retval < 0 && retval != -EPROBE_DEFER)
- pci_warn(dev, "device attach failed (%d)\n", retval);
+
+ if (pci_dont_attach_external_devs && dev_is_external(&dev->dev)) {
+ pci_info(dev, "not attaching external device\n");
+ } else {
+ retval = device_attach(&dev->dev);
+ if (retval < 0 && retval != -EPROBE_DEFER)
+ pci_warn(dev, "device attach failed (%d)\n", retval);
+ }
pci_dev_assign_added(dev, true);
}
@@ -128,6 +128,13 @@ static bool pcie_ats_disabled;
/* If set, the PCI config space of each device is printed during boot. */
bool pci_early_dump;
+/*
+ * If set, the devices behind external-facing bridges (as marked by firmware)
+ * shall not be attached automatically. Userspace will need to attach them
+ * manually: echo <pci device> > /sys/bus/pci/drivers/<driver>/bind
+ */
+bool pci_dont_attach_external_devs;
+
bool pci_ats_disabled(void)
{
return pcie_ats_disabled;
@@ -6539,6 +6546,8 @@ static int __init pci_setup(char *str)
pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
} else if (!strncmp(str, "disable_acs_redir=", 18)) {
disable_acs_redir_param = str + 18;
+ } else if (!strcmp(str, "dont_attach_external_devs")) {
+ pci_dont_attach_external_devs = true;
} else {
pr_err("PCI: Unknown option `%s'\n", str);
}
@@ -13,6 +13,7 @@
extern const unsigned char pcie_link_speed[];
extern bool pci_early_dump;
+extern bool pci_dont_attach_external_devs;
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
bool pcie_cap_has_rtctl(const struct pci_dev *dev);
Introduce a PCI parameter that disables the automatic attachment of external devices to their drivers. This is needed to allow an admin to control which drivers he wants to allow on external ports. For more context, see threads at: https://lore.kernel.org/linux-pci/20200609210400.GA1461839@bjorn-Precision-5520/ https://lore.kernel.org/linux-pci/CACK8Z6H-DZQYBMqtU5_H5TTwwn35Q7Yysm9a7Wj0twfQP8QBzA@mail.gmail.com/ drivers_autoprobe can only be disabled after userspace comes up. So any external devices that were plugged in before boot may still bind to drivers before userspace gets a chance to clear drivers_autoprobe. Another problem is that even with drivers_autoprobe=0, the hot-added PCI devices are bound to drivers because PCI explicitly calls device_attach() asking driver core to find and attach a driver. This patch helps with both of these problems. Signed-off-by: Rajat Jain <rajatja@google.com> --- v2: Use the newly introduced dev_is_external() from device core commit log elaborated drivers/pci/bus.c | 11 ++++++++--- drivers/pci/pci.c | 9 +++++++++ drivers/pci/pci.h | 1 + 3 files changed, 18 insertions(+), 3 deletions(-)