Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'iommu/page-sizes' and 'iommu/group-id' into next

Conflicts:
drivers/iommu/amd_iommu.c
drivers/iommu/intel-iommu.c
include/linux/iommu.h

+155 -1
+3 -1
Documentation/kernel-parameters.txt
··· 1064 1064 nomerge 1065 1065 forcesac 1066 1066 soft 1067 - pt [x86, IA-64] 1067 + pt [x86, IA-64] 1068 + group_mf [x86, IA-64] 1069 + 1068 1070 1069 1071 io7= [HW] IO7 for Marvel based alpha systems 1070 1072 See comment before marvel_specify_io7 in
+2
arch/ia64/include/asm/iommu.h
··· 11 11 extern int force_iommu, no_iommu; 12 12 extern int iommu_pass_through; 13 13 extern int iommu_detected; 14 + extern int iommu_group_mf; 14 15 #else 15 16 #define iommu_pass_through (0) 16 17 #define no_iommu (1) 17 18 #define iommu_detected (0) 19 + #define iommu_group_mf (0) 18 20 #endif 19 21 extern void iommu_dma_init(void); 20 22 extern void machvec_init(const char *name);
+1
arch/ia64/kernel/pci-dma.c
··· 33 33 #endif 34 34 35 35 int iommu_pass_through; 36 + int iommu_group_mf; 36 37 37 38 /* Dummy device used for NULL arguments (normally ISA). Better would 38 39 be probably a smaller DMA mask, but this is bug-to-bug compatible
+1
arch/x86/include/asm/iommu.h
··· 5 5 extern int force_iommu, no_iommu; 6 6 extern int iommu_detected; 7 7 extern int iommu_pass_through; 8 + extern int iommu_group_mf; 8 9 9 10 /* 10 seconds */ 10 11 #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
+11
arch/x86/kernel/pci-dma.c
··· 45 45 */ 46 46 int iommu_pass_through __read_mostly; 47 47 48 + /* 49 + * Group multi-function PCI devices into a single device-group for the 50 + * iommu_device_group interface. This tells the iommu driver to pretend 51 + * it cannot distinguish between functions of a device, exposing only one 52 + * group for the device. Useful for disallowing use of individual PCI 53 + * functions from userspace drivers. 54 + */ 55 + int iommu_group_mf __read_mostly; 56 + 48 57 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; 49 58 50 59 /* Dummy device used for NULL arguments (normally ISA). */ ··· 178 169 #endif 179 170 if (!strncmp(p, "pt", 2)) 180 171 iommu_pass_through = 1; 172 + if (!strncmp(p, "group_mf", 8)) 173 + iommu_group_mf = 1; 181 174 182 175 gart_parse_options(p); 183 176
+21
drivers/iommu/amd_iommu.c
··· 3188 3188 return 0; 3189 3189 } 3190 3190 3191 + static int amd_iommu_device_group(struct device *dev, unsigned int *groupid) 3192 + { 3193 + struct iommu_dev_data *dev_data = dev->archdata.iommu; 3194 + struct pci_dev *pdev = to_pci_dev(dev); 3195 + u16 devid; 3196 + 3197 + if (!dev_data) 3198 + return -ENODEV; 3199 + 3200 + if (pdev->is_virtfn || !iommu_group_mf) 3201 + devid = dev_data->devid; 3202 + else 3203 + devid = calc_devid(pdev->bus->number, 3204 + PCI_DEVFN(PCI_SLOT(pdev->devfn), 0)); 3205 + 3206 + *groupid = amd_iommu_alias_table[devid]; 3207 + 3208 + return 0; 3209 + } 3210 + 3191 3211 static struct iommu_ops amd_iommu_ops = { 3192 3212 .domain_init = amd_iommu_domain_init, 3193 3213 .domain_destroy = amd_iommu_domain_destroy, ··· 3217 3197 .unmap = amd_iommu_unmap, 3218 3198 .iova_to_phys = amd_iommu_iova_to_phys, 3219 3199 .domain_has_cap = amd_iommu_domain_has_cap, 3200 + .device_group = amd_iommu_device_group, 3220 3201 .pgsize_bitmap = AMD_IOMMU_PGSIZES, 3221 3202 }; 3222 3203
+49
drivers/iommu/intel-iommu.c
··· 4080 4080 return 0; 4081 4081 } 4082 4082 4083 + /* 4084 + * Group numbers are arbitrary. Device with the same group number 4085 + * indicate the iommu cannot differentiate between them. To avoid 4086 + * tracking used groups we just use the seg|bus|devfn of the lowest 4087 + * level we're able to differentiate devices 4088 + */ 4089 + static int intel_iommu_device_group(struct device *dev, unsigned int *groupid) 4090 + { 4091 + struct pci_dev *pdev = to_pci_dev(dev); 4092 + struct pci_dev *bridge; 4093 + union { 4094 + struct { 4095 + u8 devfn; 4096 + u8 bus; 4097 + u16 segment; 4098 + } pci; 4099 + u32 group; 4100 + } id; 4101 + 4102 + if (iommu_no_mapping(dev)) 4103 + return -ENODEV; 4104 + 4105 + id.pci.segment = pci_domain_nr(pdev->bus); 4106 + id.pci.bus = pdev->bus->number; 4107 + id.pci.devfn = pdev->devfn; 4108 + 4109 + if (!device_to_iommu(id.pci.segment, id.pci.bus, id.pci.devfn)) 4110 + return -ENODEV; 4111 + 4112 + bridge = pci_find_upstream_pcie_bridge(pdev); 4113 + if (bridge) { 4114 + if (pci_is_pcie(bridge)) { 4115 + id.pci.bus = bridge->subordinate->number; 4116 + id.pci.devfn = 0; 4117 + } else { 4118 + id.pci.bus = bridge->bus->number; 4119 + id.pci.devfn = bridge->devfn; 4120 + } 4121 + } 4122 + 4123 + if (!pdev->is_virtfn && iommu_group_mf) 4124 + id.pci.devfn = PCI_DEVFN(PCI_SLOT(id.pci.devfn), 0); 4125 + 4126 + *groupid = id.group; 4127 + 4128 + return 0; 4129 + } 4130 + 4083 4131 static struct iommu_ops intel_iommu_ops = { 4084 4132 .domain_init = intel_iommu_domain_init, 4085 4133 .domain_destroy = intel_iommu_domain_destroy, ··· 4137 4089 .unmap = intel_iommu_unmap, 4138 4090 .iova_to_phys = intel_iommu_iova_to_phys, 4139 4091 .domain_has_cap = intel_iommu_domain_has_cap, 4092 + .device_group = intel_iommu_device_group, 4140 4093 .pgsize_bitmap = INTEL_IOMMU_PGSIZES, 4141 4094 }; 4142 4095
+60
drivers/iommu/iommu.c
··· 27 27 #include <linux/errno.h> 28 28 #include <linux/iommu.h> 29 29 30 + static ssize_t show_iommu_group(struct device *dev, 31 + struct device_attribute *attr, char *buf) 32 + { 33 + unsigned int groupid; 34 + 35 + if (iommu_device_group(dev, &groupid)) 36 + return 0; 37 + 38 + return sprintf(buf, "%u", groupid); 39 + } 40 + static DEVICE_ATTR(iommu_group, S_IRUGO, show_iommu_group, NULL); 41 + 42 + static int add_iommu_group(struct device *dev, void *data) 43 + { 44 + unsigned int groupid; 45 + 46 + if (iommu_device_group(dev, &groupid) == 0) 47 + return device_create_file(dev, &dev_attr_iommu_group); 48 + 49 + return 0; 50 + } 51 + 52 + static int remove_iommu_group(struct device *dev) 53 + { 54 + unsigned int groupid; 55 + 56 + if (iommu_device_group(dev, &groupid) == 0) 57 + device_remove_file(dev, &dev_attr_iommu_group); 58 + 59 + return 0; 60 + } 61 + 62 + static int iommu_device_notifier(struct notifier_block *nb, 63 + unsigned long action, void *data) 64 + { 65 + struct device *dev = data; 66 + 67 + if (action == BUS_NOTIFY_ADD_DEVICE) 68 + return add_iommu_group(dev, NULL); 69 + else if (action == BUS_NOTIFY_DEL_DEVICE) 70 + return remove_iommu_group(dev); 71 + 72 + return 0; 73 + } 74 + 75 + static struct notifier_block iommu_device_nb = { 76 + .notifier_call = iommu_device_notifier, 77 + }; 78 + 30 79 static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) 31 80 { 81 + bus_register_notifier(bus, &iommu_device_nb); 82 + bus_for_each_dev(bus, NULL, NULL, add_iommu_group); 32 83 } 33 84 34 85 /** ··· 332 281 return unmapped; 333 282 } 334 283 EXPORT_SYMBOL_GPL(iommu_unmap); 284 + 285 + int iommu_device_group(struct device *dev, unsigned int *groupid) 286 + { 287 + if (iommu_present(dev->bus) && dev->bus->iommu_ops->device_group) 288 + return dev->bus->iommu_ops->device_group(dev, groupid); 289 + 290 + return -ENODEV; 291 + } 292 + EXPORT_SYMBOL_GPL(iommu_device_group);
+7
include/linux/iommu.h
··· 74 74 unsigned long iova); 75 75 int (*domain_has_cap)(struct iommu_domain *domain, 76 76 unsigned long cap); 77 + int (*device_group)(struct device *dev, unsigned int *groupid); 77 78 unsigned long pgsize_bitmap; 78 79 }; 79 80 ··· 96 95 unsigned long cap); 97 96 extern void iommu_set_fault_handler(struct iommu_domain *domain, 98 97 iommu_fault_handler_t handler); 98 + extern int iommu_device_group(struct device *dev, unsigned int *groupid); 99 99 100 100 /** 101 101 * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework ··· 193 191 static inline void iommu_set_fault_handler(struct iommu_domain *domain, 194 192 iommu_fault_handler_t handler) 195 193 { 194 + } 195 + 196 + static inline int iommu_device_group(struct device *dev, unsigned int *groupid) 197 + { 198 + return -ENODEV; 196 199 } 197 200 198 201 #endif /* CONFIG_IOMMU_API */