From 3dd509ad9c09f33574e33b18090ec3fd012bb4aa Mon Sep 17 00:00:00 2001 From: rakesh goyal Date: Wed, 26 Aug 2020 21:57:36 +0530 Subject: [PATCH] nvethernet: fix kernel panic by adding napi_synchronize Issue: Kernel panic if NAPI scheduled in ether_close() path. Fix: Disable NAPI before freeing dma resources as well as call napi_synchronize() before napi_disable() for scheduled NAPI to be completed. Bug 200650229 Change-Id: I8c57ba90b5094ab3a130ca56221b3e1b16b96025 Signed-off-by: rakesh goyal Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2404266 Tested-by: mobile promotions Reviewed-by: Bhadram Varka Reviewed-by: Bitan Biswas Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/net/ethernet/nvidia/nvethernet/ether_linux.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index 76b73e99..474900e2 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -910,7 +910,10 @@ err_chan_irq: /** * @brief Disable NAPI. * - * Algorithm: Disable Tx and Rx NAPI for the channels which are enabled. + * Algorithm: + * 1) Wait for scheduled Tx and Rx NAPI to be completed. + * 2) Disable Tx and Rx NAPI for the channels which + * are enabled. * * @param[in] pdata: OSD private data structure. * @@ -924,8 +927,9 @@ static void ether_napi_disable(struct ether_priv_data *pdata) for (i = 0; i < osi_dma->num_dma_chans; i++) { chan = osi_dma->dma_chans[i]; - + napi_synchronize(&pdata->tx_napi[chan]->napi); napi_disable(&pdata->tx_napi[chan]->napi); + napi_synchronize(&pdata->rx_napi[chan]->napi); napi_disable(&pdata->rx_napi[chan]->napi); } } @@ -1853,6 +1857,8 @@ static int ether_close(struct net_device *ndev) thermal_cooling_device_unregister(pdata->tcd); #endif /* THERMAL_CAL */ + ether_napi_disable(pdata); + /* free DMA resources after DMA stop */ free_dma_resources(pdata); @@ -1862,8 +1868,6 @@ static int ether_close(struct net_device *ndev) /* MAC deinit which inturn stop MAC Tx,Rx */ osi_hw_core_deinit(pdata->osi_core); - ether_napi_disable(pdata); - /* Assert MAC RST gpio */ if (!pdata->osi_core->pre_si && pdata->mac_rst) { reset_control_assert(pdata->mac_rst);