Commit dac21527 authored by David S. Miller's avatar David S. Miller

Merge branch 'sparc32-iommu-SG-list'

Christoph Hellwig says:

====================
fix SG list handling in the sparc32 iommu driver

this series fixes some long standing bugs in the sparc32 iommu driver,
mostly the lack of handling of large sglist offsets in the map_sg
method, but also a few other smaller bits.  These now show up all the
time do some block layer changes in linux-next.
====================
Tested-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 269fe565 376b1371
......@@ -175,16 +175,37 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
}
}
static u32 iommu_get_one(struct device *dev, struct page *page, int npages)
static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t len, bool per_page_flush)
{
struct iommu_struct *iommu = dev->archdata.iommu;
int ioptex;
iopte_t *iopte, *iopte0;
phys_addr_t paddr = page_to_phys(page) + offset;
unsigned long off = paddr & ~PAGE_MASK;
unsigned long npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long pfn = __phys_to_pfn(paddr);
unsigned int busa, busa0;
int i;
iopte_t *iopte, *iopte0;
int ioptex, i;
/* XXX So what is maxphys for us and how do drivers know it? */
if (!len || len > 256 * 1024)
return DMA_MAPPING_ERROR;
/*
* We expect unmapped highmem pages to be not in the cache.
* XXX Is this a good assumption?
* XXX What if someone else unmaps it here and races us?
*/
if (per_page_flush && !PageHighMem(page)) {
unsigned long vaddr, p;
vaddr = (unsigned long)page_address(page) + offset;
for (p = vaddr & PAGE_MASK; p < vaddr + len; p += PAGE_SIZE)
flush_page_for_dma(p);
}
/* page color = pfn of page */
ioptex = bit_map_string_get(&iommu->usemap, npages, page_to_pfn(page));
ioptex = bit_map_string_get(&iommu->usemap, npages, pfn);
if (ioptex < 0)
panic("iommu out");
busa0 = iommu->start + (ioptex << PAGE_SHIFT);
......@@ -193,29 +214,15 @@ static u32 iommu_get_one(struct device *dev, struct page *page, int npages)
busa = busa0;
iopte = iopte0;
for (i = 0; i < npages; i++) {
iopte_val(*iopte) = MKIOPTE(page_to_pfn(page), IOPERM);
iopte_val(*iopte) = MKIOPTE(pfn, IOPERM);
iommu_invalidate_page(iommu->regs, busa);
busa += PAGE_SIZE;
iopte++;
page++;
pfn++;
}
iommu_flush_iotlb(iopte0, npages);
return busa0;
}
static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t len)
{
void *vaddr = page_address(page) + offset;
unsigned long off = (unsigned long)vaddr & ~PAGE_MASK;
unsigned long npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
/* XXX So what is maxphys for us and how do drivers know it? */
if (!len || len > 256 * 1024)
return DMA_MAPPING_ERROR;
return iommu_get_one(dev, virt_to_page(vaddr), npages) + off;
return busa0 + off;
}
static dma_addr_t sbus_iommu_map_page_gflush(struct device *dev,
......@@ -223,81 +230,58 @@ static dma_addr_t sbus_iommu_map_page_gflush(struct device *dev,
enum dma_data_direction dir, unsigned long attrs)
{
flush_page_for_dma(0);
return __sbus_iommu_map_page(dev, page, offset, len);
return __sbus_iommu_map_page(dev, page, offset, len, false);
}
static dma_addr_t sbus_iommu_map_page_pflush(struct device *dev,
struct page *page, unsigned long offset, size_t len,
enum dma_data_direction dir, unsigned long attrs)
{
void *vaddr = page_address(page) + offset;
unsigned long p = ((unsigned long)vaddr) & PAGE_MASK;
while (p < (unsigned long)vaddr + len) {
flush_page_for_dma(p);
p += PAGE_SIZE;
}
return __sbus_iommu_map_page(dev, page, offset, len);
return __sbus_iommu_map_page(dev, page, offset, len, true);
}
static int sbus_iommu_map_sg_gflush(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir, unsigned long attrs)
static int __sbus_iommu_map_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir, unsigned long attrs,
bool per_page_flush)
{
struct scatterlist *sg;
int i, n;
flush_page_for_dma(0);
int j;
for_each_sg(sgl, sg, nents, i) {
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset;
for_each_sg(sgl, sg, nents, j) {
sg->dma_address =__sbus_iommu_map_page(dev, sg_page(sg),
sg->offset, sg->length, per_page_flush);
if (sg->dma_address == DMA_MAPPING_ERROR)
return 0;
sg->dma_length = sg->length;
}
return nents;
}
static int sbus_iommu_map_sg_pflush(struct device *dev, struct scatterlist *sgl,
static int sbus_iommu_map_sg_gflush(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir, unsigned long attrs)
{
unsigned long page, oldpage = 0;
struct scatterlist *sg;
int i, j, n;
for_each_sg(sgl, sg, nents, j) {
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
/*
* We expect unmapped highmem pages to be not in the cache.
* XXX Is this a good assumption?
* XXX What if someone else unmaps it here and races us?
*/
if ((page = (unsigned long) page_address(sg_page(sg))) != 0) {
for (i = 0; i < n; i++) {
if (page != oldpage) { /* Already flushed? */
flush_page_for_dma(page);
oldpage = page;
}
page += PAGE_SIZE;
}
}
sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset;
sg->dma_length = sg->length;
}
flush_page_for_dma(0);
return __sbus_iommu_map_sg(dev, sgl, nents, dir, attrs, false);
}
return nents;
static int sbus_iommu_map_sg_pflush(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir, unsigned long attrs)
{
return __sbus_iommu_map_sg(dev, sgl, nents, dir, attrs, true);
}
static void iommu_release_one(struct device *dev, u32 busa, int npages)
static void sbus_iommu_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t len, enum dma_data_direction dir, unsigned long attrs)
{
struct iommu_struct *iommu = dev->archdata.iommu;
int ioptex;
int i;
unsigned int busa = dma_addr & PAGE_MASK;
unsigned long off = dma_addr & ~PAGE_MASK;
unsigned int npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT;
unsigned int ioptex = (busa - iommu->start) >> PAGE_SHIFT;
unsigned int i;
BUG_ON(busa < iommu->start);
ioptex = (busa - iommu->start) >> PAGE_SHIFT;
for (i = 0; i < npages; i++) {
iopte_val(iommu->page_table[ioptex + i]) = 0;
iommu_invalidate_page(iommu->regs, busa);
......@@ -306,25 +290,15 @@ static void iommu_release_one(struct device *dev, u32 busa, int npages)
bit_map_clear(&iommu->usemap, ioptex, npages);
}
static void sbus_iommu_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t len, enum dma_data_direction dir, unsigned long attrs)
{
unsigned long off = dma_addr & ~PAGE_MASK;
int npages;
npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT;
iommu_release_one(dev, dma_addr & PAGE_MASK, npages);
}
static void sbus_iommu_unmap_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *sg;
int i, n;
int i;
for_each_sg(sgl, sg, nents, i) {
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
iommu_release_one(dev, sg->dma_address & PAGE_MASK, n);
sbus_iommu_unmap_page(dev, sg->dma_address, sg->length, dir,
attrs);
sg->dma_address = 0x21212121;
}
}
......
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