summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@st.com>2011-08-05 10:02:40 (GMT)
committerVinod Koul <vinod.koul@intel.com>2011-08-25 14:03:39 (GMT)
commite0719165801fad04073e7dcd90e4afd02aba3fb7 (patch)
tree8b1cb65f26487d6fa0aba776e88c8e9b7f0aa22c
parent03af500f743f486648fc8afc38593e9844411945 (diff)
downloadlinux-e0719165801fad04073e7dcd90e4afd02aba3fb7.tar.xz
dmaengine/amba-pl08x: Align lli_len to max(src.width, dst.width)
Currently lli_len is aligned to min of two widths, which looks to be incorrect. Instead it should be aligned to max of both widths. Lets say, total_size = 441 bytes MIN: lets check if min() suits or not: CASE 1: srcwidth = 1, dstwidth = 4 min(src, dst) = 1 i.e. We program transfer size in control reg to 441. Now, till 440 bytes everything is fine, but on the last byte DMAC can't transfer 1 byte to dst, as its width is 4. CASE 2: srcwidth = 4, dstwidth = 1 min(src, dst) = 1 i.e. we program transfer size in control reg to 110 (data transferred = 110 * srcwidth). So, here too 1 byte is left, but on the source side. MAX: Lets check if max() suits or not: CASE 3: srcwidth = 1, dstwidth = 4 max(src, dst) = 4 Aligned size is 440 i.e. We program transfer size in control reg to 440. Now, all 440 bytes will be transferred without any issues. CASE 4: srcwidth = 4, dstwidth = 1 max(src, dst) = 4 Aligned size is 440 i.e. We program transfer size in control reg to 110 (data transferred = 110 * srcwidth). Now, also all 440 bytes will be transferred without any issues. Signed-off-by: Viresh Kumar <viresh.kumar@st.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/amba-pl08x.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 45d8a5d..4bcf603 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -669,20 +669,22 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
* width left
*/
while (bd.remainder > (mbus->buswidth - 1)) {
- size_t lli_len, tsize;
+ size_t lli_len, tsize, width;
/*
* If enough left try to send max possible,
* otherwise try to send the remainder
*/
lli_len = min(bd.remainder, max_bytes_per_lli);
+
/*
- * Check against minimum bus alignment: Calculate actual
+ * Check against maximum bus alignment: Calculate actual
* transfer size in relation to bus width and get a
- * maximum remainder of the smallest bus width - 1
+ * maximum remainder of the highest bus width - 1
*/
- tsize = lli_len / min(mbus->buswidth, sbus->buswidth);
- lli_len = tsize * min(mbus->buswidth, sbus->buswidth);
+ width = max(mbus->buswidth, sbus->buswidth);
+ lli_len = (lli_len / width) * width;
+ tsize = lli_len / bd.srcbus.buswidth;
dev_vdbg(&pl08x->adev->dev,
"%s fill lli with single lli chunk of "