aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2014-07-03 11:51:37 -0400
committerJoerg Roedel <jroedel@suse.de>2014-07-04 06:35:58 -0400
commite17f9ff413a4052d532c11c1e1c6eb27c71aada2 (patch)
treeff3380c18d2b3f90e686de87f22a54f71b9a3d41
parent65d5352f12e16dc9321b1e4f8213793565c124be (diff)
iommu/vt-d: Use iommu_group_get_for_dev()
The IOMMU code now provides a common interface for finding or creating an IOMMU group for a device on PCI buses. Make use of it and remove piles of code. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Cc: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/intel-iommu.c79
1 files changed, 4 insertions, 75 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 51b6b77dc3e5..9128c84a51e7 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
@@ -4373,91 +4372,21 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
4373 return 0; 4372 return 0;
4374} 4373}
4375 4374
4376#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
4377
4378static int intel_iommu_add_device(struct device *dev) 4375static int intel_iommu_add_device(struct device *dev)
4379{ 4376{
4380 struct pci_dev *pdev = to_pci_dev(dev);
4381 struct pci_dev *bridge, *dma_pdev = NULL;
4382 struct iommu_group *group; 4377 struct iommu_group *group;
4383 int ret;
4384 u8 bus, devfn; 4378 u8 bus, devfn;
4385 4379
4386 if (!device_to_iommu(dev, &bus, &devfn)) 4380 if (!device_to_iommu(dev, &bus, &devfn))
4387 return -ENODEV; 4381 return -ENODEV;
4388 4382
4389 bridge = pci_find_upstream_pcie_bridge(pdev); 4383 group = iommu_group_get_for_dev(dev);
4390 if (bridge) {
4391 if (pci_is_pcie(bridge))
4392 dma_pdev = pci_get_domain_bus_and_slot(
4393 pci_domain_nr(pdev->bus),
4394 bridge->subordinate->number, 0);
4395 if (!dma_pdev)
4396 dma_pdev = pci_dev_get(bridge);
4397 } else
4398 dma_pdev = pci_dev_get(pdev);
4399
4400 /* Account for quirked devices */
4401 swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
4402
4403 /*
4404 * If it's a multifunction device that does not support our
4405 * required ACS flags, add to the same group as lowest numbered
4406 * function that also does not suport the required ACS flags.
4407 */
4408 if (dma_pdev->multifunction &&
4409 !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
4410 u8 i, slot = PCI_SLOT(dma_pdev->devfn);
4411
4412 for (i = 0; i < 8; i++) {
4413 struct pci_dev *tmp;
4414
4415 tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
4416 if (!tmp)
4417 continue;
4418
4419 if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
4420 swap_pci_ref(&dma_pdev, tmp);
4421 break;
4422 }
4423 pci_dev_put(tmp);
4424 }
4425 }
4426
4427 /*
4428 * Devices on the root bus go through the iommu. If that's not us,
4429 * find the next upstream device and test ACS up to the root bus.
4430 * Finding the next device may require skipping virtual buses.
4431 */
4432 while (!pci_is_root_bus(dma_pdev->bus)) {
4433 struct pci_bus *bus = dma_pdev->bus;
4434
4435 while (!bus->self) {
4436 if (!pci_is_root_bus(bus))
4437 bus = bus->parent;
4438 else
4439 goto root_bus;
4440 }
4441
4442 if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
4443 break;
4444
4445 swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
4446 }
4447 4384
4448root_bus: 4385 if (IS_ERR(group))
4449 group = iommu_group_get(&dma_pdev->dev); 4386 return PTR_ERR(group);
4450 pci_dev_put(dma_pdev);
4451 if (!group) {
4452 group = iommu_group_alloc();
4453 if (IS_ERR(group))
4454 return PTR_ERR(group);
4455 }
4456
4457 ret = iommu_group_add_device(group, dev);
4458 4387
4459 iommu_group_put(group); 4388 iommu_group_put(group);
4460 return ret; 4389 return 0;
4461} 4390}
4462 4391
4463static void intel_iommu_remove_device(struct device *dev) 4392static void intel_iommu_remove_device(struct device *dev)