gianfar: Replace spin_event_timeout() with arch independent
authorClaudiu Manoil <claudiu.manoil@freescale.com>
Tue, 7 Oct 2014 07:44:34 +0000 (10:44 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 9 Oct 2014 05:40:37 +0000 (01:40 -0400)
Use arch independent code to replace the powerpc dependent
spin_event_timeout() from gfar_halt_nodisable().
Added GRS/GTS read accessors to clean-up the implementation
of gfar_halt_nodisable().

Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar.h

index 961198a2bfa83126e83be6c2f76abb6799a47507..356a9982d0140e3e35363f88bf0441a75ff2dcfb 100644 (file)
@@ -1762,26 +1762,32 @@ static void gfar_halt_nodisable(struct gfar_private *priv)
 {
        struct gfar __iomem *regs = priv->gfargrp[0].regs;
        u32 tempval;
+       unsigned int timeout;
+       int stopped;
 
        gfar_ints_disable(priv);
 
+       if (gfar_is_dma_stopped(priv))
+               return;
+
        /* Stop the DMA, and wait for it to stop */
        tempval = gfar_read(&regs->dmactrl);
-       if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
-           (DMACTRL_GRS | DMACTRL_GTS)) {
-               int ret;
-
-               tempval |= (DMACTRL_GRS | DMACTRL_GTS);
-               gfar_write(&regs->dmactrl, tempval);
+       tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+       gfar_write(&regs->dmactrl, tempval);
 
-               do {
-                       ret = spin_event_timeout(((gfar_read(&regs->ievent) &
-                                (IEVENT_GRSC | IEVENT_GTSC)) ==
-                                (IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0);
-                       if (!ret && !(gfar_read(&regs->ievent) & IEVENT_GRSC))
-                               ret = __gfar_is_rx_idle(priv);
-               } while (!ret);
+retry:
+       timeout = 1000;
+       while (!(stopped = gfar_is_dma_stopped(priv)) && timeout) {
+               cpu_relax();
+               timeout--;
        }
+
+       if (!timeout)
+               stopped = gfar_is_dma_stopped(priv);
+
+       if (!stopped && !gfar_is_rx_dma_stopped(priv) &&
+           !__gfar_is_rx_idle(priv))
+               goto retry;
 }
 
 /* Halt the receive and transmit queues */
index 84632c569f2c3ba43225c2a9a4f773dd24ea1580..0b3772217a9a61328ff1179659057c7c119a2bb2 100644 (file)
@@ -1226,6 +1226,21 @@ static inline void gfar_write_isrg(struct gfar_private *priv)
        }
 }
 
+static inline int gfar_is_dma_stopped(struct gfar_private *priv)
+{
+       struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+       return ((gfar_read(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) ==
+              (IEVENT_GRSC | IEVENT_GTSC));
+}
+
+static inline int gfar_is_rx_dma_stopped(struct gfar_private *priv)
+{
+       struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+       return gfar_read(&regs->ievent) & IEVENT_GRSC;
+}
+
 irqreturn_t gfar_receive(int irq, void *dev_id);
 int startup_gfar(struct net_device *dev);
 void stop_gfar(struct net_device *dev);