summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/ti
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2013-04-24 18:01:22 (GMT)
committerEmil Medve <Emilian.Medve@Freescale.com>2013-04-30 08:16:53 (GMT)
commit9fa62c8906da587aa5d651ca11c55795f454d2fb (patch)
tree0cf0416ce3f040d37896ed0ea2e2e70d69f2372a /drivers/net/ethernet/ti
parent27b9d37a0f1dd165e195e4365df8808d2d51257a (diff)
downloadlinux-fsl-qoriq-9fa62c8906da587aa5d651ca11c55795f454d2fb.tar.xz
net/cpsw: use a lock around source testing
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>
Diffstat (limited to 'drivers/net/ethernet/ti')
-rw-r--r--drivers/net/ethernet/ti/cpsw.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 3c97c21..e660122 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -490,7 +490,7 @@ void cpsw_rx_handler(void *token, int len, int status)
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 len, int status)
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 *napi, int budget)
{
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);
@@ -559,6 +566,7 @@ static int cpsw_poll(struct napi_struct *napi, int budget)
prim_cpsw->irq_enabled = true;
}
}
+ spin_unlock_irqrestore(&priv->lock, flags);
if (num_rx || num_tx)
cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",