mirror of https://github.com/torvalds/linux.git
PCI: vmd: Switch to pci_bus_find_emul_domain_nr()
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
This commit is contained in:
parent
bcce8c74f1
commit
b37b6095a9
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue