aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/sata_mv.c20
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
891static 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;