diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-14 13:05:27 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-14 13:05:27 -0800 |
commit | a9366e61b03f55a6e009e687ad10e706714c9907 (patch) | |
tree | b68f510ae8924db3385eae783a1294d0af03ae37 /drivers/pci/intel-iommu.c | |
parent | 24dfb2b5867df24ba03b6c4418312e23b1300aa8 (diff) | |
parent | 99dcadede42f8898d4c963ef69192ef4b9b76ba8 (diff) |
Merge git://git.infradead.org/users/dwmw2/iommu-2.6.32
* git://git.infradead.org/users/dwmw2/iommu-2.6.32:
intel-iommu: Support PCIe hot-plug
intel-iommu: Obey coherent_dma_mask for alloc_coherent on passthrough
intel-iommu: Check for 'DMAR at zero' BIOS error earlier.
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r-- | drivers/pci/intel-iommu.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index b1e97e68250..1840a0578a4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2767,7 +2767,15 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size, size = PAGE_ALIGN(size); order = get_order(size); - flags &= ~(GFP_DMA | GFP_DMA32); + + if (!iommu_no_mapping(hwdev)) + flags &= ~(GFP_DMA | GFP_DMA32); + else if (hwdev->coherent_dma_mask < dma_get_required_mask(hwdev)) { + if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32)) + flags |= GFP_DMA; + else + flags |= GFP_DMA32; + } vaddr = (void *)__get_free_pages(flags, order); if (!vaddr) @@ -3207,6 +3215,33 @@ static int __init init_iommu_sysfs(void) } #endif /* CONFIG_PM */ +/* + * Here we only respond to action of unbound device from driver. + * + * Added device is not attached to its DMAR domain here yet. That will happen + * when mapping the device to iova. + */ +static int device_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct pci_dev *pdev = to_pci_dev(dev); + struct dmar_domain *domain; + + domain = find_domain(pdev); + if (!domain) + return 0; + + if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) + domain_remove_one_dev_info(domain, pdev); + + return 0; +} + +static struct notifier_block device_nb = { + .notifier_call = device_notifier, +}; + int __init intel_iommu_init(void) { int ret = 0; @@ -3259,6 +3294,8 @@ int __init intel_iommu_init(void) register_iommu(&intel_iommu_ops); + bus_register_notifier(&pci_bus_type, &device_nb); + return 0; } |