Commit 510a1e72 authored by Mugunthan V N's avatar Mugunthan V N Committed by David S. Miller

drivers: net: davinci_cpdma: acknowledge interrupt properly

CPDMA interrupts are not properly acknowledged which leads to interrupt
storm, only cpdma interrupt 0 is acknowledged in Davinci CPDMA driver.
Changed cpdma_ctlr_eoi api to acknowledge 1 and 2 interrupts which are
used for rx and tx respectively.
Reported-by: default avatarPantelis Antoniou <panto@antoniou-consulting.com>
Signed-off-by: default avatarMugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4153577a
...@@ -510,19 +510,21 @@ static int cpsw_poll(struct napi_struct *napi, int budget) ...@@ -510,19 +510,21 @@ static int cpsw_poll(struct napi_struct *napi, int budget)
int num_tx, num_rx; int num_tx, num_rx;
num_tx = cpdma_chan_process(priv->txch, 128); num_tx = cpdma_chan_process(priv->txch, 128);
num_rx = cpdma_chan_process(priv->rxch, budget); if (num_tx)
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
if (num_rx || num_tx)
cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
num_rx, num_tx);
num_rx = cpdma_chan_process(priv->rxch, budget);
if (num_rx < budget) { if (num_rx < budget) {
napi_complete(napi); napi_complete(napi);
cpsw_intr_enable(priv); cpsw_intr_enable(priv);
cpdma_ctlr_eoi(priv->dma); cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
cpsw_enable_irq(priv); cpsw_enable_irq(priv);
} }
if (num_rx || num_tx)
cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
num_rx, num_tx);
return num_rx; return num_rx;
} }
...@@ -835,7 +837,8 @@ static int cpsw_ndo_open(struct net_device *ndev) ...@@ -835,7 +837,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpdma_ctlr_start(priv->dma); cpdma_ctlr_start(priv->dma);
cpsw_intr_enable(priv); cpsw_intr_enable(priv);
napi_enable(&priv->napi); napi_enable(&priv->napi);
cpdma_ctlr_eoi(priv->dma); cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
if (priv->data.dual_emac) if (priv->data.dual_emac)
priv->slaves[priv->emac_port].open_stat = true; priv->slaves[priv->emac_port].open_stat = true;
...@@ -1075,7 +1078,9 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev) ...@@ -1075,7 +1078,9 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
cpdma_chan_start(priv->txch); cpdma_chan_start(priv->txch);
cpdma_ctlr_int_ctrl(priv->dma, true); cpdma_ctlr_int_ctrl(priv->dma, true);
cpsw_intr_enable(priv); cpsw_intr_enable(priv);
cpdma_ctlr_eoi(priv->dma); cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
} }
static struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev) static struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev)
...@@ -1094,7 +1099,9 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev) ...@@ -1094,7 +1099,9 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
cpsw_interrupt(ndev->irq, priv); cpsw_interrupt(ndev->irq, priv);
cpdma_ctlr_int_ctrl(priv->dma, true); cpdma_ctlr_int_ctrl(priv->dma, true);
cpsw_intr_enable(priv); cpsw_intr_enable(priv);
cpdma_ctlr_eoi(priv->dma); cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
} }
#endif #endif
......
...@@ -493,9 +493,9 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) ...@@ -493,9 +493,9 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
return 0; return 0;
} }
void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)
{ {
dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value);
} }
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
......
...@@ -26,6 +26,11 @@ ...@@ -26,6 +26,11 @@
#define CPDMA_RX_SOURCE_PORT(__status__) ((__status__ >> 16) & 0x7) #define CPDMA_RX_SOURCE_PORT(__status__) ((__status__ >> 16) & 0x7)
#define CPDMA_EOI_RX_THRESH 0x0
#define CPDMA_EOI_RX 0x1
#define CPDMA_EOI_TX 0x2
#define CPDMA_EOI_MISC 0x3
struct cpdma_params { struct cpdma_params {
struct device *dev; struct device *dev;
void __iomem *dmaregs; void __iomem *dmaregs;
...@@ -88,7 +93,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, ...@@ -88,7 +93,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
int cpdma_chan_process(struct cpdma_chan *chan, int quota); int cpdma_chan_process(struct cpdma_chan *chan, int quota);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value);
int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
bool cpdma_check_free_tx_desc(struct cpdma_chan *chan); bool cpdma_check_free_tx_desc(struct cpdma_chan *chan);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment