]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/pci/probe.c
Merge tag 'ovl-fixes-5.14-rc6-v2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-jammy-kernel.git] / drivers / pci / probe.c
index 72fccb86330f767e5a42912da5b4a00d8ef7db99..79177ac37880fb14a61617c77a7ad8245d8c32ec 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/hypervisor.h>
 #include <linux/irqdomain.h>
 #include <linux/pm_runtime.h>
-#include <linux/list_sort.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -875,31 +874,14 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
        dev_set_msi_domain(&bus->dev, d);
 }
 
-static int res_cmp(void *priv, const struct list_head *a,
-                  const struct list_head *b)
-{
-       struct resource_entry *entry1, *entry2;
-
-       entry1 = container_of(a, struct resource_entry, node);
-       entry2 = container_of(b, struct resource_entry, node);
-
-       if (entry1->res->flags != entry2->res->flags)
-               return entry1->res->flags > entry2->res->flags;
-
-       if (entry1->offset != entry2->offset)
-               return entry1->offset > entry2->offset;
-
-       return entry1->res->start > entry2->res->start;
-}
-
 static int pci_register_host_bridge(struct pci_host_bridge *bridge)
 {
        struct device *parent = bridge->dev.parent;
-       struct resource_entry *window, *next, *n;
+       struct resource_entry *window, *n;
        struct pci_bus *bus, *b;
-       resource_size_t offset, next_offset;
+       resource_size_t offset;
        LIST_HEAD(resources);
-       struct resource *res, *next_res;
+       struct resource *res;
        char addr[64], *fmt;
        const char *name;
        int err;
@@ -943,7 +925,8 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
        device_enable_async_suspend(bus->bridge);
        pci_set_bus_of_node(bus);
        pci_set_bus_msi_domain(bus);
-       if (bridge->msi_domain && !dev_get_msi_domain(&bus->dev))
+       if (bridge->msi_domain && !dev_get_msi_domain(&bus->dev) &&
+           !pci_host_of_has_msi_map(parent))
                bus->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
 
        if (!parent)
@@ -978,35 +961,11 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
        if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE)
                dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n");
 
-       /* Sort and coalesce contiguous windows */
-       list_sort(NULL, &resources, res_cmp);
-       resource_list_for_each_entry_safe(window, n, &resources) {
-               if (list_is_last(&window->node, &resources))
-                       break;
-
-               next = list_next_entry(window, node);
-               offset = window->offset;
-               res = window->res;
-               next_offset = next->offset;
-               next_res = next->res;
-
-               if (res->flags != next_res->flags || offset != next_offset)
-                       continue;
-
-               if (res->end + 1 == next_res->start) {
-                       next_res->start = res->start;
-                       res->flags = res->start = res->end = 0;
-               }
-       }
-
        /* Add initial resources to the bus */
        resource_list_for_each_entry_safe(window, n, &resources) {
+               list_move_tail(&window->node, &bridge->windows);
                offset = window->offset;
                res = window->res;
-               if (!res->end)
-                       continue;
-
-               list_move_tail(&window->node, &bridge->windows);
 
                if (res->flags & IORESOURCE_BUS)
                        pci_bus_insert_busn_res(bus, bus->number, res->end);
@@ -1617,6 +1576,26 @@ static void set_pcie_untrusted(struct pci_dev *dev)
                dev->untrusted = true;
 }
 
+static void pci_set_removable(struct pci_dev *dev)
+{
+       struct pci_dev *parent = pci_upstream_bridge(dev);
+
+       /*
+        * We (only) consider everything downstream from an external_facing
+        * device to be removable by the user. We're mainly concerned with
+        * consumer platforms with user accessible thunderbolt ports that are
+        * vulnerable to DMA attacks, and we expect those ports to be marked by
+        * the firmware as external_facing. Devices in traditional hotplug
+        * slots can technically be removed, but the expectation is that unless
+        * the port is marked with external_facing, such devices are less
+        * accessible to user / may not be removed by end user, and thus not
+        * exposed as "removable" to userspace.
+        */
+       if (parent &&
+           (parent->external_facing || dev_is_removable(&parent->dev)))
+               dev_set_removable(&dev->dev, DEVICE_REMOVABLE);
+}
+
 /**
  * pci_ext_cfg_is_aliased - Is ext config space just an alias of std config?
  * @dev: PCI device
@@ -1864,6 +1843,8 @@ int pci_setup_device(struct pci_dev *dev)
        /* Early fixups, before probing the BARs */
        pci_fixup_device(pci_fixup_early, dev);
 
+       pci_set_removable(dev);
+
        pci_info(dev, "[%04x:%04x] type %02x class %#08x\n",
                 dev->vendor, dev->device, dev->hdr_type, dev->class);