Commit 564df7ab authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa-shutdown'

Vladimir Oltean says:

====================
Make DSA switch drivers compatible with masters which unregister on shutdown

Changes in v2:
- fix build for b53_mmap
- use unregister_netdevice_many

It was reported by Lino here:

https://lore.kernel.org/netdev/20210909095324.12978-1-LinoSanfilippo@gmx.de/



that when the DSA master attempts to unregister its net_device on
shutdown, DSA should prevent that operation from succeeding because it
holds a reference to it. This hangs the shutdown process.

This issue was essentially introduced in commit 2f1e8ea7 ("net: dsa:
link interfaces with the DSA master to get rid of lockdep warnings").
The present series patches all DSA drivers to handle that case,
depending on whether those drivers were introduced before or after the
offending commit, a different Fixes: tag is specified for them.

The approach taken by this series solves the issue in essentially the
same way as Lino's patches, except for three key differences:

- this series takes a more minimal approach in what is done on shutdown,
  we do not attempt a full tree teardown as that is not strictly
  necessary. I might revisit this if there are compelling reasons to do
  otherwise

- this series fixes the issues for all DSA drivers, not just KSZ9897

- this series works even if the ->remove driver method gets called for
  the same device too, not just ->shutdown. This is really possible to
  happen for SPI device drivers, and potentially possible for other bus
  device drivers too.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 02319bf1 a68e9da4
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -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,
+13 −0
Original line number Diff line number Diff line
@@ -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,
+5 −0
Original line number Diff line number Diff line
@@ -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)		\
+13 −0
Original line number Diff line number Diff line
@@ -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);
+19 −2
Original line number Diff line number Diff line
@@ -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,
Loading