net: ti: am65-cpsw-nuss: Fix crash when changing number of TX queues
[ Upstream commit ce8eb4c728ef40b554b4f3d8963f11ed44502e00 ]
When changing number of TX queues using ethtool:
# ethtool -L eth0 tx 1
[ 135.301047] Unable to handle kernel paging request at virtual address 00000000af5d0000
[...]
[ 135.525128] Call trace:
[ 135.525142] dma_release_from_dev_coherent+0x2c/0xb0
[ 135.525148] dma_free_attrs+0x54/0xe0
[ 135.525156] k3_cppi_desc_pool_destroy+0x50/0xa0
[ 135.525164] am65_cpsw_nuss_remove_tx_chns+0x88/0xdc
[ 135.525171] am65_cpsw_set_channels+0x3c/0x70
[...]
This is because k3_cppi_desc_pool_destroy() which is called after
k3_udma_glue_release_tx_chn() in am65_cpsw_nuss_remove_tx_chns()
references struct device that is unregistered at the end of
k3_udma_glue_release_tx_chn()
Therefore the right order is to call k3_cppi_desc_pool_destroy() and
destroy desc pool before calling k3_udma_glue_release_tx_chn().
Fix this throughout the driver.
Fixes: 93a7653031
("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver")
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
6610d5a73b
commit
997285646a
@@ -1433,12 +1433,12 @@ static void am65_cpsw_nuss_free_tx_chns(void *data)
|
|||||||
for (i = 0; i < common->tx_ch_num; i++) {
|
for (i = 0; i < common->tx_ch_num; i++) {
|
||||||
struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
|
struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
|
||||||
k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
|
if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
|
||||||
k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
|
k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
|
||||||
|
|
||||||
|
if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
||||||
|
k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
||||||
|
|
||||||
memset(tx_chn, 0, sizeof(*tx_chn));
|
memset(tx_chn, 0, sizeof(*tx_chn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1458,12 +1458,12 @@ void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common)
|
|||||||
|
|
||||||
netif_napi_del(&tx_chn->napi_tx);
|
netif_napi_del(&tx_chn->napi_tx);
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
|
||||||
k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
|
if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
|
||||||
k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
|
k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
|
||||||
|
|
||||||
|
if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
||||||
|
k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
||||||
|
|
||||||
memset(tx_chn, 0, sizeof(*tx_chn));
|
memset(tx_chn, 0, sizeof(*tx_chn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1550,11 +1550,11 @@ static void am65_cpsw_nuss_free_rx_chns(void *data)
|
|||||||
|
|
||||||
rx_chn = &common->rx_chns;
|
rx_chn = &common->rx_chns;
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
|
|
||||||
k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
|
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
|
if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
|
||||||
k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
|
k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
|
||||||
|
|
||||||
|
if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
|
||||||
|
k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
|
static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
|
||||||
|
Reference in New Issue
Block a user