debuggers.hg
changeset 18048:c1577f094ae4
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@netronome.com>
Release all pci devices before doing iommu domain teardown. Also
moved pdev_flr() into generic pci code.
Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Wed Jul 09 14:08:58 2008 +0100 (2008-07-09) |
parents | 9afe01a0e160 |
children | e10f43449463 |
files | xen/arch/x86/domain.c xen/drivers/passthrough/amd/pci_amd_iommu.c xen/drivers/passthrough/pci.c xen/drivers/passthrough/vtd/extern.h xen/drivers/passthrough/vtd/iommu.c xen/drivers/passthrough/vtd/utils.c xen/include/xen/pci.h |
line diff
1.1 --- a/xen/arch/x86/domain.c Wed Jul 09 13:01:16 2008 +0100 1.2 +++ b/xen/arch/x86/domain.c Wed Jul 09 14:08:58 2008 +0100 1.3 @@ -30,6 +30,7 @@ 1.4 #include <xen/percpu.h> 1.5 #include <xen/compat.h> 1.6 #include <xen/acpi.h> 1.7 +#include <xen/pci.h> 1.8 #include <asm/regs.h> 1.9 #include <asm/mc146818rtc.h> 1.10 #include <asm/system.h> 1.11 @@ -473,6 +474,7 @@ void arch_domain_destroy(struct domain * 1.12 if ( is_hvm_domain(d) ) 1.13 hvm_domain_destroy(d); 1.14 1.15 + pci_release_devices(d); 1.16 if ( !is_idle_domain(d) ) 1.17 iommu_domain_destroy(d); 1.18
2.1 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Wed Jul 09 13:01:16 2008 +0100 2.2 +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Wed Jul 09 14:08:58 2008 +0100 2.3 @@ -485,8 +485,6 @@ static void amd_iommu_disable_domain_dev 2.4 } 2.5 } 2.6 2.7 -extern void pdev_flr(u8 bus, u8 devfn); 2.8 - 2.9 static int reassign_device( struct domain *source, struct domain *target, 2.10 u8 bus, u8 devfn) 2.11 { 2.12 @@ -498,6 +496,7 @@ static int reassign_device( struct domai 2.13 if ( !pdev ) 2.14 return -ENODEV; 2.15 2.16 + pdev_flr(pdev); 2.17 bdf = (bus << 8) | devfn; 2.18 /* supported device? */ 2.19 iommu = (bdf < ivrs_bdf_entries) ? 2.20 @@ -545,26 +544,9 @@ static int amd_iommu_assign_device(struc 2.21 ivrs_mappings[req_id].read_permission); 2.22 } 2.23 2.24 - pdev_flr(bus, devfn); 2.25 return reassign_device(dom0, d, bus, devfn); 2.26 } 2.27 2.28 -static void release_domain_devices(struct domain *d) 2.29 -{ 2.30 - struct pci_dev *pdev; 2.31 - u8 bus, devfn; 2.32 - 2.33 - while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) ) 2.34 - { 2.35 - pdev_flr(pdev->bus, pdev->devfn); 2.36 - bus = pdev->bus; devfn = pdev->devfn; 2.37 - spin_unlock(&pdev->lock); 2.38 - amd_iov_info("release domain %d devices %x:%x.%x\n", d->domain_id, 2.39 - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 2.40 - reassign_device(d, dom0, bus, devfn); 2.41 - } 2.42 -} 2.43 - 2.44 static void deallocate_next_page_table(void *table, unsigned long index, 2.45 int level) 2.46 { 2.47 @@ -618,13 +600,11 @@ static void deallocate_iommu_page_tables 2.48 static void amd_iommu_domain_destroy(struct domain *d) 2.49 { 2.50 deallocate_iommu_page_tables(d); 2.51 - release_domain_devices(d); 2.52 } 2.53 2.54 static int amd_iommu_return_device( 2.55 struct domain *s, struct domain *t, u8 bus, u8 devfn) 2.56 { 2.57 - pdev_flr(bus, devfn); 2.58 return reassign_device(s, t, bus, devfn); 2.59 } 2.60
3.1 --- a/xen/drivers/passthrough/pci.c Wed Jul 09 13:01:16 2008 +0100 3.2 +++ b/xen/drivers/passthrough/pci.c Wed Jul 09 14:08:58 2008 +0100 3.3 @@ -17,9 +17,11 @@ 3.4 3.5 #include <xen/sched.h> 3.6 #include <xen/pci.h> 3.7 +#include <xen/pci_regs.h> 3.8 #include <xen/list.h> 3.9 #include <xen/prefetch.h> 3.10 #include <xen/iommu.h> 3.11 +#include <xen/delay.h> 3.12 #include <xen/keyhandler.h> 3.13 3.14 3.15 @@ -145,6 +147,85 @@ int pci_remove_device(u8 bus, u8 devfn) 3.16 return ret; 3.17 } 3.18 3.19 +void pci_release_devices(struct domain *d) 3.20 +{ 3.21 + struct pci_dev *pdev; 3.22 + u8 bus, devfn; 3.23 + 3.24 + while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) ) 3.25 + { 3.26 + pci_cleanup_msi(pdev); 3.27 + bus = pdev->bus; devfn = pdev->devfn; 3.28 + spin_unlock(&pdev->lock); 3.29 + deassign_device(d, bus, devfn); 3.30 + } 3.31 +} 3.32 + 3.33 +#define PCI_D3hot (3) 3.34 +#define PCI_CONFIG_DWORD_SIZE (64) 3.35 +#define PCI_EXP_DEVCAP_FLR (1 << 28) 3.36 +#define PCI_EXP_DEVCTL_FLR (1 << 15) 3.37 + 3.38 +void pdev_flr(struct pci_dev *pdev) 3.39 +{ 3.40 + u8 pos; 3.41 + u32 dev_cap, dev_status, pm_ctl; 3.42 + int flr = 0; 3.43 + u8 dev = PCI_SLOT(pdev->devfn); 3.44 + u8 func = PCI_FUNC(pdev->devfn); 3.45 + 3.46 + pos = pci_find_cap_offset(pdev->bus, dev, func, PCI_CAP_ID_EXP); 3.47 + if ( pos != 0 ) 3.48 + { 3.49 + dev_cap = pci_conf_read32(pdev->bus, dev, func, pos + PCI_EXP_DEVCAP); 3.50 + if ( dev_cap & PCI_EXP_DEVCAP_FLR ) 3.51 + { 3.52 + pci_conf_write32(pdev->bus, dev, func, 3.53 + pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR); 3.54 + do { 3.55 + dev_status = pci_conf_read32(pdev->bus, dev, func, 3.56 + pos + PCI_EXP_DEVSTA); 3.57 + } while ( dev_status & PCI_EXP_DEVSTA_TRPND ); 3.58 + 3.59 + flr = 1; 3.60 + } 3.61 + } 3.62 + 3.63 + /* If this device doesn't support function level reset, 3.64 + * program device from D0 t0 D3hot, and then return to D0 3.65 + * to implement function level reset 3.66 + */ 3.67 + if ( flr == 0 ) 3.68 + { 3.69 + pos = pci_find_cap_offset(pdev->bus, dev, func, PCI_CAP_ID_PM); 3.70 + if ( pos != 0 ) 3.71 + { 3.72 + int i; 3.73 + u32 config[PCI_CONFIG_DWORD_SIZE]; 3.74 + for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) 3.75 + config[i] = pci_conf_read32(pdev->bus, dev, func, i*4); 3.76 + 3.77 + /* Enter D3hot without soft reset */ 3.78 + pm_ctl = pci_conf_read32(pdev->bus, dev, func, pos + PCI_PM_CTRL); 3.79 + pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET; 3.80 + pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; 3.81 + pm_ctl |= PCI_D3hot; 3.82 + pci_conf_write32(pdev->bus, dev, func, pos + PCI_PM_CTRL, pm_ctl); 3.83 + mdelay(10); 3.84 + 3.85 + /* From D3hot to D0 */ 3.86 + pci_conf_write32(pdev->bus, dev, func, pos + PCI_PM_CTRL, 0); 3.87 + mdelay(10); 3.88 + 3.89 + /* Write saved configurations to device */ 3.90 + for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) 3.91 + pci_conf_write32(pdev->bus, dev, func, i*4, config[i]); 3.92 + 3.93 + flr = 1; 3.94 + } 3.95 + } 3.96 +} 3.97 + 3.98 static void dump_pci_devices(unsigned char ch) 3.99 { 3.100 struct pci_dev *pdev; 3.101 @@ -174,3 +255,14 @@ static int __init setup_dump_pcidevs(voi 3.102 return 0; 3.103 } 3.104 __initcall(setup_dump_pcidevs); 3.105 + 3.106 + 3.107 + 3.108 +/* 3.109 + * Local variables: 3.110 + * mode: C 3.111 + * c-set-style: "BSD" 3.112 + * c-basic-offset: 4 3.113 + * indent-tabs-mode: nil 3.114 + * End: 3.115 + */
4.1 --- a/xen/drivers/passthrough/vtd/extern.h Wed Jul 09 13:01:16 2008 +0100 4.2 +++ b/xen/drivers/passthrough/vtd/extern.h Wed Jul 09 14:08:58 2008 +0100 4.3 @@ -28,7 +28,6 @@ extern struct ir_ctrl *ir_ctrl; 4.4 4.5 void print_iommu_regs(struct acpi_drhd_unit *drhd); 4.6 void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn); 4.7 -void pdev_flr(u8 bus, u8 devfn); 4.8 4.9 int qinval_setup(struct iommu *iommu); 4.10 int intremap_setup(struct iommu *iommu);
5.1 --- a/xen/drivers/passthrough/vtd/iommu.c Wed Jul 09 13:01:16 2008 +0100 5.2 +++ b/xen/drivers/passthrough/vtd/iommu.c Wed Jul 09 14:08:58 2008 +0100 5.3 @@ -1366,7 +1366,7 @@ static int reassign_device_ownership( 5.4 if ( !(pdev = pci_lock_domain_pdev(source, bus, devfn)) ) 5.5 return -ENODEV; 5.6 5.7 - pdev_flr(bus, devfn); 5.8 + pdev_flr(pdev); 5.9 drhd = acpi_find_matched_drhd_unit(bus, devfn); 5.10 pdev_iommu = drhd->iommu; 5.11 domain_context_unmap(bus, devfn); 5.12 @@ -1397,28 +1397,6 @@ static int reassign_device_ownership( 5.13 return ret; 5.14 } 5.15 5.16 -void return_devices_to_dom0(struct domain *d) 5.17 -{ 5.18 - struct pci_dev *pdev; 5.19 - 5.20 - while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) ) 5.21 - { 5.22 - pci_cleanup_msi(pdev); 5.23 - spin_unlock(&pdev->lock); 5.24 - reassign_device_ownership(d, dom0, pdev->bus, pdev->devfn); 5.25 - } 5.26 - 5.27 -#ifdef VTD_DEBUG 5.28 - read_lock(&pcidevs_lock); 5.29 - for_each_pdev ( dom0, pdev ) 5.30 - dprintk(XENLOG_INFO VTDPREFIX, 5.31 - "return_devices_to_dom0:%x: bdf = %x:%x:%x\n", 5.32 - dom0->domain_id, pdev->bus, 5.33 - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 5.34 - read_unlock(&pcidevs_lock); 5.35 -#endif 5.36 -} 5.37 - 5.38 void iommu_domain_teardown(struct domain *d) 5.39 { 5.40 struct hvm_iommu *hd = domain_hvm_iommu(d); 5.41 @@ -1426,7 +1404,6 @@ void iommu_domain_teardown(struct domain 5.42 if ( list_empty(&acpi_drhd_units) ) 5.43 return; 5.44 5.45 - return_devices_to_dom0(d); 5.46 iommu_free_pagetable(hd->pgd_maddr, agaw_to_level(hd->agaw)); 5.47 hd->pgd_maddr = 0; 5.48 iommu_domid_release(d);
6.1 --- a/xen/drivers/passthrough/vtd/utils.c Wed Jul 09 13:01:16 2008 +0100 6.2 +++ b/xen/drivers/passthrough/vtd/utils.c Wed Jul 09 14:08:58 2008 +0100 6.3 @@ -94,71 +94,6 @@ void disable_pmr(struct iommu *iommu) 6.4 "Disabled protected memory registers\n"); 6.5 } 6.6 6.7 -#define PCI_D3hot (3) 6.8 -#define PCI_CONFIG_DWORD_SIZE (64) 6.9 -#define PCI_EXP_DEVCAP_FLR (1 << 28) 6.10 -#define PCI_EXP_DEVCTL_FLR (1 << 15) 6.11 - 6.12 -void pdev_flr(u8 bus, u8 devfn) 6.13 -{ 6.14 - u8 pos; 6.15 - u32 dev_cap, dev_status, pm_ctl; 6.16 - int flr = 0; 6.17 - u8 dev = PCI_SLOT(devfn); 6.18 - u8 func = PCI_FUNC(devfn); 6.19 - 6.20 - pos = pci_find_cap_offset(bus, dev, func, PCI_CAP_ID_EXP); 6.21 - if ( pos != 0 ) 6.22 - { 6.23 - dev_cap = pci_conf_read32(bus, dev, func, pos + PCI_EXP_DEVCAP); 6.24 - if ( dev_cap & PCI_EXP_DEVCAP_FLR ) 6.25 - { 6.26 - pci_conf_write32(bus, dev, func, 6.27 - pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR); 6.28 - do { 6.29 - dev_status = pci_conf_read32(bus, dev, func, 6.30 - pos + PCI_EXP_DEVSTA); 6.31 - } while ( dev_status & PCI_EXP_DEVSTA_TRPND ); 6.32 - 6.33 - flr = 1; 6.34 - } 6.35 - } 6.36 - 6.37 - /* If this device doesn't support function level reset, 6.38 - * program device from D0 t0 D3hot, and then return to D0 6.39 - * to implement function level reset 6.40 - */ 6.41 - if ( flr == 0 ) 6.42 - { 6.43 - pos = pci_find_cap_offset(bus, dev, func, PCI_CAP_ID_PM); 6.44 - if ( pos != 0 ) 6.45 - { 6.46 - int i; 6.47 - u32 config[PCI_CONFIG_DWORD_SIZE]; 6.48 - for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) 6.49 - config[i] = pci_conf_read32(bus, dev, func, i*4); 6.50 - 6.51 - /* Enter D3hot without soft reset */ 6.52 - pm_ctl = pci_conf_read32(bus, dev, func, pos + PCI_PM_CTRL); 6.53 - pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET; 6.54 - pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; 6.55 - pm_ctl |= PCI_D3hot; 6.56 - pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, pm_ctl); 6.57 - mdelay(10); 6.58 - 6.59 - /* From D3hot to D0 */ 6.60 - pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, 0); 6.61 - mdelay(10); 6.62 - 6.63 - /* Write saved configurations to device */ 6.64 - for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) 6.65 - pci_conf_write32(bus, dev, func, i*4, config[i]); 6.66 - 6.67 - flr = 1; 6.68 - } 6.69 - } 6.70 -} 6.71 - 6.72 void print_iommu_regs(struct acpi_drhd_unit *drhd) 6.73 { 6.74 struct iommu *iommu = drhd->iommu;
7.1 --- a/xen/include/xen/pci.h Wed Jul 09 13:01:16 2008 +0100 7.2 +++ b/xen/include/xen/pci.h Wed Jul 09 14:08:58 2008 +0100 7.3 @@ -56,6 +56,8 @@ void free_pdev(struct pci_dev *pdev); 7.4 struct pci_dev *pci_lock_pdev(int bus, int devfn); 7.5 struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn); 7.6 7.7 +void pdev_flr(struct pci_dev *pdev); 7.8 +void pci_release_devices(struct domain *d); 7.9 int pci_add_device(u8 bus, u8 devfn); 7.10 int pci_remove_device(u8 bus, u8 devfn); 7.11