]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
x86/amd-iommu: Add extended feature detection
authorJoerg Roedel <joerg.roedel@amd.com>
Mon, 11 Apr 2011 09:03:18 +0000 (11:03 +0200)
committerJoerg Roedel <joerg.roedel@amd.com>
Tue, 12 Apr 2011 07:21:51 +0000 (09:21 +0200)
This patch adds detection of the extended features of an
AMD IOMMU. The available features are printed to dmesg on
boot.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
arch/x86/include/asm/amd_iommu_proto.h
arch/x86/include/asm/amd_iommu_types.h
arch/x86/kernel/amd_iommu_init.c

index 1223c0fe03f5bd29a8574bf134fbee13b5386159..a4ae6c3875eb9b6fcc88e78aafc31acb99da9029 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef _ASM_X86_AMD_IOMMU_PROTO_H
 #define _ASM_X86_AMD_IOMMU_PROTO_H
 
-struct amd_iommu;
+#include <asm/amd_iommu_types.h>
 
 extern int amd_iommu_init_dma_ops(void);
 extern int amd_iommu_init_passthrough(void);
@@ -42,4 +42,12 @@ static inline bool is_rd890_iommu(struct pci_dev *pdev)
               (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
 }
 
+static inline bool iommu_feature(struct amd_iommu *iommu, u64 f)
+{
+       if (!(iommu->cap & (1 << IOMMU_CAP_EFR)))
+               return false;
+
+       return !!(iommu->features & f);
+}
+
 #endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
index 878ae008eb048ddbd4950aa346c8d1e1315d110d..5c24e4652347d8e097765947ad8426bc8975ebd7 100644 (file)
 #define MMIO_CONTROL_OFFSET     0x0018
 #define MMIO_EXCL_BASE_OFFSET   0x0020
 #define MMIO_EXCL_LIMIT_OFFSET  0x0028
+#define MMIO_EXT_FEATURES      0x0030
 #define MMIO_CMD_HEAD_OFFSET   0x2000
 #define MMIO_CMD_TAIL_OFFSET   0x2008
 #define MMIO_EVT_HEAD_OFFSET   0x2010
 #define MMIO_EVT_TAIL_OFFSET   0x2018
 #define MMIO_STATUS_OFFSET     0x2020
 
+
+/* Extended Feature Bits */
+#define FEATURE_PREFETCH       (1ULL<<0)
+#define FEATURE_PPR            (1ULL<<1)
+#define FEATURE_X2APIC         (1ULL<<2)
+#define FEATURE_NX             (1ULL<<3)
+#define FEATURE_GT             (1ULL<<4)
+#define FEATURE_IA             (1ULL<<6)
+#define FEATURE_GA             (1ULL<<7)
+#define FEATURE_HE             (1ULL<<8)
+#define FEATURE_PC             (1ULL<<9)
+
 /* MMIO status bits */
 #define MMIO_STATUS_COM_WAIT_INT_MASK  0x04
 
 /* IOMMU capabilities */
 #define IOMMU_CAP_IOTLB   24
 #define IOMMU_CAP_NPCACHE 26
+#define IOMMU_CAP_EFR     27
 
 #define MAX_DOMAIN_ID 65536
 
@@ -371,6 +385,9 @@ struct amd_iommu {
        /* flags read from acpi table */
        u8 acpi_flags;
 
+       /* Extended features */
+       u64 features;
+
        /*
         * Capability pointer. There could be more than one IOMMU per PCI
         * device function if there are more than one AMD IOMMU capability
index 8848dda808e21ba1a3487c61ab2e873e2291f2f4..047905dc3e14e2f995a96e9035aac70a638d4a3d 100644 (file)
@@ -299,9 +299,23 @@ static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
 /* Function to enable the hardware */
 static void iommu_enable(struct amd_iommu *iommu)
 {
-       printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n",
+       static const char * const feat_str[] = {
+               "PreF", "PPR", "X2APIC", "NX", "GT", "[5]",
+               "IA", "GA", "HE", "PC", NULL
+       };
+       int i;
+
+       printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx",
               dev_name(&iommu->dev->dev), iommu->cap_ptr);
 
+       if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
+               printk(KERN_CONT " extended features: ");
+               for (i = 0; feat_str[i]; ++i)
+                       if (iommu_feature(iommu, (1ULL << i)))
+                               printk(KERN_CONT " %s", feat_str[i]);
+       }
+       printk(KERN_CONT "\n");
+
        iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
 }
 
@@ -657,7 +671,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
 static void __init init_iommu_from_pci(struct amd_iommu *iommu)
 {
        int cap_ptr = iommu->cap_ptr;
-       u32 range, misc;
+       u32 range, misc, low, high;
        int i, j;
 
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
@@ -673,6 +687,12 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
                                        MMIO_GET_LD(range));
        iommu->evt_msi_num = MMIO_MSI_NUM(misc);
 
+       /* read extended feature bits */
+       low  = readl(iommu->mmio_base + MMIO_EXT_FEATURES);
+       high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4);
+
+       iommu->features = ((u64)high << 32) | low;
+
        if (!is_rd890_iommu(iommu->dev))
                return;