Skip to content

Commit

Permalink
net: dsa: mv88e6xxx: Fix cleanup on error for g1 interrupt setup
Browse files Browse the repository at this point in the history
On error, remask the interrupts, release all maps, and remove the
domain. This cannot be done using the mv88e6xxx_g1_irq_free() because
some of these actions are not idempotent.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Andrew Lunn authored and David S. Miller committed Nov 21, 2016
1 parent 3460a57 commit 3dd0ef0
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions drivers/net/dsa/mv88e6xxx/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)

static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
{
int err, irq;
u16 reg;
int err, irq, virq;
u16 reg, mask;

chip->g1_irq.nirqs = chip->info->g1_irqs;
chip->g1_irq.domain = irq_domain_add_simple(
Expand All @@ -447,32 +447,41 @@ static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
chip->g1_irq.masked = ~0;

err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg);
err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
if (err)
goto out;
goto out_mapping;

reg &= ~GENMASK(chip->g1_irq.nirqs, 0);
mask &= ~GENMASK(chip->g1_irq.nirqs, 0);

err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
if (err)
goto out;
goto out_disable;

/* Reading the interrupt status clears (most of) them */
err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
if (err)
goto out;
goto out_disable;

err = request_threaded_irq(chip->irq, NULL,
mv88e6xxx_g1_irq_thread_fn,
IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
dev_name(chip->dev), chip);
if (err)
goto out;
goto out_disable;

return 0;

out:
mv88e6xxx_g1_irq_free(chip);
out_disable:
mask |= GENMASK(chip->g1_irq.nirqs, 0);
mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);

out_mapping:
for (irq = 0; irq < 16; irq++) {
virq = irq_find_mapping(chip->g1_irq.domain, irq);
irq_dispose_mapping(virq);
}

irq_domain_remove(chip->g1_irq.domain);

return err;
}
Expand Down

0 comments on commit 3dd0ef0

Please sign in to comment.