gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
                                goto again;
                        }
+
+                       /* Let low level make its own zone decisions */
+                       gfp &= ~(GFP_DMA32|GFP_DMA);
+
+                       if (dma_ops->alloc_coherent)
+                               return dma_ops->alloc_coherent(dev, size,
+                                                          dma_handle, gfp);
+                       return NULL;
+
                }
                memset(ret, 0, size);
-               *dma_handle = bus;
+               if (!mmu) {
+                       *dma_handle = bus;
+                       return ret;
+               }
+       }
+
+       if (dma_ops->alloc_coherent) {
+               free_pages((unsigned long)ret, get_order(size));
+               gfp &= ~(GFP_DMA|GFP_DMA32);
+               return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
+       }
+
+       if (dma_ops->map_simple) {
+               *dma_handle = dma_ops->map_simple(dev, virt_to_phys(ret),
+                                             size,
+                                             PCI_DMA_BIDIRECTIONAL);
+               if (*dma_handle != bad_dma_address)
+                       return ret;
        }
 
-       return ret;
+       if (panic_on_overflow)
+               panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",
+                     (unsigned long)size);
+       free_pages((unsigned long)ret, get_order(size));
+       return NULL;
 }
 EXPORT_SYMBOL(dma_alloc_coherent);