diff options
author | David S. Miller <davem@davemloft.net> | 2017-12-07 13:53:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-12-07 13:53:05 -0500 |
commit | c880949f006f6095295eb596635b599513970ad4 (patch) | |
tree | 542764a7424158766550b4f7915f70aa955b8964 | |
parent | e46772a6946a7d1f3fbbc1415871851d6651f1d4 (diff) | |
parent | 3126aeec5313565bfa19e2dd8fd7e3c3390514cb (diff) |
Merge branch 'mv88e6xxx-error-patch-fixes'
Andrew Lunn says:
====================
mv88e6xxx error patch fixes
While trying to bring up a new PHY on a board, i exercised the error
paths a bit, and discovered some bugs. The unwind for interrupt
handling deadlocks, and the MDIO code hits a BUG() when a registered
MDIO device is freed without first being unregistered.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8171055fde7a..66d33e97cbc5 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -339,7 +339,7 @@ static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip) | |||
339 | u16 mask; | 339 | u16 mask; |
340 | 340 | ||
341 | mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask); | 341 | mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask); |
342 | mask |= GENMASK(chip->g1_irq.nirqs, 0); | 342 | mask &= ~GENMASK(chip->g1_irq.nirqs, 0); |
343 | mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); | 343 | mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); |
344 | 344 | ||
345 | free_irq(chip->irq, chip); | 345 | free_irq(chip->irq, chip); |
@@ -395,7 +395,7 @@ static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) | |||
395 | return 0; | 395 | return 0; |
396 | 396 | ||
397 | out_disable: | 397 | out_disable: |
398 | mask |= GENMASK(chip->g1_irq.nirqs, 0); | 398 | mask &= ~GENMASK(chip->g1_irq.nirqs, 0); |
399 | mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); | 399 | mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); |
400 | 400 | ||
401 | out_mapping: | 401 | out_mapping: |
@@ -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; |