diff options
Diffstat (limited to 'drivers/net/dsa')
47 files changed, 547 insertions, 114 deletions
diff --git a/drivers/net/dsa/b53/b53_mdio.c b/drivers/net/dsa/b53/b53_mdio.c index a533a90e3904..a7aeb3c132c9 100644 --- a/drivers/net/dsa/b53/b53_mdio.c +++ b/drivers/net/dsa/b53/b53_mdio.c @@ -351,9 +351,25 @@ static int b53_mdio_probe(struct mdio_device *mdiodev)  static void b53_mdio_remove(struct mdio_device *mdiodev)  {  	struct b53_device *dev = dev_get_drvdata(&mdiodev->dev); -	struct dsa_switch *ds = dev->ds; -	dsa_unregister_switch(ds); +	if (!dev) +		return; + +	b53_switch_remove(dev); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void b53_mdio_shutdown(struct mdio_device *mdiodev) +{ +	struct b53_device *dev = dev_get_drvdata(&mdiodev->dev); + +	if (!dev) +		return; + +	b53_switch_shutdown(dev); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static const struct of_device_id b53_of_match[] = { @@ -373,6 +389,7 @@ MODULE_DEVICE_TABLE(of, b53_of_match);  static struct mdio_driver b53_mdio_driver = {  	.probe	= b53_mdio_probe,  	.remove	= b53_mdio_remove, +	.shutdown = b53_mdio_shutdown,  	.mdiodrv.driver = {  		.name = "bcm53xx",  		.of_match_table = b53_of_match, diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index 82680e083cc2..ae4c79d39bc0 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -316,9 +316,21 @@ static int b53_mmap_remove(struct platform_device *pdev)  	if (dev)  		b53_switch_remove(dev); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } +static void b53_mmap_shutdown(struct platform_device *pdev) +{ +	struct b53_device *dev = platform_get_drvdata(pdev); + +	if (dev) +		b53_switch_shutdown(dev); + +	platform_set_drvdata(pdev, NULL); +} +  static const struct of_device_id b53_mmap_of_table[] = {  	{ .compatible = "brcm,bcm3384-switch" },  	{ .compatible = "brcm,bcm6328-switch" }, @@ -331,6 +343,7 @@ MODULE_DEVICE_TABLE(of, b53_mmap_of_table);  static struct platform_driver b53_mmap_driver = {  	.probe = b53_mmap_probe,  	.remove = b53_mmap_remove, +	.shutdown = b53_mmap_shutdown,  	.driver = {  		.name = "b53-switch",  		.of_match_table = b53_mmap_of_table, diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 5d068acf7cf8..959a52d41f0a 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -228,6 +228,11 @@ static inline void b53_switch_remove(struct b53_device *dev)  	dsa_unregister_switch(dev->ds);  } +static inline void b53_switch_shutdown(struct b53_device *dev) +{ +	dsa_switch_shutdown(dev->ds); +} +  #define b53_build_op(type_op_size, val_type)				\  static inline int b53_##type_op_size(struct b53_device *dev, u8 page,	\  				     u8 reg, val_type val)		\ diff --git a/drivers/net/dsa/b53/b53_spi.c b/drivers/net/dsa/b53/b53_spi.c index ecb9f7f6b335..01e37b75471e 100644 --- a/drivers/net/dsa/b53/b53_spi.c +++ b/drivers/net/dsa/b53/b53_spi.c @@ -321,9 +321,21 @@ static int b53_spi_remove(struct spi_device *spi)  	if (dev)  		b53_switch_remove(dev); +	spi_set_drvdata(spi, NULL); +  	return 0;  } +static void b53_spi_shutdown(struct spi_device *spi) +{ +	struct b53_device *dev = spi_get_drvdata(spi); + +	if (dev) +		b53_switch_shutdown(dev); + +	spi_set_drvdata(spi, NULL); +} +  static const struct of_device_id b53_spi_of_match[] = {  	{ .compatible = "brcm,bcm5325" },  	{ .compatible = "brcm,bcm5365" }, @@ -344,6 +356,7 @@ static struct spi_driver b53_spi_driver = {  	},  	.probe	= b53_spi_probe,  	.remove	= b53_spi_remove, +	.shutdown = b53_spi_shutdown,  };  module_spi_driver(b53_spi_driver); diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c index 3f4249de70c5..4591bb1c05d2 100644 --- a/drivers/net/dsa/b53/b53_srab.c +++ b/drivers/net/dsa/b53/b53_srab.c @@ -629,17 +629,34 @@ static int b53_srab_probe(struct platform_device *pdev)  static int b53_srab_remove(struct platform_device *pdev)  {  	struct b53_device *dev = platform_get_drvdata(pdev); -	struct b53_srab_priv *priv = dev->priv; -	b53_srab_intr_set(priv, false); +	if (!dev) +		return 0; + +	b53_srab_intr_set(dev->priv, false);  	b53_switch_remove(dev); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } +static void b53_srab_shutdown(struct platform_device *pdev) +{ +	struct b53_device *dev = platform_get_drvdata(pdev); + +	if (!dev) +		return; + +	b53_switch_shutdown(dev); + +	platform_set_drvdata(pdev, NULL); +} +  static struct platform_driver b53_srab_driver = {  	.probe = b53_srab_probe,  	.remove = b53_srab_remove, +	.shutdown = b53_srab_shutdown,  	.driver = {  		.name = "b53-srab-switch",  		.of_match_table = b53_srab_of_match, diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 6ce9ec1283e0..7578a5c38df5 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -68,7 +68,7 @@ static unsigned int bcm_sf2_num_active_ports(struct dsa_switch *ds)  	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);  	unsigned int port, count = 0; -	for (port = 0; port < ARRAY_SIZE(priv->port_sts); port++) { +	for (port = 0; port < ds->num_ports; port++) {  		if (dsa_is_cpu_port(ds, port))  			continue;  		if (priv->port_sts[port].enabled) @@ -1512,6 +1512,9 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)  {  	struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); +	if (!priv) +		return 0; +  	priv->wol_ports_mask = 0;  	/* Disable interrupts */  	bcm_sf2_intr_disable(priv); @@ -1523,6 +1526,8 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)  	if (priv->type == BCM7278_DEVICE_ID)  		reset_control_assert(priv->rcdev); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } @@ -1530,6 +1535,9 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev)  {  	struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); +	if (!priv) +		return; +  	/* For a kernel about to be kexec'd we want to keep the GPHY on for a  	 * successful MDIO bus scan to occur. If we did turn off the GPHY  	 * before (e.g: port_disable), this will also power it back on. @@ -1538,6 +1546,10 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev)  	 */  	if (priv->hw_params.num_gphy == 1)  		bcm_sf2_gphy_enable_set(priv->dev->ds, true); + +	dsa_switch_shutdown(priv->dev->ds); + +	platform_set_drvdata(pdev, NULL);  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c index bfdf3324aac3..e638e3eea911 100644 --- a/drivers/net/dsa/dsa_loop.c +++ b/drivers/net/dsa/dsa_loop.c @@ -340,10 +340,29 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev)  static void dsa_loop_drv_remove(struct mdio_device *mdiodev)  {  	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); -	struct dsa_loop_priv *ps = ds->priv; +	struct dsa_loop_priv *ps; + +	if (!ds) +		return; + +	ps = ds->priv;  	dsa_unregister_switch(ds);  	dev_put(ps->netdev); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void dsa_loop_drv_shutdown(struct mdio_device *mdiodev) +{ +	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); + +	if (!ds) +		return; + +	dsa_switch_shutdown(ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static struct mdio_driver dsa_loop_drv = { @@ -352,6 +371,7 @@ static struct mdio_driver dsa_loop_drv = {  	},  	.probe	= dsa_loop_drv_probe,  	.remove	= dsa_loop_drv_remove, +	.shutdown = dsa_loop_drv_shutdown,  };  #define NUM_FIXED_PHYS	(DSA_LOOP_NUM_PORTS - 2) diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 542cfc4ccb08..354655f9ed00 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1916,6 +1916,9 @@ static int hellcreek_remove(struct platform_device *pdev)  {  	struct hellcreek *hellcreek = platform_get_drvdata(pdev); +	if (!hellcreek) +		return 0; +  	hellcreek_hwtstamp_free(hellcreek);  	hellcreek_ptp_free(hellcreek);  	dsa_unregister_switch(hellcreek->ds); @@ -1924,6 +1927,18 @@ static int hellcreek_remove(struct platform_device *pdev)  	return 0;  } +static void hellcreek_shutdown(struct platform_device *pdev) +{ +	struct hellcreek *hellcreek = platform_get_drvdata(pdev); + +	if (!hellcreek) +		return; + +	dsa_switch_shutdown(hellcreek->ds); + +	platform_set_drvdata(pdev, NULL); +} +  static const struct hellcreek_platform_data de1soc_r1_pdata = {  	.name		 = "r4c30",  	.num_ports	 = 4, @@ -1946,6 +1961,7 @@ MODULE_DEVICE_TABLE(of, hellcreek_of_match);  static struct platform_driver hellcreek_driver = {  	.probe	= hellcreek_probe,  	.remove = hellcreek_remove, +	.shutdown = hellcreek_shutdown,  	.driver = {  		.name = "hellcreek",  		.of_match_table = hellcreek_of_match, diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index d7ce281570b5..89f920289ae2 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1379,6 +1379,12 @@ int lan9303_remove(struct lan9303 *chip)  }  EXPORT_SYMBOL(lan9303_remove); +void lan9303_shutdown(struct lan9303 *chip) +{ +	dsa_switch_shutdown(chip->ds); +} +EXPORT_SYMBOL(lan9303_shutdown); +  MODULE_AUTHOR("Juergen Borleis <[email protected]>");  MODULE_DESCRIPTION("Core driver for SMSC/Microchip LAN9303 three port ethernet switch");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/dsa/lan9303.h b/drivers/net/dsa/lan9303.h index 11f590b64701..c7f73efa50f0 100644 --- a/drivers/net/dsa/lan9303.h +++ b/drivers/net/dsa/lan9303.h @@ -10,3 +10,4 @@ extern const struct lan9303_phy_ops lan9303_indirect_phy_ops;  int lan9303_probe(struct lan9303 *chip, struct device_node *np);  int lan9303_remove(struct lan9303 *chip); +void lan9303_shutdown(struct lan9303 *chip); diff --git a/drivers/net/dsa/lan9303_i2c.c b/drivers/net/dsa/lan9303_i2c.c index 9bffaef65a04..8ca4713310fa 100644 --- a/drivers/net/dsa/lan9303_i2c.c +++ b/drivers/net/dsa/lan9303_i2c.c @@ -67,13 +67,28 @@ static int lan9303_i2c_probe(struct i2c_client *client,  static int lan9303_i2c_remove(struct i2c_client *client)  { -	struct lan9303_i2c *sw_dev; +	struct lan9303_i2c *sw_dev = i2c_get_clientdata(client); -	sw_dev = i2c_get_clientdata(client);  	if (!sw_dev) -		return -ENODEV; +		return 0; + +	lan9303_remove(&sw_dev->chip); + +	i2c_set_clientdata(client, NULL); + +	return 0; +} + +static void lan9303_i2c_shutdown(struct i2c_client *client) +{ +	struct lan9303_i2c *sw_dev = i2c_get_clientdata(client); + +	if (!sw_dev) +		return; + +	lan9303_shutdown(&sw_dev->chip); -	return lan9303_remove(&sw_dev->chip); +	i2c_set_clientdata(client, NULL);  }  /*-------------------------------------------------------------------------*/ @@ -97,6 +112,7 @@ static struct i2c_driver lan9303_i2c_driver = {  	},  	.probe = lan9303_i2c_probe,  	.remove = lan9303_i2c_remove, +	.shutdown = lan9303_i2c_shutdown,  	.id_table = lan9303_i2c_id,  };  module_i2c_driver(lan9303_i2c_driver); diff --git a/drivers/net/dsa/lan9303_mdio.c b/drivers/net/dsa/lan9303_mdio.c index 9cbe80460b53..bbb7032409ba 100644 --- a/drivers/net/dsa/lan9303_mdio.c +++ b/drivers/net/dsa/lan9303_mdio.c @@ -138,6 +138,20 @@ static void lan9303_mdio_remove(struct mdio_device *mdiodev)  		return;  	lan9303_remove(&sw_dev->chip); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void lan9303_mdio_shutdown(struct mdio_device *mdiodev) +{ +	struct lan9303_mdio *sw_dev = dev_get_drvdata(&mdiodev->dev); + +	if (!sw_dev) +		return; + +	lan9303_shutdown(&sw_dev->chip); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  /*-------------------------------------------------------------------------*/ @@ -155,6 +169,7 @@ static struct mdio_driver lan9303_mdio_driver = {  	},  	.probe  = lan9303_mdio_probe,  	.remove = lan9303_mdio_remove, +	.shutdown = lan9303_mdio_shutdown,  };  mdio_module_driver(lan9303_mdio_driver); diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 64d6dfa83122..3ff4b7e177f3 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1885,6 +1885,12 @@ static int gswip_gphy_fw_load(struct gswip_priv *priv, struct gswip_gphy_fw *gph  	reset_control_assert(gphy_fw->reset); +	/* The vendor BSP uses a 200ms delay after asserting the reset line. +	 * Without this some users are observing that the PHY is not coming up +	 * on the MDIO bus. +	 */ +	msleep(200); +  	ret = request_firmware(&fw, gphy_fw->fw_name, dev);  	if (ret) {  		dev_err(dev, "failed to load firmware: %s, error: %i\n", @@ -2178,6 +2184,9 @@ static int gswip_remove(struct platform_device *pdev)  	struct gswip_priv *priv = platform_get_drvdata(pdev);  	int i; +	if (!priv) +		return 0; +  	/* disable the switch */  	gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); @@ -2191,9 +2200,23 @@ static int gswip_remove(struct platform_device *pdev)  	for (i = 0; i < priv->num_gphy_fw; i++)  		gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } +static void gswip_shutdown(struct platform_device *pdev) +{ +	struct gswip_priv *priv = platform_get_drvdata(pdev); + +	if (!priv) +		return; + +	dsa_switch_shutdown(priv->ds); + +	platform_set_drvdata(pdev, NULL); +} +  static const struct gswip_hw_info gswip_xrx200 = {  	.max_ports = 7,  	.cpu_port = 6, @@ -2217,6 +2240,7 @@ MODULE_DEVICE_TABLE(of, gswip_of_match);  static struct platform_driver gswip_driver = {  	.probe = gswip_probe,  	.remove = gswip_remove, +	.shutdown = gswip_shutdown,  	.driver = {  		.name = "gswip",  		.of_match_table = gswip_of_match, diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index ea7550d1b634..866767b70d65 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -94,6 +94,8 @@ static int ksz8795_spi_remove(struct spi_device *spi)  	if (dev)  		ksz_switch_remove(dev); +	spi_set_drvdata(spi, NULL); +  	return 0;  } @@ -101,8 +103,15 @@ static void ksz8795_spi_shutdown(struct spi_device *spi)  {  	struct ksz_device *dev = spi_get_drvdata(spi); -	if (dev && dev->dev_ops->shutdown) +	if (!dev) +		return; + +	if (dev->dev_ops->shutdown)  		dev->dev_ops->shutdown(dev); + +	dsa_switch_shutdown(dev->ds); + +	spi_set_drvdata(spi, NULL);  }  static const struct of_device_id ksz8795_dt_ids[] = { diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c index 11293485138c..5883fa7edda2 100644 --- a/drivers/net/dsa/microchip/ksz8863_smi.c +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -191,6 +191,18 @@ static void ksz8863_smi_remove(struct mdio_device *mdiodev)  	if (dev)  		ksz_switch_remove(dev); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void ksz8863_smi_shutdown(struct mdio_device *mdiodev) +{ +	struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev); + +	if (dev) +		dsa_switch_shutdown(dev->ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static const struct of_device_id ksz8863_dt_ids[] = { @@ -203,6 +215,7 @@ MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);  static struct mdio_driver ksz8863_driver = {  	.probe	= ksz8863_smi_probe,  	.remove	= ksz8863_smi_remove, +	.shutdown = ksz8863_smi_shutdown,  	.mdiodrv.driver = {  		.name	= "ksz8863-switch",  		.of_match_table = ksz8863_dt_ids, diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index 4e053a25d077..f3afb8b8c4cc 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -56,7 +56,10 @@ static int ksz9477_i2c_remove(struct i2c_client *i2c)  {  	struct ksz_device *dev = i2c_get_clientdata(i2c); -	ksz_switch_remove(dev); +	if (dev) +		ksz_switch_remove(dev); + +	i2c_set_clientdata(i2c, NULL);  	return 0;  } @@ -65,8 +68,15 @@ static void ksz9477_i2c_shutdown(struct i2c_client *i2c)  {  	struct ksz_device *dev = i2c_get_clientdata(i2c); -	if (dev && dev->dev_ops->shutdown) +	if (!dev) +		return; + +	if (dev->dev_ops->shutdown)  		dev->dev_ops->shutdown(dev); + +	dsa_switch_shutdown(dev->ds); + +	i2c_set_clientdata(i2c, NULL);  }  static const struct i2c_device_id ksz9477_i2c_id[] = { diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index 15bc11b3cda4..e3cb0e6c9f6f 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -72,6 +72,8 @@ static int ksz9477_spi_remove(struct spi_device *spi)  	if (dev)  		ksz_switch_remove(dev); +	spi_set_drvdata(spi, NULL); +  	return 0;  } @@ -79,8 +81,10 @@ static void ksz9477_spi_shutdown(struct spi_device *spi)  {  	struct ksz_device *dev = spi_get_drvdata(spi); -	if (dev && dev->dev_ops->shutdown) -		dev->dev_ops->shutdown(dev); +	if (dev) +		dsa_switch_shutdown(dev->ds); + +	spi_set_drvdata(spi, NULL);  }  static const struct of_device_id ksz9477_dt_ids[] = { diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index d0cba2d1cd68..094737e5084a 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -3286,6 +3286,9 @@ mt7530_remove(struct mdio_device *mdiodev)  	struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);  	int ret = 0; +	if (!priv) +		return; +  	ret = regulator_disable(priv->core_pwr);  	if (ret < 0)  		dev_err(priv->dev, @@ -3301,11 +3304,26 @@ mt7530_remove(struct mdio_device *mdiodev)  	dsa_unregister_switch(priv->ds);  	mutex_destroy(&priv->reg_mutex); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void mt7530_shutdown(struct mdio_device *mdiodev) +{ +	struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); + +	if (!priv) +		return; + +	dsa_switch_shutdown(priv->ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static struct mdio_driver mt7530_mdio_driver = {  	.probe  = mt7530_probe,  	.remove = mt7530_remove, +	.shutdown = mt7530_shutdown,  	.mdiodrv.driver = {  		.name = "mt7530",  		.of_match_table = mt7530_of_match, diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 24b8219fd607..a4c6eb9a52d0 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -290,7 +290,24 @@ static void mv88e6060_remove(struct mdio_device *mdiodev)  {  	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); +	if (!ds) +		return; +  	dsa_unregister_switch(ds); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void mv88e6060_shutdown(struct mdio_device *mdiodev) +{ +	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); + +	if (!ds) +		return; + +	dsa_switch_shutdown(ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static const struct of_device_id mv88e6060_of_match[] = { @@ -303,6 +320,7 @@ static const struct of_device_id mv88e6060_of_match[] = {  static struct mdio_driver mv88e6060_driver = {  	.probe	= mv88e6060_probe,  	.remove = mv88e6060_remove, +	.shutdown = mv88e6060_shutdown,  	.mdiodrv.driver = {  		.name = "mv88e6060",  		.of_match_table = mv88e6060_of_match, diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index c45ca2473743..8ab0be793811 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3071,7 +3071,7 @@ static void mv88e6xxx_teardown(struct dsa_switch *ds)  {  	mv88e6xxx_teardown_devlink_params(ds);  	dsa_devlink_resources_unregister(ds); -	mv88e6xxx_teardown_devlink_regions(ds); +	mv88e6xxx_teardown_devlink_regions_global(ds);  }  static int mv88e6xxx_setup(struct dsa_switch *ds) @@ -3215,7 +3215,7 @@ unlock:  	if (err)  		goto out_resources; -	err = mv88e6xxx_setup_devlink_regions(ds); +	err = mv88e6xxx_setup_devlink_regions_global(ds);  	if (err)  		goto out_params; @@ -3229,6 +3229,16 @@ out_resources:  	return err;  } +static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) +{ +	return mv88e6xxx_setup_devlink_regions_port(ds, port); +} + +static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) +{ +	mv88e6xxx_teardown_devlink_regions_port(ds, port); +} +  /* prod_id for switch families which do not have a PHY model number */  static const u16 family_prod_id_table[] = {  	[MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, @@ -6116,6 +6126,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {  	.change_tag_protocol	= mv88e6xxx_change_tag_protocol,  	.setup			= mv88e6xxx_setup,  	.teardown		= mv88e6xxx_teardown, +	.port_setup		= mv88e6xxx_port_setup, +	.port_teardown		= mv88e6xxx_port_teardown,  	.phylink_validate	= mv88e6xxx_validate,  	.phylink_mac_link_state	= mv88e6xxx_serdes_pcs_get_state,  	.phylink_mac_config	= mv88e6xxx_mac_config, @@ -6389,7 +6401,12 @@ out:  static void mv88e6xxx_remove(struct mdio_device *mdiodev)  {  	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); -	struct mv88e6xxx_chip *chip = ds->priv; +	struct mv88e6xxx_chip *chip; + +	if (!ds) +		return; + +	chip = ds->priv;  	if (chip->info->ptp_support) {  		mv88e6xxx_hwtstamp_free(chip); @@ -6410,6 +6427,20 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)  		mv88e6xxx_g1_irq_free(chip);  	else  		mv88e6xxx_irq_poll_free(chip); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void mv88e6xxx_shutdown(struct mdio_device *mdiodev) +{ +	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); + +	if (!ds) +		return; + +	dsa_switch_shutdown(ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static const struct of_device_id mv88e6xxx_of_match[] = { @@ -6433,6 +6464,7 @@ MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);  static struct mdio_driver mv88e6xxx_driver = {  	.probe	= mv88e6xxx_probe,  	.remove = mv88e6xxx_remove, +	.shutdown = mv88e6xxx_shutdown,  	.mdiodrv.driver = {  		.name = "mv88e6085",  		.of_match_table = mv88e6xxx_of_match, diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xxx/devlink.c index 0c0f5ea6680c..381068395c63 100644 --- a/drivers/net/dsa/mv88e6xxx/devlink.c +++ b/drivers/net/dsa/mv88e6xxx/devlink.c @@ -647,26 +647,25 @@ static struct mv88e6xxx_region mv88e6xxx_regions[] = {  	},  }; -static void -mv88e6xxx_teardown_devlink_regions_global(struct mv88e6xxx_chip *chip) +void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds)  { +	struct mv88e6xxx_chip *chip = ds->priv;  	int i;  	for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++)  		dsa_devlink_region_destroy(chip->regions[i]);  } -static void -mv88e6xxx_teardown_devlink_regions_port(struct mv88e6xxx_chip *chip, -					int port) +void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port)  { +	struct mv88e6xxx_chip *chip = ds->priv; +  	dsa_devlink_region_destroy(chip->ports[port].region);  } -static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, -						struct mv88e6xxx_chip *chip, -						int port) +int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port)  { +	struct mv88e6xxx_chip *chip = ds->priv;  	struct devlink_region *region;  	region = dsa_devlink_port_region_create(ds, @@ -681,40 +680,10 @@ static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds,  	return 0;  } -static void -mv88e6xxx_teardown_devlink_regions_ports(struct mv88e6xxx_chip *chip) -{ -	int port; - -	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) -		mv88e6xxx_teardown_devlink_regions_port(chip, port); -} - -static int mv88e6xxx_setup_devlink_regions_ports(struct dsa_switch *ds, -						 struct mv88e6xxx_chip *chip) -{ -	int port; -	int err; - -	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { -		err = mv88e6xxx_setup_devlink_regions_port(ds, chip, port); -		if (err) -			goto out; -	} - -	return 0; - -out: -	while (port-- > 0) -		mv88e6xxx_teardown_devlink_regions_port(chip, port); - -	return err; -} - -static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds, -						  struct mv88e6xxx_chip *chip) +int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds)  {  	bool (*cond)(struct mv88e6xxx_chip *chip); +	struct mv88e6xxx_chip *chip = ds->priv;  	struct devlink_region_ops *ops;  	struct devlink_region *region;  	u64 size; @@ -753,30 +722,6 @@ out:  	return PTR_ERR(region);  } -int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds) -{ -	struct mv88e6xxx_chip *chip = ds->priv; -	int err; - -	err = mv88e6xxx_setup_devlink_regions_global(ds, chip); -	if (err) -		return err; - -	err = mv88e6xxx_setup_devlink_regions_ports(ds, chip); -	if (err) -		mv88e6xxx_teardown_devlink_regions_global(chip); - -	return err; -} - -void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds) -{ -	struct mv88e6xxx_chip *chip = ds->priv; - -	mv88e6xxx_teardown_devlink_regions_ports(chip); -	mv88e6xxx_teardown_devlink_regions_global(chip); -} -  int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,  			       struct devlink_info_req *req,  			       struct netlink_ext_ack *extack) diff --git a/drivers/net/dsa/mv88e6xxx/devlink.h b/drivers/net/dsa/mv88e6xxx/devlink.h index 3d72db3dcf95..65ce6a6858b9 100644 --- a/drivers/net/dsa/mv88e6xxx/devlink.h +++ b/drivers/net/dsa/mv88e6xxx/devlink.h @@ -12,8 +12,10 @@ int mv88e6xxx_devlink_param_get(struct dsa_switch *ds, u32 id,  				struct devlink_param_gset_ctx *ctx);  int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id,  				struct devlink_param_gset_ctx *ctx); -int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds); -void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds); +int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds); +void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds); +int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port); +void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port);  int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,  			       struct devlink_info_req *req, diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 3656e67af789..a3a9636430d6 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 -/* Copyright 2019-2021 NXP Semiconductors +/* Copyright 2019-2021 NXP   *   * This is an umbrella module for all network switches that are   * register-compatible with Ocelot and that perform I/O to their host CPU diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 5854bab43327..54024b6f9498 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -1,5 +1,5 @@  /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright 2019 NXP Semiconductors +/* Copyright 2019 NXP   */  #ifndef _MSCC_FELIX_H  #define _MSCC_FELIX_H diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index f966a253d1c7..11b42fd812e4 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: (GPL-2.0 OR MIT)  /* Copyright 2017 Microsemi Corporation - * Copyright 2018-2019 NXP Semiconductors + * Copyright 2018-2019 NXP   */  #include <linux/fsl/enetc_mdio.h>  #include <soc/mscc/ocelot_qsys.h> @@ -1472,9 +1472,10 @@ err_pci_enable:  static void felix_pci_remove(struct pci_dev *pdev)  { -	struct felix *felix; +	struct felix *felix = pci_get_drvdata(pdev); -	felix = pci_get_drvdata(pdev); +	if (!felix) +		return;  	dsa_unregister_switch(felix->ds); @@ -1482,6 +1483,20 @@ static void felix_pci_remove(struct pci_dev *pdev)  	kfree(felix);  	pci_disable_device(pdev); + +	pci_set_drvdata(pdev, NULL); +} + +static void felix_pci_shutdown(struct pci_dev *pdev) +{ +	struct felix *felix = pci_get_drvdata(pdev); + +	if (!felix) +		return; + +	dsa_switch_shutdown(felix->ds); + +	pci_set_drvdata(pdev, NULL);  }  static struct pci_device_id felix_ids[] = { @@ -1498,6 +1513,7 @@ static struct pci_driver felix_vsc9959_pci_driver = {  	.id_table	= felix_ids,  	.probe		= felix_pci_probe,  	.remove		= felix_pci_remove, +	.shutdown	= felix_pci_shutdown,  };  module_pci_driver(felix_vsc9959_pci_driver); diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index deae923c8b7a..de1d34a1f1e4 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1245,18 +1245,33 @@ err_alloc_felix:  static int seville_remove(struct platform_device *pdev)  { -	struct felix *felix; +	struct felix *felix = platform_get_drvdata(pdev); -	felix = platform_get_drvdata(pdev); +	if (!felix) +		return 0;  	dsa_unregister_switch(felix->ds);  	kfree(felix->ds);  	kfree(felix); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } +static void seville_shutdown(struct platform_device *pdev) +{ +	struct felix *felix = platform_get_drvdata(pdev); + +	if (!felix) +		return; + +	dsa_switch_shutdown(felix->ds); + +	platform_set_drvdata(pdev, NULL); +} +  static const struct of_device_id seville_of_match[] = {  	{ .compatible = "mscc,vsc9953-switch" },  	{ }, @@ -1266,6 +1281,7 @@ MODULE_DEVICE_TABLE(of, seville_of_match);  static struct platform_driver seville_vsc9953_driver = {  	.probe		= seville_probe,  	.remove		= seville_remove, +	.shutdown	= seville_shutdown,  	.driver = {  		.name		= "mscc_seville",  		.of_match_table	= of_match_ptr(seville_of_match), diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index 563d8a279030..a6bfb6abc51a 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -1083,6 +1083,9 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev)  	struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev);  	unsigned int i; +	if (!priv) +		return; +  	for (i = 0; i < ARRAY_SIZE(priv->port); i++) {  		struct ar9331_sw_port *port = &priv->port[i]; @@ -1094,6 +1097,20 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev)  	dsa_unregister_switch(&priv->ds);  	reset_control_assert(priv->sw_reset); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void ar9331_sw_shutdown(struct mdio_device *mdiodev) +{ +	struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev); + +	if (!priv) +		return; + +	dsa_switch_shutdown(&priv->ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static const struct of_device_id ar9331_sw_of_match[] = { @@ -1104,6 +1121,7 @@ static const struct of_device_id ar9331_sw_of_match[] = {  static struct mdio_driver ar9331_sw_mdio_driver = {  	.probe = ar9331_sw_probe,  	.remove = ar9331_sw_remove, +	.shutdown = ar9331_sw_shutdown,  	.mdiodrv.driver = {  		.name = AR9331_SW_NAME,  		.of_match_table = ar9331_sw_of_match, diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index 1f63f50f73f1..a984f06f6f04 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -643,10 +643,8 @@ qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask)  }  static int -qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) +qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data)  { -	struct qca8k_priv *priv = salve_bus->priv; -	struct mii_bus *bus = priv->bus;  	u16 r1, r2, page;  	u32 val;  	int ret; @@ -682,10 +680,8 @@ exit:  }  static int -qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) +qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum)  { -	struct qca8k_priv *priv = salve_bus->priv; -	struct mii_bus *bus = priv->bus;  	u16 r1, r2, page;  	u32 val;  	int ret; @@ -727,6 +723,24 @@ exit:  }  static int +qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data) +{ +	struct qca8k_priv *priv = slave_bus->priv; +	struct mii_bus *bus = priv->bus; + +	return qca8k_mdio_write(bus, phy, regnum, data); +} + +static int +qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) +{ +	struct qca8k_priv *priv = slave_bus->priv; +	struct mii_bus *bus = priv->bus; + +	return qca8k_mdio_read(bus, phy, regnum); +} + +static int  qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data)  {  	struct qca8k_priv *priv = ds->priv; @@ -775,8 +789,8 @@ qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio)  	bus->priv = (void *)priv;  	bus->name = "qca8k slave mii"; -	bus->read = qca8k_mdio_read; -	bus->write = qca8k_mdio_write; +	bus->read = qca8k_internal_mdio_read; +	bus->write = qca8k_internal_mdio_write;  	snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d",  		 ds->index); @@ -1866,10 +1880,27 @@ qca8k_sw_remove(struct mdio_device *mdiodev)  	struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev);  	int i; +	if (!priv) +		return; +  	for (i = 0; i < QCA8K_NUM_PORTS; i++)  		qca8k_port_set_status(priv, i, 0);  	dsa_unregister_switch(priv->ds); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void qca8k_sw_shutdown(struct mdio_device *mdiodev) +{ +	struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); + +	if (!priv) +		return; + +	dsa_switch_shutdown(priv->ds); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  #ifdef CONFIG_PM_SLEEP @@ -1926,6 +1957,7 @@ static const struct of_device_id qca8k_of_match[] = {  static struct mdio_driver qca8kmdio_driver = {  	.probe  = qca8k_sw_probe,  	.remove = qca8k_sw_remove, +	.shutdown = qca8k_sw_shutdown,  	.mdiodrv.driver = {  		.name = "qca8k",  		.of_match_table = qca8k_of_match, diff --git a/drivers/net/dsa/realtek-smi-core.c b/drivers/net/dsa/realtek-smi-core.c index 8e49d4f85d48..2fcfd917b876 100644 --- a/drivers/net/dsa/realtek-smi-core.c +++ b/drivers/net/dsa/realtek-smi-core.c @@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)  	smi->slave_mii_bus->parent = smi->dev;  	smi->ds->slave_mii_bus = smi->slave_mii_bus; -	ret = of_mdiobus_register(smi->slave_mii_bus, mdio_np); +	ret = devm_of_mdiobus_register(smi->dev, smi->slave_mii_bus, mdio_np);  	if (ret) {  		dev_err(smi->dev, "unable to register MDIO bus %s\n",  			smi->slave_mii_bus->id); @@ -464,16 +464,33 @@ static int realtek_smi_probe(struct platform_device *pdev)  static int realtek_smi_remove(struct platform_device *pdev)  { -	struct realtek_smi *smi = dev_get_drvdata(&pdev->dev); +	struct realtek_smi *smi = platform_get_drvdata(pdev); + +	if (!smi) +		return 0;  	dsa_unregister_switch(smi->ds);  	if (smi->slave_mii_bus)  		of_node_put(smi->slave_mii_bus->dev.of_node);  	gpiod_set_value(smi->reset, 1); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } +static void realtek_smi_shutdown(struct platform_device *pdev) +{ +	struct realtek_smi *smi = platform_get_drvdata(pdev); + +	if (!smi) +		return; + +	dsa_switch_shutdown(smi->ds); + +	platform_set_drvdata(pdev, NULL); +} +  static const struct of_device_id realtek_smi_of_match[] = {  	{  		.compatible = "realtek,rtl8366rb", @@ -495,6 +512,7 @@ static struct platform_driver realtek_smi_driver = {  	},  	.probe  = realtek_smi_probe,  	.remove = realtek_smi_remove, +	.shutdown = realtek_smi_shutdown,  };  module_platform_driver(realtek_smi_driver); diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c index 387a1f2f161c..5bbf1707f2af 100644 --- a/drivers/net/dsa/sja1105/sja1105_clocking.c +++ b/drivers/net/dsa/sja1105/sja1105_clocking.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: BSD-3-Clause -/* Copyright (c) 2016-2018, NXP Semiconductors +/* Copyright 2016-2018 NXP   * Copyright (c) 2018-2019, Vladimir Oltean <[email protected]>   */  #include <linux/packing.h> diff --git a/drivers/net/dsa/sja1105/sja1105_devlink.c b/drivers/net/dsa/sja1105/sja1105_devlink.c index 05c7f4ca3b1a..0569ff066634 100644 --- a/drivers/net/dsa/sja1105/sja1105_devlink.c +++ b/drivers/net/dsa/sja1105/sja1105_devlink.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0  /* Copyright (c) 2018-2019, Vladimir Oltean <[email protected]> - * Copyright 2020 NXP Semiconductors + * Copyright 2020 NXP   */  #include "sja1105.h" diff --git a/drivers/net/dsa/sja1105/sja1105_flower.c b/drivers/net/dsa/sja1105/sja1105_flower.c index 6c10ffa968ce..72b9b39b0989 100644 --- a/drivers/net/dsa/sja1105/sja1105_flower.c +++ b/drivers/net/dsa/sja1105/sja1105_flower.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 -/* Copyright 2020, NXP Semiconductors +/* Copyright 2020 NXP   */  #include "sja1105.h"  #include "sja1105_vl.h" diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 2f8cc6686c38..7c0db80eff00 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3335,13 +3335,29 @@ static int sja1105_probe(struct spi_device *spi)  static int sja1105_remove(struct spi_device *spi)  {  	struct sja1105_private *priv = spi_get_drvdata(spi); -	struct dsa_switch *ds = priv->ds; -	dsa_unregister_switch(ds); +	if (!priv) +		return 0; + +	dsa_unregister_switch(priv->ds); + +	spi_set_drvdata(spi, NULL);  	return 0;  } +static void sja1105_shutdown(struct spi_device *spi) +{ +	struct sja1105_private *priv = spi_get_drvdata(spi); + +	if (!priv) +		return; + +	dsa_switch_shutdown(priv->ds); + +	spi_set_drvdata(spi, NULL); +} +  static const struct of_device_id sja1105_dt_ids[] = {  	{ .compatible = "nxp,sja1105e", .data = &sja1105e_info },  	{ .compatible = "nxp,sja1105t", .data = &sja1105t_info }, @@ -3365,6 +3381,7 @@ static struct spi_driver sja1105_driver = {  	},  	.probe  = sja1105_probe,  	.remove = sja1105_remove, +	.shutdown = sja1105_shutdown,  };  module_spi_driver(sja1105_driver); diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c index 705d3900e43a..215dd17ca790 100644 --- a/drivers/net/dsa/sja1105/sja1105_mdio.c +++ b/drivers/net/dsa/sja1105/sja1105_mdio.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 -/* Copyright 2021, NXP Semiconductors +/* Copyright 2021 NXP   */  #include <linux/pcs/pcs-xpcs.h>  #include <linux/of_mdio.h> diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index d60a530d0272..d3c9ad6d39d4 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: BSD-3-Clause -/* Copyright (c) 2016-2018, NXP Semiconductors +/* Copyright 2016-2018 NXP   * Copyright (c) 2018, Sensor-Technik Wiedemann GmbH   * Copyright (c) 2018-2019, Vladimir Oltean <[email protected]>   */ diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c index 7a422ef4deb6..baba204ad62f 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.c +++ b/drivers/net/dsa/sja1105/sja1105_static_config.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: BSD-3-Clause -/* Copyright (c) 2016-2018, NXP Semiconductors +/* Copyright 2016-2018 NXP   * Copyright (c) 2018-2019, Vladimir Oltean <[email protected]>   */  #include "sja1105_static_config.h" diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index bce0f5c03d0b..6a372d5f22ae 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -1,5 +1,5 @@  /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright (c) 2016-2018, NXP Semiconductors +/* Copyright 2016-2018 NXP   * Copyright (c) 2018-2019, Vladimir Oltean <[email protected]>   */  #ifndef _SJA1105_STATIC_CONFIG_H diff --git a/drivers/net/dsa/sja1105/sja1105_vl.c b/drivers/net/dsa/sja1105/sja1105_vl.c index ec7b65daec20..6802f4057cc0 100644 --- a/drivers/net/dsa/sja1105/sja1105_vl.c +++ b/drivers/net/dsa/sja1105/sja1105_vl.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 -/* Copyright 2020, NXP Semiconductors +/* Copyright 2020 NXP   */  #include <net/tc_act/tc_gate.h>  #include <linux/dsa/8021q.h> diff --git a/drivers/net/dsa/sja1105/sja1105_vl.h b/drivers/net/dsa/sja1105/sja1105_vl.h index 173d78963fed..51fba0dce91a 100644 --- a/drivers/net/dsa/sja1105/sja1105_vl.h +++ b/drivers/net/dsa/sja1105/sja1105_vl.h @@ -1,5 +1,5 @@  /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright 2020, NXP Semiconductors +/* Copyright 2020 NXP   */  #ifndef _SJA1105_VL_H  #define _SJA1105_VL_H diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c index 19ce4aa0973b..a4b1447ff055 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-core.c +++ b/drivers/net/dsa/vitesse-vsc73xx-core.c @@ -1225,6 +1225,12 @@ int vsc73xx_remove(struct vsc73xx *vsc)  }  EXPORT_SYMBOL(vsc73xx_remove); +void vsc73xx_shutdown(struct vsc73xx *vsc) +{ +	dsa_switch_shutdown(vsc->ds); +} +EXPORT_SYMBOL(vsc73xx_shutdown); +  MODULE_AUTHOR("Linus Walleij <[email protected]>");  MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/dsa/vitesse-vsc73xx-platform.c b/drivers/net/dsa/vitesse-vsc73xx-platform.c index 2a57f337b2a2..fe4b154a0a57 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-platform.c +++ b/drivers/net/dsa/vitesse-vsc73xx-platform.c @@ -116,7 +116,26 @@ static int vsc73xx_platform_remove(struct platform_device *pdev)  {  	struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev); -	return vsc73xx_remove(&vsc_platform->vsc); +	if (!vsc_platform) +		return 0; + +	vsc73xx_remove(&vsc_platform->vsc); + +	platform_set_drvdata(pdev, NULL); + +	return 0; +} + +static void vsc73xx_platform_shutdown(struct platform_device *pdev) +{ +	struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev); + +	if (!vsc_platform) +		return; + +	vsc73xx_shutdown(&vsc_platform->vsc); + +	platform_set_drvdata(pdev, NULL);  }  static const struct vsc73xx_ops vsc73xx_platform_ops = { @@ -144,6 +163,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match);  static struct platform_driver vsc73xx_platform_driver = {  	.probe = vsc73xx_platform_probe,  	.remove = vsc73xx_platform_remove, +	.shutdown = vsc73xx_platform_shutdown,  	.driver = {  		.name = "vsc73xx-platform",  		.of_match_table = vsc73xx_of_match, diff --git a/drivers/net/dsa/vitesse-vsc73xx-spi.c b/drivers/net/dsa/vitesse-vsc73xx-spi.c index 81eca4a5781d..645398901e05 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-spi.c +++ b/drivers/net/dsa/vitesse-vsc73xx-spi.c @@ -163,7 +163,26 @@ static int vsc73xx_spi_remove(struct spi_device *spi)  {  	struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi); -	return vsc73xx_remove(&vsc_spi->vsc); +	if (!vsc_spi) +		return 0; + +	vsc73xx_remove(&vsc_spi->vsc); + +	spi_set_drvdata(spi, NULL); + +	return 0; +} + +static void vsc73xx_spi_shutdown(struct spi_device *spi) +{ +	struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi); + +	if (!vsc_spi) +		return; + +	vsc73xx_shutdown(&vsc_spi->vsc); + +	spi_set_drvdata(spi, NULL);  }  static const struct vsc73xx_ops vsc73xx_spi_ops = { @@ -191,6 +210,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match);  static struct spi_driver vsc73xx_spi_driver = {  	.probe = vsc73xx_spi_probe,  	.remove = vsc73xx_spi_remove, +	.shutdown = vsc73xx_spi_shutdown,  	.driver = {  		.name = "vsc73xx-spi",  		.of_match_table = vsc73xx_of_match, diff --git a/drivers/net/dsa/vitesse-vsc73xx.h b/drivers/net/dsa/vitesse-vsc73xx.h index 7478f8d4e0a9..30b951504e65 100644 --- a/drivers/net/dsa/vitesse-vsc73xx.h +++ b/drivers/net/dsa/vitesse-vsc73xx.h @@ -27,3 +27,4 @@ struct vsc73xx_ops {  int vsc73xx_is_addr_valid(u8 block, u8 subblock);  int vsc73xx_probe(struct vsc73xx *vsc);  int vsc73xx_remove(struct vsc73xx *vsc); +void vsc73xx_shutdown(struct vsc73xx *vsc); diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c index 130abb0f1438..469420941054 100644 --- a/drivers/net/dsa/xrs700x/xrs700x.c +++ b/drivers/net/dsa/xrs700x/xrs700x.c @@ -822,6 +822,12 @@ void xrs700x_switch_remove(struct xrs700x *priv)  }  EXPORT_SYMBOL(xrs700x_switch_remove); +void xrs700x_switch_shutdown(struct xrs700x *priv) +{ +	dsa_switch_shutdown(priv->ds); +} +EXPORT_SYMBOL(xrs700x_switch_shutdown); +  MODULE_AUTHOR("George McCollister <[email protected]>");  MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/dsa/xrs700x/xrs700x.h b/drivers/net/dsa/xrs700x/xrs700x.h index ff62cf61b091..4d58257471d2 100644 --- a/drivers/net/dsa/xrs700x/xrs700x.h +++ b/drivers/net/dsa/xrs700x/xrs700x.h @@ -40,3 +40,4 @@ struct xrs700x {  struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv);  int xrs700x_switch_register(struct xrs700x *priv);  void xrs700x_switch_remove(struct xrs700x *priv); +void xrs700x_switch_shutdown(struct xrs700x *priv); diff --git a/drivers/net/dsa/xrs700x/xrs700x_i2c.c b/drivers/net/dsa/xrs700x/xrs700x_i2c.c index 489d9385b4f0..6deae388a0d6 100644 --- a/drivers/net/dsa/xrs700x/xrs700x_i2c.c +++ b/drivers/net/dsa/xrs700x/xrs700x_i2c.c @@ -109,11 +109,28 @@ static int xrs700x_i2c_remove(struct i2c_client *i2c)  {  	struct xrs700x *priv = i2c_get_clientdata(i2c); +	if (!priv) +		return 0; +  	xrs700x_switch_remove(priv); +	i2c_set_clientdata(i2c, NULL); +  	return 0;  } +static void xrs700x_i2c_shutdown(struct i2c_client *i2c) +{ +	struct xrs700x *priv = i2c_get_clientdata(i2c); + +	if (!priv) +		return; + +	xrs700x_switch_shutdown(priv); + +	i2c_set_clientdata(i2c, NULL); +} +  static const struct i2c_device_id xrs700x_i2c_id[] = {  	{ "xrs700x-switch", 0 },  	{}, @@ -137,6 +154,7 @@ static struct i2c_driver xrs700x_i2c_driver = {  	},  	.probe	= xrs700x_i2c_probe,  	.remove	= xrs700x_i2c_remove, +	.shutdown = xrs700x_i2c_shutdown,  	.id_table = xrs700x_i2c_id,  }; diff --git a/drivers/net/dsa/xrs700x/xrs700x_mdio.c b/drivers/net/dsa/xrs700x/xrs700x_mdio.c index 44f58bee04a4..d01cf1073d49 100644 --- a/drivers/net/dsa/xrs700x/xrs700x_mdio.c +++ b/drivers/net/dsa/xrs700x/xrs700x_mdio.c @@ -136,7 +136,24 @@ static void xrs700x_mdio_remove(struct mdio_device *mdiodev)  {  	struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev); +	if (!priv) +		return; +  	xrs700x_switch_remove(priv); + +	dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void xrs700x_mdio_shutdown(struct mdio_device *mdiodev) +{ +	struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev); + +	if (!priv) +		return; + +	xrs700x_switch_shutdown(priv); + +	dev_set_drvdata(&mdiodev->dev, NULL);  }  static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = { @@ -155,6 +172,7 @@ static struct mdio_driver xrs700x_mdio_driver = {  	},  	.probe	= xrs700x_mdio_probe,  	.remove	= xrs700x_mdio_remove, +	.shutdown = xrs700x_mdio_shutdown,  };  mdio_module_driver(xrs700x_mdio_driver);  |