diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2007-10-10 05:42:55 -0400 |
---|---|---|
committer | Bryan Wu <bryan.wu@analog.com> | 2007-10-10 05:42:55 -0400 |
commit | 1a7d91d651f25005c4f507aebf9eab17e508889c (patch) | |
tree | d3070fe9edd252e485a07fb41c5ee8a4df4cec5c /arch/blackfin/kernel/bfin_dma_5xx.c | |
parent | a359cca71e73a83612b5bbecea41d3b7a47160ca (diff) |
Blackfin arch: flush/inv the correct range when using write back cache and fix bugs find by dmacopy
- flush/inv the correct range
- dmacopy test failed when policy is write_back - invalidate before dma
http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3367
It's the cache invalidate what is causing the issue.
There is no invalidate only instruction it's always: FLUSHINV
So when we "invalidate" after the DMA we might (do) overwrite freshly
dma'ed data by dirty Cache WB content.
Fixed by moving the "invalidate" at the beginning of dma_memcpy.
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/kernel/bfin_dma_5xx.c')
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 17edd6599959..e19164fb4cd1 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -436,6 +436,10 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size) | |||
436 | blackfin_dcache_flush_range((unsigned int)src, | 436 | blackfin_dcache_flush_range((unsigned int)src, |
437 | (unsigned int)(src + size)); | 437 | (unsigned int)(src + size)); |
438 | 438 | ||
439 | if ((unsigned long)dest < memory_end) | ||
440 | blackfin_dcache_invalidate_range((unsigned int)dest, | ||
441 | (unsigned int)(dest + size)); | ||
442 | |||
439 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 443 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
440 | 444 | ||
441 | if ((unsigned long)src < (unsigned long)dest) | 445 | if ((unsigned long)src < (unsigned long)dest) |
@@ -543,6 +547,8 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size) | |||
543 | } | 547 | } |
544 | } | 548 | } |
545 | 549 | ||
550 | SSYNC(); | ||
551 | |||
546 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) | 552 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) |
547 | ; | 553 | ; |
548 | 554 | ||
@@ -552,9 +558,6 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size) | |||
552 | bfin_write_MDMA_S0_CONFIG(0); | 558 | bfin_write_MDMA_S0_CONFIG(0); |
553 | bfin_write_MDMA_D0_CONFIG(0); | 559 | bfin_write_MDMA_D0_CONFIG(0); |
554 | 560 | ||
555 | if ((unsigned long)dest < memory_end) | ||
556 | blackfin_dcache_invalidate_range((unsigned int)dest, | ||
557 | (unsigned int)(dest + size)); | ||
558 | local_irq_restore(flags); | 561 | local_irq_restore(flags); |
559 | 562 | ||
560 | return dest; | 563 | return dest; |
@@ -589,7 +592,8 @@ void dma_outsb(unsigned long addr, const void *buf, unsigned short len) | |||
589 | 592 | ||
590 | local_irq_save(flags); | 593 | local_irq_save(flags); |
591 | 594 | ||
592 | blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len); | 595 | blackfin_dcache_flush_range((unsigned int)buf, |
596 | (unsigned int)(buf) + len); | ||
593 | 597 | ||
594 | bfin_write_MDMA_D0_START_ADDR(addr); | 598 | bfin_write_MDMA_D0_START_ADDR(addr); |
595 | bfin_write_MDMA_D0_X_COUNT(len); | 599 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -604,6 +608,8 @@ void dma_outsb(unsigned long addr, const void *buf, unsigned short len) | |||
604 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); | 608 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); |
605 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); | 609 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); |
606 | 610 | ||
611 | SSYNC(); | ||
612 | |||
607 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 613 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
608 | 614 | ||
609 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 615 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
@@ -620,6 +626,9 @@ void dma_insb(unsigned long addr, void *buf, unsigned short len) | |||
620 | { | 626 | { |
621 | unsigned long flags; | 627 | unsigned long flags; |
622 | 628 | ||
629 | blackfin_dcache_invalidate_range((unsigned int)buf, | ||
630 | (unsigned int)(buf) + len); | ||
631 | |||
623 | local_irq_save(flags); | 632 | local_irq_save(flags); |
624 | bfin_write_MDMA_D0_START_ADDR(buf); | 633 | bfin_write_MDMA_D0_START_ADDR(buf); |
625 | bfin_write_MDMA_D0_X_COUNT(len); | 634 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -634,7 +643,7 @@ void dma_insb(unsigned long addr, void *buf, unsigned short len) | |||
634 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); | 643 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); |
635 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); | 644 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); |
636 | 645 | ||
637 | blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len); | 646 | SSYNC(); |
638 | 647 | ||
639 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 648 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
640 | 649 | ||
@@ -653,7 +662,8 @@ void dma_outsw(unsigned long addr, const void *buf, unsigned short len) | |||
653 | 662 | ||
654 | local_irq_save(flags); | 663 | local_irq_save(flags); |
655 | 664 | ||
656 | blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len); | 665 | blackfin_dcache_flush_range((unsigned int)buf, |
666 | (unsigned int)(buf) + len * sizeof(short)); | ||
657 | 667 | ||
658 | bfin_write_MDMA_D0_START_ADDR(addr); | 668 | bfin_write_MDMA_D0_START_ADDR(addr); |
659 | bfin_write_MDMA_D0_X_COUNT(len); | 669 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -668,6 +678,8 @@ void dma_outsw(unsigned long addr, const void *buf, unsigned short len) | |||
668 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); | 678 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); |
669 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); | 679 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); |
670 | 680 | ||
681 | SSYNC(); | ||
682 | |||
671 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 683 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
672 | 684 | ||
673 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 685 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
@@ -683,6 +695,9 @@ void dma_insw(unsigned long addr, void *buf, unsigned short len) | |||
683 | { | 695 | { |
684 | unsigned long flags; | 696 | unsigned long flags; |
685 | 697 | ||
698 | blackfin_dcache_invalidate_range((unsigned int)buf, | ||
699 | (unsigned int)(buf) + len * sizeof(short)); | ||
700 | |||
686 | local_irq_save(flags); | 701 | local_irq_save(flags); |
687 | 702 | ||
688 | bfin_write_MDMA_D0_START_ADDR(buf); | 703 | bfin_write_MDMA_D0_START_ADDR(buf); |
@@ -698,7 +713,7 @@ void dma_insw(unsigned long addr, void *buf, unsigned short len) | |||
698 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); | 713 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); |
699 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); | 714 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); |
700 | 715 | ||
701 | blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len); | 716 | SSYNC(); |
702 | 717 | ||
703 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 718 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
704 | 719 | ||
@@ -717,7 +732,8 @@ void dma_outsl(unsigned long addr, const void *buf, unsigned short len) | |||
717 | 732 | ||
718 | local_irq_save(flags); | 733 | local_irq_save(flags); |
719 | 734 | ||
720 | blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len); | 735 | blackfin_dcache_flush_range((unsigned int)buf, |
736 | (unsigned int)(buf) + len * sizeof(long)); | ||
721 | 737 | ||
722 | bfin_write_MDMA_D0_START_ADDR(addr); | 738 | bfin_write_MDMA_D0_START_ADDR(addr); |
723 | bfin_write_MDMA_D0_X_COUNT(len); | 739 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -732,6 +748,8 @@ void dma_outsl(unsigned long addr, const void *buf, unsigned short len) | |||
732 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); | 748 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); |
733 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); | 749 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); |
734 | 750 | ||
751 | SSYNC(); | ||
752 | |||
735 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 753 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
736 | 754 | ||
737 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 755 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
@@ -747,6 +765,9 @@ void dma_insl(unsigned long addr, void *buf, unsigned short len) | |||
747 | { | 765 | { |
748 | unsigned long flags; | 766 | unsigned long flags; |
749 | 767 | ||
768 | blackfin_dcache_invalidate_range((unsigned int)buf, | ||
769 | (unsigned int)(buf) + len * sizeof(long)); | ||
770 | |||
750 | local_irq_save(flags); | 771 | local_irq_save(flags); |
751 | 772 | ||
752 | bfin_write_MDMA_D0_START_ADDR(buf); | 773 | bfin_write_MDMA_D0_START_ADDR(buf); |
@@ -762,7 +783,7 @@ void dma_insl(unsigned long addr, void *buf, unsigned short len) | |||
762 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); | 783 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); |
763 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); | 784 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); |
764 | 785 | ||
765 | blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len); | 786 | SSYNC(); |
766 | 787 | ||
767 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 788 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
768 | 789 | ||