| From 0c30e56aca8110ba0017063f1d22358d74621a79 Mon Sep 17 00:00:00 2001 |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| Date: Fri, 28 Feb 2020 19:39:41 +0000 |
| Subject: [PATCH] net: dsa: mv88e6xxx: fix lockup on warm boot |
| |
| commit 0395823b8d9a4d87bd1bf74359123461c2ae801b upstream. |
| |
| If the switch is not hardware reset on a warm boot, interrupts can be |
| left enabled, and possibly pending. This will cause us to enter an |
| infinite loop trying to service an interrupt we are unable to handle, |
| thereby preventing the kernel from booting. |
| |
| Ensure that the global 2 interrupt sources are disabled before we claim |
| the parent interrupt. |
| |
| Observed on the ZII development revision B and C platforms with |
| reworked serdes support, and using reboot -f to reboot the platform. |
| |
| Fixes: dc30c35be720 ("net: dsa: mv88e6xxx: Implement interrupt support.") |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| Reviewed-by: Andrew Lunn <andrew@lunn.ch> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| [PG: use old mutex lock names - v5.2 doesn't have c9acece064e3.] |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c |
| index 1546171210a1..d70f08cfcaf8 100644 |
| --- a/drivers/net/dsa/mv88e6xxx/global2.c |
| +++ b/drivers/net/dsa/mv88e6xxx/global2.c |
| @@ -1043,6 +1043,13 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) |
| { |
| int err, irq, virq; |
| |
| + chip->g2_irq.masked = ~0; |
| + mutex_lock(&chip->reg_lock); |
| + err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked); |
| + mutex_unlock(&chip->reg_lock); |
| + if (err) |
| + return err; |
| + |
| chip->g2_irq.domain = irq_domain_add_simple( |
| chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip); |
| if (!chip->g2_irq.domain) |
| @@ -1052,7 +1059,6 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) |
| irq_create_mapping(chip->g2_irq.domain, irq); |
| |
| chip->g2_irq.chip = mv88e6xxx_g2_irq_chip; |
| - chip->g2_irq.masked = ~0; |
| |
| chip->device_irq = irq_find_mapping(chip->g1_irq.domain, |
| MV88E6XXX_G1_STS_IRQ_DEVICE); |
| -- |
| 2.7.4 |
| |