commit:     387de4a9273f6e5a4bc69bbc9bcf5d4f4bdce3ea
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Fri Aug  9 17:47:28 2019 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Fri Aug  9 17:47:28 2019 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=387de4a9
Linux patch 5.2.8

Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>

 0000_README            |    4 +
 1007_linux-5.2.8.patch | 2838 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 2842 insertions(+)

diff --git a/0000_README b/0000_README
index 139084e..6e8d29d 100644
--- a/0000_README
+++ b/0000_README
@@ -71,6 +71,10 @@ Patch:  1006_linux-5.2.7.patch
 From:   https://www.kernel.org
 Desc:   Linux 5.2.7
 
+Patch:  1007_linux-5.2.8.patch
+From:   https://www.kernel.org
+Desc:   Linux 5.2.8
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1007_linux-5.2.8.patch b/1007_linux-5.2.8.patch
new file mode 100644
index 0000000..25fd638
--- /dev/null
+++ b/1007_linux-5.2.8.patch
@@ -0,0 +1,2838 @@
+diff --git a/Makefile b/Makefile
+index 359a6b49e576..bad87c4c8117 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 2
+-SUBLEVEL = 7
++SUBLEVEL = 8
+ EXTRAVERSION =
+ NAME = Bobtail Squid
+ 
+diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
+index 302cf0ba1600..8c7a996d1f16 100644
+--- a/drivers/atm/iphase.c
++++ b/drivers/atm/iphase.c
+@@ -63,6 +63,7 @@
+ #include <asm/byteorder.h>  
+ #include <linux/vmalloc.h>
+ #include <linux/jiffies.h>
++#include <linux/nospec.h>
+ #include "iphase.h"             
+ #include "suni.h"               
+ #define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
+@@ -2760,8 +2761,11 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int 
cmd, void __user *arg)
+    }
+    if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT; 
+    board = ia_cmds.status;
+-   if ((board < 0) || (board > iadev_count))
+-         board = 0;    
++
++      if ((board < 0) || (board > iadev_count))
++              board = 0;
++      board = array_index_nospec(board, iadev_count + 1);
++
+    iadev = ia_dev[board];
+    switch (ia_cmds.cmd) {
+    case MEMDUMP:
+diff --git a/drivers/gpu/drm/i915/intel_bios.c 
b/drivers/gpu/drm/i915/intel_bios.c
+index 1dc8d03ff127..ee6fa75d65a2 100644
+--- a/drivers/gpu/drm/i915/intel_bios.c
++++ b/drivers/gpu/drm/i915/intel_bios.c
+@@ -762,7 +762,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct 
bdb_header *bdb)
+       }
+ 
+       if (bdb->version >= 226) {
+-              u32 wakeup_time = psr_table->psr2_tp2_tp3_wakeup_time;
++              u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
+ 
+               wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
+               switch (wakeup_time) {
+diff --git a/drivers/gpu/drm/i915/intel_vbt_defs.h 
b/drivers/gpu/drm/i915/intel_vbt_defs.h
+index fdbbb9a53804..796c070bbe6f 100644
+--- a/drivers/gpu/drm/i915/intel_vbt_defs.h
++++ b/drivers/gpu/drm/i915/intel_vbt_defs.h
+@@ -772,13 +772,13 @@ struct psr_table {
+       /* TP wake up time in multiple of 100 */
+       u16 tp1_wakeup_time;
+       u16 tp2_tp3_wakeup_time;
+-
+-      /* PSR2 TP2/TP3 wakeup time for 16 panels */
+-      u32 psr2_tp2_tp3_wakeup_time;
+ } __packed;
+ 
+ struct bdb_psr {
+       struct psr_table psr_table[16];
++
++      /* PSR2 TP2/TP3 wakeup time for 16 panels */
++      u32 psr2_tp2_tp3_wakeup_time;
+ } __packed;
+ 
+ /*
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index bfc584ada4eb..34a812025b94 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -568,6 +568,7 @@
+ #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
+ #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE                0x134a
+ #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A   0x094a
++#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641   0x0641
+ 
+ #define USB_VENDOR_ID_HUION           0x256c
+ #define USB_DEVICE_ID_HUION_TABLET    0x006e
+diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
+index 1549c7a2f04c..5b669f7d653f 100644
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -91,6 +91,7 @@ static const struct hid_device_id hid_quirks[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_HP, 
USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HP, 
USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HP, 
USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
++      { HID_USB_DEVICE(USB_VENDOR_ID_HP, 
USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), 
HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, 
USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), 
HID_QUIRK_MULTI_INPUT },
+diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
+index 489436503e49..926c597f5f46 100644
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -533,14 +533,14 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
+                */
+               buttons = (data[4] << 1) | (data[3] & 0x01);
+       } else if (features->type == CINTIQ_COMPANION_2) {
+-              /* d-pad right  -> data[4] & 0x10
+-               * d-pad up     -> data[4] & 0x20
+-               * d-pad left   -> data[4] & 0x40
+-               * d-pad down   -> data[4] & 0x80
+-               * d-pad center -> data[3] & 0x01
++              /* d-pad right  -> data[2] & 0x10
++               * d-pad up     -> data[2] & 0x20
++               * d-pad left   -> data[2] & 0x40
++               * d-pad down   -> data[2] & 0x80
++               * d-pad center -> data[1] & 0x01
+                */
+               buttons = ((data[2] >> 4) << 7) |
+-                        ((data[1] & 0x04) << 6) |
++                        ((data[1] & 0x04) << 4) |
+                         ((data[2] & 0x0F) << 2) |
+                         (data[1] & 0x03);
+       } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c 
b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+index bf39fc83d577..4039a9599d79 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+@@ -1934,8 +1934,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct 
sk_buff *skb,
+       }
+ 
+       /* select a non-FCoE queue */
+-      return netdev_pick_tx(dev, skb, NULL) %
+-             (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
++      return netdev_pick_tx(dev, skb, NULL) % (BNX2X_NUM_ETH_QUEUES(bp));
+ }
+ 
+ void bnx2x_set_num_queues(struct bnx2x *bp)
+diff --git a/drivers/net/ethernet/marvell/mvmdio.c 
b/drivers/net/ethernet/marvell/mvmdio.c
+index ee7857298361..aca878a3f81f 100644
+--- a/drivers/net/ethernet/marvell/mvmdio.c
++++ b/drivers/net/ethernet/marvell/mvmdio.c
+@@ -319,15 +319,31 @@ static int orion_mdio_probe(struct platform_device *pdev)
+ 
+       init_waitqueue_head(&dev->smi_busy_wait);
+ 
+-      for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+-              dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
+-              if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
++      if (pdev->dev.of_node) {
++              for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
++                      dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
++                      if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
++                              ret = -EPROBE_DEFER;
++                              goto out_clk;
++                      }
++                      if (IS_ERR(dev->clk[i]))
++                              break;
++                      clk_prepare_enable(dev->clk[i]);
++              }
++
++              if (!IS_ERR(of_clk_get(pdev->dev.of_node,
++                                     ARRAY_SIZE(dev->clk))))
++                      dev_warn(&pdev->dev,
++                               "unsupported number of clocks, limiting to the 
first "
++                               __stringify(ARRAY_SIZE(dev->clk)) "\n");
++      } else {
++              dev->clk[0] = clk_get(&pdev->dev, NULL);
++              if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
+                       ret = -EPROBE_DEFER;
+                       goto out_clk;
+               }
+-              if (IS_ERR(dev->clk[i]))
+-                      break;
+-              clk_prepare_enable(dev->clk[i]);
++              if (!IS_ERR(dev->clk[0]))
++                      clk_prepare_enable(dev->clk[0]);
+       }
+ 
+       dev->err_interrupt = platform_get_irq(pdev, 0);
+diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c 
b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+index d8e5241097a9..50ed1bdb632d 100644
+--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+@@ -3609,6 +3609,7 @@ static int mvpp2_set_mac_address(struct net_device *dev, 
void *p)
+ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
+ {
+       struct mvpp2_port *port = netdev_priv(dev);
++      bool running = netif_running(dev);
+       int err;
+ 
+       if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
+@@ -3617,40 +3618,24 @@ static int mvpp2_change_mtu(struct net_device *dev, 
int mtu)
+               mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
+       }
+ 
+-      if (!netif_running(dev)) {
+-              err = mvpp2_bm_update_mtu(dev, mtu);
+-              if (!err) {
+-                      port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
+-                      return 0;
+-              }
+-
+-              /* Reconfigure BM to the original MTU */
+-              err = mvpp2_bm_update_mtu(dev, dev->mtu);
+-              if (err)
+-                      goto log_error;
+-      }
+-
+-      mvpp2_stop_dev(port);
++      if (running)
++              mvpp2_stop_dev(port);
+ 
+       err = mvpp2_bm_update_mtu(dev, mtu);
+-      if (!err) {
++      if (err) {
++              netdev_err(dev, "failed to change MTU\n");
++              /* Reconfigure BM to the original MTU */
++              mvpp2_bm_update_mtu(dev, dev->mtu);
++      } else {
+               port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
+-              goto out_start;
+       }
+ 
+-      /* Reconfigure BM to the original MTU */
+-      err = mvpp2_bm_update_mtu(dev, dev->mtu);
+-      if (err)
+-              goto log_error;
+-
+-out_start:
+-      mvpp2_start_dev(port);
+-      mvpp2_egress_enable(port);
+-      mvpp2_ingress_enable(port);
++      if (running) {
++              mvpp2_start_dev(port);
++              mvpp2_egress_enable(port);
++              mvpp2_ingress_enable(port);
++      }
+ 
+-      return 0;
+-log_error:
+-      netdev_err(dev, "failed to change MTU\n");
+       return err;
+ }
+ 
+@@ -5609,9 +5594,6 @@ static int mvpp2_remove(struct platform_device *pdev)
+ 
+       mvpp2_dbgfs_cleanup(priv);
+ 
+-      flush_workqueue(priv->stats_queue);
+-      destroy_workqueue(priv->stats_queue);
+-
+       fwnode_for_each_available_child_node(fwnode, port_fwnode) {
+               if (priv->port_list[i]) {
+                       mutex_destroy(&priv->port_list[i]->gather_stats_lock);
+@@ -5620,6 +5602,8 @@ static int mvpp2_remove(struct platform_device *pdev)
+               i++;
+       }
+ 
++      destroy_workqueue(priv->stats_queue);
++
+       for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+               struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c 
b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
+index f6b1da99e6c2..ba5f46da1c5c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
+@@ -213,7 +213,7 @@ void mlx5_unregister_device(struct mlx5_core_dev *dev)
+       struct mlx5_interface *intf;
+ 
+       mutex_lock(&mlx5_intf_mutex);
+-      list_for_each_entry(intf, &intf_list, list)
++      list_for_each_entry_reverse(intf, &intf_list, list)
+               mlx5_remove_device(intf, priv);
+       list_del(&priv->dev_list);
+       mutex_unlock(&mlx5_intf_mutex);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+index d5e5afbdca6d..f777994f3005 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+@@ -78,9 +78,10 @@ static const u32 
mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
+ };
+ 
+ static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
+-                                   const u32 **arr, u32 *size)
++                                   const u32 **arr, u32 *size,
++                                   bool force_legacy)
+ {
+-      bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
++      bool ext = force_legacy ? false : MLX5_CAP_PCAM_FEATURE(mdev, 
ptys_extended_ethernet);
+ 
+       *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
+                     ARRAY_SIZE(mlx5e_link_speed);
+@@ -152,7 +153,8 @@ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool 
an_disable,
+                           sizeof(out), MLX5_REG_PTYS, 0, 1);
+ }
+ 
+-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
++u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
++                        bool force_legacy)
+ {
+       unsigned long temp = eth_proto_oper;
+       const u32 *table;
+@@ -160,7 +162,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 
eth_proto_oper)
+       u32 max_size;
+       int i;
+ 
+-      mlx5e_port_get_speed_arr(mdev, &table, &max_size);
++      mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
+       i = find_first_bit(&temp, max_size);
+       if (i < max_size)
+               speed = table[i];
+@@ -170,6 +172,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 
eth_proto_oper)
+ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
+ {
+       struct mlx5e_port_eth_proto eproto;
++      bool force_legacy = false;
+       bool ext;
+       int err;
+ 
+@@ -177,8 +180,13 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 
*speed)
+       err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
+       if (err)
+               goto out;
+-
+-      *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
++      if (ext && !eproto.admin) {
++              force_legacy = true;
++              err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
++              if (err)
++                      goto out;
++      }
++      *speed = mlx5e_port_ptys2speed(mdev, eproto.oper, force_legacy);
+       if (!(*speed))
+               err = -EINVAL;
+ 
+@@ -201,7 +209,7 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, 
u32 *speed)
+       if (err)
+               return err;
+ 
+-      mlx5e_port_get_speed_arr(mdev, &table, &max_size);
++      mlx5e_port_get_speed_arr(mdev, &table, &max_size, false);
+       for (i = 0; i < max_size; ++i)
+               if (eproto.cap & MLX5E_PROT_MASK(i))
+                       max_speed = max(max_speed, table[i]);
+@@ -210,14 +218,15 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, 
u32 *speed)
+       return 0;
+ }
+ 
+-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
++u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
++                             bool force_legacy)
+ {
+       u32 link_modes = 0;
+       const u32 *table;
+       u32 max_size;
+       int i;
+ 
+-      mlx5e_port_get_speed_arr(mdev, &table, &max_size);
++      mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
+       for (i = 0; i < max_size; ++i) {
+               if (table[i] == speed)
+                       link_modes |= MLX5E_PROT_MASK(i);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h 
b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+index 70f536ec51c4..4a7f4497692b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+@@ -48,10 +48,12 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev 
*dev, u8 *an_status,
+                                u8 *an_disable_cap, u8 *an_disable_admin);
+ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
+                          u32 proto_admin, bool ext);
+-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper);
++u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
++                        bool force_legacy);
+ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
+ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
+-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed);
++u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
++                             bool force_legacy);
+ 
+ int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
+ int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+index dd764e0471f2..f637d81f08bc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+@@ -764,7 +764,7 @@ static void ptys2ethtool_supported_advertised_port(struct 
ethtool_link_ksettings
+ }
+ 
+ static void get_speed_duplex(struct net_device *netdev,
+-                           u32 eth_proto_oper,
++                           u32 eth_proto_oper, bool force_legacy,
+                            struct ethtool_link_ksettings *link_ksettings)
+ {
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+@@ -774,7 +774,7 @@ static void get_speed_duplex(struct net_device *netdev,
+       if (!netif_carrier_ok(netdev))
+               goto out;
+ 
+-      speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
++      speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper, force_legacy);
+       if (!speed) {
+               speed = SPEED_UNKNOWN;
+               goto out;
+@@ -893,8 +893,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv 
*priv,
+       /* Fields: eth_proto_admin and ext_eth_proto_admin  are
+        * mutually exclusive. Hence try reading legacy advertising
+        * when extended advertising is zero.
+-       * admin_ext indicates how eth_proto_admin should be
+-       * interpreted
++       * admin_ext indicates which proto_admin (ext vs. legacy)
++       * should be read and interpreted
+        */
+       admin_ext = ext;
+       if (ext && !eth_proto_admin) {
+@@ -903,7 +903,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv 
*priv,
+               admin_ext = false;
+       }
+ 
+-      eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
++      eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, admin_ext,
+                                             eth_proto_oper);
+       eth_proto_lp        = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
+       an_disable_admin    = MLX5_GET(ptys_reg, out, an_disable_admin);
+@@ -918,7 +918,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv 
*priv,
+       get_supported(mdev, eth_proto_cap, link_ksettings);
+       get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
+                       admin_ext);
+-      get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
++      get_speed_duplex(priv->netdev, eth_proto_oper, !admin_ext,
++                       link_ksettings);
+ 
+       eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
+ 
+@@ -995,45 +996,69 @@ static u32 mlx5e_ethtool2ptys_ext_adver_link(const 
unsigned long *link_modes)
+       return ptys_modes;
+ }
+ 
++static bool ext_link_mode_requested(const unsigned long *adver)
++{
++#define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT 
ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
++      int size = __ETHTOOL_LINK_MODE_MASK_NBITS - 
MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT;
++      __ETHTOOL_DECLARE_LINK_MODE_MASK(modes);
++
++      bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size);
++      return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
++}
++
++static bool ext_speed_requested(u32 speed)
++{
++#define MLX5E_MAX_PTYS_LEGACY_SPEED 100000
++      return !!(speed > MLX5E_MAX_PTYS_LEGACY_SPEED);
++}
++
++static bool ext_requested(u8 autoneg, const unsigned long *adver, u32 speed)
++{
++      bool ext_link_mode = ext_link_mode_requested(adver);
++      bool ext_speed = ext_speed_requested(speed);
++
++      return  autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_speed;
++}
++
+ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
+                                    const struct ethtool_link_ksettings 
*link_ksettings)
+ {
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct mlx5e_port_eth_proto eproto;
++      const unsigned long *adver;
+       bool an_changes = false;
+       u8 an_disable_admin;
+       bool ext_supported;
+-      bool ext_requested;
+       u8 an_disable_cap;
+       bool an_disable;
+       u32 link_modes;
+       u8 an_status;
++      u8 autoneg;
+       u32 speed;
++      bool ext;
+       int err;
+ 
+       u32 (*ethtool2ptys_adver_func)(const unsigned long *adver);
+ 
+-#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)
++      adver = link_ksettings->link_modes.advertising;
++      autoneg = link_ksettings->base.autoneg;
++      speed = link_ksettings->base.speed;
+ 
+-      ext_requested = !!(link_ksettings->link_modes.advertising[0] >
+-                      MLX5E_PTYS_EXT ||
+-                      link_ksettings->link_modes.advertising[1]);
++      ext = ext_requested(autoneg, adver, speed),
+       ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+-      ext_requested &= ext_supported;
++      if (!ext_supported && ext)
++              return -EOPNOTSUPP;
+ 
+-      speed = link_ksettings->base.speed;
+-      ethtool2ptys_adver_func = ext_requested ?
+-                                mlx5e_ethtool2ptys_ext_adver_link :
++      ethtool2ptys_adver_func = ext ? mlx5e_ethtool2ptys_ext_adver_link :
+                                 mlx5e_ethtool2ptys_adver_link;
+-      err = mlx5_port_query_eth_proto(mdev, 1, ext_requested, &eproto);
++      err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
+       if (err) {
+               netdev_err(priv->netdev, "%s: query port eth proto failed: 
%d\n",
+                          __func__, err);
+               goto out;
+       }
+-      link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
+-              ethtool2ptys_adver_func(link_ksettings->link_modes.advertising) 
:
+-              mlx5e_port_speed2linkmodes(mdev, speed);
++      link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) 
:
++              mlx5e_port_speed2linkmodes(mdev, speed, !ext);
+ 
+       link_modes = link_modes & eproto.cap;
+       if (!link_modes) {
+@@ -1046,14 +1071,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv 
*priv,
+       mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap,
+                                   &an_disable_admin);
+ 
+-      an_disable = link_ksettings->base.autoneg == AUTONEG_DISABLE;
++      an_disable = autoneg == AUTONEG_DISABLE;
+       an_changes = ((!an_disable && an_disable_admin) ||
+                     (an_disable && !an_disable_admin));
+ 
+       if (!an_changes && link_modes == eproto.admin)
+               goto out;
+ 
+-      mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_requested);
++      mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
+       mlx5_toggle_port_link(mdev);
+ 
+ out:
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index a44c24280128..882d26b8095d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -340,12 +340,11 @@ static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq 
*rq, u16 wqe_ix)
+ 
+ static void mlx5e_init_frags_partition(struct mlx5e_rq *rq)
+ {
+-      struct mlx5e_wqe_frag_info next_frag, *prev;
++      struct mlx5e_wqe_frag_info next_frag = {};
++      struct mlx5e_wqe_frag_info *prev = NULL;
+       int i;
+ 
+       next_frag.di = &rq->wqe.di[0];
+-      next_frag.offset = 0;
+-      prev = NULL;
+ 
+       for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
+               struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index e40c60d1631f..ee95f96ead4e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -1210,13 +1210,13 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct 
mlx5e_tc_flow *flow)
+ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
+ {
+       struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
+-      u64 bytes, packets, lastuse = 0;
+       struct mlx5e_tc_flow *flow;
+       struct mlx5e_encap_entry *e;
+       struct mlx5_fc *counter;
+       struct neigh_table *tbl;
+       bool neigh_used = false;
+       struct neighbour *n;
++      u64 lastuse;
+ 
+       if (m_neigh->family == AF_INET)
+               tbl = &arp_tbl;
+@@ -1236,7 +1236,7 @@ void mlx5e_tc_update_neigh_used_value(struct 
mlx5e_neigh_hash_entry *nhe)
+                                           encaps[efi->index]);
+                       if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
+                               counter = mlx5e_tc_get_counter(flow);
+-                              mlx5_fc_query_cached(counter, &bytes, &packets, 
&lastuse);
++                              lastuse = mlx5_fc_query_lastuse(counter);
+                               if (time_after((unsigned long)lastuse, 
nhe->reported_lastuse)) {
+                                       neigh_used = true;
+                                       break;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h 
b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+index a08c3d09a50f..2664a05eee00 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+@@ -68,7 +68,7 @@ enum fs_flow_table_type {
+       FS_FT_SNIFFER_RX        = 0X5,
+       FS_FT_SNIFFER_TX        = 0X6,
+       FS_FT_RDMA_RX           = 0X7,
+-      FS_FT_MAX_TYPE = FS_FT_SNIFFER_TX,
++      FS_FT_MAX_TYPE = FS_FT_RDMA_RX,
+ };
+ 
+ enum fs_flow_table_op_mod {
+@@ -274,7 +274,8 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
+       (type == FS_FT_FDB) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :           
\
+       (type == FS_FT_SNIFFER_RX) ? MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) : 
        \
+       (type == FS_FT_SNIFFER_TX) ? MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) : 
        \
+-      (BUILD_BUG_ON_ZERO(FS_FT_SNIFFER_TX != FS_FT_MAX_TYPE))\
++      (type == FS_FT_RDMA_RX) ? MLX5_CAP_FLOWTABLE_RDMA_RX(mdev, cap) :       
        \
++      (BUILD_BUG_ON_ZERO(FS_FT_RDMA_RX != FS_FT_MAX_TYPE))\
+       )
+ 
+ #endif
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c 
b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+index c6c28f56aa29..add9db67028f 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+@@ -367,6 +367,11 @@ int mlx5_fc_query(struct mlx5_core_dev *dev, struct 
mlx5_fc *counter,
+ }
+ EXPORT_SYMBOL(mlx5_fc_query);
+ 
++u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter)
++{
++      return counter->cache.lastuse;
++}
++
+ void mlx5_fc_query_cached(struct mlx5_fc *counter,
+                         u64 *bytes, u64 *packets, u64 *lastuse)
+ {
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+index 23204356ad88..d51442e63aba 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+@@ -5989,7 +5989,7 @@ static int __init mlxsw_sp_module_init(void)
+       return 0;
+ 
+ err_sp2_pci_driver_register:
+-      mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
++      mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
+ err_sp1_pci_driver_register:
+       mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
+ err_sp2_core_driver_register:
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+index 1537f70bc26d..888ba4300bcc 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+@@ -437,8 +437,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
+                          MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
+ };
+ 
+-#define MLXSW_SP2_SB_PR_INGRESS_SIZE  38128752
+-#define MLXSW_SP2_SB_PR_EGRESS_SIZE   38128752
++#define MLXSW_SP2_SB_PR_INGRESS_SIZE  35297568
++#define MLXSW_SP2_SB_PR_EGRESS_SIZE   35297568
+ #define MLXSW_SP2_SB_PR_CPU_SIZE      (256 * 1000)
+ 
+ /* Order according to mlxsw_sp2_sb_pool_dess */
+diff --git a/drivers/net/ethernet/mscc/ocelot.c 
b/drivers/net/ethernet/mscc/ocelot.c
+index 02ad11e0b0d8..58e76e7cb0d6 100644
+--- a/drivers/net/ethernet/mscc/ocelot.c
++++ b/drivers/net/ethernet/mscc/ocelot.c
+@@ -1797,6 +1797,7 @@ EXPORT_SYMBOL(ocelot_init);
+ 
+ void ocelot_deinit(struct ocelot *ocelot)
+ {
++      cancel_delayed_work(&ocelot->stats_work);
+       destroy_workqueue(ocelot->stats_queue);
+       mutex_destroy(&ocelot->stats_lock);
+ }
+diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h 
b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
+index 4bf20d0651c4..90ad5694e2af 100644
+--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
++++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
+@@ -51,7 +51,7 @@ struct rmnet_map_dl_csum_trailer {
+ struct rmnet_map_ul_csum_header {
+       __be16 csum_start_offset;
+       u16 csum_insert_offset:14;
+-      u16 udp_ip4_ind:1;
++      u16 udp_ind:1;
+       u16 csum_enabled:1;
+ } __aligned(1);
+ 
+diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c 
b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+index 60189923737a..21d38167f961 100644
+--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
++++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+@@ -206,9 +206,9 @@ rmnet_map_ipv4_ul_csum_header(void *iphdr,
+       ul_header->csum_insert_offset = skb->csum_offset;
+       ul_header->csum_enabled = 1;
+       if (ip4h->protocol == IPPROTO_UDP)
+-              ul_header->udp_ip4_ind = 1;
++              ul_header->udp_ind = 1;
+       else
+-              ul_header->udp_ip4_ind = 0;
++              ul_header->udp_ind = 0;
+ 
+       /* Changing remaining fields to network order */
+       hdr++;
+@@ -239,6 +239,7 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
+                             struct rmnet_map_ul_csum_header *ul_header,
+                             struct sk_buff *skb)
+ {
++      struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
+       __be16 *hdr = (__be16 *)ul_header, offset;
+ 
+       offset = htons((__force u16)(skb_transport_header(skb) -
+@@ -246,7 +247,11 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
+       ul_header->csum_start_offset = offset;
+       ul_header->csum_insert_offset = skb->csum_offset;
+       ul_header->csum_enabled = 1;
+-      ul_header->udp_ip4_ind = 0;
++
++      if (ip6h->nexthdr == IPPROTO_UDP)
++              ul_header->udp_ind = 1;
++      else
++              ul_header->udp_ind = 0;
+ 
+       /* Changing remaining fields to network order */
+       hdr++;
+@@ -419,7 +424,7 @@ sw_csum:
+       ul_header->csum_start_offset = 0;
+       ul_header->csum_insert_offset = 0;
+       ul_header->csum_enabled = 0;
+-      ul_header->udp_ip4_ind = 0;
++      ul_header->udp_ind = 0;
+ 
+       priv->stats.csum_sw++;
+ }
+diff --git a/drivers/net/ethernet/realtek/r8169.c 
b/drivers/net/ethernet/realtek/r8169.c
+index 96637fcbe65d..36261b2959b4 100644
+--- a/drivers/net/ethernet/realtek/r8169.c
++++ b/drivers/net/ethernet/realtek/r8169.c
+@@ -7050,13 +7050,18 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
+ {
+       unsigned int flags;
+ 
+-      if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
++      switch (tp->mac_version) {
++      case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
+               rtl_unlock_config_regs(tp);
+               RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
+               rtl_lock_config_regs(tp);
++              /* fall through */
++      case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_24:
+               flags = PCI_IRQ_LEGACY;
+-      } else {
++              break;
++      default:
+               flags = PCI_IRQ_ALL_TYPES;
++              break;
+       }
+ 
+       return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
+diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
+index 3e5bc1fc3c46..c245a0f15066 100644
+--- a/drivers/net/ethernet/rocker/rocker_main.c
++++ b/drivers/net/ethernet/rocker/rocker_main.c
+@@ -2208,6 +2208,7 @@ static int rocker_router_fib_event(struct notifier_block 
*nb,
+ 
+                       if (fen_info->fi->fib_nh_is_v6) {
+                               NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway 
with IPv4 route is not supported");
++                              kfree(fib_work);
+                               return notifier_from_errno(-EINVAL);
+                       }
+               }
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 932e54e25b71..b14f46a57154 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -4374,8 +4374,9 @@ int stmmac_dvr_probe(struct device *device,
+                                      NAPI_POLL_WEIGHT);
+               }
+               if (queue < priv->plat->tx_queues_to_use) {
+-                      netif_napi_add(ndev, &ch->tx_napi, stmmac_napi_poll_tx,
+-                                     NAPI_POLL_WEIGHT);
++                      netif_tx_napi_add(ndev, &ch->tx_napi,
++                                        stmmac_napi_poll_tx,
++                                        NAPI_POLL_WEIGHT);
+               }
+       }
+ 
+diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
+index 3ffe46df249e..7c5265fd2b94 100644
+--- a/drivers/net/phy/fixed_phy.c
++++ b/drivers/net/phy/fixed_phy.c
+@@ -216,8 +216,10 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct 
device_node *np)
+       if (IS_ERR(gpiod)) {
+               if (PTR_ERR(gpiod) == -EPROBE_DEFER)
+                       return gpiod;
+-              pr_err("error getting GPIO for fixed link %pOF, proceed 
without\n",
+-                     fixed_link_node);
++
++              if (PTR_ERR(gpiod) != -ENOENT)
++                      pr_err("error getting GPIO for fixed link %pOF, proceed 
without\n",
++                             fixed_link_node);
+               gpiod = NULL;
+       }
+ 
+diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
+index 28676af97b42..645d354ffb48 100644
+--- a/drivers/net/phy/mscc.c
++++ b/drivers/net/phy/mscc.c
+@@ -2226,8 +2226,8 @@ static int vsc8514_probe(struct phy_device *phydev)
+       vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
+       vsc8531->hw_stats = vsc85xx_hw_stats;
+       vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
+-      vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
+-                                          sizeof(u64), GFP_KERNEL);
++      vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
++                                    sizeof(u64), GFP_KERNEL);
+       if (!vsc8531->stats)
+               return -ENOMEM;
+ 
+@@ -2251,8 +2251,8 @@ static int vsc8574_probe(struct phy_device *phydev)
+       vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
+       vsc8531->hw_stats = vsc8584_hw_stats;
+       vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
+-      vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
+-                                          sizeof(u64), GFP_KERNEL);
++      vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
++                                    sizeof(u64), GFP_KERNEL);
+       if (!vsc8531->stats)
+               return -ENOMEM;
+ 
+@@ -2281,8 +2281,8 @@ static int vsc8584_probe(struct phy_device *phydev)
+       vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
+       vsc8531->hw_stats = vsc8584_hw_stats;
+       vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
+-      vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
+-                                          sizeof(u64), GFP_KERNEL);
++      vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
++                                    sizeof(u64), GFP_KERNEL);
+       if (!vsc8531->stats)
+               return -ENOMEM;
+ 
+@@ -2311,8 +2311,8 @@ static int vsc85xx_probe(struct phy_device *phydev)
+       vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
+       vsc8531->hw_stats = vsc85xx_hw_stats;
+       vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
+-      vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
+-                                          sizeof(u64), GFP_KERNEL);
++      vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
++                                    sizeof(u64), GFP_KERNEL);
+       if (!vsc8531->stats)
+               return -ENOMEM;
+ 
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index a3f8740c6163..ffa402732aea 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -1730,6 +1730,12 @@ done:
+       phydev->link = status & BMSR_LSTATUS ? 1 : 0;
+       phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
+ 
++      /* Consider the case that autoneg was started and "aneg complete"
++       * bit has been reset, but "link up" bit not yet.
++       */
++      if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
++              phydev->link = 0;
++
+       return 0;
+ }
+ EXPORT_SYMBOL(genphy_update_link);
+diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
+index 4c0616ba314d..c45ee6e3fe01 100644
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -195,6 +195,8 @@ static int phylink_parse_fixedlink(struct phylink *pl,
+                              pl->supported, true);
+       linkmode_zero(pl->supported);
+       phylink_set(pl->supported, MII);
++      phylink_set(pl->supported, Pause);
++      phylink_set(pl->supported, Asym_Pause);
+       if (s) {
+               __set_bit(s->bit, pl->supported);
+       } else {
+@@ -912,10 +914,10 @@ void phylink_start(struct phylink *pl)
+ 
+       if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
+               mod_timer(&pl->link_poll, jiffies + HZ);
+-      if (pl->sfp_bus)
+-              sfp_upstream_start(pl->sfp_bus);
+       if (pl->phydev)
+               phy_start(pl->phydev);
++      if (pl->sfp_bus)
++              sfp_upstream_start(pl->sfp_bus);
+ }
+ EXPORT_SYMBOL_GPL(phylink_start);
+ 
+@@ -932,10 +934,10 @@ void phylink_stop(struct phylink *pl)
+ {
+       ASSERT_RTNL();
+ 
+-      if (pl->phydev)
+-              phy_stop(pl->phydev);
+       if (pl->sfp_bus)
+               sfp_upstream_stop(pl->sfp_bus);
++      if (pl->phydev)
++              phy_stop(pl->phydev);
+       if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
+               del_timer_sync(&pl->link_poll);
+ 
+diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
+index 1d902ecb4aa8..a44dd3c8af63 100644
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -1115,6 +1115,9 @@ static const struct proto_ops pppoe_ops = {
+       .recvmsg        = pppoe_recvmsg,
+       .mmap           = sock_no_mmap,
+       .ioctl          = pppox_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl   = pppox_compat_ioctl,
++#endif
+ };
+ 
+ static const struct pppox_proto pppoe_proto = {
+diff --git a/drivers/net/ppp/pppox.c b/drivers/net/ppp/pppox.c
+index 5ef422a43d70..08364f10a43f 100644
+--- a/drivers/net/ppp/pppox.c
++++ b/drivers/net/ppp/pppox.c
+@@ -17,6 +17,7 @@
+ #include <linux/string.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
++#include <linux/compat.h>
+ #include <linux/errno.h>
+ #include <linux/netdevice.h>
+ #include <linux/net.h>
+@@ -98,6 +99,18 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, 
unsigned long arg)
+ 
+ EXPORT_SYMBOL(pppox_ioctl);
+ 
++#ifdef CONFIG_COMPAT
++int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long 
arg)
++{
++      if (cmd == PPPOEIOCSFWD32)
++              cmd = PPPOEIOCSFWD;
++
++      return pppox_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
++}
++
++EXPORT_SYMBOL(pppox_compat_ioctl);
++#endif
++
+ static int pppox_create(struct net *net, struct socket *sock, int protocol,
+                       int kern)
+ {
+diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
+index a8e52c8e4128..734de7de03f7 100644
+--- a/drivers/net/ppp/pptp.c
++++ b/drivers/net/ppp/pptp.c
+@@ -623,6 +623,9 @@ static const struct proto_ops pptp_ops = {
+       .recvmsg    = sock_no_recvmsg,
+       .mmap       = sock_no_mmap,
+       .ioctl      = pppox_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl = pppox_compat_ioctl,
++#endif
+ };
+ 
+ static const struct pppox_proto pppox_pptp_proto = {
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index d7c55e0fa8f4..192ac47fd055 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1600,7 +1600,8 @@ static bool tun_can_build_skb(struct tun_struct *tun, 
struct tun_file *tfile,
+       return true;
+ }
+ 
+-static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char 
*buf,
++static struct sk_buff *__tun_build_skb(struct tun_file *tfile,
++                                     struct page_frag *alloc_frag, char *buf,
+                                      int buflen, int len, int pad)
+ {
+       struct sk_buff *skb = build_skb(buf, buflen);
+@@ -1610,6 +1611,7 @@ static struct sk_buff *__tun_build_skb(struct page_frag 
*alloc_frag, char *buf,
+ 
+       skb_reserve(skb, pad);
+       skb_put(skb, len);
++      skb_set_owner_w(skb, tfile->socket.sk);
+ 
+       get_page(alloc_frag->page);
+       alloc_frag->offset += buflen;
+@@ -1687,7 +1689,8 @@ static struct sk_buff *tun_build_skb(struct tun_struct 
*tun,
+        */
+       if (hdr->gso_type || !xdp_prog) {
+               *skb_xdp = 1;
+-              return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
++              return __tun_build_skb(tfile, alloc_frag, buf, buflen, len,
++                                     pad);
+       }
+ 
+       *skb_xdp = 0;
+@@ -1724,7 +1727,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct 
*tun,
+       rcu_read_unlock();
+       local_bh_enable();
+ 
+-      return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
++      return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad);
+ 
+ err_xdp:
+       put_page(alloc_frag->page);
+diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
+index e65d027b91fa..529be35ac178 100644
+--- a/drivers/nfc/nfcmrvl/main.c
++++ b/drivers/nfc/nfcmrvl/main.c
+@@ -244,7 +244,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
+       /* Reset possible fault of previous session */
+       clear_bit(NFCMRVL_PHY_ERROR, &priv->flags);
+ 
+-      if (priv->config.reset_n_io) {
++      if (gpio_is_valid(priv->config.reset_n_io)) {
+               nfc_info(priv->dev, "reset the chip\n");
+               gpio_set_value(priv->config.reset_n_io, 0);
+               usleep_range(5000, 10000);
+@@ -255,7 +255,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
+ 
+ void nfcmrvl_chip_halt(struct nfcmrvl_private *priv)
+ {
+-      if (priv->config.reset_n_io)
++      if (gpio_is_valid(priv->config.reset_n_io))
+               gpio_set_value(priv->config.reset_n_io, 0);
+ }
+ 
+diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c
+index 9a22056e8d9e..e5a622ce4b95 100644
+--- a/drivers/nfc/nfcmrvl/uart.c
++++ b/drivers/nfc/nfcmrvl/uart.c
+@@ -26,7 +26,7 @@
+ static unsigned int hci_muxed;
+ static unsigned int flow_control;
+ static unsigned int break_control;
+-static unsigned int reset_n_io;
++static int reset_n_io = -EINVAL;
+ 
+ /*
+ ** NFCMRVL NCI OPS
+@@ -231,5 +231,5 @@ MODULE_PARM_DESC(break_control, "Tell if UART driver must 
drive break signal.");
+ module_param(hci_muxed, uint, 0);
+ MODULE_PARM_DESC(hci_muxed, "Tell if transport is muxed in HCI one.");
+ 
+-module_param(reset_n_io, uint, 0);
++module_param(reset_n_io, int, 0);
+ MODULE_PARM_DESC(reset_n_io, "GPIO that is wired to RESET_N signal.");
+diff --git a/drivers/nfc/nfcmrvl/usb.c b/drivers/nfc/nfcmrvl/usb.c
+index 945cc903d8f1..888e298f610b 100644
+--- a/drivers/nfc/nfcmrvl/usb.c
++++ b/drivers/nfc/nfcmrvl/usb.c
+@@ -305,6 +305,7 @@ static int nfcmrvl_probe(struct usb_interface *intf,
+ 
+       /* No configuration for USB */
+       memset(&config, 0, sizeof(config));
++      config.reset_n_io = -EINVAL;
+ 
+       nfc_info(&udev->dev, "intf %p id %p\n", intf, id);
+ 
+diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
+index dfb93228d6a7..df41f3571dc9 100644
+--- a/drivers/nvdimm/bus.c
++++ b/drivers/nvdimm/bus.c
+@@ -887,10 +887,12 @@ void wait_nvdimm_bus_probe_idle(struct device *dev)
+       do {
+               if (nvdimm_bus->probe_active == 0)
+                       break;
+-              nvdimm_bus_unlock(&nvdimm_bus->dev);
++              nvdimm_bus_unlock(dev);
++              device_unlock(dev);
+               wait_event(nvdimm_bus->wait,
+                               nvdimm_bus->probe_active == 0);
+-              nvdimm_bus_lock(&nvdimm_bus->dev);
++              device_lock(dev);
++              nvdimm_bus_lock(dev);
+       } while (true);
+ }
+ 
+@@ -973,20 +975,19 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+               int read_only, unsigned int ioctl_cmd, unsigned long arg)
+ {
+       struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
+-      static char out_env[ND_CMD_MAX_ENVELOPE];
+-      static char in_env[ND_CMD_MAX_ENVELOPE];
+       const struct nd_cmd_desc *desc = NULL;
+       unsigned int cmd = _IOC_NR(ioctl_cmd);
+       struct device *dev = &nvdimm_bus->dev;
+       void __user *p = (void __user *) arg;
++      char *out_env = NULL, *in_env = NULL;
+       const char *cmd_name, *dimm_name;
+       u32 in_len = 0, out_len = 0;
+       unsigned int func = cmd;
+       unsigned long cmd_mask;
+       struct nd_cmd_pkg pkg;
+       int rc, i, cmd_rc;
++      void *buf = NULL;
+       u64 buf_len = 0;
+-      void *buf;
+ 
+       if (nvdimm) {
+               desc = nd_cmd_dimm_desc(cmd);
+@@ -1017,7 +1018,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+               case ND_CMD_ARS_START:
+               case ND_CMD_CLEAR_ERROR:
+               case ND_CMD_CALL:
+-                      dev_dbg(&nvdimm_bus->dev, "'%s' command while 
read-only.\n",
++                      dev_dbg(dev, "'%s' command while read-only.\n",
+                                       nvdimm ? nvdimm_cmd_name(cmd)
+                                       : nvdimm_bus_cmd_name(cmd));
+                       return -EPERM;
+@@ -1026,6 +1027,9 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+               }
+ 
+       /* process an input envelope */
++      in_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
++      if (!in_env)
++              return -ENOMEM;
+       for (i = 0; i < desc->in_num; i++) {
+               u32 in_size, copy;
+ 
+@@ -1033,14 +1037,17 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+               if (in_size == UINT_MAX) {
+                       dev_err(dev, "%s:%s unknown input size cmd: %s field: 
%d\n",
+                                       __func__, dimm_name, cmd_name, i);
+-                      return -ENXIO;
++                      rc = -ENXIO;
++                      goto out;
+               }
+-              if (in_len < sizeof(in_env))
+-                      copy = min_t(u32, sizeof(in_env) - in_len, in_size);
++              if (in_len < ND_CMD_MAX_ENVELOPE)
++                      copy = min_t(u32, ND_CMD_MAX_ENVELOPE - in_len, 
in_size);
+               else
+                       copy = 0;
+-              if (copy && copy_from_user(&in_env[in_len], p + in_len, copy))
+-                      return -EFAULT;
++              if (copy && copy_from_user(&in_env[in_len], p + in_len, copy)) {
++                      rc = -EFAULT;
++                      goto out;
++              }
+               in_len += in_size;
+       }
+ 
+@@ -1052,6 +1059,12 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+       }
+ 
+       /* process an output envelope */
++      out_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
++      if (!out_env) {
++              rc = -ENOMEM;
++              goto out;
++      }
++
+       for (i = 0; i < desc->out_num; i++) {
+               u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
+                               (u32 *) in_env, (u32 *) out_env, 0);
+@@ -1060,15 +1073,18 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+               if (out_size == UINT_MAX) {
+                       dev_dbg(dev, "%s unknown output size cmd: %s field: 
%d\n",
+                                       dimm_name, cmd_name, i);
+-                      return -EFAULT;
++                      rc = -EFAULT;
++                      goto out;
+               }
+-              if (out_len < sizeof(out_env))
+-                      copy = min_t(u32, sizeof(out_env) - out_len, out_size);
++              if (out_len < ND_CMD_MAX_ENVELOPE)
++                      copy = min_t(u32, ND_CMD_MAX_ENVELOPE - out_len, 
out_size);
+               else
+                       copy = 0;
+               if (copy && copy_from_user(&out_env[out_len],
+-                                      p + in_len + out_len, copy))
+-                      return -EFAULT;
++                                      p + in_len + out_len, copy)) {
++                      rc = -EFAULT;
++                      goto out;
++              }
+               out_len += out_size;
+       }
+ 
+@@ -1076,19 +1092,23 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+       if (buf_len > ND_IOCTL_MAX_BUFLEN) {
+               dev_dbg(dev, "%s cmd: %s buf_len: %llu > %d\n", dimm_name,
+                               cmd_name, buf_len, ND_IOCTL_MAX_BUFLEN);
+-              return -EINVAL;
++              rc = -EINVAL;
++              goto out;
+       }
+ 
+       buf = vmalloc(buf_len);
+-      if (!buf)
+-              return -ENOMEM;
++      if (!buf) {
++              rc = -ENOMEM;
++              goto out;
++      }
+ 
+       if (copy_from_user(buf, p, buf_len)) {
+               rc = -EFAULT;
+               goto out;
+       }
+ 
+-      nvdimm_bus_lock(&nvdimm_bus->dev);
++      device_lock(dev);
++      nvdimm_bus_lock(dev);
+       rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
+       if (rc)
+               goto out_unlock;
+@@ -1103,17 +1123,16 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, 
struct nvdimm *nvdimm,
+               nvdimm_account_cleared_poison(nvdimm_bus, clear_err->address,
+                               clear_err->cleared);
+       }
+-      nvdimm_bus_unlock(&nvdimm_bus->dev);
+ 
+       if (copy_to_user(p, buf, buf_len))
+               rc = -EFAULT;
+ 
+-      vfree(buf);
+-      return rc;
+-
+- out_unlock:
+-      nvdimm_bus_unlock(&nvdimm_bus->dev);
+- out:
++out_unlock:
++      nvdimm_bus_unlock(dev);
++      device_unlock(dev);
++out:
++      kfree(in_env);
++      kfree(out_env);
+       vfree(buf);
+       return rc;
+ }
+diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
+index 4fed9ce9c2fe..a15276cdec7d 100644
+--- a/drivers/nvdimm/region_devs.c
++++ b/drivers/nvdimm/region_devs.c
+@@ -422,10 +422,12 @@ static ssize_t available_size_show(struct device *dev,
+        * memory nvdimm_bus_lock() is dropped, but that's userspace's
+        * problem to not race itself.
+        */
++      device_lock(dev);
+       nvdimm_bus_lock(dev);
+       wait_nvdimm_bus_probe_idle(dev);
+       available = nd_region_available_dpa(nd_region);
+       nvdimm_bus_unlock(dev);
++      device_unlock(dev);
+ 
+       return sprintf(buf, "%llu\n", available);
+ }
+@@ -437,10 +439,12 @@ static ssize_t max_available_extent_show(struct device 
*dev,
+       struct nd_region *nd_region = to_nd_region(dev);
+       unsigned long long available = 0;
+ 
++      device_lock(dev);
+       nvdimm_bus_lock(dev);
+       wait_nvdimm_bus_probe_idle(dev);
+       available = nd_region_allocatable_dpa(nd_region);
+       nvdimm_bus_unlock(dev);
++      device_unlock(dev);
+ 
+       return sprintf(buf, "%llu\n", available);
+ }
+diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
+index 590ec8009f52..9e444b1846ce 100644
+--- a/drivers/scsi/fcoe/fcoe_ctlr.c
++++ b/drivers/scsi/fcoe/fcoe_ctlr.c
+@@ -2005,7 +2005,7 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
+  */
+ static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
+ {
+-      return (struct fcoe_rport *)(rdata + 1);
++      return container_of(rdata, struct fcoe_rport, rdata);
+ }
+ 
+ /**
+@@ -2269,7 +2269,7 @@ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
+  */
+ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
+                             struct sk_buff *skb,
+-                            struct fc_rport_priv *rdata)
++                            struct fcoe_rport *frport)
+ {
+       struct fip_header *fiph;
+       struct fip_desc *desc = NULL;
+@@ -2277,16 +2277,12 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
+       struct fip_wwn_desc *wwn = NULL;
+       struct fip_vn_desc *vn = NULL;
+       struct fip_size_desc *size = NULL;
+-      struct fcoe_rport *frport;
+       size_t rlen;
+       size_t dlen;
+       u32 desc_mask = 0;
+       u32 dtype;
+       u8 sub;
+ 
+-      memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
+-      frport = fcoe_ctlr_rport(rdata);
+-
+       fiph = (struct fip_header *)skb->data;
+       frport->flags = ntohs(fiph->fip_flags);
+ 
+@@ -2349,15 +2345,17 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
+                       if (dlen != sizeof(struct fip_wwn_desc))
+                               goto len_err;
+                       wwn = (struct fip_wwn_desc *)desc;
+-                      rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
++                      frport->rdata.ids.node_name =
++                              get_unaligned_be64(&wwn->fd_wwn);
+                       break;
+               case FIP_DT_VN_ID:
+                       if (dlen != sizeof(struct fip_vn_desc))
+                               goto len_err;
+                       vn = (struct fip_vn_desc *)desc;
+                       memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
+-                      rdata->ids.port_id = ntoh24(vn->fd_fc_id);
+-                      rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
++                      frport->rdata.ids.port_id = ntoh24(vn->fd_fc_id);
++                      frport->rdata.ids.port_name =
++                              get_unaligned_be64(&vn->fd_wwpn);
+                       break;
+               case FIP_DT_FC4F:
+                       if (dlen != sizeof(struct fip_fc4_feat))
+@@ -2738,10 +2736,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
+ {
+       struct fip_header *fiph;
+       enum fip_vn2vn_subcode sub;
+-      struct {
+-              struct fc_rport_priv rdata;
+-              struct fcoe_rport frport;
+-      } buf;
++      struct fcoe_rport frport = { };
+       int rc, vlan_id = 0;
+ 
+       fiph = (struct fip_header *)skb->data;
+@@ -2757,7 +2752,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
+               goto drop;
+       }
+ 
+-      rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
++      rc = fcoe_ctlr_vn_parse(fip, skb, &frport);
+       if (rc) {
+               LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
+               goto drop;
+@@ -2766,19 +2761,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
+       mutex_lock(&fip->ctlr_mutex);
+       switch (sub) {
+       case FIP_SC_VN_PROBE_REQ:
+-              fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
++              fcoe_ctlr_vn_probe_req(fip, &frport.rdata);
+               break;
+       case FIP_SC_VN_PROBE_REP:
+-              fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
++              fcoe_ctlr_vn_probe_reply(fip, &frport.rdata);
+               break;
+       case FIP_SC_VN_CLAIM_NOTIFY:
+-              fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
++              fcoe_ctlr_vn_claim_notify(fip, &frport.rdata);
+               break;
+       case FIP_SC_VN_CLAIM_REP:
+-              fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
++              fcoe_ctlr_vn_claim_resp(fip, &frport.rdata);
+               break;
+       case FIP_SC_VN_BEACON:
+-              fcoe_ctlr_vn_beacon(fip, &buf.rdata);
++              fcoe_ctlr_vn_beacon(fip, &frport.rdata);
+               break;
+       default:
+               LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
+@@ -2802,22 +2797,18 @@ drop:
+  */
+ static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
+                             struct sk_buff *skb,
+-                            struct fc_rport_priv *rdata)
++                            struct fcoe_rport *frport)
+ {
+       struct fip_header *fiph;
+       struct fip_desc *desc = NULL;
+       struct fip_mac_desc *macd = NULL;
+       struct fip_wwn_desc *wwn = NULL;
+-      struct fcoe_rport *frport;
+       size_t rlen;
+       size_t dlen;
+       u32 desc_mask = 0;
+       u32 dtype;
+       u8 sub;
+ 
+-      memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
+-      frport = fcoe_ctlr_rport(rdata);
+-
+       fiph = (struct fip_header *)skb->data;
+       frport->flags = ntohs(fiph->fip_flags);
+ 
+@@ -2871,7 +2862,8 @@ static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
+                       if (dlen != sizeof(struct fip_wwn_desc))
+                               goto len_err;
+                       wwn = (struct fip_wwn_desc *)desc;
+-                      rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
++                      frport->rdata.ids.node_name =
++                              get_unaligned_be64(&wwn->fd_wwn);
+                       break;
+               default:
+                       LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+@@ -2982,22 +2974,19 @@ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
+ {
+       struct fip_header *fiph;
+       enum fip_vlan_subcode sub;
+-      struct {
+-              struct fc_rport_priv rdata;
+-              struct fcoe_rport frport;
+-      } buf;
++      struct fcoe_rport frport = { };
+       int rc;
+ 
+       fiph = (struct fip_header *)skb->data;
+       sub = fiph->fip_subcode;
+-      rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
++      rc = fcoe_ctlr_vlan_parse(fip, skb, &frport);
+       if (rc) {
+               LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc);
+               goto drop;
+       }
+       mutex_lock(&fip->ctlr_mutex);
+       if (sub == FIP_SC_VL_REQ)
+-              fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata);
++              fcoe_ctlr_vlan_disc_reply(fip, &frport.rdata);
+       mutex_unlock(&fip->ctlr_mutex);
+ 
+ drop:
+diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
+index e0f3852fdad1..da6e97d8dc3b 100644
+--- a/drivers/scsi/libfc/fc_rport.c
++++ b/drivers/scsi/libfc/fc_rport.c
+@@ -128,6 +128,7 @@ EXPORT_SYMBOL(fc_rport_lookup);
+ struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)
+ {
+       struct fc_rport_priv *rdata;
++      size_t rport_priv_size = sizeof(*rdata);
+ 
+       lockdep_assert_held(&lport->disc.disc_mutex);
+ 
+@@ -135,7 +136,9 @@ struct fc_rport_priv *fc_rport_create(struct fc_lport 
*lport, u32 port_id)
+       if (rdata)
+               return rdata;
+ 
+-      rdata = kzalloc(sizeof(*rdata) + lport->rport_priv_size, GFP_KERNEL);
++      if (lport->rport_priv_size > 0)
++              rport_priv_size = lport->rport_priv_size;
++      rdata = kzalloc(rport_priv_size, GFP_KERNEL);
+       if (!rdata)
+               return NULL;
+ 
+diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
+index 402c1efcd762..6435b8652159 100644
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -764,7 +764,8 @@ static int bcm2835_spi_transfer_one(struct spi_master 
*master,
+       bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
+ 
+       /* handle all the 3-wire mode */
+-      if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
++      if (spi->mode & SPI_3WIRE && tfr->rx_buf &&
++          tfr->rx_buf != master->dummy_rx)
+               cs |= BCM2835_SPI_CS_REN;
+       else
+               cs &= ~BCM2835_SPI_CS_REN;
+diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
+index 6e30949d9f77..a7ec2d3dff92 100644
+--- a/fs/compat_ioctl.c
++++ b/fs/compat_ioctl.c
+@@ -638,9 +638,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN)
+ COMPATIBLE_IOCTL(PPPIOCATTCHAN)
+ COMPATIBLE_IOCTL(PPPIOCGCHAN)
+ COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
+-/* PPPOX */
+-COMPATIBLE_IOCTL(PPPOEIOCSFWD)
+-COMPATIBLE_IOCTL(PPPOEIOCDFWD)
+ /* Big A */
+ /* sparc only */
+ /* Big Q for sound/OSS */
+diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
+index 8b728750a625..69e813bcb947 100644
+--- a/include/linux/if_pppox.h
++++ b/include/linux/if_pppox.h
+@@ -80,6 +80,9 @@ extern int register_pppox_proto(int proto_num, const struct 
pppox_proto *pp);
+ extern void unregister_pppox_proto(int proto_num);
+ extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding 
*/
+ extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long 
arg);
++extern int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned 
long arg);
++
++#define PPPOEIOCSFWD32    _IOW(0xB1 ,0, compat_size_t)
+ 
+ /* PPPoX socket states */
+ enum {
+diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
+index e690ba0f965c..70185079f83e 100644
+--- a/include/linux/mlx5/fs.h
++++ b/include/linux/mlx5/fs.h
+@@ -211,6 +211,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle 
*handler,
+ 
+ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
+ void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
++u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
+ void mlx5_fc_query_cached(struct mlx5_fc *counter,
+                         u64 *bytes, u64 *packets, u64 *lastuse);
+ int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
+diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
+index 7e42efa143a0..29b55f8cd7b3 100644
+--- a/include/linux/mlx5/mlx5_ifc.h
++++ b/include/linux/mlx5/mlx5_ifc.h
+@@ -5865,10 +5865,12 @@ struct mlx5_ifc_modify_cq_in_bits {
+ 
+       struct mlx5_ifc_cqc_bits cq_context;
+ 
+-      u8         reserved_at_280[0x40];
++      u8         reserved_at_280[0x60];
+ 
+       u8         cq_umem_valid[0x1];
+-      u8         reserved_at_2c1[0x5bf];
++      u8         reserved_at_2e1[0x1f];
++
++      u8         reserved_at_300[0x580];
+ 
+       u8         pas[0][0x40];
+ };
+diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
+index c50fb297e265..e89a922ee849 100644
+--- a/include/scsi/libfcoe.h
++++ b/include/scsi/libfcoe.h
+@@ -229,6 +229,7 @@ struct fcoe_fcf {
+  * @vn_mac:   VN_Node assigned MAC address for data
+  */
+ struct fcoe_rport {
++      struct fc_rport_priv rdata;
+       unsigned long time;
+       u16 fcoe_len;
+       u16 flags;
+diff --git a/net/bridge/br.c b/net/bridge/br.c
+index d164f63a4345..8a8f9e5f264f 100644
+--- a/net/bridge/br.c
++++ b/net/bridge/br.c
+@@ -37,12 +37,15 @@ static int br_device_event(struct notifier_block *unused, 
unsigned long event, v
+       int err;
+ 
+       if (dev->priv_flags & IFF_EBRIDGE) {
++              err = br_vlan_bridge_event(dev, event, ptr);
++              if (err)
++                      return notifier_from_errno(err);
++
+               if (event == NETDEV_REGISTER) {
+                       /* register of bridge completed, add sysfs entries */
+                       br_sysfs_addbr(dev);
+                       return NOTIFY_DONE;
+               }
+-              br_vlan_bridge_event(dev, event, ptr);
+       }
+ 
+       /* not a port of a bridge */
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 3d8deac2353d..f8cac3702712 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -1388,6 +1388,9 @@ br_multicast_leave_group(struct net_bridge *br,
+                       if (!br_port_group_equal(p, port, src))
+                               continue;
+ 
++                      if (p->flags & MDB_PG_FLAGS_PERMANENT)
++                              break;
++
+                       rcu_assign_pointer(*pp, p->next);
+                       hlist_del_init(&p->mglist);
+                       del_timer(&p->timer);
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
+index 159a0e2cb0f6..9564a953bdf9 100644
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -893,8 +893,8 @@ int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 
filter_mask);
+ void br_vlan_get_stats(const struct net_bridge_vlan *v,
+                      struct br_vlan_stats *stats);
+ void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
+-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
+-                        void *ptr);
++int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
++                       void *ptr);
+ 
+ static inline struct net_bridge_vlan_group *br_vlan_group(
+                                       const struct net_bridge *br)
+@@ -1084,9 +1084,10 @@ static inline void br_vlan_port_event(struct 
net_bridge_port *p,
+ {
+ }
+ 
+-static inline void br_vlan_bridge_event(struct net_device *dev,
+-                                      unsigned long event, void *ptr)
++static inline int br_vlan_bridge_event(struct net_device *dev,
++                                     unsigned long event, void *ptr)
+ {
++      return 0;
+ }
+ #endif
+ 
+diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
+index f47f526b4f19..6b2c48b07e04 100644
+--- a/net/bridge/br_vlan.c
++++ b/net/bridge/br_vlan.c
+@@ -1043,7 +1043,6 @@ int br_vlan_init(struct net_bridge *br)
+ {
+       struct net_bridge_vlan_group *vg;
+       int ret = -ENOMEM;
+-      bool changed;
+ 
+       vg = kzalloc(sizeof(*vg), GFP_KERNEL);
+       if (!vg)
+@@ -1058,17 +1057,10 @@ int br_vlan_init(struct net_bridge *br)
+       br->vlan_proto = htons(ETH_P_8021Q);
+       br->default_pvid = 1;
+       rcu_assign_pointer(br->vlgrp, vg);
+-      ret = br_vlan_add(br, 1,
+-                        BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED |
+-                        BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
+-      if (ret)
+-              goto err_vlan_add;
+ 
+ out:
+       return ret;
+ 
+-err_vlan_add:
+-      vlan_tunnel_deinit(vg);
+ err_tunnel_init:
+       rhashtable_destroy(&vg->vlan_hash);
+ err_rhtbl:
+@@ -1443,13 +1435,23 @@ static void nbp_vlan_set_vlan_dev_state(struct 
net_bridge_port *p, u16 vid)
+ }
+ 
+ /* Must be protected by RTNL. */
+-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
+-                        void *ptr)
++int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void 
*ptr)
+ {
+       struct netdev_notifier_changeupper_info *info;
+-      struct net_bridge *br;
++      struct net_bridge *br = netdev_priv(dev);
++      bool changed;
++      int ret = 0;
+ 
+       switch (event) {
++      case NETDEV_REGISTER:
++              ret = br_vlan_add(br, br->default_pvid,
++                                BRIDGE_VLAN_INFO_PVID |
++                                BRIDGE_VLAN_INFO_UNTAGGED |
++                                BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
++              break;
++      case NETDEV_UNREGISTER:
++              br_vlan_delete(br, br->default_pvid);
++              break;
+       case NETDEV_CHANGEUPPER:
+               info = ptr;
+               br_vlan_upper_change(dev, info->upper_dev, info->linking);
+@@ -1457,12 +1459,13 @@ void br_vlan_bridge_event(struct net_device *dev, 
unsigned long event,
+ 
+       case NETDEV_CHANGE:
+       case NETDEV_UP:
+-              br = netdev_priv(dev);
+               if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING))
+-                      return;
++                      break;
+               br_vlan_link_state_change(dev, br);
+               break;
+       }
++
++      return ret;
+ }
+ 
+ /* Must be protected by RTNL. */
+diff --git a/net/core/dev.c b/net/core/dev.c
+index d6edd218babd..29fcff2c3d51 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4382,12 +4382,17 @@ static u32 netif_receive_generic_xdp(struct sk_buff 
*skb,
+ 
+       act = bpf_prog_run_xdp(xdp_prog, xdp);
+ 
++      /* check if bpf_xdp_adjust_head was used */
+       off = xdp->data - orig_data;
+-      if (off > 0)
+-              __skb_pull(skb, off);
+-      else if (off < 0)
+-              __skb_push(skb, -off);
+-      skb->mac_header += off;
++      if (off) {
++              if (off > 0)
++                      __skb_pull(skb, off);
++              else if (off < 0)
++                      __skb_push(skb, -off);
++
++              skb->mac_header += off;
++              skb_reset_network_header(skb);
++      }
+ 
+       /* check if bpf_xdp_adjust_tail was used. it can only "shrink"
+        * pckt.
+@@ -9711,6 +9716,8 @@ static void __net_exit default_device_exit(struct net 
*net)
+ 
+               /* Push remaining network devices to init_net */
+               snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
++              if (__dev_get_by_name(&init_net, fb_name))
++                      snprintf(fb_name, IFNAMSIZ, "dev%%d");
+               err = dev_change_net_namespace(dev, &init_net, fb_name);
+               if (err) {
+                       pr_emerg("%s: failed to move %s to init_net: %d\n",
+diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
+index 43adfc1641ba..2f01cf6fa0de 100644
+--- a/net/ipv4/ipip.c
++++ b/net/ipv4/ipip.c
+@@ -275,6 +275,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
+       const struct iphdr  *tiph = &tunnel->parms.iph;
+       u8 ipproto;
+ 
++      if (!pskb_inet_may_pull(skb))
++              goto tx_error;
++
+       switch (skb->protocol) {
+       case htons(ETH_P_IP):
+               ipproto = IPPROTO_IPIP;
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index c2049c72f3e5..dd2d0b963260 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -660,12 +660,13 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
+                                   struct flowi6 *fl6, __u8 *dsfield,
+                                   int *encap_limit)
+ {
+-      struct ipv6hdr *ipv6h = ipv6_hdr(skb);
++      struct ipv6hdr *ipv6h;
+       struct ip6_tnl *t = netdev_priv(dev);
+       __u16 offset;
+ 
+       offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+       /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
++      ipv6h = ipv6_hdr(skb);
+ 
+       if (offset > 0) {
+               struct ipv6_tlv_tnl_enc_lim *tel;
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
+index b80fde1bc005..d10a9e40729f 100644
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -1278,12 +1278,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device 
*dev)
+       }
+ 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
++      dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
+ 
+       if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+               return -1;
+ 
+-      dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
+-
+       skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+ 
+       err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
+@@ -1367,12 +1366,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device 
*dev)
+       }
+ 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
++      dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
+ 
+       if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+               return -1;
+ 
+-      dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
+-
+       skb_set_inner_ipproto(skb, IPPROTO_IPV6);
+ 
+       err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index 1d0e5904dedf..c54cb59593ef 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -1681,6 +1681,9 @@ static const struct proto_ops pppol2tp_ops = {
+       .recvmsg        = pppol2tp_recvmsg,
+       .mmap           = sock_no_mmap,
+       .ioctl          = pppox_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl = pppox_compat_ioctl,
++#endif
+ };
+ 
+ static const struct pppox_proto pppol2tp_proto = {
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 06aac0aaae64..8dc6580e1787 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -1222,7 +1222,6 @@ static void ieee80211_if_setup(struct net_device *dev)
+ static void ieee80211_if_setup_no_queue(struct net_device *dev)
+ {
+       ieee80211_if_setup(dev);
+-      dev->features |= NETIF_F_LLTX;
+       dev->priv_flags |= IFF_NO_QUEUE;
+ }
+ 
+diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
+index 8126b26f125e..fd1f7e799e23 100644
+--- a/net/sched/act_bpf.c
++++ b/net/sched/act_bpf.c
+@@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr 
*nla,
+       struct tcf_bpf *prog;
+       bool is_bpf, is_ebpf;
+       int ret, res = 0;
++      u32 index;
+ 
+       if (!nla)
+               return -EINVAL;
+@@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr 
*nla,
+               return -EINVAL;
+ 
+       parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
+-
+-      ret = tcf_idr_check_alloc(tn, &parm->index, act, bind);
++      index = parm->index;
++      ret = tcf_idr_check_alloc(tn, &index, act, bind);
+       if (!ret) {
+-              ret = tcf_idr_create(tn, parm->index, est, act,
++              ret = tcf_idr_create(tn, index, est, act,
+                                    &act_bpf_ops, bind, true);
+               if (ret < 0) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+ 
+diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
+index ce36b0f7e1dc..32ac04d77a45 100644
+--- a/net/sched/act_connmark.c
++++ b/net/sched/act_connmark.c
+@@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct 
nlattr *nla,
+       struct tcf_connmark_info *ci;
+       struct tc_connmark *parm;
+       int ret = 0, err;
++      u32 index;
+ 
+       if (!nla)
+               return -EINVAL;
+@@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct 
nlattr *nla,
+               return -EINVAL;
+ 
+       parm = nla_data(tb[TCA_CONNMARK_PARMS]);
+-
+-      ret = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      ret = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (!ret) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_connmark_ops, bind, false);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+ 
+diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
+index 621fb22ce2a9..9b9288267a54 100644
+--- a/net/sched/act_csum.c
++++ b/net/sched/act_csum.c
+@@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
+       struct tc_csum *parm;
+       struct tcf_csum *p;
+       int ret = 0, err;
++      u32 index;
+ 
+       if (nla == NULL)
+               return -EINVAL;
+@@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr 
*nla,
+       if (tb[TCA_CSUM_PARMS] == NULL)
+               return -EINVAL;
+       parm = nla_data(tb[TCA_CSUM_PARMS]);
+-
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (!err) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_csum_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
+index b2380c5284e6..8f0140c6ca58 100644
+--- a/net/sched/act_gact.c
++++ b/net/sched/act_gact.c
+@@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
+       struct tc_gact *parm;
+       struct tcf_gact *gact;
+       int ret = 0;
++      u32 index;
+       int err;
+ #ifdef CONFIG_GACT_PROB
+       struct tc_gact_p *p_parm = NULL;
+@@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
+       if (tb[TCA_GACT_PARMS] == NULL)
+               return -EINVAL;
+       parm = nla_data(tb[TCA_GACT_PARMS]);
++      index = parm->index;
+ 
+ #ifndef CONFIG_GACT_PROB
+       if (tb[TCA_GACT_PROB] != NULL)
+@@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr 
*nla,
+       }
+ #endif
+ 
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (!err) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_gact_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
+index 41d5398dd2f2..92ee853d43e6 100644
+--- a/net/sched/act_ife.c
++++ b/net/sched/act_ife.c
+@@ -479,8 +479,14 @@ static int tcf_ife_init(struct net *net, struct nlattr 
*nla,
+       u8 *saddr = NULL;
+       bool exists = false;
+       int ret = 0;
++      u32 index;
+       int err;
+ 
++      if (!nla) {
++              NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be 
passed");
++              return -EINVAL;
++      }
++
+       err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy,
+                                         NULL);
+       if (err < 0)
+@@ -502,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr 
*nla,
+       if (!p)
+               return -ENOMEM;
+ 
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0) {
+               kfree(p);
+               return err;
+@@ -514,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr 
*nla,
+       }
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops,
++              ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
+                                    bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       kfree(p);
+                       return ret;
+               }
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index 58e7573dded4..d10dca7a13e1 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -101,6 +101,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
+       struct net_device *dev;
+       bool exists = false;
+       int ret, err;
++      u32 index;
+ 
+       if (!nla) {
+               NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be 
passed");
+@@ -115,8 +116,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
+               return -EINVAL;
+       }
+       parm = nla_data(tb[TCA_MIRRED_PARMS]);
+-
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -133,21 +134,21 @@ static int tcf_mirred_init(struct net *net, struct 
nlattr *nla,
+               if (exists)
+                       tcf_idr_release(*a, bind);
+               else
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+               NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
+               return -EINVAL;
+       }
+ 
+       if (!exists) {
+               if (!parm->ifindex) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       NL_SET_ERR_MSG_MOD(extack, "Specified device does not 
exist");
+                       return -EINVAL;
+               }
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_mirred_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
+index 45923ebb7a4f..7b858c11b1b5 100644
+--- a/net/sched/act_nat.c
++++ b/net/sched/act_nat.c
+@@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, 
struct nlattr *est,
+       struct tc_nat *parm;
+       int ret = 0, err;
+       struct tcf_nat *p;
++      u32 index;
+ 
+       if (nla == NULL)
+               return -EINVAL;
+@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr 
*nla, struct nlattr *est,
+       if (tb[TCA_NAT_PARMS] == NULL)
+               return -EINVAL;
+       parm = nla_data(tb[TCA_NAT_PARMS]);
+-
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (!err) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_nat_ops, bind, false);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index 45e9d6bfddb3..17360c6faeaa 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr 
*nla,
+       struct tcf_pedit *p;
+       int ret = 0, err;
+       int ksize;
++      u32 index;
+ 
+       if (!nla) {
+               NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be 
passed");
+@@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr 
*nla,
+       if (IS_ERR(keys_ex))
+               return PTR_ERR(keys_ex);
+ 
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (!err) {
+               if (!parm->nkeys) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be 
passed");
+                       ret = -EINVAL;
+                       goto out_free;
+               }
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_pedit_ops, bind, false);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       goto out_free;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_police.c b/net/sched/act_police.c
+index a065f62fa79c..49cec3e64a4d 100644
+--- a/net/sched/act_police.c
++++ b/net/sched/act_police.c
+@@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr 
*nla,
+       struct tc_action_net *tn = net_generic(net, police_net_id);
+       struct tcf_police_params *new;
+       bool exists = false;
++      u32 index;
+ 
+       if (nla == NULL)
+               return -EINVAL;
+@@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr 
*nla,
+               return -EINVAL;
+ 
+       parm = nla_data(tb[TCA_POLICE_TBF]);
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr 
*nla,
+               return 0;
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, NULL, a,
++              ret = tcf_idr_create(tn, index, NULL, a,
+                                    &act_police_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
+index 274d7a0c0e25..595308d60133 100644
+--- a/net/sched/act_sample.c
++++ b/net/sched/act_sample.c
+@@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr 
*nla,
+       struct tc_action_net *tn = net_generic(net, sample_net_id);
+       struct nlattr *tb[TCA_SAMPLE_MAX + 1];
+       struct psample_group *psample_group;
++      u32 psample_group_num, rate, index;
+       struct tcf_chain *goto_ch = NULL;
+-      u32 psample_group_num, rate;
+       struct tc_sample *parm;
+       struct tcf_sample *s;
+       bool exists = false;
+@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr 
*nla,
+               return -EINVAL;
+ 
+       parm = nla_data(tb[TCA_SAMPLE_PARMS]);
+-
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr 
*nla,
+               return 0;
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_sample_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+               ret = ACT_P_CREATED;
+diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
+index f28ddbabff76..33aefa25b545 100644
+--- a/net/sched/act_simple.c
++++ b/net/sched/act_simple.c
+@@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
+       struct tcf_defact *d;
+       bool exists = false;
+       int ret = 0, err;
++      u32 index;
+ 
+       if (nla == NULL)
+               return -EINVAL;
+@@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr 
*nla,
+               return -EINVAL;
+ 
+       parm = nla_data(tb[TCA_DEF_PARMS]);
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr 
*nla,
+               if (exists)
+                       tcf_idr_release(*a, bind);
+               else
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+               return -EINVAL;
+       }
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_simp_ops, bind, false);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+ 
+diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
+index 215a06705cef..b100870f02a6 100644
+--- a/net/sched/act_skbedit.c
++++ b/net/sched/act_skbedit.c
+@@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
+       u16 *queue_mapping = NULL, *ptype = NULL;
+       bool exists = false;
+       int ret = 0, err;
++      u32 index;
+ 
+       if (nla == NULL)
+               return -EINVAL;
+@@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
+       }
+ 
+       parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
+-
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct 
nlattr *nla,
+               if (exists)
+                       tcf_idr_release(*a, bind);
+               else
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+               return -EINVAL;
+       }
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_skbedit_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+ 
+diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
+index 4f07706eff07..7da3518e18ef 100644
+--- a/net/sched/act_skbmod.c
++++ b/net/sched/act_skbmod.c
+@@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr 
*nla,
+       struct tcf_skbmod_params *p, *p_old;
+       struct tcf_chain *goto_ch = NULL;
+       struct tc_skbmod *parm;
++      u32 lflags = 0, index;
+       struct tcf_skbmod *d;
+       bool exists = false;
+       u8 *daddr = NULL;
+       u8 *saddr = NULL;
+       u16 eth_type = 0;
+-      u32 lflags = 0;
+       int ret = 0, err;
+ 
+       if (!nla)
+@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct 
nlattr *nla,
+       }
+ 
+       parm = nla_data(tb[TCA_SKBMOD_PARMS]);
++      index = parm->index;
+       if (parm->flags & SKBMOD_F_SWAPMAC)
+               lflags = SKBMOD_F_SWAPMAC;
+ 
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct 
nlattr *nla,
+               if (exists)
+                       tcf_idr_release(*a, bind);
+               else
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+               return -EINVAL;
+       }
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_skbmod_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+ 
+diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
+index 10dffda1d5cc..6d0debdc9b97 100644
+--- a/net/sched/act_tunnel_key.c
++++ b/net/sched/act_tunnel_key.c
+@@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr 
*nla,
+       __be16 flags = 0;
+       u8 tos, ttl;
+       int ret = 0;
++      u32 index;
+       int err;
+ 
+       if (!nla) {
+@@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr 
*nla,
+       }
+ 
+       parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr 
*nla,
+       }
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_tunnel_key_ops, bind, true);
+               if (ret) {
+                       NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
+@@ -403,7 +405,7 @@ err_out:
+       if (exists)
+               tcf_idr_release(*a, bind);
+       else
+-              tcf_idr_cleanup(tn, parm->index);
++              tcf_idr_cleanup(tn, index);
+       return ret;
+ }
+ 
+diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
+index 9269d350fb8a..a3c9eea1ee8a 100644
+--- a/net/sched/act_vlan.c
++++ b/net/sched/act_vlan.c
+@@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr 
*nla,
+       u8 push_prio = 0;
+       bool exists = false;
+       int ret = 0, err;
++      u32 index;
+ 
+       if (!nla)
+               return -EINVAL;
+@@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr 
*nla,
+       if (!tb[TCA_VLAN_PARMS])
+               return -EINVAL;
+       parm = nla_data(tb[TCA_VLAN_PARMS]);
+-      err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
++      index = parm->index;
++      err = tcf_idr_check_alloc(tn, &index, a, bind);
+       if (err < 0)
+               return err;
+       exists = err;
+@@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr 
*nla,
+                       if (exists)
+                               tcf_idr_release(*a, bind);
+                       else
+-                              tcf_idr_cleanup(tn, parm->index);
++                              tcf_idr_cleanup(tn, index);
+                       return -EINVAL;
+               }
+               push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
+@@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr 
*nla,
+                       if (exists)
+                               tcf_idr_release(*a, bind);
+                       else
+-                              tcf_idr_cleanup(tn, parm->index);
++                              tcf_idr_cleanup(tn, index);
+                       return -ERANGE;
+               }
+ 
+@@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr 
*nla,
+                               if (exists)
+                                       tcf_idr_release(*a, bind);
+                               else
+-                                      tcf_idr_cleanup(tn, parm->index);
++                                      tcf_idr_cleanup(tn, index);
+                               return -EPROTONOSUPPORT;
+                       }
+               } else {
+@@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr 
*nla,
+               if (exists)
+                       tcf_idr_release(*a, bind);
+               else
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+               return -EINVAL;
+       }
+       action = parm->v_action;
+ 
+       if (!exists) {
+-              ret = tcf_idr_create(tn, parm->index, est, a,
++              ret = tcf_idr_create(tn, index, est, a,
+                                    &act_vlan_ops, bind, true);
+               if (ret) {
+-                      tcf_idr_cleanup(tn, parm->index);
++                      tcf_idr_cleanup(tn, index);
+                       return ret;
+               }
+ 
+@@ -306,6 +308,14 @@ static int tcf_vlan_search(struct net *net, struct 
tc_action **a, u32 index)
+       return tcf_idr_search(tn, a, index);
+ }
+ 
++static size_t tcf_vlan_get_fill_size(const struct tc_action *act)
++{
++      return nla_total_size(sizeof(struct tc_vlan))
++              + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_ID */
++              + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_PROTOCOL */
++              + nla_total_size(sizeof(u8)); /* TCA_VLAN_PUSH_VLAN_PRIORITY */
++}
++
+ static struct tc_action_ops act_vlan_ops = {
+       .kind           =       "vlan",
+       .id             =       TCA_ID_VLAN,
+@@ -315,6 +325,7 @@ static struct tc_action_ops act_vlan_ops = {
+       .init           =       tcf_vlan_init,
+       .cleanup        =       tcf_vlan_cleanup,
+       .walk           =       tcf_vlan_walker,
++      .get_fill_size  =       tcf_vlan_get_fill_size,
+       .lookup         =       tcf_vlan_search,
+       .size           =       sizeof(struct tcf_vlan),
+ };
+diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
+index 25ef172c23df..30169b3adbbb 100644
+--- a/net/sched/sch_codel.c
++++ b/net/sched/sch_codel.c
+@@ -71,10 +71,10 @@ static struct sk_buff *dequeue_func(struct codel_vars 
*vars, void *ctx)
+       struct Qdisc *sch = ctx;
+       struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
+ 
+-      if (skb)
++      if (skb) {
+               sch->qstats.backlog -= qdisc_pkt_len(skb);
+-
+-      prefetch(&skb->end); /* we'll need skb_shinfo() */
++              prefetch(&skb->end); /* we'll need skb_shinfo() */
++      }
+       return skb;
+ }
+ 
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 7621ec2f539c..a3cc879d2589 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -253,7 +253,7 @@ static int smc_bind(struct socket *sock, struct sockaddr 
*uaddr,
+ 
+       /* Check if socket is already active */
+       rc = -EINVAL;
+-      if (sk->sk_state != SMC_INIT)
++      if (sk->sk_state != SMC_INIT || smc->connect_nonblock)
+               goto out_rel;
+ 
+       smc->clcsock->sk->sk_reuse = sk->sk_reuse;
+@@ -1399,7 +1399,8 @@ static int smc_listen(struct socket *sock, int backlog)
+       lock_sock(sk);
+ 
+       rc = -EINVAL;
+-      if ((sk->sk_state != SMC_INIT) && (sk->sk_state != SMC_LISTEN))
++      if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) ||
++          smc->connect_nonblock)
+               goto out;
+ 
+       rc = 0;
+@@ -1527,7 +1528,7 @@ static int smc_sendmsg(struct socket *sock, struct 
msghdr *msg, size_t len)
+               goto out;
+ 
+       if (msg->msg_flags & MSG_FASTOPEN) {
+-              if (sk->sk_state == SMC_INIT) {
++              if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {
+                       smc_switch_to_fallback(smc);
+                       smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
+               } else {
+@@ -1741,14 +1742,18 @@ static int smc_setsockopt(struct socket *sock, int 
level, int optname,
+               }
+               break;
+       case TCP_NODELAY:
+-              if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
++              if (sk->sk_state != SMC_INIT &&
++                  sk->sk_state != SMC_LISTEN &&
++                  sk->sk_state != SMC_CLOSED) {
+                       if (val && !smc->use_fallback)
+                               mod_delayed_work(system_wq, &smc->conn.tx_work,
+                                                0);
+               }
+               break;
+       case TCP_CORK:
+-              if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
++              if (sk->sk_state != SMC_INIT &&
++                  sk->sk_state != SMC_LISTEN &&
++                  sk->sk_state != SMC_CLOSED) {
+                       if (!val && !smc->use_fallback)
+                               mod_delayed_work(system_wq, &smc->conn.tx_work,
+                                                0);
+diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
+index cf155061c472..acd8a72169c1 100644
+--- a/net/tipc/netlink_compat.c
++++ b/net/tipc/netlink_compat.c
+@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
+       int rep_type;
+       int rep_size;
+       int req_type;
++      int req_size;
+       struct net *net;
+       struct sk_buff *rep;
+       struct tlv_desc *req;
+@@ -257,7 +258,8 @@ static int tipc_nl_compat_dumpit(struct 
tipc_nl_compat_cmd_dump *cmd,
+       int err;
+       struct sk_buff *arg;
+ 
+-      if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
++      if (msg->req_type && (!msg->req_size ||
++                            !TLV_CHECK_TYPE(msg->req, msg->req_type)))
+               return -EINVAL;
+ 
+       msg->rep = tipc_tlv_alloc(msg->rep_size);
+@@ -354,7 +356,8 @@ static int tipc_nl_compat_doit(struct 
tipc_nl_compat_cmd_doit *cmd,
+ {
+       int err;
+ 
+-      if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
++      if (msg->req_type && (!msg->req_size ||
++                            !TLV_CHECK_TYPE(msg->req, msg->req_type)))
+               return -EINVAL;
+ 
+       err = __tipc_nl_compat_doit(cmd, msg);
+@@ -1288,8 +1291,8 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, 
struct genl_info *info)
+               goto send;
+       }
+ 
+-      len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
+-      if (!len || !TLV_OK(msg.req, len)) {
++      msg.req_size = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
++      if (msg.req_size && !TLV_OK(msg.req, msg.req_size)) {
+               msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
+               err = -EOPNOTSUPP;
+               goto send;
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index dd8537f988c4..83ae41d7e554 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -485,9 +485,8 @@ static int tipc_sk_create(struct net *net, struct socket 
*sock,
+               tsk_set_unreturnable(tsk, true);
+               if (sock->type == SOCK_DGRAM)
+                       tsk_set_unreliable(tsk, true);
+-              __skb_queue_head_init(&tsk->mc_method.deferredq);
+       }
+-
++      __skb_queue_head_init(&tsk->mc_method.deferredq);
+       trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " ");
+       return 0;
+ }
+diff --git a/net/vmw_vsock/hyperv_transport.c 
b/net/vmw_vsock/hyperv_transport.c
+index 62dcdf082349..6c81a911fc02 100644
+--- a/net/vmw_vsock/hyperv_transport.c
++++ b/net/vmw_vsock/hyperv_transport.c
+@@ -311,6 +311,11 @@ static void hvs_close_connection(struct vmbus_channel 
*chan)
+       lock_sock(sk);
+       hvs_do_close_lock_held(vsock_sk(sk), true);
+       release_sock(sk);
++
++      /* Release the refcnt for the channel that's opened in
++       * hvs_open_connection().
++       */
++      sock_put(sk);
+ }
+ 
+ static void hvs_open_connection(struct vmbus_channel *chan)
+@@ -378,6 +383,9 @@ static void hvs_open_connection(struct vmbus_channel *chan)
+       }
+ 
+       set_per_channel_state(chan, conn_from_host ? new : sk);
++
++      /* This reference will be dropped by hvs_close_connection(). */
++      sock_hold(conn_from_host ? new : sk);
+       vmbus_set_chn_rescind_callback(chan, hvs_close_connection);
+ 
+       /* Set the pending send size to max packet size to always get
+diff --git a/sound/usb/helper.c b/sound/usb/helper.c
+index 84aa265dd802..4c12cc5b53fd 100644
+--- a/sound/usb/helper.c
++++ b/sound/usb/helper.c
+@@ -63,6 +63,20 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, 
void *after, u8 dsubtype
+       return NULL;
+ }
+ 
++/* check the validity of pipe and EP types */
++int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe)
++{
++      static const int pipetypes[4] = {
++              PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
++      };
++      struct usb_host_endpoint *ep;
++
++      ep = usb_pipe_endpoint(dev, pipe);
++      if (!ep || usb_pipetype(pipe) != 
pipetypes[usb_endpoint_type(&ep->desc)])
++              return -EINVAL;
++      return 0;
++}
++
+ /*
+  * Wrapper for usb_control_msg().
+  * Allocates a temp buffer to prevent dmaing from/to the stack.
+@@ -75,6 +89,9 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int 
pipe, __u8 request,
+       void *buf = NULL;
+       int timeout;
+ 
++      if (snd_usb_pipe_sanity_check(dev, pipe))
++              return -EINVAL;
++
+       if (size > 0) {
+               buf = kmemdup(data, size, GFP_KERNEL);
+               if (!buf)
+diff --git a/sound/usb/helper.h b/sound/usb/helper.h
+index d338bd0e0ca6..6afb70156ec4 100644
+--- a/sound/usb/helper.h
++++ b/sound/usb/helper.h
+@@ -7,6 +7,7 @@ unsigned int snd_usb_combine_bytes(unsigned char *bytes, int 
size);
+ void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype);
+ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 
dsubtype);
+ 
++int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe);
+ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
+                   __u8 request, __u8 requesttype, __u16 value, __u16 index,
+                   void *data, __u16 size);
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index cf5cff10c08e..78858918cbc1 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -828,11 +828,13 @@ static int snd_usb_novation_boot_quirk(struct usb_device 
*dev)
+ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
+ {
+       int err, actual_length;
+-
+       /* "midi send" enable */
+       static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 };
++      void *buf;
+ 
+-      void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
++      if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x05)))
++              return -EINVAL;
++      buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf,
+@@ -857,7 +859,11 @@ static int snd_usb_accessmusic_boot_quirk(struct 
usb_device *dev)
+ 
+ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
+ {
+-      int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++      int ret;
++
++      if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0)))
++              return -EINVAL;
++      ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                                 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                                 1, 0, NULL, 0, 1000);
+ 
+@@ -964,6 +970,8 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device 
*dev)
+ 
+       dev_dbg(&dev->dev, "Waiting for Axe-Fx III to boot up...\n");
+ 
++      if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0)))
++              return -EINVAL;
+       /* If the Axe-Fx III has not fully booted, it will timeout when trying
+        * to enable the audio streaming interface. A more generous timeout is
+        * used here to detect when the Axe-Fx III has finished booting as the
+@@ -996,6 +1004,8 @@ static int snd_usb_motu_microbookii_communicate(struct 
usb_device *dev, u8 *buf,
+ {
+       int err, actual_length;
+ 
++      if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x01)))
++              return -EINVAL;
+       err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x01), buf, *length,
+                               &actual_length, 1000);
+       if (err < 0)
+@@ -1006,6 +1016,8 @@ static int snd_usb_motu_microbookii_communicate(struct 
usb_device *dev, u8 *buf,
+ 
+       memset(buf, 0, buf_size);
+ 
++      if (snd_usb_pipe_sanity_check(dev, usb_rcvintpipe(dev, 0x82)))
++              return -EINVAL;
+       err = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x82), buf, buf_size,
+                               &actual_length, 1000);
+       if (err < 0)
+diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
+index f1573a11d3e4..b9e88ccc289b 100644
+--- a/tools/testing/selftests/bpf/Makefile
++++ b/tools/testing/selftests/bpf/Makefile
+@@ -51,7 +51,8 @@ TEST_PROGS := test_kmod.sh \
+       test_lirc_mode2.sh \
+       test_skb_cgroup_id.sh \
+       test_flow_dissector.sh \
+-      test_xdp_vlan.sh \
++      test_xdp_vlan_mode_generic.sh \
++      test_xdp_vlan_mode_native.sh \
+       test_lwt_ip_encap.sh \
+       test_tcp_check_syncookie.sh \
+       test_tc_tunnel.sh \
+diff --git a/tools/testing/selftests/bpf/test_xdp_vlan.sh 
b/tools/testing/selftests/bpf/test_xdp_vlan.sh
+index 51a3a31d1aac..bb8b0da91686 100755
+--- a/tools/testing/selftests/bpf/test_xdp_vlan.sh
++++ b/tools/testing/selftests/bpf/test_xdp_vlan.sh
+@@ -1,6 +1,14 @@
+ #!/bin/bash
++# SPDX-License-Identifier: GPL-2.0
++# Author: Jesper Dangaard Brouer <h...@kernel.org>
+ 
+-TESTNAME=xdp_vlan
++# Allow wrapper scripts to name test
++if [ -z "$TESTNAME" ]; then
++    TESTNAME=xdp_vlan
++fi
++
++# Default XDP mode
++XDP_MODE=xdpgeneric
+ 
+ usage() {
+   echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME"
+@@ -9,9 +17,23 @@ usage() {
+   echo "  -v | --verbose : Verbose"
+   echo "  --flush        : Flush before starting (e.g. after --interactive)"
+   echo "  --interactive  : Keep netns setup running after test-run"
++  echo "  --mode=XXX     : Choose XDP mode (xdp | xdpgeneric | xdpdrv)"
+   echo ""
+ }
+ 
++valid_xdp_mode()
++{
++      local mode=$1
++
++      case "$mode" in
++              xdpgeneric | xdpdrv | xdp)
++                      return 0
++                      ;;
++              *)
++                      return 1
++      esac
++}
++
+ cleanup()
+ {
+       local status=$?
+@@ -37,7 +59,7 @@ cleanup()
+ 
+ # Using external program "getopt" to get --long-options
+ OPTIONS=$(getopt -o hvfi: \
+-    --long verbose,flush,help,interactive,debug -- "$@")
++    --long verbose,flush,help,interactive,debug,mode: -- "$@")
+ if (( $? != 0 )); then
+     usage
+     echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"
+@@ -60,6 +82,11 @@ while true; do
+               cleanup
+               shift
+               ;;
++          --mode )
++              shift
++              XDP_MODE=$1
++              shift
++              ;;
+           -- )
+               shift
+               break
+@@ -81,8 +108,14 @@ if [ "$EUID" -ne 0 ]; then
+       exit 1
+ fi
+ 
+-ip link set dev lo xdp off 2>/dev/null > /dev/null
+-if [ $? -ne 0 ];then
++valid_xdp_mode $XDP_MODE
++if [ $? -ne 0 ]; then
++      echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)"
++      exit 1
++fi
++
++ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
++if [ $? -ne 0 ]; then
+       echo "selftests: $TESTNAME [SKIP] need ip xdp support"
+       exit 0
+ fi
+@@ -155,7 +188,7 @@ ip netns exec ns2 ip link set lo up
+ # At this point, the hosts cannot reach each-other,
+ # because ns2 are using VLAN tags on the packets.
+ 
+-ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Okay ping fails"'
++ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First 
ping must fail"'
+ 
+ 
+ # Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags
+@@ -166,7 +199,7 @@ export FILE=test_xdp_vlan.o
+ 
+ # First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
+ export XDP_PROG=xdp_vlan_change
+-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
++ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
+ 
+ # In ns1: egress use TC to add back VLAN tag 4011
+ #  (del cmd)
+@@ -177,8 +210,8 @@ ip netns exec ns1 tc filter add dev $DEVNS1 egress \
+   prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
+ 
+ # Now the namespaces can reach each-other, test with ping:
+-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
+-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
++ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
++ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
+ 
+ # Second test: Replace xdp prog, that fully remove vlan header
+ #
+@@ -187,9 +220,9 @@ ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ # ETH_P_8021Q indication, and this cause overwriting of our changes.
+ #
+ export XDP_PROG=xdp_vlan_remove_outer2
+-ip netns exec ns1 ip link set $DEVNS1 xdp off
+-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
++ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE off
++ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
+ 
+ # Now the namespaces should still be able reach each-other, test with ping:
+-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
+-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
++ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
++ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
+diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh 
b/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh
+new file mode 100644
+index 000000000000..c515326d6d59
+--- /dev/null
++++ b/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh
+@@ -0,0 +1,9 @@
++#!/bin/bash
++# SPDX-License-Identifier: GPL-2.0
++
++# Exit on failure
++set -e
++
++# Wrapper script to test generic-XDP
++export TESTNAME=xdp_vlan_mode_generic
++./test_xdp_vlan.sh --mode=xdpgeneric
+diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh 
b/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh
+new file mode 100644
+index 000000000000..5cf7ce1f16c1
+--- /dev/null
++++ b/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh
+@@ -0,0 +1,9 @@
++#!/bin/bash
++# SPDX-License-Identifier: GPL-2.0
++
++# Exit on failure
++set -e
++
++# Wrapper script to test native-XDP
++export TESTNAME=xdp_vlan_mode_native
++./test_xdp_vlan.sh --mode=xdpdrv

Reply via email to