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; |
