| From: Dan Carpenter <dan.carpenter@oracle.com> |
| Date: Thu, 31 May 2018 09:44:49 +0300 |
| Subject: net: ethernet: davinci_emac: fix error handling in probe() |
| |
| commit 8005b09d99fac78e6f5fb9da30b5ae94840af03b upstream. |
| |
| The current error handling code has an issue where it does: |
| |
| if (priv->txchan) |
| cpdma_chan_destroy(priv->txchan); |
| |
| The problem is that ->txchan is either valid or an error pointer (which |
| would lead to an Oops). I've changed it to use multiple error labels so |
| that the test can be removed. |
| |
| Also there were some missing calls to netif_napi_del(). |
| |
| Fixes: 3ef0fdb2342c ("net: davinci_emac: switch to new cpdma layer") |
| Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/net/ethernet/ti/davinci_emac.c | 22 ++++++++++++---------- |
| 1 file changed, 12 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/net/ethernet/ti/davinci_emac.c |
| +++ b/drivers/net/ethernet/ti/davinci_emac.c |
| @@ -1971,7 +1971,7 @@ static int davinci_emac_probe(struct pla |
| if (IS_ERR(priv->txchan)) { |
| dev_err(&pdev->dev, "error initializing tx dma channel\n"); |
| rc = PTR_ERR(priv->txchan); |
| - goto no_cpdma_chan; |
| + goto err_free_dma; |
| } |
| |
| priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), |
| @@ -1979,14 +1979,14 @@ static int davinci_emac_probe(struct pla |
| if (IS_ERR(priv->rxchan)) { |
| dev_err(&pdev->dev, "error initializing rx dma channel\n"); |
| rc = PTR_ERR(priv->rxchan); |
| - goto no_cpdma_chan; |
| + goto err_free_txchan; |
| } |
| |
| res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| if (!res) { |
| dev_err(&pdev->dev, "error getting irq res\n"); |
| rc = -ENOENT; |
| - goto no_cpdma_chan; |
| + goto err_free_rxchan; |
| } |
| ndev->irq = res->start; |
| |
| @@ -2008,7 +2008,7 @@ static int davinci_emac_probe(struct pla |
| pm_runtime_put_noidle(&pdev->dev); |
| dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n", |
| __func__, rc); |
| - goto no_cpdma_chan; |
| + goto err_napi_del; |
| } |
| |
| /* register the network device */ |
| @@ -2018,7 +2018,7 @@ static int davinci_emac_probe(struct pla |
| dev_err(&pdev->dev, "error in register_netdev\n"); |
| rc = -ENODEV; |
| pm_runtime_put(&pdev->dev); |
| - goto no_cpdma_chan; |
| + goto err_napi_del; |
| } |
| |
| |
| @@ -2031,11 +2031,13 @@ static int davinci_emac_probe(struct pla |
| |
| return 0; |
| |
| -no_cpdma_chan: |
| - if (priv->txchan) |
| - cpdma_chan_destroy(priv->txchan); |
| - if (priv->rxchan) |
| - cpdma_chan_destroy(priv->rxchan); |
| +err_napi_del: |
| + netif_napi_del(&priv->napi); |
| +err_free_rxchan: |
| + cpdma_chan_destroy(priv->rxchan); |
| +err_free_txchan: |
| + cpdma_chan_destroy(priv->txchan); |
| +err_free_dma: |
| cpdma_ctlr_destroy(priv->dma); |
| no_pdata: |
| free_netdev(ndev); |