bcm63xx: update ethernet kernel panics fix
Use new patch from Sieng Piaw Liew.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
(cherry-picked from commit 31a06f8fcc)
			
			
This commit is contained in:
		| @@ -1,15 +1,23 @@ | |||||||
|  | From ca6be00ca1d3a2f5b8794894e2dae175e63768f5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sieng Piaw Liew <liew.s.piaw@gmail.com> | ||||||
|  | Date: Tue, 16 Feb 2021 16:23:08 +0800 | ||||||
|  | Subject: [PATCH] bcm63xx_enet: Fix sporadic kernel panic | ||||||
|  |  | ||||||
|  | In ndo_stop functions, netdev_completed_queue() is called during forced | ||||||
|  | tx reclaim, after netdev_reset_queue(). This may trigger kernel panic if | ||||||
|  | there is any tx skb left. | ||||||
|  |  | ||||||
|  | This patch moves netdev_reset_queue() to after tx reclaim, so BQL can | ||||||
|  | complete successfully then reset. | ||||||
|  |  | ||||||
|  | Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/broadcom/bcm63xx_enet.c | 8 ++++++-- | ||||||
|  |  1 file changed, 6 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
| --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| @@ -1105,6 +1105,8 @@ static int bcm_enet_open(struct net_devi | @@ -1193,7 +1193,6 @@ static int bcm_enet_stop(struct net_devi | ||||||
|  	else |  | ||||||
|  		bcm_enet_adjust_link(dev); |  | ||||||
|   |  | ||||||
| +	netdev_reset_queue(dev); |  | ||||||
| + |  | ||||||
|  	netif_start_queue(dev); |  | ||||||
|  	return 0; |  | ||||||
|   |  | ||||||
| @@ -1193,7 +1195,6 @@ static int bcm_enet_stop(struct net_devi |  | ||||||
|  	kdev = &priv->pdev->dev; |  	kdev = &priv->pdev->dev; | ||||||
|   |   | ||||||
|  	netif_stop_queue(dev); |  	netif_stop_queue(dev); | ||||||
| @@ -17,13 +25,15 @@ | |||||||
|  	napi_disable(&priv->napi); |  	napi_disable(&priv->napi); | ||||||
|  	if (priv->has_phy) |  	if (priv->has_phy) | ||||||
|  		phy_stop(dev->phydev); |  		phy_stop(dev->phydev); | ||||||
| @@ -2267,6 +2268,7 @@ static int bcm_enetsw_open(struct net_de | @@ -1232,6 +1231,9 @@ static int bcm_enet_stop(struct net_devi | ||||||
|  	enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, |  	if (priv->has_phy) | ||||||
|  			 ENETDMAC_IRMASK, priv->tx_chan); |  		phy_disconnect(dev->phydev); | ||||||
|   |   | ||||||
|  | +	/* reset BQL after forced tx reclaim to not kernel panic */ | ||||||
| +	netdev_reset_queue(dev); | +	netdev_reset_queue(dev); | ||||||
|  	netif_carrier_on(dev); | + | ||||||
|  	netif_start_queue(dev); |  	return 0; | ||||||
|  |  } | ||||||
|   |   | ||||||
| @@ -2348,7 +2350,6 @@ static int bcm_enetsw_stop(struct net_de | @@ -2348,7 +2350,6 @@ static int bcm_enetsw_stop(struct net_de | ||||||
|   |   | ||||||
| @@ -33,3 +43,13 @@ | |||||||
|  	napi_disable(&priv->napi); |  	napi_disable(&priv->napi); | ||||||
|  	del_timer_sync(&priv->rx_timeout); |  	del_timer_sync(&priv->rx_timeout); | ||||||
|   |   | ||||||
|  | @@ -2376,6 +2377,9 @@ static int bcm_enetsw_stop(struct net_de | ||||||
|  |  		free_irq(priv->irq_tx, dev); | ||||||
|  |  	free_irq(priv->irq_rx, dev); | ||||||
|  |   | ||||||
|  | +	/* reset BQL after forced tx reclaim to not kernel panic */ | ||||||
|  | +	netdev_reset_queue(dev); | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| @@ -1630,7 +1630,7 @@ static int bcm_enet_change_mtu(struct ne | @@ -1631,7 +1631,7 @@ static int bcm_enet_change_mtu(struct ne | ||||||
|  		return -EBUSY; |  		return -EBUSY; | ||||||
|   |   | ||||||
|  	/* add ethernet header + vlan tag size */ |  	/* add ethernet header + vlan tag size */ | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
|  	else |  	else | ||||||
|  		bcm_enet_adjust_link(dev); |  		bcm_enet_adjust_link(dev); | ||||||
|   |   | ||||||
| @@ -1133,10 +1110,6 @@ out_freeirq_rx: | @@ -1131,10 +1108,6 @@ out_freeirq_rx: | ||||||
|  out_freeirq: |  out_freeirq: | ||||||
|  	free_irq(dev->irq, dev); |  	free_irq(dev->irq, dev); | ||||||
|   |   | ||||||
| @@ -90,7 +90,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
|  	return ret; |  	return ret; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -1229,10 +1202,6 @@ static int bcm_enet_stop(struct net_devi | @@ -1227,10 +1200,6 @@ static int bcm_enet_stop(struct net_devi | ||||||
|  	free_irq(priv->irq_rx, dev); |  	free_irq(priv->irq_rx, dev); | ||||||
|  	free_irq(dev->irq, dev); |  	free_irq(dev->irq, dev); | ||||||
|   |   | ||||||
| @@ -98,10 +98,10 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
| -	if (priv->has_phy) | -	if (priv->has_phy) | ||||||
| -		phy_disconnect(dev->phydev); | -		phy_disconnect(dev->phydev); | ||||||
| - | - | ||||||
|  	return 0; |  	/* reset BQL after forced tx reclaim to not kernel panic */ | ||||||
|  } |  	netdev_reset_queue(dev); | ||||||
|   |   | ||||||
| @@ -1801,14 +1770,47 @@ static int bcm_enet_probe(struct platfor | @@ -1802,14 +1771,47 @@ static int bcm_enet_probe(struct platfor | ||||||
|   |   | ||||||
|  	/* do minimal hardware init to be able to probe mii bus */ |  	/* do minimal hardware init to be able to probe mii bus */ | ||||||
|  	bcm_enet_hw_preinit(priv); |  	bcm_enet_hw_preinit(priv); | ||||||
| @@ -150,7 +150,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
|  		} |  		} | ||||||
|   |   | ||||||
|  		bus = priv->mii_bus; |  		bus = priv->mii_bus; | ||||||
| @@ -1832,6 +1834,26 @@ static int bcm_enet_probe(struct platfor | @@ -1833,6 +1835,26 @@ static int bcm_enet_probe(struct platfor | ||||||
|  			dev_err(&pdev->dev, "unable to register mdio bus\n"); |  			dev_err(&pdev->dev, "unable to register mdio bus\n"); | ||||||
|  			goto out_free_mdio; |  			goto out_free_mdio; | ||||||
|  		} |  		} | ||||||
| @@ -177,7 +177,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
|  	} else { |  	} else { | ||||||
|   |   | ||||||
|  		/* run platform code to initialize PHY device */ |  		/* run platform code to initialize PHY device */ | ||||||
| @@ -1839,45 +1861,16 @@ static int bcm_enet_probe(struct platfor | @@ -1840,45 +1862,16 @@ static int bcm_enet_probe(struct platfor | ||||||
|  		    pd->mii_config(dev, 1, bcm_enet_mdio_read_mii, |  		    pd->mii_config(dev, 1, bcm_enet_mdio_read_mii, | ||||||
|  				   bcm_enet_mdio_write_mii)) { |  				   bcm_enet_mdio_write_mii)) { | ||||||
|  			dev_err(&pdev->dev, "unable to configure mdio bus\n"); |  			dev_err(&pdev->dev, "unable to configure mdio bus\n"); | ||||||
| @@ -227,7 +227,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
|  	if (priv->mii_bus) |  	if (priv->mii_bus) | ||||||
|  		mdiobus_unregister(priv->mii_bus); |  		mdiobus_unregister(priv->mii_bus); | ||||||
|   |   | ||||||
| @@ -1885,6 +1878,9 @@ out_free_mdio: | @@ -1886,6 +1879,9 @@ out_free_mdio: | ||||||
|  	if (priv->mii_bus) |  	if (priv->mii_bus) | ||||||
|  		mdiobus_free(priv->mii_bus); |  		mdiobus_free(priv->mii_bus); | ||||||
|   |   | ||||||
| @@ -237,7 +237,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | |||||||
|  out_uninit_hw: |  out_uninit_hw: | ||||||
|  	/* turn off mdc clock */ |  	/* turn off mdc clock */ | ||||||
|  	enet_writel(priv, 0, ENET_MIISC_REG); |  	enet_writel(priv, 0, ENET_MIISC_REG); | ||||||
| @@ -1915,6 +1911,7 @@ static int bcm_enet_remove(struct platfo | @@ -1916,6 +1912,7 @@ static int bcm_enet_remove(struct platfo | ||||||
|  	enet_writel(priv, 0, ENET_MIISC_REG); |  	enet_writel(priv, 0, ENET_MIISC_REG); | ||||||
|   |   | ||||||
|  	if (priv->has_phy) { |  	if (priv->has_phy) { | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ Subject: [PATCH 54/81] bcm63xx_enet: enable rgmii clock on external ports | |||||||
|  #define ENETSW_MDIOC_EXT_MASK		(1 << 16) |  #define ENETSW_MDIOC_EXT_MASK		(1 << 16) | ||||||
| --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| @@ -2184,6 +2184,18 @@ static int bcm_enetsw_open(struct net_de | @@ -2185,6 +2185,18 @@ static int bcm_enetsw_open(struct net_de | ||||||
|  		priv->sw_port_link[i] = 0; |  		priv->sw_port_link[i] = 0; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|   |   | ||||||
|  #include <bcm63xx_dev_enet.h> |  #include <bcm63xx_dev_enet.h> | ||||||
|  #include "bcm63xx_enet.h" |  #include "bcm63xx_enet.h" | ||||||
| @@ -1931,7 +1932,8 @@ static int bcm_enet_remove(struct platfo | @@ -1932,7 +1933,8 @@ static int bcm_enet_remove(struct platfo | ||||||
|  	return 0; |  	return 0; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -30,7 +30,7 @@ | |||||||
|  	.probe	= bcm_enet_probe, |  	.probe	= bcm_enet_probe, | ||||||
|  	.remove	= bcm_enet_remove, |  	.remove	= bcm_enet_remove, | ||||||
|  	.driver	= { |  	.driver	= { | ||||||
| @@ -1940,6 +1942,42 @@ struct platform_driver bcm63xx_enet_driv | @@ -1941,6 +1943,42 @@ struct platform_driver bcm63xx_enet_driv | ||||||
|  	}, |  	}, | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
| @@ -73,7 +73,7 @@ | |||||||
|  /* |  /* | ||||||
|   * switch mii access callbacks |   * switch mii access callbacks | ||||||
|   */ |   */ | ||||||
| @@ -2196,29 +2234,6 @@ static int bcm_enetsw_open(struct net_de | @@ -2197,29 +2235,6 @@ static int bcm_enetsw_open(struct net_de | ||||||
|  		enetsw_writeb(priv, rgmii_ctrl, ENETSW_RGMII_CTRL_REG(i)); |  		enetsw_writeb(priv, rgmii_ctrl, ENETSW_RGMII_CTRL_REG(i)); | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @@ -103,7 +103,7 @@ | |||||||
|  	/* initialize flow control buffer allocation */ |  	/* initialize flow control buffer allocation */ | ||||||
|  	enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0, |  	enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0, | ||||||
|  			ENETDMA_BUFALLOC_REG(priv->rx_chan)); |  			ENETDMA_BUFALLOC_REG(priv->rx_chan)); | ||||||
| @@ -2652,6 +2667,9 @@ static int bcm_enetsw_probe(struct platf | @@ -2655,6 +2670,9 @@ static int bcm_enetsw_probe(struct platf | ||||||
|  	struct bcm63xx_enetsw_platform_data *pd; |  	struct bcm63xx_enetsw_platform_data *pd; | ||||||
|  	struct resource *res_mem; |  	struct resource *res_mem; | ||||||
|  	int ret, irq_rx, irq_tx; |  	int ret, irq_rx, irq_tx; | ||||||
| @@ -113,7 +113,7 @@ | |||||||
|   |   | ||||||
|  	if (!bcm_enet_shared_base[0]) |  	if (!bcm_enet_shared_base[0]) | ||||||
|  		return -EPROBE_DEFER; |  		return -EPROBE_DEFER; | ||||||
| @@ -2732,6 +2750,43 @@ static int bcm_enetsw_probe(struct platf | @@ -2735,6 +2753,43 @@ static int bcm_enetsw_probe(struct platf | ||||||
|  	priv->pdev = pdev; |  	priv->pdev = pdev; | ||||||
|  	priv->net_dev = dev; |  	priv->net_dev = dev; | ||||||
|   |   | ||||||
| @@ -157,7 +157,7 @@ | |||||||
|  	return 0; |  	return 0; | ||||||
|   |   | ||||||
|  out_disable_clk: |  out_disable_clk: | ||||||
| @@ -2753,6 +2808,9 @@ static int bcm_enetsw_remove(struct plat | @@ -2756,6 +2811,9 @@ static int bcm_enetsw_remove(struct plat | ||||||
|  	priv = netdev_priv(dev); |  	priv = netdev_priv(dev); | ||||||
|  	unregister_netdev(dev); |  	unregister_netdev(dev); | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| @@ -2711,9 +2711,9 @@ static int bcm_enetsw_probe(struct platf | @@ -2714,9 +2714,9 @@ static int bcm_enetsw_probe(struct platf | ||||||
|  	if (ret) |  	if (ret) | ||||||
|  		goto out; |  		goto out; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
|   |   | ||||||
| --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | ||||||
| @@ -2231,6 +2231,10 @@ static int bcm_enetsw_open(struct net_de | @@ -2232,6 +2232,10 @@ static int bcm_enetsw_open(struct net_de | ||||||
|   |   | ||||||
|  		rgmii_ctrl = enetsw_readb(priv, ENETSW_RGMII_CTRL_REG(i)); |  		rgmii_ctrl = enetsw_readb(priv, ENETSW_RGMII_CTRL_REG(i)); | ||||||
|  		rgmii_ctrl |= ENETSW_RGMII_CTRL_GMII_CLK_EN; |  		rgmii_ctrl |= ENETSW_RGMII_CTRL_GMII_CLK_EN; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Álvaro Fernández Rojas
					Álvaro Fernández Rojas