diff options
Diffstat (limited to '4.9.11/1010_linux-4.9.11.patch')
-rw-r--r-- | 4.9.11/1010_linux-4.9.11.patch | 1893 |
1 files changed, 0 insertions, 1893 deletions
diff --git a/4.9.11/1010_linux-4.9.11.patch b/4.9.11/1010_linux-4.9.11.patch deleted file mode 100644 index 59eb5c7..0000000 --- a/4.9.11/1010_linux-4.9.11.patch +++ /dev/null @@ -1,1893 +0,0 @@ -diff --git a/Makefile b/Makefile -index d2fe757..18b0c5a 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 ebb4e95..96d80df 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 f2e8bed..4d3ddc2 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 71382df..81d8e3b 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 51c6a57..126cfeb 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 5dc3e24..b3067137 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 914e546..7e20e4b 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 7df4ff1..7d19029 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 6255973..1b65f0f 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 6f38daf..adea6f5 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 18402d7..b31aca8 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 d9ca05d..4086415 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 1434e5d..ee40ac2 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 7c72bfa..dc4f7ea 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 a087500..df08a41 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 d83590e..bb9b102 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 3ebb168..a34b141 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 f11ca83..7f15f95 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 fc7c0db..3f40132 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 1108079..5488e4a 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 fca0fe9..b86f512 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 5e9ed5e..e4f694d 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 4551687..77c8af4 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 b075f02..6dc546a 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 df51c50..60b0a604 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 715e5d1..7506c03 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 da38621..0f99297 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 02acfff..24d7aff 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 = ð_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 72d6f05..ae20616 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 32a08bc..1bc623d 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 877bdb0..e5c1dbe 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 f226f408..65336f3 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 96b8e2b..105c074 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 814af89..6a90a0e 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 896e9df..65d6189 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 532c3ef..798a095 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 d7d6d3a..0a59220 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 59eb4ed..9a87bfb 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 f95437f..f6ba452 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 14a3903..1bdc703 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 b1cdf80..40d7405 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 b9f1fee..6673965 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 2599af6..181e755c 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 8938b6b..c0f0750 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 aa821cb..1a65c9a 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 94e4a59..458722b 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 f935429..b12bc2a 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 176af30..6a2532d 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 ca12aa3..6cbe5bd 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; |