Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 273869
b: refs/heads/master
c: 16a2e7d
h: refs/heads/master
i:
  273867: b557380
v: v3
  • Loading branch information
Viresh Kumar authored and Vinod Koul committed Aug 25, 2011
1 parent 8f90734 commit bb93ac0
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 127 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 28da28365da3f3bea1d4b7212a8a40e4b9ac3229
refs/heads/master: 16a2e7d359b9fc64fb8a6717c0642691b1e60bb7
141 changes: 17 additions & 124 deletions trunk/drivers/dma/amba-pl08x.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,6 @@ struct pl08x_driver_data {
* PL08X specific defines
*/

/*
* Memory boundaries: the manual for PL08x says that the controller
* cannot read past a 1KiB boundary, so these defines are used to
* create transfer LLIs that do not cross such boundaries.
*/
#define PL08X_BOUNDARY_SHIFT (10) /* 1KB 0x400 */
#define PL08X_BOUNDARY_SIZE (1 << PL08X_BOUNDARY_SHIFT)

/* Size (bytes) of each LLI buffer allocated for one transfer */
# define PL08X_LLI_TSFR_SIZE 0x2000

Expand Down Expand Up @@ -567,18 +559,6 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
bd->remainder -= len;
}

/*
* Return number of bytes to fill to boundary, or len.
* This calculation works for any value of addr.
*/
static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
{
size_t boundary_len = PL08X_BOUNDARY_SIZE -
(addr & (PL08X_BOUNDARY_SIZE - 1));

return min(boundary_len, len);
}

/*
* This fills in the table of LLIs for the transfer descriptor
* Note that we assume we never have to change the burst sizes
Expand Down Expand Up @@ -685,118 +665,30 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
* width left
*/
while (bd.remainder > (mbus->buswidth - 1)) {
size_t lli_len, target_len, tsize, odd_bytes;
size_t lli_len, tsize;

/*
* If enough left try to send max possible,
* otherwise try to send the remainder
*/
target_len = min(bd.remainder, max_bytes_per_lli);

lli_len = min(bd.remainder, max_bytes_per_lli);
/*
* Set bus lengths for incrementing buses to the
* number of bytes which fill to next memory boundary,
* limiting on the target length calculated above.
* Check against minimum bus alignment: Calculate actual
* transfer size in relation to bus width and get a
* maximum remainder of the smallest bus width - 1
*/
if (cctl & PL080_CONTROL_SRC_INCR)
bd.srcbus.fill_bytes =
pl08x_pre_boundary(bd.srcbus.addr,
target_len);
else
bd.srcbus.fill_bytes = target_len;

if (cctl & PL080_CONTROL_DST_INCR)
bd.dstbus.fill_bytes =
pl08x_pre_boundary(bd.dstbus.addr,
target_len);
else
bd.dstbus.fill_bytes = target_len;

/* Find the nearest */
lli_len = min(bd.srcbus.fill_bytes,
bd.dstbus.fill_bytes);

BUG_ON(lli_len > bd.remainder);

if (lli_len <= 0) {
dev_err(&pl08x->adev->dev,
"%s lli_len is %zu, <= 0\n",
__func__, lli_len);
return 0;
}

if (lli_len == target_len) {
/*
* Can send what we wanted.
* Maintain alignment
*/
lli_len = (lli_len/mbus->buswidth) *
mbus->buswidth;
odd_bytes = 0;
} else {
/*
* So now we know how many bytes to transfer
* to get to the nearest boundary. The next
* LLI will past the boundary. However, we
* may be working to a boundary on the slave
* bus. We need to ensure the master stays
* aligned, and that we are working in
* multiples of the bus widths.
*/
odd_bytes = lli_len % mbus->buswidth;
lli_len -= odd_bytes;

}

if (lli_len) {
/*
* Check against minimum bus alignment:
* Calculate actual transfer size in relation
* to bus width an get a maximum remainder of
* the smallest bus width - 1
*/
/* FIXME: use round_down()? */
tsize = lli_len / min(mbus->buswidth,
sbus->buswidth);
lli_len = tsize * min(mbus->buswidth,
sbus->buswidth);

if (target_len != lli_len) {
dev_vdbg(&pl08x->adev->dev,
"%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
__func__, target_len, lli_len, txd->len);
}

cctl = pl08x_cctl_bits(cctl,
bd.srcbus.buswidth,
bd.dstbus.buswidth,
tsize);

dev_vdbg(&pl08x->adev->dev,
"%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
__func__, lli_len, bd.remainder);
pl08x_fill_lli_for_desc(&bd, num_llis++,
lli_len, cctl);
total_bytes += lli_len;
}
tsize = lli_len / min(mbus->buswidth, sbus->buswidth);
lli_len = tsize * min(mbus->buswidth, sbus->buswidth);

if (odd_bytes) {
/*
* Creep past the boundary, maintaining
* master alignment
*/
int j;
for (j = 0; (j < mbus->buswidth)
&& (bd.remainder); j++) {
cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
dev_vdbg(&pl08x->adev->dev,
"%s align with boundary, single byte (remain 0x%08zx)\n",
__func__, bd.remainder);
pl08x_fill_lli_for_desc(&bd,
num_llis++, 1, cctl);
total_bytes++;
}
}
dev_vdbg(&pl08x->adev->dev,
"%s fill lli with single lli chunk of "
"size 0x%08zx (remainder 0x%08zx)\n",
__func__, lli_len, bd.remainder);

cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
bd.dstbus.buswidth, tsize);
pl08x_fill_lli_for_desc(&bd, num_llis++, lli_len, cctl);
total_bytes += lli_len;
}

/*
Expand All @@ -811,6 +703,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
total_bytes++;
}
}

if (total_bytes != txd->len) {
dev_err(&pl08x->adev->dev,
"%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
Expand Down
2 changes: 0 additions & 2 deletions trunk/include/linux/amba/pl08x.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,11 @@ struct pl08x_channel_data {
* @addr: current address
* @maxwidth: the maximum width of a transfer on this bus
* @buswidth: the width of this bus in bytes: 1, 2 or 4
* @fill_bytes: bytes required to fill to the next bus memory boundary
*/
struct pl08x_bus_data {
dma_addr_t addr;
u8 maxwidth;
u8 buswidth;
size_t fill_bytes;
};

/**
Expand Down

0 comments on commit bb93ac0

Please sign in to comment.