lkml.org 
[lkml]   [2018]   [Oct]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.18 017/135] net: systemport: Fix wake-up interrupt race during resume
    Date
    4.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Florian Fainelli <f.fainelli@gmail.com>

    [ Upstream commit 45ec318578c0c22a11f5b9927d064418e1ab1905 ]

    The AON_PM_L2 is normally used to trigger and identify the source of a
    wake-up event. Since the RX_SYS clock is no longer turned off, we also
    have an interrupt being sent to the SYSTEMPORT INTRL_2_0 controller, and
    that interrupt remains active up until the magic packet detector is
    disabled which happens much later during the driver resumption.

    The race happens if we have a CPU that is entering the SYSTEMPORT
    INTRL2_0 handler during resume, and another CPU has managed to clear the
    wake-up interrupt during bcm_sysport_resume_from_wol(). In that case, we
    have the first CPU stuck in the interrupt handler with an interrupt
    cause that has been cleared under its feet, and so we keep returning
    IRQ_NONE and we never make any progress.

    This was not a problem before because we would always turn off the
    RX_SYS clock during WoL, so the SYSTEMPORT INTRL2_0 would also be turned
    off as well, thus not latching the interrupt.

    The fix is to make sure we do not enable either the MPD or
    BRCM_TAG_MATCH interrupts since those are redundant with what the
    AON_PM_L2 interrupt controller already processes and they would cause
    such a race to occur.

    Fixes: bb9051a2b230 ("net: systemport: Add support for WAKE_FILTER")
    Fixes: 83e82f4c706b ("net: systemport: add Wake-on-LAN support")
    Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/net/ethernet/broadcom/bcmsysport.c | 22 +++++++++++-----------
    1 file changed, 11 insertions(+), 11 deletions(-)

    --- a/drivers/net/ethernet/broadcom/bcmsysport.c
    +++ b/drivers/net/ethernet/broadcom/bcmsysport.c
    @@ -1045,14 +1045,22 @@ static void bcm_sysport_resume_from_wol(
    {
    u32 reg;

    - /* Stop monitoring MPD interrupt */
    - intrl2_0_mask_set(priv, INTRL2_0_MPD);
    -
    /* Clear the MagicPacket detection logic */
    reg = umac_readl(priv, UMAC_MPD_CTRL);
    reg &= ~MPD_EN;
    umac_writel(priv, reg, UMAC_MPD_CTRL);

    + reg = intrl2_0_readl(priv, INTRL2_CPU_STATUS);
    + if (reg & INTRL2_0_MPD)
    + netdev_info(priv->netdev, "Wake-on-LAN (MPD) interrupt!\n");
    +
    + if (reg & INTRL2_0_BRCM_MATCH_TAG) {
    + reg = rxchk_readl(priv, RXCHK_BRCM_TAG_MATCH_STATUS) &
    + RXCHK_BRCM_TAG_MATCH_MASK;
    + netdev_info(priv->netdev,
    + "Wake-on-LAN (filters 0x%02x) interrupt!\n", reg);
    + }
    +
    netif_dbg(priv, wol, priv->netdev, "resumed from WOL\n");
    }

    @@ -1102,11 +1110,6 @@ static irqreturn_t bcm_sysport_rx_isr(in
    if (priv->irq0_stat & INTRL2_0_TX_RING_FULL)
    bcm_sysport_tx_reclaim_all(priv);

    - if (priv->irq0_stat & INTRL2_0_MPD) {
    - netdev_info(priv->netdev, "Wake-on-LAN interrupt!\n");
    - bcm_sysport_resume_from_wol(priv);
    - }
    -
    if (!priv->is_lite)
    goto out;

    @@ -2459,9 +2462,6 @@ static int bcm_sysport_suspend_to_wol(st
    /* UniMAC receive needs to be turned on */
    umac_enable_set(priv, CMD_RX_EN, 1);

    - /* Enable the interrupt wake-up source */
    - intrl2_0_mask_clear(priv, INTRL2_0_MPD);
    -
    netif_dbg(priv, wol, ndev, "entered WOL mode\n");

    return 0;

    \
     
     \ /
      Last update: 2018-10-16 19:47    [W:4.357 / U:0.184 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site