diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_mv.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 10ef9683f048..692996216b1a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -888,6 +888,25 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, | |||
888 | } | 888 | } |
889 | } | 889 | } |
890 | 890 | ||
891 | static void mv_wait_for_edma_empty_idle(struct ata_port *ap) | ||
892 | { | ||
893 | void __iomem *port_mmio = mv_ap_base(ap); | ||
894 | const u32 empty_idle = (EDMA_STATUS_CACHE_EMPTY | EDMA_STATUS_IDLE); | ||
895 | const int per_loop = 5, timeout = (15 * 1000 / per_loop); | ||
896 | int i; | ||
897 | |||
898 | /* | ||
899 | * Wait for the EDMA engine to finish transactions in progress. | ||
900 | */ | ||
901 | for (i = 0; i < timeout; ++i) { | ||
902 | u32 edma_stat = readl(port_mmio + EDMA_STATUS_OFS); | ||
903 | if ((edma_stat & empty_idle) == empty_idle) | ||
904 | break; | ||
905 | udelay(per_loop); | ||
906 | } | ||
907 | /* ata_port_printk(ap, KERN_INFO, "%s: %u+ usecs\n", __func__, i); */ | ||
908 | } | ||
909 | |||
891 | /** | 910 | /** |
892 | * mv_stop_edma_engine - Disable eDMA engine | 911 | * mv_stop_edma_engine - Disable eDMA engine |
893 | * @port_mmio: io base address | 912 | * @port_mmio: io base address |
@@ -920,6 +939,7 @@ static int mv_stop_edma(struct ata_port *ap) | |||
920 | if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) | 939 | if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) |
921 | return 0; | 940 | return 0; |
922 | pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; | 941 | pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; |
942 | mv_wait_for_edma_empty_idle(ap); | ||
923 | if (mv_stop_edma_engine(port_mmio)) { | 943 | if (mv_stop_edma_engine(port_mmio)) { |
924 | ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); | 944 | ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); |
925 | return -EIO; | 945 | return -EIO; |