diff options
author | Claudiu Manoil <claudiu.manoil@freescale.com> | 2014-10-07 09:44:34 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-09 07:40:37 +0200 |
commit | a4feee89ce4590c7a4aead49ca5a4853dc6ea5dc (patch) | |
tree | 781f0632c4405085d75e4f73394927dab39bb964 /drivers/net | |
parent | gianfar: Make MAC addr setup endian safe, cleanup (diff) | |
download | linux-a4feee89ce4590c7a4aead49ca5a4853dc6ea5dc.tar.xz linux-a4feee89ce4590c7a4aead49ca5a4853dc6ea5dc.zip |
gianfar: Replace spin_event_timeout() with arch independent
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.h | 15 |
2 files changed, 34 insertions, 13 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 961198a2bfa8..356a9982d014 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -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(®s->dmactrl); - if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) != - (DMACTRL_GRS | DMACTRL_GTS)) { - int ret; - - tempval |= (DMACTRL_GRS | DMACTRL_GTS); - gfar_write(®s->dmactrl, tempval); + tempval |= (DMACTRL_GRS | DMACTRL_GTS); + gfar_write(®s->dmactrl, tempval); - do { - ret = spin_event_timeout(((gfar_read(®s->ievent) & - (IEVENT_GRSC | IEVENT_GTSC)) == - (IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0); - if (!ret && !(gfar_read(®s->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 */ diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 84632c569f2c..0b3772217a9a 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -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(®s->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(®s->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); |