aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/amba-pl08x.c
diff options
context:
space:
mode:
authorRussell King - ARM Linux <linux@arm.linux.org.uk>2011-01-03 17:38:32 -0500
committerDan Williams <dan.j.williams@intel.com>2011-01-04 22:16:12 -0500
commitdb9f136a60c8727c8e1c9c4f2494821caebf5a7b (patch)
treed5311b870e634541e787a680d6d77bf9865f9645 /drivers/dma/amba-pl08x.c
parentbfddfb45056fa95a778f0baf463ac0f9fc926d5c (diff)
ARM: PL08x: clean up LLI lookup
As the LLI list is an array, we can use maths to locate which LLI index we're currently at, and then sum up the remaining LLI entries until we reach the end of the list. This makes the code much easier to read, and much less susceptible to falling off the end of the array. 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/amba-pl08x.c')
-rw-r--r--drivers/dma/amba-pl08x.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index a897315261bc..202c9e2d2e9e 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -340,53 +340,56 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
340static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan) 340static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
341{ 341{
342 struct pl08x_phy_chan *ch; 342 struct pl08x_phy_chan *ch;
343 struct pl08x_txd *txdi = NULL;
344 struct pl08x_txd *txd; 343 struct pl08x_txd *txd;
345 unsigned long flags; 344 unsigned long flags;
346 size_t bytes = 0; 345 size_t bytes = 0;
347 346
348 spin_lock_irqsave(&plchan->lock, flags); 347 spin_lock_irqsave(&plchan->lock, flags);
349
350 ch = plchan->phychan; 348 ch = plchan->phychan;
351 txd = plchan->at; 349 txd = plchan->at;
352 350
353 /* 351 /*
354 * Next follow the LLIs to get the number of pending bytes in the 352 * Follow the LLIs to get the number of remaining
355 * currently active transaction. 353 * bytes in the currently active transaction.
356 */ 354 */
357 if (ch && txd) { 355 if (ch && txd) {
358 struct pl08x_lli *llis_va = txd->llis_va;
359 struct pl08x_lli *llis_bus = (struct pl08x_lli *) txd->llis_bus;
360 u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2; 356 u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
361 357
362 /* First get the bytes in the current active LLI */ 358 /* First get the remaining bytes in the active transfer */
363 bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL)); 359 bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
364 360
365 if (clli) { 361 if (clli) {
366 int i = 0; 362 struct pl08x_lli *llis_va = txd->llis_va;
363 dma_addr_t llis_bus = txd->llis_bus;
364 int index;
367 365
368 /* Forward to the LLI pointed to by clli */ 366 BUG_ON(clli < llis_bus || clli >= llis_bus +
369 while ((clli != (u32) &(llis_bus[i])) && 367 sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
370 (i < MAX_NUM_TSFR_LLIS)) 368
371 i++; 369 /*
370 * Locate the next LLI - as this is an array,
371 * it's simple maths to find.
372 */
373 index = (clli - llis_bus) / sizeof(struct pl08x_lli);
374
375 for (; index < MAX_NUM_TSFR_LLIS; index++) {
376 bytes += get_bytes_in_cctl(llis_va[index].cctl);
372 377
373 while (clli) {
374 bytes += get_bytes_in_cctl(llis_va[i].cctl);
375 /* 378 /*
376 * A LLI pointer of 0 terminates the LLI list 379 * A LLI pointer of 0 terminates the LLI list
377 */ 380 */
378 clli = llis_va[i].lli; 381 if (!llis_va[index].lli)
379 i++; 382 break;
380 } 383 }
381 } 384 }
382 } 385 }
383 386
384 /* Sum up all queued transactions */ 387 /* Sum up all queued transactions */
385 if (!list_empty(&plchan->desc_list)) { 388 if (!list_empty(&plchan->desc_list)) {
389 struct pl08x_txd *txdi;
386 list_for_each_entry(txdi, &plchan->desc_list, node) { 390 list_for_each_entry(txdi, &plchan->desc_list, node) {
387 bytes += txdi->len; 391 bytes += txdi->len;
388 } 392 }
389
390 } 393 }
391 394
392 spin_unlock_irqrestore(&plchan->lock, flags); 395 spin_unlock_irqrestore(&plchan->lock, flags);