Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Dan Williams and committed by
Bjorn Helgaas
b37b6095 bcce8c74

+17 -23
+17 -23
drivers/pci/controller/vmd.c
··· 565 565 vmd->dev->resource[VMD_MEMBAR2].child = NULL; 566 566 } 567 567 568 - /* 569 - * VMD domains start at 0x10000 to not clash with ACPI _SEG domains. 570 - * Per ACPI r6.0, sec 6.5.6, _SEG returns an integer, of which the lower 571 - * 16 bits are the PCI Segment Group (domain) number. Other bits are 572 - * currently reserved. 573 - */ 574 - static int vmd_find_free_domain(void) 575 - { 576 - int domain = 0xffff; 577 - struct pci_bus *bus = NULL; 578 - 579 - while ((bus = pci_find_next_bus(bus)) != NULL) 580 - domain = max_t(int, domain, pci_domain_nr(bus)); 581 - return domain + 1; 582 - } 583 - 584 568 static int vmd_get_phys_offsets(struct vmd_dev *vmd, bool native_hint, 585 569 resource_size_t *offset1, 586 570 resource_size_t *offset2) ··· 849 865 .parent = res, 850 866 }; 851 867 852 - sd->vmd_dev = vmd->dev; 853 - sd->domain = vmd_find_free_domain(); 854 - if (sd->domain < 0) 855 - return sd->domain; 856 - 857 - sd->node = pcibus_to_node(vmd->dev->bus); 858 - 859 868 /* 860 869 * Currently MSI remapping must be enabled in guest passthrough mode 861 870 * due to some missing interrupt remapping plumbing. This is probably ··· 874 897 pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]); 875 898 pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]); 876 899 900 + sd->vmd_dev = vmd->dev; 901 + 902 + /* 903 + * Emulated domains start at 0x10000 to not clash with ACPI _SEG 904 + * domains. Per ACPI r6.0, sec 6.5.6, _SEG returns an integer, of 905 + * which the lower 16 bits are the PCI Segment Group (domain) number. 906 + * Other bits are currently reserved. 907 + */ 908 + sd->domain = pci_bus_find_emul_domain_nr(0, 0x10000, INT_MAX); 909 + if (sd->domain < 0) 910 + return sd->domain; 911 + 912 + sd->node = pcibus_to_node(vmd->dev->bus); 913 + 877 914 vmd->bus = pci_create_root_bus(&vmd->dev->dev, vmd->busn_start, 878 915 &vmd_ops, sd, &resources); 879 916 if (!vmd->bus) { 917 + pci_bus_release_emul_domain_nr(sd->domain); 880 918 pci_free_resource_list(&resources); 881 919 vmd_remove_irq_domain(vmd); 882 920 return -ENODEV; ··· 984 992 return -ENOMEM; 985 993 986 994 vmd->dev = dev; 995 + vmd->sysdata.domain = PCI_DOMAIN_NR_NOT_SET; 987 996 vmd->instance = ida_alloc(&vmd_instance_ida, GFP_KERNEL); 988 997 if (vmd->instance < 0) 989 998 return vmd->instance; ··· 1050 1057 vmd_detach_resources(vmd); 1051 1058 vmd_remove_irq_domain(vmd); 1052 1059 ida_free(&vmd_instance_ida, vmd->instance); 1060 + pci_bus_release_emul_domain_nr(vmd->sysdata.domain); 1053 1061 } 1054 1062 1055 1063 static void vmd_shutdown(struct pci_dev *dev)