aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/mv88e6xxx/global2.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2016-11-20 20:14:18 +0100
committerDavid S. Miller <davem@davemloft.net>2016-11-20 21:16:13 -0500
commit8e757eba074fff8460dc91717695e009b5f93f76 (patch)
treed7c0bf58ed1678e5f34dd02f26f02ff82364f77d /drivers/net/dsa/mv88e6xxx/global2.c
parentnet: dsa: mv88e6xxx: Fix cleanup on error for g1 interrupt setup (diff)
downloadlinux-dev-8e757eba074fff8460dc91717695e009b5f93f76.tar.xz
linux-dev-8e757eba074fff8460dc91717695e009b5f93f76.zip
net: dsa: mv88e6xxx: Fix releasing for the global2 interrupts
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>
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/global2.c')
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 1a0b13521d13..536a27c9735f 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -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);
@@ -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;
@@ -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;
}