Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil...
[pandora-kernel.git] / arch / x86_64 / kernel / pci-gart.c
index dd0718d..2480d3f 100644 (file)
@@ -65,9 +65,7 @@ static u32 gart_unmapped_entry;
 
 #define for_all_nb(dev) \
        dev = NULL;     \
-       while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)\
-            if (dev->bus->number == 0 &&                                    \
-                   (PCI_SLOT(dev->devfn) >= 24) && (PCI_SLOT(dev->devfn) <= 31))
+       while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)
 
 static struct pci_dev *northbridges[MAX_NB];
 static u32 northbridge_flush_word[MAX_NB];
@@ -114,10 +112,6 @@ static unsigned long alloc_iommu(int size)
 static void free_iommu(unsigned long offset, int size)
 { 
        unsigned long flags;
-       if (size == 1) { 
-               clear_bit(offset, iommu_gart_bitmap); 
-               return;
-       }
        spin_lock_irqsave(&iommu_bitmap_lock, flags);
        __clear_bit_string(iommu_gart_bitmap, offset, size);
        spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
@@ -148,9 +142,12 @@ static void flush_gart(struct device *dev)
                        if (!northbridges[i])
                                continue;
                        /* Make sure the hardware actually executed the flush. */
-                       do { 
+                       for (;;) { 
                                pci_read_config_dword(northbridges[i], 0x9c, &w);
-                       } while (w & 1);
+                               if (!(w & 1))
+                                       break;
+                               cpu_relax();
+                       }
                } 
                if (!flushed) 
                        printk("nothing to flush?\n");
@@ -228,11 +225,6 @@ static inline int need_iommu(struct device *dev, unsigned long addr, size_t size
        int mmu = high;
        if (force_iommu) 
                mmu = 1; 
-       if (no_iommu) { 
-               if (high) 
-                       panic("PCI-DMA: high address but no IOMMU.\n"); 
-               mmu = 0; 
-       }       
        return mmu; 
 }
 
@@ -241,11 +233,6 @@ static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t
        u64 mask = *dev->dma_mask;
        int high = addr + size >= mask;
        int mmu = high;
-       if (no_iommu) { 
-               if (high) 
-                       panic("PCI-DMA: high address but no IOMMU.\n"); 
-               mmu = 0; 
-       }       
        return mmu; 
 }
 
@@ -310,7 +297,7 @@ void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int di
 
        for (i = 0; i < nents; i++) {
                struct scatterlist *s = &sg[i];
-               if (!s->dma_length)
+               if (!s->dma_length || !s->length)
                        break;
                dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
        }
@@ -364,6 +351,7 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
                
                BUG_ON(i > start && s->offset);
                if (i == start) {
+                       *sout = *s; 
                        sout->dma_address = iommu_bus_base;
                        sout->dma_address += iommu_page*PAGE_SIZE + s->offset;
                        sout->dma_length = s->length;
@@ -390,6 +378,7 @@ static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat,
 {
        if (!need) { 
                BUG_ON(stopat - start != 1);
+               *sout = sg[start]; 
                sout->dma_length = sg[start].length; 
                return 0;
        } 
@@ -632,17 +621,13 @@ static int __init pci_iommu_init(void)
                (agp_copy_info(agp_bridge, &info) < 0);
 #endif 
 
-       if (swiotlb) { 
-               no_iommu = 1;
+       if (swiotlb)
                return -1; 
-       } 
-       
+
        if (no_iommu ||
            (!force_iommu && end_pfn <= MAX_DMA32_PFN) ||
            !iommu_aperture ||
            (no_agp && init_k8_gatt(&info) < 0)) {
-               no_iommu = 1;
-               no_iommu_init();
                printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
                if (end_pfn > MAX_DMA32_PFN) {
                        printk(KERN_ERR "WARNING more than 4GB of memory "
@@ -654,6 +639,14 @@ static int __init pci_iommu_init(void)
                return -1;
        }
 
+       i = 0;
+       for_all_nb(dev)
+               i++;
+       if (i > MAX_NB) {
+               printk(KERN_ERR "PCI-GART: Too many northbridges (%ld). Disabled\n", i);
+               return -1;
+       }
+
        printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
        aper_size = info.aper_size * 1024 * 1024;       
        iommu_size = check_iommu_size(info.aper_base, aper_size);