aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorRussell King - ARM Linux <linux@arm.linux.org.uk>2011-01-03 17:42:14 -0500
committerDan Williams <dan.j.williams@intel.com>2011-01-04 22:16:13 -0500
commitb61be8d728abad7fd98e62e98f22325f8f254b51 (patch)
treea4c5d5aa7e942122fc24d45d6ab977de5032be99 /drivers/dma
parent0059005f2cbf4847551b9ad9915ffffe23aef0b9 (diff)
ARM: PL08x: ensure pl08x_pre_boundary() works for any value of addr
pl08x_pre_boundary() was unsafe with addresses towards the top of memory space: boundary = ((addr >> PL08X_BOUNDARY_SHIFT) + 1) << PL08X_BOUNDARY_SHIFT; This can overflow a 32-bit number, producing zero. When it does: if (boundary < addr + len) return boundary - addr; else return len; results in (boundary - addr) returning either a large positive value. Also if addr + len overflows, this calculation also fails. We can fix this trivially as the only thing we're actually interested in is the value of the least significant PL08X_BOUNDARY_SHIFT bits: boundary_len = PL08X_BOUNDARY_SIZE - (addr & (PL08X_BOUNDARY_SIZE - 1)); gives us the number of bytes before 'addr' becomes a multiple of PL08X_BOUNDARY_SIZE. We can then just take the min() of the two calculated lengths. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/amba-pl08x.c14
1 files changed, 5 insertions, 9 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index f61940434669..7c327c315878 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -547,19 +547,15 @@ static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
547} 547}
548 548
549/* 549/*
550 * Return number of bytes to fill to boundary, or len 550 * Return number of bytes to fill to boundary, or len.
551 * This calculation works for any value of addr.
551 */ 552 */
552static inline size_t pl08x_pre_boundary(u32 addr, size_t len) 553static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
553{ 554{
554 u32 boundary; 555 size_t boundary_len = PL08X_BOUNDARY_SIZE -
556 (addr & (PL08X_BOUNDARY_SIZE - 1));
555 557
556 boundary = ((addr >> PL08X_BOUNDARY_SHIFT) + 1) 558 return min(boundary_len, len);
557 << PL08X_BOUNDARY_SHIFT;
558
559 if (boundary < addr + len)
560 return boundary - addr;
561 else
562 return len;
563} 559}
564 560
565/* 561/*