Skip to content

Commit

Permalink
net: dsa: mv88e6xxx: Fix releasing for the global2 interrupts
Browse files Browse the repository at this point in the history
It is not possible to use devm_request_threaded_irq() because we have
two stacked interrupt controllers in one device. The lower interrupt
controller cannot be removed until the upper is fully removed. This
happens too late with the devm API, resulting in error messages about
removing a domain while there is still an active interrupt. Swap to
using request_threaded_irq() and manage the release of the interrupt
manually.

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 3dd0ef0 commit 8e757eb
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 10 deletions.
28 changes: 18 additions & 10 deletions drivers/net/dsa/mv88e6xxx/global2.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
{
int irq, virq;

free_irq(chip->device_irq, chip);
irq_dispose_mapping(chip->device_irq);

for (irq = 0; irq < 16; irq++) {
virq = irq_find_mapping(chip->g2_irq.domain, irq);
irq_dispose_mapping(virq);
Expand All @@ -517,8 +520,7 @@ void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)

int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
{
int device_irq;
int err, irq;
int err, irq, virq;

if (!chip->dev->of_node)
return -EINVAL;
Expand All @@ -534,22 +536,28 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
chip->g2_irq.masked = ~0;

device_irq = irq_find_mapping(chip->g1_irq.domain,
GLOBAL_STATUS_IRQ_DEVICE);
if (device_irq < 0) {
err = device_irq;
chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
GLOBAL_STATUS_IRQ_DEVICE);
if (chip->device_irq < 0) {
err = chip->device_irq;
goto out;
}

err = devm_request_threaded_irq(chip->dev, device_irq, NULL,
mv88e6xxx_g2_irq_thread_fn,
IRQF_ONESHOT, "mv88e6xxx-g1", chip);
err = request_threaded_irq(chip->device_irq, NULL,
mv88e6xxx_g2_irq_thread_fn,
IRQF_ONESHOT, "mv88e6xxx-g1", chip);
if (err)
goto out;

return 0;

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

irq_domain_remove(chip->g2_irq.domain);

return err;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ struct mv88e6xxx_chip {
struct mv88e6xxx_irq g1_irq;
struct mv88e6xxx_irq g2_irq;
int irq;
int device_irq;
};

struct mv88e6xxx_bus_ops {
Expand Down

0 comments on commit 8e757eb

Please sign in to comment.