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:43:15 -0500
committerDan Williams <dan.j.williams@intel.com>2011-01-04 22:16:13 -0500
commit542361f8e385355c68e263eba49d4306739b9220 (patch)
tree64d465d026c348f4b5d945cb53aaaf12fb8338a3 /drivers/dma/amba-pl08x.c
parent5f638b4f313e345bf02700910e581bccf71212f5 (diff)
ARM: PL08x: don't manipulate txd->srcbus or txd->dstbus during LLI fill
Don't alter any txd->srcbus or txd->dstbus values while building the LLI list. This allows us to see the original dma_addr_t values passed in via the prep_memcpy() method. 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.c159
1 files changed, 83 insertions, 76 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index be7fa174d6c0..39970c5038d6 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -481,38 +481,45 @@ static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
481 return retbits; 481 return retbits;
482} 482}
483 483
484struct pl08x_lli_build_data {
485 struct pl08x_txd *txd;
486 struct pl08x_driver_data *pl08x;
487 struct pl08x_bus_data srcbus;
488 struct pl08x_bus_data dstbus;
489 size_t remainder;
490};
491
484/* 492/*
485 * Autoselect a master bus to use for the transfer 493 * Autoselect a master bus to use for the transfer
486 * this prefers the destination bus if both available 494 * this prefers the destination bus if both available
487 * if fixed address on one bus the other will be chosen 495 * if fixed address on one bus the other will be chosen
488 */ 496 */
489static void pl08x_choose_master_bus(struct pl08x_bus_data *src_bus, 497static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
490 struct pl08x_bus_data *dst_bus, struct pl08x_bus_data **mbus, 498 struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
491 struct pl08x_bus_data **sbus, u32 cctl)
492{ 499{
493 if (!(cctl & PL080_CONTROL_DST_INCR)) { 500 if (!(cctl & PL080_CONTROL_DST_INCR)) {
494 *mbus = src_bus; 501 *mbus = &bd->srcbus;
495 *sbus = dst_bus; 502 *sbus = &bd->dstbus;
496 } else if (!(cctl & PL080_CONTROL_SRC_INCR)) { 503 } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
497 *mbus = dst_bus; 504 *mbus = &bd->dstbus;
498 *sbus = src_bus; 505 *sbus = &bd->srcbus;
499 } else { 506 } else {
500 if (dst_bus->buswidth == 4) { 507 if (bd->dstbus.buswidth == 4) {
501 *mbus = dst_bus; 508 *mbus = &bd->dstbus;
502 *sbus = src_bus; 509 *sbus = &bd->srcbus;
503 } else if (src_bus->buswidth == 4) { 510 } else if (bd->srcbus.buswidth == 4) {
504 *mbus = src_bus; 511 *mbus = &bd->srcbus;
505 *sbus = dst_bus; 512 *sbus = &bd->dstbus;
506 } else if (dst_bus->buswidth == 2) { 513 } else if (bd->dstbus.buswidth == 2) {
507 *mbus = dst_bus; 514 *mbus = &bd->dstbus;
508 *sbus = src_bus; 515 *sbus = &bd->srcbus;
509 } else if (src_bus->buswidth == 2) { 516 } else if (bd->srcbus.buswidth == 2) {
510 *mbus = src_bus; 517 *mbus = &bd->srcbus;
511 *sbus = dst_bus; 518 *sbus = &bd->dstbus;
512 } else { 519 } else {
513 /* src_bus->buswidth == 1 */ 520 /* bd->srcbus.buswidth == 1 */
514 *mbus = dst_bus; 521 *mbus = &bd->dstbus;
515 *sbus = src_bus; 522 *sbus = &bd->srcbus;
516 } 523 }
517 } 524 }
518} 525}
@@ -521,29 +528,29 @@ static void pl08x_choose_master_bus(struct pl08x_bus_data *src_bus,
521 * Fills in one LLI for a certain transfer descriptor 528 * Fills in one LLI for a certain transfer descriptor
522 * and advance the counter 529 * and advance the counter
523 */ 530 */
524static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x, 531static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
525 struct pl08x_txd *txd, int num_llis, int len, u32 cctl, u32 *remainder) 532 int num_llis, int len, u32 cctl)
526{ 533{
527 struct pl08x_lli *llis_va = txd->llis_va; 534 struct pl08x_lli *llis_va = bd->txd->llis_va;
528 dma_addr_t llis_bus = txd->llis_bus; 535 dma_addr_t llis_bus = bd->txd->llis_bus;
529 536
530 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS); 537 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
531 538
532 llis_va[num_llis].cctl = cctl; 539 llis_va[num_llis].cctl = cctl;
533 llis_va[num_llis].src = txd->srcbus.addr; 540 llis_va[num_llis].src = bd->srcbus.addr;
534 llis_va[num_llis].dst = txd->dstbus.addr; 541 llis_va[num_llis].dst = bd->dstbus.addr;
535 llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli); 542 llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
536 if (pl08x->lli_buses & PL08X_AHB2) 543 if (bd->pl08x->lli_buses & PL08X_AHB2)
537 llis_va[num_llis].lli |= PL080_LLI_LM_AHB2; 544 llis_va[num_llis].lli |= PL080_LLI_LM_AHB2;
538 545
539 if (cctl & PL080_CONTROL_SRC_INCR) 546 if (cctl & PL080_CONTROL_SRC_INCR)
540 txd->srcbus.addr += len; 547 bd->srcbus.addr += len;
541 if (cctl & PL080_CONTROL_DST_INCR) 548 if (cctl & PL080_CONTROL_DST_INCR)
542 txd->dstbus.addr += len; 549 bd->dstbus.addr += len;
543 550
544 BUG_ON(*remainder < len); 551 BUG_ON(bd->remainder < len);
545 552
546 *remainder -= len; 553 bd->remainder -= len;
547} 554}
548 555
549/* 556/*
@@ -567,7 +574,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
567 struct pl08x_txd *txd) 574 struct pl08x_txd *txd)
568{ 575{
569 struct pl08x_bus_data *mbus, *sbus; 576 struct pl08x_bus_data *mbus, *sbus;
570 size_t remainder; 577 struct pl08x_lli_build_data bd;
571 int num_llis = 0; 578 int num_llis = 0;
572 u32 cctl; 579 u32 cctl;
573 size_t max_bytes_per_lli; 580 size_t max_bytes_per_lli;
@@ -586,38 +593,43 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
586 /* Get the default CCTL */ 593 /* Get the default CCTL */
587 cctl = txd->cctl; 594 cctl = txd->cctl;
588 595
596 bd.txd = txd;
597 bd.pl08x = pl08x;
598 bd.srcbus.addr = txd->srcbus.addr;
599 bd.dstbus.addr = txd->dstbus.addr;
600
589 /* Find maximum width of the source bus */ 601 /* Find maximum width of the source bus */
590 txd->srcbus.maxwidth = 602 bd.srcbus.maxwidth =
591 pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_SWIDTH_MASK) >> 603 pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_SWIDTH_MASK) >>
592 PL080_CONTROL_SWIDTH_SHIFT); 604 PL080_CONTROL_SWIDTH_SHIFT);
593 605
594 /* Find maximum width of the destination bus */ 606 /* Find maximum width of the destination bus */
595 txd->dstbus.maxwidth = 607 bd.dstbus.maxwidth =
596 pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >> 608 pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >>
597 PL080_CONTROL_DWIDTH_SHIFT); 609 PL080_CONTROL_DWIDTH_SHIFT);
598 610
599 /* Set up the bus widths to the maximum */ 611 /* Set up the bus widths to the maximum */
600 txd->srcbus.buswidth = txd->srcbus.maxwidth; 612 bd.srcbus.buswidth = bd.srcbus.maxwidth;
601 txd->dstbus.buswidth = txd->dstbus.maxwidth; 613 bd.dstbus.buswidth = bd.dstbus.maxwidth;
602 dev_vdbg(&pl08x->adev->dev, 614 dev_vdbg(&pl08x->adev->dev,
603 "%s source bus is %d bytes wide, dest bus is %d bytes wide\n", 615 "%s source bus is %d bytes wide, dest bus is %d bytes wide\n",
604 __func__, txd->srcbus.buswidth, txd->dstbus.buswidth); 616 __func__, bd.srcbus.buswidth, bd.dstbus.buswidth);
605 617
606 618
607 /* 619 /*
608 * Bytes transferred == tsize * MIN(buswidths), not max(buswidths) 620 * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
609 */ 621 */
610 max_bytes_per_lli = min(txd->srcbus.buswidth, txd->dstbus.buswidth) * 622 max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
611 PL080_CONTROL_TRANSFER_SIZE_MASK; 623 PL080_CONTROL_TRANSFER_SIZE_MASK;
612 dev_vdbg(&pl08x->adev->dev, 624 dev_vdbg(&pl08x->adev->dev,
613 "%s max bytes per lli = %zu\n", 625 "%s max bytes per lli = %zu\n",
614 __func__, max_bytes_per_lli); 626 __func__, max_bytes_per_lli);
615 627
616 /* We need to count this down to zero */ 628 /* We need to count this down to zero */
617 remainder = txd->len; 629 bd.remainder = txd->len;
618 dev_vdbg(&pl08x->adev->dev, 630 dev_vdbg(&pl08x->adev->dev,
619 "%s remainder = %zu\n", 631 "%s remainder = %zu\n",
620 __func__, remainder); 632 __func__, bd.remainder);
621 633
622 /* 634 /*
623 * Choose bus to align to 635 * Choose bus to align to
@@ -625,22 +637,20 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
625 * - if fixed address on one bus chooses other 637 * - if fixed address on one bus chooses other
626 * - modifies cctl to choose an appropriate master 638 * - modifies cctl to choose an appropriate master
627 */ 639 */
628 pl08x_choose_master_bus(&txd->srcbus, &txd->dstbus, 640 pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
629 &mbus, &sbus, cctl);
630 641
631 if (txd->len < mbus->buswidth) { 642 if (txd->len < mbus->buswidth) {
632 /* 643 /*
633 * Less than a bus width available 644 * Less than a bus width available
634 * - send as single bytes 645 * - send as single bytes
635 */ 646 */
636 while (remainder) { 647 while (bd.remainder) {
637 dev_vdbg(&pl08x->adev->dev, 648 dev_vdbg(&pl08x->adev->dev,
638 "%s single byte LLIs for a transfer of " 649 "%s single byte LLIs for a transfer of "
639 "less than a bus width (remain 0x%08x)\n", 650 "less than a bus width (remain 0x%08x)\n",
640 __func__, remainder); 651 __func__, bd.remainder);
641 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 652 cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
642 pl08x_fill_lli_for_desc(pl08x, txd, num_llis++, 1, 653 pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
643 cctl, &remainder);
644 total_bytes++; 654 total_bytes++;
645 } 655 }
646 } else { 656 } else {
@@ -652,10 +662,9 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
652 dev_vdbg(&pl08x->adev->dev, 662 dev_vdbg(&pl08x->adev->dev,
653 "%s adjustment lli for less than bus width " 663 "%s adjustment lli for less than bus width "
654 "(remain 0x%08x)\n", 664 "(remain 0x%08x)\n",
655 __func__, remainder); 665 __func__, bd.remainder);
656 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 666 cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
657 pl08x_fill_lli_for_desc(pl08x, txd, num_llis++, 1, 667 pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
658 cctl, &remainder);
659 total_bytes++; 668 total_bytes++;
660 } 669 }
661 670
@@ -675,14 +684,14 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
675 * Make largest possible LLIs until less than one bus 684 * Make largest possible LLIs until less than one bus
676 * width left 685 * width left
677 */ 686 */
678 while (remainder > (mbus->buswidth - 1)) { 687 while (bd.remainder > (mbus->buswidth - 1)) {
679 size_t lli_len, target_len, tsize, odd_bytes; 688 size_t lli_len, target_len, tsize, odd_bytes;
680 689
681 /* 690 /*
682 * If enough left try to send max possible, 691 * If enough left try to send max possible,
683 * otherwise try to send the remainder 692 * otherwise try to send the remainder
684 */ 693 */
685 target_len = min(remainder, max_bytes_per_lli); 694 target_len = min(bd.remainder, max_bytes_per_lli);
686 695
687 /* 696 /*
688 * Set bus lengths for incrementing buses to the 697 * Set bus lengths for incrementing buses to the
@@ -690,24 +699,24 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
690 * limiting on the target length calculated above. 699 * limiting on the target length calculated above.
691 */ 700 */
692 if (cctl & PL080_CONTROL_SRC_INCR) 701 if (cctl & PL080_CONTROL_SRC_INCR)
693 txd->srcbus.fill_bytes = 702 bd.srcbus.fill_bytes =
694 pl08x_pre_boundary(txd->srcbus.addr, 703 pl08x_pre_boundary(bd.srcbus.addr,
695 target_len); 704 target_len);
696 else 705 else
697 txd->srcbus.fill_bytes = target_len; 706 bd.srcbus.fill_bytes = target_len;
698 707
699 if (cctl & PL080_CONTROL_DST_INCR) 708 if (cctl & PL080_CONTROL_DST_INCR)
700 txd->dstbus.fill_bytes = 709 bd.dstbus.fill_bytes =
701 pl08x_pre_boundary(txd->dstbus.addr, 710 pl08x_pre_boundary(bd.dstbus.addr,
702 target_len); 711 target_len);
703 else 712 else
704 txd->dstbus.fill_bytes = target_len; 713 bd.dstbus.fill_bytes = target_len;
705 714
706 /* Find the nearest */ 715 /* Find the nearest */
707 lli_len = min(txd->srcbus.fill_bytes, 716 lli_len = min(bd.srcbus.fill_bytes,
708 txd->dstbus.fill_bytes); 717 bd.dstbus.fill_bytes);
709 718
710 BUG_ON(lli_len > remainder); 719 BUG_ON(lli_len > bd.remainder);
711 720
712 if (lli_len <= 0) { 721 if (lli_len <= 0) {
713 dev_err(&pl08x->adev->dev, 722 dev_err(&pl08x->adev->dev,
@@ -764,15 +773,15 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
764 } 773 }
765 774
766 cctl = pl08x_cctl_bits(cctl, 775 cctl = pl08x_cctl_bits(cctl,
767 txd->srcbus.buswidth, 776 bd.srcbus.buswidth,
768 txd->dstbus.buswidth, 777 bd.dstbus.buswidth,
769 tsize); 778 tsize);
770 779
771 dev_vdbg(&pl08x->adev->dev, 780 dev_vdbg(&pl08x->adev->dev,
772 "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n", 781 "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
773 __func__, lli_len, remainder); 782 __func__, lli_len, bd.remainder);
774 pl08x_fill_lli_for_desc(pl08x, txd, num_llis++, 783 pl08x_fill_lli_for_desc(&bd, num_llis++,
775 lli_len, cctl, &remainder); 784 lli_len, cctl);
776 total_bytes += lli_len; 785 total_bytes += lli_len;
777 } 786 }
778 787
@@ -784,14 +793,13 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
784 */ 793 */
785 int j; 794 int j;
786 for (j = 0; (j < mbus->buswidth) 795 for (j = 0; (j < mbus->buswidth)
787 && (remainder); j++) { 796 && (bd.remainder); j++) {
788 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 797 cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
789 dev_vdbg(&pl08x->adev->dev, 798 dev_vdbg(&pl08x->adev->dev,
790 "%s align with boundary, single byte (remain 0x%08zx)\n", 799 "%s align with boundary, single byte (remain 0x%08zx)\n",
791 __func__, remainder); 800 __func__, bd.remainder);
792 pl08x_fill_lli_for_desc(pl08x, txd, 801 pl08x_fill_lli_for_desc(&bd,
793 num_llis++, 1, cctl, 802 num_llis++, 1, cctl);
794 &remainder);
795 total_bytes++; 803 total_bytes++;
796 } 804 }
797 } 805 }
@@ -800,13 +808,12 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
800 /* 808 /*
801 * Send any odd bytes 809 * Send any odd bytes
802 */ 810 */
803 while (remainder) { 811 while (bd.remainder) {
804 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 812 cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
805 dev_vdbg(&pl08x->adev->dev, 813 dev_vdbg(&pl08x->adev->dev,
806 "%s align with boundary, single odd byte (remain %zu)\n", 814 "%s align with boundary, single odd byte (remain %zu)\n",
807 __func__, remainder); 815 __func__, bd.remainder);
808 pl08x_fill_lli_for_desc(pl08x, txd, num_llis++, 1, 816 pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
809 cctl, &remainder);
810 total_bytes++; 817 total_bytes++;
811 } 818 }
812 } 819 }