#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/page-flags.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 
        BUG_ON(!valid_dma_direction(dir));
 
+       if (PageHighMem(page)) {
+               dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
+                            "is not supported\n");
+               return ~0;
+       }
+
        return map_single(dev, page_address(page) + offset, size, dir);
 }
 EXPORT_SYMBOL(dma_map_page);
 
  * must not be used by drivers.
  */
 #ifndef __arch_page_to_dma
+
+#if !defined(CONFIG_HIGHMEM)
 static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
 {
        return (dma_addr_t)__virt_to_bus((unsigned long)page_address(page));
 }
+#elif defined(__pfn_to_bus)
+static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+{
+       return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
+}
+#else
+#error "this machine class needs to define __arch_page_to_dma to use HIGHMEM"
+#endif
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
 {
 
 #ifndef __virt_to_bus
 #define __virt_to_bus  __virt_to_phys
 #define __bus_to_virt  __phys_to_virt
+#define __pfn_to_bus(x)        ((x) << PAGE_SHIFT)
 #endif
 
 static inline __deprecated unsigned long virt_to_bus(void *x)
 
        })
 
 #define __arch_page_to_dma(dev, page)                                  \
-       __arch_virt_to_dma(dev, page_address(page))
+       ({                                                              \
+               /* __is_lbus_virt() can never be true for RAM pages */  \
+               (dma_addr_t)page_to_phys(page);                         \
+       })
 
 #endif /* CONFIG_ARCH_IOP13XX */
 #endif /* !ASSEMBLY */
 
                                        __phys_to_virt(x) : __bus_to_virt(x)); })
 #define __arch_virt_to_dma(dev, x)     ({ is_lbus_device(dev) ? \
                                        (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
-#define __arch_page_to_dma(dev, x)     __arch_virt_to_dma(dev, page_address(x))
+#define __arch_page_to_dma(dev, x)     \
+       ({ dma_addr_t __dma = page_to_phys(page); \
+          if (!is_lbus_device(dev)) \
+               __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
+          __dma; })
 
 #endif
 
 
 #define lbus_to_virt(x)                ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
 #define is_lbus_device(dev)    (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
 
-#define __arch_page_to_dma(dev, page)  ({is_lbus_device(dev) ? \
-                                       (dma_addr_t)virt_to_lbus(page_address(page)) : \
-                                       (dma_addr_t)__virt_to_phys(page_address(page));})
+#define __arch_page_to_dma(dev, page)  \
+       ({ dma_addr_t __dma = page_to_phys(page); \
+          if (is_lbus_device(dev)) \
+               __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
+          __dma; })
 
 #define __arch_dma_to_virt(dev, addr)  ({ (void *) (is_lbus_device(dev) ? \
                                                lbus_to_virt(addr) : \