Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorJakub Kicinski <kuba@kernel.org>
Thu, 29 Sep 2022 21:30:51 +0000 (14:30 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 29 Sep 2022 21:30:51 +0000 (14:30 -0700)
No conflicts.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
18 files changed:
1  2 
MAINTAINERS
drivers/net/dsa/mt7530.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/phy/phy_device.c
drivers/net/tun.c
drivers/net/usb/usbnet.c
kernel/cgroup/cgroup.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/mac80211/util.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/sched/act_ct.c
net/wireless/util.c

diff --combined MAINTAINERS
index 5d58b55c5ae50b72020f9941c6d53ed748193f79,17abc6483100b2bb973565411610ff0416089677..eb8776f2f06131395ec83ca9c6bec043010f0bcd
@@@ -671,7 -671,8 +671,8 @@@ F: fs/afs
  F:    include/trace/events/afs.h
  
  AGPGART DRIVER
- M:    David Airlie <airlied@linux.ie>
+ M:    David Airlie <airlied@redhat.com>
+ L:    dri-devel@lists.freedesktop.org
  S:    Maintained
  T:    git git://anongit.freedesktop.org/drm/drm
  F:    drivers/char/agp/
@@@ -878,13 -879,6 +879,13 @@@ L:       netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/ethernet/altera/
  
 +ALTERA TSE PCS
 +M:    Maxime Chevallier <maxime.chevallier@bootlin.com>
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    drivers/net/pcs/pcs-altera-tse.c
 +F:    include/linux/pcs-altera-tse.h
 +
  ALTERA UART/JTAG UART SERIAL DRIVERS
  M:    Tobias Klauser <tklauser@distanz.ch>
  L:    linux-serial@vger.kernel.org
@@@ -1017,7 -1011,6 +1018,6 @@@ F:      drivers/spi/spi-amd.
  
  AMD MP2 I2C DRIVER
  M:    Elie Morisse <syniurge@gmail.com>
- M:    Nehal Shah <nehal-bakulchandra.shah@amd.com>
  M:    Shyam Sundar S K <shyam-sundar.s-k@amd.com>
  L:    linux-i2c@vger.kernel.org
  S:    Maintained
@@@ -2401,7 -2394,6 +2401,7 @@@ N:      atme
  ARM/Microchip Sparx5 SoC support
  M:    Lars Povlsen <lars.povlsen@microchip.com>
  M:    Steen Hegelund <Steen.Hegelund@microchip.com>
 +M:    Daniel Machon <daniel.machon@microchip.com>
  M:    UNGLinuxDriver@microchip.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Supported
@@@ -2587,7 -2579,7 +2587,7 @@@ W:      http://www.armlinux.org.uk
  
  ARM/QUALCOMM SUPPORT
  M:    Andy Gross <agross@kernel.org>
- M:    Bjorn Andersson <bjorn.andersson@linaro.org>
+ M:    Bjorn Andersson <andersson@kernel.org>
  R:    Konrad Dybcio <konrad.dybcio@somainline.org>
  L:    linux-arm-msm@vger.kernel.org
  S:    Maintained
@@@ -5253,6 -5245,7 +5253,7 @@@ F:      block/blk-throttle.
  F:    include/linux/blk-cgroup.h
  
  CONTROL GROUP - CPUSET
+ M:    Waiman Long <longman@redhat.com>
  M:    Zefan Li <lizefan.x@bytedance.com>
  L:    cgroups@vger.kernel.org
  S:    Maintained
@@@ -5730,6 -5723,13 +5731,6 @@@ F:     include/linux/tfrc.
  F:    include/uapi/linux/dccp.h
  F:    net/dccp/
  
 -DECnet NETWORK LAYER
 -L:    linux-decnet-user@lists.sourceforge.net
 -S:    Orphan
 -W:    http://linux-decnet.sourceforge.net
 -F:    Documentation/networking/decnet.rst
 -F:    net/decnet/
 -
  DECSTATION PLATFORM SUPPORT
  M:    "Maciej W. Rozycki" <macro@orcam.me.uk>
  L:    linux-mips@vger.kernel.org
@@@ -6754,7 -6754,7 +6755,7 @@@ F:      Documentation/devicetree/bindings/di
  F:    drivers/gpu/drm/panel/panel-widechips-ws2401.c
  
  DRM DRIVERS
- M:    David Airlie <airlied@linux.ie>
+ M:    David Airlie <airlied@gmail.com>
  M:    Daniel Vetter <daniel@ffwll.ch>
  L:    dri-devel@lists.freedesktop.org
  S:    Maintained
@@@ -8944,7 -8944,7 +8945,7 @@@ F:      include/linux/hw_random.
  
  HARDWARE SPINLOCK CORE
  M:    Ohad Ben-Cohen <ohad@wizery.com>
- M:    Bjorn Andersson <bjorn.andersson@linaro.org>
+ M:    Bjorn Andersson <andersson@kernel.org>
  R:    Baolin Wang <baolin.wang7@gmail.com>
  L:    linux-remoteproc@vger.kernel.org
  S:    Maintained
@@@ -14747,13 -14747,6 +14748,13 @@@ F: net/dsa/tag_ocelot.
  F:    net/dsa/tag_ocelot_8021q.c
  F:    tools/testing/selftests/drivers/net/ocelot/*
  
 +OCELOT EXTERNAL SWITCH CONTROL
 +M:    Colin Foster <colin.foster@in-advantage.com>
 +S:    Supported
 +F:    Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml
 +F:    drivers/mfd/ocelot*
 +F:    include/linux/mfd/ocelot.h
 +
  OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
  M:    Frederic Barrat <fbarrat@linux.ibm.com>
  M:    Andrew Donnellan <ajd@linux.ibm.com>
@@@ -16133,7 -16126,7 +16134,7 @@@ F:   drivers/gpio/gpio-sama5d2-piobu.
  F:    drivers/pinctrl/pinctrl-at91*
  
  PIN CONTROLLER - QUALCOMM
- M:    Bjorn Andersson <bjorn.andersson@linaro.org>
+ M:    Bjorn Andersson <andersson@kernel.org>
  L:    linux-arm-msm@vger.kernel.org
  S:    Maintained
  F:    Documentation/devicetree/bindings/pinctrl/qcom,*.txt
@@@ -16826,7 -16819,7 +16827,7 @@@ F:   Documentation/devicetree/bindings/me
  F:    drivers/media/platform/qcom/camss/
  
  QUALCOMM CLOCK DRIVERS
- M:    Bjorn Andersson <bjorn.andersson@linaro.org>
+ M:    Bjorn Andersson <andersson@kernel.org>
  L:    linux-arm-msm@vger.kernel.org
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
@@@ -17316,7 -17309,7 +17317,7 @@@ S:   Supporte
  F:    fs/reiserfs/
  
  REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
- M:    Bjorn Andersson <bjorn.andersson@linaro.org>
+ M:    Bjorn Andersson <andersson@kernel.org>
  M:    Mathieu Poirier <mathieu.poirier@linaro.org>
  L:    linux-remoteproc@vger.kernel.org
  S:    Maintained
@@@ -17329,7 -17322,7 +17330,7 @@@ F:   include/linux/remoteproc.
  F:    include/linux/remoteproc/
  
  REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM
- M:    Bjorn Andersson <bjorn.andersson@linaro.org>
+ M:    Bjorn Andersson <andersson@kernel.org>
  M:    Mathieu Poirier <mathieu.poirier@linaro.org>
  L:    linux-remoteproc@vger.kernel.org
  S:    Maintained
@@@ -19511,11 -19504,6 +19512,11 @@@ L: netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/ethernet/dlink/sundance.c
  
 +SUN HAPPY MEAL ETHERNET DRIVER
 +M:    Sean Anderson <seanga2@gmail.com>
 +S:    Maintained
 +F:    drivers/net/ethernet/sun/sunhme.*
 +
  SUNPLUS ETHERNET DRIVER
  M:    Wells Lu <wellslutw@gmail.com>
  L:    netdev@vger.kernel.org
@@@ -19973,7 -19961,7 +19974,7 @@@ S:   Supporte
  F:    drivers/net/team/
  F:    include/linux/if_team.h
  F:    include/uapi/linux/if_team.h
- F:    tools/testing/selftests/net/team/
+ F:    tools/testing/selftests/drivers/net/team/
  
  TECHNOLOGIC SYSTEMS TS-5500 PLATFORM SUPPORT
  M:    "Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
@@@ -21580,7 -21568,7 +21581,7 @@@ F:   drivers/gpio/gpio-virtio.
  F:    include/uapi/linux/virtio_gpio.h
  
  VIRTIO GPU DRIVER
- M:    David Airlie <airlied@linux.ie>
+ M:    David Airlie <airlied@redhat.com>
  M:    Gerd Hoffmann <kraxel@redhat.com>
  R:    Gurchetan Singh <gurchetansingh@chromium.org>
  R:    Chia-I Wu <olvaffe@gmail.com>
@@@ -21886,11 -21874,9 +21887,11 @@@ F: drivers/input/tablet/wacom_serial4.
  
  WANGXUN ETHERNET DRIVER
  M:    Jiawen Wu <jiawenwu@trustnetic.com>
 +M:    Mengyuan Lou <mengyuanlou@net-swift.com>
 +W:    https://www.net-swift.com
  L:    netdev@vger.kernel.org
  S:    Maintained
 -F:    Documentation/networking/device_drivers/ethernet/wangxun/txgbe.rst
 +F:    Documentation/networking/device_drivers/ethernet/wangxun/*
  F:    drivers/net/ethernet/wangxun/
  
  WATCHDOG DEVICE DRIVERS
diff --combined drivers/net/dsa/mt7530.c
index e87f16a5756b2a659579f6a985b2220046f78192,409d5c3d76ea6fee386466a16578676bc0b6720a..e74c6b4061728e5bbb5d14e5d2c4f903c7c4752e
@@@ -506,14 -506,19 +506,19 @@@ static bool mt7531_dual_sgmii_supported
  static int
  mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
  {
-       struct mt7530_priv *priv = ds->priv;
+       return 0;
+ }
+ static void
+ mt7531_pll_setup(struct mt7530_priv *priv)
+ {
        u32 top_sig;
        u32 hwstrap;
        u32 xtal;
        u32 val;
  
        if (mt7531_dual_sgmii_supported(priv))
-               return 0;
+               return;
  
        val = mt7530_read(priv, MT7531_CREV);
        top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR);
        val |= EN_COREPLL;
        mt7530_write(priv, MT7531_PLLGP_EN, val);
        usleep_range(25, 35);
-       return 0;
  }
  
  static void
@@@ -2326,11 -2329,17 +2329,17 @@@ mt7531_setup(struct dsa_switch *ds
                return -ENODEV;
        }
  
+       /* all MACs must be forced link-down before sw reset */
+       for (i = 0; i < MT7530_NUM_PORTS; i++)
+               mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK);
        /* Reset the switch through internal reset */
        mt7530_write(priv, MT7530_SYS_CTRL,
                     SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
                     SYS_CTRL_REG_RST);
  
+       mt7531_pll_setup(priv);
        if (mt7531_dual_sgmii_supported(priv)) {
                priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII;
  
@@@ -2699,6 -2708,9 +2708,6 @@@ mt7531_mac_config(struct dsa_switch *ds
        case PHY_INTERFACE_MODE_NA:
        case PHY_INTERFACE_MODE_1000BASEX:
        case PHY_INTERFACE_MODE_2500BASEX:
 -              if (phylink_autoneg_inband(mode))
 -                      return -EINVAL;
 -
                return mt7531_sgmii_setup_mode_force(priv, port, interface);
        default:
                return -EINVAL;
@@@ -2774,6 -2786,13 +2783,6 @@@ unsupported
                return;
        }
  
 -      if (phylink_autoneg_inband(mode) &&
 -          state->interface != PHY_INTERFACE_MODE_SGMII) {
 -              dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
 -                      __func__);
 -              return;
 -      }
 -
        mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
        mcr_new = mcr_cur;
        mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
@@@ -2877,8 -2896,6 +2886,6 @@@ mt7531_cpu_port_config(struct dsa_switc
        case 6:
                interface = PHY_INTERFACE_MODE_2500BASEX;
  
-               mt7531_pad_setup(ds, interface);
                priv->p6_interface = interface;
                break;
        default:
@@@ -2912,9 -2929,6 +2919,9 @@@ static void mt753x_phylink_get_caps(str
        config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
                                   MAC_10 | MAC_100 | MAC_1000FD;
  
 +      if ((priv->id == ID_MT7531) && mt753x_is_mac_port(port))
 +              config->mac_capabilities |= MAC_2500FD;
 +
        /* This driver does not make use of the speed, duplex, pause or the
         * advertisement in its mac_config, so it is safe to mark this driver
         * as non-legacy.
@@@ -2980,7 -2994,6 +2987,7 @@@ mt7531_sgmii_pcs_get_state_an(struct mt
  
        status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
        state->link = !!(status & MT7531_SGMII_LINK_STATUS);
 +      state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE);
        if (state->interface == PHY_INTERFACE_MODE_SGMII &&
            (status & MT7531_SGMII_AN_ENABLE)) {
                val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port));
        return 0;
  }
  
 +static void
 +mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port,
 +                                struct phylink_link_state *state)
 +{
 +      unsigned int val;
 +
 +      val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
 +      state->link = !!(val & MT7531_SGMII_LINK_STATUS);
 +      if (!state->link)
 +              return;
 +
 +      state->an_complete = state->link;
 +
 +      if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
 +              state->speed = SPEED_2500;
 +      else
 +              state->speed = SPEED_1000;
 +
 +      state->duplex = DUPLEX_FULL;
 +      state->pause = MLO_PAUSE_NONE;
 +}
 +
  static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
                                 struct phylink_link_state *state)
  {
        struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
        int port = pcs_to_mt753x_pcs(pcs)->port;
  
 -      if (state->interface == PHY_INTERFACE_MODE_SGMII)
 +      if (state->interface == PHY_INTERFACE_MODE_SGMII) {
                mt7531_sgmii_pcs_get_state_an(priv, port, state);
 -      else
 -              state->link = false;
 +              return;
 +      } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) ||
 +                 (state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
 +              mt7531_sgmii_pcs_get_state_inband(priv, port, state);
 +              return;
 +      }
 +
 +      state->link = false;
  }
  
  static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
@@@ -3089,8 -3074,6 +3096,8 @@@ mt753x_setup(struct dsa_switch *ds
                priv->pcs[i].pcs.ops = priv->info->pcs_ops;
                priv->pcs[i].priv = priv;
                priv->pcs[i].port = i;
 +              if (mt753x_is_mac_port(i))
 +                      priv->pcs[i].pcs.poll = 1;
        }
  
        ret = priv->info->sw_setup(ds);
@@@ -3324,6 -3307,8 +3331,6 @@@ mt7530_remove(struct mdio_device *mdiod
  
        dsa_unregister_switch(priv->ds);
        mutex_destroy(&priv->reg_mutex);
 -
 -      dev_set_drvdata(&mdiodev->dev, NULL);
  }
  
  static void mt7530_shutdown(struct mdio_device *mdiodev)
index c39697bed2fa2bcfd370c83e925db5d79e055733,a2897549f9c4d38a752c91a72df70b8bc6b4002a..51c9fd6f68a42f295b7386eeba3b1b188ac1005a
@@@ -38,7 -38,6 +38,7 @@@
  #include <linux/pm_runtime.h>
  #include <linux/ptp_classify.h>
  #include <linux/reset.h>
 +#include <linux/firmware/xlnx-zynqmp.h>
  #include "macb.h"
  
  /* This structure is only used for MACB on SiFive FU540 devices */
@@@ -3978,8 -3977,8 +3978,8 @@@ static int macb_init(struct platform_de
                queue = &bp->queues[q];
                queue->bp = bp;
                spin_lock_init(&queue->tx_ptr_lock);
 -              netif_napi_add(dev, &queue->napi_rx, macb_rx_poll, NAPI_POLL_WEIGHT);
 -              netif_napi_add(dev, &queue->napi_tx, macb_tx_poll, NAPI_POLL_WEIGHT);
 +              netif_napi_add(dev, &queue->napi_rx, macb_rx_poll);
 +              netif_napi_add(dev, &queue->napi_tx, macb_tx_poll);
                if (hw_q) {
                        queue->ISR  = GEM_ISR(hw_q - 1);
                        queue->IER  = GEM_IER(hw_q - 1);
@@@ -4622,25 -4621,6 +4622,25 @@@ static int init_reset_optional(struct p
                                             "failed to init SGMII PHY\n");
        }
  
 +      ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_SET_GEM_CONFIG);
 +      if (!ret) {
 +              u32 pm_info[2];
 +
 +              ret = of_property_read_u32_array(pdev->dev.of_node, "power-domains",
 +                                               pm_info, ARRAY_SIZE(pm_info));
 +              if (ret) {
 +                      dev_err(&pdev->dev, "Failed to read power management information\n");
 +                      goto err_out_phy_exit;
 +              }
 +              ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_FIXED, 0);
 +              if (ret)
 +                      goto err_out_phy_exit;
 +
 +              ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_SGMII_MODE, 1);
 +              if (ret)
 +                      goto err_out_phy_exit;
 +      }
 +
        /* Fully reset controller at hardware level if mapped in device tree */
        ret = device_reset_optional(&pdev->dev);
        if (ret) {
        }
  
        ret = macb_init(pdev);
 +
 +err_out_phy_exit:
        if (ret)
                phy_exit(bp->sgmii_phy);
  
@@@ -5131,6 -5109,7 +5131,7 @@@ static int __maybe_unused macb_suspend(
        if (!(bp->wol & MACB_WOL_ENABLED)) {
                rtnl_lock();
                phylink_stop(bp->phylink);
+               phy_exit(bp->sgmii_phy);
                rtnl_unlock();
                spin_lock_irqsave(&bp->lock, flags);
                macb_reset_hw(bp);
@@@ -5220,6 -5199,9 +5221,9 @@@ static int __maybe_unused macb_resume(s
        macb_set_rx_mode(netdev);
        macb_restore_features(bp);
        rtnl_lock();
+       if (!device_may_wakeup(&bp->dev->dev))
+               phy_init(bp->sgmii_phy);
        phylink_start(bp->phylink);
        rtnl_unlock();
  
index a5a0c9706b5a2411d6e5b4098e6c13933e2ba127,dd2285d4bef478aa649a4856f5cc9280b00c859e..dbe80e5053a823163ab4e4fe1d9e054a4c1b948e
@@@ -1467,7 -1467,7 +1467,7 @@@ int ice_napi_poll(struct napi_struct *n
                bool wd;
  
                if (tx_ring->xsk_pool)
-                       wd = ice_xmit_zc(tx_ring, ICE_DESC_UNUSED(tx_ring), budget);
+                       wd = ice_xmit_zc(tx_ring);
                else if (ice_ring_is_xdp(tx_ring))
                        wd = true;
                else
@@@ -2258,10 -2258,8 +2258,10 @@@ ice_tstamp(struct ice_tx_ring *tx_ring
  
        /* Grab an open timestamp slot */
        idx = ice_ptp_request_ts(tx_ring->tx_tstamps, skb);
 -      if (idx < 0)
 +      if (idx < 0) {
 +              tx_ring->vsi->back->ptp.tx_hwtstamp_skipped++;
                return;
 +      }
  
        off->cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
                             (ICE_TX_CTX_DESC_TSYN << ICE_TXD_CTX_QW1_CMD_S) |
index 1efaba5d43377551d43491e0e312fefc4c9f4590,0f9668a4079d9cf31bc810a88a5bd06c6407e24d..b52f3b0177efb9ed4db04567d5e58211c9b83f84
  #define MTK_GDMA_TCS_EN               BIT(21)
  #define MTK_GDMA_UCS_EN               BIT(20)
  #define MTK_GDMA_TO_PDMA      0x0
 -#define MTK_GDMA_TO_PPE               0x4444
  #define MTK_GDMA_DROP_ALL       0x7777
  
  /* Unicast Filter MAC Address Register - Low */
  #define TX_DMA_FPORT_MASK_V2  0xf
  #define TX_DMA_SWC_V2         BIT(30)
  
 -#define MTK_WDMA0_BASE                0x2800
 -#define MTK_WDMA1_BASE                0x2c00
 -
  /* QDMA descriptor txd4 */
  #define TX_DMA_CHKSUM         (0x7 << 29)
  #define TX_DMA_TSO            BIT(28)
  #define MTK_RXD5_PPE_CPU_REASON       GENMASK(22, 18)
  #define MTK_RXD5_SRC_PORT     GENMASK(29, 26)
  
- #define RX_DMA_GET_SPORT(x)   (((x) >> 19) & 0xf)
- #define RX_DMA_GET_SPORT_V2(x)        (((x) >> 26) & 0x7)
+ #define RX_DMA_GET_SPORT(x)   (((x) >> 19) & 0x7)
+ #define RX_DMA_GET_SPORT_V2(x)        (((x) >> 26) & 0xf)
  
  /* PDMA V2 descriptor rxd3 */
  #define RX_DMA_VTAG_V2                BIT(0)
@@@ -951,9 -955,6 +951,9 @@@ struct mtk_reg_map 
                u32     fq_blen;        /* fq free page buffer length */
        } qdma;
        u32     gdm1_cnt;
 +      u32     gdma_to_ppe;
 +      u32     ppe_base;
 +      u32     wdma_base[2];
  };
  
  /* struct mtk_eth_data -      This is the structure holding all differences
   *                            the target SoC
   * @required_pctl             A bool value to show whether the SoC requires
   *                            the extra setup for those pins used by GMAC.
 + * @hash_offset                       Flow table hash offset.
 + * @foe_entry_size            Foe table entry size.
   * @txd_size                  Tx DMA descriptor size.
   * @rxd_size                  Rx DMA descriptor size.
   * @rx_irq_done_mask          Rx irq done register mask.
@@@ -983,8 -982,6 +983,8 @@@ struct mtk_soc_data 
        u32             required_clks;
        bool            required_pctl;
        u8              offload_version;
 +      u8              hash_offset;
 +      u16             foe_entry_size;
        netdev_features_t hw_features;
        struct {
                u32     txd_size;
@@@ -1114,7 -1111,7 +1114,7 @@@ struct mtk_eth 
  
        int                             ip_align;
  
 -      struct mtk_ppe                  *ppe;
 +      struct mtk_ppe                  *ppe[2];
        struct rhashtable               flow_table;
  
        struct bpf_prog                 __rcu *prog;
@@@ -1145,86 -1142,6 +1145,86 @@@ struct mtk_mac 
  /* the struct describing the SoC. these are declared in the soc_xyz.c files */
  extern const struct of_device_id of_mtk_match[];
  
 +static inline struct mtk_foe_entry *
 +mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash)
 +{
 +      const struct mtk_soc_data *soc = ppe->eth->soc;
 +
 +      return ppe->foe_table + hash * soc->foe_entry_size;
 +}
 +
 +static inline u32 mtk_get_ib1_ts_mask(struct mtk_eth *eth)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return MTK_FOE_IB1_BIND_TIMESTAMP_V2;
 +
 +      return MTK_FOE_IB1_BIND_TIMESTAMP;
 +}
 +
 +static inline u32 mtk_get_ib1_ppoe_mask(struct mtk_eth *eth)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return MTK_FOE_IB1_BIND_PPPOE_V2;
 +
 +      return MTK_FOE_IB1_BIND_PPPOE;
 +}
 +
 +static inline u32 mtk_get_ib1_vlan_tag_mask(struct mtk_eth *eth)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return MTK_FOE_IB1_BIND_VLAN_TAG_V2;
 +
 +      return MTK_FOE_IB1_BIND_VLAN_TAG;
 +}
 +
 +static inline u32 mtk_get_ib1_vlan_layer_mask(struct mtk_eth *eth)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return MTK_FOE_IB1_BIND_VLAN_LAYER_V2;
 +
 +      return MTK_FOE_IB1_BIND_VLAN_LAYER;
 +}
 +
 +static inline u32 mtk_prep_ib1_vlan_layer(struct mtk_eth *eth, u32 val)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val);
 +
 +      return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, val);
 +}
 +
 +static inline u32 mtk_get_ib1_vlan_layer(struct mtk_eth *eth, u32 val)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val);
 +
 +      return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, val);
 +}
 +
 +static inline u32 mtk_get_ib1_pkt_type_mask(struct mtk_eth *eth)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return MTK_FOE_IB1_PACKET_TYPE_V2;
 +
 +      return MTK_FOE_IB1_PACKET_TYPE;
 +}
 +
 +static inline u32 mtk_get_ib1_pkt_type(struct mtk_eth *eth, u32 val)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE_V2, val);
 +
 +      return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, val);
 +}
 +
 +static inline u32 mtk_get_ib2_multicast_mask(struct mtk_eth *eth)
 +{
 +      if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 +              return MTK_FOE_IB2_MULTICAST_V2;
 +
 +      return MTK_FOE_IB2_MULTICAST;
 +}
 +
  /* read the hardware status register */
  void mtk_stats_update_mac(struct mtk_mac *mac);
  
index 7a613b52787d4f5374f564ecf6b53a28ddca24e9,8f8005bc6eea3bb652b383870c7145c597e094d3..13b14110a06034990b385edd3f31b830664c2117
@@@ -6,6 -6,7 +6,6 @@@
   */
  #include <linux/dsa/ocelot.h>
  #include <linux/if_bridge.h>
 -#include <linux/ptp_classify.h>
  #include <soc/mscc/ocelot_vcap.h>
  #include "ocelot.h"
  #include "ocelot_vcap.h"
@@@ -289,6 -290,13 +289,13 @@@ static int ocelot_port_num_untagged_vla
                if (!(vlan->portmask & BIT(port)))
                        continue;
  
+               /* Ignore the VLAN added by ocelot_add_vlan_unaware_pvid(),
+                * because this is never active in hardware at the same time as
+                * the bridge VLANs, which only matter in VLAN-aware mode.
+                */
+               if (vlan->vid >= OCELOT_RSV_VLAN_RANGE_START)
+                       continue;
                if (vlan->untagged & BIT(port))
                        num_untagged++;
        }
@@@ -909,6 -917,211 +916,6 @@@ void ocelot_phylink_mac_link_up(struct 
  }
  EXPORT_SYMBOL_GPL(ocelot_phylink_mac_link_up);
  
 -static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
 -                                      struct sk_buff *clone)
 -{
 -      struct ocelot_port *ocelot_port = ocelot->ports[port];
 -      unsigned long flags;
 -
 -      spin_lock_irqsave(&ocelot->ts_id_lock, flags);
 -
 -      if (ocelot_port->ptp_skbs_in_flight == OCELOT_MAX_PTP_ID ||
 -          ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
 -              spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
 -              return -EBUSY;
 -      }
 -
 -      skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
 -      /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
 -      OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id;
 -
 -      ocelot_port->ts_id++;
 -      if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID)
 -              ocelot_port->ts_id = 0;
 -
 -      ocelot_port->ptp_skbs_in_flight++;
 -      ocelot->ptp_skbs_in_flight++;
 -
 -      skb_queue_tail(&ocelot_port->tx_skbs, clone);
 -
 -      spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
 -
 -      return 0;
 -}
 -
 -static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb,
 -                                     unsigned int ptp_class)
 -{
 -      struct ptp_header *hdr;
 -      u8 msgtype, twostep;
 -
 -      hdr = ptp_parse_header(skb, ptp_class);
 -      if (!hdr)
 -              return false;
 -
 -      msgtype = ptp_get_msgtype(hdr, ptp_class);
 -      twostep = hdr->flag_field[0] & 0x2;
 -
 -      if (msgtype == PTP_MSGTYPE_SYNC && twostep == 0)
 -              return true;
 -
 -      return false;
 -}
 -
 -int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
 -                               struct sk_buff *skb,
 -                               struct sk_buff **clone)
 -{
 -      struct ocelot_port *ocelot_port = ocelot->ports[port];
 -      u8 ptp_cmd = ocelot_port->ptp_cmd;
 -      unsigned int ptp_class;
 -      int err;
 -
 -      /* Don't do anything if PTP timestamping not enabled */
 -      if (!ptp_cmd)
 -              return 0;
 -
 -      ptp_class = ptp_classify_raw(skb);
 -      if (ptp_class == PTP_CLASS_NONE)
 -              return -EINVAL;
 -
 -      /* Store ptp_cmd in OCELOT_SKB_CB(skb)->ptp_cmd */
 -      if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
 -              if (ocelot_ptp_is_onestep_sync(skb, ptp_class)) {
 -                      OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
 -                      return 0;
 -              }
 -
 -              /* Fall back to two-step timestamping */
 -              ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
 -      }
 -
 -      if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
 -              *clone = skb_clone_sk(skb);
 -              if (!(*clone))
 -                      return -ENOMEM;
 -
 -              err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone);
 -              if (err)
 -                      return err;
 -
 -              OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
 -              OCELOT_SKB_CB(*clone)->ptp_class = ptp_class;
 -      }
 -
 -      return 0;
 -}
 -EXPORT_SYMBOL(ocelot_port_txtstamp_request);
 -
 -static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
 -                                 struct timespec64 *ts)
 -{
 -      unsigned long flags;
 -      u32 val;
 -
 -      spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
 -
 -      /* Read current PTP time to get seconds */
 -      val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
 -
 -      val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
 -      val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
 -      ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
 -      ts->tv_sec = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
 -
 -      /* Read packet HW timestamp from FIFO */
 -      val = ocelot_read(ocelot, SYS_PTP_TXSTAMP);
 -      ts->tv_nsec = SYS_PTP_TXSTAMP_PTP_TXSTAMP(val);
 -
 -      /* Sec has incremented since the ts was registered */
 -      if ((ts->tv_sec & 0x1) != !!(val & SYS_PTP_TXSTAMP_PTP_TXSTAMP_SEC))
 -              ts->tv_sec--;
 -
 -      spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
 -}
 -
 -static bool ocelot_validate_ptp_skb(struct sk_buff *clone, u16 seqid)
 -{
 -      struct ptp_header *hdr;
 -
 -      hdr = ptp_parse_header(clone, OCELOT_SKB_CB(clone)->ptp_class);
 -      if (WARN_ON(!hdr))
 -              return false;
 -
 -      return seqid == ntohs(hdr->sequence_id);
 -}
 -
 -void ocelot_get_txtstamp(struct ocelot *ocelot)
 -{
 -      int budget = OCELOT_PTP_QUEUE_SZ;
 -
 -      while (budget--) {
 -              struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
 -              struct skb_shared_hwtstamps shhwtstamps;
 -              u32 val, id, seqid, txport;
 -              struct ocelot_port *port;
 -              struct timespec64 ts;
 -              unsigned long flags;
 -
 -              val = ocelot_read(ocelot, SYS_PTP_STATUS);
 -
 -              /* Check if a timestamp can be retrieved */
 -              if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
 -                      break;
 -
 -              WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
 -
 -              /* Retrieve the ts ID and Tx port */
 -              id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
 -              txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
 -              seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val);
 -
 -              port = ocelot->ports[txport];
 -
 -              spin_lock(&ocelot->ts_id_lock);
 -              port->ptp_skbs_in_flight--;
 -              ocelot->ptp_skbs_in_flight--;
 -              spin_unlock(&ocelot->ts_id_lock);
 -
 -              /* Retrieve its associated skb */
 -try_again:
 -              spin_lock_irqsave(&port->tx_skbs.lock, flags);
 -
 -              skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
 -                      if (OCELOT_SKB_CB(skb)->ts_id != id)
 -                              continue;
 -                      __skb_unlink(skb, &port->tx_skbs);
 -                      skb_match = skb;
 -                      break;
 -              }
 -
 -              spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
 -
 -              if (WARN_ON(!skb_match))
 -                      continue;
 -
 -              if (!ocelot_validate_ptp_skb(skb_match, seqid)) {
 -                      dev_err_ratelimited(ocelot->dev,
 -                                          "port %d received stale TX timestamp for seqid %d, discarding\n",
 -                                          txport, seqid);
 -                      dev_kfree_skb_any(skb);
 -                      goto try_again;
 -              }
 -
 -              /* Get the h/w timestamp */
 -              ocelot_get_hwtimestamp(ocelot, &ts);
 -
 -              /* Set the timestamp into the skb */
 -              memset(&shhwtstamps, 0, sizeof(shhwtstamps));
 -              shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
 -              skb_complete_tx_timestamp(skb_match, &shhwtstamps);
 -
 -              /* Next ts */
 -              ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
 -      }
 -}
 -EXPORT_SYMBOL(ocelot_get_txtstamp);
 -
  static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh,
                                u32 *rval)
  {
@@@ -1160,6 -1373,50 +1167,6 @@@ int ocelot_fdb_del(struct ocelot *ocelo
  }
  EXPORT_SYMBOL(ocelot_fdb_del);
  
 -int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
 -                          bool is_static, void *data)
 -{
 -      struct ocelot_dump_ctx *dump = data;
 -      u32 portid = NETLINK_CB(dump->cb->skb).portid;
 -      u32 seq = dump->cb->nlh->nlmsg_seq;
 -      struct nlmsghdr *nlh;
 -      struct ndmsg *ndm;
 -
 -      if (dump->idx < dump->cb->args[2])
 -              goto skip;
 -
 -      nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
 -                      sizeof(*ndm), NLM_F_MULTI);
 -      if (!nlh)
 -              return -EMSGSIZE;
 -
 -      ndm = nlmsg_data(nlh);
 -      ndm->ndm_family  = AF_BRIDGE;
 -      ndm->ndm_pad1    = 0;
 -      ndm->ndm_pad2    = 0;
 -      ndm->ndm_flags   = NTF_SELF;
 -      ndm->ndm_type    = 0;
 -      ndm->ndm_ifindex = dump->dev->ifindex;
 -      ndm->ndm_state   = is_static ? NUD_NOARP : NUD_REACHABLE;
 -
 -      if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr))
 -              goto nla_put_failure;
 -
 -      if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid))
 -              goto nla_put_failure;
 -
 -      nlmsg_end(dump->skb, nlh);
 -
 -skip:
 -      dump->idx++;
 -      return 0;
 -
 -nla_put_failure:
 -      nlmsg_cancel(dump->skb, nlh);
 -      return -EMSGSIZE;
 -}
 -EXPORT_SYMBOL(ocelot_port_fdb_do_dump);
 -
  /* Caller must hold &ocelot->mact_lock */
  static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
                            struct ocelot_mact_entry *entry)
@@@ -1291,6 -1548,53 +1298,6 @@@ int ocelot_fdb_dump(struct ocelot *ocel
  }
  EXPORT_SYMBOL(ocelot_fdb_dump);
  
 -static void ocelot_populate_l2_ptp_trap_key(struct ocelot_vcap_filter *trap)
 -{
 -      trap->key_type = OCELOT_VCAP_KEY_ETYPE;
 -      *(__be16 *)trap->key.etype.etype.value = htons(ETH_P_1588);
 -      *(__be16 *)trap->key.etype.etype.mask = htons(0xffff);
 -}
 -
 -static void
 -ocelot_populate_ipv4_ptp_event_trap_key(struct ocelot_vcap_filter *trap)
 -{
 -      trap->key_type = OCELOT_VCAP_KEY_IPV4;
 -      trap->key.ipv4.proto.value[0] = IPPROTO_UDP;
 -      trap->key.ipv4.proto.mask[0] = 0xff;
 -      trap->key.ipv4.dport.value = PTP_EV_PORT;
 -      trap->key.ipv4.dport.mask = 0xffff;
 -}
 -
 -static void
 -ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap)
 -{
 -      trap->key_type = OCELOT_VCAP_KEY_IPV6;
 -      trap->key.ipv4.proto.value[0] = IPPROTO_UDP;
 -      trap->key.ipv4.proto.mask[0] = 0xff;
 -      trap->key.ipv6.dport.value = PTP_EV_PORT;
 -      trap->key.ipv6.dport.mask = 0xffff;
 -}
 -
 -static void
 -ocelot_populate_ipv4_ptp_general_trap_key(struct ocelot_vcap_filter *trap)
 -{
 -      trap->key_type = OCELOT_VCAP_KEY_IPV4;
 -      trap->key.ipv4.proto.value[0] = IPPROTO_UDP;
 -      trap->key.ipv4.proto.mask[0] = 0xff;
 -      trap->key.ipv4.dport.value = PTP_GEN_PORT;
 -      trap->key.ipv4.dport.mask = 0xffff;
 -}
 -
 -static void
 -ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap)
 -{
 -      trap->key_type = OCELOT_VCAP_KEY_IPV6;
 -      trap->key.ipv4.proto.value[0] = IPPROTO_UDP;
 -      trap->key.ipv4.proto.mask[0] = 0xff;
 -      trap->key.ipv6.dport.value = PTP_GEN_PORT;
 -      trap->key.ipv6.dport.mask = 0xffff;
 -}
 -
  int ocelot_trap_add(struct ocelot *ocelot, int port,
                    unsigned long cookie, bool take_ts,
                    void (*populate)(struct ocelot_vcap_filter *f))
@@@ -1359,6 -1663,381 +1366,6 @@@ int ocelot_trap_del(struct ocelot *ocel
        return ocelot_vcap_filter_replace(ocelot, trap);
  }
  
 -static int ocelot_l2_ptp_trap_add(struct ocelot *ocelot, int port)
 -{
 -      unsigned long l2_cookie = OCELOT_VCAP_IS2_L2_PTP_TRAP(ocelot);
 -
 -      return ocelot_trap_add(ocelot, port, l2_cookie, true,
 -                             ocelot_populate_l2_ptp_trap_key);
 -}
 -
 -static int ocelot_l2_ptp_trap_del(struct ocelot *ocelot, int port)
 -{
 -      unsigned long l2_cookie = OCELOT_VCAP_IS2_L2_PTP_TRAP(ocelot);
 -
 -      return ocelot_trap_del(ocelot, port, l2_cookie);
 -}
 -
 -static int ocelot_ipv4_ptp_trap_add(struct ocelot *ocelot, int port)
 -{
 -      unsigned long ipv4_gen_cookie = OCELOT_VCAP_IS2_IPV4_GEN_PTP_TRAP(ocelot);
 -      unsigned long ipv4_ev_cookie = OCELOT_VCAP_IS2_IPV4_EV_PTP_TRAP(ocelot);
 -      int err;
 -
 -      err = ocelot_trap_add(ocelot, port, ipv4_ev_cookie, true,
 -                            ocelot_populate_ipv4_ptp_event_trap_key);
 -      if (err)
 -              return err;
 -
 -      err = ocelot_trap_add(ocelot, port, ipv4_gen_cookie, false,
 -                            ocelot_populate_ipv4_ptp_general_trap_key);
 -      if (err)
 -              ocelot_trap_del(ocelot, port, ipv4_ev_cookie);
 -
 -      return err;
 -}
 -
 -static int ocelot_ipv4_ptp_trap_del(struct ocelot *ocelot, int port)
 -{
 -      unsigned long ipv4_gen_cookie = OCELOT_VCAP_IS2_IPV4_GEN_PTP_TRAP(ocelot);
 -      unsigned long ipv4_ev_cookie = OCELOT_VCAP_IS2_IPV4_EV_PTP_TRAP(ocelot);
 -      int err;
 -
 -      err = ocelot_trap_del(ocelot, port, ipv4_ev_cookie);
 -      err |= ocelot_trap_del(ocelot, port, ipv4_gen_cookie);
 -      return err;
 -}
 -
 -static int ocelot_ipv6_ptp_trap_add(struct ocelot *ocelot, int port)
 -{
 -      unsigned long ipv6_gen_cookie = OCELOT_VCAP_IS2_IPV6_GEN_PTP_TRAP(ocelot);
 -      unsigned long ipv6_ev_cookie = OCELOT_VCAP_IS2_IPV6_EV_PTP_TRAP(ocelot);
 -      int err;
 -
 -      err = ocelot_trap_add(ocelot, port, ipv6_ev_cookie, true,
 -                            ocelot_populate_ipv6_ptp_event_trap_key);
 -      if (err)
 -              return err;
 -
 -      err = ocelot_trap_add(ocelot, port, ipv6_gen_cookie, false,
 -                            ocelot_populate_ipv6_ptp_general_trap_key);
 -      if (err)
 -              ocelot_trap_del(ocelot, port, ipv6_ev_cookie);
 -
 -      return err;
 -}
 -
 -static int ocelot_ipv6_ptp_trap_del(struct ocelot *ocelot, int port)
 -{
 -      unsigned long ipv6_gen_cookie = OCELOT_VCAP_IS2_IPV6_GEN_PTP_TRAP(ocelot);
 -      unsigned long ipv6_ev_cookie = OCELOT_VCAP_IS2_IPV6_EV_PTP_TRAP(ocelot);
 -      int err;
 -
 -      err = ocelot_trap_del(ocelot, port, ipv6_ev_cookie);
 -      err |= ocelot_trap_del(ocelot, port, ipv6_gen_cookie);
 -      return err;
 -}
 -
 -static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port,
 -                                bool l2, bool l4)
 -{
 -      int err;
 -
 -      if (l2)
 -              err = ocelot_l2_ptp_trap_add(ocelot, port);
 -      else
 -              err = ocelot_l2_ptp_trap_del(ocelot, port);
 -      if (err)
 -              return err;
 -
 -      if (l4) {
 -              err = ocelot_ipv4_ptp_trap_add(ocelot, port);
 -              if (err)
 -                      goto err_ipv4;
 -
 -              err = ocelot_ipv6_ptp_trap_add(ocelot, port);
 -              if (err)
 -                      goto err_ipv6;
 -      } else {
 -              err = ocelot_ipv4_ptp_trap_del(ocelot, port);
 -
 -              err |= ocelot_ipv6_ptp_trap_del(ocelot, port);
 -      }
 -      if (err)
 -              return err;
 -
 -      return 0;
 -
 -err_ipv6:
 -      ocelot_ipv4_ptp_trap_del(ocelot, port);
 -err_ipv4:
 -      if (l2)
 -              ocelot_l2_ptp_trap_del(ocelot, port);
 -      return err;
 -}
 -
 -int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
 -{
 -      return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
 -                          sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
 -}
 -EXPORT_SYMBOL(ocelot_hwstamp_get);
 -
 -int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
 -{
 -      struct ocelot_port *ocelot_port = ocelot->ports[port];
 -      bool l2 = false, l4 = false;
 -      struct hwtstamp_config cfg;
 -      int err;
 -
 -      if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
 -              return -EFAULT;
 -
 -      /* Tx type sanity check */
 -      switch (cfg.tx_type) {
 -      case HWTSTAMP_TX_ON:
 -              ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
 -              break;
 -      case HWTSTAMP_TX_ONESTEP_SYNC:
 -              /* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
 -               * need to update the origin time.
 -               */
 -              ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
 -              break;
 -      case HWTSTAMP_TX_OFF:
 -              ocelot_port->ptp_cmd = 0;
 -              break;
 -      default:
 -              return -ERANGE;
 -      }
 -
 -      mutex_lock(&ocelot->ptp_lock);
 -
 -      switch (cfg.rx_filter) {
 -      case HWTSTAMP_FILTER_NONE:
 -              break;
 -      case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
 -      case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
 -      case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
 -              l4 = true;
 -              break;
 -      case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
 -      case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 -      case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 -              l2 = true;
 -              break;
 -      case HWTSTAMP_FILTER_PTP_V2_EVENT:
 -      case HWTSTAMP_FILTER_PTP_V2_SYNC:
 -      case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 -              l2 = true;
 -              l4 = true;
 -              break;
 -      default:
 -              mutex_unlock(&ocelot->ptp_lock);
 -              return -ERANGE;
 -      }
 -
 -      err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
 -      if (err) {
 -              mutex_unlock(&ocelot->ptp_lock);
 -              return err;
 -      }
 -
 -      if (l2 && l4)
 -              cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 -      else if (l2)
 -              cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
 -      else if (l4)
 -              cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
 -      else
 -              cfg.rx_filter = HWTSTAMP_FILTER_NONE;
 -
 -      /* Commit back the result & save it */
 -      memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
 -      mutex_unlock(&ocelot->ptp_lock);
 -
 -      return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 -}
 -EXPORT_SYMBOL(ocelot_hwstamp_set);
 -
 -void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
 -{
 -      int i;
 -
 -      if (sset != ETH_SS_STATS)
 -              return;
 -
 -      for (i = 0; i < OCELOT_NUM_STATS; i++) {
 -              if (ocelot->stats_layout[i].name[0] == '\0')
 -                      continue;
 -
 -              memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name,
 -                     ETH_GSTRING_LEN);
 -      }
 -}
 -EXPORT_SYMBOL(ocelot_get_strings);
 -
 -/* Caller must hold &ocelot->stats_lock */
 -static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
 -{
 -      unsigned int idx = port * OCELOT_NUM_STATS;
 -      struct ocelot_stats_region *region;
 -      int err, j;
 -
 -      /* Configure the port to read the stats from */
 -      ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG);
 -
 -      list_for_each_entry(region, &ocelot->stats_regions, node) {
 -              err = ocelot_bulk_read(ocelot, region->base, region->buf,
 -                                     region->count);
 -              if (err)
 -                      return err;
 -
 -              for (j = 0; j < region->count; j++) {
 -                      u64 *stat = &ocelot->stats[idx + j];
 -                      u64 val = region->buf[j];
 -
 -                      if (val < (*stat & U32_MAX))
 -                              *stat += (u64)1 << 32;
 -
 -                      *stat = (*stat & ~(u64)U32_MAX) + val;
 -              }
 -
 -              idx += region->count;
 -      }
 -
 -      return err;
 -}
 -
 -static void ocelot_check_stats_work(struct work_struct *work)
 -{
 -      struct delayed_work *del_work = to_delayed_work(work);
 -      struct ocelot *ocelot = container_of(del_work, struct ocelot,
 -                                           stats_work);
 -      int i, err;
 -
 -      spin_lock(&ocelot->stats_lock);
 -      for (i = 0; i < ocelot->num_phys_ports; i++) {
 -              err = ocelot_port_update_stats(ocelot, i);
 -              if (err)
 -                      break;
 -      }
 -      spin_unlock(&ocelot->stats_lock);
 -
 -      if (err)
 -              dev_err(ocelot->dev, "Error %d updating ethtool stats\n",  err);
 -
 -      queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
 -                         OCELOT_STATS_CHECK_DELAY);
 -}
 -
 -void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
 -{
 -      int i, err;
 -
 -      spin_lock(&ocelot->stats_lock);
 -
 -      /* check and update now */
 -      err = ocelot_port_update_stats(ocelot, port);
 -
 -      /* Copy all supported counters */
 -      for (i = 0; i < OCELOT_NUM_STATS; i++) {
 -              int index = port * OCELOT_NUM_STATS + i;
 -
 -              if (ocelot->stats_layout[i].name[0] == '\0')
 -                      continue;
 -
 -              *data++ = ocelot->stats[index];
 -      }
 -
 -      spin_unlock(&ocelot->stats_lock);
 -
 -      if (err)
 -              dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err);
 -}
 -EXPORT_SYMBOL(ocelot_get_ethtool_stats);
 -
 -int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
 -{
 -      int i, num_stats = 0;
 -
 -      if (sset != ETH_SS_STATS)
 -              return -EOPNOTSUPP;
 -
 -      for (i = 0; i < OCELOT_NUM_STATS; i++)
 -              if (ocelot->stats_layout[i].name[0] != '\0')
 -                      num_stats++;
 -
 -      return num_stats;
 -}
 -EXPORT_SYMBOL(ocelot_get_sset_count);
 -
 -static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
 -{
 -      struct ocelot_stats_region *region = NULL;
 -      unsigned int last;
 -      int i;
 -
 -      INIT_LIST_HEAD(&ocelot->stats_regions);
 -
 -      for (i = 0; i < OCELOT_NUM_STATS; i++) {
 -              if (ocelot->stats_layout[i].name[0] == '\0')
 -                      continue;
 -
 -              if (region && ocelot->stats_layout[i].reg == last + 4) {
 -                      region->count++;
 -              } else {
 -                      region = devm_kzalloc(ocelot->dev, sizeof(*region),
 -                                            GFP_KERNEL);
 -                      if (!region)
 -                              return -ENOMEM;
 -
 -                      region->base = ocelot->stats_layout[i].reg;
 -                      region->count = 1;
 -                      list_add_tail(&region->node, &ocelot->stats_regions);
 -              }
 -
 -              last = ocelot->stats_layout[i].reg;
 -      }
 -
 -      list_for_each_entry(region, &ocelot->stats_regions, node) {
 -              region->buf = devm_kcalloc(ocelot->dev, region->count,
 -                                         sizeof(*region->buf), GFP_KERNEL);
 -              if (!region->buf)
 -                      return -ENOMEM;
 -      }
 -
 -      return 0;
 -}
 -
 -int ocelot_get_ts_info(struct ocelot *ocelot, int port,
 -                     struct ethtool_ts_info *info)
 -{
 -      info->phc_index = ocelot->ptp_clock ?
 -                        ptp_clock_index(ocelot->ptp_clock) : -1;
 -      if (info->phc_index == -1) {
 -              info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
 -                                       SOF_TIMESTAMPING_RX_SOFTWARE |
 -                                       SOF_TIMESTAMPING_SOFTWARE;
 -              return 0;
 -      }
 -      info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
 -                               SOF_TIMESTAMPING_RX_SOFTWARE |
 -                               SOF_TIMESTAMPING_SOFTWARE |
 -                               SOF_TIMESTAMPING_TX_HARDWARE |
 -                               SOF_TIMESTAMPING_RX_HARDWARE |
 -                               SOF_TIMESTAMPING_RAW_HARDWARE;
 -      info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
 -                       BIT(HWTSTAMP_TX_ONESTEP_SYNC);
 -      info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
 -                         BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
 -                         BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
 -                         BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
 -
 -      return 0;
 -}
 -EXPORT_SYMBOL(ocelot_get_ts_info);
 -
  static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond)
  {
        u32 mask = 0;
  /* The logical port number of a LAG is equal to the lowest numbered physical
   * port ID present in that LAG. It may change if that port ever leaves the LAG.
   */
 -static int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond)
 +int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond)
  {
        int bond_mask = ocelot_get_bond_mask(ocelot, bond);
  
  
        return __ffs(bond_mask);
  }
 +EXPORT_SYMBOL_GPL(ocelot_bond_get_id);
  
 +/* Returns the mask of user ports assigned to this DSA tag_8021q CPU port.
 + * Note that when CPU ports are in a LAG, the user ports are assigned to the
 + * 'primary' CPU port, the one whose physical port number gives the logical
 + * port number of the LAG.
 + *
 + * We leave PGID_SRC poorly configured for the 'secondary' CPU port in the LAG
 + * (to which no user port is assigned), but it appears that forwarding from
 + * this secondary CPU port looks at the PGID_SRC associated with the logical
 + * port ID that it's assigned to, which *is* configured properly.
 + */
  static u32 ocelot_dsa_8021q_cpu_assigned_ports(struct ocelot *ocelot,
                                               struct ocelot_port *cpu)
  {
                        mask |= BIT(port);
        }
  
 +      if (cpu->bond)
 +              mask &= ~ocelot_get_bond_mask(ocelot, cpu->bond);
 +
        return mask;
  }
  
 +/* Returns the DSA tag_8021q CPU port that the given port is assigned to,
 + * or the bit mask of CPU ports if said CPU port is in a LAG.
 + */
  u32 ocelot_port_assigned_dsa_8021q_cpu_mask(struct ocelot *ocelot, int port)
  {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
        if (!cpu_port)
                return 0;
  
 +      if (cpu_port->bond)
 +              return ocelot_get_bond_mask(ocelot, cpu_port->bond);
 +
        return BIT(cpu_port->index);
  }
  EXPORT_SYMBOL_GPL(ocelot_port_assigned_dsa_8021q_cpu_mask);
@@@ -1562,61 -2221,61 +1569,61 @@@ static void ocelot_update_pgid_cpu(stru
        ocelot_write_rix(ocelot, pgid_cpu, ANA_PGID_PGID, PGID_CPU);
  }
  
 -void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port,
 -                                    int cpu)
 +void ocelot_port_setup_dsa_8021q_cpu(struct ocelot *ocelot, int cpu)
  {
        struct ocelot_port *cpu_port = ocelot->ports[cpu];
        u16 vid;
  
        mutex_lock(&ocelot->fwd_domain_lock);
  
 -      ocelot->ports[port]->dsa_8021q_cpu = cpu_port;
 -
 -      if (!cpu_port->is_dsa_8021q_cpu) {
 -              cpu_port->is_dsa_8021q_cpu = true;
 +      cpu_port->is_dsa_8021q_cpu = true;
  
 -              for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
 -                      ocelot_vlan_member_add(ocelot, cpu, vid, true);
 +      for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
 +              ocelot_vlan_member_add(ocelot, cpu, vid, true);
  
 -              ocelot_update_pgid_cpu(ocelot);
 -      }
 -
 -      ocelot_apply_bridge_fwd_mask(ocelot, true);
 +      ocelot_update_pgid_cpu(ocelot);
  
        mutex_unlock(&ocelot->fwd_domain_lock);
  }
 -EXPORT_SYMBOL_GPL(ocelot_port_assign_dsa_8021q_cpu);
 +EXPORT_SYMBOL_GPL(ocelot_port_setup_dsa_8021q_cpu);
  
 -void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port)
 +void ocelot_port_teardown_dsa_8021q_cpu(struct ocelot *ocelot, int cpu)
  {
 -      struct ocelot_port *cpu_port = ocelot->ports[port]->dsa_8021q_cpu;
 -      bool keep = false;
 +      struct ocelot_port *cpu_port = ocelot->ports[cpu];
        u16 vid;
 -      int p;
  
        mutex_lock(&ocelot->fwd_domain_lock);
  
 -      ocelot->ports[port]->dsa_8021q_cpu = NULL;
 +      cpu_port->is_dsa_8021q_cpu = false;
  
 -      for (p = 0; p < ocelot->num_phys_ports; p++) {
 -              if (!ocelot->ports[p])
 -                      continue;
 +      for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
 +              ocelot_vlan_member_del(ocelot, cpu_port->index, vid);
  
 -              if (ocelot->ports[p]->dsa_8021q_cpu == cpu_port) {
 -                      keep = true;
 -                      break;
 -              }
 -      }
 +      ocelot_update_pgid_cpu(ocelot);
  
 -      if (!keep) {
 -              cpu_port->is_dsa_8021q_cpu = false;
 +      mutex_unlock(&ocelot->fwd_domain_lock);
 +}
 +EXPORT_SYMBOL_GPL(ocelot_port_teardown_dsa_8021q_cpu);
  
 -              for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
 -                      ocelot_vlan_member_del(ocelot, cpu_port->index, vid);
 +void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port,
 +                                    int cpu)
 +{
 +      struct ocelot_port *cpu_port = ocelot->ports[cpu];
  
 -              ocelot_update_pgid_cpu(ocelot);
 -      }
 +      mutex_lock(&ocelot->fwd_domain_lock);
 +
 +      ocelot->ports[port]->dsa_8021q_cpu = cpu_port;
 +      ocelot_apply_bridge_fwd_mask(ocelot, true);
 +
 +      mutex_unlock(&ocelot->fwd_domain_lock);
 +}
 +EXPORT_SYMBOL_GPL(ocelot_port_assign_dsa_8021q_cpu);
 +
 +void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port)
 +{
 +      mutex_lock(&ocelot->fwd_domain_lock);
  
 +      ocelot->ports[port]->dsa_8021q_cpu = NULL;
        ocelot_apply_bridge_fwd_mask(ocelot, true);
  
        mutex_unlock(&ocelot->fwd_domain_lock);
@@@ -2133,14 -2792,10 +2140,14 @@@ static void ocelot_migrate_lag_fdbs(str
  
  int ocelot_port_lag_join(struct ocelot *ocelot, int port,
                         struct net_device *bond,
 -                       struct netdev_lag_upper_info *info)
 +                       struct netdev_lag_upper_info *info,
 +                       struct netlink_ext_ack *extack)
  {
 -      if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
 +      if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
 +              NL_SET_ERR_MSG_MOD(extack,
 +                                 "Can only offload LAG using hash TX type");
                return -EOPNOTSUPP;
 +      }
  
        mutex_lock(&ocelot->fwd_domain_lock);
  
@@@ -2710,6 -3365,7 +2717,6 @@@ static void ocelot_detect_features(stru
  
  int ocelot_init(struct ocelot *ocelot)
  {
 -      char queue_name[32];
        int i, ret;
        u32 port;
  
                }
        }
  
 -      ocelot->stats = devm_kcalloc(ocelot->dev,
 -                                   ocelot->num_phys_ports * OCELOT_NUM_STATS,
 -                                   sizeof(u64), GFP_KERNEL);
 -      if (!ocelot->stats)
 -              return -ENOMEM;
 -
 -      spin_lock_init(&ocelot->stats_lock);
        mutex_init(&ocelot->ptp_lock);
        mutex_init(&ocelot->mact_lock);
        mutex_init(&ocelot->fwd_domain_lock);
        mutex_init(&ocelot->tas_lock);
        spin_lock_init(&ocelot->ptp_clock_lock);
        spin_lock_init(&ocelot->ts_id_lock);
 -      snprintf(queue_name, sizeof(queue_name), "%s-stats",
 -               dev_name(ocelot->dev));
 -      ocelot->stats_queue = create_singlethread_workqueue(queue_name);
 -      if (!ocelot->stats_queue)
 -              return -ENOMEM;
  
        ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0);
 -      if (!ocelot->owq) {
 -              destroy_workqueue(ocelot->stats_queue);
 +      if (!ocelot->owq)
                return -ENOMEM;
 +
 +      ret = ocelot_stats_init(ocelot);
 +      if (ret) {
 +              destroy_workqueue(ocelot->owq);
 +              return ret;
        }
  
        INIT_LIST_HEAD(&ocelot->multicast);
                                 ANA_CPUQ_8021_CFG_CPUQ_BPDU_VAL(6),
                                 ANA_CPUQ_8021_CFG, i);
  
 -      ret = ocelot_prepare_stats_regions(ocelot);
 -      if (ret) {
 -              destroy_workqueue(ocelot->stats_queue);
 -              destroy_workqueue(ocelot->owq);
 -              return ret;
 -      }
 -
 -      INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
 -      queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
 -                         OCELOT_STATS_CHECK_DELAY);
 -
        return 0;
  }
  EXPORT_SYMBOL(ocelot_init);
  
  void ocelot_deinit(struct ocelot *ocelot)
  {
 -      cancel_delayed_work(&ocelot->stats_work);
 -      destroy_workqueue(ocelot->stats_queue);
 +      ocelot_stats_deinit(ocelot);
        destroy_workqueue(ocelot->owq);
  }
  EXPORT_SYMBOL(ocelot_deinit);
index 5ec3d4537baef4eb1941397c47642fec64699f27,9083159b93f140ba9fabe003afd0238cff7b4c32..65c96773c6d2b2972cea2c6cc80128675e8ffa54
@@@ -3801,6 -3801,15 +3801,15 @@@ static int __stmmac_open(struct net_dev
  
        stmmac_reset_queues_param(priv);
  
+       if (priv->plat->serdes_powerup) {
+               ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv);
+               if (ret < 0) {
+                       netdev_err(priv->dev, "%s: Serdes powerup failed\n",
+                                  __func__);
+                       goto init_error;
+               }
+       }
        ret = stmmac_hw_setup(dev, true);
        if (ret < 0) {
                netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
@@@ -3904,6 -3913,10 +3913,10 @@@ static int stmmac_release(struct net_de
        /* Disable the MAC Rx/Tx */
        stmmac_mac_set(priv, priv->ioaddr, false);
  
+       /* Powerdown Serdes if there is */
+       if (priv->plat->serdes_powerdown)
+               priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
        netif_carrier_off(dev);
  
        stmmac_release_ptp(priv);
@@@ -5076,8 -5089,16 +5089,8 @@@ read_again
                buf1_len = stmmac_rx_buf1_len(priv, p, status, len);
                len += buf1_len;
  
 -              /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
 -               * Type frames (LLC/LLC-SNAP)
 -               *
 -               * llc_snap is never checked in GMAC >= 4, so this ACS
 -               * feature is always disabled and packets need to be
 -               * stripped manually.
 -               */
 -              if (likely(!(status & rx_not_ls)) &&
 -                  (likely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
 -                   unlikely(status != llc_snap))) {
 +              /* ACS is disabled; strip manually. */
 +              if (likely(!(status & rx_not_ls))) {
                        buf1_len -= ETH_FCS_LEN;
                        len -= ETH_FCS_LEN;
                }
@@@ -5254,8 -5275,16 +5267,8 @@@ read_again
                buf2_len = stmmac_rx_buf2_len(priv, p, status, len);
                len += buf2_len;
  
 -              /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
 -               * Type frames (LLC/LLC-SNAP)
 -               *
 -               * llc_snap is never checked in GMAC >= 4, so this ACS
 -               * feature is always disabled and packets need to be
 -               * stripped manually.
 -               */
 -              if (likely(!(status & rx_not_ls)) &&
 -                  (likely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
 -                   unlikely(status != llc_snap))) {
 +              /* ACS is disabled; strip manually. */
 +              if (likely(!(status & rx_not_ls))) {
                        if (buf2_len) {
                                buf2_len -= ETH_FCS_LEN;
                                len -= ETH_FCS_LEN;
@@@ -6874,7 -6903,8 +6887,7 @@@ static void stmmac_napi_add(struct net_
                spin_lock_init(&ch->lock);
  
                if (queue < priv->plat->rx_queues_to_use) {
 -                      netif_napi_add(dev, &ch->rx_napi, stmmac_napi_poll_rx,
 -                                     NAPI_POLL_WEIGHT);
 +                      netif_napi_add(dev, &ch->rx_napi, stmmac_napi_poll_rx);
                }
                if (queue < priv->plat->tx_queues_to_use) {
                        netif_napi_add_tx(dev, &ch->tx_napi,
                if (queue < priv->plat->rx_queues_to_use &&
                    queue < priv->plat->tx_queues_to_use) {
                        netif_napi_add(dev, &ch->rxtx_napi,
 -                                     stmmac_napi_poll_rxtx,
 -                                     NAPI_POLL_WEIGHT);
 +                                     stmmac_napi_poll_rxtx);
                }
        }
  }
@@@ -7275,14 -7306,6 +7288,6 @@@ int stmmac_dvr_probe(struct device *dev
                goto error_netdev_register;
        }
  
-       if (priv->plat->serdes_powerup) {
-               ret = priv->plat->serdes_powerup(ndev,
-                                                priv->plat->bsp_priv);
-               if (ret < 0)
-                       goto error_serdes_powerup;
-       }
  #ifdef CONFIG_DEBUG_FS
        stmmac_init_fs(ndev);
  #endif
  
        return ret;
  
- error_serdes_powerup:
-       unregister_netdev(ndev);
  error_netdev_register:
        phylink_destroy(priv->phylink);
  error_xpcs_setup:
index 2198f1302642d5b17e2696f4fa2ed7cc6b70e701,4df8c337221bd5f06699899e8e729de04712847f..83cafa4057207c03e076c2a40407693453f76113
@@@ -316,11 -316,13 +316,13 @@@ static __maybe_unused int mdio_bus_phy_
  
        phydev->suspended_by_mdio_bus = 0;
  
-       /* If we manged to get here with the PHY state machine in a state neither
-        * PHY_HALTED nor PHY_READY this is an indication that something went wrong
-        * and we should most likely be using MAC managed PM and we are not.
+       /* If we managed to get here with the PHY state machine in a state
+        * neither PHY_HALTED, PHY_READY nor PHY_UP, this is an indication
+        * that something went wrong and we should most likely be using
+        * MAC managed PM, but we are not.
         */
-       WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY);
+       WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY &&
+               phydev->state != PHY_UP);
  
        ret = phy_init_hw(phydev);
        if (ret < 0)
@@@ -370,7 -372,7 +372,7 @@@ int phy_register_fixup(const char *bus_
        if (!fixup)
                return -ENOMEM;
  
 -      strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
 +      strscpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
        fixup->phy_uid = phy_uid;
        fixup->phy_uid_mask = phy_uid_mask;
        fixup->run = run;
diff --combined drivers/net/tun.c
index 3732e51b5ad8d7ac3dca1dfd11eed29168331432,db736b944016e2dbc40a0d9c007947de97d27c63..9064ff053a164babe3ff6606424ed40195d3dc10
@@@ -2828,7 -2828,10 +2828,10 @@@ static int tun_set_iff(struct net *net
                rcu_assign_pointer(tfile->tun, tun);
        }
  
-       netif_carrier_on(tun->dev);
+       if (ifr->ifr_flags & IFF_NO_CARRIER)
+               netif_carrier_off(tun->dev);
+       else
+               netif_carrier_on(tun->dev);
  
        /* Make sure persistent devices do not get stuck in
         * xoff state.
@@@ -3056,8 -3059,8 +3059,8 @@@ static long __tun_chr_ioctl(struct fil
                 * This is needed because we never checked for invalid flags on
                 * TUNSETIFF.
                 */
-               return put_user(IFF_TUN | IFF_TAP | TUN_FEATURES,
-                               (unsigned int __user*)argp);
+               return put_user(IFF_TUN | IFF_TAP | IFF_NO_CARRIER |
+                               TUN_FEATURES, (unsigned int __user*)argp);
        } else if (cmd == TUNSETQUEUE) {
                return tun_set_queue(file, &ifr);
        } else if (cmd == SIOCGSKNS) {
@@@ -3540,15 -3543,15 +3543,15 @@@ static void tun_get_drvinfo(struct net_
  {
        struct tun_struct *tun = netdev_priv(dev);
  
 -      strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 -      strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 +      strscpy(info->driver, DRV_NAME, sizeof(info->driver));
 +      strscpy(info->version, DRV_VERSION, sizeof(info->version));
  
        switch (tun->flags & TUN_TYPE_MASK) {
        case IFF_TUN:
 -              strlcpy(info->bus_info, "tun", sizeof(info->bus_info));
 +              strscpy(info->bus_info, "tun", sizeof(info->bus_info));
                break;
        case IFF_TAP:
 -              strlcpy(info->bus_info, "tap", sizeof(info->bus_info));
 +              strscpy(info->bus_info, "tap", sizeof(info->bus_info));
                break;
        }
  }
diff --combined drivers/net/usb/usbnet.c
index fd399a8ed973fcdc1077233e7b091ffef73bdd56,e368b0780753f26f0454cfa11a895af37be973bc..64a9a80b23094ea57948fbc8181b9dff2a373523
@@@ -1050,9 -1050,9 +1050,9 @@@ void usbnet_get_drvinfo (struct net_dev
  {
        struct usbnet *dev = netdev_priv(net);
  
 -      strlcpy (info->driver, dev->driver_name, sizeof info->driver);
 -      strlcpy (info->fw_version, dev->driver_info->description,
 -              sizeof info->fw_version);
 +      strscpy(info->driver, dev->driver_name, sizeof(info->driver));
 +      strscpy(info->fw_version, dev->driver_info->description,
 +              sizeof(info->fw_version));
        usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
  }
  EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
@@@ -1598,6 -1598,7 +1598,7 @@@ void usbnet_disconnect (struct usb_inte
        struct usbnet           *dev;
        struct usb_device       *xdev;
        struct net_device       *net;
+       struct urb              *urb;
  
        dev = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
        net = dev->net;
        unregister_netdev (net);
  
-       usb_scuttle_anchored_urbs(&dev->deferred);
+       while ((urb = usb_get_from_anchor(&dev->deferred))) {
+               dev_kfree_skb(urb->context);
+               kfree(urb->sg);
+               usb_free_urb(urb);
+       }
  
        if (dev->driver_info->unbind)
                dev->driver_info->unbind(dev, intf);
diff --combined kernel/cgroup/cgroup.c
index 2ddae5743d53b6608b42011fd1be5c107faae42b,5f2090d051acba2fd4718c07ffc193d21ac40777..8ad2c267ff471004f30b662a5576ee3e4921c105
@@@ -6049,6 -6049,9 +6049,9 @@@ struct cgroup *cgroup_get_from_id(u64 i
        if (!kn)
                goto out;
  
+       if (kernfs_type(kn) != KERNFS_DIR)
+               goto put;
        rcu_read_lock();
  
        cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
                cgrp = NULL;
  
        rcu_read_unlock();
+ put:
        kernfs_put(kn);
  out:
        return cgrp;
@@@ -6164,6 -6167,11 +6167,6 @@@ static struct cgroup *cgroup_get_from_f
                return ERR_CAST(css);
  
        cgrp = css->cgroup;
 -      if (!cgroup_on_dfl(cgrp)) {
 -              cgroup_put(cgrp);
 -              return ERR_PTR(-EBADF);
 -      }
 -
        return cgrp;
  }
  
diff --combined net/mac80211/mlme.c
index 699e409ef45a3ba5cf1503e8ce3b9f59d1ed175b,fc764984d687f86e93baeec1ec4487b6e6e536f6..d7cf6fa4c4918e9c2310473030846f8219f40453
@@@ -314,7 -314,7 +314,7 @@@ ieee80211_determine_chantype(struct iee
        if (eht_oper && (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
                struct cfg80211_chan_def eht_chandef = *chandef;
  
 -              ieee80211_chandef_eht_oper(sdata, eht_oper,
 +              ieee80211_chandef_eht_oper(eht_oper,
                                           eht_chandef.width ==
                                           NL80211_CHAN_WIDTH_160,
                                           false, &eht_chandef);
@@@ -695,7 -695,6 +695,7 @@@ static bool ieee80211_add_vht_ie(struc
  static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
                                struct sk_buff *skb,
                                struct ieee80211_supported_band *sband,
 +                              enum ieee80211_smps_mode smps_mode,
                                ieee80211_conn_flags_t conn_flags)
  {
        u8 *pos, *pre_he_pos;
        /* trim excess if any */
        skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos));
  
 -      ieee80211_ie_build_he_6ghz_cap(sdata, skb);
 +      ieee80211_ie_build_he_6ghz_cap(sdata, smps_mode, skb);
  }
  
  static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata,
        eht_cap_size =
                2 + 1 + sizeof(eht_cap->eht_cap_elem) +
                ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
 -                                         &eht_cap->eht_cap_elem) +
 +                                         &eht_cap->eht_cap_elem,
 +                                         false) +
                ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
                                       eht_cap->eht_cap_elem.phy_cap_info);
        pos = skb_put(skb, eht_cap_size);
 -      ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size);
 +      ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size,
 +                                 false);
  }
  
  static void ieee80211_assoc_add_rates(struct sk_buff *skb,
@@@ -1101,7 -1098,7 +1101,7 @@@ static size_t ieee80211_assoc_link_elem
                                               offset);
  
        if (!(assoc_data->link[link_id].conn_flags & IEEE80211_CONN_DISABLE_HE)) {
 -              ieee80211_add_he_ie(sdata, skb, sband,
 +              ieee80211_add_he_ie(sdata, skb, sband, smps_mode,
                                    assoc_data->link[link_id].conn_flags);
                ADD_PRESENT_EXT_ELEM(WLAN_EID_EXT_HE_CAPABILITY);
        }
@@@ -1223,21 -1220,14 +1223,21 @@@ static void ieee80211_assoc_add_ml_elem
        ml_elem = skb_put(skb, sizeof(*ml_elem));
        ml_elem->control =
                cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC |
 -                          IEEE80211_MLC_BASIC_PRES_EML_CAPA |
                            IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP);
        common = skb_put(skb, sizeof(*common));
        common->len = sizeof(*common) +
 -                    2 + /* EML capabilities */
                      2;  /* MLD capa/ops */
        memcpy(common->mld_mac_addr, sdata->vif.addr, ETH_ALEN);
 -      skb_put_data(skb, &eml_capa, sizeof(eml_capa));
 +
 +      /* add EML_CAPA only if needed, see Draft P802.11be_D2.1, 35.3.17 */
 +      if (eml_capa &
 +          cpu_to_le16((IEEE80211_EML_CAP_EMLSR_SUPP |
 +                       IEEE80211_EML_CAP_EMLMR_SUPPORT))) {
 +              common->len += 2; /* EML capabilities */
 +              ml_elem->control |=
 +                      cpu_to_le16(IEEE80211_MLC_BASIC_PRES_EML_CAPA);
 +              skb_put_data(skb, &eml_capa, sizeof(eml_capa));
 +      }
        /* need indication from userspace to support this */
        mld_capa_ops &= ~cpu_to_le16(IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP);
        skb_put_data(skb, &mld_capa_ops, sizeof(mld_capa_ops));
@@@ -1912,7 -1902,7 +1912,7 @@@ ieee80211_sta_process_chanswitch(struc
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
        mutex_unlock(&local->mtx);
  
 -      cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
 +      cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
                                          csa_ie.count, csa_ie.mode);
  
        if (local->ops->channel_switch) {
@@@ -2445,29 -2435,6 +2445,29 @@@ static void ieee80211_sta_handle_tspec_
        ieee80211_sta_handle_tspec_ac_params(sdata);
  }
  
 +void ieee80211_mgd_set_link_qos_params(struct ieee80211_link_data *link)
 +{
 +      struct ieee80211_sub_if_data *sdata = link->sdata;
 +      struct ieee80211_local *local = sdata->local;
 +      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 +      struct ieee80211_tx_queue_params *params = link->tx_conf;
 +      u8 ac;
 +
 +      for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
 +              mlme_dbg(sdata,
 +                       "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
 +                       ac, params[ac].acm,
 +                       params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
 +                       params[ac].txop, params[ac].uapsd,
 +                       ifmgd->tx_tspec[ac].downgraded);
 +              if (!ifmgd->tx_tspec[ac].downgraded &&
 +                  drv_conf_tx(local, link, ac, &params[ac]))
 +                      link_err(link,
 +                               "failed to set TX queue parameters for AC %d\n",
 +                               ac);
 +      }
 +}
 +
  /* MLME */
  static bool
  ieee80211_sta_wmm_params(struct ieee80211_local *local,
                }
        }
  
 -      for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
 -              mlme_dbg(sdata,
 -                       "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
 -                       ac, params[ac].acm,
 -                       params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
 -                       params[ac].txop, params[ac].uapsd,
 -                       ifmgd->tx_tspec[ac].downgraded);
 +      for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
                link->tx_conf[ac] = params[ac];
 -              if (!ifmgd->tx_tspec[ac].downgraded &&
 -                  drv_conf_tx(local, link, ac, &params[ac]))
 -                      link_err(link,
 -                               "failed to set TX queue parameters for AC %d\n",
 -                               ac);
 -      }
 +
 +      ieee80211_mgd_set_link_qos_params(link);
  
        /* enable WMM or activate new settings */
        link->conf->qos = true;
@@@ -3927,7 -3904,6 +3927,7 @@@ static bool ieee80211_assoc_config_link
                .len = elem_len,
                .bss = cbss,
                .link_id = link == &sdata->deflink ? -1 : link->link_id,
 +              .from_ap = true,
        };
        bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
        bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ;
  
        if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
            (!elems->he_cap || !elems->he_operation)) {
-               mutex_unlock(&sdata->local->sta_mtx);
                sdata_info(sdata,
                           "HE AP is missing HE capability/operation\n");
                ret = false;
@@@ -4596,11 -4571,6 +4595,11 @@@ static int ieee80211_prep_channel(struc
        bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
        bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ;
        struct ieee80211_bss *bss = (void *)cbss->priv;
 +      struct ieee80211_elems_parse_params parse_params = {
 +              .bss = cbss,
 +              .link_id = -1,
 +              .from_ap = true,
 +      };
        struct ieee802_11_elems *elems;
        const struct cfg80211_bss_ies *ies;
        int ret;
        rcu_read_lock();
  
        ies = rcu_dereference(cbss->ies);
 -      elems = ieee802_11_parse_elems(ies->data, ies->len, false, cbss);
 +      parse_params.start = ies->data;
 +      parse_params.len = ies->len;
 +      elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems) {
                rcu_read_unlock();
                return -ENOMEM;
@@@ -4967,11 -4935,6 +4966,11 @@@ static void ieee80211_rx_mgmt_assoc_res
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
        u16 capab_info, status_code, aid;
 +      struct ieee80211_elems_parse_params parse_params = {
 +              .bss = NULL,
 +              .link_id = -1,
 +              .from_ap = true,
 +      };
        struct ieee802_11_elems *elems;
        int ac;
        const u8 *elem_start;
                return;
  
        elem_len = len - (elem_start - (u8 *)mgmt);
 -      elems = ieee802_11_parse_elems(elem_start, elem_len, false, NULL);
 +      parse_params.start = elem_start;
 +      parse_params.len = elem_len;
 +      elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                goto notify_driver;
  
        resp.req_ies = ifmgd->assoc_req_ies;
        resp.req_ies_len = ifmgd->assoc_req_ies_len;
        if (sdata->vif.valid_links)
 -              resp.ap_mld_addr = assoc_data->ap_addr;
 +              resp.ap_mld_addr = sdata->vif.cfg.ap_addr;
        cfg80211_rx_assoc_resp(sdata->dev, &resp);
  notify_driver:
        drv_mgd_complete_tx(sdata->local, sdata, &info);
@@@ -5393,10 -5354,6 +5392,10 @@@ static void ieee80211_rx_mgmt_beacon(st
        u32 ncrc = 0;
        u8 *bssid, *variable = mgmt->u.beacon.variable;
        u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
 +      struct ieee80211_elems_parse_params parse_params = {
 +              .link_id = -1,
 +              .from_ap = true,
 +      };
  
        sdata_assert_lock(sdata);
  
        if (baselen > len)
                return;
  
 +      parse_params.start = variable;
 +      parse_params.len = len - baselen;
 +
        rcu_read_lock();
        chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
        if (!chanctx_conf) {
        if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
            !WARN_ON(sdata->vif.valid_links) &&
            ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->link[0].bss)) {
 -              elems = ieee802_11_parse_elems(variable, len - baselen, false,
 -                                             ifmgd->assoc_data->link[0].bss);
 +              parse_params.bss = ifmgd->assoc_data->link[0].bss;
 +              elems = ieee802_11_parse_elems_full(&parse_params);
                if (!elems)
                        return;
  
         */
        if (!ieee80211_is_s1g_beacon(hdr->frame_control))
                ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
 -      elems = ieee802_11_parse_elems_crc(variable, len - baselen,
 -                                         false, care_about_ies, ncrc,
 -                                         link->u.mgd.bss);
 +      parse_params.bss = link->u.mgd.bss;
 +      parse_params.filter = care_about_ies;
 +      parse_params.crc = ncrc;
 +      elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                return;
        ncrc = elems->crc;
  
        mutex_lock(&local->sta_mtx);
        sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
-       if (WARN_ON(!sta))
+       if (WARN_ON(!sta)) {
+               mutex_unlock(&local->sta_mtx);
                goto free;
+       }
        link_sta = rcu_dereference_protected(sta->link[link->link_id],
                                             lockdep_is_held(&local->sta_mtx));
-       if (WARN_ON(!link_sta))
+       if (WARN_ON(!link_sta)) {
+               mutex_unlock(&local->sta_mtx);
                goto free;
+       }
  
        changed |= ieee80211_recalc_twt_req(link, link_sta, elems);
  
@@@ -5716,13 -5673,6 +5719,13 @@@ void ieee80211_sta_rx_queued_mgmt(struc
  
        sdata_lock(sdata);
  
 +      if (rx_status->link_valid) {
 +              link = sdata_dereference(sdata->link[rx_status->link_id],
 +                                       sdata);
 +              if (!link)
 +                      goto out;
 +      }
 +
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_BEACON:
                ieee80211_rx_mgmt_beacon(link, (void *)mgmt,
                }
                break;
        }
 +out:
        sdata_unlock(sdata);
  }
  
@@@ -6335,8 -6284,6 +6338,8 @@@ void ieee80211_mgd_setup_link(struct ie
        if (sdata->u.mgd.assoc_data)
                ether_addr_copy(link->conf->addr,
                                sdata->u.mgd.assoc_data->link[link_id].addr);
 +      else if (!is_valid_ether_addr(link->conf->addr))
 +              eth_random_addr(link->conf->addr);
  }
  
  /* scan finished notification */
@@@ -6424,6 -6371,9 +6427,6 @@@ static int ieee80211_prep_connection(st
                goto out_err;
        }
  
 -      if (mlo && !is_valid_ether_addr(link->conf->addr))
 -              eth_random_addr(link->conf->addr);
 -
        if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) {
                err = -EINVAL;
                goto out_err;
@@@ -6906,10 -6856,6 +6909,10 @@@ int ieee80211_mgd_assoc(struct ieee8021
                }
        }
  
 +      /* FIXME: no support for 4-addr MLO yet */
 +      if (sdata->u.mgd.use_4addr && req->link_id >= 0)
 +              return -EOPNOTSUPP;
 +
        assoc_data = kzalloc(size, GFP_KERNEL);
        if (!assoc_data)
                return -ENOMEM;
diff --combined net/mac80211/tx.c
index 1be8c9d83d6ae40f3ab0f981bc1ce6b2e5584863,13249e97a06929bc6d85fb3d0ace86ea7ddcb529..8d4051e4c9f6fa65e9178fdaadbb8c6c3fe26193
@@@ -576,51 -576,6 +576,51 @@@ ieee80211_tx_h_check_control_port_proto
        return TX_CONTINUE;
  }
  
 +static struct ieee80211_key *
 +ieee80211_select_link_key(struct ieee80211_tx_data *tx)
 +{
 +      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
 +      enum {
 +              USE_NONE,
 +              USE_MGMT_KEY,
 +              USE_MCAST_KEY,
 +      } which_key = USE_NONE;
 +      struct ieee80211_link_data *link;
 +      unsigned int link_id;
 +
 +      if (ieee80211_is_group_privacy_action(tx->skb))
 +              which_key = USE_MCAST_KEY;
 +      else if (ieee80211_is_mgmt(hdr->frame_control) &&
 +               is_multicast_ether_addr(hdr->addr1) &&
 +               ieee80211_is_robust_mgmt_frame(tx->skb))
 +              which_key = USE_MGMT_KEY;
 +      else if (is_multicast_ether_addr(hdr->addr1))
 +              which_key = USE_MCAST_KEY;
 +      else
 +              return NULL;
 +
 +      link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
 +      if (link_id == IEEE80211_LINK_UNSPECIFIED) {
 +              link = &tx->sdata->deflink;
 +      } else {
 +              link = rcu_dereference(tx->sdata->link[link_id]);
 +              if (!link)
 +                      return NULL;
 +      }
 +
 +      switch (which_key) {
 +      case USE_NONE:
 +              break;
 +      case USE_MGMT_KEY:
 +              return rcu_dereference(link->default_mgmt_key);
 +      case USE_MCAST_KEY:
 +              return rcu_dereference(link->default_multicast_key);
 +      }
 +
 +      return NULL;
 +}
 +
  static ieee80211_tx_result debug_noinline
  ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
  {
        if (tx->sta &&
            (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
                tx->key = key;
 -      else if (ieee80211_is_group_privacy_action(tx->skb) &&
 -              (key = rcu_dereference(tx->sdata->deflink.default_multicast_key)))
 -              tx->key = key;
 -      else if (ieee80211_is_mgmt(hdr->frame_control) &&
 -               is_multicast_ether_addr(hdr->addr1) &&
 -               ieee80211_is_robust_mgmt_frame(tx->skb) &&
 -               (key = rcu_dereference(tx->sdata->deflink.default_mgmt_key)))
 -              tx->key = key;
 -      else if (is_multicast_ether_addr(hdr->addr1) &&
 -               (key = rcu_dereference(tx->sdata->deflink.default_multicast_key)))
 +      else if ((key = ieee80211_select_link_key(tx)))
                tx->key = key;
        else if (!is_multicast_ether_addr(hdr->addr1) &&
                 (key = rcu_dereference(tx->sdata->default_unicast_key)))
@@@ -2676,8 -2640,7 +2676,8 @@@ static struct sk_buff *ieee80211_build_
                                goto free;
                        }
                        memcpy(hdr.addr2, link->conf->addr, ETH_ALEN);
 -              } else if (link_id == IEEE80211_LINK_UNSPECIFIED) {
 +              } else if (link_id == IEEE80211_LINK_UNSPECIFIED ||
 +                         (sta && sta->sta.mlo)) {
                        memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
                } else {
                        struct ieee80211_bss_conf *conf;
@@@ -3772,8 -3735,8 +3772,8 @@@ begin
                             !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) &&
                             (!(info->control.flags &
                                IEEE80211_TX_CTRL_PORT_CTRL_PROTO) ||
 -                            !ether_addr_equal(tx.sdata->vif.addr,
 -                                              hdr->addr2)))) {
 +                            !ieee80211_is_our_addr(tx.sdata, hdr->addr2,
 +                                                   NULL)))) {
                        I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
                        ieee80211_free_txskb(&local->hw, skb);
                        goto begin;
@@@ -5098,8 -5061,6 +5098,8 @@@ ieee80211_beacon_get_finish(struct ieee
        rate_control_get_rate(sdata, NULL, &txrc);
  
        info->control.vif = vif;
 +      info->control.flags |= u32_encode_bits(link->link_id,
 +                                             IEEE80211_TX_CTRL_MLO_LINK);
        info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
                       IEEE80211_TX_CTL_ASSIGN_SEQ |
                       IEEE80211_TX_CTL_FIRST_FRAGMENT;
@@@ -5917,6 -5878,9 +5917,9 @@@ int ieee80211_tx_control_port(struct wi
        skb_reset_network_header(skb);
        skb_reset_mac_header(skb);
  
+       if (local->hw.queues < IEEE80211_NUM_ACS)
+               goto start_xmit;
        /* update QoS header to prioritize control port frames if possible,
         * priorization also happens for control port frames send over
         * AF_PACKET
        }
        rcu_read_unlock();
  
+ start_xmit:
        /* mutex lock is only needed for incrementing the cookie counter */
        mutex_lock(&local->mtx);
  
diff --combined net/mac80211/util.c
index 3359ab332d7d0a6a63cf70496168b3ce8e109440,efcefb2dd8826d1a3d5af8af883a63007f938145..38941ee272cd3767b0565130a0081a9cd422ed1e
@@@ -301,14 -301,14 +301,14 @@@ static void __ieee80211_wake_txqs(struc
        local_bh_disable();
        spin_lock(&fq->lock);
  
+       sdata->vif.txqs_stopped[ac] = false;
        if (!test_bit(SDATA_STATE_RUNNING, &sdata->state))
                goto out;
  
        if (sdata->vif.type == NL80211_IFTYPE_AP)
                ps = &sdata->bss->ps;
  
-       sdata->vif.txqs_stopped[ac] = false;
        list_for_each_entry_rcu(sta, &local->sta_list, list) {
                if (sdata != sta->sdata)
                        continue;
@@@ -954,11 -954,9 +954,11 @@@ void ieee80211_queue_delayed_work(struc
  }
  EXPORT_SYMBOL(ieee80211_queue_delayed_work);
  
 -static void ieee80211_parse_extension_element(u32 *crc,
 -                                            const struct element *elem,
 -                                            struct ieee802_11_elems *elems)
 +static void
 +ieee80211_parse_extension_element(u32 *crc,
 +                                const struct element *elem,
 +                                struct ieee802_11_elems *elems,
 +                                struct ieee80211_elems_parse_params *params)
  {
        const void *data = elem->data + 1;
        u8 len;
                break;
        case WLAN_EID_EXT_EHT_CAPABILITY:
                if (ieee80211_eht_capa_size_ok(elems->he_cap,
 -                                             data, len)) {
 +                                             data, len,
 +                                             params->from_ap)) {
                        elems->eht_cap = data;
                        elems->eht_cap_len = len;
                }
@@@ -1388,7 -1385,7 +1388,7 @@@ _ieee802_11_parse_elems_full(struct iee
                case WLAN_EID_EXTENSION:
                        ieee80211_parse_extension_element(calc_crc ?
                                                                &crc : NULL,
 -                                                        elem, elems);
 +                                                        elem, elems, params);
                        break;
                case WLAN_EID_S1G_CAPABILITIES:
                        if (elen >= sizeof(*elems->s1g_capab))
@@@ -2028,8 -2025,7 +2028,8 @@@ static int ieee80211_build_preq_ies_ban
            cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band),
                                         IEEE80211_CHAN_NO_HE |
                                         IEEE80211_CHAN_NO_EHT)) {
 -              pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end);
 +              pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end,
 +                                               sdata->vif.type == NL80211_IFTYPE_AP);
                if (!pos)
                        goto out_err;
        }
@@@ -2530,6 -2526,7 +2530,6 @@@ int ieee80211_reconfig(struct ieee80211
                        if (link)
                                ieee80211_assign_chanctx(local, sdata, link);
                }
 -              sdata_unlock(sdata);
  
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_AP_VLAN:
                                            &sdata->deflink.tx_conf[i]);
                        break;
                }
 +              sdata_unlock(sdata);
  
                /* common change flags for all interface types */
                changed = BSS_CHANGED_ERP_CTS_PROT |
        }
  
        /* APs are now beaconing, add back stations */
 -      mutex_lock(&local->sta_mtx);
 -      list_for_each_entry(sta, &local->sta_list, list) {
 -              enum ieee80211_sta_state state;
 -
 -              if (!sta->uploaded)
 -                      continue;
 -
 -              if (sta->sdata->vif.type != NL80211_IFTYPE_AP &&
 -                  sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
 +      list_for_each_entry(sdata, &local->interfaces, list) {
 +              if (!ieee80211_sdata_running(sdata))
                        continue;
  
 -              for (state = IEEE80211_STA_NOTEXIST;
 -                   state < sta->sta_state; state++)
 -                      WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
 -                                            state + 1));
 +              sdata_lock(sdata);
 +              switch (sdata->vif.type) {
 +              case NL80211_IFTYPE_AP_VLAN:
 +              case NL80211_IFTYPE_AP:
 +                      ieee80211_reconfig_stations(sdata);
 +                      break;
 +              default:
 +                      break;
 +              }
 +              sdata_unlock(sdata);
        }
 -      mutex_unlock(&local->sta_mtx);
  
        /* add back keys */
        list_for_each_entry(sdata, &local->interfaces, list)
@@@ -3082,7 -3080,6 +3082,7 @@@ end
  }
  
  void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
 +                                  enum ieee80211_smps_mode smps_mode,
                                    struct sk_buff *skb)
  {
        struct ieee80211_supported_band *sband;
        cap = le16_to_cpu(iftd->he_6ghz_capa.capa);
        cap &= ~IEEE80211_HE_6GHZ_CAP_SM_PS;
  
 -      switch (sdata->deflink.smps_mode) {
 +      switch (smps_mode) {
        case IEEE80211_SMPS_AUTOMATIC:
        case IEEE80211_SMPS_NUM_MODES:
                WARN_ON(1);
@@@ -3510,7 -3507,8 +3510,7 @@@ bool ieee80211_chandef_vht_oper(struct 
        return true;
  }
  
 -void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
 -                              const struct ieee80211_eht_operation *eht_oper,
 +void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
                                bool support_160, bool support_320,
                                struct cfg80211_chan_def *chandef)
  {
@@@ -3686,7 -3684,7 +3686,7 @@@ bool ieee80211_chandef_he_6ghz_oper(str
                support_320 =
                        eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
  
 -              ieee80211_chandef_eht_oper(sdata, eht_oper, support_160,
 +              ieee80211_chandef_eht_oper(eht_oper, support_160,
                                           support_320, &he_chandef);
        }
  
@@@ -4772,7 -4770,6 +4772,7 @@@ u8 ieee80211_ie_len_eht_cap(struct ieee
        const struct ieee80211_sta_he_cap *he_cap;
        const struct ieee80211_sta_eht_cap *eht_cap;
        struct ieee80211_supported_band *sband;
 +      bool is_ap;
        u8 n;
  
        sband = ieee80211_get_sband(sdata);
        if (!he_cap || !eht_cap)
                return 0;
  
 +      is_ap = iftype == NL80211_IFTYPE_AP ||
 +              iftype == NL80211_IFTYPE_P2P_GO;
 +
        n = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
 -                                     &eht_cap->eht_cap_elem);
 +                                     &eht_cap->eht_cap_elem,
 +                                     is_ap);
        return 2 + 1 +
               sizeof(he_cap->he_cap_elem) + n +
               ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
  u8 *ieee80211_ie_build_eht_cap(u8 *pos,
                               const struct ieee80211_sta_he_cap *he_cap,
                               const struct ieee80211_sta_eht_cap *eht_cap,
 -                             u8 *end)
 +                             u8 *end,
 +                             bool for_ap)
  {
        u8 mcs_nss_len, ppet_len;
        u8 ie_len;
                return orig_pos;
  
        mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
 -                                               &eht_cap->eht_cap_elem);
 +                                               &eht_cap->eht_cap_elem,
 +                                               for_ap);
        ppet_len = ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
                                          eht_cap->eht_cap_elem.phy_cap_info);
  
diff --combined net/mptcp/protocol.c
index 16c3a6fc347fd4acb67a10c468e5ae73af98c966,f8897a70c11d48d1787ba2fe48704fcd6ed97215..760404b15cd0442bf8cb069a4e583de63ec897aa
@@@ -1544,9 -1544,8 +1544,9 @@@ void __mptcp_push_pending(struct sock *
        struct mptcp_sendmsg_info info = {
                                .flags = flags,
        };
 +      bool do_check_data_fin = false;
        struct mptcp_data_frag *dfrag;
 -      int len, copied = 0;
 +      int len;
  
        while ((dfrag = mptcp_send_head(sk))) {
                info.sent = dfrag->already_sent;
                                goto out;
                        }
  
 +                      do_check_data_fin = true;
                        info.sent += ret;
 -                      copied += ret;
                        len -= ret;
  
                        mptcp_update_post_push(msk, dfrag, ret);
@@@ -1598,7 -1597,7 +1598,7 @@@ out
        /* ensure the rtx timer is running */
        if (!mptcp_timer_pending(sk))
                mptcp_reset_timer(sk);
 -      if (copied)
 +      if (do_check_data_fin)
                __mptcp_check_send_data_fin(sk);
  }
  
@@@ -1677,7 -1676,6 +1677,7 @@@ static int mptcp_sendmsg(struct sock *s
  {
        struct mptcp_sock *msk = mptcp_sk(sk);
        struct page_frag *pfrag;
 +      struct socket *ssock;
        size_t copied = 0;
        int ret = 0;
        long timeo;
  
        lock_sock(sk);
  
 +      ssock = __mptcp_nmpc_socket(msk);
 +      if (unlikely(ssock && inet_sk(ssock->sk)->defer_connect)) {
 +              struct sock *ssk = ssock->sk;
 +              int copied_syn = 0;
 +
 +              lock_sock(ssk);
 +
 +              ret = tcp_sendmsg_fastopen(ssk, msg, &copied_syn, len, NULL);
 +              copied += copied_syn;
 +              if (ret == -EINPROGRESS && copied_syn > 0) {
 +                      /* reflect the new state on the MPTCP socket */
 +                      inet_sk_state_store(sk, inet_sk_state_load(ssk));
 +                      release_sock(ssk);
 +                      goto out;
 +              } else if (ret) {
 +                      release_sock(ssk);
 +                      goto out;
 +              }
 +              release_sock(ssk);
 +      }
 +
        timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
  
        if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
@@@ -2386,7 -2363,7 +2386,7 @@@ static void __mptcp_close_subflow(struc
  
        might_sleep();
  
 -      list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
 +      mptcp_for_each_subflow_safe(msk, subflow, tmp) {
                struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
  
                if (inet_sk_state_load(ssk) != TCP_CLOSE)
@@@ -2429,7 -2406,7 +2429,7 @@@ static void mptcp_check_fastclose(struc
  
        mptcp_token_destroy(msk);
  
 -      list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
 +      mptcp_for_each_subflow_safe(msk, subflow, tmp) {
                struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
                bool slow;
  
@@@ -2685,7 -2662,7 +2685,7 @@@ static void __mptcp_clear_xmit(struct s
                dfrag_clear(sk, dfrag);
  }
  
static void mptcp_cancel_work(struct sock *sk)
+ void mptcp_cancel_work(struct sock *sk)
  {
        struct mptcp_sock *msk = mptcp_sk(sk);
  
@@@ -2825,13 -2802,12 +2825,12 @@@ static void __mptcp_destroy_sock(struc
        sock_put(sk);
  }
  
static void mptcp_close(struct sock *sk, long timeout)
bool __mptcp_close(struct sock *sk, long timeout)
  {
        struct mptcp_subflow_context *subflow;
        struct mptcp_sock *msk = mptcp_sk(sk);
        bool do_cancel_work = false;
  
-       lock_sock(sk);
        sk->sk_shutdown = SHUTDOWN_MASK;
  
        if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
@@@ -2873,6 -2849,17 +2872,17 @@@ cleanup
        } else {
                mptcp_reset_timeout(msk, 0);
        }
+       return do_cancel_work;
+ }
+ static void mptcp_close(struct sock *sk, long timeout)
+ {
+       bool do_cancel_work;
+       lock_sock(sk);
+       do_cancel_work = __mptcp_close(sk, timeout);
        release_sock(sk);
        if (do_cancel_work)
                mptcp_cancel_work(sk);
@@@ -3076,7 -3063,7 +3086,7 @@@ void mptcp_destroy_common(struct mptcp_
        __mptcp_clear_xmit(sk);
  
        /* join list will be eventually flushed (with rst) at sock lock release time */
 -      list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node)
 +      mptcp_for_each_subflow_safe(msk, subflow, tmp)
                __mptcp_close_ssk(sk, mptcp_subflow_tcp_sock(subflow), subflow, flags);
  
        /* move to sk_receive_queue, sk_stream_kill_queues will purge it */
@@@ -3548,7 -3535,6 +3558,7 @@@ static int mptcp_stream_connect(struct 
  
  do_connect:
        err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
 +      inet_sk(sock->sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
        sock->state = ssock->state;
  
        /* on successful connect, the msk state will be moved to established by
@@@ -3699,9 -3685,6 +3709,9 @@@ static __poll_t mptcp_poll(struct file 
        if (state != TCP_SYN_SENT && state != TCP_SYN_RECV) {
                mask |= mptcp_check_readable(msk);
                mask |= mptcp_check_writeable(msk);
 +      } else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
 +              /* cf tcp_poll() note about TFO */
 +              mask |= EPOLLOUT | EPOLLWRNORM;
        }
        if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
                mask |= EPOLLHUP;
diff --combined net/mptcp/protocol.h
index c1b12318535dad33785ffe97052f3b246504e921,8f372b8f059c6f9eb46b92acdad4da51cd72921e..c0b5b4628f65018d02ffb4dcdd1f632828e1865c
@@@ -314,8 -314,6 +314,8 @@@ struct mptcp_sock 
  
  #define mptcp_for_each_subflow(__msk, __subflow)                      \
        list_for_each_entry(__subflow, &((__msk)->conn_list), node)
 +#define mptcp_for_each_subflow_safe(__msk, __subflow, __tmp)                  \
 +      list_for_each_entry_safe(__subflow, __tmp, &((__msk)->conn_list), node)
  
  static inline void msk_owned_by_me(const struct mptcp_sock *msk)
  {
@@@ -614,6 -612,8 +614,8 @@@ void mptcp_subflow_reset(struct sock *s
  void mptcp_subflow_queue_clean(struct sock *ssk);
  void mptcp_sock_graft(struct sock *sk, struct socket *parent);
  struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
+ bool __mptcp_close(struct sock *sk, long timeout);
+ void mptcp_cancel_work(struct sock *sk);
  
  bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
                           const struct mptcp_addr_info *b, bool use_port);
diff --combined net/sched/act_ct.c
index 9d19710835b00f5229e9d22beeabc8304a79fc16,5950974ae8f643852cc2c2535310dabe1e00fee8..b38d91d6b249b475ffc10303ad5e2c49f9497e00
@@@ -649,6 -649,7 +649,6 @@@ static void tcf_ct_flow_tables_uninit(v
  }
  
  static struct tc_action_ops act_ct_ops;
 -static unsigned int ct_net_id;
  
  struct tc_ct_action_net {
        struct tc_action_net tn; /* Must be first */
@@@ -696,6 -697,7 +696,6 @@@ drop_ct
  static int tcf_ct_skb_network_trim(struct sk_buff *skb, int family)
  {
        unsigned int len;
 -      int err;
  
        switch (family) {
        case NFPROTO_IPV4:
                len = skb->len;
        }
  
 -      err = pskb_trim_rcsum(skb, len);
 -
 -      return err;
 +      return pskb_trim_rcsum(skb, len);
  }
  
  static u8 tcf_ct_skb_nf_family(struct sk_buff *skb)
@@@ -1251,7 -1255,7 +1251,7 @@@ static int tcf_ct_fill_params(struct ne
                              struct nlattr **tb,
                              struct netlink_ext_ack *extack)
  {
 -      struct tc_ct_action_net *tn = net_generic(net, ct_net_id);
 +      struct tc_ct_action_net *tn = net_generic(net, act_ct_ops.net_id);
        struct nf_conntrack_zone zone;
        struct nf_conn *tmpl;
        int err;
@@@ -1326,7 -1330,7 +1326,7 @@@ static int tcf_ct_init(struct net *net
                       struct tcf_proto *tp, u32 flags,
                       struct netlink_ext_ack *extack)
  {
 -      struct tc_action_net *tn = net_generic(net, ct_net_id);
 +      struct tc_action_net *tn = net_generic(net, act_ct_ops.net_id);
        bool bind = flags & TCA_ACT_FLAGS_BIND;
        struct tcf_ct_params *params = NULL;
        struct nlattr *tb[TCA_CT_MAX + 1];
  
        err = tcf_ct_flow_table_get(net, params);
        if (err)
-               goto cleanup;
+               goto cleanup_params;
  
        spin_lock_bh(&c->tcf_lock);
        goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
  
        return res;
  
+ cleanup_params:
+       if (params->tmpl)
+               nf_ct_put(params->tmpl);
  cleanup:
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
@@@ -1554,6 -1561,23 +1557,6 @@@ nla_put_failure
        return -1;
  }
  
 -static int tcf_ct_walker(struct net *net, struct sk_buff *skb,
 -                       struct netlink_callback *cb, int type,
 -                       const struct tc_action_ops *ops,
 -                       struct netlink_ext_ack *extack)
 -{
 -      struct tc_action_net *tn = net_generic(net, ct_net_id);
 -
 -      return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 -}
 -
 -static int tcf_ct_search(struct net *net, struct tc_action **a, u32 index)
 -{
 -      struct tc_action_net *tn = net_generic(net, ct_net_id);
 -
 -      return tcf_idr_search(tn, a, index);
 -}
 -
  static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,
                             u64 drops, u64 lastuse, bool hw)
  {
@@@ -1592,6 -1616,8 +1595,6 @@@ static struct tc_action_ops act_ct_ops 
        .dump           =       tcf_ct_dump,
        .init           =       tcf_ct_init,
        .cleanup        =       tcf_ct_cleanup,
 -      .walk           =       tcf_ct_walker,
 -      .lookup         =       tcf_ct_search,
        .stats_update   =       tcf_stats_update,
        .offload_act_setup =    tcf_ct_offload_act_setup,
        .size           =       sizeof(struct tcf_ct),
  static __net_init int ct_init_net(struct net *net)
  {
        unsigned int n_bits = sizeof_field(struct tcf_ct_params, labels) * 8;
 -      struct tc_ct_action_net *tn = net_generic(net, ct_net_id);
 +      struct tc_ct_action_net *tn = net_generic(net, act_ct_ops.net_id);
  
        if (nf_connlabels_get(net, n_bits - 1)) {
                tn->labels = false;
@@@ -1618,20 -1644,20 +1621,20 @@@ static void __net_exit ct_exit_net(stru
  
        rtnl_lock();
        list_for_each_entry(net, net_list, exit_list) {
 -              struct tc_ct_action_net *tn = net_generic(net, ct_net_id);
 +              struct tc_ct_action_net *tn = net_generic(net, act_ct_ops.net_id);
  
                if (tn->labels)
                        nf_connlabels_put(net);
        }
        rtnl_unlock();
  
 -      tc_action_net_exit(net_list, ct_net_id);
 +      tc_action_net_exit(net_list, act_ct_ops.net_id);
  }
  
  static struct pernet_operations ct_net_ops = {
        .init = ct_init_net,
        .exit_batch = ct_exit_net,
 -      .id   = &ct_net_id,
 +      .id   = &act_ct_ops.net_id,
        .size = sizeof(struct tc_ct_action_net),
  };
  
diff --combined net/wireless/util.c
index 0b28d00ba8f55f146f347a4d8e5b75bc43ccd44b,775836f6785ab5142d698ef1297a9ed8ae95ab3d..01493568a21dfe07d36377c2e4a1ca7c602ac037
@@@ -935,13 -935,13 +935,13 @@@ void cfg80211_upload_connect_keys(struc
        for (i = 0; i < CFG80211_MAX_WEP_KEYS; i++) {
                if (!wdev->connect_keys->params[i].cipher)
                        continue;
 -              if (rdev_add_key(rdev, dev, i, false, NULL,
 +              if (rdev_add_key(rdev, dev, -1, i, false, NULL,
                                 &wdev->connect_keys->params[i])) {
                        netdev_err(dev, "failed to set key %d\n", i);
                        continue;
                }
                if (wdev->connect_keys->def == i &&
 -                  rdev_set_default_key(rdev, dev, i, true, true)) {
 +                  rdev_set_default_key(rdev, dev, -1, i, true, true)) {
                        netdev_err(dev, "failed to set defkey %d\n", i);
                        continue;
                }
@@@ -1361,7 -1361,7 +1361,7 @@@ static u32 cfg80211_calculate_bitrate_h
                 25599, /*  4.166666... */
                 17067, /*  2.777777... */
                 12801, /*  2.083333... */
-                11769, /*  1.851851... */
+                11377, /*  1.851725... */
                 10239, /*  1.666666... */
                  8532, /*  1.388888... */
                  7680, /*  1.250000... */
@@@ -1444,7 -1444,7 +1444,7 @@@ static u32 cfg80211_calculate_bitrate_e
                 25599, /*  4.166666... */
                 17067, /*  2.777777... */
                 12801, /*  2.083333... */
-                11769, /*  1.851851... */
+                11377, /*  1.851725... */
                 10239, /*  1.666666... */
                  8532, /*  1.388888... */
                  7680, /*  1.250000... */