]> git.itanic.dy.fi Git - linux-stable/commitdiff
net: phy: micrel: fix shared interrupt on LAN8814
authorMichael Walle <michael@walle.cc>
Tue, 20 Sep 2022 14:16:19 +0000 (16:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Sep 2022 09:32:20 +0000 (11:32 +0200)
[ Upstream commit 2002fbac743b6e2391b4ed50ad9eb626768dd78a ]

Since commit ece19502834d ("net: phy: micrel: 1588 support for LAN8814
phy") the handler always returns IRQ_HANDLED, except in an error case.
Before that commit, the interrupt status register was checked and if
it was empty, IRQ_NONE was returned. Restore that behavior to play nice
with the interrupt line being shared with others.

Fixes: ece19502834d ("net: phy: micrel: 1588 support for LAN8814 phy")
Signed-off-by: Michael Walle <michael@walle.cc>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Reviewed-by: Divya Koppera <Divya.Koppera@microchip.com>
Link: https://lore.kernel.org/r/20220920141619.808117-1-michael@walle.cc
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/phy/micrel.c

index 34483a4bd688a06ee0840c09443c3385172c24de..e8e1101911b2fb8d8265aabb9b83a5484f1d91cf 100644 (file)
@@ -2662,16 +2662,19 @@ static int lan8804_config_init(struct phy_device *phydev)
 static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev)
 {
        int irq_status, tsu_irq_status;
 static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev)
 {
        int irq_status, tsu_irq_status;
+       int ret = IRQ_NONE;
 
        irq_status = phy_read(phydev, LAN8814_INTS);
 
        irq_status = phy_read(phydev, LAN8814_INTS);
-       if (irq_status > 0 && (irq_status & LAN8814_INT_LINK))
-               phy_trigger_machine(phydev);
-
        if (irq_status < 0) {
                phy_error(phydev);
                return IRQ_NONE;
        }
 
        if (irq_status < 0) {
                phy_error(phydev);
                return IRQ_NONE;
        }
 
+       if (irq_status & LAN8814_INT_LINK) {
+               phy_trigger_machine(phydev);
+               ret = IRQ_HANDLED;
+       }
+
        while (1) {
                tsu_irq_status = lanphy_read_page_reg(phydev, 4,
                                                      LAN8814_INTR_STS_REG);
        while (1) {
                tsu_irq_status = lanphy_read_page_reg(phydev, 4,
                                                      LAN8814_INTR_STS_REG);
@@ -2680,12 +2683,15 @@ static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev)
                    (tsu_irq_status & (LAN8814_INTR_STS_REG_1588_TSU0_ |
                                       LAN8814_INTR_STS_REG_1588_TSU1_ |
                                       LAN8814_INTR_STS_REG_1588_TSU2_ |
                    (tsu_irq_status & (LAN8814_INTR_STS_REG_1588_TSU0_ |
                                       LAN8814_INTR_STS_REG_1588_TSU1_ |
                                       LAN8814_INTR_STS_REG_1588_TSU2_ |
-                                      LAN8814_INTR_STS_REG_1588_TSU3_)))
+                                      LAN8814_INTR_STS_REG_1588_TSU3_))) {
                        lan8814_handle_ptp_interrupt(phydev);
                        lan8814_handle_ptp_interrupt(phydev);
-               else
+                       ret = IRQ_HANDLED;
+               } else {
                        break;
                        break;
+               }
        }
        }
-       return IRQ_HANDLED;
+
+       return ret;
 }
 
 static int lan8814_ack_interrupt(struct phy_device *phydev)
 }
 
 static int lan8814_ack_interrupt(struct phy_device *phydev)