Skip to content

Commit e0910b3

Browse files
committed
Merge branch 'pci/enumeration'
- Enable host bridge emulation for PCI_DOMAINS_GENERIC platforms (Dan Williams) - Switch vmd from custom domain number allocator to the common allocator (Dan Williams) * pci/enumeration: PCI: vmd: Switch to pci_bus_find_emul_domain_nr() PCI: Enable host bridge emulation for PCI_DOMAINS_GENERIC platforms
2 parents 3a86608 + b37b609 commit e0910b3

5 files changed

Lines changed: 63 additions & 78 deletions

File tree

drivers/pci/controller/pci-hyperv.c

Lines changed: 9 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3696,48 +3696,6 @@ static int hv_send_resources_released(struct hv_device *hdev)
36963696
return 0;
36973697
}
36983698

3699-
#define HVPCI_DOM_MAP_SIZE (64 * 1024)
3700-
static DECLARE_BITMAP(hvpci_dom_map, HVPCI_DOM_MAP_SIZE);
3701-
3702-
/*
3703-
* PCI domain number 0 is used by emulated devices on Gen1 VMs, so define 0
3704-
* as invalid for passthrough PCI devices of this driver.
3705-
*/
3706-
#define HVPCI_DOM_INVALID 0
3707-
3708-
/**
3709-
* hv_get_dom_num() - Get a valid PCI domain number
3710-
* Check if the PCI domain number is in use, and return another number if
3711-
* it is in use.
3712-
*
3713-
* @dom: Requested domain number
3714-
*
3715-
* return: domain number on success, HVPCI_DOM_INVALID on failure
3716-
*/
3717-
static u16 hv_get_dom_num(u16 dom)
3718-
{
3719-
unsigned int i;
3720-
3721-
if (test_and_set_bit(dom, hvpci_dom_map) == 0)
3722-
return dom;
3723-
3724-
for_each_clear_bit(i, hvpci_dom_map, HVPCI_DOM_MAP_SIZE) {
3725-
if (test_and_set_bit(i, hvpci_dom_map) == 0)
3726-
return i;
3727-
}
3728-
3729-
return HVPCI_DOM_INVALID;
3730-
}
3731-
3732-
/**
3733-
* hv_put_dom_num() - Mark the PCI domain number as free
3734-
* @dom: Domain number to be freed
3735-
*/
3736-
static void hv_put_dom_num(u16 dom)
3737-
{
3738-
clear_bit(dom, hvpci_dom_map);
3739-
}
3740-
37413699
/**
37423700
* hv_pci_probe() - New VMBus channel probe, for a root PCI bus
37433701
* @hdev: VMBus's tracking struct for this root PCI bus
@@ -3750,9 +3708,9 @@ static int hv_pci_probe(struct hv_device *hdev,
37503708
{
37513709
struct pci_host_bridge *bridge;
37523710
struct hv_pcibus_device *hbus;
3753-
u16 dom_req, dom;
3711+
int ret, dom;
3712+
u16 dom_req;
37543713
char *name;
3755-
int ret;
37563714

37573715
bridge = devm_pci_alloc_host_bridge(&hdev->device, 0);
37583716
if (!bridge)
@@ -3779,11 +3737,14 @@ static int hv_pci_probe(struct hv_device *hdev,
37793737
* PCI bus (which is actually emulated by the hypervisor) is domain 0.
37803738
* (2) There will be no overlap between domains (after fixing possible
37813739
* collisions) in the same VM.
3740+
*
3741+
* Because Gen1 VMs use domain 0, don't allow picking domain 0 here,
3742+
* even if bytes 4 and 5 of the instance GUID are both zero. For wider
3743+
* userspace compatibility, limit the domain ID to a 16-bit value.
37823744
*/
37833745
dom_req = hdev->dev_instance.b[5] << 8 | hdev->dev_instance.b[4];
3784-
dom = hv_get_dom_num(dom_req);
3785-
3786-
if (dom == HVPCI_DOM_INVALID) {
3746+
dom = pci_bus_find_emul_domain_nr(dom_req, 1, U16_MAX);
3747+
if (dom < 0) {
37873748
dev_err(&hdev->device,
37883749
"Unable to use dom# 0x%x or other numbers", dom_req);
37893750
ret = -EINVAL;
@@ -3917,7 +3878,7 @@ static int hv_pci_probe(struct hv_device *hdev,
39173878
destroy_wq:
39183879
destroy_workqueue(hbus->wq);
39193880
free_dom:
3920-
hv_put_dom_num(hbus->bridge->domain_nr);
3881+
pci_bus_release_emul_domain_nr(hbus->bridge->domain_nr);
39213882
free_bus:
39223883
kfree(hbus);
39233884
return ret;
@@ -4042,8 +4003,6 @@ static void hv_pci_remove(struct hv_device *hdev)
40424003
irq_domain_remove(hbus->irq_domain);
40434004
irq_domain_free_fwnode(hbus->fwnode);
40444005

4045-
hv_put_dom_num(hbus->bridge->domain_nr);
4046-
40474006
kfree(hbus);
40484007
}
40494008

@@ -4217,9 +4176,6 @@ static int __init init_hv_pci_drv(void)
42174176
if (ret)
42184177
return ret;
42194178

4220-
/* Set the invalid domain number's bit, so it will not be used */
4221-
set_bit(HVPCI_DOM_INVALID, hvpci_dom_map);
4222-
42234179
/* Initialize PCI block r/w interface */
42244180
hvpci_block_ops.read_block = hv_read_config_block;
42254181
hvpci_block_ops.write_block = hv_write_config_block;

drivers/pci/controller/vmd.c

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -565,22 +565,6 @@ static void vmd_detach_resources(struct vmd_dev *vmd)
565565
vmd->dev->resource[VMD_MEMBAR2].child = NULL;
566566
}
567567

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-
584568
static int vmd_get_phys_offsets(struct vmd_dev *vmd, bool native_hint,
585569
resource_size_t *offset1,
586570
resource_size_t *offset2)
@@ -865,13 +849,6 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
865849
.parent = res,
866850
};
867851

868-
sd->vmd_dev = vmd->dev;
869-
sd->domain = vmd_find_free_domain();
870-
if (sd->domain < 0)
871-
return sd->domain;
872-
873-
sd->node = pcibus_to_node(vmd->dev->bus);
874-
875852
/*
876853
* Currently MSI remapping must be enabled in guest passthrough mode
877854
* 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)
897874
pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
898875
pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
899876

877+
sd->vmd_dev = vmd->dev;
878+
879+
/*
880+
* Emulated domains start at 0x10000 to not clash with ACPI _SEG
881+
* domains. Per ACPI r6.0, sec 6.5.6, _SEG returns an integer, of
882+
* which the lower 16 bits are the PCI Segment Group (domain) number.
883+
* Other bits are currently reserved.
884+
*/
885+
sd->domain = pci_bus_find_emul_domain_nr(0, 0x10000, INT_MAX);
886+
if (sd->domain < 0)
887+
return sd->domain;
888+
889+
sd->node = pcibus_to_node(vmd->dev->bus);
890+
900891
vmd->bus = pci_create_root_bus(&vmd->dev->dev, vmd->busn_start,
901892
&vmd_ops, sd, &resources);
902893
if (!vmd->bus) {
894+
pci_bus_release_emul_domain_nr(sd->domain);
903895
pci_free_resource_list(&resources);
904896
vmd_remove_irq_domain(vmd);
905897
return -ENODEV;
@@ -992,6 +984,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
992984
return -ENOMEM;
993985

994986
vmd->dev = dev;
987+
vmd->sysdata.domain = PCI_DOMAIN_NR_NOT_SET;
995988
vmd->instance = ida_alloc(&vmd_instance_ida, GFP_KERNEL);
996989
if (vmd->instance < 0)
997990
return vmd->instance;
@@ -1057,6 +1050,7 @@ static void vmd_remove(struct pci_dev *dev)
10571050
vmd_detach_resources(vmd);
10581051
vmd_remove_irq_domain(vmd);
10591052
ida_free(&vmd_instance_ida, vmd->instance);
1053+
pci_bus_release_emul_domain_nr(vmd->sysdata.domain);
10601054
}
10611055

10621056
static void vmd_shutdown(struct pci_dev *dev)

drivers/pci/pci.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6656,9 +6656,31 @@ static void pci_no_domains(void)
66566656
#endif
66576657
}
66586658

6659+
#ifdef CONFIG_PCI_DOMAINS
6660+
static DEFINE_IDA(pci_domain_nr_dynamic_ida);
6661+
6662+
/**
6663+
* pci_bus_find_emul_domain_nr() - allocate a PCI domain number per constraints
6664+
* @hint: desired domain, 0 if any ID in the range of @min to @max is acceptable
6665+
* @min: minimum allowable domain
6666+
* @max: maximum allowable domain, no IDs higher than INT_MAX will be returned
6667+
*/
6668+
int pci_bus_find_emul_domain_nr(u32 hint, u32 min, u32 max)
6669+
{
6670+
return ida_alloc_range(&pci_domain_nr_dynamic_ida, max(hint, min), max,
6671+
GFP_KERNEL);
6672+
}
6673+
EXPORT_SYMBOL_GPL(pci_bus_find_emul_domain_nr);
6674+
6675+
void pci_bus_release_emul_domain_nr(int domain_nr)
6676+
{
6677+
ida_free(&pci_domain_nr_dynamic_ida, domain_nr);
6678+
}
6679+
EXPORT_SYMBOL_GPL(pci_bus_release_emul_domain_nr);
6680+
#endif
6681+
66596682
#ifdef CONFIG_PCI_DOMAINS_GENERIC
66606683
static DEFINE_IDA(pci_domain_nr_static_ida);
6661-
static DEFINE_IDA(pci_domain_nr_dynamic_ida);
66626684

66636685
static void of_pci_reserve_static_domain_nr(void)
66646686
{

drivers/pci/probe.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,11 @@ static void pci_release_host_bridge_dev(struct device *dev)
657657

658658
pci_free_resource_list(&bridge->windows);
659659
pci_free_resource_list(&bridge->dma_ranges);
660+
661+
/* Host bridges only have domain_nr set in the emulation case */
662+
if (bridge->domain_nr != PCI_DOMAIN_NR_NOT_SET)
663+
pci_bus_release_emul_domain_nr(bridge->domain_nr);
664+
660665
kfree(bridge);
661666
}
662667

@@ -1137,7 +1142,8 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
11371142
device_del(&bridge->dev);
11381143
free:
11391144
#ifdef CONFIG_PCI_DOMAINS_GENERIC
1140-
pci_bus_release_domain_nr(parent, bus->domain_nr);
1145+
if (bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET)
1146+
pci_bus_release_domain_nr(parent, bus->domain_nr);
11411147
#endif
11421148
if (bus_registered)
11431149
put_device(&bus->dev);

include/linux/pci.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,10 +1956,17 @@ DEFINE_GUARD(pci_dev, struct pci_dev *, pci_dev_lock(_T), pci_dev_unlock(_T))
19561956
*/
19571957
#ifdef CONFIG_PCI_DOMAINS
19581958
extern int pci_domains_supported;
1959+
int pci_bus_find_emul_domain_nr(u32 hint, u32 min, u32 max);
1960+
void pci_bus_release_emul_domain_nr(int domain_nr);
19591961
#else
19601962
enum { pci_domains_supported = 0 };
19611963
static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
19621964
static inline int pci_proc_domain(struct pci_bus *bus) { return 0; }
1965+
static inline int pci_bus_find_emul_domain_nr(u32 hint, u32 min, u32 max)
1966+
{
1967+
return 0;
1968+
}
1969+
static inline void pci_bus_release_emul_domain_nr(int domain_nr) { }
19631970
#endif /* CONFIG_PCI_DOMAINS */
19641971

19651972
/*

0 commit comments

Comments
 (0)