From b044d33f4c9d4d41a4923a4baaf00c65a1d9318d Mon Sep 17 00:00:00 2001 From: NĂ©lio Laranjeiro Date: Thu, 21 Jun 2012 11:26:53 +0200 Subject: cleo/linux/drv/net/arm/synop3504: reset rings on timeout, refs #3161 Linux network scheduler handles a timer to detect timeout TX. This timeout is configurable for the device. The watchdog only call the drivers' timeout function if the carrier is ON, so it is only used to detect problems on transmission or congestion on the medium. In our case, as the timeout is pretty long, if the first packet in the DMA has expired the last one has expired too, so the ring can be reseted. This is only true for TX DMA ring, because the timeout is configured to expire 4 seconds after the last TX has been requested. Used example from drivers/net/meth.c --- .../drivers/net/arm/synop3504.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c index f340e45d87..800f5f9034 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c @@ -591,9 +591,24 @@ static void synop3504_set_multicast(struct net_device *dev) #ifndef CONFIG_SYNOP3504_NO_TX_TIMEOUT static void synop3504_tx_timeout(struct net_device *dev) { - dev->stats.tx_errors++; - dev->trans_start = jiffies; - printk (KERN_WARNING DRV_NAME" %s: Transmit timed out\n",dev->name); + struct net_priv *priv = (struct net_priv *)dev->priv; + Synopsys *synop = &priv->synop; + + dev->stats.tx_errors++; + dev->trans_start = jiffies; + printk (KERN_WARNING DRV_NAME" %s: Transmit timed out\n",dev->name); + + //Reset TX descriptors. + SynopsysDisableInt(synop); + SynopsysStopTx(synop); + + synop3504_txdesc_reset(dev); + + SynopsysStartTx(synop); + SynopsysEnableInt(synop); + + //The ring is empty, the queue can be awaken. + netif_wake_queue(dev); }// synop3504_tx_timeout #endif -- cgit v1.2.3