diff options
author | Andrew Lunn <andrew@lunn.ch> | 2017-12-06 19:05:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-12-07 13:53:05 -0500 |
commit | 3126aeec5313565bfa19e2dd8fd7e3c3390514cb (patch) | |
tree | 542764a7424158766550b4f7915f70aa955b8964 | |
parent | 3d5fdba1842bdd2eef29364c660558cb4cbb3fe0 (diff) |
net: dsa: mv88e6xxx: Unregister MDIO bus on error path
The MDIO busses need to be unregistered before they are freed,
otherwise BUG() is called. Add a call to the unregister code if the
registration fails, since we can have multiple busses, of which some
may correctly register before one fails. This requires moving the code
around a little.
Fixes: a3c53be55c95 ("net: dsa: mv88e6xxx: Support multiple MDIO busses")
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 70004264f60d..66d33e97cbc5 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -2177,6 +2177,19 @@ static const struct of_device_id mv88e6xxx_mdio_external_match[] = { | |||
2177 | { }, | 2177 | { }, |
2178 | }; | 2178 | }; |
2179 | 2179 | ||
2180 | static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) | ||
2181 | |||
2182 | { | ||
2183 | struct mv88e6xxx_mdio_bus *mdio_bus; | ||
2184 | struct mii_bus *bus; | ||
2185 | |||
2186 | list_for_each_entry(mdio_bus, &chip->mdios, list) { | ||
2187 | bus = mdio_bus->bus; | ||
2188 | |||
2189 | mdiobus_unregister(bus); | ||
2190 | } | ||
2191 | } | ||
2192 | |||
2180 | static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip, | 2193 | static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip, |
2181 | struct device_node *np) | 2194 | struct device_node *np) |
2182 | { | 2195 | { |
@@ -2201,27 +2214,16 @@ static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip, | |||
2201 | match = of_match_node(mv88e6xxx_mdio_external_match, child); | 2214 | match = of_match_node(mv88e6xxx_mdio_external_match, child); |
2202 | if (match) { | 2215 | if (match) { |
2203 | err = mv88e6xxx_mdio_register(chip, child, true); | 2216 | err = mv88e6xxx_mdio_register(chip, child, true); |
2204 | if (err) | 2217 | if (err) { |
2218 | mv88e6xxx_mdios_unregister(chip); | ||
2205 | return err; | 2219 | return err; |
2220 | } | ||
2206 | } | 2221 | } |
2207 | } | 2222 | } |
2208 | 2223 | ||
2209 | return 0; | 2224 | return 0; |
2210 | } | 2225 | } |
2211 | 2226 | ||
2212 | static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) | ||
2213 | |||
2214 | { | ||
2215 | struct mv88e6xxx_mdio_bus *mdio_bus; | ||
2216 | struct mii_bus *bus; | ||
2217 | |||
2218 | list_for_each_entry(mdio_bus, &chip->mdios, list) { | ||
2219 | bus = mdio_bus->bus; | ||
2220 | |||
2221 | mdiobus_unregister(bus); | ||
2222 | } | ||
2223 | } | ||
2224 | |||
2225 | static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds) | 2227 | static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds) |
2226 | { | 2228 | { |
2227 | struct mv88e6xxx_chip *chip = ds->priv; | 2229 | struct mv88e6xxx_chip *chip = ds->priv; |