Merge branch 'iommu/largepages' into amd-iommu/2.6.35
[pandora-kernel.git] / arch / x86 / kernel / amd_iommu.c
index d8da998..fa5a147 100644 (file)
@@ -18,8 +18,8 @@
  */
 
 #include <linux/pci.h>
-#include <linux/gfp.h>
 #include <linux/bitmap.h>
+#include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
@@ -118,7 +118,7 @@ static bool check_device(struct device *dev)
                return false;
 
        /* No device or no PCI device */
-       if (!dev || dev->bus != &pci_bus_type)
+       if (dev->bus != &pci_bus_type)
                return false;
 
        devid = get_device_id(dev);
@@ -392,6 +392,7 @@ static int __iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
        u32 tail, head;
        u8 *target;
 
+       WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
        tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
        target = iommu->cmd_buf + tail;
        memcpy_toio(target, cmd, sizeof(*cmd));
@@ -2253,7 +2254,7 @@ static void prealloc_protection_domains(void)
        struct dma_ops_domain *dma_dom;
        u16 devid;
 
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev) {
 
                /* Do we handle this device? */
                if (!check_device(&dev->dev))
@@ -2365,7 +2366,7 @@ static void cleanup_domain(struct protection_domain *domain)
        list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
                struct device *dev = dev_data->dev;
 
-               do_detach(dev);
+               __detach_device(dev);
                atomic_set(&dev_data->bind, 0);
        }
 
@@ -2394,6 +2395,7 @@ static struct protection_domain *protection_domain_alloc(void)
                return NULL;
 
        spin_lock_init(&domain->lock);
+       mutex_init(&domain->api_lock);
        domain->id = domain_id_alloc();
        if (!domain->id)
                goto out_err;
@@ -2446,9 +2448,7 @@ static void amd_iommu_domain_destroy(struct iommu_domain *dom)
 
        free_pagetable(domain);
 
-       domain_id_free(domain->id);
-
-       kfree(domain);
+       protection_domain_free(domain);
 
        dom->priv = NULL;
 }
@@ -2512,13 +2512,18 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
        unsigned long page_size = 0x1000UL << gfp_order;
        struct protection_domain *domain = dom->priv;
        int prot = 0;
+       int ret;
 
        if (iommu_prot & IOMMU_READ)
                prot |= IOMMU_PROT_IR;
        if (iommu_prot & IOMMU_WRITE)
                prot |= IOMMU_PROT_IW;
 
-       return iommu_map_page(domain, iova, paddr, prot, page_size);
+       mutex_lock(&domain->api_lock);
+       ret = iommu_map_page(domain, iova, paddr, prot, page_size);
+       mutex_unlock(&domain->api_lock);
+
+       return ret;
 }
 
 static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
@@ -2528,7 +2533,12 @@ static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
        unsigned long page_size, unmap_size;
 
        page_size  = 0x1000UL << gfp_order;
+
+       mutex_lock(&domain->api_lock);
        unmap_size = iommu_unmap_page(domain, iova, page_size);
+       mutex_unlock(&domain->api_lock);
+
+       iommu_flush_tlb_pde(domain);
 
        return get_order(unmap_size);
 }