mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-17 03:07:00 +07:00
net: systemport: Fix wake-up interrupt race during resume
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:bb9051a2b2
("net: systemport: Add support for WAKE_FILTER") Fixes:83e82f4c70
("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>
This commit is contained in:
parent
11bde89981
commit
45ec318578
@ -1069,9 +1069,6 @@ static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* Stop monitoring MPD interrupt */
|
||||
intrl2_0_mask_set(priv, INTRL2_0_MPD | INTRL2_0_BRCM_MATCH_TAG);
|
||||
|
||||
/* Disable RXCHK, active filters and Broadcom tag matching */
|
||||
reg = rxchk_readl(priv, RXCHK_CONTROL);
|
||||
reg &= ~(RXCHK_BRCM_TAG_MATCH_MASK <<
|
||||
@ -1081,6 +1078,17 @@ static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
|
||||
/* Clear the MagicPacket detection logic */
|
||||
mpd_enable_set(priv, false);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@ -1105,7 +1113,6 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
|
||||
struct bcm_sysport_priv *priv = netdev_priv(dev);
|
||||
struct bcm_sysport_tx_ring *txr;
|
||||
unsigned int ring, ring_bit;
|
||||
u32 reg;
|
||||
|
||||
priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) &
|
||||
~intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
|
||||
@ -1131,16 +1138,6 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
|
||||
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 (MPD) interrupt!\n");
|
||||
|
||||
if (priv->irq0_stat & 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);
|
||||
}
|
||||
|
||||
if (!priv->is_lite)
|
||||
goto out;
|
||||
|
||||
@ -2641,9 +2638,6 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
|
||||
/* 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 | INTRL2_0_BRCM_MATCH_TAG);
|
||||
|
||||
netif_dbg(priv, wol, ndev, "entered WOL mode\n");
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user