mirror of
https://github.com/torvalds/linux
synced 2024-09-27 15:00:46 +00:00
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;
|
int num_tx, num_rx;
|
||||||
|
|
||||||
num_tx = cpdma_chan_process(priv->txch, 128);
|
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);
|
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)
|
if (num_rx || num_tx)
|
||||||
cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
|
cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
|
||||||
num_rx, num_tx);
|
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;
|
return num_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@
|
||||||
|
|
||||||
#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,
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue