66 lines
2.2 KiB
Diff
66 lines
2.2 KiB
Diff
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Date: Wed, 24 Apr 2013 20:01:22 +0200
|
|
Subject: [PATCH] net/cpsw: use a lock around source testing
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/3.10/patches-3.10.4-rt1.tar.xz
|
|
|
|
For some reason on RT it happens that the TX interrupt fires over and
|
|
over again but according to tx_stat there is nothing going on. Same goes
|
|
for RX but not that often.
|
|
With this lock around it this is gone. However I still see from time to
|
|
time interrupts where each source is set to 0.
|
|
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
drivers/net/ethernet/ti/cpsw.c | 11 +++++++++--
|
|
1 file changed, 9 insertions(+), 2 deletions(-)
|
|
|
|
Index: linux-stable/drivers/net/ethernet/ti/cpsw.c
|
|
===================================================================
|
|
--- linux-stable.orig/drivers/net/ethernet/ti/cpsw.c
|
|
+++ linux-stable/drivers/net/ethernet/ti/cpsw.c
|
|
@@ -490,7 +490,7 @@ void cpsw_rx_handler(void *token, int le
|
|
skb_put(skb, len);
|
|
cpts_rx_timestamp(priv->cpts, skb);
|
|
skb->protocol = eth_type_trans(skb, ndev);
|
|
- netif_receive_skb(skb);
|
|
+ netif_rx(skb);
|
|
priv->stats.rx_bytes += len;
|
|
priv->stats.rx_packets++;
|
|
} else {
|
|
@@ -507,19 +507,24 @@ void cpsw_rx_handler(void *token, int le
|
|
static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
|
|
{
|
|
struct cpsw_priv *priv = dev_id;
|
|
+ unsigned long flags;
|
|
u32 rx, tx, rx_thresh;
|
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
rx_thresh = __raw_readl(&priv->wr_regs->rx_thresh_stat);
|
|
rx = __raw_readl(&priv->wr_regs->rx_stat);
|
|
tx = __raw_readl(&priv->wr_regs->tx_stat);
|
|
- if (!rx_thresh && !rx && !tx)
|
|
+ if (!rx_thresh && !rx && !tx) {
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
return IRQ_NONE;
|
|
+ }
|
|
|
|
cpsw_intr_disable(priv);
|
|
if (priv->irq_enabled == true) {
|
|
cpsw_disable_irq(priv);
|
|
priv->irq_enabled = false;
|
|
}
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
|
if (netif_running(priv->ndev)) {
|
|
napi_schedule(&priv->napi);
|
|
@@ -541,7 +546,9 @@ static int cpsw_poll(struct napi_struct
|
|
{
|
|
struct cpsw_priv *priv = napi_to_priv(napi);
|
|
int num_tx, num_rx;
|
|
+ unsigned long flags;
|
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
num_tx = cpdma_chan_process(priv->txch, 128);
|
|
if (num_tx)
|
|
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
|