Commit 7e996890 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David S. Miller

sparc/iommu: fix __sbus_iommu_map_page for highmem pages

__sbus_iommu_map_page currently assumes all pages are mapped into the
kernel direct mapping.  Switch to using physical address instead of
virtual ones for all the normal mapping operations, and only use
the virtual addresses for cache flushing when not operating on
a highmem page.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reported-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8668b38c
...@@ -209,24 +209,23 @@ static u32 iommu_get_one(struct device *dev, phys_addr_t paddr, int npages) ...@@ -209,24 +209,23 @@ static u32 iommu_get_one(struct device *dev, phys_addr_t paddr, int npages)
static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page, static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t len, bool per_page_flush) unsigned long offset, size_t len, bool per_page_flush)
{ {
void *vaddr = page_address(page) + offset; phys_addr_t paddr = page_to_phys(page) + offset;
unsigned long off = (unsigned long)vaddr & ~PAGE_MASK; unsigned long off = paddr & ~PAGE_MASK;
unsigned long npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
/* XXX So what is maxphys for us and how do drivers know it? */ /* XXX So what is maxphys for us and how do drivers know it? */
if (!len || len > 256 * 1024) if (!len || len > 256 * 1024)
return DMA_MAPPING_ERROR; return DMA_MAPPING_ERROR;
if (per_page_flush) { if (per_page_flush && !PageHighMem(page)) {
unsigned long p = (unsigned long)vaddr & PAGE_MASK; unsigned long vaddr, p;
while (p < (unsigned long)vaddr + len) { vaddr = (unsigned long)page_address(page) + offset;
for (p = vaddr & PAGE_MASK; p < vaddr + len; p += PAGE_SIZE)
flush_page_for_dma(p); flush_page_for_dma(p);
p += PAGE_SIZE;
}
} }
return iommu_get_one(dev, virt_to_phys(vaddr), npages) + off; return iommu_get_one(dev, paddr, npages) + off;
} }
static dma_addr_t sbus_iommu_map_page_gflush(struct device *dev, static dma_addr_t sbus_iommu_map_page_gflush(struct device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment