diff options
author | Wei Wang <wei.wang2@amd.com> | 2011-11-11 12:03:21 +0100 |
---|---|---|
committer | Wei Wang <wei.wang2@amd.com> | 2011-11-11 12:03:21 +0100 |
commit | 756273ab103c20be805fcbea1c3dbee6aed73e71 (patch) | |
tree | e9e7f9bd65f38a16c2375fe91d249b2e646da614 | |
parent | ce56a70bd78a43e59266d884c1398c1ede2f3b89 (diff) | |
download | xen-756273ab103c20be805fcbea1c3dbee6aed73e71.tar.gz xen-756273ab103c20be805fcbea1c3dbee6aed73e71.tar.bz2 xen-756273ab103c20be805fcbea1c3dbee6aed73e71.zip |
amd iommu: Cleanup iommu pci capabilites detection
* Define new structure to represent capability block.
* Remove unnecessary read for unused information.
* Add sanity check into get_iommu_capabilities.
* iommu capability offset is 16 bit not 8 bit, fix that.
Signed-off-by: Wei Wang <wei.wang2@amd.com>
Committed-by: Jan Beulich <jbeulich@suse.com>
-rw-r--r-- | xen/drivers/passthrough/amd/iommu_detect.c | 43 | ||||
-rw-r--r-- | xen/include/asm-x86/amd-iommu.h | 14 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 2 |
3 files changed, 32 insertions, 27 deletions
diff --git a/xen/drivers/passthrough/amd/iommu_detect.c b/xen/drivers/passthrough/amd/iommu_detect.c index 5113f67544..9ead31d4e6 100644 --- a/xen/drivers/passthrough/amd/iommu_detect.c +++ b/xen/drivers/passthrough/amd/iommu_detect.c @@ -48,25 +48,16 @@ static int __init get_iommu_msi_capabilities( } static int __init get_iommu_capabilities( - u16 seg, u8 bus, u8 dev, u8 func, u8 cap_ptr, struct amd_iommu *iommu) + u16 seg, u8 bus, u8 dev, u8 func, u16 cap_ptr, struct amd_iommu *iommu) { - u32 cap_header, cap_range, misc_info; + u8 type; - cap_header = pci_conf_read32(seg, bus, dev, func, cap_ptr); - iommu->revision = get_field_from_reg_u32( - cap_header, PCI_CAP_REV_MASK, PCI_CAP_REV_SHIFT); - iommu->pte_not_present_cached = get_field_from_reg_u32( - cap_header, PCI_CAP_NP_CACHE_MASK, PCI_CAP_NP_CACHE_SHIFT); + iommu->cap.header = pci_conf_read32(seg, bus, dev, func, cap_ptr); + type = get_field_from_reg_u32(iommu->cap.header, PCI_CAP_TYPE_MASK, + PCI_CAP_TYPE_SHIFT); - cap_range = pci_conf_read32(seg, bus, dev, func, - cap_ptr + PCI_CAP_RANGE_OFFSET); - iommu->unit_id = get_field_from_reg_u32( - cap_range, PCI_CAP_UNIT_ID_MASK, PCI_CAP_UNIT_ID_SHIFT); - - misc_info = pci_conf_read32(seg, bus, dev, func, - cap_ptr + PCI_MISC_INFO_OFFSET); - iommu->msi_number = get_field_from_reg_u32( - misc_info, PCI_CAP_MSI_NUMBER_MASK, PCI_CAP_MSI_NUMBER_SHIFT); + if ( type != PCI_CAP_TYPE_IOMMU ) + return -ENODEV; return 0; } @@ -76,6 +67,7 @@ int __init amd_iommu_detect_one_acpi(void *ivhd) struct amd_iommu *iommu; u8 bus, dev, func; struct acpi_ivhd_block_header *ivhd_block; + int rt = 0; ivhd_block = (struct acpi_ivhd_block_header *)ivhd; @@ -125,12 +117,19 @@ int __init amd_iommu_detect_one_acpi(void *ivhd) iommu->ht_tunnel_enable = get_field_from_byte(ivhd_block->header.flags, AMD_IOMMU_ACPI_HT_TUN_ENB_MASK, AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT); - bus = iommu->bdf >> 8; - dev = PCI_SLOT(iommu->bdf & 0xFF); - func = PCI_FUNC(iommu->bdf & 0xFF); - get_iommu_capabilities(iommu->seg, bus, dev, func, - iommu->cap_offset, iommu); - get_iommu_msi_capabilities(iommu->seg, bus, dev, func, iommu); + + bus = PCI_BUS(iommu->bdf); + dev = PCI_SLOT(iommu->bdf); + func = PCI_FUNC(iommu->bdf); + + rt = get_iommu_capabilities(iommu->seg, bus, dev, func, + iommu->cap_offset, iommu); + if ( rt ) + return -ENODEV; + + rt = get_iommu_msi_capabilities(iommu->seg, bus, dev, func, iommu); + if ( rt ) + return -ENODEV; list_add_tail(&iommu->list, &amd_iommu_head); diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h index 5dc97c6766..df36fe25ac 100644 --- a/xen/include/asm-x86/amd-iommu.h +++ b/xen/include/asm-x86/amd-iommu.h @@ -36,16 +36,22 @@ struct table_struct { unsigned long alloc_size; }; +typedef struct iommu_cap { + uint32_t header; /* offset 00h */ + uint32_t base_low; /* offset 04h */ + uint32_t base_hi; /* offset 08h */ + uint32_t range; /* offset 0Ch */ + uint32_t misc; /* offset 10h */ +} iommu_cap_t; + struct amd_iommu { struct list_head list; spinlock_t lock; /* protect iommu */ u16 seg; u16 bdf; - u8 cap_offset; - u8 revision; - u8 unit_id; - u8 msi_number; + u16 cap_offset; + iommu_cap_t cap; u8 pte_not_present_cached; u8 ht_tunnel_support; diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h index a37e32d8c1..dfcf4d77b9 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h @@ -74,7 +74,7 @@ #define PCI_CAP_UNIT_ID_MASK 0x0000001F #define PCI_CAP_UNIT_ID_SHIFT 0 -#define PCI_MISC_INFO_OFFSET 0x10 +#define PCI_CAP_MISC_INFO_OFFSET 0x10 #define PCI_CAP_MSI_NUMBER_MASK 0x0000001F #define PCI_CAP_MSI_NUMBER_SHIFT 0 |