net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
[ Upstream commit 5f079290e5913a0060e059500b7d440990ac1066 ]
Registering the interrupts for TX or RX DMA Channels prior to registering
their respective NAPI callbacks can result in a NULL pointer dereference.
This is seen in practice as a random occurrence since it depends on the
randomness associated with the generation of traffic by Linux and the
reception of traffic from the wire.
Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Co-developed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
Reviewed-by: Roger Quadros <rogerq@kernel.org>
Link: https://patch.msgid.link/20250311154259.102865-1-s-vadapalli@ti.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
8bf2f1ba27
commit
d4bf956547
@@ -2225,14 +2225,18 @@ static void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common)
|
||||
static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
|
||||
{
|
||||
struct device *dev = common->dev;
|
||||
struct am65_cpsw_tx_chn *tx_chn;
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < common->tx_ch_num; i++) {
|
||||
struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
|
||||
tx_chn = &common->tx_chns[i];
|
||||
|
||||
hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
|
||||
tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
|
||||
|
||||
netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
|
||||
am65_cpsw_nuss_tx_poll);
|
||||
|
||||
ret = devm_request_irq(dev, tx_chn->irq,
|
||||
am65_cpsw_nuss_tx_irq,
|
||||
IRQF_TRIGGER_HIGH,
|
||||
@@ -2242,19 +2246,16 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
|
||||
tx_chn->id, tx_chn->irq, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
|
||||
am65_cpsw_nuss_tx_poll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (--i ; i >= 0 ; i--) {
|
||||
struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
|
||||
|
||||
netif_napi_del(&tx_chn->napi_tx);
|
||||
netif_napi_del(&tx_chn->napi_tx);
|
||||
for (--i; i >= 0; i--) {
|
||||
tx_chn = &common->tx_chns[i];
|
||||
devm_free_irq(dev, tx_chn->irq, tx_chn);
|
||||
netif_napi_del(&tx_chn->napi_tx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2488,6 +2489,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
|
||||
HRTIMER_MODE_REL_PINNED);
|
||||
flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
|
||||
|
||||
netif_napi_add(common->dma_ndev, &flow->napi_rx,
|
||||
am65_cpsw_nuss_rx_poll);
|
||||
|
||||
ret = devm_request_irq(dev, flow->irq,
|
||||
am65_cpsw_nuss_rx_irq,
|
||||
IRQF_TRIGGER_HIGH,
|
||||
@@ -2496,11 +2500,8 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
|
||||
dev_err(dev, "failure requesting rx %d irq %u, %d\n",
|
||||
i, flow->irq, ret);
|
||||
flow->irq = -EINVAL;
|
||||
goto err_flow;
|
||||
goto err_request_irq;
|
||||
}
|
||||
|
||||
netif_napi_add(common->dma_ndev, &flow->napi_rx,
|
||||
am65_cpsw_nuss_rx_poll);
|
||||
}
|
||||
|
||||
/* setup classifier to route priorities to flows */
|
||||
@@ -2508,11 +2509,14 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
|
||||
|
||||
return 0;
|
||||
|
||||
err_request_irq:
|
||||
netif_napi_del(&flow->napi_rx);
|
||||
|
||||
err_flow:
|
||||
for (--i; i >= 0 ; i--) {
|
||||
for (--i; i >= 0; i--) {
|
||||
flow = &rx_chn->flows[i];
|
||||
netif_napi_del(&flow->napi_rx);
|
||||
devm_free_irq(dev, flow->irq, flow);
|
||||
netif_napi_del(&flow->napi_rx);
|
||||
}
|
||||
|
||||
err:
|
||||
|
||||
Reference in New Issue
Block a user