| From cd2c54ae0227ab3e07a09d1e2d46448eeba8aeb2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jun 2021 20:08:57 +0530 |
| Subject: net: ti: am65-cpsw-nuss: Fix crash when changing number of TX queues |
| |
| From: Vignesh Raghavendra <vigneshr@ti.com> |
| |
| [ 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: 93a76530316a ("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> |
| --- |
| drivers/net/ethernet/ti/am65-cpsw-nuss.c | 18 +++++++++--------- |
| 1 file changed, 9 insertions(+), 9 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c |
| index 501d676fd88b..0805edef5625 100644 |
| --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c |
| +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c |
| @@ -1433,12 +1433,12 @@ static void am65_cpsw_nuss_free_tx_chns(void *data) |
| for (i = 0; i < common->tx_ch_num; 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)) |
| 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)); |
| } |
| } |
| @@ -1458,12 +1458,12 @@ void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common) |
| |
| 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)) |
| 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)); |
| } |
| } |
| @@ -1550,11 +1550,11 @@ static void am65_cpsw_nuss_free_rx_chns(void *data) |
| |
| 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)) |
| 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) |
| -- |
| 2.30.2 |
| |