gianfar: Add missing graceful reset steps and fixes

gfar_halt() and gfar_start() are responsible for stopping
and starting the DMA and the Rx/Tx hw rings. They implement
the support for the "graceful Rx/Tx stop/start" hw procedure,
and also disable/enable eTSEC's hw interrupts in the process.

The GRS/GTS procedure requires however to have the RQUEUE/TQUEUE
registers cleared first and to wait for a period of time for the
current frame to pass through the interface (around ~10ms for a
jumbo frame). Only then may the GTS and GRS bits from DMACTRL be
set to shut down the DMA, and finally the Tx_EN and Rx_EN bits in
MACCFG1 may be cleared to disable the Tx/Rx blocks.

The same register programming order applies to start the Rx/Tx:
enabling the RQUEUE/TQUEUE *before* clearing the GRS/GTS bits.

This is a HW recommendation in order to avoid a possible
controller "lock up" during graceful reset.

Cleanup the gfar_halt()/start() prototypes, to take priv instead
of ndev as their purpose is to operate on HW. Enabling the
RQUEUE/TQUEUE in the hw_init() is not needed anymore since
that's the job of gfar_start().

Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Claudiu Manoil
2014-02-17 12:53:18 +02:00
committed by David S. Miller
parent efeddce7ea
commit c10650b661
3 changed files with 31 additions and 30 deletions

View File

@@ -44,7 +44,6 @@
#include "gianfar.h"
extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
int rx_work_limit);
@@ -504,7 +503,7 @@ static int gfar_sringparam(struct net_device *dev,
lock_tx_qs(priv);
lock_rx_qs(priv);
gfar_halt(dev);
gfar_halt(priv);
unlock_rx_qs(priv);
unlock_tx_qs(priv);
@@ -627,7 +626,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
lock_tx_qs(priv);
lock_rx_qs(priv);
gfar_halt(dev);
gfar_halt(priv);
unlock_tx_qs(priv);
unlock_rx_qs(priv);