diff options
author | 2018-05-20 18:22:28 -0400 | |
---|---|---|
committer | 2018-05-20 18:22:28 -0400 | |
commit | c741e5c30736c7523ab72393e932827a9179a35f (patch) | |
tree | 88ed3f20a520abbdae2efdbde3f4203fe383bf0f | |
parent | Linux patch 4.16.9 (diff) | |
download | linux-patches-4.16-11.tar.gz linux-patches-4.16-11.tar.bz2 linux-patches-4.16-11.zip |
Linux patch 4.16.104.16-11
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1009_linux-4.16.10.patch | 1808 |
2 files changed, 1812 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 73b7e2e1..89eb684a 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 00000000..7d08449d --- /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; |