diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2013-04-24 18:01:22 (GMT) |
---|---|---|
committer | Emil Medve <Emilian.Medve@Freescale.com> | 2013-04-30 08:16:53 (GMT) |
commit | 9fa62c8906da587aa5d651ca11c55795f454d2fb (patch) | |
tree | 0cf0416ce3f040d37896ed0ea2e2e70d69f2372a /drivers/net | |
parent | 27b9d37a0f1dd165e195e4365df8808d2d51257a (diff) | |
download | linux-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')
-rw-r--r-- | drivers/net/ethernet/ti/cpsw.c | 12 |
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", |