[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Make PCI device release function generic
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1215608938 -3600 # Node ID c1577f094ae4a66922be3a3b6705a936557e8c80 # Parent 9afe01a0e160353be900e041207101ada4a2deee Make PCI device release function generic Release all pci devices before doing iommu domain teardown. Also moved pdev_flr() into generic pci code. Signed-off-by: Espen Skoglund <espen.skoglund@xxxxxxxxxxxxx> --- xen/arch/x86/domain.c | 2 xen/drivers/passthrough/amd/pci_amd_iommu.c | 22 ------ xen/drivers/passthrough/pci.c | 92 ++++++++++++++++++++++++++++ xen/drivers/passthrough/vtd/extern.h | 1 xen/drivers/passthrough/vtd/iommu.c | 25 ------- xen/drivers/passthrough/vtd/utils.c | 65 ------------------- xen/include/xen/pci.h | 2 7 files changed, 98 insertions(+), 111 deletions(-) diff -r 9afe01a0e160 -r c1577f094ae4 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/arch/x86/domain.c Wed Jul 09 14:08:58 2008 +0100 @@ -30,6 +30,7 @@ #include <xen/percpu.h> #include <xen/compat.h> #include <xen/acpi.h> +#include <xen/pci.h> #include <asm/regs.h> #include <asm/mc146818rtc.h> #include <asm/system.h> @@ -473,6 +474,7 @@ void arch_domain_destroy(struct domain * if ( is_hvm_domain(d) ) hvm_domain_destroy(d); + pci_release_devices(d); if ( !is_idle_domain(d) ) iommu_domain_destroy(d); diff -r 9afe01a0e160 -r c1577f094ae4 xen/drivers/passthrough/amd/pci_amd_iommu.c --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Wed Jul 09 14:08:58 2008 +0100 @@ -485,8 +485,6 @@ static void amd_iommu_disable_domain_dev } } -extern void pdev_flr(u8 bus, u8 devfn); - static int reassign_device( struct domain *source, struct domain *target, u8 bus, u8 devfn) { @@ -498,6 +496,7 @@ static int reassign_device( struct domai if ( !pdev ) return -ENODEV; + pdev_flr(pdev); bdf = (bus << 8) | devfn; /* supported device? */ iommu = (bdf < ivrs_bdf_entries) ? @@ -545,24 +544,7 @@ static int amd_iommu_assign_device(struc ivrs_mappings[req_id].read_permission); } - pdev_flr(bus, devfn); return reassign_device(dom0, d, bus, devfn); -} - -static void release_domain_devices(struct domain *d) -{ - struct pci_dev *pdev; - u8 bus, devfn; - - while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) ) - { - pdev_flr(pdev->bus, pdev->devfn); - bus = pdev->bus; devfn = pdev->devfn; - spin_unlock(&pdev->lock); - amd_iov_info("release domain %d devices %x:%x.%x\n", d->domain_id, - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - reassign_device(d, dom0, bus, devfn); - } } static void deallocate_next_page_table(void *table, unsigned long index, @@ -618,13 +600,11 @@ static void amd_iommu_domain_destroy(str static void amd_iommu_domain_destroy(struct domain *d) { deallocate_iommu_page_tables(d); - release_domain_devices(d); } static int amd_iommu_return_device( struct domain *s, struct domain *t, u8 bus, u8 devfn) { - pdev_flr(bus, devfn); return reassign_device(s, t, bus, devfn); } diff -r 9afe01a0e160 -r c1577f094ae4 xen/drivers/passthrough/pci.c --- a/xen/drivers/passthrough/pci.c Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/drivers/passthrough/pci.c Wed Jul 09 14:08:58 2008 +0100 @@ -17,9 +17,11 @@ #include <xen/sched.h> #include <xen/pci.h> +#include <xen/pci_regs.h> #include <xen/list.h> #include <xen/prefetch.h> #include <xen/iommu.h> +#include <xen/delay.h> #include <xen/keyhandler.h> @@ -145,6 +147,85 @@ int pci_remove_device(u8 bus, u8 devfn) return ret; } +void pci_release_devices(struct domain *d) +{ + struct pci_dev *pdev; + u8 bus, devfn; + + while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) ) + { + pci_cleanup_msi(pdev); + bus = pdev->bus; devfn = pdev->devfn; + spin_unlock(&pdev->lock); + deassign_device(d, bus, devfn); + } +} + +#define PCI_D3hot (3) +#define PCI_CONFIG_DWORD_SIZE (64) +#define PCI_EXP_DEVCAP_FLR (1 << 28) +#define PCI_EXP_DEVCTL_FLR (1 << 15) + +void pdev_flr(struct pci_dev *pdev) +{ + u8 pos; + u32 dev_cap, dev_status, pm_ctl; + int flr = 0; + u8 dev = PCI_SLOT(pdev->devfn); + u8 func = PCI_FUNC(pdev->devfn); + + pos = pci_find_cap_offset(pdev->bus, dev, func, PCI_CAP_ID_EXP); + if ( pos != 0 ) + { + dev_cap = pci_conf_read32(pdev->bus, dev, func, pos + PCI_EXP_DEVCAP); + if ( dev_cap & PCI_EXP_DEVCAP_FLR ) + { + pci_conf_write32(pdev->bus, dev, func, + pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR); + do { + dev_status = pci_conf_read32(pdev->bus, dev, func, + pos + PCI_EXP_DEVSTA); + } while ( dev_status & PCI_EXP_DEVSTA_TRPND ); + + flr = 1; + } + } + + /* If this device doesn't support function level reset, + * program device from D0 t0 D3hot, and then return to D0 + * to implement function level reset + */ + if ( flr == 0 ) + { + pos = pci_find_cap_offset(pdev->bus, dev, func, PCI_CAP_ID_PM); + if ( pos != 0 ) + { + int i; + u32 config[PCI_CONFIG_DWORD_SIZE]; + for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) + config[i] = pci_conf_read32(pdev->bus, dev, func, i*4); + + /* Enter D3hot without soft reset */ + pm_ctl = pci_conf_read32(pdev->bus, dev, func, pos + PCI_PM_CTRL); + pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET; + pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; + pm_ctl |= PCI_D3hot; + pci_conf_write32(pdev->bus, dev, func, pos + PCI_PM_CTRL, pm_ctl); + mdelay(10); + + /* From D3hot to D0 */ + pci_conf_write32(pdev->bus, dev, func, pos + PCI_PM_CTRL, 0); + mdelay(10); + + /* Write saved configurations to device */ + for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) + pci_conf_write32(pdev->bus, dev, func, i*4, config[i]); + + flr = 1; + } + } +} + static void dump_pci_devices(unsigned char ch) { struct pci_dev *pdev; @@ -174,3 +255,14 @@ static int __init setup_dump_pcidevs(voi return 0; } __initcall(setup_dump_pcidevs); + + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 9afe01a0e160 -r c1577f094ae4 xen/drivers/passthrough/vtd/extern.h --- a/xen/drivers/passthrough/vtd/extern.h Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/drivers/passthrough/vtd/extern.h Wed Jul 09 14:08:58 2008 +0100 @@ -28,7 +28,6 @@ extern struct ir_ctrl *ir_ctrl; void print_iommu_regs(struct acpi_drhd_unit *drhd); void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn); -void pdev_flr(u8 bus, u8 devfn); int qinval_setup(struct iommu *iommu); int intremap_setup(struct iommu *iommu); diff -r 9afe01a0e160 -r c1577f094ae4 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Wed Jul 09 14:08:58 2008 +0100 @@ -1366,7 +1366,7 @@ static int reassign_device_ownership( if ( !(pdev = pci_lock_domain_pdev(source, bus, devfn)) ) return -ENODEV; - pdev_flr(bus, devfn); + pdev_flr(pdev); drhd = acpi_find_matched_drhd_unit(bus, devfn); pdev_iommu = drhd->iommu; domain_context_unmap(bus, devfn); @@ -1397,28 +1397,6 @@ static int reassign_device_ownership( return ret; } -void return_devices_to_dom0(struct domain *d) -{ - struct pci_dev *pdev; - - while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) ) - { - pci_cleanup_msi(pdev); - spin_unlock(&pdev->lock); - reassign_device_ownership(d, dom0, pdev->bus, pdev->devfn); - } - -#ifdef VTD_DEBUG - read_lock(&pcidevs_lock); - for_each_pdev ( dom0, pdev ) - dprintk(XENLOG_INFO VTDPREFIX, - "return_devices_to_dom0:%x: bdf = %x:%x:%x\n", - dom0->domain_id, pdev->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - read_unlock(&pcidevs_lock); -#endif -} - void iommu_domain_teardown(struct domain *d) { struct hvm_iommu *hd = domain_hvm_iommu(d); @@ -1426,7 +1404,6 @@ void iommu_domain_teardown(struct domain if ( list_empty(&acpi_drhd_units) ) return; - return_devices_to_dom0(d); iommu_free_pagetable(hd->pgd_maddr, agaw_to_level(hd->agaw)); hd->pgd_maddr = 0; iommu_domid_release(d); diff -r 9afe01a0e160 -r c1577f094ae4 xen/drivers/passthrough/vtd/utils.c --- a/xen/drivers/passthrough/vtd/utils.c Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/drivers/passthrough/vtd/utils.c Wed Jul 09 14:08:58 2008 +0100 @@ -92,71 +92,6 @@ void disable_pmr(struct iommu *iommu) dprintk(XENLOG_INFO VTDPREFIX, "Disabled protected memory registers\n"); -} - -#define PCI_D3hot (3) -#define PCI_CONFIG_DWORD_SIZE (64) -#define PCI_EXP_DEVCAP_FLR (1 << 28) -#define PCI_EXP_DEVCTL_FLR (1 << 15) - -void pdev_flr(u8 bus, u8 devfn) -{ - u8 pos; - u32 dev_cap, dev_status, pm_ctl; - int flr = 0; - u8 dev = PCI_SLOT(devfn); - u8 func = PCI_FUNC(devfn); - - pos = pci_find_cap_offset(bus, dev, func, PCI_CAP_ID_EXP); - if ( pos != 0 ) - { - dev_cap = pci_conf_read32(bus, dev, func, pos + PCI_EXP_DEVCAP); - if ( dev_cap & PCI_EXP_DEVCAP_FLR ) - { - pci_conf_write32(bus, dev, func, - pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR); - do { - dev_status = pci_conf_read32(bus, dev, func, - pos + PCI_EXP_DEVSTA); - } while ( dev_status & PCI_EXP_DEVSTA_TRPND ); - - flr = 1; - } - } - - /* If this device doesn't support function level reset, - * program device from D0 t0 D3hot, and then return to D0 - * to implement function level reset - */ - if ( flr == 0 ) - { - pos = pci_find_cap_offset(bus, dev, func, PCI_CAP_ID_PM); - if ( pos != 0 ) - { - int i; - u32 config[PCI_CONFIG_DWORD_SIZE]; - for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) - config[i] = pci_conf_read32(bus, dev, func, i*4); - - /* Enter D3hot without soft reset */ - pm_ctl = pci_conf_read32(bus, dev, func, pos + PCI_PM_CTRL); - pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET; - pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; - pm_ctl |= PCI_D3hot; - pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, pm_ctl); - mdelay(10); - - /* From D3hot to D0 */ - pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, 0); - mdelay(10); - - /* Write saved configurations to device */ - for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) - pci_conf_write32(bus, dev, func, i*4, config[i]); - - flr = 1; - } - } } void print_iommu_regs(struct acpi_drhd_unit *drhd) diff -r 9afe01a0e160 -r c1577f094ae4 xen/include/xen/pci.h --- a/xen/include/xen/pci.h Wed Jul 09 13:01:16 2008 +0100 +++ b/xen/include/xen/pci.h Wed Jul 09 14:08:58 2008 +0100 @@ -56,6 +56,8 @@ struct pci_dev *pci_lock_pdev(int bus, i struct pci_dev *pci_lock_pdev(int bus, int devfn); struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn); +void pdev_flr(struct pci_dev *pdev); +void pci_release_devices(struct domain *d); int pci_add_device(u8 bus, u8 devfn); int pci_remove_device(u8 bus, u8 devfn); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |