forked from Minki/linux
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: Pantelis Antoniou <panto@antoniou-consulting.com> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4153577a8d
commit
510a1e7249
@ -510,19 +510,21 @@ static int cpsw_poll(struct napi_struct *napi, int budget)
|
||||
int num_tx, num_rx;
|
||||
|
||||
num_tx = cpdma_chan_process(priv->txch, 128);
|
||||
if (num_tx)
|
||||
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
|
||||
|
||||
num_rx = cpdma_chan_process(priv->rxch, budget);
|
||||
if (num_rx < budget) {
|
||||
napi_complete(napi);
|
||||
cpsw_intr_enable(priv);
|
||||
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
|
||||
cpsw_enable_irq(priv);
|
||||
}
|
||||
|
||||
if (num_rx || num_tx)
|
||||
cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
|
||||
num_rx, num_tx);
|
||||
|
||||
if (num_rx < budget) {
|
||||
napi_complete(napi);
|
||||
cpsw_intr_enable(priv);
|
||||
cpdma_ctlr_eoi(priv->dma);
|
||||
cpsw_enable_irq(priv);
|
||||
}
|
||||
|
||||
return num_rx;
|
||||
}
|
||||
|
||||
@ -835,7 +837,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
|
||||
cpdma_ctlr_start(priv->dma);
|
||||
cpsw_intr_enable(priv);
|
||||
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)
|
||||
priv->slaves[priv->emac_port].open_stat = true;
|
||||
@ -1075,7 +1078,9 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
|
||||
cpdma_chan_start(priv->txch);
|
||||
cpdma_ctlr_int_ctrl(priv->dma, true);
|
||||
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)
|
||||
@ -1094,7 +1099,9 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
|
||||
cpsw_interrupt(ndev->irq, priv);
|
||||
cpdma_ctlr_int_ctrl(priv->dma, true);
|
||||
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
|
||||
|
||||
|
@ -493,9 +493,9 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
|
||||
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,
|
||||
|
@ -26,6 +26,11 @@
|
||||
|
||||
#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 device *dev;
|
||||
void __iomem *dmaregs;
|
||||
@ -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_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);
|
||||
bool cpdma_check_free_tx_desc(struct cpdma_chan *chan);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user