Merge branch 'iommu/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
authorIngo Molnar <mingo@elte.hu>
Tue, 13 Apr 2010 11:24:54 +0000 (13:24 +0200)
committerIngo Molnar <mingo@elte.hu>
Tue, 13 Apr 2010 11:24:54 +0000 (13:24 +0200)
1  2 
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/pci-gart_64.c

@@@ -18,8 -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 +118,7 @@@ static bool check_device(struct device 
                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 +392,7 @@@ static int __iommu_queue_command(struc
        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));
@@@ -2186,7 -2187,7 +2187,7 @@@ static void prealloc_protection_domains
        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))
@@@ -2298,7 -2299,7 +2299,7 @@@ static void cleanup_domain(struct prote
        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);
        }
  
@@@ -2327,6 -2328,7 +2328,7 @@@ static struct protection_domain *protec
                return NULL;
  
        spin_lock_init(&domain->lock);
+       mutex_init(&domain->api_lock);
        domain->id = domain_id_alloc();
        if (!domain->id)
                goto out_err;
@@@ -2379,9 -2381,7 +2381,7 @@@ static void amd_iommu_domain_destroy(st
  
        free_pagetable(domain);
  
-       domain_id_free(domain->id);
-       kfree(domain);
+       protection_domain_free(domain);
  
        dom->priv = NULL;
  }
@@@ -2456,6 -2456,8 +2456,8 @@@ static int amd_iommu_map_range(struct i
        iova  &= PAGE_MASK;
        paddr &= PAGE_MASK;
  
+       mutex_lock(&domain->api_lock);
        for (i = 0; i < npages; ++i) {
                ret = iommu_map_page(domain, iova, paddr, prot, PM_MAP_4k);
                if (ret)
                paddr += PAGE_SIZE;
        }
  
+       mutex_unlock(&domain->api_lock);
        return 0;
  }
  
@@@ -2477,12 -2481,16 +2481,16 @@@ static void amd_iommu_unmap_range(struc
  
        iova  &= PAGE_MASK;
  
+       mutex_lock(&domain->api_lock);
        for (i = 0; i < npages; ++i) {
                iommu_unmap_page(domain, iova, PM_MAP_4k);
                iova  += PAGE_SIZE;
        }
  
        iommu_flush_tlb_pde(domain);
+       mutex_unlock(&domain->api_lock);
  }
  
  static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
@@@ -19,8 -19,8 +19,8 @@@
  
  #include <linux/pci.h>
  #include <linux/acpi.h>
 -#include <linux/gfp.h>
  #include <linux/list.h>
 +#include <linux/slab.h>
  #include <linux/sysdev.h>
  #include <linux/interrupt.h>
  #include <linux/msi.h>
@@@ -138,9 -138,9 +138,9 @@@ int amd_iommus_present
  bool amd_iommu_np_cache __read_mostly;
  
  /*
-  * Set to true if ACPI table parsing and hardware intialization went properly
+  * The ACPI table parsing functions set this variable on an error
   */
- static bool amd_iommu_initialized;
+ static int __initdata amd_iommu_init_err;
  
  /*
   * List of protection domains - used during resume
@@@ -391,9 -391,11 +391,11 @@@ static int __init find_last_devid_acpi(
         */
        for (i = 0; i < table->length; ++i)
                checksum += p[i];
-       if (checksum != 0)
+       if (checksum != 0) {
                /* ACPI table corrupt */
-               return -ENODEV;
+               amd_iommu_init_err = -ENODEV;
+               return 0;
+       }
  
        p += IVRS_HEADER_LENGTH;
  
@@@ -436,7 -438,7 +438,7 @@@ static u8 * __init alloc_command_buffer
        if (cmd_buf == NULL)
                return NULL;
  
-       iommu->cmd_buf_size = CMD_BUFFER_SIZE;
+       iommu->cmd_buf_size = CMD_BUFFER_SIZE | CMD_BUFFER_UNINITIALIZED;
  
        return cmd_buf;
  }
@@@ -472,12 -474,13 +474,13 @@@ static void iommu_enable_command_buffer
                    &entry, sizeof(entry));
  
        amd_iommu_reset_cmd_buffer(iommu);
+       iommu->cmd_buf_size &= ~(CMD_BUFFER_UNINITIALIZED);
  }
  
  static void __init free_command_buffer(struct amd_iommu *iommu)
  {
        free_pages((unsigned long)iommu->cmd_buf,
-                  get_order(iommu->cmd_buf_size));
+                  get_order(iommu->cmd_buf_size & ~(CMD_BUFFER_UNINITIALIZED)));
  }
  
  /* allocates the memory where the IOMMU will log its events to */
@@@ -920,11 -923,16 +923,16 @@@ static int __init init_iommu_all(struc
                                    h->mmio_phys);
  
                        iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL);
-                       if (iommu == NULL)
-                               return -ENOMEM;
+                       if (iommu == NULL) {
+                               amd_iommu_init_err = -ENOMEM;
+                               return 0;
+                       }
                        ret = init_iommu_one(iommu, h);
-                       if (ret)
-                               return ret;
+                       if (ret) {
+                               amd_iommu_init_err = ret;
+                               return 0;
+                       }
                        break;
                default:
                        break;
        }
        WARN_ON(p != end);
  
-       amd_iommu_initialized = true;
        return 0;
  }
  
@@@ -1211,6 -1217,10 +1217,10 @@@ static int __init amd_iommu_init(void
        if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0)
                return -ENODEV;
  
+       ret = amd_iommu_init_err;
+       if (ret)
+               goto out;
        dev_table_size     = tbl_size(DEV_TABLE_ENTRY_SIZE);
        alias_table_size   = tbl_size(ALIAS_TABLE_ENTRY_SIZE);
        rlookup_table_size = tbl_size(RLOOKUP_TABLE_ENTRY_SIZE);
        if (acpi_table_parse("IVRS", init_iommu_all) != 0)
                goto free;
  
-       if (!amd_iommu_initialized)
+       if (amd_iommu_init_err) {
+               ret = amd_iommu_init_err;
                goto free;
+       }
  
        if (acpi_table_parse("IVRS", init_memory_definitions) != 0)
                goto free;
  
+       if (amd_iommu_init_err) {
+               ret = amd_iommu_init_err;
+               goto free;
+       }
        ret = sysdev_class_register(&amd_iommu_sysdev_class);
        if (ret)
                goto free;
        if (ret)
                goto free;
  
+       enable_iommus();
        if (iommu_pass_through)
                ret = amd_iommu_init_passthrough();
        else
  
        amd_iommu_init_notifier();
  
-       enable_iommus();
        if (iommu_pass_through)
                goto out;
  
@@@ -1315,6 -1332,7 +1332,7 @@@ out
        return ret;
  
  free:
+       disable_iommus();
  
        amd_iommu_uninit_devices();
  
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/iommu-helper.h>
  #include <linux/sysdev.h>
  #include <linux/io.h>
 +#include <linux/gfp.h>
  #include <asm/atomic.h>
  #include <asm/mtrr.h>
  #include <asm/pgtable.h>
@@@ -565,6 -564,9 +565,9 @@@ static void enable_gart_translations(vo
  
                enable_gart_translation(dev, __pa(agp_gatt_table));
        }
+       /* Flush the GART-TLB to remove stale entries */
+       k8_flush_garts();
  }
  
  /*