diff options
author | Joerg Roedel <jroedel@suse.de> | 2014-07-23 10:04:37 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2014-07-23 10:04:37 -0400 |
commit | cbb24a25a871cbdac4e58b68b541aadd91b249be (patch) | |
tree | 0b8207913c437d91c938a64a48c1a1751a31a37b /drivers | |
parent | aa4d066a2a8041b7e73cee68ce5499aca29f265e (diff) | |
parent | e09f8ea560490e941139d23b4c278d3e6e2c871a (diff) |
Merge branch 'core' into x86/vt-d
Conflicts:
drivers/iommu/intel-iommu.c
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/Makefile | 1 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu.c | 224 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 38 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 4 | ||||
-rw-r--r-- | drivers/iommu/arm-smmu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/dmar.c | 9 | ||||
-rw-r--r-- | drivers/iommu/exynos-iommu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/fsl_pamu_domain.c | 68 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 385 | ||||
-rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 55 | ||||
-rw-r--r-- | drivers/iommu/iommu-sysfs.c | 134 | ||||
-rw-r--r-- | drivers/iommu/iommu.c | 201 | ||||
-rw-r--r-- | drivers/iommu/ipmmu-vmsa.c | 2 | ||||
-rw-r--r-- | drivers/iommu/msm_iommu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/pci.h | 29 | ||||
-rw-r--r-- | drivers/iommu/shmobile-iommu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/tegra-gart.c | 2 | ||||
-rw-r--r-- | drivers/iommu/tegra-smmu.c | 2 |
19 files changed, 689 insertions, 475 deletions
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 8893bad048e0..7788ebd1f6e2 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_IOMMU_API) += iommu.o | 1 | obj-$(CONFIG_IOMMU_API) += iommu.o |
2 | obj-$(CONFIG_IOMMU_API) += iommu-traces.o | 2 | obj-$(CONFIG_IOMMU_API) += iommu-traces.o |
3 | obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o | ||
3 | obj-$(CONFIG_OF_IOMMU) += of_iommu.o | 4 | obj-$(CONFIG_OF_IOMMU) += of_iommu.o |
4 | obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o | 5 | obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o |
5 | obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o | 6 | obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 4aec6a29e316..18405314168b 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include "amd_iommu_proto.h" | 46 | #include "amd_iommu_proto.h" |
47 | #include "amd_iommu_types.h" | 47 | #include "amd_iommu_types.h" |
48 | #include "irq_remapping.h" | 48 | #include "irq_remapping.h" |
49 | #include "pci.h" | ||
50 | 49 | ||
51 | #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28)) | 50 | #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28)) |
52 | 51 | ||
@@ -81,7 +80,7 @@ LIST_HEAD(hpet_map); | |||
81 | */ | 80 | */ |
82 | static struct protection_domain *pt_domain; | 81 | static struct protection_domain *pt_domain; |
83 | 82 | ||
84 | static struct iommu_ops amd_iommu_ops; | 83 | static const struct iommu_ops amd_iommu_ops; |
85 | 84 | ||
86 | static ATOMIC_NOTIFIER_HEAD(ppr_notifier); | 85 | static ATOMIC_NOTIFIER_HEAD(ppr_notifier); |
87 | int amd_iommu_max_glx_val = -1; | 86 | int amd_iommu_max_glx_val = -1; |
@@ -133,9 +132,6 @@ static void free_dev_data(struct iommu_dev_data *dev_data) | |||
133 | list_del(&dev_data->dev_data_list); | 132 | list_del(&dev_data->dev_data_list); |
134 | spin_unlock_irqrestore(&dev_data_list_lock, flags); | 133 | spin_unlock_irqrestore(&dev_data_list_lock, flags); |
135 | 134 | ||
136 | if (dev_data->group) | ||
137 | iommu_group_put(dev_data->group); | ||
138 | |||
139 | kfree(dev_data); | 135 | kfree(dev_data); |
140 | } | 136 | } |
141 | 137 | ||
@@ -264,167 +260,79 @@ static bool check_device(struct device *dev) | |||
264 | return true; | 260 | return true; |
265 | } | 261 | } |
266 | 262 | ||
267 | static struct pci_bus *find_hosted_bus(struct pci_bus *bus) | 263 | static int init_iommu_group(struct device *dev) |
268 | { | ||
269 | while (!bus->self) { | ||
270 | if (!pci_is_root_bus(bus)) | ||
271 | bus = bus->parent; | ||
272 | else | ||
273 | return ERR_PTR(-ENODEV); | ||
274 | } | ||
275 | |||
276 | return bus; | ||
277 | } | ||
278 | |||
279 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | ||
280 | |||
281 | static struct pci_dev *get_isolation_root(struct pci_dev *pdev) | ||
282 | { | ||
283 | struct pci_dev *dma_pdev = pdev; | ||
284 | |||
285 | /* Account for quirked devices */ | ||
286 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | ||
287 | |||
288 | /* | ||
289 | * If it's a multifunction device that does not support our | ||
290 | * required ACS flags, add to the same group as lowest numbered | ||
291 | * function that also does not suport the required ACS flags. | ||
292 | */ | ||
293 | if (dma_pdev->multifunction && | ||
294 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { | ||
295 | u8 i, slot = PCI_SLOT(dma_pdev->devfn); | ||
296 | |||
297 | for (i = 0; i < 8; i++) { | ||
298 | struct pci_dev *tmp; | ||
299 | |||
300 | tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); | ||
301 | if (!tmp) | ||
302 | continue; | ||
303 | |||
304 | if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { | ||
305 | swap_pci_ref(&dma_pdev, tmp); | ||
306 | break; | ||
307 | } | ||
308 | pci_dev_put(tmp); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * Devices on the root bus go through the iommu. If that's not us, | ||
314 | * find the next upstream device and test ACS up to the root bus. | ||
315 | * Finding the next device may require skipping virtual buses. | ||
316 | */ | ||
317 | while (!pci_is_root_bus(dma_pdev->bus)) { | ||
318 | struct pci_bus *bus = find_hosted_bus(dma_pdev->bus); | ||
319 | if (IS_ERR(bus)) | ||
320 | break; | ||
321 | |||
322 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) | ||
323 | break; | ||
324 | |||
325 | swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); | ||
326 | } | ||
327 | |||
328 | return dma_pdev; | ||
329 | } | ||
330 | |||
331 | static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev) | ||
332 | { | 264 | { |
333 | struct iommu_group *group = iommu_group_get(&pdev->dev); | 265 | struct iommu_group *group; |
334 | int ret; | ||
335 | 266 | ||
336 | if (!group) { | 267 | group = iommu_group_get_for_dev(dev); |
337 | group = iommu_group_alloc(); | ||
338 | if (IS_ERR(group)) | ||
339 | return PTR_ERR(group); | ||
340 | 268 | ||
341 | WARN_ON(&pdev->dev != dev); | 269 | if (IS_ERR(group)) |
342 | } | 270 | return PTR_ERR(group); |
343 | 271 | ||
344 | ret = iommu_group_add_device(group, dev); | ||
345 | iommu_group_put(group); | 272 | iommu_group_put(group); |
346 | return ret; | 273 | return 0; |
347 | } | 274 | } |
348 | 275 | ||
349 | static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data, | 276 | static int __last_alias(struct pci_dev *pdev, u16 alias, void *data) |
350 | struct device *dev) | ||
351 | { | 277 | { |
352 | if (!dev_data->group) { | 278 | *(u16 *)data = alias; |
353 | struct iommu_group *group = iommu_group_alloc(); | 279 | return 0; |
354 | if (IS_ERR(group)) | ||
355 | return PTR_ERR(group); | ||
356 | |||
357 | dev_data->group = group; | ||
358 | } | ||
359 | |||
360 | return iommu_group_add_device(dev_data->group, dev); | ||
361 | } | 280 | } |
362 | 281 | ||
363 | static int init_iommu_group(struct device *dev) | 282 | static u16 get_alias(struct device *dev) |
364 | { | 283 | { |
365 | struct iommu_dev_data *dev_data; | 284 | struct pci_dev *pdev = to_pci_dev(dev); |
366 | struct iommu_group *group; | 285 | u16 devid, ivrs_alias, pci_alias; |
367 | struct pci_dev *dma_pdev; | ||
368 | int ret; | ||
369 | |||
370 | group = iommu_group_get(dev); | ||
371 | if (group) { | ||
372 | iommu_group_put(group); | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | dev_data = find_dev_data(get_device_id(dev)); | ||
377 | if (!dev_data) | ||
378 | return -ENOMEM; | ||
379 | 286 | ||
380 | if (dev_data->alias_data) { | 287 | devid = get_device_id(dev); |
381 | u16 alias; | 288 | ivrs_alias = amd_iommu_alias_table[devid]; |
382 | struct pci_bus *bus; | 289 | pci_for_each_dma_alias(pdev, __last_alias, &pci_alias); |
383 | 290 | ||
384 | if (dev_data->alias_data->group) | 291 | if (ivrs_alias == pci_alias) |
385 | goto use_group; | 292 | return ivrs_alias; |
386 | 293 | ||
387 | /* | 294 | /* |
388 | * If the alias device exists, it's effectively just a first | 295 | * DMA alias showdown |
389 | * level quirk for finding the DMA source. | 296 | * |
390 | */ | 297 | * The IVRS is fairly reliable in telling us about aliases, but it |
391 | alias = amd_iommu_alias_table[dev_data->devid]; | 298 | * can't know about every screwy device. If we don't have an IVRS |
392 | dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff); | 299 | * reported alias, use the PCI reported alias. In that case we may |
393 | if (dma_pdev) { | 300 | * still need to initialize the rlookup and dev_table entries if the |
394 | dma_pdev = get_isolation_root(dma_pdev); | 301 | * alias is to a non-existent device. |
395 | goto use_pdev; | 302 | */ |
303 | if (ivrs_alias == devid) { | ||
304 | if (!amd_iommu_rlookup_table[pci_alias]) { | ||
305 | amd_iommu_rlookup_table[pci_alias] = | ||
306 | amd_iommu_rlookup_table[devid]; | ||
307 | memcpy(amd_iommu_dev_table[pci_alias].data, | ||
308 | amd_iommu_dev_table[devid].data, | ||
309 | sizeof(amd_iommu_dev_table[pci_alias].data)); | ||
396 | } | 310 | } |
397 | 311 | ||
398 | /* | 312 | return pci_alias; |
399 | * If the alias is virtual, try to find a parent device | 313 | } |
400 | * and test whether the IOMMU group is actualy rooted above | ||
401 | * the alias. Be careful to also test the parent device if | ||
402 | * we think the alias is the root of the group. | ||
403 | */ | ||
404 | bus = pci_find_bus(0, alias >> 8); | ||
405 | if (!bus) | ||
406 | goto use_group; | ||
407 | |||
408 | bus = find_hosted_bus(bus); | ||
409 | if (IS_ERR(bus) || !bus->self) | ||
410 | goto use_group; | ||
411 | 314 | ||
412 | dma_pdev = get_isolation_root(pci_dev_get(bus->self)); | 315 | pr_info("AMD-Vi: Using IVRS reported alias %02x:%02x.%d " |
413 | if (dma_pdev != bus->self || (dma_pdev->multifunction && | 316 | "for device %s[%04x:%04x], kernel reported alias " |
414 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))) | 317 | "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias), |
415 | goto use_pdev; | 318 | PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device, |
319 | PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias), | ||
320 | PCI_FUNC(pci_alias)); | ||
416 | 321 | ||
417 | pci_dev_put(dma_pdev); | 322 | /* |
418 | goto use_group; | 323 | * If we don't have a PCI DMA alias and the IVRS alias is on the same |
324 | * bus, then the IVRS table may know about a quirk that we don't. | ||
325 | */ | ||
326 | if (pci_alias == devid && | ||
327 | PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) { | ||
328 | pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; | ||
329 | pdev->dma_alias_devfn = ivrs_alias & 0xff; | ||
330 | pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n", | ||
331 | PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias), | ||
332 | dev_name(dev)); | ||
419 | } | 333 | } |
420 | 334 | ||
421 | dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev))); | 335 | return ivrs_alias; |
422 | use_pdev: | ||
423 | ret = use_pdev_iommu_group(dma_pdev, dev); | ||
424 | pci_dev_put(dma_pdev); | ||
425 | return ret; | ||
426 | use_group: | ||
427 | return use_dev_data_iommu_group(dev_data->alias_data, dev); | ||
428 | } | 336 | } |
429 | 337 | ||
430 | static int iommu_init_device(struct device *dev) | 338 | static int iommu_init_device(struct device *dev) |
@@ -441,7 +349,8 @@ static int iommu_init_device(struct device *dev) | |||
441 | if (!dev_data) | 349 | if (!dev_data) |
442 | return -ENOMEM; | 350 | return -ENOMEM; |
443 | 351 | ||
444 | alias = amd_iommu_alias_table[dev_data->devid]; | 352 | alias = get_alias(dev); |
353 | |||
445 | if (alias != dev_data->devid) { | 354 | if (alias != dev_data->devid) { |
446 | struct iommu_dev_data *alias_data; | 355 | struct iommu_dev_data *alias_data; |
447 | 356 | ||
@@ -470,6 +379,9 @@ static int iommu_init_device(struct device *dev) | |||
470 | 379 | ||
471 | dev->archdata.iommu = dev_data; | 380 | dev->archdata.iommu = dev_data; |
472 | 381 | ||
382 | iommu_device_link(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev, | ||
383 | dev); | ||
384 | |||
473 | return 0; | 385 | return 0; |
474 | } | 386 | } |
475 | 387 | ||
@@ -489,12 +401,22 @@ static void iommu_ignore_device(struct device *dev) | |||
489 | 401 | ||
490 | static void iommu_uninit_device(struct device *dev) | 402 | static void iommu_uninit_device(struct device *dev) |
491 | { | 403 | { |
404 | struct iommu_dev_data *dev_data = search_dev_data(get_device_id(dev)); | ||
405 | |||
406 | if (!dev_data) | ||
407 | return; | ||
408 | |||
409 | iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev, | ||
410 | dev); | ||
411 | |||
492 | iommu_group_remove_device(dev); | 412 | iommu_group_remove_device(dev); |
493 | 413 | ||
414 | /* Unlink from alias, it may change if another device is re-plugged */ | ||
415 | dev_data->alias_data = NULL; | ||
416 | |||
494 | /* | 417 | /* |
495 | * Nothing to do here - we keep dev_data around for unplugged devices | 418 | * We keep dev_data around for unplugged devices and reuse it when the |
496 | * and reuse it when the device is re-plugged - not doing so would | 419 | * device is re-plugged - not doing so would introduce a ton of races. |
497 | * introduce a ton of races. | ||
498 | */ | 420 | */ |
499 | } | 421 | } |
500 | 422 | ||
@@ -3473,7 +3395,7 @@ static int amd_iommu_domain_has_cap(struct iommu_domain *domain, | |||
3473 | return 0; | 3395 | return 0; |
3474 | } | 3396 | } |
3475 | 3397 | ||
3476 | static struct iommu_ops amd_iommu_ops = { | 3398 | static const struct iommu_ops amd_iommu_ops = { |
3477 | .domain_init = amd_iommu_domain_init, | 3399 | .domain_init = amd_iommu_domain_init, |
3478 | .domain_destroy = amd_iommu_domain_destroy, | 3400 | .domain_destroy = amd_iommu_domain_destroy, |
3479 | .attach_dev = amd_iommu_attach_device, | 3401 | .attach_dev = amd_iommu_attach_device, |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 0e08545d7298..3783e0b44df6 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/msi.h> | 26 | #include <linux/msi.h> |
27 | #include <linux/amd-iommu.h> | 27 | #include <linux/amd-iommu.h> |
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <linux/iommu.h> | ||
29 | #include <asm/pci-direct.h> | 30 | #include <asm/pci-direct.h> |
30 | #include <asm/iommu.h> | 31 | #include <asm/iommu.h> |
31 | #include <asm/gart.h> | 32 | #include <asm/gart.h> |
@@ -1197,6 +1198,39 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) | |||
1197 | iommu->max_counters = (u8) ((val >> 7) & 0xf); | 1198 | iommu->max_counters = (u8) ((val >> 7) & 0xf); |
1198 | } | 1199 | } |
1199 | 1200 | ||
1201 | static ssize_t amd_iommu_show_cap(struct device *dev, | ||
1202 | struct device_attribute *attr, | ||
1203 | char *buf) | ||
1204 | { | ||
1205 | struct amd_iommu *iommu = dev_get_drvdata(dev); | ||
1206 | return sprintf(buf, "%x\n", iommu->cap); | ||
1207 | } | ||
1208 | static DEVICE_ATTR(cap, S_IRUGO, amd_iommu_show_cap, NULL); | ||
1209 | |||
1210 | static ssize_t amd_iommu_show_features(struct device *dev, | ||
1211 | struct device_attribute *attr, | ||
1212 | char *buf) | ||
1213 | { | ||
1214 | struct amd_iommu *iommu = dev_get_drvdata(dev); | ||
1215 | return sprintf(buf, "%llx\n", iommu->features); | ||
1216 | } | ||
1217 | static DEVICE_ATTR(features, S_IRUGO, amd_iommu_show_features, NULL); | ||
1218 | |||
1219 | static struct attribute *amd_iommu_attrs[] = { | ||
1220 | &dev_attr_cap.attr, | ||
1221 | &dev_attr_features.attr, | ||
1222 | NULL, | ||
1223 | }; | ||
1224 | |||
1225 | static struct attribute_group amd_iommu_group = { | ||
1226 | .name = "amd-iommu", | ||
1227 | .attrs = amd_iommu_attrs, | ||
1228 | }; | ||
1229 | |||
1230 | static const struct attribute_group *amd_iommu_groups[] = { | ||
1231 | &amd_iommu_group, | ||
1232 | NULL, | ||
1233 | }; | ||
1200 | 1234 | ||
1201 | static int iommu_init_pci(struct amd_iommu *iommu) | 1235 | static int iommu_init_pci(struct amd_iommu *iommu) |
1202 | { | 1236 | { |
@@ -1297,6 +1331,10 @@ static int iommu_init_pci(struct amd_iommu *iommu) | |||
1297 | 1331 | ||
1298 | amd_iommu_erratum_746_workaround(iommu); | 1332 | amd_iommu_erratum_746_workaround(iommu); |
1299 | 1333 | ||
1334 | iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu, | ||
1335 | amd_iommu_groups, "ivhd%d", | ||
1336 | iommu->index); | ||
1337 | |||
1300 | return pci_enable_device(iommu->dev); | 1338 | return pci_enable_device(iommu->dev); |
1301 | } | 1339 | } |
1302 | 1340 | ||
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index f1a5abf11acf..557a20e533f0 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
@@ -432,7 +432,6 @@ struct iommu_dev_data { | |||
432 | struct iommu_dev_data *alias_data;/* The alias dev_data */ | 432 | struct iommu_dev_data *alias_data;/* The alias dev_data */ |
433 | struct protection_domain *domain; /* Domain the device is bound to */ | 433 | struct protection_domain *domain; /* Domain the device is bound to */ |
434 | atomic_t bind; /* Domain attach reference count */ | 434 | atomic_t bind; /* Domain attach reference count */ |
435 | struct iommu_group *group; /* IOMMU group for virtual aliases */ | ||
436 | u16 devid; /* PCI Device ID */ | 435 | u16 devid; /* PCI Device ID */ |
437 | bool iommu_v2; /* Device can make use of IOMMUv2 */ | 436 | bool iommu_v2; /* Device can make use of IOMMUv2 */ |
438 | bool passthrough; /* Default for device is pt_domain */ | 437 | bool passthrough; /* Default for device is pt_domain */ |
@@ -578,6 +577,9 @@ struct amd_iommu { | |||
578 | /* default dma_ops domain for that IOMMU */ | 577 | /* default dma_ops domain for that IOMMU */ |
579 | struct dma_ops_domain *default_dom; | 578 | struct dma_ops_domain *default_dom; |
580 | 579 | ||
580 | /* IOMMU sysfs device */ | ||
581 | struct device *iommu_dev; | ||
582 | |||
581 | /* | 583 | /* |
582 | * We can't rely on the BIOS to restore all values on reinit, so we | 584 | * We can't rely on the BIOS to restore all values on reinit, so we |
583 | * need to stash them | 585 | * need to stash them |
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 1599354e974d..67727294e6b5 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -1609,7 +1609,7 @@ static void arm_smmu_remove_device(struct device *dev) | |||
1609 | iommu_group_remove_device(dev); | 1609 | iommu_group_remove_device(dev); |
1610 | } | 1610 | } |
1611 | 1611 | ||
1612 | static struct iommu_ops arm_smmu_ops = { | 1612 | static const struct iommu_ops arm_smmu_ops = { |
1613 | .domain_init = arm_smmu_domain_init, | 1613 | .domain_init = arm_smmu_domain_init, |
1614 | .domain_destroy = arm_smmu_domain_destroy, | 1614 | .domain_destroy = arm_smmu_domain_destroy, |
1615 | .attach_dev = arm_smmu_attach_dev, | 1615 | .attach_dev = arm_smmu_attach_dev, |
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index f2eb0bc419f8..4306885f48b1 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/tboot.h> | 38 | #include <linux/tboot.h> |
39 | #include <linux/dmi.h> | 39 | #include <linux/dmi.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/iommu.h> | ||
41 | #include <asm/irq_remapping.h> | 42 | #include <asm/irq_remapping.h> |
42 | #include <asm/iommu_table.h> | 43 | #include <asm/iommu_table.h> |
43 | 44 | ||
@@ -980,6 +981,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
980 | raw_spin_lock_init(&iommu->register_lock); | 981 | raw_spin_lock_init(&iommu->register_lock); |
981 | 982 | ||
982 | drhd->iommu = iommu; | 983 | drhd->iommu = iommu; |
984 | |||
985 | if (intel_iommu_enabled) | ||
986 | iommu->iommu_dev = iommu_device_create(NULL, iommu, | ||
987 | intel_iommu_groups, | ||
988 | iommu->name); | ||
989 | |||
983 | return 0; | 990 | return 0; |
984 | 991 | ||
985 | err_unmap: | 992 | err_unmap: |
@@ -991,6 +998,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
991 | 998 | ||
992 | static void free_iommu(struct intel_iommu *iommu) | 999 | static void free_iommu(struct intel_iommu *iommu) |
993 | { | 1000 | { |
1001 | iommu_device_destroy(iommu->iommu_dev); | ||
1002 | |||
994 | if (iommu->irq) { | 1003 | if (iommu->irq) { |
995 | free_irq(iommu->irq, iommu); | 1004 | free_irq(iommu->irq, iommu); |
996 | irq_set_handler_data(iommu->irq, NULL); | 1005 | irq_set_handler_data(iommu->irq, NULL); |
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 99054d2c040d..d037e87a1fe5 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -1170,7 +1170,7 @@ static void exynos_iommu_remove_device(struct device *dev) | |||
1170 | iommu_group_remove_device(dev); | 1170 | iommu_group_remove_device(dev); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | static struct iommu_ops exynos_iommu_ops = { | 1173 | static const struct iommu_ops exynos_iommu_ops = { |
1174 | .domain_init = exynos_iommu_domain_init, | 1174 | .domain_init = exynos_iommu_domain_init, |
1175 | .domain_destroy = exynos_iommu_domain_destroy, | 1175 | .domain_destroy = exynos_iommu_domain_destroy, |
1176 | .attach_dev = exynos_iommu_attach_device, | 1176 | .attach_dev = exynos_iommu_attach_device, |
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 93072ba44b1d..fd5e9146aee6 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <sysdev/fsl_pci.h> | 38 | #include <sysdev/fsl_pci.h> |
39 | 39 | ||
40 | #include "fsl_pamu_domain.h" | 40 | #include "fsl_pamu_domain.h" |
41 | #include "pci.h" | ||
42 | 41 | ||
43 | /* | 42 | /* |
44 | * Global spinlock that needs to be held while | 43 | * Global spinlock that needs to be held while |
@@ -892,8 +891,6 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, | |||
892 | return ret; | 891 | return ret; |
893 | } | 892 | } |
894 | 893 | ||
895 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | ||
896 | |||
897 | static struct iommu_group *get_device_iommu_group(struct device *dev) | 894 | static struct iommu_group *get_device_iommu_group(struct device *dev) |
898 | { | 895 | { |
899 | struct iommu_group *group; | 896 | struct iommu_group *group; |
@@ -950,74 +947,13 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev) | |||
950 | struct pci_controller *pci_ctl; | 947 | struct pci_controller *pci_ctl; |
951 | bool pci_endpt_partioning; | 948 | bool pci_endpt_partioning; |
952 | struct iommu_group *group = NULL; | 949 | struct iommu_group *group = NULL; |
953 | struct pci_dev *bridge, *dma_pdev = NULL; | ||
954 | 950 | ||
955 | pci_ctl = pci_bus_to_host(pdev->bus); | 951 | pci_ctl = pci_bus_to_host(pdev->bus); |
956 | pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl); | 952 | pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl); |
957 | /* We can partition PCIe devices so assign device group to the device */ | 953 | /* We can partition PCIe devices so assign device group to the device */ |
958 | if (pci_endpt_partioning) { | 954 | if (pci_endpt_partioning) { |
959 | bridge = pci_find_upstream_pcie_bridge(pdev); | 955 | group = iommu_group_get_for_dev(&pdev->dev); |
960 | if (bridge) { | ||
961 | if (pci_is_pcie(bridge)) | ||
962 | dma_pdev = pci_get_domain_bus_and_slot( | ||
963 | pci_domain_nr(pdev->bus), | ||
964 | bridge->subordinate->number, 0); | ||
965 | if (!dma_pdev) | ||
966 | dma_pdev = pci_dev_get(bridge); | ||
967 | } else | ||
968 | dma_pdev = pci_dev_get(pdev); | ||
969 | |||
970 | /* Account for quirked devices */ | ||
971 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | ||
972 | |||
973 | /* | ||
974 | * If it's a multifunction device that does not support our | ||
975 | * required ACS flags, add to the same group as lowest numbered | ||
976 | * function that also does not suport the required ACS flags. | ||
977 | */ | ||
978 | if (dma_pdev->multifunction && | ||
979 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { | ||
980 | u8 i, slot = PCI_SLOT(dma_pdev->devfn); | ||
981 | |||
982 | for (i = 0; i < 8; i++) { | ||
983 | struct pci_dev *tmp; | ||
984 | |||
985 | tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); | ||
986 | if (!tmp) | ||
987 | continue; | ||
988 | |||
989 | if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { | ||
990 | swap_pci_ref(&dma_pdev, tmp); | ||
991 | break; | ||
992 | } | ||
993 | pci_dev_put(tmp); | ||
994 | } | ||
995 | } | ||
996 | |||
997 | /* | ||
998 | * Devices on the root bus go through the iommu. If that's not us, | ||
999 | * find the next upstream device and test ACS up to the root bus. | ||
1000 | * Finding the next device may require skipping virtual buses. | ||
1001 | */ | ||
1002 | while (!pci_is_root_bus(dma_pdev->bus)) { | ||
1003 | struct pci_bus *bus = dma_pdev->bus; | ||
1004 | |||
1005 | while (!bus->self) { | ||
1006 | if (!pci_is_root_bus(bus)) | ||
1007 | bus = bus->parent; | ||
1008 | else | ||
1009 | goto root_bus; | ||
1010 | } | ||
1011 | |||
1012 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) | ||
1013 | break; | ||
1014 | |||
1015 | swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); | ||
1016 | } | ||
1017 | 956 | ||
1018 | root_bus: | ||
1019 | group = get_device_iommu_group(&dma_pdev->dev); | ||
1020 | pci_dev_put(dma_pdev); | ||
1021 | /* | 957 | /* |
1022 | * PCIe controller is not a paritionable entity | 958 | * PCIe controller is not a paritionable entity |
1023 | * free the controller device iommu_group. | 959 | * free the controller device iommu_group. |
@@ -1140,7 +1076,7 @@ static u32 fsl_pamu_get_windows(struct iommu_domain *domain) | |||
1140 | return dma_domain->win_cnt; | 1076 | return dma_domain->win_cnt; |
1141 | } | 1077 | } |
1142 | 1078 | ||
1143 | static struct iommu_ops fsl_pamu_ops = { | 1079 | static const struct iommu_ops fsl_pamu_ops = { |
1144 | .domain_init = fsl_pamu_domain_init, | 1080 | .domain_init = fsl_pamu_domain_init, |
1145 | .domain_destroy = fsl_pamu_domain_destroy, | 1081 | .domain_destroy = fsl_pamu_domain_destroy, |
1146 | .attach_dev = fsl_pamu_attach_device, | 1082 | .attach_dev = fsl_pamu_attach_device, |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c03d4b44bb92..3664d0d00338 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <asm/iommu.h> | 45 | #include <asm/iommu.h> |
46 | 46 | ||
47 | #include "irq_remapping.h" | 47 | #include "irq_remapping.h" |
48 | #include "pci.h" | ||
49 | 48 | ||
50 | #define ROOT_SIZE VTD_PAGE_SIZE | 49 | #define ROOT_SIZE VTD_PAGE_SIZE |
51 | #define CONTEXT_SIZE VTD_PAGE_SIZE | 50 | #define CONTEXT_SIZE VTD_PAGE_SIZE |
@@ -451,7 +450,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); | |||
451 | static DEFINE_SPINLOCK(device_domain_lock); | 450 | static DEFINE_SPINLOCK(device_domain_lock); |
452 | static LIST_HEAD(device_domain_list); | 451 | static LIST_HEAD(device_domain_list); |
453 | 452 | ||
454 | static struct iommu_ops intel_iommu_ops; | 453 | static const struct iommu_ops intel_iommu_ops; |
455 | 454 | ||
456 | static int __init intel_iommu_setup(char *str) | 455 | static int __init intel_iommu_setup(char *str) |
457 | { | 456 | { |
@@ -1840,54 +1839,56 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
1840 | return 0; | 1839 | return 0; |
1841 | } | 1840 | } |
1842 | 1841 | ||
1842 | struct domain_context_mapping_data { | ||
1843 | struct dmar_domain *domain; | ||
1844 | struct intel_iommu *iommu; | ||
1845 | int translation; | ||
1846 | }; | ||
1847 | |||
1848 | static int domain_context_mapping_cb(struct pci_dev *pdev, | ||
1849 | u16 alias, void *opaque) | ||
1850 | { | ||
1851 | struct domain_context_mapping_data *data = opaque; | ||
1852 | |||
1853 | return domain_context_mapping_one(data->domain, data->iommu, | ||
1854 | PCI_BUS_NUM(alias), alias & 0xff, | ||
1855 | data->translation); | ||
1856 | } | ||
1857 | |||
1843 | static int | 1858 | static int |
1844 | domain_context_mapping(struct dmar_domain *domain, struct device *dev, | 1859 | domain_context_mapping(struct dmar_domain *domain, struct device *dev, |
1845 | int translation) | 1860 | int translation) |
1846 | { | 1861 | { |
1847 | int ret; | ||
1848 | struct pci_dev *pdev, *tmp, *parent; | ||
1849 | struct intel_iommu *iommu; | 1862 | struct intel_iommu *iommu; |
1850 | u8 bus, devfn; | 1863 | u8 bus, devfn; |
1864 | struct domain_context_mapping_data data; | ||
1851 | 1865 | ||
1852 | iommu = device_to_iommu(dev, &bus, &devfn); | 1866 | iommu = device_to_iommu(dev, &bus, &devfn); |
1853 | if (!iommu) | 1867 | if (!iommu) |
1854 | return -ENODEV; | 1868 | return -ENODEV; |
1855 | 1869 | ||
1856 | ret = domain_context_mapping_one(domain, iommu, bus, devfn, | 1870 | if (!dev_is_pci(dev)) |
1857 | translation); | 1871 | return domain_context_mapping_one(domain, iommu, bus, devfn, |
1858 | if (ret || !dev_is_pci(dev)) | ||
1859 | return ret; | ||
1860 | |||
1861 | /* dependent device mapping */ | ||
1862 | pdev = to_pci_dev(dev); | ||
1863 | tmp = pci_find_upstream_pcie_bridge(pdev); | ||
1864 | if (!tmp) | ||
1865 | return 0; | ||
1866 | /* Secondary interface's bus number and devfn 0 */ | ||
1867 | parent = pdev->bus->self; | ||
1868 | while (parent != tmp) { | ||
1869 | ret = domain_context_mapping_one(domain, iommu, | ||
1870 | parent->bus->number, | ||
1871 | parent->devfn, translation); | ||
1872 | if (ret) | ||
1873 | return ret; | ||
1874 | parent = parent->bus->self; | ||
1875 | } | ||
1876 | if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */ | ||
1877 | return domain_context_mapping_one(domain, iommu, | ||
1878 | tmp->subordinate->number, 0, | ||
1879 | translation); | ||
1880 | else /* this is a legacy PCI bridge */ | ||
1881 | return domain_context_mapping_one(domain, iommu, | ||
1882 | tmp->bus->number, | ||
1883 | tmp->devfn, | ||
1884 | translation); | 1872 | translation); |
1873 | |||
1874 | data.domain = domain; | ||
1875 | data.iommu = iommu; | ||
1876 | data.translation = translation; | ||
1877 | |||
1878 | return pci_for_each_dma_alias(to_pci_dev(dev), | ||
1879 | &domain_context_mapping_cb, &data); | ||
1880 | } | ||
1881 | |||
1882 | static int domain_context_mapped_cb(struct pci_dev *pdev, | ||
1883 | u16 alias, void *opaque) | ||
1884 | { | ||
1885 | struct intel_iommu *iommu = opaque; | ||
1886 | |||
1887 | return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff); | ||
1885 | } | 1888 | } |
1886 | 1889 | ||
1887 | static int domain_context_mapped(struct device *dev) | 1890 | static int domain_context_mapped(struct device *dev) |
1888 | { | 1891 | { |
1889 | int ret; | ||
1890 | struct pci_dev *pdev, *tmp, *parent; | ||
1891 | struct intel_iommu *iommu; | 1892 | struct intel_iommu *iommu; |
1892 | u8 bus, devfn; | 1893 | u8 bus, devfn; |
1893 | 1894 | ||
@@ -1895,30 +1896,11 @@ static int domain_context_mapped(struct device *dev) | |||
1895 | if (!iommu) | 1896 | if (!iommu) |
1896 | return -ENODEV; | 1897 | return -ENODEV; |
1897 | 1898 | ||
1898 | ret = device_context_mapped(iommu, bus, devfn); | 1899 | if (!dev_is_pci(dev)) |
1899 | if (!ret || !dev_is_pci(dev)) | 1900 | return device_context_mapped(iommu, bus, devfn); |
1900 | return ret; | ||
1901 | 1901 | ||
1902 | /* dependent device mapping */ | 1902 | return !pci_for_each_dma_alias(to_pci_dev(dev), |
1903 | pdev = to_pci_dev(dev); | 1903 | domain_context_mapped_cb, iommu); |
1904 | tmp = pci_find_upstream_pcie_bridge(pdev); | ||
1905 | if (!tmp) | ||
1906 | return ret; | ||
1907 | /* Secondary interface's bus number and devfn 0 */ | ||
1908 | parent = pdev->bus->self; | ||
1909 | while (parent != tmp) { | ||
1910 | ret = device_context_mapped(iommu, parent->bus->number, | ||
1911 | parent->devfn); | ||
1912 | if (!ret) | ||
1913 | return ret; | ||
1914 | parent = parent->bus->self; | ||
1915 | } | ||
1916 | if (pci_is_pcie(tmp)) | ||
1917 | return device_context_mapped(iommu, tmp->subordinate->number, | ||
1918 | 0); | ||
1919 | else | ||
1920 | return device_context_mapped(iommu, tmp->bus->number, | ||
1921 | tmp->devfn); | ||
1922 | } | 1904 | } |
1923 | 1905 | ||
1924 | /* Returns a number of VTD pages, but aligned to MM page size */ | 1906 | /* Returns a number of VTD pages, but aligned to MM page size */ |
@@ -2205,80 +2187,86 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu, | |||
2205 | return domain; | 2187 | return domain; |
2206 | } | 2188 | } |
2207 | 2189 | ||
2190 | static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque) | ||
2191 | { | ||
2192 | *(u16 *)opaque = alias; | ||
2193 | return 0; | ||
2194 | } | ||
2195 | |||
2208 | /* domain is initialized */ | 2196 | /* domain is initialized */ |
2209 | static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw) | 2197 | static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw) |
2210 | { | 2198 | { |
2211 | struct dmar_domain *domain, *free = NULL; | 2199 | struct dmar_domain *domain, *tmp; |
2212 | struct intel_iommu *iommu = NULL; | 2200 | struct intel_iommu *iommu; |
2213 | struct device_domain_info *info; | 2201 | struct device_domain_info *info; |
2214 | struct pci_dev *dev_tmp = NULL; | 2202 | u16 dma_alias; |
2215 | unsigned long flags; | 2203 | unsigned long flags; |
2216 | u8 bus, devfn; | 2204 | u8 bus, devfn; |
2217 | u8 bridge_bus = 0, bridge_devfn = 0; | ||
2218 | 2205 | ||
2219 | domain = find_domain(dev); | 2206 | domain = find_domain(dev); |
2220 | if (domain) | 2207 | if (domain) |
2221 | return domain; | 2208 | return domain; |
2222 | 2209 | ||
2210 | iommu = device_to_iommu(dev, &bus, &devfn); | ||
2211 | if (!iommu) | ||
2212 | return NULL; | ||
2213 | |||
2223 | if (dev_is_pci(dev)) { | 2214 | if (dev_is_pci(dev)) { |
2224 | struct pci_dev *pdev = to_pci_dev(dev); | 2215 | struct pci_dev *pdev = to_pci_dev(dev); |
2225 | u16 segment; | ||
2226 | 2216 | ||
2227 | segment = pci_domain_nr(pdev->bus); | 2217 | pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias); |
2228 | dev_tmp = pci_find_upstream_pcie_bridge(pdev); | 2218 | |
2229 | if (dev_tmp) { | 2219 | spin_lock_irqsave(&device_domain_lock, flags); |
2230 | if (pci_is_pcie(dev_tmp)) { | 2220 | info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus), |
2231 | bridge_bus = dev_tmp->subordinate->number; | 2221 | PCI_BUS_NUM(dma_alias), |
2232 | bridge_devfn = 0; | 2222 | dma_alias & 0xff); |
2233 | } else { | 2223 | if (info) { |
2234 | bridge_bus = dev_tmp->bus->number; | 2224 | iommu = info->iommu; |
2235 | bridge_devfn = dev_tmp->devfn; | 2225 | domain = info->domain; |
2236 | } | ||
2237 | spin_lock_irqsave(&device_domain_lock, flags); | ||
2238 | info = dmar_search_domain_by_dev_info(segment, | ||
2239 | bridge_bus, | ||
2240 | bridge_devfn); | ||
2241 | if (info) { | ||
2242 | iommu = info->iommu; | ||
2243 | domain = info->domain; | ||
2244 | } | ||
2245 | spin_unlock_irqrestore(&device_domain_lock, flags); | ||
2246 | /* pcie-pci bridge already has a domain, uses it */ | ||
2247 | if (info) | ||
2248 | goto found_domain; | ||
2249 | } | 2226 | } |
2250 | } | 2227 | spin_unlock_irqrestore(&device_domain_lock, flags); |
2251 | 2228 | ||
2252 | iommu = device_to_iommu(dev, &bus, &devfn); | 2229 | /* DMA alias already has a domain, uses it */ |
2253 | if (!iommu) | 2230 | if (info) |
2254 | goto error; | 2231 | goto found_domain; |
2232 | } | ||
2255 | 2233 | ||
2256 | /* Allocate and initialize new domain for the device */ | 2234 | /* Allocate and initialize new domain for the device */ |
2257 | domain = alloc_domain(false); | 2235 | domain = alloc_domain(false); |
2258 | if (!domain) | 2236 | if (!domain) |
2259 | goto error; | 2237 | return NULL; |
2238 | |||
2260 | if (iommu_attach_domain(domain, iommu)) { | 2239 | if (iommu_attach_domain(domain, iommu)) { |
2261 | free_domain_mem(domain); | 2240 | free_domain_mem(domain); |
2262 | domain = NULL; | 2241 | return NULL; |
2263 | goto error; | ||
2264 | } | 2242 | } |
2265 | free = domain; | ||
2266 | if (domain_init(domain, gaw)) | ||
2267 | goto error; | ||
2268 | 2243 | ||
2269 | /* register pcie-to-pci device */ | 2244 | if (domain_init(domain, gaw)) { |
2270 | if (dev_tmp) { | 2245 | domain_exit(domain); |
2271 | domain = dmar_insert_dev_info(iommu, bridge_bus, bridge_devfn, | 2246 | return NULL; |
2272 | NULL, domain); | 2247 | } |
2248 | |||
2249 | /* register PCI DMA alias device */ | ||
2250 | if (dev_is_pci(dev)) { | ||
2251 | tmp = dmar_insert_dev_info(iommu, PCI_BUS_NUM(dma_alias), | ||
2252 | dma_alias & 0xff, NULL, domain); | ||
2253 | |||
2254 | if (!tmp || tmp != domain) { | ||
2255 | domain_exit(domain); | ||
2256 | domain = tmp; | ||
2257 | } | ||
2258 | |||
2273 | if (!domain) | 2259 | if (!domain) |
2274 | goto error; | 2260 | return NULL; |
2275 | } | 2261 | } |
2276 | 2262 | ||
2277 | found_domain: | 2263 | found_domain: |
2278 | domain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain); | 2264 | tmp = dmar_insert_dev_info(iommu, bus, devfn, dev, domain); |
2279 | error: | 2265 | |
2280 | if (free != domain) | 2266 | if (!tmp || tmp != domain) { |
2281 | domain_exit(free); | 2267 | domain_exit(domain); |
2268 | domain = tmp; | ||
2269 | } | ||
2282 | 2270 | ||
2283 | return domain; | 2271 | return domain; |
2284 | } | 2272 | } |
@@ -3953,6 +3941,63 @@ static struct notifier_block intel_iommu_memory_nb = { | |||
3953 | .priority = 0 | 3941 | .priority = 0 |
3954 | }; | 3942 | }; |
3955 | 3943 | ||
3944 | |||
3945 | static ssize_t intel_iommu_show_version(struct device *dev, | ||
3946 | struct device_attribute *attr, | ||
3947 | char *buf) | ||
3948 | { | ||
3949 | struct intel_iommu *iommu = dev_get_drvdata(dev); | ||
3950 | u32 ver = readl(iommu->reg + DMAR_VER_REG); | ||
3951 | return sprintf(buf, "%d:%d\n", | ||
3952 | DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver)); | ||
3953 | } | ||
3954 | static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL); | ||
3955 | |||
3956 | static ssize_t intel_iommu_show_address(struct device *dev, | ||
3957 | struct device_attribute *attr, | ||
3958 | char *buf) | ||
3959 | { | ||
3960 | struct intel_iommu *iommu = dev_get_drvdata(dev); | ||
3961 | return sprintf(buf, "%llx\n", iommu->reg_phys); | ||
3962 | } | ||
3963 | static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL); | ||
3964 | |||
3965 | static ssize_t intel_iommu_show_cap(struct device *dev, | ||
3966 | struct device_attribute *attr, | ||
3967 | char *buf) | ||
3968 | { | ||
3969 | struct intel_iommu *iommu = dev_get_drvdata(dev); | ||
3970 | return sprintf(buf, "%llx\n", iommu->cap); | ||
3971 | } | ||
3972 | static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL); | ||
3973 | |||
3974 | static ssize_t intel_iommu_show_ecap(struct device *dev, | ||
3975 | struct device_attribute *attr, | ||
3976 | char *buf) | ||
3977 | { | ||
3978 | struct intel_iommu *iommu = dev_get_drvdata(dev); | ||
3979 | return sprintf(buf, "%llx\n", iommu->ecap); | ||
3980 | } | ||
3981 | static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL); | ||
3982 | |||
3983 | static struct attribute *intel_iommu_attrs[] = { | ||
3984 | &dev_attr_version.attr, | ||
3985 | &dev_attr_address.attr, | ||
3986 | &dev_attr_cap.attr, | ||
3987 | &dev_attr_ecap.attr, | ||
3988 | NULL, | ||
3989 | }; | ||
3990 | |||
3991 | static struct attribute_group intel_iommu_group = { | ||
3992 | .name = "intel-iommu", | ||
3993 | .attrs = intel_iommu_attrs, | ||
3994 | }; | ||
3995 | |||
3996 | const struct attribute_group *intel_iommu_groups[] = { | ||
3997 | &intel_iommu_group, | ||
3998 | NULL, | ||
3999 | }; | ||
4000 | |||
3956 | int __init intel_iommu_init(void) | 4001 | int __init intel_iommu_init(void) |
3957 | { | 4002 | { |
3958 | int ret = -ENODEV; | 4003 | int ret = -ENODEV; |
@@ -4024,6 +4069,11 @@ int __init intel_iommu_init(void) | |||
4024 | 4069 | ||
4025 | init_iommu_pm_ops(); | 4070 | init_iommu_pm_ops(); |
4026 | 4071 | ||
4072 | for_each_active_iommu(iommu, drhd) | ||
4073 | iommu->iommu_dev = iommu_device_create(NULL, iommu, | ||
4074 | intel_iommu_groups, | ||
4075 | iommu->name); | ||
4076 | |||
4027 | bus_set_iommu(&pci_bus_type, &intel_iommu_ops); | 4077 | bus_set_iommu(&pci_bus_type, &intel_iommu_ops); |
4028 | bus_register_notifier(&pci_bus_type, &device_nb); | 4078 | bus_register_notifier(&pci_bus_type, &device_nb); |
4029 | if (si_domain && !hw_pass_through) | 4079 | if (si_domain && !hw_pass_through) |
@@ -4042,33 +4092,27 @@ out_free_dmar: | |||
4042 | return ret; | 4092 | return ret; |
4043 | } | 4093 | } |
4044 | 4094 | ||
4095 | static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque) | ||
4096 | { | ||
4097 | struct intel_iommu *iommu = opaque; | ||
4098 | |||
4099 | iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff); | ||
4100 | return 0; | ||
4101 | } | ||
4102 | |||
4103 | /* | ||
4104 | * NB - intel-iommu lacks any sort of reference counting for the users of | ||
4105 | * dependent devices. If multiple endpoints have intersecting dependent | ||
4106 | * devices, unbinding the driver from any one of them will possibly leave | ||
4107 | * the others unable to operate. | ||
4108 | */ | ||
4045 | static void iommu_detach_dependent_devices(struct intel_iommu *iommu, | 4109 | static void iommu_detach_dependent_devices(struct intel_iommu *iommu, |
4046 | struct device *dev) | 4110 | struct device *dev) |
4047 | { | 4111 | { |
4048 | struct pci_dev *tmp, *parent, *pdev; | ||
4049 | |||
4050 | if (!iommu || !dev || !dev_is_pci(dev)) | 4112 | if (!iommu || !dev || !dev_is_pci(dev)) |
4051 | return; | 4113 | return; |
4052 | 4114 | ||
4053 | pdev = to_pci_dev(dev); | 4115 | pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu); |
4054 | |||
4055 | /* dependent device detach */ | ||
4056 | tmp = pci_find_upstream_pcie_bridge(pdev); | ||
4057 | /* Secondary interface's bus number and devfn 0 */ | ||
4058 | if (tmp) { | ||
4059 | parent = pdev->bus->self; | ||
4060 | while (parent != tmp) { | ||
4061 | iommu_detach_dev(iommu, parent->bus->number, | ||
4062 | parent->devfn); | ||
4063 | parent = parent->bus->self; | ||
4064 | } | ||
4065 | if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */ | ||
4066 | iommu_detach_dev(iommu, | ||
4067 | tmp->subordinate->number, 0); | ||
4068 | else /* this is a legacy PCI bridge */ | ||
4069 | iommu_detach_dev(iommu, tmp->bus->number, | ||
4070 | tmp->devfn); | ||
4071 | } | ||
4072 | } | 4116 | } |
4073 | 4117 | ||
4074 | static void domain_remove_one_dev_info(struct dmar_domain *domain, | 4118 | static void domain_remove_one_dev_info(struct dmar_domain *domain, |
@@ -4370,99 +4414,42 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain, | |||
4370 | return 0; | 4414 | return 0; |
4371 | } | 4415 | } |
4372 | 4416 | ||
4373 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | ||
4374 | |||
4375 | static int intel_iommu_add_device(struct device *dev) | 4417 | static int intel_iommu_add_device(struct device *dev) |
4376 | { | 4418 | { |
4377 | struct pci_dev *pdev = to_pci_dev(dev); | 4419 | struct intel_iommu *iommu; |
4378 | struct pci_dev *bridge, *dma_pdev = NULL; | ||
4379 | struct iommu_group *group; | 4420 | struct iommu_group *group; |
4380 | int ret; | ||
4381 | u8 bus, devfn; | 4421 | u8 bus, devfn; |
4382 | 4422 | ||
4383 | if (!device_to_iommu(dev, &bus, &devfn)) | 4423 | iommu = device_to_iommu(dev, &bus, &devfn); |
4424 | if (!iommu) | ||
4384 | return -ENODEV; | 4425 | return -ENODEV; |
4385 | 4426 | ||
4386 | bridge = pci_find_upstream_pcie_bridge(pdev); | 4427 | iommu_device_link(iommu->iommu_dev, dev); |
4387 | if (bridge) { | ||
4388 | if (pci_is_pcie(bridge)) | ||
4389 | dma_pdev = pci_get_domain_bus_and_slot( | ||
4390 | pci_domain_nr(pdev->bus), | ||
4391 | bridge->subordinate->number, 0); | ||
4392 | if (!dma_pdev) | ||
4393 | dma_pdev = pci_dev_get(bridge); | ||
4394 | } else | ||
4395 | dma_pdev = pci_dev_get(pdev); | ||
4396 | |||
4397 | /* Account for quirked devices */ | ||
4398 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | ||
4399 | |||
4400 | /* | ||
4401 | * If it's a multifunction device that does not support our | ||
4402 | * required ACS flags, add to the same group as lowest numbered | ||
4403 | * function that also does not suport the required ACS flags. | ||
4404 | */ | ||
4405 | if (dma_pdev->multifunction && | ||
4406 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { | ||
4407 | u8 i, slot = PCI_SLOT(dma_pdev->devfn); | ||
4408 | |||
4409 | for (i = 0; i < 8; i++) { | ||
4410 | struct pci_dev *tmp; | ||
4411 | |||
4412 | tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); | ||
4413 | if (!tmp) | ||
4414 | continue; | ||
4415 | |||
4416 | if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { | ||
4417 | swap_pci_ref(&dma_pdev, tmp); | ||
4418 | break; | ||
4419 | } | ||
4420 | pci_dev_put(tmp); | ||
4421 | } | ||
4422 | } | ||
4423 | |||
4424 | /* | ||
4425 | * Devices on the root bus go through the iommu. If that's not us, | ||
4426 | * find the next upstream device and test ACS up to the root bus. | ||
4427 | * Finding the next device may require skipping virtual buses. | ||
4428 | */ | ||
4429 | while (!pci_is_root_bus(dma_pdev->bus)) { | ||
4430 | struct pci_bus *bus = dma_pdev->bus; | ||
4431 | |||
4432 | while (!bus->self) { | ||
4433 | if (!pci_is_root_bus(bus)) | ||
4434 | bus = bus->parent; | ||
4435 | else | ||
4436 | goto root_bus; | ||
4437 | } | ||
4438 | 4428 | ||
4439 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) | 4429 | group = iommu_group_get_for_dev(dev); |
4440 | break; | ||
4441 | 4430 | ||
4442 | swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); | 4431 | if (IS_ERR(group)) |
4443 | } | 4432 | return PTR_ERR(group); |
4444 | |||
4445 | root_bus: | ||
4446 | group = iommu_group_get(&dma_pdev->dev); | ||
4447 | pci_dev_put(dma_pdev); | ||
4448 | if (!group) { | ||
4449 | group = iommu_group_alloc(); | ||
4450 | if (IS_ERR(group)) | ||
4451 | return PTR_ERR(group); | ||
4452 | } | ||
4453 | |||
4454 | ret = iommu_group_add_device(group, dev); | ||
4455 | 4433 | ||
4456 | iommu_group_put(group); | 4434 | iommu_group_put(group); |
4457 | return ret; | 4435 | return 0; |
4458 | } | 4436 | } |
4459 | 4437 | ||
4460 | static void intel_iommu_remove_device(struct device *dev) | 4438 | static void intel_iommu_remove_device(struct device *dev) |
4461 | { | 4439 | { |
4440 | struct intel_iommu *iommu; | ||
4441 | u8 bus, devfn; | ||
4442 | |||
4443 | iommu = device_to_iommu(dev, &bus, &devfn); | ||
4444 | if (!iommu) | ||
4445 | return; | ||
4446 | |||
4462 | iommu_group_remove_device(dev); | 4447 | iommu_group_remove_device(dev); |
4448 | |||
4449 | iommu_device_unlink(iommu->iommu_dev, dev); | ||
4463 | } | 4450 | } |
4464 | 4451 | ||
4465 | static struct iommu_ops intel_iommu_ops = { | 4452 | static const struct iommu_ops intel_iommu_ops = { |
4466 | .domain_init = intel_iommu_domain_init, | 4453 | .domain_init = intel_iommu_domain_init, |
4467 | .domain_destroy = intel_iommu_domain_destroy, | 4454 | .domain_destroy = intel_iommu_domain_destroy, |
4468 | .attach_dev = intel_iommu_attach_device, | 4455 | .attach_dev = intel_iommu_attach_device, |
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 9b174893f0f5..757e0b0d19ff 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c | |||
@@ -369,29 +369,52 @@ static int set_hpet_sid(struct irte *irte, u8 id) | |||
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
371 | 371 | ||
372 | struct set_msi_sid_data { | ||
373 | struct pci_dev *pdev; | ||
374 | u16 alias; | ||
375 | }; | ||
376 | |||
377 | static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque) | ||
378 | { | ||
379 | struct set_msi_sid_data *data = opaque; | ||
380 | |||
381 | data->pdev = pdev; | ||
382 | data->alias = alias; | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
372 | static int set_msi_sid(struct irte *irte, struct pci_dev *dev) | 387 | static int set_msi_sid(struct irte *irte, struct pci_dev *dev) |
373 | { | 388 | { |
374 | struct pci_dev *bridge; | 389 | struct set_msi_sid_data data; |
375 | 390 | ||
376 | if (!irte || !dev) | 391 | if (!irte || !dev) |
377 | return -1; | 392 | return -1; |
378 | 393 | ||
379 | /* PCIe device or Root Complex integrated PCI device */ | 394 | pci_for_each_dma_alias(dev, set_msi_sid_cb, &data); |
380 | if (pci_is_pcie(dev) || !dev->bus->parent) { | ||
381 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, | ||
382 | (dev->bus->number << 8) | dev->devfn); | ||
383 | return 0; | ||
384 | } | ||
385 | 395 | ||
386 | bridge = pci_find_upstream_pcie_bridge(dev); | 396 | /* |
387 | if (bridge) { | 397 | * DMA alias provides us with a PCI device and alias. The only case |
388 | if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */ | 398 | * where the it will return an alias on a different bus than the |
389 | set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, | 399 | * device is the case of a PCIe-to-PCI bridge, where the alias is for |
390 | (bridge->bus->number << 8) | dev->bus->number); | 400 | * the subordinate bus. In this case we can only verify the bus. |
391 | else /* this is a legacy PCI bridge */ | 401 | * |
392 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, | 402 | * If the alias device is on a different bus than our source device |
393 | (bridge->bus->number << 8) | bridge->devfn); | 403 | * then we have a topology based alias, use it. |
394 | } | 404 | * |
405 | * Otherwise, the alias is for a device DMA quirk and we cannot | ||
406 | * assume that MSI uses the same requester ID. Therefore use the | ||
407 | * original device. | ||
408 | */ | ||
409 | if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number) | ||
410 | set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, | ||
411 | PCI_DEVID(PCI_BUS_NUM(data.alias), | ||
412 | dev->bus->number)); | ||
413 | else if (data.pdev->bus->number != dev->bus->number) | ||
414 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias); | ||
415 | else | ||
416 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, | ||
417 | PCI_DEVID(dev->bus->number, dev->devfn)); | ||
395 | 418 | ||
396 | return 0; | 419 | return 0; |
397 | } | 420 | } |
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c new file mode 100644 index 000000000000..39b2d9127dbf --- /dev/null +++ b/drivers/iommu/iommu-sysfs.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * IOMMU sysfs class support | ||
3 | * | ||
4 | * Copyright (C) 2014 Red Hat, Inc. All rights reserved. | ||
5 | * Author: Alex Williamson <alex.williamson@redhat.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/iommu.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | /* | ||
18 | * We provide a common class "devices" group which initially has no attributes. | ||
19 | * As devices are added to the IOMMU, we'll add links to the group. | ||
20 | */ | ||
21 | static struct attribute *devices_attr[] = { | ||
22 | NULL, | ||
23 | }; | ||
24 | |||
25 | static const struct attribute_group iommu_devices_attr_group = { | ||
26 | .name = "devices", | ||
27 | .attrs = devices_attr, | ||
28 | }; | ||
29 | |||
30 | static const struct attribute_group *iommu_dev_groups[] = { | ||
31 | &iommu_devices_attr_group, | ||
32 | NULL, | ||
33 | }; | ||
34 | |||
35 | static void iommu_release_device(struct device *dev) | ||
36 | { | ||
37 | kfree(dev); | ||
38 | } | ||
39 | |||
40 | static struct class iommu_class = { | ||
41 | .name = "iommu", | ||
42 | .dev_release = iommu_release_device, | ||
43 | .dev_groups = iommu_dev_groups, | ||
44 | }; | ||
45 | |||
46 | static int __init iommu_dev_init(void) | ||
47 | { | ||
48 | return class_register(&iommu_class); | ||
49 | } | ||
50 | postcore_initcall(iommu_dev_init); | ||
51 | |||
52 | /* | ||
53 | * Create an IOMMU device and return a pointer to it. IOMMU specific | ||
54 | * attributes can be provided as an attribute group, allowing a unique | ||
55 | * namespace per IOMMU type. | ||
56 | */ | ||
57 | struct device *iommu_device_create(struct device *parent, void *drvdata, | ||
58 | const struct attribute_group **groups, | ||
59 | const char *fmt, ...) | ||
60 | { | ||
61 | struct device *dev; | ||
62 | va_list vargs; | ||
63 | int ret; | ||
64 | |||
65 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
66 | if (!dev) | ||
67 | return ERR_PTR(-ENOMEM); | ||
68 | |||
69 | device_initialize(dev); | ||
70 | |||
71 | dev->class = &iommu_class; | ||
72 | dev->parent = parent; | ||
73 | dev->groups = groups; | ||
74 | dev_set_drvdata(dev, drvdata); | ||
75 | |||
76 | va_start(vargs, fmt); | ||
77 | ret = kobject_set_name_vargs(&dev->kobj, fmt, vargs); | ||
78 | va_end(vargs); | ||
79 | if (ret) | ||
80 | goto error; | ||
81 | |||
82 | ret = device_add(dev); | ||
83 | if (ret) | ||
84 | goto error; | ||
85 | |||
86 | return dev; | ||
87 | |||
88 | error: | ||
89 | put_device(dev); | ||
90 | return ERR_PTR(ret); | ||
91 | } | ||
92 | |||
93 | void iommu_device_destroy(struct device *dev) | ||
94 | { | ||
95 | if (!dev || IS_ERR(dev)) | ||
96 | return; | ||
97 | |||
98 | device_unregister(dev); | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * IOMMU drivers can indicate a device is managed by a given IOMMU using | ||
103 | * this interface. A link to the device will be created in the "devices" | ||
104 | * directory of the IOMMU device in sysfs and an "iommu" link will be | ||
105 | * created under the linked device, pointing back at the IOMMU device. | ||
106 | */ | ||
107 | int iommu_device_link(struct device *dev, struct device *link) | ||
108 | { | ||
109 | int ret; | ||
110 | |||
111 | if (!dev || IS_ERR(dev)) | ||
112 | return -ENODEV; | ||
113 | |||
114 | ret = sysfs_add_link_to_group(&dev->kobj, "devices", | ||
115 | &link->kobj, dev_name(link)); | ||
116 | if (ret) | ||
117 | return ret; | ||
118 | |||
119 | ret = sysfs_create_link_nowarn(&link->kobj, &dev->kobj, "iommu"); | ||
120 | if (ret) | ||
121 | sysfs_remove_link_from_group(&dev->kobj, "devices", | ||
122 | dev_name(link)); | ||
123 | |||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | void iommu_device_unlink(struct device *dev, struct device *link) | ||
128 | { | ||
129 | if (!dev || IS_ERR(dev)) | ||
130 | return; | ||
131 | |||
132 | sysfs_remove_link(&link->kobj, "iommu"); | ||
133 | sysfs_remove_link_from_group(&dev->kobj, "devices", dev_name(link)); | ||
134 | } | ||
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index e5555fcfe703..169836020208 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -29,12 +29,17 @@ | |||
29 | #include <linux/idr.h> | 29 | #include <linux/idr.h> |
30 | #include <linux/notifier.h> | 30 | #include <linux/notifier.h> |
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/pci.h> | ||
32 | #include <trace/events/iommu.h> | 33 | #include <trace/events/iommu.h> |
33 | 34 | ||
34 | static struct kset *iommu_group_kset; | 35 | static struct kset *iommu_group_kset; |
35 | static struct ida iommu_group_ida; | 36 | static struct ida iommu_group_ida; |
36 | static struct mutex iommu_group_mutex; | 37 | static struct mutex iommu_group_mutex; |
37 | 38 | ||
39 | struct iommu_callback_data { | ||
40 | const struct iommu_ops *ops; | ||
41 | }; | ||
42 | |||
38 | struct iommu_group { | 43 | struct iommu_group { |
39 | struct kobject kobj; | 44 | struct kobject kobj; |
40 | struct kobject *devices_kobj; | 45 | struct kobject *devices_kobj; |
@@ -514,9 +519,191 @@ int iommu_group_id(struct iommu_group *group) | |||
514 | } | 519 | } |
515 | EXPORT_SYMBOL_GPL(iommu_group_id); | 520 | EXPORT_SYMBOL_GPL(iommu_group_id); |
516 | 521 | ||
522 | /* | ||
523 | * To consider a PCI device isolated, we require ACS to support Source | ||
524 | * Validation, Request Redirection, Completer Redirection, and Upstream | ||
525 | * Forwarding. This effectively means that devices cannot spoof their | ||
526 | * requester ID, requests and completions cannot be redirected, and all | ||
527 | * transactions are forwarded upstream, even as it passes through a | ||
528 | * bridge where the target device is downstream. | ||
529 | */ | ||
530 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | ||
531 | |||
532 | struct group_for_pci_data { | ||
533 | struct pci_dev *pdev; | ||
534 | struct iommu_group *group; | ||
535 | }; | ||
536 | |||
537 | /* | ||
538 | * DMA alias iterator callback, return the last seen device. Stop and return | ||
539 | * the IOMMU group if we find one along the way. | ||
540 | */ | ||
541 | static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque) | ||
542 | { | ||
543 | struct group_for_pci_data *data = opaque; | ||
544 | |||
545 | data->pdev = pdev; | ||
546 | data->group = iommu_group_get(&pdev->dev); | ||
547 | |||
548 | return data->group != NULL; | ||
549 | } | ||
550 | |||
551 | /* | ||
552 | * Use standard PCI bus topology, isolation features, and DMA alias quirks | ||
553 | * to find or create an IOMMU group for a device. | ||
554 | */ | ||
555 | static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev) | ||
556 | { | ||
557 | struct group_for_pci_data data; | ||
558 | struct pci_bus *bus; | ||
559 | struct iommu_group *group = NULL; | ||
560 | struct pci_dev *tmp; | ||
561 | |||
562 | /* | ||
563 | * Find the upstream DMA alias for the device. A device must not | ||
564 | * be aliased due to topology in order to have its own IOMMU group. | ||
565 | * If we find an alias along the way that already belongs to a | ||
566 | * group, use it. | ||
567 | */ | ||
568 | if (pci_for_each_dma_alias(pdev, get_pci_alias_or_group, &data)) | ||
569 | return data.group; | ||
570 | |||
571 | pdev = data.pdev; | ||
572 | |||
573 | /* | ||
574 | * Continue upstream from the point of minimum IOMMU granularity | ||
575 | * due to aliases to the point where devices are protected from | ||
576 | * peer-to-peer DMA by PCI ACS. Again, if we find an existing | ||
577 | * group, use it. | ||
578 | */ | ||
579 | for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) { | ||
580 | if (!bus->self) | ||
581 | continue; | ||
582 | |||
583 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) | ||
584 | break; | ||
585 | |||
586 | pdev = bus->self; | ||
587 | |||
588 | group = iommu_group_get(&pdev->dev); | ||
589 | if (group) | ||
590 | return group; | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * Next we need to consider DMA alias quirks. If one device aliases | ||
595 | * to another, they should be grouped together. It's theoretically | ||
596 | * possible that aliases could create chains of devices where each | ||
597 | * device aliases another device. If we then factor in multifunction | ||
598 | * ACS grouping requirements, each alias could incorporate a new slot | ||
599 | * with multiple functions, each with aliases. This is all extremely | ||
600 | * unlikely as DMA alias quirks are typically only used for PCIe | ||
601 | * devices where we usually have a single slot per bus. Furthermore, | ||
602 | * the alias quirk is usually to another function within the slot | ||
603 | * (and ACS multifunction is not supported) or to a different slot | ||
604 | * that doesn't physically exist. The likely scenario is therefore | ||
605 | * that everything on the bus gets grouped together. To reduce the | ||
606 | * problem space, share the IOMMU group for all devices on the bus | ||
607 | * if a DMA alias quirk is present on the bus. | ||
608 | */ | ||
609 | tmp = NULL; | ||
610 | for_each_pci_dev(tmp) { | ||
611 | if (tmp->bus != pdev->bus || | ||
612 | !(tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) | ||
613 | continue; | ||
614 | |||
615 | pci_dev_put(tmp); | ||
616 | tmp = NULL; | ||
617 | |||
618 | /* We have an alias quirk, search for an existing group */ | ||
619 | for_each_pci_dev(tmp) { | ||
620 | struct iommu_group *group_tmp; | ||
621 | |||
622 | if (tmp->bus != pdev->bus) | ||
623 | continue; | ||
624 | |||
625 | group_tmp = iommu_group_get(&tmp->dev); | ||
626 | if (!group) { | ||
627 | group = group_tmp; | ||
628 | continue; | ||
629 | } | ||
630 | |||
631 | if (group_tmp) { | ||
632 | WARN_ON(group != group_tmp); | ||
633 | iommu_group_put(group_tmp); | ||
634 | } | ||
635 | } | ||
636 | |||
637 | return group ? group : iommu_group_alloc(); | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Non-multifunction devices or multifunction devices supporting | ||
642 | * ACS get their own group. | ||
643 | */ | ||
644 | if (!pdev->multifunction || pci_acs_enabled(pdev, REQ_ACS_FLAGS)) | ||
645 | return iommu_group_alloc(); | ||
646 | |||
647 | /* | ||
648 | * Multifunction devices not supporting ACS share a group with other | ||
649 | * similar devices in the same slot. | ||
650 | */ | ||
651 | tmp = NULL; | ||
652 | for_each_pci_dev(tmp) { | ||
653 | if (tmp == pdev || tmp->bus != pdev->bus || | ||
654 | PCI_SLOT(tmp->devfn) != PCI_SLOT(pdev->devfn) || | ||
655 | pci_acs_enabled(tmp, REQ_ACS_FLAGS)) | ||
656 | continue; | ||
657 | |||
658 | group = iommu_group_get(&tmp->dev); | ||
659 | if (group) { | ||
660 | pci_dev_put(tmp); | ||
661 | return group; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | /* No shared group found, allocate new */ | ||
666 | return iommu_group_alloc(); | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * iommu_group_get_for_dev - Find or create the IOMMU group for a device | ||
671 | * @dev: target device | ||
672 | * | ||
673 | * This function is intended to be called by IOMMU drivers and extended to | ||
674 | * support common, bus-defined algorithms when determining or creating the | ||
675 | * IOMMU group for a device. On success, the caller will hold a reference | ||
676 | * to the returned IOMMU group, which will already include the provided | ||
677 | * device. The reference should be released with iommu_group_put(). | ||
678 | */ | ||
679 | struct iommu_group *iommu_group_get_for_dev(struct device *dev) | ||
680 | { | ||
681 | struct iommu_group *group = ERR_PTR(-EIO); | ||
682 | int ret; | ||
683 | |||
684 | group = iommu_group_get(dev); | ||
685 | if (group) | ||
686 | return group; | ||
687 | |||
688 | if (dev_is_pci(dev)) | ||
689 | group = iommu_group_get_for_pci_dev(to_pci_dev(dev)); | ||
690 | |||
691 | if (IS_ERR(group)) | ||
692 | return group; | ||
693 | |||
694 | ret = iommu_group_add_device(group, dev); | ||
695 | if (ret) { | ||
696 | iommu_group_put(group); | ||
697 | return ERR_PTR(ret); | ||
698 | } | ||
699 | |||
700 | return group; | ||
701 | } | ||
702 | |||
517 | static int add_iommu_group(struct device *dev, void *data) | 703 | static int add_iommu_group(struct device *dev, void *data) |
518 | { | 704 | { |
519 | struct iommu_ops *ops = data; | 705 | struct iommu_callback_data *cb = data; |
706 | const struct iommu_ops *ops = cb->ops; | ||
520 | 707 | ||
521 | if (!ops->add_device) | 708 | if (!ops->add_device) |
522 | return -ENODEV; | 709 | return -ENODEV; |
@@ -532,7 +719,7 @@ static int iommu_bus_notifier(struct notifier_block *nb, | |||
532 | unsigned long action, void *data) | 719 | unsigned long action, void *data) |
533 | { | 720 | { |
534 | struct device *dev = data; | 721 | struct device *dev = data; |
535 | struct iommu_ops *ops = dev->bus->iommu_ops; | 722 | const struct iommu_ops *ops = dev->bus->iommu_ops; |
536 | struct iommu_group *group; | 723 | struct iommu_group *group; |
537 | unsigned long group_action = 0; | 724 | unsigned long group_action = 0; |
538 | 725 | ||
@@ -585,10 +772,14 @@ static struct notifier_block iommu_bus_nb = { | |||
585 | .notifier_call = iommu_bus_notifier, | 772 | .notifier_call = iommu_bus_notifier, |
586 | }; | 773 | }; |
587 | 774 | ||
588 | static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) | 775 | static void iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) |
589 | { | 776 | { |
777 | struct iommu_callback_data cb = { | ||
778 | .ops = ops, | ||
779 | }; | ||
780 | |||
590 | bus_register_notifier(bus, &iommu_bus_nb); | 781 | bus_register_notifier(bus, &iommu_bus_nb); |
591 | bus_for_each_dev(bus, NULL, ops, add_iommu_group); | 782 | bus_for_each_dev(bus, NULL, &cb, add_iommu_group); |
592 | } | 783 | } |
593 | 784 | ||
594 | /** | 785 | /** |
@@ -604,7 +795,7 @@ static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) | |||
604 | * is set up. With this function the iommu-driver can set the iommu-ops | 795 | * is set up. With this function the iommu-driver can set the iommu-ops |
605 | * afterwards. | 796 | * afterwards. |
606 | */ | 797 | */ |
607 | int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops) | 798 | int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops) |
608 | { | 799 | { |
609 | if (bus->iommu_ops != NULL) | 800 | if (bus->iommu_ops != NULL) |
610 | return -EBUSY; | 801 | return -EBUSY; |
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 53cde086e83b..7dab5cbcc775 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c | |||
@@ -1120,7 +1120,7 @@ static void ipmmu_remove_device(struct device *dev) | |||
1120 | dev->archdata.iommu = NULL; | 1120 | dev->archdata.iommu = NULL; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | static struct iommu_ops ipmmu_ops = { | 1123 | static const struct iommu_ops ipmmu_ops = { |
1124 | .domain_init = ipmmu_domain_init, | 1124 | .domain_init = ipmmu_domain_init, |
1125 | .domain_destroy = ipmmu_domain_destroy, | 1125 | .domain_destroy = ipmmu_domain_destroy, |
1126 | .attach_dev = ipmmu_attach_device, | 1126 | .attach_dev = ipmmu_attach_device, |
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index f5ff657f49fa..49f41d6e02f1 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c | |||
@@ -674,7 +674,7 @@ fail: | |||
674 | return 0; | 674 | return 0; |
675 | } | 675 | } |
676 | 676 | ||
677 | static struct iommu_ops msm_iommu_ops = { | 677 | static const struct iommu_ops msm_iommu_ops = { |
678 | .domain_init = msm_iommu_domain_init, | 678 | .domain_init = msm_iommu_domain_init, |
679 | .domain_destroy = msm_iommu_domain_destroy, | 679 | .domain_destroy = msm_iommu_domain_destroy, |
680 | .attach_dev = msm_iommu_attach_dev, | 680 | .attach_dev = msm_iommu_attach_dev, |
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 895af06a667f..031b2476bcc4 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -1291,7 +1291,7 @@ static void omap_iommu_remove_device(struct device *dev) | |||
1291 | kfree(arch_data); | 1291 | kfree(arch_data); |
1292 | } | 1292 | } |
1293 | 1293 | ||
1294 | static struct iommu_ops omap_iommu_ops = { | 1294 | static const struct iommu_ops omap_iommu_ops = { |
1295 | .domain_init = omap_iommu_domain_init, | 1295 | .domain_init = omap_iommu_domain_init, |
1296 | .domain_destroy = omap_iommu_domain_destroy, | 1296 | .domain_destroy = omap_iommu_domain_destroy, |
1297 | .attach_dev = omap_iommu_attach_dev, | 1297 | .attach_dev = omap_iommu_attach_dev, |
diff --git a/drivers/iommu/pci.h b/drivers/iommu/pci.h deleted file mode 100644 index 352d80ae7443..000000000000 --- a/drivers/iommu/pci.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License, version 2, as | ||
4 | * published by the Free Software Foundation. | ||
5 | * | ||
6 | * This program is distributed in the hope that it will be useful, | ||
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
9 | * GNU General Public License for more details. | ||
10 | * | ||
11 | * You should have received a copy of the GNU General Public License | ||
12 | * along with this program; if not, write to the Free Software | ||
13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
14 | * | ||
15 | * Copyright (C) 2013 Red Hat, Inc. | ||
16 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
17 | * | ||
18 | */ | ||
19 | #ifndef __IOMMU_PCI_H | ||
20 | #define __IOMMU_PCI_H | ||
21 | |||
22 | /* Helper function for swapping pci device reference */ | ||
23 | static inline void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) | ||
24 | { | ||
25 | pci_dev_put(*from); | ||
26 | *from = to; | ||
27 | } | ||
28 | |||
29 | #endif /* __IOMMU_PCI_H */ | ||
diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c index 464acda0bbc4..1333e6fb3405 100644 --- a/drivers/iommu/shmobile-iommu.c +++ b/drivers/iommu/shmobile-iommu.c | |||
@@ -354,7 +354,7 @@ static int shmobile_iommu_add_device(struct device *dev) | |||
354 | return 0; | 354 | return 0; |
355 | } | 355 | } |
356 | 356 | ||
357 | static struct iommu_ops shmobile_iommu_ops = { | 357 | static const struct iommu_ops shmobile_iommu_ops = { |
358 | .domain_init = shmobile_iommu_domain_init, | 358 | .domain_init = shmobile_iommu_domain_init, |
359 | .domain_destroy = shmobile_iommu_domain_destroy, | 359 | .domain_destroy = shmobile_iommu_domain_destroy, |
360 | .attach_dev = shmobile_iommu_attach_device, | 360 | .attach_dev = shmobile_iommu_attach_device, |
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index dba1a9fd5070..b10a8ecede8e 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c | |||
@@ -309,7 +309,7 @@ static int gart_iommu_domain_has_cap(struct iommu_domain *domain, | |||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static struct iommu_ops gart_iommu_ops = { | 312 | static const struct iommu_ops gart_iommu_ops = { |
313 | .domain_init = gart_iommu_domain_init, | 313 | .domain_init = gart_iommu_domain_init, |
314 | .domain_destroy = gart_iommu_domain_destroy, | 314 | .domain_destroy = gart_iommu_domain_destroy, |
315 | .attach_dev = gart_iommu_attach_dev, | 315 | .attach_dev = gart_iommu_attach_dev, |
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 605b5b46a903..792da5ea6d12 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c | |||
@@ -947,7 +947,7 @@ static void smmu_iommu_domain_destroy(struct iommu_domain *domain) | |||
947 | dev_dbg(smmu->dev, "smmu_as@%p\n", as); | 947 | dev_dbg(smmu->dev, "smmu_as@%p\n", as); |
948 | } | 948 | } |
949 | 949 | ||
950 | static struct iommu_ops smmu_iommu_ops = { | 950 | static const struct iommu_ops smmu_iommu_ops = { |
951 | .domain_init = smmu_iommu_domain_init, | 951 | .domain_init = smmu_iommu_domain_init, |
952 | .domain_destroy = smmu_iommu_domain_destroy, | 952 | .domain_destroy = smmu_iommu_domain_destroy, |
953 | .attach_dev = smmu_iommu_attach_dev, | 953 | .attach_dev = smmu_iommu_attach_dev, |