--- /dev/null
+From ddf4bd3f738485c84edb98ff96a5759904498e70 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Thu, 20 Mar 2025 22:11:22 +0000
+Subject: net: phylink: add functions to block/unblock rx clock stop
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+commit ddf4bd3f738485c84edb98ff96a5759904498e70 upstream.
+
+Some MACs require the PHY receive clock to be running to complete setup
+actions. This may fail if the PHY has negotiated EEE, the MAC supports
+receive clock stop, and the link has entered LPI state. Provide a pair
+of APIs that MAC drivers can use to temporarily block the PHY disabling
+the receive clock.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1tvO6k-008Vjt-MZ@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/phy/phylink.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/phylink.h | 3 ++
+ 2 files changed, 62 insertions(+)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -90,6 +90,7 @@ struct phylink {
+ bool mac_enable_tx_lpi;
+ bool mac_tx_clk_stop;
+ u32 mac_tx_lpi_timer;
++ u8 mac_rx_clk_stop_blocked;
+
+ struct sfp_bus *sfp_bus;
+ bool sfp_may_have_phy;
+@@ -2622,6 +2623,64 @@ void phylink_stop(struct phylink *pl)
+ EXPORT_SYMBOL_GPL(phylink_stop);
+
+ /**
++ * phylink_rx_clk_stop_block() - block PHY ability to stop receive clock in LPI
++ * @pl: a pointer to a &struct phylink returned from phylink_create()
++ *
++ * Disable the PHY's ability to stop the receive clock while the receive path
++ * is in EEE LPI state, until the number of calls to phylink_rx_clk_stop_block()
++ * are balanced by calls to phylink_rx_clk_stop_unblock().
++ */
++void phylink_rx_clk_stop_block(struct phylink *pl)
++{
++ ASSERT_RTNL();
++
++ if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
++ phylink_warn(pl, "%s called too many times - ignoring\n",
++ __func__);
++ dump_stack();
++ return;
++ }
++
++ /* Disable PHY receive clock stop if this is the first time this
++ * function has been called and clock-stop was previously enabled.
++ */
++ if (pl->mac_rx_clk_stop_blocked++ == 0 &&
++ pl->mac_supports_eee_ops && pl->phydev &&
++ pl->config->eee_rx_clk_stop_enable)
++ phy_eee_rx_clock_stop(pl->phydev, false);
++}
++EXPORT_SYMBOL_GPL(phylink_rx_clk_stop_block);
++
++/**
++ * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
++ * @pl: a pointer to a &struct phylink returned from phylink_create()
++ *
++ * All calls to phylink_rx_clk_stop_block() must be balanced with a
++ * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
++ * ability to stop the receive clock when the receive path is in EEE LPI mode.
++ */
++void phylink_rx_clk_stop_unblock(struct phylink *pl)
++{
++ ASSERT_RTNL();
++
++ if (pl->mac_rx_clk_stop_blocked == 0) {
++ phylink_warn(pl, "%s called too many times - ignoring\n",
++ __func__);
++ dump_stack();
++ return;
++ }
++
++ /* Re-enable PHY receive clock stop if the number of unblocks matches
++ * the number of calls to the block function above.
++ */
++ if (--pl->mac_rx_clk_stop_blocked == 0 &&
++ pl->mac_supports_eee_ops && pl->phydev &&
++ pl->config->eee_rx_clk_stop_enable)
++ phy_eee_rx_clock_stop(pl->phydev, true);
++}
++EXPORT_SYMBOL_GPL(phylink_rx_clk_stop_unblock);
++
++/**
+ * phylink_suspend() - handle a network device suspend event
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @mac_wol: true if the MAC needs to receive packets for Wake-on-Lan
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -678,6 +678,9 @@ int phylink_pcs_pre_init(struct phylink
+ void phylink_start(struct phylink *);
+ void phylink_stop(struct phylink *);
+
++void phylink_rx_clk_stop_block(struct phylink *);
++void phylink_rx_clk_stop_unblock(struct phylink *);
++
+ void phylink_suspend(struct phylink *pl, bool mac_wol);
+ void phylink_prepare_resume(struct phylink *pl);
+ void phylink_resume(struct phylink *pl);
--- /dev/null
+From 367f1854d442b33c4a0305b068ae40d67ccd7d6a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Thu, 20 Mar 2025 22:11:07 +0000
+Subject: net: phylink: add phylink_prepare_resume()
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+commit 367f1854d442b33c4a0305b068ae40d67ccd7d6a upstream.
+
+When the system is suspended, the PHY may be placed in low-power mode
+by setting the BMCR 0.11 Power down bit. IEEE 802.3 states that the
+behaviour of the PHY in this state is implementation specific, and
+the PHY is not required to meet the RX_CLK and TX_CLK requirements.
+Essentially, this means that a PHY may stop the clocks that it is
+generating while in power down state.
+
+However, MACs exist which require the clocks from the PHY to be running
+in order to properly resume. phylink_prepare_resume() provides them
+with a way to clear the Power down bit early.
+
+Note, however, that IEEE 802.3 gives PHYs up to 500ms grace before the
+transmit and receive clocks meet the requirements after clearing the
+power down bit.
+
+Add a resume preparation function, which will ensure that the receive
+clock from the PHY is appropriately configured while resuming.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1tvO6V-008Vjb-AP@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/phy/phylink.c | 25 +++++++++++++++++++++++++
+ include/linux/phylink.h | 1 +
+ 2 files changed, 26 insertions(+)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -2668,6 +2668,31 @@ void phylink_suspend(struct phylink *pl,
+ EXPORT_SYMBOL_GPL(phylink_suspend);
+
+ /**
++ * phylink_prepare_resume() - prepare to resume a network device
++ * @pl: a pointer to a &struct phylink returned from phylink_create()
++ *
++ * Optional, but if called must be called prior to phylink_resume().
++ *
++ * Prepare to resume a network device, preparing the PHY as necessary.
++ */
++void phylink_prepare_resume(struct phylink *pl)
++{
++ struct phy_device *phydev = pl->phydev;
++
++ ASSERT_RTNL();
++
++ /* IEEE 802.3 22.2.4.1.5 allows PHYs to stop their receive clock
++ * when PDOWN is set. However, some MACs require RXC to be running
++ * in order to resume. If the MAC requires RXC, and we have a PHY,
++ * then resume the PHY. Note that 802.3 allows PHYs 500ms before
++ * the clock meets requirements. We do not implement this delay.
++ */
++ if (pl->config->mac_requires_rxc && phydev && phydev->suspended)
++ phy_resume(phydev);
++}
++EXPORT_SYMBOL_GPL(phylink_prepare_resume);
++
++/**
+ * phylink_resume() - handle a network device resume event
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -679,6 +679,7 @@ void phylink_start(struct phylink *);
+ void phylink_stop(struct phylink *);
+
+ void phylink_suspend(struct phylink *pl, bool mac_wol);
++void phylink_prepare_resume(struct phylink *pl);
+ void phylink_resume(struct phylink *pl);
+
+ void phylink_ethtool_get_wol(struct phylink *, struct ethtool_wolinfo *);
--- /dev/null
+From ef43e5132895ad59b45e38855d32e966bb7434d9 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Thu, 20 Mar 2025 22:11:12 +0000
+Subject: net: stmmac: address non-LPI resume failures properly
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+commit ef43e5132895ad59b45e38855d32e966bb7434d9 upstream.
+
+The Synopsys Designware GMAC core databook requires all clocks to be
+active in order to complete software reset, which we perform during
+resume.
+
+However, IEEE 802.3 allows a PHY to stop its clocks when placed in
+low-power mode, which happens when the system is suspended and WoL
+is not enabled.
+
+As an attempt to work around this, commit 36d18b5664ef ("net: stmmac:
+start phylink instance before stmmac_hw_setup()") started phylink
+early, but this has the side effect that the mac_link_up() method may
+be called before or during the initialisation of GMAC hardware.
+
+We also have the socfpga glue driver directly calling phy_resume()
+also as an attempt to work around this.
+
+In a previous commit, phylink_prepare_resume() has been introduced
+to give MAC drivers a way to ensure that the PHY is resumed prior to
+their initialisation of their MAC hardware. This commit adds the call,
+and moves the phylink_resume() call back to where it should be before
+the aforementioned commit.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1tvO6a-008Vjh-FG@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -7907,12 +7907,12 @@ int stmmac_resume(struct device *dev)
+ }
+
+ rtnl_lock();
+- phylink_resume(priv->phylink);
+- if (device_may_wakeup(priv->device) && !priv->plat->pmt)
+- phylink_speed_up(priv->phylink);
+- rtnl_unlock();
+
+- rtnl_lock();
++ /* Prepare the PHY to resume, ensuring that its clocks which are
++ * necessary for the MAC DMA reset to complete are running
++ */
++ phylink_prepare_resume(priv->phylink);
++
+ mutex_lock(&priv->lock);
+
+ stmmac_reset_queues_param(priv);
+@@ -7930,6 +7930,15 @@ int stmmac_resume(struct device *dev)
+ stmmac_enable_all_dma_irq(priv);
+
+ mutex_unlock(&priv->lock);
++
++ /* phylink_resume() must be called after the hardware has been
++ * initialised because it may bring the link up immediately in a
++ * workqueue thread, which will race with initialisation.
++ */
++ phylink_resume(priv->phylink);
++ if (device_may_wakeup(priv->device) && !priv->plat->pmt)
++ phylink_speed_up(priv->phylink);
++
+ rtnl_unlock();
+
+ netif_device_attach(ndev);
--- /dev/null
+From dd557266cf5fb01a8cd85482dd258c1e172301d1 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Thu, 20 Mar 2025 22:11:27 +0000
+Subject: net: stmmac: block PHY RXC clock-stop
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+commit dd557266cf5fb01a8cd85482dd258c1e172301d1 upstream.
+
+The DesignWare core requires the receive clock to be running during
+certain operations. Ensure that we block PHY RXC clock-stop during
+these operations.
+
+This is a best-efforts change - not everywhere can be covered by this
+because of net's core locking, which means we can't access the MDIO
+bus to configure the PHY to disable RXC clock-stop in certain areas.
+These are marked with FIXME comments.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1tvO6p-008Vjz-Qy@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 27 ++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -3448,9 +3448,18 @@ static int stmmac_hw_setup(struct net_de
+ if (priv->hw->phylink_pcs)
+ phylink_pcs_pre_init(priv->phylink, priv->hw->phylink_pcs);
+
++ /* Note that clk_rx_i must be running for reset to complete. This
++ * clock may also be required when setting the MAC address.
++ *
++ * Block the receive clock stop for LPI mode at the PHY in case
++ * the link is established with EEE mode active.
++ */
++ phylink_rx_clk_stop_block(priv->phylink);
++
+ /* DMA initialization and SW reset */
+ ret = stmmac_init_dma_engine(priv);
+ if (ret < 0) {
++ phylink_rx_clk_stop_unblock(priv->phylink);
+ netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
+ __func__);
+ return ret;
+@@ -3458,6 +3467,7 @@ static int stmmac_hw_setup(struct net_de
+
+ /* Copy the MAC addr into the HW */
+ stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0);
++ phylink_rx_clk_stop_unblock(priv->phylink);
+
+ /* PS and related bits will be programmed according to the speed */
+ if (priv->hw->pcs) {
+@@ -3568,7 +3578,9 @@ static int stmmac_hw_setup(struct net_de
+ /* Start the ball rolling... */
+ stmmac_start_all_dma(priv);
+
++ phylink_rx_clk_stop_block(priv->phylink);
+ stmmac_set_hw_vlan_mode(priv, priv->hw);
++ phylink_rx_clk_stop_unblock(priv->phylink);
+
+ return 0;
+ }
+@@ -5853,6 +5865,9 @@ static void stmmac_tx_timeout(struct net
+ * whenever multicast addresses must be enabled/disabled.
+ * Return value:
+ * void.
++ *
++ * FIXME: This may need RXC to be running, but it may be called with BH
++ * disabled, which means we can't call phylink_rx_clk_stop*().
+ */
+ static void stmmac_set_rx_mode(struct net_device *dev)
+ {
+@@ -5985,7 +6000,9 @@ static int stmmac_set_features(struct ne
+ else
+ priv->hw->hw_vlan_en = false;
+
++ phylink_rx_clk_stop_block(priv->phylink);
+ stmmac_set_hw_vlan_mode(priv, priv->hw);
++ phylink_rx_clk_stop_unblock(priv->phylink);
+
+ return 0;
+ }
+@@ -6269,7 +6286,9 @@ static int stmmac_set_mac_address(struct
+ if (ret)
+ goto set_mac_error;
+
++ phylink_rx_clk_stop_block(priv->phylink);
+ stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0);
++ phylink_rx_clk_stop_unblock(priv->phylink);
+
+ set_mac_error:
+ pm_runtime_put(priv->device);
+@@ -6625,6 +6644,9 @@ static int stmmac_vlan_update(struct stm
+ return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
+ }
+
++/* FIXME: This may need RXC to be running, but it may be called with BH
++ * disabled, which means we can't call phylink_rx_clk_stop*().
++ */
+ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
+ {
+ struct stmmac_priv *priv = netdev_priv(ndev);
+@@ -6656,6 +6678,9 @@ err_pm_put:
+ return ret;
+ }
+
++/* FIXME: This may need RXC to be running, but it may be called with BH
++ * disabled, which means we can't call phylink_rx_clk_stop*().
++ */
+ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
+ {
+ struct stmmac_priv *priv = netdev_priv(ndev);
+@@ -7922,9 +7947,11 @@ int stmmac_resume(struct device *dev)
+
+ stmmac_hw_setup(ndev, false);
+ stmmac_init_coalesce(priv);
++ phylink_rx_clk_stop_block(priv->phylink);
+ stmmac_set_rx_mode(ndev);
+
+ stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
++ phylink_rx_clk_stop_unblock(priv->phylink);
+
+ stmmac_enable_all_queues(priv);
+ stmmac_enable_all_dma_irq(priv);
--- /dev/null
+From f732549eb303d7e382f5101b82bb6852ad4ad642 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Tue, 4 Mar 2025 11:21:27 +0000
+Subject: net: stmmac: simplify phylink_suspend() and phylink_resume() calls
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+commit f732549eb303d7e382f5101b82bb6852ad4ad642 upstream.
+
+Currently, the calls to phylink's suspend and resume functions are
+inside overly complex tests, and boil down to:
+
+ if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+ call phylink
+ } else {
+ call phylink and
+ if (device_may_wakeup(priv->device))
+ do something else
+ }
+
+This results in phylink always being called, possibly with differing
+arguments for phylink_suspend().
+
+Simplify this code, noting that each site is slightly different due to
+the order in which phylink is called and the "something else".
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/E1tpQL1-005St4-Hn@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 22 ++++++++--------------
+ 1 file changed, 8 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -7813,13 +7813,11 @@ int stmmac_suspend(struct device *dev)
+ mutex_unlock(&priv->lock);
+
+ rtnl_lock();
+- if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+- phylink_suspend(priv->phylink, true);
+- } else {
+- if (device_may_wakeup(priv->device))
+- phylink_speed_down(priv->phylink, false);
+- phylink_suspend(priv->phylink, false);
+- }
++ if (device_may_wakeup(priv->device) && !priv->plat->pmt)
++ phylink_speed_down(priv->phylink, false);
++
++ phylink_suspend(priv->phylink,
++ device_may_wakeup(priv->device) && priv->plat->pmt);
+ rtnl_unlock();
+
+ if (stmmac_fpe_supported(priv))
+@@ -7909,13 +7907,9 @@ int stmmac_resume(struct device *dev)
+ }
+
+ rtnl_lock();
+- if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+- phylink_resume(priv->phylink);
+- } else {
+- phylink_resume(priv->phylink);
+- if (device_may_wakeup(priv->device))
+- phylink_speed_up(priv->phylink);
+- }
++ phylink_resume(priv->phylink);
++ if (device_may_wakeup(priv->device) && !priv->plat->pmt)
++ phylink_speed_up(priv->phylink);
+ rtnl_unlock();
+
+ rtnl_lock();
--- /dev/null
+From 366aeeba79088003307f0f12bb3575fb083cc72a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Thu, 20 Mar 2025 22:11:17 +0000
+Subject: net: stmmac: socfpga: remove phy_resume() call
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+commit 366aeeba79088003307f0f12bb3575fb083cc72a upstream.
+
+As the previous commit addressed DWGMAC resuming with a PHY in
+suspended state, there is now no need for socfpga to work around
+this. Remove this code.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1tvO6f-008Vjn-J1@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 18 ------------------
+ 1 file changed, 18 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+@@ -523,24 +523,6 @@ static int socfpga_dwmac_resume(struct d
+
+ dwmac_priv->ops->set_phy_mode(priv->plat->bsp_priv);
+
+- /* Before the enet controller is suspended, the phy is suspended.
+- * This causes the phy clock to be gated. The enet controller is
+- * resumed before the phy, so the clock is still gated "off" when
+- * the enet controller is resumed. This code makes sure the phy
+- * is "resumed" before reinitializing the enet controller since
+- * the enet controller depends on an active phy clock to complete
+- * a DMA reset. A DMA reset will "time out" if executed
+- * with no phy clock input on the Synopsys enet controller.
+- * Verified through Synopsys Case #8000711656.
+- *
+- * Note that the phy clock is also gated when the phy is isolated.
+- * Phy "suspend" and "isolate" controls are located in phy basic
+- * control register 0, and can be modified by the phy driver
+- * framework.
+- */
+- if (ndev->phydev)
+- phy_resume(ndev->phydev);
+-
+ return stmmac_resume(dev);
+ }
+ #endif /* CONFIG_PM_SLEEP */
--- /dev/null
+From eaaff9b6702e99be5d79135f2afa9fc48a0d59e0 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Thu, 20 Feb 2025 14:07:01 +0100
+Subject: netfilter: fib: avoid lookup if socket is available
+
+From: Florian Westphal <fw@strlen.de>
+
+commit eaaff9b6702e99be5d79135f2afa9fc48a0d59e0 upstream.
+
+In case the fib match is used from the input hook we can avoid the fib
+lookup if early demux assigned a socket for us: check that the input
+interface matches sk-cached one.
+
+Rework the existing 'lo bypass' logic to first check sk, then
+for loopback interface type to elide the fib lookup.
+
+This speeds up fib matching a little, before:
+93.08 GBit/s (no rules at all)
+75.1 GBit/s ("fib saddr . iif oif missing drop" in prerouting)
+75.62 GBit/s ("fib saddr . iif oif missing drop" in input)
+
+After:
+92.48 GBit/s (no rules at all)
+75.62 GBit/s (fib rule in prerouting)
+90.37 GBit/s (fib rule in input).
+
+Numbers for the 'no rules' and 'prerouting' are expected to
+closely match in-between runs, the 3rd/input test case exercises the
+the 'avoid lookup if cached ifindex in sk matches' case.
+
+Test used iperf3 via veth interface, lo can't be used due to existing
+loopback test.
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/netfilter/nft_fib.h | 21 +++++++++++++++++++++
+ net/ipv4/netfilter/nft_fib_ipv4.c | 11 +++++------
+ net/ipv6/netfilter/nft_fib_ipv6.c | 19 ++++++++++---------
+ 3 files changed, 36 insertions(+), 15 deletions(-)
+
+--- a/include/net/netfilter/nft_fib.h
++++ b/include/net/netfilter/nft_fib.h
+@@ -18,6 +18,27 @@ nft_fib_is_loopback(const struct sk_buff
+ return skb->pkt_type == PACKET_LOOPBACK || in->flags & IFF_LOOPBACK;
+ }
+
++static inline bool nft_fib_can_skip(const struct nft_pktinfo *pkt)
++{
++ const struct net_device *indev = nft_in(pkt);
++ const struct sock *sk;
++
++ switch (nft_hook(pkt)) {
++ case NF_INET_PRE_ROUTING:
++ case NF_INET_INGRESS:
++ case NF_INET_LOCAL_IN:
++ break;
++ default:
++ return false;
++ }
++
++ sk = pkt->skb->sk;
++ if (sk && sk_fullsock(sk))
++ return sk->sk_rx_dst_ifindex == indev->ifindex;
++
++ return nft_fib_is_loopback(pkt->skb, indev);
++}
++
+ int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr, bool reset);
+ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+--- a/net/ipv4/netfilter/nft_fib_ipv4.c
++++ b/net/ipv4/netfilter/nft_fib_ipv4.c
+@@ -71,6 +71,11 @@ void nft_fib4_eval(const struct nft_expr
+ const struct net_device *oif;
+ const struct net_device *found;
+
++ if (nft_fib_can_skip(pkt)) {
++ nft_fib_store_result(dest, priv, nft_in(pkt));
++ return;
++ }
++
+ /*
+ * Do not set flowi4_oif, it restricts results (for example, asking
+ * for oif 3 will get RTN_UNICAST result even if the daddr exits
+@@ -85,12 +90,6 @@ void nft_fib4_eval(const struct nft_expr
+ else
+ oif = NULL;
+
+- if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
+- nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
+- nft_fib_store_result(dest, priv, nft_in(pkt));
+- return;
+- }
+-
+ iph = skb_header_pointer(pkt->skb, noff, sizeof(_iph), &_iph);
+ if (!iph) {
+ regs->verdict.code = NFT_BREAK;
+--- a/net/ipv6/netfilter/nft_fib_ipv6.c
++++ b/net/ipv6/netfilter/nft_fib_ipv6.c
+@@ -170,6 +170,11 @@ void nft_fib6_eval(const struct nft_expr
+ struct rt6_info *rt;
+ int lookup_flags;
+
++ if (nft_fib_can_skip(pkt)) {
++ nft_fib_store_result(dest, priv, nft_in(pkt));
++ return;
++ }
++
+ if (priv->flags & NFTA_FIB_F_IIF)
+ oif = nft_in(pkt);
+ else if (priv->flags & NFTA_FIB_F_OIF)
+@@ -181,17 +186,13 @@ void nft_fib6_eval(const struct nft_expr
+ return;
+ }
+
+- lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
+-
+- if (nft_hook(pkt) == NF_INET_PRE_ROUTING ||
+- nft_hook(pkt) == NF_INET_INGRESS) {
+- if (nft_fib_is_loopback(pkt->skb, nft_in(pkt)) ||
+- nft_fib_v6_skip_icmpv6(pkt->skb, pkt->tprot, iph)) {
+- nft_fib_store_result(dest, priv, nft_in(pkt));
+- return;
+- }
++ if (nft_fib_v6_skip_icmpv6(pkt->skb, pkt->tprot, iph)) {
++ nft_fib_store_result(dest, priv, nft_in(pkt));
++ return;
+ }
+
++ lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
++
+ *dest = 0;
+ rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb,
+ lookup_flags);
loongarch-make-regs_irqs_disabled-more-clear.patch
loongarch-make-do_xyz-exception-handlers-more-robust.patch
sched-eevdf-fix-se-slice-being-set-to-u64_max-and-re.patch
+net-stmmac-simplify-phylink_suspend-and-phylink_resume-calls.patch
+net-phylink-add-phylink_prepare_resume.patch
+net-stmmac-address-non-lpi-resume-failures-properly.patch
+net-stmmac-socfpga-remove-phy_resume-call.patch
+net-phylink-add-functions-to-block-unblock-rx-clock-stop.patch
+net-stmmac-block-phy-rxc-clock-stop.patch
+netfilter-fib-avoid-lookup-if-socket-is-available.patch