Commit 489797e7 authored by Pete Zaitcev's avatar Pete Zaitcev Committed by David S. Miller

[sparc] Fix off-by-one in s/g handling

parent eaf3a1b6
...@@ -135,7 +135,8 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus ...@@ -135,7 +135,8 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus
/* FIXME: Cache some resolved pages - often several sg entries are to the same page */ /* FIXME: Cache some resolved pages - often several sg entries are to the same page */
spin_lock_irqsave(&iounit->lock, flags); spin_lock_irqsave(&iounit->lock, flags);
for (; sz >= 0; sz--) { while (sz != 0) {
--sz;
sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length);
sg[sz].dvma_length = sg[sz].length; sg[sz].dvma_length = sg[sz].length;
} }
...@@ -163,7 +164,8 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_ ...@@ -163,7 +164,8 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
spin_lock_irqsave(&iounit->lock, flags); spin_lock_irqsave(&iounit->lock, flags);
for (; sz >= 0; sz--) { while (sz != 0) {
--sz;
len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT; len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr));
......
...@@ -171,7 +171,8 @@ static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sb ...@@ -171,7 +171,8 @@ static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sb
static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
{ {
for (; sz >= 0; sz--) { while (sz != 0) {
--sz;
sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset); sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset);
sg[sz].dvma_length = (__u32) (sg[sz].length); sg[sz].dvma_length = (__u32) (sg[sz].length);
} }
...@@ -180,7 +181,8 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sb ...@@ -180,7 +181,8 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sb
static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
{ {
flush_page_for_dma(0); flush_page_for_dma(0);
for (; sz >= 0; sz--) { while (sz != 0) {
--sz;
sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset); sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset);
sg[sz].dvma_length = (__u32) (sg[sz].length); sg[sz].dvma_length = (__u32) (sg[sz].length);
} }
...@@ -191,6 +193,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu ...@@ -191,6 +193,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
unsigned long page, oldpage = 0; unsigned long page, oldpage = 0;
while(sz >= 0) { while(sz >= 0) {
--sz;
page = ((unsigned long) sg[sz].offset) & PAGE_MASK; page = ((unsigned long) sg[sz].offset) & PAGE_MASK;
if (oldpage == page) if (oldpage == page)
page += PAGE_SIZE; /* We flushed that page already */ page += PAGE_SIZE; /* We flushed that page already */
...@@ -200,7 +203,6 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu ...@@ -200,7 +203,6 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
} }
sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset); sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset);
sg[sz].dvma_length = (__u32) (sg[sz].length); sg[sz].dvma_length = (__u32) (sg[sz].length);
sz--;
oldpage = page - PAGE_SIZE; oldpage = page - PAGE_SIZE;
} }
} }
......
...@@ -1219,10 +1219,10 @@ static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus ...@@ -1219,10 +1219,10 @@ static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus
static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
{ {
while (sz >= 0) { while (sz != 0) {
--sz;
sg[sz].dvma_address = (__u32)sun4c_lockarea(page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); sg[sz].dvma_address = (__u32)sun4c_lockarea(page_address(sg[sz].page) + sg[sz].offset, sg[sz].length);
sg[sz].dvma_length = sg[sz].length; sg[sz].dvma_length = sg[sz].length;
sz--;
} }
} }
...@@ -1235,9 +1235,9 @@ static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_ ...@@ -1235,9 +1235,9 @@ static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_
static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
{ {
while (sz >= 0) { while (sz != 0) {
--sz;
sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length); sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length);
sz--;
} }
} }
......
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