public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Mike Pagano" <mpagano@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:4.16 commit in: /
Date: Sun, 20 May 2018 22:22:38 +0000 (UTC)	[thread overview]
Message-ID: <1526854948.c741e5c30736c7523ab72393e932827a9179a35f.mpagano@gentoo> (raw)

commit:     c741e5c30736c7523ab72393e932827a9179a35f
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun May 20 22:22:28 2018 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun May 20 22:22:28 2018 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=c741e5c3

Linux patch 4.16.10

 0000_README              |    4 +
 1009_linux-4.16.10.patch | 1808 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1812 insertions(+)

diff --git a/0000_README b/0000_README
index 73b7e2e..89eb684 100644
--- a/0000_README
+++ b/0000_README
@@ -79,6 +79,10 @@ Patch:  1008_linux-4.16.9.patch
 From:   http://www.kernel.org
 Desc:   Linux 4.16.9
 
+Patch:  1009_linux-4.16.10.patch
+From:   http://www.kernel.org
+Desc:   Linux 4.16.10
+
 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/1009_linux-4.16.10.patch b/1009_linux-4.16.10.patch
new file mode 100644
index 0000000..7d08449
--- /dev/null
+++ b/1009_linux-4.16.10.patch
@@ -0,0 +1,1808 @@
+diff --git a/Makefile b/Makefile
+index ea3cb221d7c5..33f3c94f02ca 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 4
+ PATCHLEVEL = 16
+-SUBLEVEL = 9
++SUBLEVEL = 10
+ EXTRAVERSION =
+ NAME = Fearless Coyote
+ 
+diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
+index 7f8bda3a2005..0881f7907848 100644
+--- a/drivers/infiniband/hw/mlx5/main.c
++++ b/drivers/infiniband/hw/mlx5/main.c
+@@ -4303,7 +4303,7 @@ mlx5_ib_get_vector_affinity(struct ib_device *ibdev, int comp_vector)
+ {
+ 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
+ 
+-	return mlx5_get_vector_affinity(dev->mdev, comp_vector);
++	return mlx5_get_vector_affinity_hint(dev->mdev, comp_vector);
+ }
+ 
+ /* The mlx5_ib_multiport_mutex should be held when calling this function */
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 1ed9529e7bd1..5eb0df2e5464 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -450,7 +450,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
+ {
+ 	int i;
+ 
+-	if (!client_info->slave)
++	if (!client_info->slave || !is_valid_ether_addr(client_info->mac_dst))
+ 		return;
+ 
+ 	for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
+@@ -943,6 +943,10 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
+ 	skb->priority = TC_PRIO_CONTROL;
+ 	skb->dev = slave->dev;
+ 
++	netdev_dbg(slave->bond->dev,
++		   "Send learning packet: dev %s mac %pM vlan %d\n",
++		   slave->dev->name, mac_addr, vid);
++
+ 	if (vid)
+ 		__vlan_hwaccel_put_tag(skb, vlan_proto, vid);
+ 
+@@ -965,14 +969,13 @@ static int alb_upper_dev_walk(struct net_device *upper, void *_data)
+ 	u8 *mac_addr = data->mac_addr;
+ 	struct bond_vlan_tag *tags;
+ 
+-	if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
+-		if (strict_match &&
+-		    ether_addr_equal_64bits(mac_addr,
+-					    upper->dev_addr)) {
++	if (is_vlan_dev(upper) &&
++	    bond->nest_level == vlan_get_encap_level(upper) - 1) {
++		if (upper->addr_assign_type == NET_ADDR_STOLEN) {
+ 			alb_send_lp_vid(slave, mac_addr,
+ 					vlan_dev_vlan_proto(upper),
+ 					vlan_dev_vlan_id(upper));
+-		} else if (!strict_match) {
++		} else {
+ 			alb_send_lp_vid(slave, upper->dev_addr,
+ 					vlan_dev_vlan_proto(upper),
+ 					vlan_dev_vlan_id(upper));
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 718e4914e3a0..1f1e97b26f95 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1738,6 +1738,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ 	if (bond_mode_uses_xmit_hash(bond))
+ 		bond_update_slave_arr(bond, NULL);
+ 
++	bond->nest_level = dev_get_nest_level(bond_dev);
++
+ 	netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
+ 		    slave_dev->name,
+ 		    bond_is_active_slave(new_slave) ? "an active" : "a backup",
+diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
+index 3fc549b88c43..d61e51ebca51 100644
+--- a/drivers/net/ethernet/broadcom/bcmsysport.c
++++ b/drivers/net/ethernet/broadcom/bcmsysport.c
+@@ -2052,14 +2052,21 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
+ 	.ndo_select_queue	= bcm_sysport_select_queue,
+ };
+ 
+-static int bcm_sysport_map_queues(struct net_device *dev,
++static int bcm_sysport_map_queues(struct notifier_block *nb,
+ 				  struct dsa_notifier_register_info *info)
+ {
+-	struct bcm_sysport_priv *priv = netdev_priv(dev);
+ 	struct bcm_sysport_tx_ring *ring;
++	struct bcm_sysport_priv *priv;
+ 	struct net_device *slave_dev;
+ 	unsigned int num_tx_queues;
+ 	unsigned int q, start, port;
++	struct net_device *dev;
++
++	priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
++	if (priv->netdev != info->master)
++		return 0;
++
++	dev = info->master;
+ 
+ 	/* We can't be setting up queue inspection for non directly attached
+ 	 * switches
+@@ -2082,6 +2089,7 @@ static int bcm_sysport_map_queues(struct net_device *dev,
+ 	if (priv->is_lite)
+ 		netif_set_real_num_tx_queues(slave_dev,
+ 					     slave_dev->num_tx_queues / 2);
++
+ 	num_tx_queues = slave_dev->real_num_tx_queues;
+ 
+ 	if (priv->per_port_num_tx_queues &&
+@@ -2109,7 +2117,7 @@ static int bcm_sysport_map_queues(struct net_device *dev,
+ 	return 0;
+ }
+ 
+-static int bcm_sysport_dsa_notifier(struct notifier_block *unused,
++static int bcm_sysport_dsa_notifier(struct notifier_block *nb,
+ 				    unsigned long event, void *ptr)
+ {
+ 	struct dsa_notifier_register_info *info;
+@@ -2119,7 +2127,7 @@ static int bcm_sysport_dsa_notifier(struct notifier_block *unused,
+ 
+ 	info = ptr;
+ 
+-	return notifier_from_errno(bcm_sysport_map_queues(info->master, info));
++	return notifier_from_errno(bcm_sysport_map_queues(nb, info));
+ }
+ 
+ #define REV_FMT	"v%2x.%02x"
+diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
+index f2593978ae75..bde98a994e96 100644
+--- a/drivers/net/ethernet/broadcom/tg3.c
++++ b/drivers/net/ethernet/broadcom/tg3.c
+@@ -8733,14 +8733,15 @@ static void tg3_free_consistent(struct tg3 *tp)
+ 	tg3_mem_rx_release(tp);
+ 	tg3_mem_tx_release(tp);
+ 
+-	/* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
+-	tg3_full_lock(tp, 0);
++	/* tp->hw_stats can be referenced safely:
++	 *     1. under rtnl_lock
++	 *     2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
++	 */
+ 	if (tp->hw_stats) {
+ 		dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
+ 				  tp->hw_stats, tp->stats_mapping);
+ 		tp->hw_stats = NULL;
+ 	}
+-	tg3_full_unlock(tp);
+ }
+ 
+ /*
+@@ -14178,7 +14179,7 @@ static void tg3_get_stats64(struct net_device *dev,
+ 	struct tg3 *tp = netdev_priv(dev);
+ 
+ 	spin_lock_bh(&tp->lock);
+-	if (!tp->hw_stats) {
++	if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
+ 		*stats = tp->net_stats_prev;
+ 		spin_unlock_bh(&tp->lock);
+ 		return;
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+index f3302edba8b4..7f87db9734b8 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+@@ -1013,6 +1013,22 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
+ 	if (!coal->tx_max_coalesced_frames_irq)
+ 		return -EINVAL;
+ 
++	if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
++	    coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
++	    coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME ||
++	    coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) {
++		netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n",
++			    __func__, MLX4_EN_MAX_COAL_TIME);
++		return -ERANGE;
++	}
++
++	if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS ||
++	    coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) {
++		netdev_info(dev, "%s: maximum coalesced frames supported is %d\n",
++			    __func__, MLX4_EN_MAX_COAL_PKTS);
++		return -ERANGE;
++	}
++
+ 	priv->rx_frames = (coal->rx_max_coalesced_frames ==
+ 			   MLX4_EN_AUTO_CONF) ?
+ 				MLX4_EN_RX_COAL_TARGET :
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index 8fc51bc29003..41f8fbced11d 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -3320,12 +3320,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ 					   MAX_TX_RINGS, GFP_KERNEL);
+ 		if (!priv->tx_ring[t]) {
+ 			err = -ENOMEM;
+-			goto err_free_tx;
++			goto out;
+ 		}
+ 		priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
+ 					 MAX_TX_RINGS, GFP_KERNEL);
+ 		if (!priv->tx_cq[t]) {
+-			kfree(priv->tx_ring[t]);
+ 			err = -ENOMEM;
+ 			goto out;
+ 		}
+@@ -3578,11 +3577,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ 
+ 	return 0;
+ 
+-err_free_tx:
+-	while (t--) {
+-		kfree(priv->tx_ring[t]);
+-		kfree(priv->tx_cq[t]);
+-	}
+ out:
+ 	mlx4_en_destroy_netdev(dev);
+ 	return err;
+diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+index f470ae37d937..4dabaf025b12 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+@@ -132,6 +132,9 @@
+ #define MLX4_EN_TX_COAL_PKTS	16
+ #define MLX4_EN_TX_COAL_TIME	0x10
+ 
++#define MLX4_EN_MAX_COAL_PKTS	U16_MAX
++#define MLX4_EN_MAX_COAL_TIME	U16_MAX
++
+ #define MLX4_EN_RX_RATE_LOW		400000
+ #define MLX4_EN_RX_COAL_TIME_LOW	0
+ #define MLX4_EN_RX_RATE_HIGH		450000
+@@ -552,8 +555,8 @@ struct mlx4_en_priv {
+ 	u16 rx_usecs_low;
+ 	u32 pkt_rate_high;
+ 	u16 rx_usecs_high;
+-	u16 sample_interval;
+-	u16 adaptive_rx_coal;
++	u32 sample_interval;
++	u32 adaptive_rx_coal;
+ 	u32 msg_enable;
+ 	u32 loopback_ok;
+ 	u32 validate_loopback;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+index 3d46ef48d5b8..c641d5656b2d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+@@ -1007,12 +1007,14 @@ static void mlx5e_trust_update_sq_inline_mode(struct mlx5e_priv *priv)
+ 
+ 	mutex_lock(&priv->state_lock);
+ 
+-	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
+-		goto out;
+-
+ 	new_channels.params = priv->channels.params;
+ 	mlx5e_trust_update_tx_min_inline_mode(priv, &new_channels.params);
+ 
++	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
++		priv->channels.params = new_channels.params;
++		goto out;
++	}
++
+ 	/* Skip if tx_min_inline is the same */
+ 	if (new_channels.params.tx_min_inline_mode ==
+ 	    priv->channels.params.tx_min_inline_mode)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 43234cabf444..8665670fddbc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -1260,6 +1260,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+ 						  f->mask);
+ 		addr_type = key->addr_type;
+ 
++		/* the HW doesn't support frag first/later */
++		if (mask->flags & FLOW_DIS_FIRST_FRAG)
++			return -EOPNOTSUPP;
++
+ 		if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
+ 			MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
+ 			MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
+@@ -1863,7 +1867,8 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
+ 	}
+ 
+ 	ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol);
+-	if (modify_ip_header && ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) {
++	if (modify_ip_header && ip_proto != IPPROTO_TCP &&
++	    ip_proto != IPPROTO_UDP && ip_proto != IPPROTO_ICMP) {
+ 		pr_info("can't offload re-write of ip proto %d\n", ip_proto);
+ 		return false;
+ 	}
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+index 11b4f1089d1c..ea725664f4f2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+@@ -255,7 +255,7 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ 		dma_addr = dma_map_single(sq->pdev, skb_data, headlen,
+ 					  DMA_TO_DEVICE);
+ 		if (unlikely(dma_mapping_error(sq->pdev, dma_addr)))
+-			return -ENOMEM;
++			goto dma_unmap_wqe_err;
+ 
+ 		dseg->addr       = cpu_to_be64(dma_addr);
+ 		dseg->lkey       = sq->mkey_be;
+@@ -273,7 +273,7 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ 		dma_addr = skb_frag_dma_map(sq->pdev, frag, 0, fsz,
+ 					    DMA_TO_DEVICE);
+ 		if (unlikely(dma_mapping_error(sq->pdev, dma_addr)))
+-			return -ENOMEM;
++			goto dma_unmap_wqe_err;
+ 
+ 		dseg->addr       = cpu_to_be64(dma_addr);
+ 		dseg->lkey       = sq->mkey_be;
+@@ -285,6 +285,10 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ 	}
+ 
+ 	return num_dma;
++
++dma_unmap_wqe_err:
++	mlx5e_dma_unmap_wqe_err(sq, num_dma);
++	return -ENOMEM;
+ }
+ 
+ static inline void
+@@ -380,17 +384,15 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ 	num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb_data, headlen,
+ 					  (struct mlx5_wqe_data_seg *)cseg + ds_cnt);
+ 	if (unlikely(num_dma < 0))
+-		goto dma_unmap_wqe_err;
++		goto err_drop;
+ 
+ 	mlx5e_txwqe_complete(sq, skb, opcode, ds_cnt + num_dma,
+ 			     num_bytes, num_dma, wi, cseg);
+ 
+ 	return NETDEV_TX_OK;
+ 
+-dma_unmap_wqe_err:
++err_drop:
+ 	sq->stats.dropped++;
+-	mlx5e_dma_unmap_wqe_err(sq, wi->num_dma);
+-
+ 	dev_kfree_skb_any(skb);
+ 
+ 	return NETDEV_TX_OK;
+@@ -620,17 +622,15 @@ netdev_tx_t mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ 	num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb_data, headlen,
+ 					  (struct mlx5_wqe_data_seg *)cseg + ds_cnt);
+ 	if (unlikely(num_dma < 0))
+-		goto dma_unmap_wqe_err;
++		goto err_drop;
+ 
+ 	mlx5e_txwqe_complete(sq, skb, opcode, ds_cnt + num_dma,
+ 			     num_bytes, num_dma, wi, cseg);
+ 
+ 	return NETDEV_TX_OK;
+ 
+-dma_unmap_wqe_err:
++err_drop:
+ 	sq->stats.dropped++;
+-	mlx5e_dma_unmap_wqe_err(sq, wi->num_dma);
+-
+ 	dev_kfree_skb_any(skb);
+ 
+ 	return NETDEV_TX_OK;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+index c2b1d7d351fc..0f745df1506c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+@@ -2143,26 +2143,35 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
+ 	memset(vf_stats, 0, sizeof(*vf_stats));
+ 	vf_stats->rx_packets =
+ 		MLX5_GET_CTR(out, received_eth_unicast.packets) +
++		MLX5_GET_CTR(out, received_ib_unicast.packets) +
+ 		MLX5_GET_CTR(out, received_eth_multicast.packets) +
++		MLX5_GET_CTR(out, received_ib_multicast.packets) +
+ 		MLX5_GET_CTR(out, received_eth_broadcast.packets);
+ 
+ 	vf_stats->rx_bytes =
+ 		MLX5_GET_CTR(out, received_eth_unicast.octets) +
++		MLX5_GET_CTR(out, received_ib_unicast.octets) +
+ 		MLX5_GET_CTR(out, received_eth_multicast.octets) +
++		MLX5_GET_CTR(out, received_ib_multicast.octets) +
+ 		MLX5_GET_CTR(out, received_eth_broadcast.octets);
+ 
+ 	vf_stats->tx_packets =
+ 		MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
++		MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
+ 		MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
++		MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
+ 		MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
+ 
+ 	vf_stats->tx_bytes =
+ 		MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
++		MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
+ 		MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
++		MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
+ 		MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
+ 
+ 	vf_stats->multicast =
+-		MLX5_GET_CTR(out, received_eth_multicast.packets);
++		MLX5_GET_CTR(out, received_eth_multicast.packets) +
++		MLX5_GET_CTR(out, received_ib_multicast.packets);
+ 
+ 	vf_stats->broadcast =
+ 		MLX5_GET_CTR(out, received_eth_broadcast.packets);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index 31fc2cfac3b3..4d5b87e0d472 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -185,6 +185,7 @@ static void del_sw_ns(struct fs_node *node);
+ static void del_sw_hw_rule(struct fs_node *node);
+ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ 				struct mlx5_flow_destination *d2);
++static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns);
+ static struct mlx5_flow_rule *
+ find_flow_rule(struct fs_fte *fte,
+ 	       struct mlx5_flow_destination *dest);
+@@ -2329,23 +2330,27 @@ static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
+ 
+ static int init_root_ns(struct mlx5_flow_steering *steering)
+ {
++	int err;
++
+ 	steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
+ 	if (!steering->root_ns)
+-		goto cleanup;
++		return -ENOMEM;
+ 
+-	if (init_root_tree(steering, &root_fs, &steering->root_ns->ns.node))
+-		goto cleanup;
++	err = init_root_tree(steering, &root_fs, &steering->root_ns->ns.node);
++	if (err)
++		goto out_err;
+ 
+ 	set_prio_attrs(steering->root_ns);
+-
+-	if (create_anchor_flow_table(steering))
+-		goto cleanup;
++	err = create_anchor_flow_table(steering);
++	if (err)
++		goto out_err;
+ 
+ 	return 0;
+ 
+-cleanup:
+-	mlx5_cleanup_fs(steering->dev);
+-	return -ENOMEM;
++out_err:
++	cleanup_root_ns(steering->root_ns);
++	steering->root_ns = NULL;
++	return err;
+ }
+ 
+ static void clean_tree(struct fs_node *node)
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
+index 3529b545675d..1c09a274c637 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
+@@ -1099,11 +1099,11 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
+ err_alloc_lag_mapping:
+ 	mlxsw_ports_fini(mlxsw_core);
+ err_ports_init:
+-	mlxsw_bus->fini(bus_priv);
+-err_bus_init:
+ 	if (!reload)
+ 		devlink_resources_unregister(devlink, NULL);
+ err_register_resources:
++	mlxsw_bus->fini(bus_priv);
++err_bus_init:
+ 	if (!reload)
+ 		devlink_free(devlink);
+ err_devlink_alloc:
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+index 161bcdc012f0..fd6b86892595 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+@@ -1718,13 +1718,11 @@ __mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
+ 	struct net_device *dev = mlxsw_sp_port->dev;
+ 	int err;
+ 
+-	if (bridge_port->bridge_device->multicast_enabled) {
+-		if (bridge_port->bridge_device->multicast_enabled) {
+-			err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid,
+-						     false);
+-			if (err)
+-				netdev_err(dev, "Unable to remove port from SMID\n");
+-		}
++	if (bridge_port->bridge_device->multicast_enabled &&
++	    !bridge_port->mrouter) {
++		err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
++		if (err)
++			netdev_err(dev, "Unable to remove port from SMID\n");
+ 	}
+ 
+ 	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
+index b3567a596fc1..80df9a5d4217 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
++++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
+@@ -183,17 +183,21 @@ static int
+ nfp_fl_set_ipv4_udp_tun(struct nfp_fl_set_ipv4_udp_tun *set_tun,
+ 			const struct tc_action *action,
+ 			struct nfp_fl_pre_tunnel *pre_tun,
+-			enum nfp_flower_tun_type tun_type)
++			enum nfp_flower_tun_type tun_type,
++			struct net_device *netdev)
+ {
+ 	size_t act_size = sizeof(struct nfp_fl_set_ipv4_udp_tun);
+ 	struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action);
+ 	u32 tmp_set_ip_tun_type_index = 0;
+ 	/* Currently support one pre-tunnel so index is always 0. */
+ 	int pretun_idx = 0;
++	struct net *net;
+ 
+ 	if (ip_tun->options_len)
+ 		return -EOPNOTSUPP;
+ 
++	net = dev_net(netdev);
++
+ 	set_tun->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL;
+ 	set_tun->head.len_lw = act_size >> NFP_FL_LW_SIZ;
+ 
+@@ -204,6 +208,7 @@ nfp_fl_set_ipv4_udp_tun(struct nfp_fl_set_ipv4_udp_tun *set_tun,
+ 
+ 	set_tun->tun_type_index = cpu_to_be32(tmp_set_ip_tun_type_index);
+ 	set_tun->tun_id = ip_tun->key.tun_id;
++	set_tun->ttl = net->ipv4.sysctl_ip_default_ttl;
+ 
+ 	/* Complete pre_tunnel action. */
+ 	pre_tun->ipv4_dst = ip_tun->key.u.ipv4.dst;
+@@ -511,7 +516,8 @@ nfp_flower_loop_action(const struct tc_action *a,
+ 		*a_len += sizeof(struct nfp_fl_pre_tunnel);
+ 
+ 		set_tun = (void *)&nfp_fl->action_data[*a_len];
+-		err = nfp_fl_set_ipv4_udp_tun(set_tun, a, pre_tun, *tun_type);
++		err = nfp_fl_set_ipv4_udp_tun(set_tun, a, pre_tun, *tun_type,
++					      netdev);
+ 		if (err)
+ 			return err;
+ 		*a_len += sizeof(struct nfp_fl_set_ipv4_udp_tun);
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
+index adfe474c2cf0..329a9b6d453a 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
++++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
+@@ -178,7 +178,10 @@ struct nfp_fl_set_ipv4_udp_tun {
+ 	__be16 reserved;
+ 	__be64 tun_id __packed;
+ 	__be32 tun_type_index;
+-	__be32 extra[3];
++	__be16 reserved2;
++	u8 ttl;
++	u8 reserved3;
++	__be32 extra[2];
+ };
+ 
+ /* Metadata with L2 (1W/4B)
+diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
+index d24b47b8e0b2..d118da5a10a2 100644
+--- a/drivers/net/ethernet/realtek/8139too.c
++++ b/drivers/net/ethernet/realtek/8139too.c
+@@ -2224,7 +2224,7 @@ static void rtl8139_poll_controller(struct net_device *dev)
+ 	struct rtl8139_private *tp = netdev_priv(dev);
+ 	const int irq = tp->pci_dev->irq;
+ 
+-	disable_irq(irq);
++	disable_irq_nosync(irq);
+ 	rtl8139_interrupt(irq, dev);
+ 	enable_irq(irq);
+ }
+diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
+index b4779acb6b5c..18bb1e226e6d 100644
+--- a/drivers/net/ethernet/realtek/r8169.c
++++ b/drivers/net/ethernet/realtek/r8169.c
+@@ -5087,6 +5087,9 @@ static void rtl_pll_power_down(struct rtl8169_private *tp)
+ static void rtl_pll_power_up(struct rtl8169_private *tp)
+ {
+ 	rtl_generic_op(tp, tp->pll_power_ops.up);
++
++	/* give MAC/PHY some time to resume */
++	msleep(20);
+ }
+ 
+ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
+diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
+index 8dd545fed30d..6c94af263be8 100644
+--- a/drivers/net/ethernet/sun/niu.c
++++ b/drivers/net/ethernet/sun/niu.c
+@@ -3443,7 +3443,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
+ 
+ 		len = (val & RCR_ENTRY_L2_LEN) >>
+ 			RCR_ENTRY_L2_LEN_SHIFT;
+-		len -= ETH_FCS_LEN;
++		append_size = len + ETH_HLEN + ETH_FCS_LEN;
+ 
+ 		addr = (val & RCR_ENTRY_PKT_BUF_ADDR) <<
+ 			RCR_ENTRY_PKT_BUF_ADDR_SHIFT;
+@@ -3453,7 +3453,6 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
+ 					 RCR_ENTRY_PKTBUFSZ_SHIFT];
+ 
+ 		off = addr & ~PAGE_MASK;
+-		append_size = rcr_size;
+ 		if (num_rcr == 1) {
+ 			int ptype;
+ 
+@@ -3466,7 +3465,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
+ 			else
+ 				skb_checksum_none_assert(skb);
+ 		} else if (!(val & RCR_ENTRY_MULTI))
+-			append_size = len - skb->len;
++			append_size = append_size - skb->len;
+ 
+ 		niu_rx_skb_append(skb, page, off, append_size, rcr_size);
+ 		if ((page->index + rp->rbr_block_size) - rcr_size == addr) {
+diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
+index 33c35b2df7d5..5490c7d09c16 100644
+--- a/drivers/net/ethernet/ti/cpsw.c
++++ b/drivers/net/ethernet/ti/cpsw.c
+@@ -1278,6 +1278,8 @@ static inline void cpsw_add_dual_emac_def_ale_entries(
+ 	cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
+ 			   HOST_PORT_NUM, ALE_VLAN |
+ 			   ALE_SECURE, slave->port_vlan);
++	cpsw_ale_control_set(cpsw->ale, slave_port,
++			     ALE_PORT_DROP_UNKNOWN_VLAN, 1);
+ }
+ 
+ static void soft_reset_slave(struct cpsw_slave *slave)
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index f28c85d212ce..4774766fe20d 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -1840,7 +1840,8 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
+ 		goto rx_handler_failed;
+ 	}
+ 
+-	ret = netdev_upper_dev_link(vf_netdev, ndev, NULL);
++	ret = netdev_master_upper_dev_link(vf_netdev, ndev,
++					   NULL, NULL, NULL);
+ 	if (ret != 0) {
+ 		netdev_err(vf_netdev,
+ 			   "can not set master device %s (err = %d)\n",
+diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
+index 465c42e30508..95846f0321f3 100644
+--- a/drivers/net/hyperv/rndis_filter.c
++++ b/drivers/net/hyperv/rndis_filter.c
+@@ -1282,7 +1282,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
+ 		   rndis_device->link_state ? "down" : "up");
+ 
+ 	if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
+-		return net_device;
++		goto out;
+ 
+ 	rndis_filter_query_link_speed(rndis_device, net_device);
+ 
+diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
+index 8961209ee949..a386138c7255 100644
+--- a/drivers/net/phy/sfp-bus.c
++++ b/drivers/net/phy/sfp-bus.c
+@@ -190,7 +190,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
+ 	if (id->base.br_nominal) {
+ 		if (id->base.br_nominal != 255) {
+ 			br_nom = id->base.br_nominal * 100;
+-			br_min = br_nom + id->base.br_nominal * id->ext.br_min;
++			br_min = br_nom - id->base.br_nominal * id->ext.br_min;
+ 			br_max = br_nom + id->base.br_nominal * id->ext.br_max;
+ 		} else if (id->ext.br_max) {
+ 			br_nom = 250 * id->ext.br_max;
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 51c68fc416fa..42565dd33aa6 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -1344,6 +1344,18 @@ static int qmi_wwan_probe(struct usb_interface *intf,
+ 		id->driver_info = (unsigned long)&qmi_wwan_info;
+ 	}
+ 
++	/* There are devices where the same interface number can be
++	 * configured as different functions. We should only bind to
++	 * vendor specific functions when matching on interface number
++	 */
++	if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER &&
++	    desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) {
++		dev_dbg(&intf->dev,
++			"Rejecting interface number match for class %02x\n",
++			desc->bInterfaceClass);
++		return -ENODEV;
++	}
++
+ 	/* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */
+ 	if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) {
+ 		dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n");
+diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
+index 84858d5c8257..d9f2229664ad 100644
+--- a/drivers/scsi/aacraid/commsup.c
++++ b/drivers/scsi/aacraid/commsup.c
+@@ -724,6 +724,8 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
+ 	int wait;
+ 	unsigned long flags = 0;
+ 	unsigned long mflags = 0;
++	struct aac_hba_cmd_req *hbacmd = (struct aac_hba_cmd_req *)
++			fibptr->hw_fib_va;
+ 
+ 	fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA);
+ 	if (callback) {
+@@ -734,11 +736,9 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
+ 		wait = 1;
+ 
+ 
+-	if (command == HBA_IU_TYPE_SCSI_CMD_REQ) {
+-		struct aac_hba_cmd_req *hbacmd =
+-			(struct aac_hba_cmd_req *)fibptr->hw_fib_va;
++	hbacmd->iu_type = command;
+ 
+-		hbacmd->iu_type = command;
++	if (command == HBA_IU_TYPE_SCSI_CMD_REQ) {
+ 		/* bit1 of request_id must be 0 */
+ 		hbacmd->request_id =
+ 			cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1);
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 9298324325ed..f034eccd8616 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -264,7 +264,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
+ 	 * Inherently racy -- command line shares address space
+ 	 * with code and data.
+ 	 */
+-	rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0);
++	rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
+ 	if (rv <= 0)
+ 		goto out_free_page;
+ 
+@@ -282,7 +282,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
+ 			int nr_read;
+ 
+ 			_count = min3(count, len, PAGE_SIZE);
+-			nr_read = access_remote_vm(mm, p, page, _count, 0);
++			nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
+ 			if (nr_read < 0)
+ 				rv = nr_read;
+ 			if (nr_read <= 0)
+@@ -328,7 +328,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
+ 				bool final;
+ 
+ 				_count = min3(count, len, PAGE_SIZE);
+-				nr_read = access_remote_vm(mm, p, page, _count, 0);
++				nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
+ 				if (nr_read < 0)
+ 					rv = nr_read;
+ 				if (nr_read <= 0)
+@@ -946,7 +946,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
+ 		max_len = min_t(size_t, PAGE_SIZE, count);
+ 		this_len = min(max_len, this_len);
+ 
+-		retval = access_remote_vm(mm, (env_start + src), page, this_len, 0);
++		retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
+ 
+ 		if (retval <= 0) {
+ 			ret = retval;
+diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
+index 9d3a03364e6e..1352b1b990a7 100644
+--- a/include/linux/mlx5/driver.h
++++ b/include/linux/mlx5/driver.h
+@@ -1269,25 +1269,19 @@ enum {
+ };
+ 
+ static inline const struct cpumask *
+-mlx5_get_vector_affinity(struct mlx5_core_dev *dev, int vector)
++mlx5_get_vector_affinity_hint(struct mlx5_core_dev *dev, int vector)
+ {
+-	const struct cpumask *mask;
+ 	struct irq_desc *desc;
+ 	unsigned int irq;
+ 	int eqn;
+ 	int err;
+ 
+-	err = mlx5_vector2eqn(dev, MLX5_EQ_VEC_COMP_BASE + vector, &eqn, &irq);
++	err = mlx5_vector2eqn(dev, vector, &eqn, &irq);
+ 	if (err)
+ 		return NULL;
+ 
+ 	desc = irq_to_desc(irq);
+-#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
+-	mask = irq_data_get_effective_affinity_mask(&desc->irq_data);
+-#else
+-	mask = desc->irq_common_data.affinity;
+-#endif
+-	return mask;
++	return desc->affinity_hint;
+ }
+ 
+ #endif /* MLX5_DRIVER_H */
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index 95a2d748e978..a4e9bdbec490 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -2441,6 +2441,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
+ #define FOLL_MLOCK	0x1000	/* lock present pages */
+ #define FOLL_REMOTE	0x2000	/* we are working on non-current tsk/mm */
+ #define FOLL_COW	0x4000	/* internal GUP flag */
++#define FOLL_ANON	0x8000	/* don't do file mappings */
+ 
+ static inline int vm_fault_to_errno(int vm_fault, int foll_flags)
+ {
+diff --git a/include/net/bonding.h b/include/net/bonding.h
+index f801fc940b29..b52235158836 100644
+--- a/include/net/bonding.h
++++ b/include/net/bonding.h
+@@ -198,6 +198,7 @@ struct bonding {
+ 	struct   slave __rcu *primary_slave;
+ 	struct   bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
+ 	bool     force_primary;
++	u32      nest_level;
+ 	s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
+ 	int     (*recv_probe)(const struct sk_buff *, struct bonding *,
+ 			      struct slave *);
+diff --git a/include/net/tls.h b/include/net/tls.h
+index 4913430ab807..f5c928a76994 100644
+--- a/include/net/tls.h
++++ b/include/net/tls.h
+@@ -102,6 +102,7 @@ struct tls_context {
+ 	struct scatterlist *partially_sent_record;
+ 	u16 partially_sent_offset;
+ 	unsigned long flags;
++	bool in_tcp_sendpages;
+ 
+ 	u16 pending_open_record_frags;
+ 	int (*push_pending_record)(struct sock *sk, int flags);
+diff --git a/mm/gup.c b/mm/gup.c
+index 8f3a06408e28..f5f83c2e6c83 100644
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -544,6 +544,9 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
+ 	if (vm_flags & (VM_IO | VM_PFNMAP))
+ 		return -EFAULT;
+ 
++	if (gup_flags & FOLL_ANON && !vma_is_anonymous(vma))
++		return -EFAULT;
++
+ 	if (write) {
+ 		if (!(vm_flags & VM_WRITE)) {
+ 			if (!(gup_flags & FOLL_FORCE))
+diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
+index 9ba4ed65c52b..4be5335407c5 100644
+--- a/net/bridge/br_if.c
++++ b/net/bridge/br_if.c
+@@ -509,8 +509,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
+ 		return -ELOOP;
+ 	}
+ 
+-	/* Device is already being bridged */
+-	if (br_port_exists(dev))
++	/* Device has master upper dev */
++	if (netdev_master_upper_dev_get(dev))
+ 		return -EBUSY;
+ 
+ 	/* No bridging devices that dislike that (e.g. wireless) */
+diff --git a/net/compat.c b/net/compat.c
+index 22381719718c..32ed993588d6 100644
+--- a/net/compat.c
++++ b/net/compat.c
+@@ -377,7 +377,8 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
+ 	    optname == SO_ATTACH_REUSEPORT_CBPF)
+ 		return do_set_attach_filter(sock, level, optname,
+ 					    optval, optlen);
+-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
++	if (!COMPAT_USE_64BIT_TIME &&
++	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
+ 		return do_set_sock_timeout(sock, level, optname, optval, optlen);
+ 
+ 	return sock_setsockopt(sock, level, optname, optval, optlen);
+@@ -442,7 +443,8 @@ static int do_get_sock_timeout(struct socket *sock, int level, int optname,
+ static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
+ 				char __user *optval, int __user *optlen)
+ {
+-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
++	if (!COMPAT_USE_64BIT_TIME &&
++	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
+ 		return do_get_sock_timeout(sock, level, optname, optval, optlen);
+ 	return sock_getsockopt(sock, level, optname, optval, optlen);
+ }
+diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
+index 92d016e87816..385f153fe031 100644
+--- a/net/dccp/ccids/ccid2.c
++++ b/net/dccp/ccids/ccid2.c
+@@ -126,6 +126,16 @@ static void ccid2_change_l_seq_window(struct sock *sk, u64 val)
+ 						  DCCPF_SEQ_WMAX));
+ }
+ 
++static void dccp_tasklet_schedule(struct sock *sk)
++{
++	struct tasklet_struct *t = &dccp_sk(sk)->dccps_xmitlet;
++
++	if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
++		sock_hold(sk);
++		__tasklet_schedule(t);
++	}
++}
++
+ static void ccid2_hc_tx_rto_expire(struct timer_list *t)
+ {
+ 	struct ccid2_hc_tx_sock *hc = from_timer(hc, t, tx_rtotimer);
+@@ -166,7 +176,7 @@ static void ccid2_hc_tx_rto_expire(struct timer_list *t)
+ 
+ 	/* if we were blocked before, we may now send cwnd=1 packet */
+ 	if (sender_was_blocked)
+-		tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet);
++		dccp_tasklet_schedule(sk);
+ 	/* restart backed-off timer */
+ 	sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
+ out:
+@@ -706,7 +716,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
+ done:
+ 	/* check if incoming Acks allow pending packets to be sent */
+ 	if (sender_was_blocked && !ccid2_cwnd_network_limited(hc))
+-		tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet);
++		dccp_tasklet_schedule(sk);
+ 	dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
+ }
+ 
+diff --git a/net/dccp/timer.c b/net/dccp/timer.c
+index b50a8732ff43..1501a20a94ca 100644
+--- a/net/dccp/timer.c
++++ b/net/dccp/timer.c
+@@ -232,6 +232,7 @@ static void dccp_write_xmitlet(unsigned long data)
+ 	else
+ 		dccp_write_xmit(sk);
+ 	bh_unlock_sock(sk);
++	sock_put(sk);
+ }
+ 
+ static void dccp_write_xmit_timer(struct timer_list *t)
+@@ -240,7 +241,6 @@ static void dccp_write_xmit_timer(struct timer_list *t)
+ 	struct sock *sk = &dp->dccps_inet_connection.icsk_inet.sk;
+ 
+ 	dccp_write_xmitlet((unsigned long)sk);
+-	sock_put(sk);
+ }
+ 
+ void dccp_init_xmit_timers(struct sock *sk)
+diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
+index b8f0db54b197..16226d49263d 100644
+--- a/net/ipv4/ping.c
++++ b/net/ipv4/ping.c
+@@ -775,8 +775,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ 	ipc.addr = faddr = daddr;
+ 
+ 	if (ipc.opt && ipc.opt->opt.srr) {
+-		if (!daddr)
+-			return -EINVAL;
++		if (!daddr) {
++			err = -EINVAL;
++			goto out_free;
++		}
+ 		faddr = ipc.opt->opt.faddr;
+ 	}
+ 	tos = get_rttos(&ipc, inet);
+@@ -842,6 +844,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ 
+ out:
+ 	ip_rt_put(rt);
++out_free:
+ 	if (free)
+ 		kfree(ipc.opt);
+ 	if (!err) {
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 9d9b8358a898..df1c04d75f93 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -710,7 +710,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
+ 		fnhe->fnhe_gw = gw;
+ 		fnhe->fnhe_pmtu = pmtu;
+ 		fnhe->fnhe_mtu_locked = lock;
+-		fnhe->fnhe_expires = expires;
++		fnhe->fnhe_expires = max(1UL, expires);
+ 
+ 		/* Exception created; mark the cached routes for the nexthop
+ 		 * stale, so anyone caching it rechecks if this exception
+@@ -1298,6 +1298,36 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
+ 	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
+ }
+ 
++static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
++{
++	struct fnhe_hash_bucket *hash;
++	struct fib_nh_exception *fnhe, __rcu **fnhe_p;
++	u32 hval = fnhe_hashfun(daddr);
++
++	spin_lock_bh(&fnhe_lock);
++
++	hash = rcu_dereference_protected(nh->nh_exceptions,
++					 lockdep_is_held(&fnhe_lock));
++	hash += hval;
++
++	fnhe_p = &hash->chain;
++	fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock));
++	while (fnhe) {
++		if (fnhe->fnhe_daddr == daddr) {
++			rcu_assign_pointer(*fnhe_p, rcu_dereference_protected(
++				fnhe->fnhe_next, lockdep_is_held(&fnhe_lock)));
++			fnhe_flush_routes(fnhe);
++			kfree_rcu(fnhe, rcu);
++			break;
++		}
++		fnhe_p = &fnhe->fnhe_next;
++		fnhe = rcu_dereference_protected(fnhe->fnhe_next,
++						 lockdep_is_held(&fnhe_lock));
++	}
++
++	spin_unlock_bh(&fnhe_lock);
++}
++
+ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
+ {
+ 	struct fnhe_hash_bucket *hash = rcu_dereference(nh->nh_exceptions);
+@@ -1311,8 +1341,14 @@ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
+ 
+ 	for (fnhe = rcu_dereference(hash[hval].chain); fnhe;
+ 	     fnhe = rcu_dereference(fnhe->fnhe_next)) {
+-		if (fnhe->fnhe_daddr == daddr)
++		if (fnhe->fnhe_daddr == daddr) {
++			if (fnhe->fnhe_expires &&
++			    time_after(jiffies, fnhe->fnhe_expires)) {
++				ip_del_fnhe(nh, daddr);
++				break;
++			}
+ 			return fnhe;
++		}
+ 	}
+ 	return NULL;
+ }
+@@ -1340,6 +1376,7 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
+ 			fnhe->fnhe_gw = 0;
+ 			fnhe->fnhe_pmtu = 0;
+ 			fnhe->fnhe_expires = 0;
++			fnhe->fnhe_mtu_locked = false;
+ 			fnhe_flush_routes(fnhe);
+ 			orig = NULL;
+ 		}
+@@ -1638,36 +1675,6 @@ static void ip_handle_martian_source(struct net_device *dev,
+ #endif
+ }
+ 
+-static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
+-{
+-	struct fnhe_hash_bucket *hash;
+-	struct fib_nh_exception *fnhe, __rcu **fnhe_p;
+-	u32 hval = fnhe_hashfun(daddr);
+-
+-	spin_lock_bh(&fnhe_lock);
+-
+-	hash = rcu_dereference_protected(nh->nh_exceptions,
+-					 lockdep_is_held(&fnhe_lock));
+-	hash += hval;
+-
+-	fnhe_p = &hash->chain;
+-	fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock));
+-	while (fnhe) {
+-		if (fnhe->fnhe_daddr == daddr) {
+-			rcu_assign_pointer(*fnhe_p, rcu_dereference_protected(
+-				fnhe->fnhe_next, lockdep_is_held(&fnhe_lock)));
+-			fnhe_flush_routes(fnhe);
+-			kfree_rcu(fnhe, rcu);
+-			break;
+-		}
+-		fnhe_p = &fnhe->fnhe_next;
+-		fnhe = rcu_dereference_protected(fnhe->fnhe_next,
+-						 lockdep_is_held(&fnhe_lock));
+-	}
+-
+-	spin_unlock_bh(&fnhe_lock);
+-}
+-
+ static void set_lwt_redirect(struct rtable *rth)
+ {
+ 	if (lwtunnel_output_redirect(rth->dst.lwtstate)) {
+@@ -1734,20 +1741,10 @@ static int __mkroute_input(struct sk_buff *skb,
+ 
+ 	fnhe = find_exception(&FIB_RES_NH(*res), daddr);
+ 	if (do_cache) {
+-		if (fnhe) {
++		if (fnhe)
+ 			rth = rcu_dereference(fnhe->fnhe_rth_input);
+-			if (rth && rth->dst.expires &&
+-			    time_after(jiffies, rth->dst.expires)) {
+-				ip_del_fnhe(&FIB_RES_NH(*res), daddr);
+-				fnhe = NULL;
+-			} else {
+-				goto rt_cache;
+-			}
+-		}
+-
+-		rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+-
+-rt_cache:
++		else
++			rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+ 		if (rt_cache_valid(rth)) {
+ 			skb_dst_set_noref(skb, &rth->dst);
+ 			goto out;
+@@ -2224,39 +2221,31 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
+ 		 * the loopback interface and the IP_PKTINFO ipi_ifindex will
+ 		 * be set to the loopback interface as well.
+ 		 */
+-		fi = NULL;
++		do_cache = false;
+ 	}
+ 
+ 	fnhe = NULL;
+ 	do_cache &= fi != NULL;
+-	if (do_cache) {
++	if (fi) {
+ 		struct rtable __rcu **prth;
+ 		struct fib_nh *nh = &FIB_RES_NH(*res);
+ 
+ 		fnhe = find_exception(nh, fl4->daddr);
++		if (!do_cache)
++			goto add;
+ 		if (fnhe) {
+ 			prth = &fnhe->fnhe_rth_output;
+-			rth = rcu_dereference(*prth);
+-			if (rth && rth->dst.expires &&
+-			    time_after(jiffies, rth->dst.expires)) {
+-				ip_del_fnhe(nh, fl4->daddr);
+-				fnhe = NULL;
+-			} else {
+-				goto rt_cache;
++		} else {
++			if (unlikely(fl4->flowi4_flags &
++				     FLOWI_FLAG_KNOWN_NH &&
++				     !(nh->nh_gw &&
++				       nh->nh_scope == RT_SCOPE_LINK))) {
++				do_cache = false;
++				goto add;
+ 			}
++			prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ 		}
+-
+-		if (unlikely(fl4->flowi4_flags &
+-			     FLOWI_FLAG_KNOWN_NH &&
+-			     !(nh->nh_gw &&
+-			       nh->nh_scope == RT_SCOPE_LINK))) {
+-			do_cache = false;
+-			goto add;
+-		}
+-		prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ 		rth = rcu_dereference(*prth);
+-
+-rt_cache:
+ 		if (rt_cache_valid(rth) && dst_hold_safe(&rth->dst))
+ 			return rth;
+ 	}
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index c92fd253fc46..80e39d9a0423 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -688,7 +688,7 @@ static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
+ {
+ 	return skb->len < size_goal &&
+ 	       sock_net(sk)->ipv4.sysctl_tcp_autocorking &&
+-	       skb != tcp_write_queue_head(sk) &&
++	       !tcp_rtx_queue_empty(sk) &&
+ 	       refcount_read(&sk->sk_wmem_alloc) > skb->truesize;
+ }
+ 
+@@ -1210,7 +1210,8 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
+ 			uarg->zerocopy = 0;
+ 	}
+ 
+-	if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect)) {
++	if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect) &&
++	    !tp->repair) {
+ 		err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
+ 		if (err == -EINPROGRESS && copied_syn > 0)
+ 			goto out;
+diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c
+index a471f696e13c..29478454b527 100644
+--- a/net/ipv4/tcp_bbr.c
++++ b/net/ipv4/tcp_bbr.c
+@@ -803,7 +803,9 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs)
+ 			}
+ 		}
+ 	}
+-	bbr->idle_restart = 0;
++	/* Restart after idle ends only once we process a new S/ACK for data */
++	if (rs->delivered > 0)
++		bbr->idle_restart = 0;
+ }
+ 
+ static void bbr_update_model(struct sock *sk, const struct rate_sample *rs)
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index e5ef7c38c934..b6ba51536b37 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -407,9 +407,9 @@ static int compute_score(struct sock *sk, struct net *net,
+ 		bool dev_match = (sk->sk_bound_dev_if == dif ||
+ 				  sk->sk_bound_dev_if == sdif);
+ 
+-		if (exact_dif && !dev_match)
++		if (!dev_match)
+ 			return -1;
+-		if (sk->sk_bound_dev_if && dev_match)
++		if (sk->sk_bound_dev_if)
+ 			score += 4;
+ 	}
+ 
+@@ -958,8 +958,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ 	sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags);
+ 
+ 	if (ipc.opt && ipc.opt->opt.srr) {
+-		if (!daddr)
+-			return -EINVAL;
++		if (!daddr) {
++			err = -EINVAL;
++			goto out_free;
++		}
+ 		faddr = ipc.opt->opt.faddr;
+ 		connected = 0;
+ 	}
+@@ -1080,6 +1082,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ 
+ out:
+ 	ip_rt_put(rt);
++out_free:
+ 	if (free)
+ 		kfree(ipc.opt);
+ 	if (!err)
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 74a2e37412b2..1aee1a537cb1 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -1822,11 +1822,16 @@ static void ip6_multipath_l3_keys(const struct sk_buff *skb,
+ 	const struct ipv6hdr *inner_iph;
+ 	const struct icmp6hdr *icmph;
+ 	struct ipv6hdr _inner_iph;
++	struct icmp6hdr _icmph;
+ 
+ 	if (likely(outer_iph->nexthdr != IPPROTO_ICMPV6))
+ 		goto out;
+ 
+-	icmph = icmp6_hdr(skb);
++	icmph = skb_header_pointer(skb, skb_transport_offset(skb),
++				   sizeof(_icmph), &_icmph);
++	if (!icmph)
++		goto out;
++
+ 	if (icmph->icmp6_type != ICMPV6_DEST_UNREACH &&
+ 	    icmph->icmp6_type != ICMPV6_PKT_TOOBIG &&
+ 	    icmph->icmp6_type != ICMPV6_TIME_EXCEED &&
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 52e3ea0e6f50..68d589f8d2b2 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -148,9 +148,9 @@ static int compute_score(struct sock *sk, struct net *net,
+ 		bool dev_match = (sk->sk_bound_dev_if == dif ||
+ 				  sk->sk_bound_dev_if == sdif);
+ 
+-		if (exact_dif && !dev_match)
++		if (!dev_match)
+ 			return -1;
+-		if (sk->sk_bound_dev_if && dev_match)
++		if (sk->sk_bound_dev_if)
+ 			score++;
+ 	}
+ 
+diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
+index cf41d9b4a0b8..b49f5afab405 100644
+--- a/net/llc/af_llc.c
++++ b/net/llc/af_llc.c
+@@ -930,6 +930,9 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+ 	if (size > llc->dev->mtu)
+ 		size = llc->dev->mtu;
+ 	copied = size - hdrlen;
++	rc = -EINVAL;
++	if (copied < 0)
++		goto release;
+ 	release_sock(sk);
+ 	skb = sock_alloc_send_skb(sk, size, noblock, &rc);
+ 	lock_sock(sk);
+diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
+index d7da99a0b0b8..9696ef96b719 100644
+--- a/net/nsh/nsh.c
++++ b/net/nsh/nsh.c
+@@ -57,6 +57,8 @@ int nsh_pop(struct sk_buff *skb)
+ 		return -ENOMEM;
+ 	nh = (struct nshhdr *)(skb->data);
+ 	length = nsh_hdr_len(nh);
++	if (length < NSH_BASE_HDR_LEN)
++		return -EINVAL;
+ 	inner_proto = tun_p_to_eth_p(nh->np);
+ 	if (!pskb_may_pull(skb, length))
+ 		return -ENOMEM;
+@@ -90,6 +92,8 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
+ 	if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
+ 		goto out;
+ 	nsh_len = nsh_hdr_len(nsh_hdr(skb));
++	if (nsh_len < NSH_BASE_HDR_LEN)
++		goto out;
+ 	if (unlikely(!pskb_may_pull(skb, nsh_len)))
+ 		goto out;
+ 
+diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
+index 7322aa1e382e..492ab0c36f7c 100644
+--- a/net/openvswitch/flow_netlink.c
++++ b/net/openvswitch/flow_netlink.c
+@@ -1712,13 +1712,10 @@ static void nlattr_set(struct nlattr *attr, u8 val,
+ 
+ 	/* The nlattr stream should already have been validated */
+ 	nla_for_each_nested(nla, attr, rem) {
+-		if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) {
+-			if (tbl[nla_type(nla)].next)
+-				tbl = tbl[nla_type(nla)].next;
+-			nlattr_set(nla, val, tbl);
+-		} else {
++		if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
++			nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl);
++		else
+ 			memset(nla_data(nla), val, nla_len(nla));
+-		}
+ 
+ 		if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
+ 			*(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
+diff --git a/net/rds/recv.c b/net/rds/recv.c
+index b25bcfe411ca..555f07ccf0dc 100644
+--- a/net/rds/recv.c
++++ b/net/rds/recv.c
+@@ -558,6 +558,7 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg,
+ 		struct rds_cmsg_rx_trace t;
+ 		int i, j;
+ 
++		memset(&t, 0, sizeof(t));
+ 		inc->i_rx_lat_trace[RDS_MSG_RX_CMSG] = local_clock();
+ 		t.rx_traces =  rs->rs_rx_traces;
+ 		for (i = 0; i < rs->rs_rx_traces; i++) {
+diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
+index 7b0700f52b50..d87b611046bb 100644
+--- a/net/sched/act_skbmod.c
++++ b/net/sched/act_skbmod.c
+@@ -131,8 +131,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
+ 	if (exists && bind)
+ 		return 0;
+ 
+-	if (!lflags)
++	if (!lflags) {
++		if (exists)
++			tcf_idr_release(*a, bind);
+ 		return -EINVAL;
++	}
+ 
+ 	if (!exists) {
+ 		ret = tcf_idr_create(tn, parm->index, est, a,
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 247b7cc20c13..c2c732aad87c 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -152,8 +152,8 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
+ 			NL_SET_ERR_MSG(extack, "TC classifier not found");
+ 			err = -ENOENT;
+ 		}
+-		goto errout;
+ #endif
++		goto errout;
+ 	}
+ 	tp->classify = tp->ops->classify;
+ 	tp->protocol = protocol;
+diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
+index a366e4c9413a..4808713c73b9 100644
+--- a/net/sched/sch_fq.c
++++ b/net/sched/sch_fq.c
+@@ -128,6 +128,28 @@ static bool fq_flow_is_detached(const struct fq_flow *f)
+ 	return f->next == &detached;
+ }
+ 
++static bool fq_flow_is_throttled(const struct fq_flow *f)
++{
++	return f->next == &throttled;
++}
++
++static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow)
++{
++	if (head->first)
++		head->last->next = flow;
++	else
++		head->first = flow;
++	head->last = flow;
++	flow->next = NULL;
++}
++
++static void fq_flow_unset_throttled(struct fq_sched_data *q, struct fq_flow *f)
++{
++	rb_erase(&f->rate_node, &q->delayed);
++	q->throttled_flows--;
++	fq_flow_add_tail(&q->old_flows, f);
++}
++
+ static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f)
+ {
+ 	struct rb_node **p = &q->delayed.rb_node, *parent = NULL;
+@@ -155,15 +177,6 @@ static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f)
+ 
+ static struct kmem_cache *fq_flow_cachep __read_mostly;
+ 
+-static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow)
+-{
+-	if (head->first)
+-		head->last->next = flow;
+-	else
+-		head->first = flow;
+-	head->last = flow;
+-	flow->next = NULL;
+-}
+ 
+ /* limit number of collected flows per round */
+ #define FQ_GC_MAX 8
+@@ -267,6 +280,8 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
+ 				     f->socket_hash != sk->sk_hash)) {
+ 				f->credit = q->initial_quantum;
+ 				f->socket_hash = sk->sk_hash;
++				if (fq_flow_is_throttled(f))
++					fq_flow_unset_throttled(q, f);
+ 				f->time_next_packet = 0ULL;
+ 			}
+ 			return f;
+@@ -438,9 +453,7 @@ static void fq_check_throttled(struct fq_sched_data *q, u64 now)
+ 			q->time_next_delayed_flow = f->time_next_packet;
+ 			break;
+ 		}
+-		rb_erase(p, &q->delayed);
+-		q->throttled_flows--;
+-		fq_flow_add_tail(&q->old_flows, f);
++		fq_flow_unset_throttled(q, f);
+ 	}
+ }
+ 
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 837806dd5799..a47179da24e6 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -1024,8 +1024,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
+ 	struct sctp_endpoint *ep;
+ 	struct sctp_chunk *chunk;
+ 	struct sctp_inq *inqueue;
+-	int state;
++	int first_time = 1;	/* is this the first time through the loop */
+ 	int error = 0;
++	int state;
+ 
+ 	/* The association should be held so we should be safe. */
+ 	ep = asoc->ep;
+@@ -1036,6 +1037,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
+ 		state = asoc->state;
+ 		subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
+ 
++		/* If the first chunk in the packet is AUTH, do special
++		 * processing specified in Section 6.3 of SCTP-AUTH spec
++		 */
++		if (first_time && subtype.chunk == SCTP_CID_AUTH) {
++			struct sctp_chunkhdr *next_hdr;
++
++			next_hdr = sctp_inq_peek(inqueue);
++			if (!next_hdr)
++				goto normal;
++
++			/* If the next chunk is COOKIE-ECHO, skip the AUTH
++			 * chunk while saving a pointer to it so we can do
++			 * Authentication later (during cookie-echo
++			 * processing).
++			 */
++			if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
++				chunk->auth_chunk = skb_clone(chunk->skb,
++							      GFP_ATOMIC);
++				chunk->auth = 1;
++				continue;
++			}
++		}
++
++normal:
+ 		/* SCTP-AUTH, Section 6.3:
+ 		 *    The receiver has a list of chunk types which it expects
+ 		 *    to be received only after an AUTH-chunk.  This list has
+@@ -1074,6 +1099,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
+ 		/* If there is an error on chunk, discard this packet. */
+ 		if (error && chunk)
+ 			chunk->pdiscard = 1;
++
++		if (first_time)
++			first_time = 0;
+ 	}
+ 	sctp_association_put(asoc);
+ }
+diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
+index 23ebc5318edc..eb93ffe2408b 100644
+--- a/net/sctp/inqueue.c
++++ b/net/sctp/inqueue.c
+@@ -217,7 +217,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
+ 	skb_pull(chunk->skb, sizeof(*ch));
+ 	chunk->subh.v = NULL; /* Subheader is no longer valid.  */
+ 
+-	if (chunk->chunk_end + sizeof(*ch) < skb_tail_pointer(chunk->skb)) {
++	if (chunk->chunk_end + sizeof(*ch) <= skb_tail_pointer(chunk->skb)) {
+ 		/* This is not a singleton */
+ 		chunk->singleton = 0;
+ 	} else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) {
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index 07b64719d1bc..351e80c59211 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -866,6 +866,9 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
+ 	if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2))
+ 		return 1;
+ 
++	if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET)
++		return addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr;
++
+ 	return __sctp_v6_cmp_addr(addr1, addr2);
+ }
+ 
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index eb7905ffe5f2..88573c57e106 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -153,10 +153,7 @@ static enum sctp_disposition sctp_sf_violation_chunk(
+ 					struct sctp_cmd_seq *commands);
+ 
+ static enum sctp_ierror sctp_sf_authenticate(
+-					struct net *net,
+-					const struct sctp_endpoint *ep,
+ 					const struct sctp_association *asoc,
+-					const union sctp_subtype type,
+ 					struct sctp_chunk *chunk);
+ 
+ static enum sctp_disposition __sctp_sf_do_9_1_abort(
+@@ -621,6 +618,38 @@ enum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net,
+ 	return SCTP_DISPOSITION_CONSUME;
+ }
+ 
++static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,
++				   const struct sctp_association *asoc)
++{
++	struct sctp_chunk auth;
++
++	if (!chunk->auth_chunk)
++		return true;
++
++	/* SCTP-AUTH:  auth_chunk pointer is only set when the cookie-echo
++	 * is supposed to be authenticated and we have to do delayed
++	 * authentication.  We've just recreated the association using
++	 * the information in the cookie and now it's much easier to
++	 * do the authentication.
++	 */
++
++	/* Make sure that we and the peer are AUTH capable */
++	if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
++		return false;
++
++	/* set-up our fake chunk so that we can process it */
++	auth.skb = chunk->auth_chunk;
++	auth.asoc = chunk->asoc;
++	auth.sctp_hdr = chunk->sctp_hdr;
++	auth.chunk_hdr = (struct sctp_chunkhdr *)
++				skb_push(chunk->auth_chunk,
++					 sizeof(struct sctp_chunkhdr));
++	skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr));
++	auth.transport = chunk->transport;
++
++	return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR;
++}
++
+ /*
+  * Respond to a normal COOKIE ECHO chunk.
+  * We are the side that is being asked for an association.
+@@ -758,37 +787,9 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
+ 	if (error)
+ 		goto nomem_init;
+ 
+-	/* SCTP-AUTH:  auth_chunk pointer is only set when the cookie-echo
+-	 * is supposed to be authenticated and we have to do delayed
+-	 * authentication.  We've just recreated the association using
+-	 * the information in the cookie and now it's much easier to
+-	 * do the authentication.
+-	 */
+-	if (chunk->auth_chunk) {
+-		struct sctp_chunk auth;
+-		enum sctp_ierror ret;
+-
+-		/* Make sure that we and the peer are AUTH capable */
+-		if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
+-			sctp_association_free(new_asoc);
+-			return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+-		}
+-
+-		/* set-up our fake chunk so that we can process it */
+-		auth.skb = chunk->auth_chunk;
+-		auth.asoc = chunk->asoc;
+-		auth.sctp_hdr = chunk->sctp_hdr;
+-		auth.chunk_hdr = (struct sctp_chunkhdr *)
+-					skb_push(chunk->auth_chunk,
+-						 sizeof(struct sctp_chunkhdr));
+-		skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr));
+-		auth.transport = chunk->transport;
+-
+-		ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
+-		if (ret != SCTP_IERROR_NO_ERROR) {
+-			sctp_association_free(new_asoc);
+-			return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+-		}
++	if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) {
++		sctp_association_free(new_asoc);
++		return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+ 	}
+ 
+ 	repl = sctp_make_cookie_ack(new_asoc, chunk);
+@@ -1758,13 +1759,15 @@ static enum sctp_disposition sctp_sf_do_dupcook_a(
+ 			       GFP_ATOMIC))
+ 		goto nomem;
+ 
++	if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
++		return SCTP_DISPOSITION_DISCARD;
++
+ 	/* Make sure no new addresses are being added during the
+ 	 * restart.  Though this is a pretty complicated attack
+ 	 * since you'd have to get inside the cookie.
+ 	 */
+-	if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) {
++	if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands))
+ 		return SCTP_DISPOSITION_CONSUME;
+-	}
+ 
+ 	/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
+ 	 * the peer has restarted (Action A), it MUST NOT setup a new
+@@ -1870,6 +1873,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_b(
+ 			       GFP_ATOMIC))
+ 		goto nomem;
+ 
++	if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
++		return SCTP_DISPOSITION_DISCARD;
++
+ 	/* Update the content of current association.  */
+ 	sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
+ 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+@@ -1964,6 +1970,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
+ 	 * a COOKIE ACK.
+ 	 */
+ 
++	if (!sctp_auth_chunk_verify(net, chunk, asoc))
++		return SCTP_DISPOSITION_DISCARD;
++
+ 	/* Don't accidentally move back into established state. */
+ 	if (asoc->state < SCTP_STATE_ESTABLISHED) {
+ 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+@@ -2003,7 +2012,7 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
+ 		}
+ 	}
+ 
+-	repl = sctp_make_cookie_ack(new_asoc, chunk);
++	repl = sctp_make_cookie_ack(asoc, chunk);
+ 	if (!repl)
+ 		goto nomem;
+ 
+@@ -4108,10 +4117,7 @@ enum sctp_disposition sctp_sf_eat_fwd_tsn_fast(
+  * The return value is the disposition of the chunk.
+  */
+ static enum sctp_ierror sctp_sf_authenticate(
+-					struct net *net,
+-					const struct sctp_endpoint *ep,
+ 					const struct sctp_association *asoc,
+-					const union sctp_subtype type,
+ 					struct sctp_chunk *chunk)
+ {
+ 	struct sctp_authhdr *auth_hdr;
+@@ -4209,7 +4215,7 @@ enum sctp_disposition sctp_sf_eat_auth(struct net *net,
+ 						  commands);
+ 
+ 	auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
+-	error = sctp_sf_authenticate(net, ep, asoc, type, chunk);
++	error = sctp_sf_authenticate(asoc, chunk);
+ 	switch (error) {
+ 	case SCTP_IERROR_AUTH_BAD_HMAC:
+ 		/* Generate the ERROR chunk and discard the rest
+diff --git a/net/sctp/stream.c b/net/sctp/stream.c
+index f799043abec9..f1f1d1b232ba 100644
+--- a/net/sctp/stream.c
++++ b/net/sctp/stream.c
+@@ -240,6 +240,8 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new)
+ 
+ 	new->out = NULL;
+ 	new->in  = NULL;
++	new->outcnt = 0;
++	new->incnt  = 0;
+ }
+ 
+ static int sctp_send_reconf(struct sctp_association *asoc,
+diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
+index 84207ad33e8e..8cb7d9858270 100644
+--- a/net/sctp/ulpevent.c
++++ b/net/sctp/ulpevent.c
+@@ -715,7 +715,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
+ 	return event;
+ 
+ fail_mark:
+-	sctp_chunk_put(chunk);
+ 	kfree_skb(skb);
+ fail:
+ 	return NULL;
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index afd5a935bbcb..5a983c9bea53 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -973,10 +973,6 @@ static void smc_tcp_listen_work(struct work_struct *work)
+ 	}
+ 
+ out:
+-	if (lsmc->clcsock) {
+-		sock_release(lsmc->clcsock);
+-		lsmc->clcsock = NULL;
+-	}
+ 	release_sock(lsk);
+ 	sock_put(&lsmc->sk); /* sock_hold in smc_listen */
+ }
+@@ -1165,13 +1161,15 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
+ 		/* delegate to CLC child sock */
+ 		release_sock(sk);
+ 		mask = smc->clcsock->ops->poll(file, smc->clcsock, wait);
+-		/* if non-blocking connect finished ... */
+ 		lock_sock(sk);
+-		if ((sk->sk_state == SMC_INIT) && (mask & EPOLLOUT)) {
+-			sk->sk_err = smc->clcsock->sk->sk_err;
+-			if (sk->sk_err) {
+-				mask |= EPOLLERR;
+-			} else {
++		sk->sk_err = smc->clcsock->sk->sk_err;
++		if (sk->sk_err) {
++			mask |= EPOLLERR;
++		} else {
++			/* if non-blocking connect finished ... */
++			if (sk->sk_state == SMC_INIT &&
++			    mask & EPOLLOUT &&
++			    smc->clcsock->sk->sk_state != TCP_CLOSE) {
+ 				rc = smc_connect_rdma(smc);
+ 				if (rc < 0)
+ 					mask |= EPOLLERR;
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index 7dfa9fc99ec3..df4f504b1fef 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -1518,10 +1518,10 @@ static void tipc_sk_set_orig_addr(struct msghdr *m, struct sk_buff *skb)
+ 
+ 	srcaddr->sock.family = AF_TIPC;
+ 	srcaddr->sock.addrtype = TIPC_ADDR_ID;
++	srcaddr->sock.scope = 0;
+ 	srcaddr->sock.addr.id.ref = msg_origport(hdr);
+ 	srcaddr->sock.addr.id.node = msg_orignode(hdr);
+ 	srcaddr->sock.addr.name.domain = 0;
+-	srcaddr->sock.scope = 0;
+ 	m->msg_namelen = sizeof(struct sockaddr_tipc);
+ 
+ 	if (!msg_in_group(hdr))
+@@ -1530,6 +1530,7 @@ static void tipc_sk_set_orig_addr(struct msghdr *m, struct sk_buff *skb)
+ 	/* Group message users may also want to know sending member's id */
+ 	srcaddr->member.family = AF_TIPC;
+ 	srcaddr->member.addrtype = TIPC_ADDR_NAME;
++	srcaddr->member.scope = 0;
+ 	srcaddr->member.addr.name.name.type = msg_nametype(hdr);
+ 	srcaddr->member.addr.name.name.instance = TIPC_SKB_CB(skb)->orig_member;
+ 	srcaddr->member.addr.name.domain = 0;
+diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
+index d824d548447e..b51180c1479a 100644
+--- a/net/tls/tls_main.c
++++ b/net/tls/tls_main.c
+@@ -107,6 +107,7 @@ int tls_push_sg(struct sock *sk,
+ 	size = sg->length - offset;
+ 	offset += sg->offset;
+ 
++	ctx->in_tcp_sendpages = true;
+ 	while (1) {
+ 		if (sg_is_last(sg))
+ 			sendpage_flags = flags;
+@@ -127,6 +128,7 @@ int tls_push_sg(struct sock *sk,
+ 			offset -= sg->offset;
+ 			ctx->partially_sent_offset = offset;
+ 			ctx->partially_sent_record = (void *)sg;
++			ctx->in_tcp_sendpages = false;
+ 			return ret;
+ 		}
+ 
+@@ -141,6 +143,8 @@ int tls_push_sg(struct sock *sk,
+ 	}
+ 
+ 	clear_bit(TLS_PENDING_CLOSED_RECORD, &ctx->flags);
++	ctx->in_tcp_sendpages = false;
++	ctx->sk_write_space(sk);
+ 
+ 	return 0;
+ }
+@@ -210,6 +214,10 @@ static void tls_write_space(struct sock *sk)
+ {
+ 	struct tls_context *ctx = tls_get_ctx(sk);
+ 
++	/* We are already sending pages, ignore notification */
++	if (ctx->in_tcp_sendpages)
++		return;
++
+ 	if (!sk->sk_write_pending && tls_is_pending_closed_record(ctx)) {
+ 		gfp_t sk_allocation = sk->sk_allocation;
+ 		int rc;


             reply	other threads:[~2018-05-20 22:22 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-20 22:22 Mike Pagano [this message]
  -- strict thread matches above, loose matches on Subject: below --
2018-06-26 16:13 [gentoo-commits] proj/linux-patches:4.16 commit in: / Alice Ferrazzi
2018-06-20 19:44 Mike Pagano
2018-06-16 15:45 Mike Pagano
2018-06-11 21:48 Mike Pagano
2018-06-05 11:23 Mike Pagano
2018-05-30 11:44 Mike Pagano
2018-05-25 15:37 Mike Pagano
2018-05-22 19:13 Mike Pagano
2018-05-16 10:25 Mike Pagano
2018-05-09 10:57 Mike Pagano
2018-05-02 16:15 Mike Pagano
2018-04-30 10:30 Mike Pagano
2018-04-26 10:22 Mike Pagano
2018-04-24 11:31 Mike Pagano
2018-04-19 10:45 Mike Pagano
2018-04-12 12:21 Mike Pagano
2018-04-08 14:33 Mike Pagano
2018-03-09 19:24 Mike Pagano
2018-02-12 20:46 Mike Pagano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1526854948.c741e5c30736c7523ab72393e932827a9179a35f.mpagano@gentoo \
    --to=mpagano@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox