dmaengine/amba-pl08x: Align lli_len to max(src.width, dst.width)
authorViresh Kumar <viresh.kumar@st.com>
Fri, 5 Aug 2011 10:02:40 +0000 (15:32 +0530)
committerVinod Koul <vinod.koul@intel.com>
Thu, 25 Aug 2011 14:03:39 +0000 (19:33 +0530)
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>
drivers/dma/amba-pl08x.c

index 45d8a5d5bccdfc15c68850629adcbd2c8dccbbb4..4bcf6036f35d38d44fce752e1c49ef144d58d667 100644 (file)
@@ -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 "