commit:     8a762c939ae238385cdc0eac9c8227f7ee8bd3d2
Author:     Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
AuthorDate: Sat Feb 18 16:13:13 2017 +0000
Commit:     Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
CommitDate: Sat Feb 18 16:13:13 2017 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=8a762c93

Linux patch 4.9.11

 0000_README             |    4 +
 1010_linux-4.9.11.patch | 1893 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1897 insertions(+)

diff --git a/0000_README b/0000_README
index 9b2ecc5..d0e4001 100644
--- a/0000_README
+++ b/0000_README
@@ -83,6 +83,10 @@ Patch:  1009_linux-4.9.10.patch
 From:   http://www.kernel.org
 Desc:   Linux 4.9.10
 
+Patch:  1010_linux-4.9.11.patch
+From:   http://www.kernel.org
+Desc:   Linux 4.9.11
+
 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/1010_linux-4.9.11.patch b/1010_linux-4.9.11.patch
new file mode 100644
index 0000000..bf7bd80
--- /dev/null
+++ b/1010_linux-4.9.11.patch
@@ -0,0 +1,1893 @@
+diff --git a/Makefile b/Makefile
+index d2fe757a979d..18b0c5adad3b 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 9
+-SUBLEVEL = 10
++SUBLEVEL = 11
+ EXTRAVERSION =
+ NAME = Roaring Lionus
+ 
+diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
+index ebb4e95fbd74..96d80dfac383 100644
+--- a/arch/x86/kernel/fpu/core.c
++++ b/arch/x86/kernel/fpu/core.c
+@@ -236,7 +236,8 @@ void fpstate_init(union fpregs_state *state)
+        * it will #GP. Make sure it is replaced after the memset().
+        */
+       if (static_cpu_has(X86_FEATURE_XSAVES))
+-              state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT;
++              state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
++                                             xfeatures_mask;
+ 
+       if (static_cpu_has(X86_FEATURE_FXSR))
+               fpstate_init_fxstate(&state->fxsave);
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c 
b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+index f2e8beddcf44..4d3ddc2f7e43 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+@@ -507,8 +507,11 @@ void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv)
+               return;
+ 
+       for (ring = 0; ring < priv->rx_ring_num; ring++) {
+-              if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
++              if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) {
++                      local_bh_disable();
+                       napi_reschedule(&priv->rx_cq[ring]->napi);
++                      local_bh_enable();
++              }
+       }
+ }
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h 
b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+index 71382df59fc0..81d8e3bd01b6 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+@@ -765,7 +765,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
+ int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd);
+ 
+ int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz, int ix);
+-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv);
++void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
++                                  enum mlx5e_traffic_types tt);
+ 
+ int mlx5e_open_locked(struct net_device *netdev);
+ int mlx5e_close_locked(struct net_device *netdev);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+index 51c6a57ca873..126cfeb7e0ec 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+@@ -975,15 +975,18 @@ static int mlx5e_get_rxfh(struct net_device *netdev, u32 
*indir, u8 *key,
+ 
+ static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int 
inlen)
+ {
+-      struct mlx5_core_dev *mdev = priv->mdev;
+       void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
+-      int i;
++      struct mlx5_core_dev *mdev = priv->mdev;
++      int ctxlen = MLX5_ST_SZ_BYTES(tirc);
++      int tt;
+ 
+       MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
+-      mlx5e_build_tir_ctx_hash(tirc, priv);
+ 
+-      for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
+-              mlx5_core_modify_tir(mdev, priv->indir_tir[i].tirn, in, inlen);
++      for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
++              memset(tirc, 0, ctxlen);
++              mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
++              mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
++      }
+ }
+ 
+ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index 5dc3e2453ff5..b30671376a3d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -1978,8 +1978,23 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct 
mlx5e_priv *priv)
+       MLX5_SET(tirc, tirc, lro_timeout_period_usecs, 
priv->params.lro_timeout);
+ }
+ 
+-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
++void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
++                                  enum mlx5e_traffic_types tt)
+ {
++      void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
++
++#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
++                               MLX5_HASH_FIELD_SEL_DST_IP)
++
++#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
++                               MLX5_HASH_FIELD_SEL_DST_IP   |\
++                               MLX5_HASH_FIELD_SEL_L4_SPORT |\
++                               MLX5_HASH_FIELD_SEL_L4_DPORT)
++
++#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
++                               MLX5_HASH_FIELD_SEL_DST_IP   |\
++                               MLX5_HASH_FIELD_SEL_IPSEC_SPI)
++
+       MLX5_SET(tirc, tirc, rx_hash_fn,
+                mlx5e_rx_hash_fn(priv->params.rss_hfunc));
+       if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
+@@ -1991,6 +2006,88 @@ void mlx5e_build_tir_ctx_hash(void *tirc, struct 
mlx5e_priv *priv)
+               MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
+               memcpy(rss_key, priv->params.toeplitz_hash_key, len);
+       }
++
++      switch (tt) {
++      case MLX5E_TT_IPV4_TCP:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV4);
++              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
++                       MLX5_L4_PROT_TYPE_TCP);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_L4PORTS);
++              break;
++
++      case MLX5E_TT_IPV6_TCP:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV6);
++              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
++                       MLX5_L4_PROT_TYPE_TCP);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_L4PORTS);
++              break;
++
++      case MLX5E_TT_IPV4_UDP:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV4);
++              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
++                       MLX5_L4_PROT_TYPE_UDP);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_L4PORTS);
++              break;
++
++      case MLX5E_TT_IPV6_UDP:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV6);
++              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
++                       MLX5_L4_PROT_TYPE_UDP);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_L4PORTS);
++              break;
++
++      case MLX5E_TT_IPV4_IPSEC_AH:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV4);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_IPSEC_SPI);
++              break;
++
++      case MLX5E_TT_IPV6_IPSEC_AH:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV6);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_IPSEC_SPI);
++              break;
++
++      case MLX5E_TT_IPV4_IPSEC_ESP:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV4);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_IPSEC_SPI);
++              break;
++
++      case MLX5E_TT_IPV6_IPSEC_ESP:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV6);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP_IPSEC_SPI);
++              break;
++
++      case MLX5E_TT_IPV4:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV4);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP);
++              break;
++
++      case MLX5E_TT_IPV6:
++              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
++                       MLX5_L3_PROT_TYPE_IPV6);
++              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
++                       MLX5_HASH_IP);
++              break;
++      default:
++              WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
++      }
+ }
+ 
+ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
+@@ -2360,110 +2457,13 @@ void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
+ static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
+                                     enum mlx5e_traffic_types tt)
+ {
+-      void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
+-
+       MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
+ 
+-#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+-                               MLX5_HASH_FIELD_SEL_DST_IP)
+-
+-#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+-                               MLX5_HASH_FIELD_SEL_DST_IP   |\
+-                               MLX5_HASH_FIELD_SEL_L4_SPORT |\
+-                               MLX5_HASH_FIELD_SEL_L4_DPORT)
+-
+-#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+-                               MLX5_HASH_FIELD_SEL_DST_IP   |\
+-                               MLX5_HASH_FIELD_SEL_IPSEC_SPI)
+-
+       mlx5e_build_tir_ctx_lro(tirc, priv);
+ 
+       MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
+       MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
+-      mlx5e_build_tir_ctx_hash(tirc, priv);
+-
+-      switch (tt) {
+-      case MLX5E_TT_IPV4_TCP:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV4);
+-              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+-                       MLX5_L4_PROT_TYPE_TCP);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_L4PORTS);
+-              break;
+-
+-      case MLX5E_TT_IPV6_TCP:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV6);
+-              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+-                       MLX5_L4_PROT_TYPE_TCP);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_L4PORTS);
+-              break;
+-
+-      case MLX5E_TT_IPV4_UDP:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV4);
+-              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+-                       MLX5_L4_PROT_TYPE_UDP);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_L4PORTS);
+-              break;
+-
+-      case MLX5E_TT_IPV6_UDP:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV6);
+-              MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+-                       MLX5_L4_PROT_TYPE_UDP);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_L4PORTS);
+-              break;
+-
+-      case MLX5E_TT_IPV4_IPSEC_AH:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV4);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_IPSEC_SPI);
+-              break;
+-
+-      case MLX5E_TT_IPV6_IPSEC_AH:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV6);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_IPSEC_SPI);
+-              break;
+-
+-      case MLX5E_TT_IPV4_IPSEC_ESP:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV4);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_IPSEC_SPI);
+-              break;
+-
+-      case MLX5E_TT_IPV6_IPSEC_ESP:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV6);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP_IPSEC_SPI);
+-              break;
+-
+-      case MLX5E_TT_IPV4:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV4);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP);
+-              break;
+-
+-      case MLX5E_TT_IPV6:
+-              MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+-                       MLX5_L3_PROT_TYPE_IPV6);
+-              MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+-                       MLX5_HASH_IP);
+-              break;
+-      default:
+-              WARN_ONCE(true,
+-                        "mlx5e_build_indir_tir_ctx: bad traffic type!\n");
+-      }
++      mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
+ }
+ 
+ static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c 
b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index 914e5466f729..7e20e4bc4cc7 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -1110,9 +1110,8 @@ static struct mlx5_flow_rule *add_rule_fg(struct 
mlx5_flow_group *fg,
+                               return rule;
+                       }
+                       rule = add_rule_fte(fte, fg, dest);
+-                      unlock_ref_node(&fte->node);
+                       if (IS_ERR(rule))
+-                              goto unlock_fg;
++                              goto unlock_fte;
+                       else
+                               goto add_rule;
+               }
+@@ -1130,6 +1129,7 @@ static struct mlx5_flow_rule *add_rule_fg(struct 
mlx5_flow_group *fg,
+               goto unlock_fg;
+       }
+       tree_init_node(&fte->node, 0, del_fte);
++      nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
+       rule = add_rule_fte(fte, fg, dest);
+       if (IS_ERR(rule)) {
+               kfree(fte);
+@@ -1142,6 +1142,8 @@ static struct mlx5_flow_rule *add_rule_fg(struct 
mlx5_flow_group *fg,
+       list_add(&fte->node.list, prev);
+ add_rule:
+       tree_add_node(&rule->node, &fte->node);
++unlock_fte:
++      unlock_ref_node(&fte->node);
+ unlock_fg:
+       unlock_ref_node(&fg->node);
+       return rule;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+index 7df4ff158f3d..7d19029e2564 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+@@ -305,8 +305,12 @@ static int dwmac1000_irq_status(struct mac_device_info 
*hw,
+ {
+       void __iomem *ioaddr = hw->pcsr;
+       u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
++      u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
+       int ret = 0;
+ 
++      /* Discard masked bits */
++      intr_status &= ~intr_mask;
++
+       /* Not used events (e.g. MMC interrupts) are not handled. */
+       if ((intr_status & GMAC_INT_STATUS_MMCTIS))
+               x->mmc_tx_irq_n++;
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index 6255973e3dda..1b65f0f975cf 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -164,6 +164,7 @@ static void loopback_setup(struct net_device *dev)
+ {
+       dev->mtu                = 64 * 1024;
+       dev->hard_header_len    = ETH_HLEN;     /* 14   */
++      dev->min_header_len     = ETH_HLEN;     /* 14   */
+       dev->addr_len           = ETH_ALEN;     /* 6    */
+       dev->type               = ARPHRD_LOOPBACK;      /* 0x0001*/
+       dev->flags              = IFF_LOOPBACK;
+diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
+index 6f38daf2d978..adea6f5a4d71 100644
+--- a/drivers/net/macvtap.c
++++ b/drivers/net/macvtap.c
+@@ -682,7 +682,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, 
struct msghdr *m,
+       ssize_t n;
+ 
+       if (q->flags & IFF_VNET_HDR) {
+-              vnet_hdr_len = q->vnet_hdr_sz;
++              vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
+ 
+               err = -EINVAL;
+               if (len < vnet_hdr_len)
+@@ -822,7 +822,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
+ 
+       if (q->flags & IFF_VNET_HDR) {
+               struct virtio_net_hdr vnet_hdr;
+-              vnet_hdr_len = q->vnet_hdr_sz;
++              vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
+               if (iov_iter_count(iter) < vnet_hdr_len)
+                       return -EINVAL;
+ 
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 18402d79539e..b31aca8146bb 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1187,9 +1187,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, 
struct tun_file *tfile,
+       }
+ 
+       if (tun->flags & IFF_VNET_HDR) {
+-              if (len < tun->vnet_hdr_sz)
++              int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
++
++              if (len < vnet_hdr_sz)
+                       return -EINVAL;
+-              len -= tun->vnet_hdr_sz;
++              len -= vnet_hdr_sz;
+ 
+               n = copy_from_iter(&gso, sizeof(gso), from);
+               if (n != sizeof(gso))
+@@ -1201,7 +1203,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, 
struct tun_file *tfile,
+ 
+               if (tun16_to_cpu(tun, gso.hdr_len) > len)
+                       return -EINVAL;
+-              iov_iter_advance(from, tun->vnet_hdr_sz - sizeof(gso));
++              iov_iter_advance(from, vnet_hdr_sz - sizeof(gso));
+       }
+ 
+       if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) {
+@@ -1348,7 +1350,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
+               vlan_hlen = VLAN_HLEN;
+ 
+       if (tun->flags & IFF_VNET_HDR)
+-              vnet_hdr_sz = tun->vnet_hdr_sz;
++              vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
+ 
+       total = skb->len + vlan_hlen + vnet_hdr_sz;
+ 
+diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
+index d9ca05d3ac8e..40864159021d 100644
+--- a/drivers/net/usb/catc.c
++++ b/drivers/net/usb/catc.c
+@@ -777,7 +777,7 @@ static int catc_probe(struct usb_interface *intf, const 
struct usb_device_id *id
+       struct net_device *netdev;
+       struct catc *catc;
+       u8 broadcast[ETH_ALEN];
+-      int i, pktsz;
++      int pktsz, ret;
+ 
+       if (usb_set_interface(usbdev,
+                       intf->altsetting->desc.bInterfaceNumber, 1)) {
+@@ -812,12 +812,8 @@ static int catc_probe(struct usb_interface *intf, const 
struct usb_device_id *id
+       if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
+           (!catc->rx_urb) || (!catc->irq_urb)) {
+               dev_err(&intf->dev, "No free urbs available.\n");
+-              usb_free_urb(catc->ctrl_urb);
+-              usb_free_urb(catc->tx_urb);
+-              usb_free_urb(catc->rx_urb);
+-              usb_free_urb(catc->irq_urb);
+-              free_netdev(netdev);
+-              return -ENOMEM;
++              ret = -ENOMEM;
++              goto fail_free;
+       }
+ 
+       /* The F5U011 has the same vendor/product as the netmate but a device 
version of 0x130 */
+@@ -845,15 +841,24 @@ static int catc_probe(struct usb_interface *intf, const 
struct usb_device_id *id
+                 catc->irq_buf, 2, catc_irq_done, catc, 1);
+ 
+       if (!catc->is_f5u011) {
++              u32 *buf;
++              int i;
++
+               dev_dbg(dev, "Checking memory size\n");
+ 
+-              i = 0x12345678;
+-              catc_write_mem(catc, 0x7a80, &i, 4);
+-              i = 0x87654321; 
+-              catc_write_mem(catc, 0xfa80, &i, 4);
+-              catc_read_mem(catc, 0x7a80, &i, 4);
++              buf = kmalloc(4, GFP_KERNEL);
++              if (!buf) {
++                      ret = -ENOMEM;
++                      goto fail_free;
++              }
++
++              *buf = 0x12345678;
++              catc_write_mem(catc, 0x7a80, buf, 4);
++              *buf = 0x87654321;
++              catc_write_mem(catc, 0xfa80, buf, 4);
++              catc_read_mem(catc, 0x7a80, buf, 4);
+         
+-              switch (i) {
++              switch (*buf) {
+               case 0x12345678:
+                       catc_set_reg(catc, TxBufCount, 8);
+                       catc_set_reg(catc, RxBufCount, 32);
+@@ -868,6 +873,8 @@ static int catc_probe(struct usb_interface *intf, const 
struct usb_device_id *id
+                       dev_dbg(dev, "32k Memory\n");
+                       break;
+               }
++
++              kfree(buf);
+         
+               dev_dbg(dev, "Getting MAC from SEEROM.\n");
+         
+@@ -914,16 +921,21 @@ static int catc_probe(struct usb_interface *intf, const 
struct usb_device_id *id
+       usb_set_intfdata(intf, catc);
+ 
+       SET_NETDEV_DEV(netdev, &intf->dev);
+-      if (register_netdev(netdev) != 0) {
+-              usb_set_intfdata(intf, NULL);
+-              usb_free_urb(catc->ctrl_urb);
+-              usb_free_urb(catc->tx_urb);
+-              usb_free_urb(catc->rx_urb);
+-              usb_free_urb(catc->irq_urb);
+-              free_netdev(netdev);
+-              return -EIO;
+-      }
++      ret = register_netdev(netdev);
++      if (ret)
++              goto fail_clear_intfdata;
++
+       return 0;
++
++fail_clear_intfdata:
++      usb_set_intfdata(intf, NULL);
++fail_free:
++      usb_free_urb(catc->ctrl_urb);
++      usb_free_urb(catc->tx_urb);
++      usb_free_urb(catc->rx_urb);
++      usb_free_urb(catc->irq_urb);
++      free_netdev(netdev);
++      return ret;
+ }
+ 
+ static void catc_disconnect(struct usb_interface *intf)
+diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
+index 1434e5dd5f9c..ee40ac23507a 100644
+--- a/drivers/net/usb/pegasus.c
++++ b/drivers/net/usb/pegasus.c
+@@ -126,40 +126,61 @@ static void async_ctrl_callback(struct urb *urb)
+ 
+ static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void 
*data)
+ {
++      u8 *buf;
+       int ret;
+ 
++      buf = kmalloc(size, GFP_NOIO);
++      if (!buf)
++              return -ENOMEM;
++
+       ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
+                             PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
+-                            indx, data, size, 1000);
++                            indx, buf, size, 1000);
+       if (ret < 0)
+               netif_dbg(pegasus, drv, pegasus->net,
+                         "%s returned %d\n", __func__, ret);
++      else if (ret <= size)
++              memcpy(data, buf, ret);
++      kfree(buf);
+       return ret;
+ }
+ 
+-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void 
*data)
++static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
++                       const void *data)
+ {
++      u8 *buf;
+       int ret;
+ 
++      buf = kmemdup(data, size, GFP_NOIO);
++      if (!buf)
++              return -ENOMEM;
++
+       ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
+                             PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
+-                            indx, data, size, 100);
++                            indx, buf, size, 100);
+       if (ret < 0)
+               netif_dbg(pegasus, drv, pegasus->net,
+                         "%s returned %d\n", __func__, ret);
++      kfree(buf);
+       return ret;
+ }
+ 
+ static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
+ {
++      u8 *buf;
+       int ret;
+ 
++      buf = kmemdup(&data, 1, GFP_NOIO);
++      if (!buf)
++              return -ENOMEM;
++
+       ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
+                             PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
+-                            indx, &data, 1, 1000);
++                            indx, buf, 1, 1000);
+       if (ret < 0)
+               netif_dbg(pegasus, drv, pegasus->net,
+                         "%s returned %d\n", __func__, ret);
++      kfree(buf);
+       return ret;
+ }
+ 
+diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
+index 7c72bfac89d0..dc4f7ea95c9b 100644
+--- a/drivers/net/usb/rtl8150.c
++++ b/drivers/net/usb/rtl8150.c
+@@ -155,16 +155,36 @@ static const char driver_name [] = "rtl8150";
+ */
+ static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
+ {
+-      return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+-                             RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
+-                             indx, 0, data, size, 500);
++      void *buf;
++      int ret;
++
++      buf = kmalloc(size, GFP_NOIO);
++      if (!buf)
++              return -ENOMEM;
++
++      ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
++                            RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
++                            indx, 0, buf, size, 500);
++      if (ret > 0 && ret <= size)
++              memcpy(data, buf, ret);
++      kfree(buf);
++      return ret;
+ }
+ 
+-static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
++static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void 
*data)
+ {
+-      return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+-                             RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
+-                             indx, 0, data, size, 500);
++      void *buf;
++      int ret;
++
++      buf = kmemdup(data, size, GFP_NOIO);
++      if (!buf)
++              return -ENOMEM;
++
++      ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
++                            RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
++                            indx, 0, buf, size, 500);
++      kfree(buf);
++      return ret;
+ }
+ 
+ static void async_set_reg_cb(struct urb *urb)
+diff --git a/include/linux/can/core.h b/include/linux/can/core.h
+index a0875001b13c..df08a41d5be5 100644
+--- a/include/linux/can/core.h
++++ b/include/linux/can/core.h
+@@ -45,10 +45,9 @@ struct can_proto {
+ extern int  can_proto_register(const struct can_proto *cp);
+ extern void can_proto_unregister(const struct can_proto *cp);
+ 
+-extern int  can_rx_register(struct net_device *dev, canid_t can_id,
+-                          canid_t mask,
+-                          void (*func)(struct sk_buff *, void *),
+-                          void *data, char *ident);
++int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
++                  void (*func)(struct sk_buff *, void *),
++                  void *data, char *ident, struct sock *sk);
+ 
+ extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
+                             canid_t mask,
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index d83590ef74a1..bb9b102c15cd 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -1508,6 +1508,7 @@ enum netdev_priv_flags {
+  *    @mtu:           Interface MTU value
+  *    @type:          Interface hardware type
+  *    @hard_header_len: Maximum hardware header length.
++ *    @min_header_len:  Minimum hardware header length
+  *
+  *    @needed_headroom: Extra headroom the hardware may need, but not in all
+  *                      cases can this be guaranteed
+@@ -1728,6 +1729,7 @@ struct net_device {
+       unsigned int            mtu;
+       unsigned short          type;
+       unsigned short          hard_header_len;
++      unsigned short          min_header_len;
+ 
+       unsigned short          needed_headroom;
+       unsigned short          needed_tailroom;
+@@ -2783,6 +2785,8 @@ static inline bool dev_validate_header(const struct 
net_device *dev,
+ {
+       if (likely(len >= dev->hard_header_len))
+               return true;
++      if (len < dev->min_header_len)
++              return false;
+ 
+       if (capable(CAP_SYS_RAWIO)) {
+               memset(ll_header + len, 0, dev->hard_header_len - len);
+diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
+index 3ebb168b9afc..a34b141f125f 100644
+--- a/include/net/cipso_ipv4.h
++++ b/include/net/cipso_ipv4.h
+@@ -309,6 +309,10 @@ static inline int cipso_v4_validate(const struct sk_buff 
*skb,
+       }
+ 
+       for (opt_iter = 6; opt_iter < opt_len;) {
++              if (opt_iter + 1 == opt_len) {
++                      err_offset = opt_iter;
++                      goto out;
++              }
+               tag_len = opt[opt_iter + 1];
+               if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
+                       err_offset = opt_iter + 1;
+diff --git a/include/net/ipv6.h b/include/net/ipv6.h
+index f11ca837361b..7f15f95625e7 100644
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -871,7 +871,7 @@ int ip6_rcv_finish(struct net *net, struct sock *sk, 
struct sk_buff *skb);
+  *    upper-layer output functions
+  */
+ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
+-           struct ipv6_txoptions *opt, int tclass);
++           __u32 mark, struct ipv6_txoptions *opt, int tclass);
+ 
+ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
+ 
+diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
+index fc7c0dbdd1ff..3f40132e2129 100644
+--- a/include/net/lwtunnel.h
++++ b/include/net/lwtunnel.h
+@@ -176,7 +176,10 @@ static inline int lwtunnel_valid_encap_type(u16 
encap_type)
+ }
+ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len)
+ {
+-      return -EOPNOTSUPP;
++      /* return 0 since we are not walking attr looking for
++       * RTA_ENCAP_TYPE attribute on nexthops.
++       */
++      return 0;
+ }
+ 
+ static inline int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
+diff --git a/net/can/af_can.c b/net/can/af_can.c
+index 1108079d934f..5488e4a6ccd0 100644
+--- a/net/can/af_can.c
++++ b/net/can/af_can.c
+@@ -445,6 +445,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, 
canid_t *mask,
+  * @func: callback function on filter match
+  * @data: returned parameter for callback function
+  * @ident: string for calling module identification
++ * @sk: socket pointer (might be NULL)
+  *
+  * Description:
+  *  Invokes the callback function with the received sk_buff and the given
+@@ -468,7 +469,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, 
canid_t *mask,
+  */
+ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
+                   void (*func)(struct sk_buff *, void *), void *data,
+-                  char *ident)
++                  char *ident, struct sock *sk)
+ {
+       struct receiver *r;
+       struct hlist_head *rl;
+@@ -496,6 +497,7 @@ int can_rx_register(struct net_device *dev, canid_t 
can_id, canid_t mask,
+               r->func    = func;
+               r->data    = data;
+               r->ident   = ident;
++              r->sk      = sk;
+ 
+               hlist_add_head_rcu(&r->list, rl);
+               d->entries++;
+@@ -520,8 +522,11 @@ EXPORT_SYMBOL(can_rx_register);
+ static void can_rx_delete_receiver(struct rcu_head *rp)
+ {
+       struct receiver *r = container_of(rp, struct receiver, rcu);
++      struct sock *sk = r->sk;
+ 
+       kmem_cache_free(rcv_cache, r);
++      if (sk)
++              sock_put(sk);
+ }
+ 
+ /**
+@@ -596,8 +601,11 @@ void can_rx_unregister(struct net_device *dev, canid_t 
can_id, canid_t mask,
+       spin_unlock(&can_rcvlists_lock);
+ 
+       /* schedule the receiver item for deletion */
+-      if (r)
++      if (r) {
++              if (r->sk)
++                      sock_hold(r->sk);
+               call_rcu(&r->rcu, can_rx_delete_receiver);
++      }
+ }
+ EXPORT_SYMBOL(can_rx_unregister);
+ 
+diff --git a/net/can/af_can.h b/net/can/af_can.h
+index fca0fe9fc45a..b86f5129e838 100644
+--- a/net/can/af_can.h
++++ b/net/can/af_can.h
+@@ -50,13 +50,14 @@
+ 
+ struct receiver {
+       struct hlist_node list;
+-      struct rcu_head rcu;
+       canid_t can_id;
+       canid_t mask;
+       unsigned long matches;
+       void (*func)(struct sk_buff *, void *);
+       void *data;
+       char *ident;
++      struct sock *sk;
++      struct rcu_head rcu;
+ };
+ 
+ #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
+diff --git a/net/can/bcm.c b/net/can/bcm.c
+index 5e9ed5ec2860..e4f694dfcf83 100644
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -1225,7 +1225,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, 
struct msghdr *msg,
+                               err = can_rx_register(dev, op->can_id,
+                                                     REGMASK(op->can_id),
+                                                     bcm_rx_handler, op,
+-                                                    "bcm");
++                                                    "bcm", sk);
+ 
+                               op->rx_reg_dev = dev;
+                               dev_put(dev);
+@@ -1234,7 +1234,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, 
struct msghdr *msg,
+               } else
+                       err = can_rx_register(NULL, op->can_id,
+                                             REGMASK(op->can_id),
+-                                            bcm_rx_handler, op, "bcm");
++                                            bcm_rx_handler, op, "bcm", sk);
+               if (err) {
+                       /* this bcm rx op is broken -> remove it */
+                       list_del(&op->list);
+diff --git a/net/can/gw.c b/net/can/gw.c
+index 455168718c2e..77c8af4047ef 100644
+--- a/net/can/gw.c
++++ b/net/can/gw.c
+@@ -442,7 +442,7 @@ static inline int cgw_register_filter(struct cgw_job *gwj)
+ {
+       return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
+                              gwj->ccgw.filter.can_mask, can_can_gw_rcv,
+-                             gwj, "gw");
++                             gwj, "gw", NULL);
+ }
+ 
+ static inline void cgw_unregister_filter(struct cgw_job *gwj)
+diff --git a/net/can/raw.c b/net/can/raw.c
+index b075f028d7e2..6dc546a06673 100644
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -190,7 +190,7 @@ static int raw_enable_filters(struct net_device *dev, 
struct sock *sk,
+       for (i = 0; i < count; i++) {
+               err = can_rx_register(dev, filter[i].can_id,
+                                     filter[i].can_mask,
+-                                    raw_rcv, sk, "raw");
++                                    raw_rcv, sk, "raw", sk);
+               if (err) {
+                       /* clean up successfully registered filters */
+                       while (--i >= 0)
+@@ -211,7 +211,7 @@ static int raw_enable_errfilter(struct net_device *dev, 
struct sock *sk,
+ 
+       if (err_mask)
+               err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
+-                                    raw_rcv, sk, "raw");
++                                    raw_rcv, sk, "raw", sk);
+ 
+       return err;
+ }
+diff --git a/net/core/dev.c b/net/core/dev.c
+index df51c50927ab..60b0a6049e72 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -1696,24 +1696,19 @@ EXPORT_SYMBOL_GPL(net_dec_egress_queue);
+ 
+ static struct static_key netstamp_needed __read_mostly;
+ #ifdef HAVE_JUMP_LABEL
+-/* We are not allowed to call static_key_slow_dec() from irq context
+- * If net_disable_timestamp() is called from irq context, defer the
+- * static_key_slow_dec() calls.
+- */
+ static atomic_t netstamp_needed_deferred;
+-#endif
+-
+-void net_enable_timestamp(void)
++static void netstamp_clear(struct work_struct *work)
+ {
+-#ifdef HAVE_JUMP_LABEL
+       int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
+ 
+-      if (deferred) {
+-              while (--deferred)
+-                      static_key_slow_dec(&netstamp_needed);
+-              return;
+-      }
++      while (deferred--)
++              static_key_slow_dec(&netstamp_needed);
++}
++static DECLARE_WORK(netstamp_work, netstamp_clear);
+ #endif
++
++void net_enable_timestamp(void)
++{
+       static_key_slow_inc(&netstamp_needed);
+ }
+ EXPORT_SYMBOL(net_enable_timestamp);
+@@ -1721,12 +1716,12 @@ EXPORT_SYMBOL(net_enable_timestamp);
+ void net_disable_timestamp(void)
+ {
+ #ifdef HAVE_JUMP_LABEL
+-      if (in_interrupt()) {
+-              atomic_inc(&netstamp_needed_deferred);
+-              return;
+-      }
+-#endif
++      /* net_disable_timestamp() can be called from non process context */
++      atomic_inc(&netstamp_needed_deferred);
++      schedule_work(&netstamp_work);
++#else
+       static_key_slow_dec(&netstamp_needed);
++#endif
+ }
+ EXPORT_SYMBOL(net_disable_timestamp);
+ 
+diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
+index 715e5d1dc107..7506c03a7db9 100644
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -227,7 +227,7 @@ static int dccp_v6_send_response(const struct sock *sk, 
struct request_sock *req
+               opt = ireq->ipv6_opt;
+               if (!opt)
+                       opt = rcu_dereference(np->opt);
+-              err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
++              err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass);
+               rcu_read_unlock();
+               err = net_xmit_eval(err);
+       }
+@@ -281,7 +281,7 @@ static void dccp_v6_ctl_send_reset(const struct sock *sk, 
struct sk_buff *rxskb)
+       dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
+       if (!IS_ERR(dst)) {
+               skb_dst_set(skb, dst);
+-              ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
++              ip6_xmit(ctl_sk, skb, &fl6, 0, NULL, 0);
+               DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
+               DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
+               return;
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index da3862124545..0f99297b2fb3 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -273,6 +273,7 @@ static int dsa_user_port_apply(struct device_node *port, 
u32 index,
+       if (err) {
+               dev_warn(ds->dev, "Failed to create slave %d: %d\n",
+                        index, err);
++              ds->ports[index].netdev = NULL;
+               return err;
+       }
+ 
+diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
+index 02acfff36028..24d7aff8db1a 100644
+--- a/net/ethernet/eth.c
++++ b/net/ethernet/eth.c
+@@ -356,6 +356,7 @@ void ether_setup(struct net_device *dev)
+       dev->header_ops         = &eth_header_ops;
+       dev->type               = ARPHRD_ETHER;
+       dev->hard_header_len    = ETH_HLEN;
++      dev->min_header_len     = ETH_HLEN;
+       dev->mtu                = ETH_DATA_LEN;
+       dev->addr_len           = ETH_ALEN;
+       dev->tx_queue_len       = 1000; /* Ethernet wants good queues */
+diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
+index 72d6f056d863..ae206163c273 100644
+--- a/net/ipv4/cipso_ipv4.c
++++ b/net/ipv4/cipso_ipv4.c
+@@ -1587,6 +1587,10 @@ int cipso_v4_validate(const struct sk_buff *skb, 
unsigned char **option)
+                               goto validate_return_locked;
+                       }
+ 
++              if (opt_iter + 1 == opt_len) {
++                      err_offset = opt_iter;
++                      goto validate_return_locked;
++              }
+               tag_len = tag[1];
+               if (tag_len > (opt_len - opt_iter)) {
+                       err_offset = opt_iter + 1;
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index 32a08bc010bf..1bc623d7f754 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -1172,6 +1172,7 @@ static void igmpv3_del_delrec(struct in_device *in_dev, 
struct ip_mc_list *im)
+                               psf->sf_crcount = im->crcount;
+               }
+               in_dev_put(pmc->interface);
++              kfree(pmc);
+       }
+       spin_unlock_bh(&im->lock);
+ }
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 877bdb02e887..e5c1dbef3626 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -1606,6 +1606,7 @@ void ip_send_unicast_reply(struct sock *sk, struct 
sk_buff *skb,
+       sk->sk_protocol = ip_hdr(skb)->protocol;
+       sk->sk_bound_dev_if = arg->bound_dev_if;
+       sk->sk_sndbuf = sysctl_wmem_default;
++      sk->sk_mark = fl4.flowi4_mark;
+       err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
+                            len, 0, &ipc, &rt, MSG_DONTWAIT);
+       if (unlikely(err)) {
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index f226f4086e05..65336f38a5d8 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -1215,7 +1215,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct 
sk_buff *skb)
+               pktinfo->ipi_ifindex = 0;
+               pktinfo->ipi_spec_dst.s_addr = 0;
+       }
+-      skb_dst_drop(skb);
++      /* We need to keep the dst for __ip_options_echo()
++       * We could restrict the test to opt.ts_needtime || opt.srr,
++       * but the following is good enough as IP options are not often used.
++       */
++      if (unlikely(IPCB(skb)->opt.optlen))
++              skb_dst_force(skb);
++      else
++              skb_dst_drop(skb);
+ }
+ 
+ int ip_setsockopt(struct sock *sk, int level,
+diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
+index 96b8e2b95731..105c0748c52f 100644
+--- a/net/ipv4/ping.c
++++ b/net/ipv4/ping.c
+@@ -642,6 +642,8 @@ static int ping_v4_push_pending_frames(struct sock *sk, 
struct pingfakehdr *pfh,
+ {
+       struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
+ 
++      if (!skb)
++              return 0;
+       pfh->wcheck = csum_partial((char *)&pfh->icmph,
+               sizeof(struct icmphdr), pfh->wcheck);
+       pfh->icmph.checksum = csum_fold(pfh->wcheck);
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 814af89c1bd3..6a90a0e130dc 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -772,6 +772,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
+                               ret = -EAGAIN;
+                               break;
+                       }
++                      /* if __tcp_splice_read() got nothing while we have
++                       * an skb in receive queue, we do not want to loop.
++                       * This might happen with URG data.
++                       */
++                      if (!skb_queue_empty(&sk->sk_receive_queue))
++                              break;
+                       sk_wait_data(sk, &timeo, NULL);
+                       if (signal_pending(current)) {
+                               ret = sock_intr_errno(timeo);
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 896e9dfbdb5c..65d6189140bc 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -2436,9 +2436,11 @@ u32 __tcp_select_window(struct sock *sk)
+       int full_space = min_t(int, tp->window_clamp, allowed_space);
+       int window;
+ 
+-      if (mss > full_space)
++      if (unlikely(mss > full_space)) {
+               mss = full_space;
+-
++              if (mss <= 0)
++                      return 0;
++      }
+       if (free_space < (full_space >> 1)) {
+               icsk->icsk_ack.quick = 0;
+ 
+diff --git a/net/ipv6/inet6_connection_sock.c 
b/net/ipv6/inet6_connection_sock.c
+index 532c3ef282c5..798a0950e9a6 100644
+--- a/net/ipv6/inet6_connection_sock.c
++++ b/net/ipv6/inet6_connection_sock.c
+@@ -173,7 +173,7 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, 
struct flowi *fl_unused
+       /* Restore final destination back after routing done */
+       fl6.daddr = sk->sk_v6_daddr;
+ 
+-      res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
++      res = ip6_xmit(sk, skb, &fl6, sk->sk_mark, rcu_dereference(np->opt),
+                      np->tclass);
+       rcu_read_unlock();
+       return res;
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index d7d6d3ae0b3b..0a5922055da2 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -367,35 +367,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
+ 
+ 
+ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+-              u8 type, u8 code, int offset, __be32 info)
++                     u8 type, u8 code, int offset, __be32 info)
+ {
+-      const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data;
+-      __be16 *p = (__be16 *)(skb->data + offset);
+-      int grehlen = offset + 4;
++      const struct gre_base_hdr *greh;
++      const struct ipv6hdr *ipv6h;
++      int grehlen = sizeof(*greh);
+       struct ip6_tnl *t;
++      int key_off = 0;
+       __be16 flags;
++      __be32 key;
+ 
+-      flags = p[0];
+-      if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
+-              if (flags&(GRE_VERSION|GRE_ROUTING))
+-                      return;
+-              if (flags&GRE_KEY) {
+-                      grehlen += 4;
+-                      if (flags&GRE_CSUM)
+-                              grehlen += 4;
+-              }
++      if (!pskb_may_pull(skb, offset + grehlen))
++              return;
++      greh = (const struct gre_base_hdr *)(skb->data + offset);
++      flags = greh->flags;
++      if (flags & (GRE_VERSION | GRE_ROUTING))
++              return;
++      if (flags & GRE_CSUM)
++              grehlen += 4;
++      if (flags & GRE_KEY) {
++              key_off = grehlen + offset;
++              grehlen += 4;
+       }
+ 
+-      /* If only 8 bytes returned, keyed message will be dropped here */
+-      if (!pskb_may_pull(skb, grehlen))
++      if (!pskb_may_pull(skb, offset + grehlen))
+               return;
+       ipv6h = (const struct ipv6hdr *)skb->data;
+-      p = (__be16 *)(skb->data + offset);
++      greh = (const struct gre_base_hdr *)(skb->data + offset);
++      key = key_off ? *(__be32 *)(skb->data + key_off) : 0;
+ 
+       t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
+-                              flags & GRE_KEY ?
+-                              *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
+-                              p[1]);
++                               key, greh->protocol);
+       if (!t)
+               return;
+ 
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 59eb4ed99ce8..9a87bfb2ec16 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -163,7 +163,7 @@ int ip6_output(struct net *net, struct sock *sk, struct 
sk_buff *skb)
+  * which are using proper atomic operations or spinlocks.
+  */
+ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
+-           struct ipv6_txoptions *opt, int tclass)
++           __u32 mark, struct ipv6_txoptions *opt, int tclass)
+ {
+       struct net *net = sock_net(sk);
+       const struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -230,7 +230,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, 
struct flowi6 *fl6,
+ 
+       skb->protocol = htons(ETH_P_IPV6);
+       skb->priority = sk->sk_priority;
+-      skb->mark = sk->sk_mark;
++      skb->mark = mark;
+ 
+       mtu = dst_mtu(dst);
+       if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
+index f95437f1087c..f6ba45242851 100644
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -400,18 +400,19 @@ ip6_tnl_dev_uninit(struct net_device *dev)
+ 
+ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
+ {
+-      const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
+-      __u8 nexthdr = ipv6h->nexthdr;
+-      __u16 off = sizeof(*ipv6h);
++      const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
++      unsigned int nhoff = raw - skb->data;
++      unsigned int off = nhoff + sizeof(*ipv6h);
++      u8 next, nexthdr = ipv6h->nexthdr;
+ 
+       while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
+-              __u16 optlen = 0;
+               struct ipv6_opt_hdr *hdr;
+-              if (raw + off + sizeof(*hdr) > skb->data &&
+-                  !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
++              u16 optlen;
++
++              if (!pskb_may_pull(skb, off + sizeof(*hdr)))
+                       break;
+ 
+-              hdr = (struct ipv6_opt_hdr *) (raw + off);
++              hdr = (struct ipv6_opt_hdr *)(skb->data + off);
+               if (nexthdr == NEXTHDR_FRAGMENT) {
+                       struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
+                       if (frag_hdr->frag_off)
+@@ -422,20 +423,29 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, 
__u8 *raw)
+               } else {
+                       optlen = ipv6_optlen(hdr);
+               }
++              /* cache hdr->nexthdr, since pskb_may_pull() might
++               * invalidate hdr
++               */
++              next = hdr->nexthdr;
+               if (nexthdr == NEXTHDR_DEST) {
+-                      __u16 i = off + 2;
++                      u16 i = 2;
++
++                      /* Remember : hdr is no longer valid at this point. */
++                      if (!pskb_may_pull(skb, off + optlen))
++                              break;
++
+                       while (1) {
+                               struct ipv6_tlv_tnl_enc_lim *tel;
+ 
+                               /* No more room for encapsulation limit */
+-                              if (i + sizeof (*tel) > off + optlen)
++                              if (i + sizeof(*tel) > optlen)
+                                       break;
+ 
+-                              tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
++                              tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data 
+ off + i);
+                               /* return index of option if found and valid */
+                               if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
+                                   tel->length == 1)
+-                                      return i;
++                                      return i + off - nhoff;
+                               /* else jump to next option */
+                               if (tel->type)
+                                       i += tel->length + 2;
+@@ -443,7 +453,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 
*raw)
+                                       i++;
+                       }
+               }
+-              nexthdr = hdr->nexthdr;
++              nexthdr = next;
+               off += optlen;
+       }
+       return 0;
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index 14a3903f1c82..1bdc703cb966 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -81,7 +81,7 @@ static void mld_gq_timer_expire(unsigned long data);
+ static void mld_ifc_timer_expire(unsigned long data);
+ static void mld_ifc_event(struct inet6_dev *idev);
+ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
+-static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr 
*addr);
++static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
+ static void mld_clear_delrec(struct inet6_dev *idev);
+ static bool mld_in_v1_mode(const struct inet6_dev *idev);
+ static int sf_setstate(struct ifmcaddr6 *pmc);
+@@ -692,9 +692,9 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
+                       dev_mc_del(dev, buf);
+       }
+ 
+-      if (mc->mca_flags & MAF_NOREPORT)
+-              goto done;
+       spin_unlock_bh(&mc->mca_lock);
++      if (mc->mca_flags & MAF_NOREPORT)
++              return;
+ 
+       if (!mc->idev->dead)
+               igmp6_leave_group(mc);
+@@ -702,8 +702,6 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
+       spin_lock_bh(&mc->mca_lock);
+       if (del_timer(&mc->mca_timer))
+               atomic_dec(&mc->mca_refcnt);
+-done:
+-      ip6_mc_clear_src(mc);
+       spin_unlock_bh(&mc->mca_lock);
+ }
+ 
+@@ -748,10 +746,11 @@ static void mld_add_delrec(struct inet6_dev *idev, 
struct ifmcaddr6 *im)
+       spin_unlock_bh(&idev->mc_lock);
+ }
+ 
+-static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr 
*pmca)
++static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
+ {
+       struct ifmcaddr6 *pmc, *pmc_prev;
+-      struct ip6_sf_list *psf, *psf_next;
++      struct ip6_sf_list *psf;
++      struct in6_addr *pmca = &im->mca_addr;
+ 
+       spin_lock_bh(&idev->mc_lock);
+       pmc_prev = NULL;
+@@ -768,14 +767,21 @@ static void mld_del_delrec(struct inet6_dev *idev, const 
struct in6_addr *pmca)
+       }
+       spin_unlock_bh(&idev->mc_lock);
+ 
++      spin_lock_bh(&im->mca_lock);
+       if (pmc) {
+-              for (psf = pmc->mca_tomb; psf; psf = psf_next) {
+-                      psf_next = psf->sf_next;
+-                      kfree(psf);
++              im->idev = pmc->idev;
++              im->mca_crcount = idev->mc_qrv;
++              im->mca_sfmode = pmc->mca_sfmode;
++              if (pmc->mca_sfmode == MCAST_INCLUDE) {
++                      im->mca_tomb = pmc->mca_tomb;
++                      im->mca_sources = pmc->mca_sources;
++                      for (psf = im->mca_sources; psf; psf = psf->sf_next)
++                              psf->sf_crcount = im->mca_crcount;
+               }
+               in6_dev_put(pmc->idev);
+               kfree(pmc);
+       }
++      spin_unlock_bh(&im->mca_lock);
+ }
+ 
+ static void mld_clear_delrec(struct inet6_dev *idev)
+@@ -904,7 +910,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct 
in6_addr *addr)
+       mca_get(mc);
+       write_unlock_bh(&idev->lock);
+ 
+-      mld_del_delrec(idev, &mc->mca_addr);
++      mld_del_delrec(idev, mc);
+       igmp6_group_added(mc);
+       ma_put(mc);
+       return 0;
+@@ -927,6 +933,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct 
in6_addr *addr)
+                               write_unlock_bh(&idev->lock);
+ 
+                               igmp6_group_dropped(ma);
++                              ip6_mc_clear_src(ma);
+ 
+                               ma_put(ma);
+                               return 0;
+@@ -2501,15 +2508,17 @@ void ipv6_mc_down(struct inet6_dev *idev)
+       /* Withdraw multicast list */
+ 
+       read_lock_bh(&idev->lock);
+-      mld_ifc_stop_timer(idev);
+-      mld_gq_stop_timer(idev);
+-      mld_dad_stop_timer(idev);
+ 
+       for (i = idev->mc_list; i; i = i->next)
+               igmp6_group_dropped(i);
+-      read_unlock_bh(&idev->lock);
+ 
+-      mld_clear_delrec(idev);
++      /* Should stop timer after group drop. or we will
++       * start timer again in mld_ifc_event()
++       */
++      mld_ifc_stop_timer(idev);
++      mld_gq_stop_timer(idev);
++      mld_dad_stop_timer(idev);
++      read_unlock_bh(&idev->lock);
+ }
+ 
+ static void ipv6_mc_reset(struct inet6_dev *idev)
+@@ -2531,8 +2540,10 @@ void ipv6_mc_up(struct inet6_dev *idev)
+ 
+       read_lock_bh(&idev->lock);
+       ipv6_mc_reset(idev);
+-      for (i = idev->mc_list; i; i = i->next)
++      for (i = idev->mc_list; i; i = i->next) {
++              mld_del_delrec(idev, i);
+               igmp6_group_added(i);
++      }
+       read_unlock_bh(&idev->lock);
+ }
+ 
+@@ -2565,6 +2576,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
+ 
+       /* Deactivate timers */
+       ipv6_mc_down(idev);
++      mld_clear_delrec(idev);
+ 
+       /* Delete all-nodes address. */
+       /* We cannot call ipv6_dev_mc_dec() directly, our caller in
+@@ -2579,11 +2591,9 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
+       write_lock_bh(&idev->lock);
+       while ((i = idev->mc_list) != NULL) {
+               idev->mc_list = i->next;
+-              write_unlock_bh(&idev->lock);
+ 
+-              igmp6_group_dropped(i);
++              write_unlock_bh(&idev->lock);
+               ma_put(i);
+-
+               write_lock_bh(&idev->lock);
+       }
+       write_unlock_bh(&idev->lock);
+diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
+index b1cdf8009d29..40d740572354 100644
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -1390,6 +1390,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
+       err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+       if (err) {
+               free_percpu(dev->tstats);
++              dev->tstats = NULL;
+               return err;
+       }
+ 
+diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
+index b9f1fee9a886..667396536feb 100644
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -467,7 +467,7 @@ static int tcp_v6_send_synack(const struct sock *sk, 
struct dst_entry *dst,
+               opt = ireq->ipv6_opt;
+               if (!opt)
+                       opt = rcu_dereference(np->opt);
+-              err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
++              err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt, np->tclass);
+               rcu_read_unlock();
+               err = net_xmit_eval(err);
+       }
+@@ -837,7 +837,7 @@ static void tcp_v6_send_response(const struct sock *sk, 
struct sk_buff *skb, u32
+       dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
+       if (!IS_ERR(dst)) {
+               skb_dst_set(buff, dst);
+-              ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
++              ip6_xmit(ctl_sk, buff, &fl6, fl6.flowi6_mark, NULL, tclass);
+               TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
+               if (rst)
+                       TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
+@@ -987,6 +987,16 @@ static int tcp_v6_conn_request(struct sock *sk, struct 
sk_buff *skb)
+       return 0; /* don't send reset */
+ }
+ 
++static void tcp_v6_restore_cb(struct sk_buff *skb)
++{
++      /* We need to move header back to the beginning if xfrm6_policy_check()
++       * and tcp_v6_fill_cb() are going to be called again.
++       * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
++       */
++      memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
++              sizeof(struct inet6_skb_parm));
++}
++
+ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct 
sk_buff *skb,
+                                        struct request_sock *req,
+                                        struct dst_entry *dst,
+@@ -1178,8 +1188,10 @@ static struct sock *tcp_v6_syn_recv_sock(const struct 
sock *sk, struct sk_buff *
+                                                     sk_gfp_mask(sk, 
GFP_ATOMIC));
+                       consume_skb(ireq->pktopts);
+                       ireq->pktopts = NULL;
+-                      if (newnp->pktoptions)
++                      if (newnp->pktoptions) {
++                              tcp_v6_restore_cb(newnp->pktoptions);
+                               skb_set_owner_r(newnp->pktoptions, newsk);
++                      }
+               }
+       }
+ 
+@@ -1194,16 +1206,6 @@ static struct sock *tcp_v6_syn_recv_sock(const struct 
sock *sk, struct sk_buff *
+       return NULL;
+ }
+ 
+-static void tcp_v6_restore_cb(struct sk_buff *skb)
+-{
+-      /* We need to move header back to the beginning if xfrm6_policy_check()
+-       * and tcp_v6_fill_cb() are going to be called again.
+-       * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
+-       */
+-      memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
+-              sizeof(struct inet6_skb_parm));
+-}
+-
+ /* The socket must have it's spinlock held when we get
+  * here, unless it is a TCP_LISTEN socket.
+  *
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
+index 2599af6378e4..181e755c2fc4 100644
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -273,6 +273,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct 
sk_buff *skb,
+ int l2tp_nl_register_ops(enum l2tp_pwtype pw_type,
+                        const struct l2tp_nl_cmd_ops *ops);
+ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
++int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+ 
+ /* Session reference counts. Incremented when code obtains a reference
+  * to a session.
+diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
+index 8938b6ba57a0..c0f0750639bd 100644
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -11,6 +11,7 @@
+ 
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+ 
++#include <asm/ioctls.h>
+ #include <linux/icmp.h>
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+@@ -560,6 +561,30 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr 
*msg,
+       return err ? err : copied;
+ }
+ 
++int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++{
++      struct sk_buff *skb;
++      int amount;
++
++      switch (cmd) {
++      case SIOCOUTQ:
++              amount = sk_wmem_alloc_get(sk);
++              break;
++      case SIOCINQ:
++              spin_lock_bh(&sk->sk_receive_queue.lock);
++              skb = skb_peek(&sk->sk_receive_queue);
++              amount = skb ? skb->len : 0;
++              spin_unlock_bh(&sk->sk_receive_queue.lock);
++              break;
++
++      default:
++              return -ENOIOCTLCMD;
++      }
++
++      return put_user(amount, (int __user *)arg);
++}
++EXPORT_SYMBOL(l2tp_ioctl);
++
+ static struct proto l2tp_ip_prot = {
+       .name              = "L2TP/IP",
+       .owner             = THIS_MODULE,
+@@ -568,7 +593,7 @@ static struct proto l2tp_ip_prot = {
+       .bind              = l2tp_ip_bind,
+       .connect           = l2tp_ip_connect,
+       .disconnect        = l2tp_ip_disconnect,
+-      .ioctl             = udp_ioctl,
++      .ioctl             = l2tp_ioctl,
+       .destroy           = l2tp_ip_destroy_sock,
+       .setsockopt        = ip_setsockopt,
+       .getsockopt        = ip_getsockopt,
+diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
+index aa821cb639e5..1a65c9a517b6 100644
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -729,7 +729,7 @@ static struct proto l2tp_ip6_prot = {
+       .bind              = l2tp_ip6_bind,
+       .connect           = l2tp_ip6_connect,
+       .disconnect        = l2tp_ip6_disconnect,
+-      .ioctl             = udp_ioctl,
++      .ioctl             = l2tp_ioctl,
+       .destroy           = l2tp_ip6_destroy_sock,
+       .setsockopt        = ipv6_setsockopt,
+       .getsockopt        = ipv6_getsockopt,
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index 94e4a5941d89..458722b938c7 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -2813,7 +2813,7 @@ static int packet_snd(struct socket *sock, struct msghdr 
*msg, size_t len)
+       struct virtio_net_hdr vnet_hdr = { 0 };
+       int offset = 0;
+       struct packet_sock *po = pkt_sk(sk);
+-      int hlen, tlen;
++      int hlen, tlen, linear;
+       int extra_len = 0;
+ 
+       /*
+@@ -2874,8 +2874,9 @@ static int packet_snd(struct socket *sock, struct msghdr 
*msg, size_t len)
+       err = -ENOBUFS;
+       hlen = LL_RESERVED_SPACE(dev);
+       tlen = dev->needed_tailroom;
+-      skb = packet_alloc_skb(sk, hlen + tlen, hlen, len,
+-                             __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len),
++      linear = __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len);
++      linear = max(linear, min_t(int, len, dev->hard_header_len));
++      skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, linear,
+                              msg->msg_flags & MSG_DONTWAIT, &err);
+       if (skb == NULL)
+               goto out_unlock;
+diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
+index f935429bd5ef..b12bc2abea93 100644
+--- a/net/sched/cls_matchall.c
++++ b/net/sched/cls_matchall.c
+@@ -16,16 +16,11 @@
+ #include <net/sch_generic.h>
+ #include <net/pkt_cls.h>
+ 
+-struct cls_mall_filter {
++struct cls_mall_head {
+       struct tcf_exts exts;
+       struct tcf_result res;
+       u32 handle;
+-      struct rcu_head rcu;
+       u32 flags;
+-};
+-
+-struct cls_mall_head {
+-      struct cls_mall_filter *filter;
+       struct rcu_head rcu;
+ };
+ 
+@@ -33,38 +28,29 @@ static int mall_classify(struct sk_buff *skb, const struct 
tcf_proto *tp,
+                        struct tcf_result *res)
+ {
+       struct cls_mall_head *head = rcu_dereference_bh(tp->root);
+-      struct cls_mall_filter *f = head->filter;
+ 
+-      if (tc_skip_sw(f->flags))
++      if (tc_skip_sw(head->flags))
+               return -1;
+ 
+-      return tcf_exts_exec(skb, &f->exts, res);
++      return tcf_exts_exec(skb, &head->exts, res);
+ }
+ 
+ static int mall_init(struct tcf_proto *tp)
+ {
+-      struct cls_mall_head *head;
+-
+-      head = kzalloc(sizeof(*head), GFP_KERNEL);
+-      if (!head)
+-              return -ENOBUFS;
+-
+-      rcu_assign_pointer(tp->root, head);
+-
+       return 0;
+ }
+ 
+-static void mall_destroy_filter(struct rcu_head *head)
++static void mall_destroy_rcu(struct rcu_head *rcu)
+ {
+-      struct cls_mall_filter *f = container_of(head, struct cls_mall_filter, 
rcu);
++      struct cls_mall_head *head = container_of(rcu, struct cls_mall_head,
++                                                rcu);
+ 
+-      tcf_exts_destroy(&f->exts);
+-
+-      kfree(f);
++      tcf_exts_destroy(&head->exts);
++      kfree(head);
+ }
+ 
+ static int mall_replace_hw_filter(struct tcf_proto *tp,
+-                                struct cls_mall_filter *f,
++                                struct cls_mall_head *head,
+                                 unsigned long cookie)
+ {
+       struct net_device *dev = tp->q->dev_queue->dev;
+@@ -74,7 +60,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
+       offload.type = TC_SETUP_MATCHALL;
+       offload.cls_mall = &mall_offload;
+       offload.cls_mall->command = TC_CLSMATCHALL_REPLACE;
+-      offload.cls_mall->exts = &f->exts;
++      offload.cls_mall->exts = &head->exts;
+       offload.cls_mall->cookie = cookie;
+ 
+       return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
+@@ -82,7 +68,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
+ }
+ 
+ static void mall_destroy_hw_filter(struct tcf_proto *tp,
+-                                 struct cls_mall_filter *f,
++                                 struct cls_mall_head *head,
+                                  unsigned long cookie)
+ {
+       struct net_device *dev = tp->q->dev_queue->dev;
+@@ -103,29 +89,20 @@ static bool mall_destroy(struct tcf_proto *tp, bool force)
+ {
+       struct cls_mall_head *head = rtnl_dereference(tp->root);
+       struct net_device *dev = tp->q->dev_queue->dev;
+-      struct cls_mall_filter *f = head->filter;
+ 
+-      if (!force && f)
+-              return false;
++      if (!head)
++              return true;
+ 
+-      if (f) {
+-              if (tc_should_offload(dev, tp, f->flags))
+-                      mall_destroy_hw_filter(tp, f, (unsigned long) f);
++      if (tc_should_offload(dev, tp, head->flags))
++              mall_destroy_hw_filter(tp, head, (unsigned long) head);
+ 
+-              call_rcu(&f->rcu, mall_destroy_filter);
+-      }
+-      kfree_rcu(head, rcu);
++      call_rcu(&head->rcu, mall_destroy_rcu);
+       return true;
+ }
+ 
+ static unsigned long mall_get(struct tcf_proto *tp, u32 handle)
+ {
+-      struct cls_mall_head *head = rtnl_dereference(tp->root);
+-      struct cls_mall_filter *f = head->filter;
+-
+-      if (f && f->handle == handle)
+-              return (unsigned long) f;
+-      return 0;
++      return 0UL;
+ }
+ 
+ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
+@@ -134,7 +111,7 @@ static const struct nla_policy 
mall_policy[TCA_MATCHALL_MAX + 1] = {
+ };
+ 
+ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
+-                        struct cls_mall_filter *f,
++                        struct cls_mall_head *head,
+                         unsigned long base, struct nlattr **tb,
+                         struct nlattr *est, bool ovr)
+ {
+@@ -147,11 +124,11 @@ static int mall_set_parms(struct net *net, struct 
tcf_proto *tp,
+               return err;
+ 
+       if (tb[TCA_MATCHALL_CLASSID]) {
+-              f->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
+-              tcf_bind_filter(tp, &f->res, base);
++              head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
++              tcf_bind_filter(tp, &head->res, base);
+       }
+ 
+-      tcf_exts_change(tp, &f->exts, &e);
++      tcf_exts_change(tp, &head->exts, &e);
+ 
+       return 0;
+ }
+@@ -162,21 +139,17 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
+                      unsigned long *arg, bool ovr)
+ {
+       struct cls_mall_head *head = rtnl_dereference(tp->root);
+-      struct cls_mall_filter *fold = (struct cls_mall_filter *) *arg;
+       struct net_device *dev = tp->q->dev_queue->dev;
+-      struct cls_mall_filter *f;
+       struct nlattr *tb[TCA_MATCHALL_MAX + 1];
++      struct cls_mall_head *new;
+       u32 flags = 0;
+       int err;
+ 
+       if (!tca[TCA_OPTIONS])
+               return -EINVAL;
+ 
+-      if (head->filter)
+-              return -EBUSY;
+-
+-      if (fold)
+-              return -EINVAL;
++      if (head)
++              return -EEXIST;
+ 
+       err = nla_parse_nested(tb, TCA_MATCHALL_MAX,
+                              tca[TCA_OPTIONS], mall_policy);
+@@ -189,23 +162,23 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
+                       return -EINVAL;
+       }
+ 
+-      f = kzalloc(sizeof(*f), GFP_KERNEL);
+-      if (!f)
++      new = kzalloc(sizeof(*new), GFP_KERNEL);
++      if (!new)
+               return -ENOBUFS;
+ 
+-      tcf_exts_init(&f->exts, TCA_MATCHALL_ACT, 0);
++      tcf_exts_init(&new->exts, TCA_MATCHALL_ACT, 0);
+ 
+       if (!handle)
+               handle = 1;
+-      f->handle = handle;
+-      f->flags = flags;
++      new->handle = handle;
++      new->flags = flags;
+ 
+-      err = mall_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
++      err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr);
+       if (err)
+               goto errout;
+ 
+       if (tc_should_offload(dev, tp, flags)) {
+-              err = mall_replace_hw_filter(tp, f, (unsigned long) f);
++              err = mall_replace_hw_filter(tp, new, (unsigned long) new);
+               if (err) {
+                       if (tc_skip_sw(flags))
+                               goto errout;
+@@ -214,39 +187,29 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
+               }
+       }
+ 
+-      *arg = (unsigned long) f;
+-      rcu_assign_pointer(head->filter, f);
+-
++      *arg = (unsigned long) head;
++      rcu_assign_pointer(tp->root, new);
++      if (head)
++              call_rcu(&head->rcu, mall_destroy_rcu);
+       return 0;
+ 
+ errout:
+-      kfree(f);
++      kfree(new);
+       return err;
+ }
+ 
+ static int mall_delete(struct tcf_proto *tp, unsigned long arg)
+ {
+-      struct cls_mall_head *head = rtnl_dereference(tp->root);
+-      struct cls_mall_filter *f = (struct cls_mall_filter *) arg;
+-      struct net_device *dev = tp->q->dev_queue->dev;
+-
+-      if (tc_should_offload(dev, tp, f->flags))
+-              mall_destroy_hw_filter(tp, f, (unsigned long) f);
+-
+-      RCU_INIT_POINTER(head->filter, NULL);
+-      tcf_unbind_filter(tp, &f->res);
+-      call_rcu(&f->rcu, mall_destroy_filter);
+-      return 0;
++      return -EOPNOTSUPP;
+ }
+ 
+ static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+ {
+       struct cls_mall_head *head = rtnl_dereference(tp->root);
+-      struct cls_mall_filter *f = head->filter;
+ 
+       if (arg->count < arg->skip)
+               goto skip;
+-      if (arg->fn(tp, (unsigned long) f, arg) < 0)
++      if (arg->fn(tp, (unsigned long) head, arg) < 0)
+               arg->stop = 1;
+ skip:
+       arg->count++;
+@@ -255,28 +218,28 @@ static void mall_walk(struct tcf_proto *tp, struct 
tcf_walker *arg)
+ static int mall_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
+                    struct sk_buff *skb, struct tcmsg *t)
+ {
+-      struct cls_mall_filter *f = (struct cls_mall_filter *) fh;
++      struct cls_mall_head *head = (struct cls_mall_head *) fh;
+       struct nlattr *nest;
+ 
+-      if (!f)
++      if (!head)
+               return skb->len;
+ 
+-      t->tcm_handle = f->handle;
++      t->tcm_handle = head->handle;
+ 
+       nest = nla_nest_start(skb, TCA_OPTIONS);
+       if (!nest)
+               goto nla_put_failure;
+ 
+-      if (f->res.classid &&
+-          nla_put_u32(skb, TCA_MATCHALL_CLASSID, f->res.classid))
++      if (head->res.classid &&
++          nla_put_u32(skb, TCA_MATCHALL_CLASSID, head->res.classid))
+               goto nla_put_failure;
+ 
+-      if (tcf_exts_dump(skb, &f->exts))
++      if (tcf_exts_dump(skb, &head->exts))
+               goto nla_put_failure;
+ 
+       nla_nest_end(skb, nest);
+ 
+-      if (tcf_exts_dump_stats(skb, &f->exts) < 0)
++      if (tcf_exts_dump_stats(skb, &head->exts) < 0)
+               goto nla_put_failure;
+ 
+       return skb->len;
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index 176af3080a2b..6a2532dd31c4 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -222,7 +222,8 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct 
sctp_transport *transport)
+       SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
+ 
+       rcu_read_lock();
+-      res = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), np->tclass);
++      res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt),
++                     np->tclass);
+       rcu_read_unlock();
+       return res;
+ }
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index ca12aa346c0d..6cbe5bdf2b15 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -7427,7 +7427,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association 
*asoc, long *timeo_p,
+                */
+               release_sock(sk);
+               current_timeo = schedule_timeout(current_timeo);
+-              BUG_ON(sk != asoc->base.sk);
++              if (sk != asoc->base.sk)
++                      goto do_error;
+               lock_sock(sk);
+ 
+               *timeo_p = current_timeo;

Reply via email to