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 <rgoyal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2404266
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
rakesh goyal
2020-08-26 21:57:36 +05:30
committed by Revanth Kumar Uppala
parent 3ff1678205
commit 3dd509ad9c

View File

@@ -910,7 +910,10 @@ err_chan_irq:
/** /**
* @brief Disable NAPI. * @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. * @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++) { for (i = 0; i < osi_dma->num_dma_chans; i++) {
chan = osi_dma->dma_chans[i]; chan = osi_dma->dma_chans[i];
napi_synchronize(&pdata->tx_napi[chan]->napi);
napi_disable(&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); 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); thermal_cooling_device_unregister(pdata->tcd);
#endif /* THERMAL_CAL */ #endif /* THERMAL_CAL */
ether_napi_disable(pdata);
/* free DMA resources after DMA stop */ /* free DMA resources after DMA stop */
free_dma_resources(pdata); free_dma_resources(pdata);
@@ -1862,8 +1868,6 @@ static int ether_close(struct net_device *ndev)
/* MAC deinit which inturn stop MAC Tx,Rx */ /* MAC deinit which inturn stop MAC Tx,Rx */
osi_hw_core_deinit(pdata->osi_core); osi_hw_core_deinit(pdata->osi_core);
ether_napi_disable(pdata);
/* Assert MAC RST gpio */ /* Assert MAC RST gpio */
if (!pdata->osi_core->pre_si && pdata->mac_rst) { if (!pdata->osi_core->pre_si && pdata->mac_rst) {
reset_control_assert(pdata->mac_rst); reset_control_assert(pdata->mac_rst);