[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20120130025724.GR10262@cronus.persephoneslair.org>
Date: Sun, 29 Jan 2012 18:57:24 -0800
From: Andrea Shepard <andrea@...sephoneslair.org>
To: linux-kernel@...r.kernel.org, netdev@...r.kernel.org
Cc: khc@...waw.pl, davem@...emloft.net, mmarek@...e.cz,
jkosina@...e.cz, joe@...ches.com, justinmattock@...il.com,
gregkh@...e.de, alan@...ux.intel.com, jdmason@...zu.us
Subject: [17/22] Cyclades PC300 driver: queue stop/start fix
Change cpc_queue_xmit() to stop and restart the queue while it does things to
the DMA buffers and registers.
The Cyclades 4.1.0 release doesn't seem to function reliably without this; I
suspect it was a race condition bug that was always present.
Signed-off-by: Andrea Shepard <andrea@...sephoneslair.org>
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index c44c26a..4d81507 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -2055,20 +2055,15 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
if (d->trace_on) {
cpc_trace(dev, skb, 'T');
}
- dev->trans_start = jiffies;
/* Start transmission */
CPC_LOCK(card, flags);
- /* verify if it has more than one free descriptor */
- if (card->chan[ch].nfree_tx_bd <= 1) {
#ifdef PC300_DEBUG_QUEUE
- printk(KERN_DEBUG
- "%s: stopping queue for transmission\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: stopping queue for transmission\n",
+ dev->name);
#endif
- /* don't have so stop the queue */
- netif_stop_queue(dev);
- }
+ netif_stop_queue(dev);
cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch),
TX_BD_ADDR(ch, chan->tx_next_bd));
cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA);
@@ -2078,12 +2073,22 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
(CPLD_REG2_FALC_LED1 << (2 * ch)));
}
+ /* verify if it has more than one free descriptor */
+ if (card->chan[ch].nfree_tx_bd > 1) {
+#ifdef PC300_DEBUG_QUEUE
+ printk(KERN_DEBUG
+ "%s: restarting queue\n",
+ dev->name);
+#endif
+ netif_wake_queue(dev);
+ }
CPC_UNLOCK(card, flags);
dev_kfree_skb(skb);
#ifdef PC300_DEBUG_TX
- printk(KERN_DEBUG "%s: cpc_queue_xmit returning normally\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: cpc_queue_xmit returning normally\n",
+ dev->name);
#endif
return 0;
@@ -2221,7 +2226,9 @@ static void sca_tx_intr(pc300dev_t *dev)
#ifdef PC300_DEBUG_QUEUE
printk(KERN_DEBUG "Waking queue on TX interrupt\n");
#endif
- netif_wake_queue(dev->netdev);
+ if (chan->nfree_tx_bd > 1 &&
+ netif_queue_stopped(dev->netdev))
+ netif_wake_queue(dev->netdev);
#ifdef CONFIG_PC300_MLPPP
}
#endif
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists