Jan Beulich
2011-Oct-04 11:22 UTC
[Xen-devel] [PATCH] passthrough: update bus2bridge mapping as PCI devices get added/removed
This deals with two limitations at once: On device removal, the mapping did not get updated so far at all, and hotplugged devices as well as such not discoverable by Xen''s initial bus scan (including the case where a non-zero PCI segment wasn''t accessible during Xen boot, but became accessible after Dom0 validated access information against ACPI data) wouldn''t cause updates to the mapping either. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -129,11 +129,67 @@ static struct pci_dev *alloc_pdev(struct list_add(&pdev->alldevs_list, &pseg->alldevs_list); spin_lock_init(&pdev->msix_table_lock); + /* update bus2bridge */ + switch ( pdev_type(pseg->nr, bus, devfn) ) + { + u8 sec_bus, sub_bus; + + case DEV_TYPE_PCIe_BRIDGE: + break; + + case DEV_TYPE_PCIe2PCI_BRIDGE: + case DEV_TYPE_LEGACY_PCI_BRIDGE: + sec_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn), + PCI_FUNC(devfn), PCI_SECONDARY_BUS); + sub_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn), + PCI_FUNC(devfn), PCI_SUBORDINATE_BUS); + + spin_lock(&pseg->bus2bridge_lock); + for ( ; sec_bus <= sub_bus; sec_bus++ ) + { + pseg->bus2bridge[sec_bus].map = 1; + pseg->bus2bridge[sec_bus].bus = bus; + pseg->bus2bridge[sec_bus].devfn = devfn; + } + spin_unlock(&pseg->bus2bridge_lock); + break; + + case DEV_TYPE_PCIe_ENDPOINT: + case DEV_TYPE_PCI: + break; + + default: + printk(XENLOG_WARNING "%s: unknown type: %04x:%02x:%02x.%u\n", + __func__, pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + break; + } + return pdev; } -static void free_pdev(struct pci_dev *pdev) +static void free_pdev(struct pci_seg *pseg, struct pci_dev *pdev) { + /* update bus2bridge */ + switch ( pdev_type(pseg->nr, pdev->bus, pdev->devfn) ) + { + u8 dev, func, sec_bus, sub_bus; + + case DEV_TYPE_PCIe2PCI_BRIDGE: + case DEV_TYPE_LEGACY_PCI_BRIDGE: + dev = PCI_SLOT(pdev->devfn); + func = PCI_FUNC(pdev->devfn); + sec_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, + PCI_SECONDARY_BUS); + sub_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, + PCI_SUBORDINATE_BUS); + + spin_lock(&pseg->bus2bridge_lock); + for ( ; sec_bus <= sub_bus; sec_bus++ ) + pseg->bus2bridge[sec_bus] = pseg->bus2bridge[pdev->bus]; + spin_unlock(&pseg->bus2bridge_lock); + break; + } + list_del(&pdev->alldevs_list); xfree(pdev); } @@ -377,7 +433,7 @@ int pci_remove_device(u16 seg, u8 bus, u if ( pdev->domain ) list_del(&pdev->domain_list); pci_cleanup_msi(pdev); - free_pdev(pdev); + free_pdev(pseg, pdev); printk(XENLOG_DEBUG "PCI remove device %04x:%02x:%02x.%u\n", seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); break; @@ -545,8 +601,6 @@ static int __init _scan_pci_devices(stru { struct pci_dev *pdev; int bus, dev, func; - u8 sec_bus, sub_bus; - int type; for ( bus = 0; bus < 256; bus++ ) { @@ -564,41 +618,6 @@ static int __init _scan_pci_devices(stru return -ENOMEM; } - /* build bus2bridge */ - type = pdev_type(pseg->nr, bus, PCI_DEVFN(dev, func)); - switch ( type ) - { - case DEV_TYPE_PCIe_BRIDGE: - break; - - case DEV_TYPE_PCIe2PCI_BRIDGE: - case DEV_TYPE_LEGACY_PCI_BRIDGE: - sec_bus = pci_conf_read8(pseg->nr, bus, dev, func, - PCI_SECONDARY_BUS); - sub_bus = pci_conf_read8(pseg->nr, bus, dev, func, - PCI_SUBORDINATE_BUS); - - spin_lock(&pseg->bus2bridge_lock); - for ( sub_bus &= 0xff; sec_bus <= sub_bus; sec_bus++ ) - { - pseg->bus2bridge[sec_bus].map = 1; - pseg->bus2bridge[sec_bus].bus = bus; - pseg->bus2bridge[sec_bus].devfn - PCI_DEVFN(dev, func); - } - spin_unlock(&pseg->bus2bridge_lock); - break; - - case DEV_TYPE_PCIe_ENDPOINT: - case DEV_TYPE_PCI: - break; - - default: - printk("%s: unknown type: %04x:%02x:%02x.%u\n", - __func__, pseg->nr, bus, dev, func); - return -EINVAL; - } - if ( !func && !(pci_conf_read8(pseg->nr, bus, dev, func, PCI_HEADER_TYPE) & 0x80) ) break; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Kay, Allen M
2011-Oct-07 02:00 UTC
[Xen-devel] RE: [PATCH] passthrough: update bus2bridge mapping as PCI devices get added/removed
Hi Jan, I''m not able to spot the difference between this patch and the earlier one you had second thoughts about in attached email. Was there a change I missed? Allen -----Original Message----- From: Jan Beulich [mailto:JBeulich@suse.com] Sent: Tuesday, October 04, 2011 4:23 AM To: xen-devel@lists.xensource.com Cc: Kay, Allen M Subject: [PATCH] passthrough: update bus2bridge mapping as PCI devices get added/removed This deals with two limitations at once: On device removal, the mapping did not get updated so far at all, and hotplugged devices as well as such not discoverable by Xen''s initial bus scan (including the case where a non-zero PCI segment wasn''t accessible during Xen boot, but became accessible after Dom0 validated access information against ACPI data) wouldn''t cause updates to the mapping either. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -129,11 +129,67 @@ static struct pci_dev *alloc_pdev(struct list_add(&pdev->alldevs_list, &pseg->alldevs_list); spin_lock_init(&pdev->msix_table_lock); + /* update bus2bridge */ + switch ( pdev_type(pseg->nr, bus, devfn) ) + { + u8 sec_bus, sub_bus; + + case DEV_TYPE_PCIe_BRIDGE: + break; + + case DEV_TYPE_PCIe2PCI_BRIDGE: + case DEV_TYPE_LEGACY_PCI_BRIDGE: + sec_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn), + PCI_FUNC(devfn), PCI_SECONDARY_BUS); + sub_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn), + PCI_FUNC(devfn), PCI_SUBORDINATE_BUS); + + spin_lock(&pseg->bus2bridge_lock); + for ( ; sec_bus <= sub_bus; sec_bus++ ) + { + pseg->bus2bridge[sec_bus].map = 1; + pseg->bus2bridge[sec_bus].bus = bus; + pseg->bus2bridge[sec_bus].devfn = devfn; + } + spin_unlock(&pseg->bus2bridge_lock); + break; + + case DEV_TYPE_PCIe_ENDPOINT: + case DEV_TYPE_PCI: + break; + + default: + printk(XENLOG_WARNING "%s: unknown type: %04x:%02x:%02x.%u\n", + __func__, pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + break; + } + return pdev; } -static void free_pdev(struct pci_dev *pdev) +static void free_pdev(struct pci_seg *pseg, struct pci_dev *pdev) { + /* update bus2bridge */ + switch ( pdev_type(pseg->nr, pdev->bus, pdev->devfn) ) + { + u8 dev, func, sec_bus, sub_bus; + + case DEV_TYPE_PCIe2PCI_BRIDGE: + case DEV_TYPE_LEGACY_PCI_BRIDGE: + dev = PCI_SLOT(pdev->devfn); + func = PCI_FUNC(pdev->devfn); + sec_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, + PCI_SECONDARY_BUS); + sub_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, + PCI_SUBORDINATE_BUS); + + spin_lock(&pseg->bus2bridge_lock); + for ( ; sec_bus <= sub_bus; sec_bus++ ) + pseg->bus2bridge[sec_bus] = pseg->bus2bridge[pdev->bus]; + spin_unlock(&pseg->bus2bridge_lock); + break; + } + list_del(&pdev->alldevs_list); xfree(pdev); } @@ -377,7 +433,7 @@ int pci_remove_device(u16 seg, u8 bus, u if ( pdev->domain ) list_del(&pdev->domain_list); pci_cleanup_msi(pdev); - free_pdev(pdev); + free_pdev(pseg, pdev); printk(XENLOG_DEBUG "PCI remove device %04x:%02x:%02x.%u\n", seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); break; @@ -545,8 +601,6 @@ static int __init _scan_pci_devices(stru { struct pci_dev *pdev; int bus, dev, func; - u8 sec_bus, sub_bus; - int type; for ( bus = 0; bus < 256; bus++ ) { @@ -564,41 +618,6 @@ static int __init _scan_pci_devices(stru return -ENOMEM; } - /* build bus2bridge */ - type = pdev_type(pseg->nr, bus, PCI_DEVFN(dev, func)); - switch ( type ) - { - case DEV_TYPE_PCIe_BRIDGE: - break; - - case DEV_TYPE_PCIe2PCI_BRIDGE: - case DEV_TYPE_LEGACY_PCI_BRIDGE: - sec_bus = pci_conf_read8(pseg->nr, bus, dev, func, - PCI_SECONDARY_BUS); - sub_bus = pci_conf_read8(pseg->nr, bus, dev, func, - PCI_SUBORDINATE_BUS); - - spin_lock(&pseg->bus2bridge_lock); - for ( sub_bus &= 0xff; sec_bus <= sub_bus; sec_bus++ ) - { - pseg->bus2bridge[sec_bus].map = 1; - pseg->bus2bridge[sec_bus].bus = bus; - pseg->bus2bridge[sec_bus].devfn - PCI_DEVFN(dev, func); - } - spin_unlock(&pseg->bus2bridge_lock); - break; - - case DEV_TYPE_PCIe_ENDPOINT: - case DEV_TYPE_PCI: - break; - - default: - printk("%s: unknown type: %04x:%02x:%02x.%u\n", - __func__, pseg->nr, bus, dev, func); - return -EINVAL; - } - if ( !func && !(pci_conf_read8(pseg->nr, bus, dev, func, PCI_HEADER_TYPE) & 0x80) ) break; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Oct-07 07:08 UTC
[Xen-devel] RE: [PATCH] passthrough: update bus2bridge mapping as PCI devices get added/removed
>>> On 07.10.11 at 04:00, "Kay, Allen M" <allen.m.kay@intel.com> wrote: > Hi Jan, > > I''m not able to spot the difference between this patch and the earlier one > you had second thoughts about in attached email. Was there a change I > missed?It addresses the comment I made in the mail you had attached, i.e. ...> Allen > > -----Original Message----- >... > -static void free_pdev(struct pci_dev *pdev) > +static void free_pdev(struct pci_seg *pseg, struct pci_dev *pdev) > { > + /* update bus2bridge */ > + switch ( pdev_type(pseg->nr, pdev->bus, pdev->devfn) ) > + { > + u8 dev, func, sec_bus, sub_bus; > + > + case DEV_TYPE_PCIe2PCI_BRIDGE: > + case DEV_TYPE_LEGACY_PCI_BRIDGE: > + dev = PCI_SLOT(pdev->devfn); > + func = PCI_FUNC(pdev->devfn); > + sec_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, > + PCI_SECONDARY_BUS); > + sub_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, > + PCI_SUBORDINATE_BUS); > + > + spin_lock(&pseg->bus2bridge_lock); > + for ( ; sec_bus <= sub_bus; sec_bus++ ) > + pseg->bus2bridge[sec_bus] = pseg->bus2bridge[pdev->bus];... the right side of this was 0 on the first posting. Jan> + spin_unlock(&pseg->bus2bridge_lock); > + break; > + } > + > list_del(&pdev->alldevs_list); > xfree(pdev); > }_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Kay, Allen M
2011-Oct-08 01:39 UTC
[Xen-devel] RE: [PATCH] passthrough: update bus2bridge mapping as PCI devices get added/removed
> + for ( ; sec_bus <= sub_bus; sec_bus++ ) > + pseg->bus2bridge[sec_bus] = pseg->bus2bridge[pdev->bus];OK. You are collapsing the bridge of the subordinate buses to be the same upstream bridge of the pdev we are removing. Looks good. Ack! Allen -----Original Message----- From: Jan Beulich [mailto:JBeulich@suse.com] Sent: Friday, October 07, 2011 12:08 AM To: Kay, Allen M Cc: xen-devel@lists.xensource.com Subject: RE: [PATCH] passthrough: update bus2bridge mapping as PCI devices get added/removed>>> On 07.10.11 at 04:00, "Kay, Allen M" <allen.m.kay@intel.com> wrote: > Hi Jan, > > I''m not able to spot the difference between this patch and the earlier one > you had second thoughts about in attached email. Was there a change I > missed?It addresses the comment I made in the mail you had attached, i.e. ...> Allen > > -----Original Message----- >... > -static void free_pdev(struct pci_dev *pdev) > +static void free_pdev(struct pci_seg *pseg, struct pci_dev *pdev) > { > + /* update bus2bridge */ > + switch ( pdev_type(pseg->nr, pdev->bus, pdev->devfn) ) > + { > + u8 dev, func, sec_bus, sub_bus; > + > + case DEV_TYPE_PCIe2PCI_BRIDGE: > + case DEV_TYPE_LEGACY_PCI_BRIDGE: > + dev = PCI_SLOT(pdev->devfn); > + func = PCI_FUNC(pdev->devfn); > + sec_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, > + PCI_SECONDARY_BUS); > + sub_bus = pci_conf_read8(pseg->nr, pdev->bus, dev, func, > + PCI_SUBORDINATE_BUS); > + > + spin_lock(&pseg->bus2bridge_lock); > + for ( ; sec_bus <= sub_bus; sec_bus++ ) > + pseg->bus2bridge[sec_bus] = pseg->bus2bridge[pdev->bus];... the right side of this was 0 on the first posting. Jan> + spin_unlock(&pseg->bus2bridge_lock); > + break; > + } > + > list_del(&pdev->alldevs_list); > xfree(pdev); > }_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel