]> Gentwo Git Trees - linux/.git/commitdiff
PCI: vmd: Switch to pci_bus_find_emul_domain_nr()
authorDan Williams <dan.j.williams@intel.com>
Fri, 24 Oct 2025 22:46:22 +0000 (15:46 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 28 Oct 2025 17:38:06 +0000 (12:38 -0500)
The new common domain number allocator can replace the custom allocator
in VMD.

Beyond some code reuse benefits it does close a potential race whereby
vmd_find_free_domain() collides with new PCI buses coming online with a
conflicting domain number. Such a race has not been observed in practice,
hence not tagging this change as a fix.

As VMD uses pci_create_root_bus() rather than pci_alloc_host_bridge() +
pci_scan_root_bus_bridge() it has no chance to set ->domain_nr in the
bridge so needs to manage freeing the domain number on its own.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Szymon Durawa <szymon.durawa@linux.intel.com>
Cc: Nirmal Patel <nirmal.patel@linux.intel.com>
Link: https://patch.msgid.link/20251024224622.1470555-3-dan.j.williams@intel.com
drivers/pci/controller/vmd.c

index 1bd5bf4a609793176de4fef10f4d12b22b2f7dec..933ca67a671c8736c5d0ad9a176e641fdd72181e 100644 (file)
@@ -565,22 +565,6 @@ static void vmd_detach_resources(struct vmd_dev *vmd)
        vmd->dev->resource[VMD_MEMBAR2].child = NULL;
 }
 
-/*
- * VMD domains start at 0x10000 to not clash with ACPI _SEG domains.
- * Per ACPI r6.0, sec 6.5.6,  _SEG returns an integer, of which the lower
- * 16 bits are the PCI Segment Group (domain) number.  Other bits are
- * currently reserved.
- */
-static int vmd_find_free_domain(void)
-{
-       int domain = 0xffff;
-       struct pci_bus *bus = NULL;
-
-       while ((bus = pci_find_next_bus(bus)) != NULL)
-               domain = max_t(int, domain, pci_domain_nr(bus));
-       return domain + 1;
-}
-
 static int vmd_get_phys_offsets(struct vmd_dev *vmd, bool native_hint,
                                resource_size_t *offset1,
                                resource_size_t *offset2)
@@ -865,13 +849,6 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
                .parent = res,
        };
 
-       sd->vmd_dev = vmd->dev;
-       sd->domain = vmd_find_free_domain();
-       if (sd->domain < 0)
-               return sd->domain;
-
-       sd->node = pcibus_to_node(vmd->dev->bus);
-
        /*
         * Currently MSI remapping must be enabled in guest passthrough mode
         * due to some missing interrupt remapping plumbing. This is probably
@@ -897,9 +874,24 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
        pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
        pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
 
+       sd->vmd_dev = vmd->dev;
+
+       /*
+        * Emulated domains start at 0x10000 to not clash with ACPI _SEG
+        * domains.  Per ACPI r6.0, sec 6.5.6, _SEG returns an integer, of
+        * which the lower 16 bits are the PCI Segment Group (domain) number.
+        * Other bits are currently reserved.
+        */
+       sd->domain = pci_bus_find_emul_domain_nr(0, 0x10000, INT_MAX);
+       if (sd->domain < 0)
+               return sd->domain;
+
+       sd->node = pcibus_to_node(vmd->dev->bus);
+
        vmd->bus = pci_create_root_bus(&vmd->dev->dev, vmd->busn_start,
                                       &vmd_ops, sd, &resources);
        if (!vmd->bus) {
+               pci_bus_release_emul_domain_nr(sd->domain);
                pci_free_resource_list(&resources);
                vmd_remove_irq_domain(vmd);
                return -ENODEV;
@@ -992,6 +984,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENOMEM;
 
        vmd->dev = dev;
+       vmd->sysdata.domain = PCI_DOMAIN_NR_NOT_SET;
        vmd->instance = ida_alloc(&vmd_instance_ida, GFP_KERNEL);
        if (vmd->instance < 0)
                return vmd->instance;
@@ -1057,6 +1050,7 @@ static void vmd_remove(struct pci_dev *dev)
        vmd_detach_resources(vmd);
        vmd_remove_irq_domain(vmd);
        ida_free(&vmd_instance_ida, vmd->instance);
+       pci_bus_release_emul_domain_nr(vmd->sysdata.domain);
 }
 
 static void vmd_shutdown(struct pci_dev *dev)