tmp_suning_uos_patched/net/dsa
Vladimir Oltean 43c880b860 net: dsa: don't allocate the slave_mii_bus using devres
[ Upstream commit 5135e96a3dd2f4555ae6981c3155a62bcf3227f6 ]

The Linux device model permits both the ->shutdown and ->remove driver
methods to get called during a shutdown procedure. Example: a DSA switch
which sits on an SPI bus, and the SPI bus driver calls this on its
->shutdown method:

spi_unregister_controller
-> device_for_each_child(&ctlr->dev, NULL, __unregister);
   -> spi_unregister_device(to_spi_device(dev));
      -> device_del(&spi->dev);

So this is a simple pattern which can theoretically appear on any bus,
although the only other buses on which I've been able to find it are
I2C:

i2c_del_adapter
-> device_for_each_child(&adap->dev, NULL, __unregister_client);
   -> i2c_unregister_device(client);
      -> device_unregister(&client->dev);

The implication of this pattern is that devices on these buses can be
unregistered after having been shut down. The drivers for these devices
might choose to return early either from ->remove or ->shutdown if the
other callback has already run once, and they might choose that the
->shutdown method should only perform a subset of the teardown done by
->remove (to avoid unnecessary delays when rebooting).

So in other words, the device driver may choose on ->remove to not
do anything (therefore to not unregister an MDIO bus it has registered
on ->probe), because this ->remove is actually triggered by the
device_shutdown path, and its ->shutdown method has already run and done
the minimally required cleanup.

This used to be fine until the blamed commit, but now, the following
BUG_ON triggers:

void mdiobus_free(struct mii_bus *bus)
{
	/* For compatibility with error handling in drivers. */
	if (bus->state == MDIOBUS_ALLOCATED) {
		kfree(bus);
		return;
	}

	BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
	bus->state = MDIOBUS_RELEASED;

	put_device(&bus->dev);
}

In other words, there is an attempt to free an MDIO bus which was not
unregistered. The attempt to free it comes from the devres release
callbacks of the SPI device, which are executed after the device is
unregistered.

I'm not saying that the fact that MDIO buses allocated using devres
would automatically get unregistered wasn't strange. I'm just saying
that the commit didn't care about auditing existing call paths in the
kernel, and now, the following code sequences are potentially buggy:

(a) devm_mdiobus_alloc followed by plain mdiobus_register, for a device
    located on a bus that unregisters its children on shutdown. After
    the blamed patch, either both the alloc and the register should use
    devres, or none should.

(b) devm_mdiobus_alloc followed by plain mdiobus_register, and then no
    mdiobus_unregister at all in the remove path. After the blamed
    patch, nobody unregisters the MDIO bus anymore, so this is even more
    buggy than the previous case which needs a specific bus
    configuration to be seen, this one is an unconditional bug.

In this case, DSA falls into category (a), it tries to be helpful and
registers an MDIO bus on behalf of the switch, which might be on such a
bus. I've no idea why it does it under devres.

It does this on probe:

	if (!ds->slave_mii_bus && ds->ops->phy_read)
		alloc and register mdio bus

and this on remove:

	if (ds->slave_mii_bus && ds->ops->phy_read)
		unregister mdio bus

I _could_ imagine using devres because the condition used on remove is
different than the condition used on probe. So strictly speaking, DSA
cannot determine whether the ds->slave_mii_bus it sees on remove is the
ds->slave_mii_bus that _it_ has allocated on probe. Using devres would
have solved that problem. But nonetheless, the existing code already
proceeds to unregister the MDIO bus, even though it might be
unregistering an MDIO bus it has never registered. So I can only guess
that no driver that implements ds->ops->phy_read also allocates and
registers ds->slave_mii_bus itself.

So in that case, if unregistering is fine, freeing must be fine too.

Stop using devres and free the MDIO bus manually. This will make devres
stop attempting to free a still registered MDIO bus on ->shutdown.

Fixes: ac3a68d566 ("net: phy: don't abuse devres in devm_mdiobus_register()")
Reported-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2021-09-30 10:11:02 +02:00
..
dsa_priv.h net: dsa: Utilize __vlan_find_dev_deep_rcu() 2020-10-02 13:36:07 -07:00
dsa.c net: dsa: Add devlink port regions support to DSA 2020-10-04 14:38:53 -07:00
dsa2.c net: dsa: don't allocate the slave_mii_bus using devres 2021-09-30 10:11:02 +02:00
Kconfig net: dsa: tag_rtl4_a: Implement Realtek 4 byte A tag 2020-07-08 15:36:19 -07:00
Makefile net: dsa: tag_rtl4_a: Implement Realtek 4 byte A tag 2020-07-08 15:36:19 -07:00
master.c net: dsa: fix a crash if ->get_sset_count() fails 2021-06-03 09:00:38 +02:00
port.c net: dsa: propagate switchdev vlan_filtering prepare phase to drivers 2020-10-05 05:56:48 -07:00
slave.c net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup 2021-09-22 12:27:58 +02:00
switch.c net: dsa: properly check for the bridge_leave methods in dsa_switch_bridge_leave() 2021-07-25 14:36:20 +02:00
tag_8021q.c net: dsa: tag_8021q: fix the VLAN IDs used for encoding sub-VLANs 2021-06-10 13:39:17 +02:00
tag_ar9331.c net: dsa: tag_ar9331: let DSA core deal with TX reallocation 2021-03-17 17:06:22 +01:00
tag_brcm.c net: dsa: tag_brcm: let DSA core deal with TX reallocation 2021-03-17 17:06:21 +01:00
tag_dsa.c net: dsa: tag_dsa: let DSA core deal with TX reallocation 2021-03-17 17:06:21 +01:00
tag_edsa.c net: dsa: tag_edsa: let DSA core deal with TX reallocation 2021-03-17 17:06:21 +01:00
tag_gswip.c net: dsa: tag_gswip: let DSA core deal with TX reallocation 2021-03-17 17:06:22 +01:00
tag_ksz.c net: dsa: tag_ksz: don't allocate additional memory for padding/tagging 2021-03-17 17:06:21 +01:00
tag_lan9303.c net: dsa: tag_lan9303: let DSA core deal with TX reallocation 2021-03-17 17:06:21 +01:00
tag_mtk.c net: dsa: tag_mtk: fix 802.1ad VLAN egress 2021-03-17 17:06:22 +01:00
tag_ocelot.c net: dsa: tag_ocelot: let DSA core deal with TX reallocation 2021-03-17 17:06:21 +01:00
tag_qca.c net: dsa: tag_qca: let DSA core deal with TX reallocation 2021-03-17 17:06:21 +01:00
tag_rtl4_a.c net: dsa: tag_rtl4_a: Fix egress tags 2021-09-22 12:28:04 +02:00
tag_sja1105.c net: dsa: tag_sja1105: use a custom flow dissector procedure 2020-09-26 14:17:59 -07:00
tag_trailer.c net: dsa: trailer: don't allocate additional memory for padding/tagging 2021-03-17 17:06:21 +01:00