Commit 1ae45cf0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'iommu-fixes-v3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull IOMMU fixes from Joerg Roedel:
 "The fixes include:

   - fix a crash in the VT-d driver when devices with a driver attached
     are hot-unplugged

   - fix a AMD IOMMU driver crash with device assignment of 32 bit PCI
     devices to KVM guests

   - fix for a copy&paste error in generic IOMMU code.  Now the right
     function pointer is checked before calling"

* tag 'iommu-fixes-v3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu/core: Check for the right function pointer in iommu_map()
  iommu/amd: Fix cleanup_domain for mass device removal
  iommu/vt-d: Defer domain removal if device is assigned to a driver
parents 5317821c 9db4ad91
...@@ -3149,14 +3149,16 @@ int __init amd_iommu_init_dma_ops(void) ...@@ -3149,14 +3149,16 @@ int __init amd_iommu_init_dma_ops(void)
static void cleanup_domain(struct protection_domain *domain) static void cleanup_domain(struct protection_domain *domain)
{ {
struct iommu_dev_data *dev_data, *next; struct iommu_dev_data *entry;
unsigned long flags; unsigned long flags;
write_lock_irqsave(&amd_iommu_devtable_lock, flags); write_lock_irqsave(&amd_iommu_devtable_lock, flags);
list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { while (!list_empty(&domain->dev_list)) {
__detach_device(dev_data); entry = list_first_entry(&domain->dev_list,
atomic_set(&dev_data->bind, 0); struct iommu_dev_data, list);
__detach_device(entry);
atomic_set(&entry->bind, 0);
} }
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
......
...@@ -3869,6 +3869,14 @@ static int device_notifier(struct notifier_block *nb, ...@@ -3869,6 +3869,14 @@ static int device_notifier(struct notifier_block *nb,
action != BUS_NOTIFY_DEL_DEVICE) action != BUS_NOTIFY_DEL_DEVICE)
return 0; return 0;
/*
* If the device is still attached to a device driver we can't
* tear down the domain yet as DMA mappings may still be in use.
* Wait for the BUS_NOTIFY_UNBOUND_DRIVER event to do that.
*/
if (action == BUS_NOTIFY_DEL_DEVICE && dev->driver != NULL)
return 0;
domain = find_domain(dev); domain = find_domain(dev);
if (!domain) if (!domain)
return 0; return 0;
......
...@@ -995,7 +995,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, ...@@ -995,7 +995,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
size_t orig_size = size; size_t orig_size = size;
int ret = 0; int ret = 0;
if (unlikely(domain->ops->unmap == NULL || if (unlikely(domain->ops->map == NULL ||
domain->ops->pgsize_bitmap == 0UL)) domain->ops->pgsize_bitmap == 0UL))
return -ENODEV; return -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment