From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id E3512139578 for ; Tue, 15 Nov 2016 07:59:36 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 1E014E0C25; Tue, 15 Nov 2016 07:59:33 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id E95EAE0C25 for ; Tue, 15 Nov 2016 07:59:32 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id B8F4134105A for ; Tue, 15 Nov 2016 07:59:31 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 582C1A7 for ; Tue, 15 Nov 2016 07:59:30 +0000 (UTC) From: "Alice Ferrazzi" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Alice Ferrazzi" Message-ID: <1479196719.215deabf1be5d79b5db37aee287bca795cf0805d.alicef@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.8 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1007_linux-4.8.8.patch X-VCS-Directories: / X-VCS-Committer: alicef X-VCS-Committer-Name: Alice Ferrazzi X-VCS-Revision: 215deabf1be5d79b5db37aee287bca795cf0805d X-VCS-Branch: 4.8 Date: Tue, 15 Nov 2016 07:59:30 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: e6b8daff-ce6b-464a-9dd7-6f6bbe5a9f1a X-Archives-Hash: a4e5877ea0cbb0de356d8eb6f20f331b commit: 215deabf1be5d79b5db37aee287bca795cf0805d Author: Alice Ferrazzi gentoo org> AuthorDate: Tue Nov 15 07:58:39 2016 +0000 Commit: Alice Ferrazzi gentoo org> CommitDate: Tue Nov 15 07:58:39 2016 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=215deabf Linux patch 4.8.8 0000_README | 4 + 1007_linux-4.8.8.patch | 1846 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1850 insertions(+) diff --git a/0000_README b/0000_README index 9cd8633..236529a 100644 --- a/0000_README +++ b/0000_README @@ -71,6 +71,10 @@ Patch: 1006_linux-4.8.7.patch From: http://www.kernel.org Desc: Linux 4.8.7 +Patch: 1007_linux-4.8.8.patch +From: http://www.kernel.org +Desc: Linux 4.8.8 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1007_linux-4.8.8.patch b/1007_linux-4.8.8.patch new file mode 100644 index 0000000..7f46629 --- /dev/null +++ b/1007_linux-4.8.8.patch @@ -0,0 +1,1846 @@ +diff --git a/Makefile b/Makefile +index 4d0f28cb481d..8f18daa2c76a 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 8 +-SUBLEVEL = 7 ++SUBLEVEL = 8 + EXTRAVERSION = + NAME = Psychotic Stoned Sheep + +diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h +index ee655ed1ff1b..1e8fceb308a5 100644 +--- a/arch/powerpc/include/asm/checksum.h ++++ b/arch/powerpc/include/asm/checksum.h +@@ -53,10 +53,8 @@ static inline __sum16 csum_fold(__wsum sum) + return (__force __sum16)(~((__force u32)sum + tmp) >> 16); + } + +-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, +- unsigned short len, +- unsigned short proto, +- __wsum sum) ++static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, ++ __u8 proto, __wsum sum) + { + #ifdef __powerpc64__ + unsigned long s = (__force u32)sum; +@@ -83,10 +81,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, +- unsigned short len, +- unsigned short proto, +- __wsum sum) ++static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, ++ __u8 proto, __wsum sum) + { + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); + } +diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h +index 9dbfcc0ab577..5ff64afd69f9 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib.h ++++ b/drivers/infiniband/ulp/ipoib/ipoib.h +@@ -63,6 +63,8 @@ enum ipoib_flush_level { + + enum { + IPOIB_ENCAP_LEN = 4, ++ IPOIB_PSEUDO_LEN = 20, ++ IPOIB_HARD_LEN = IPOIB_ENCAP_LEN + IPOIB_PSEUDO_LEN, + + IPOIB_UD_HEAD_SIZE = IB_GRH_BYTES + IPOIB_ENCAP_LEN, + IPOIB_UD_RX_SG = 2, /* max buffer needed for 4K mtu */ +@@ -134,15 +136,21 @@ struct ipoib_header { + u16 reserved; + }; + +-struct ipoib_cb { +- struct qdisc_skb_cb qdisc_cb; +- u8 hwaddr[INFINIBAND_ALEN]; ++struct ipoib_pseudo_header { ++ u8 hwaddr[INFINIBAND_ALEN]; + }; + +-static inline struct ipoib_cb *ipoib_skb_cb(const struct sk_buff *skb) ++static inline void skb_add_pseudo_hdr(struct sk_buff *skb) + { +- BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ipoib_cb)); +- return (struct ipoib_cb *)skb->cb; ++ char *data = skb_push(skb, IPOIB_PSEUDO_LEN); ++ ++ /* ++ * only the ipoib header is present now, make room for a dummy ++ * pseudo header and set skb field accordingly ++ */ ++ memset(data, 0, IPOIB_PSEUDO_LEN); ++ skb_reset_mac_header(skb); ++ skb_pull(skb, IPOIB_HARD_LEN); + } + + /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +index 4ad297d3de89..339a1eecdfe3 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +@@ -63,6 +63,8 @@ MODULE_PARM_DESC(cm_data_debug_level, + #define IPOIB_CM_RX_DELAY (3 * 256 * HZ) + #define IPOIB_CM_RX_UPDATE_MASK (0x3) + ++#define IPOIB_CM_RX_RESERVE (ALIGN(IPOIB_HARD_LEN, 16) - IPOIB_ENCAP_LEN) ++ + static struct ib_qp_attr ipoib_cm_err_attr = { + .qp_state = IB_QPS_ERR + }; +@@ -146,15 +148,15 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, + struct sk_buff *skb; + int i; + +- skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12); ++ skb = dev_alloc_skb(ALIGN(IPOIB_CM_HEAD_SIZE + IPOIB_PSEUDO_LEN, 16)); + if (unlikely(!skb)) + return NULL; + + /* +- * IPoIB adds a 4 byte header. So we need 12 more bytes to align the ++ * IPoIB adds a IPOIB_ENCAP_LEN byte header, this will align the + * IP header to a multiple of 16. + */ +- skb_reserve(skb, 12); ++ skb_reserve(skb, IPOIB_CM_RX_RESERVE); + + mapping[0] = ib_dma_map_single(priv->ca, skb->data, IPOIB_CM_HEAD_SIZE, + DMA_FROM_DEVICE); +@@ -624,9 +626,9 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) + if (wc->byte_len < IPOIB_CM_COPYBREAK) { + int dlen = wc->byte_len; + +- small_skb = dev_alloc_skb(dlen + 12); ++ small_skb = dev_alloc_skb(dlen + IPOIB_CM_RX_RESERVE); + if (small_skb) { +- skb_reserve(small_skb, 12); ++ skb_reserve(small_skb, IPOIB_CM_RX_RESERVE); + ib_dma_sync_single_for_cpu(priv->ca, rx_ring[wr_id].mapping[0], + dlen, DMA_FROM_DEVICE); + skb_copy_from_linear_data(skb, small_skb->data, dlen); +@@ -663,8 +665,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) + + copied: + skb->protocol = ((struct ipoib_header *) skb->data)->proto; +- skb_reset_mac_header(skb); +- skb_pull(skb, IPOIB_ENCAP_LEN); ++ skb_add_pseudo_hdr(skb); + + ++dev->stats.rx_packets; + dev->stats.rx_bytes += skb->len; +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c +index be11d5d5b8c1..830fecb6934c 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c +@@ -128,16 +128,15 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id) + + buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); + +- skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN); ++ skb = dev_alloc_skb(buf_size + IPOIB_HARD_LEN); + if (unlikely(!skb)) + return NULL; + + /* +- * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte +- * header. So we need 4 more bytes to get to 48 and align the +- * IP header to a multiple of 16. ++ * the IP header will be at IPOIP_HARD_LEN + IB_GRH_BYTES, that is ++ * 64 bytes aligned + */ +- skb_reserve(skb, 4); ++ skb_reserve(skb, sizeof(struct ipoib_pseudo_header)); + + mapping = priv->rx_ring[id].mapping; + mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size, +@@ -253,8 +252,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) + skb_pull(skb, IB_GRH_BYTES); + + skb->protocol = ((struct ipoib_header *) skb->data)->proto; +- skb_reset_mac_header(skb); +- skb_pull(skb, IPOIB_ENCAP_LEN); ++ skb_add_pseudo_hdr(skb); + + ++dev->stats.rx_packets; + dev->stats.rx_bytes += skb->len; +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c +index cc1c1b062ea5..823a528ef4eb 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c +@@ -925,9 +925,12 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, + ipoib_neigh_free(neigh); + goto err_drop; + } +- if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) ++ if (skb_queue_len(&neigh->queue) < ++ IPOIB_MAX_PATH_REC_QUEUE) { ++ /* put pseudoheader back on for next time */ ++ skb_push(skb, IPOIB_PSEUDO_LEN); + __skb_queue_tail(&neigh->queue, skb); +- else { ++ } else { + ipoib_warn(priv, "queue length limit %d. Packet drop.\n", + skb_queue_len(&neigh->queue)); + goto err_drop; +@@ -964,7 +967,7 @@ err_drop: + } + + static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, +- struct ipoib_cb *cb) ++ struct ipoib_pseudo_header *phdr) + { + struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_path *path; +@@ -972,16 +975,18 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, + + spin_lock_irqsave(&priv->lock, flags); + +- path = __path_find(dev, cb->hwaddr + 4); ++ path = __path_find(dev, phdr->hwaddr + 4); + if (!path || !path->valid) { + int new_path = 0; + + if (!path) { +- path = path_rec_create(dev, cb->hwaddr + 4); ++ path = path_rec_create(dev, phdr->hwaddr + 4); + new_path = 1; + } + if (path) { + if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { ++ /* put pseudoheader back on for next time */ ++ skb_push(skb, IPOIB_PSEUDO_LEN); + __skb_queue_tail(&path->queue, skb); + } else { + ++dev->stats.tx_dropped; +@@ -1009,10 +1014,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, + be16_to_cpu(path->pathrec.dlid)); + + spin_unlock_irqrestore(&priv->lock, flags); +- ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr)); ++ ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); + return; + } else if ((path->query || !path_rec_start(dev, path)) && + skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { ++ /* put pseudoheader back on for next time */ ++ skb_push(skb, IPOIB_PSEUDO_LEN); + __skb_queue_tail(&path->queue, skb); + } else { + ++dev->stats.tx_dropped; +@@ -1026,13 +1033,15 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_neigh *neigh; +- struct ipoib_cb *cb = ipoib_skb_cb(skb); ++ struct ipoib_pseudo_header *phdr; + struct ipoib_header *header; + unsigned long flags; + ++ phdr = (struct ipoib_pseudo_header *) skb->data; ++ skb_pull(skb, sizeof(*phdr)); + header = (struct ipoib_header *) skb->data; + +- if (unlikely(cb->hwaddr[4] == 0xff)) { ++ if (unlikely(phdr->hwaddr[4] == 0xff)) { + /* multicast, arrange "if" according to probability */ + if ((header->proto != htons(ETH_P_IP)) && + (header->proto != htons(ETH_P_IPV6)) && +@@ -1045,13 +1054,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) + return NETDEV_TX_OK; + } + /* Add in the P_Key for multicast*/ +- cb->hwaddr[8] = (priv->pkey >> 8) & 0xff; +- cb->hwaddr[9] = priv->pkey & 0xff; ++ phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; ++ phdr->hwaddr[9] = priv->pkey & 0xff; + +- neigh = ipoib_neigh_get(dev, cb->hwaddr); ++ neigh = ipoib_neigh_get(dev, phdr->hwaddr); + if (likely(neigh)) + goto send_using_neigh; +- ipoib_mcast_send(dev, cb->hwaddr, skb); ++ ipoib_mcast_send(dev, phdr->hwaddr, skb); + return NETDEV_TX_OK; + } + +@@ -1060,16 +1069,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) + case htons(ETH_P_IP): + case htons(ETH_P_IPV6): + case htons(ETH_P_TIPC): +- neigh = ipoib_neigh_get(dev, cb->hwaddr); ++ neigh = ipoib_neigh_get(dev, phdr->hwaddr); + if (unlikely(!neigh)) { +- neigh_add_path(skb, cb->hwaddr, dev); ++ neigh_add_path(skb, phdr->hwaddr, dev); + return NETDEV_TX_OK; + } + break; + case htons(ETH_P_ARP): + case htons(ETH_P_RARP): + /* for unicast ARP and RARP should always perform path find */ +- unicast_arp_send(skb, dev, cb); ++ unicast_arp_send(skb, dev, phdr); + return NETDEV_TX_OK; + default: + /* ethertype not supported by IPoIB */ +@@ -1086,11 +1095,13 @@ send_using_neigh: + goto unref; + } + } else if (neigh->ah) { +- ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(cb->hwaddr)); ++ ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(phdr->hwaddr)); + goto unref; + } + + if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { ++ /* put pseudoheader back on for next time */ ++ skb_push(skb, sizeof(*phdr)); + spin_lock_irqsave(&priv->lock, flags); + __skb_queue_tail(&neigh->queue, skb); + spin_unlock_irqrestore(&priv->lock, flags); +@@ -1122,8 +1133,8 @@ static int ipoib_hard_header(struct sk_buff *skb, + unsigned short type, + const void *daddr, const void *saddr, unsigned len) + { ++ struct ipoib_pseudo_header *phdr; + struct ipoib_header *header; +- struct ipoib_cb *cb = ipoib_skb_cb(skb); + + header = (struct ipoib_header *) skb_push(skb, sizeof *header); + +@@ -1132,12 +1143,13 @@ static int ipoib_hard_header(struct sk_buff *skb, + + /* + * we don't rely on dst_entry structure, always stuff the +- * destination address into skb->cb so we can figure out where ++ * destination address into skb hard header so we can figure out where + * to send the packet later. + */ +- memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN); ++ phdr = (struct ipoib_pseudo_header *) skb_push(skb, sizeof(*phdr)); ++ memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); + +- return sizeof *header; ++ return IPOIB_HARD_LEN; + } + + static void ipoib_set_mcast_list(struct net_device *dev) +@@ -1759,7 +1771,7 @@ void ipoib_setup(struct net_device *dev) + + dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + +- dev->hard_header_len = IPOIB_ENCAP_LEN; ++ dev->hard_header_len = IPOIB_HARD_LEN; + dev->addr_len = INFINIBAND_ALEN; + dev->type = ARPHRD_INFINIBAND; + dev->tx_queue_len = ipoib_sendq_size * 2; +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +index d3394b6add24..1909dd252c94 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +@@ -796,9 +796,11 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) + __ipoib_mcast_add(dev, mcast); + list_add_tail(&mcast->list, &priv->multicast_list); + } +- if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) ++ if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) { ++ /* put pseudoheader back on for next time */ ++ skb_push(skb, sizeof(struct ipoib_pseudo_header)); + skb_queue_tail(&mcast->pkt_queue, skb); +- else { ++ } else { + ++dev->stats.tx_dropped; + dev_kfree_skb_any(skb); + } +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 692ee248e486..3474de576dde 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -913,13 +913,11 @@ fec_restart(struct net_device *ndev) + * enet-mac reset will reset mac address registers too, + * so need to reconfigure it. + */ +- if (fep->quirks & FEC_QUIRK_ENET_MAC) { +- memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); +- writel((__force u32)cpu_to_be32(temp_mac[0]), +- fep->hwp + FEC_ADDR_LOW); +- writel((__force u32)cpu_to_be32(temp_mac[1]), +- fep->hwp + FEC_ADDR_HIGH); +- } ++ memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); ++ writel((__force u32)cpu_to_be32(temp_mac[0]), ++ fep->hwp + FEC_ADDR_LOW); ++ writel((__force u32)cpu_to_be32(temp_mac[1]), ++ fep->hwp + FEC_ADDR_HIGH); + + /* Clear any outstanding interrupt. */ + writel(0xffffffff, fep->hwp + FEC_IEVENT); +@@ -1432,14 +1430,14 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + skb_put(skb, pkt_len - 4); + data = skb->data; + ++ if (!is_copybreak && need_swap) ++ swap_buffer(data, pkt_len); ++ + #if !defined(CONFIG_M5272) + if (fep->quirks & FEC_QUIRK_HAS_RACC) + data = skb_pull_inline(skb, 2); + #endif + +- if (!is_copybreak && need_swap) +- swap_buffer(data, pkt_len); +- + /* Extract the enhanced buffer descriptor */ + ebdp = NULL; + if (fep->bufdesc_ex) +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c +index 132cea655920..e3be7e44ff51 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c +@@ -127,7 +127,15 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, + /* For TX we use the same irq per + ring we assigned for the RX */ + struct mlx4_en_cq *rx_cq; +- ++ int xdp_index; ++ ++ /* The xdp tx irq must align with the rx ring that forwards to ++ * it, so reindex these from 0. This should only happen when ++ * tx_ring_num is not a multiple of rx_ring_num. ++ */ ++ xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx; ++ if (xdp_index >= 0) ++ cq_idx = xdp_index; + cq_idx = cq_idx % priv->rx_ring_num; + rx_cq = priv->rx_cq[cq_idx]; + cq->vector = rx_cq->vector; +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index 3c20e87bb761..16af1ce99233 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -453,7 +453,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk, + + skb_gro_pull(skb, gh_len); + skb_gro_postpull_rcsum(skb, gh, gh_len); +- pp = ptype->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + flush = 0; + + out_unlock: +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index 3ba29fc80d05..c4d9653cae66 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -624,15 +624,18 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, + packet->total_data_buflen); + + skb->protocol = eth_type_trans(skb, net); +- if (csum_info) { +- /* We only look at the IP checksum here. +- * Should we be dropping the packet if checksum +- * failed? How do we deal with other checksums - TCP/UDP? +- */ +- if (csum_info->receive.ip_checksum_succeeded) ++ ++ /* skb is already created with CHECKSUM_NONE */ ++ skb_checksum_none_assert(skb); ++ ++ /* ++ * In Linux, the IP checksum is always checked. ++ * Do L4 checksum offload if enabled and present. ++ */ ++ if (csum_info && (net->features & NETIF_F_RXCSUM)) { ++ if (csum_info->receive.tcp_checksum_succeeded || ++ csum_info->receive.udp_checksum_succeeded) + skb->ip_summed = CHECKSUM_UNNECESSARY; +- else +- skb->ip_summed = CHECKSUM_NONE; + } + + if (vlan_tci & VLAN_TAG_PRESENT) +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index 351e701eb043..b72ddc61eff8 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -397,6 +397,14 @@ static struct macsec_cb *macsec_skb_cb(struct sk_buff *skb) + #define DEFAULT_ENCRYPT false + #define DEFAULT_ENCODING_SA 0 + ++static bool send_sci(const struct macsec_secy *secy) ++{ ++ const struct macsec_tx_sc *tx_sc = &secy->tx_sc; ++ ++ return tx_sc->send_sci || ++ (secy->n_rx_sc > 1 && !tx_sc->end_station && !tx_sc->scb); ++} ++ + static sci_t make_sci(u8 *addr, __be16 port) + { + sci_t sci; +@@ -437,15 +445,15 @@ static unsigned int macsec_extra_len(bool sci_present) + + /* Fill SecTAG according to IEEE 802.1AE-2006 10.5.3 */ + static void macsec_fill_sectag(struct macsec_eth_header *h, +- const struct macsec_secy *secy, u32 pn) ++ const struct macsec_secy *secy, u32 pn, ++ bool sci_present) + { + const struct macsec_tx_sc *tx_sc = &secy->tx_sc; + +- memset(&h->tci_an, 0, macsec_sectag_len(tx_sc->send_sci)); ++ memset(&h->tci_an, 0, macsec_sectag_len(sci_present)); + h->eth.h_proto = htons(ETH_P_MACSEC); + +- if (tx_sc->send_sci || +- (secy->n_rx_sc > 1 && !tx_sc->end_station && !tx_sc->scb)) { ++ if (sci_present) { + h->tci_an |= MACSEC_TCI_SC; + memcpy(&h->secure_channel_id, &secy->sci, + sizeof(h->secure_channel_id)); +@@ -650,6 +658,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + struct macsec_tx_sc *tx_sc; + struct macsec_tx_sa *tx_sa; + struct macsec_dev *macsec = macsec_priv(dev); ++ bool sci_present; + u32 pn; + + secy = &macsec->secy; +@@ -687,7 +696,8 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + + unprotected_len = skb->len; + eth = eth_hdr(skb); +- hh = (struct macsec_eth_header *)skb_push(skb, macsec_extra_len(tx_sc->send_sci)); ++ sci_present = send_sci(secy); ++ hh = (struct macsec_eth_header *)skb_push(skb, macsec_extra_len(sci_present)); + memmove(hh, eth, 2 * ETH_ALEN); + + pn = tx_sa_update_pn(tx_sa, secy); +@@ -696,7 +706,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + kfree_skb(skb); + return ERR_PTR(-ENOLINK); + } +- macsec_fill_sectag(hh, secy, pn); ++ macsec_fill_sectag(hh, secy, pn, sci_present); + macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN); + + skb_put(skb, secy->icv_len); +@@ -726,10 +736,10 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + skb_to_sgvec(skb, sg, 0, skb->len); + + if (tx_sc->encrypt) { +- int len = skb->len - macsec_hdr_len(tx_sc->send_sci) - ++ int len = skb->len - macsec_hdr_len(sci_present) - + secy->icv_len; + aead_request_set_crypt(req, sg, sg, len, iv); +- aead_request_set_ad(req, macsec_hdr_len(tx_sc->send_sci)); ++ aead_request_set_ad(req, macsec_hdr_len(sci_present)); + } else { + aead_request_set_crypt(req, sg, sg, 0, iv); + aead_request_set_ad(req, skb->len - secy->icv_len); +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index c6f66832a1a6..f424b867f73e 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -608,6 +608,21 @@ void phy_start_machine(struct phy_device *phydev) + } + + /** ++ * phy_trigger_machine - trigger the state machine to run ++ * ++ * @phydev: the phy_device struct ++ * ++ * Description: There has been a change in state which requires that the ++ * state machine runs. ++ */ ++ ++static void phy_trigger_machine(struct phy_device *phydev) ++{ ++ cancel_delayed_work_sync(&phydev->state_queue); ++ queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0); ++} ++ ++/** + * phy_stop_machine - stop the PHY state machine tracking + * @phydev: target phy_device struct + * +@@ -639,6 +654,8 @@ static void phy_error(struct phy_device *phydev) + mutex_lock(&phydev->lock); + phydev->state = PHY_HALTED; + mutex_unlock(&phydev->lock); ++ ++ phy_trigger_machine(phydev); + } + + /** +@@ -800,8 +817,7 @@ void phy_change(struct work_struct *work) + } + + /* reschedule state queue work to run as soon as possible */ +- cancel_delayed_work_sync(&phydev->state_queue); +- queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0); ++ phy_trigger_machine(phydev); + return; + + ignore: +@@ -890,6 +906,8 @@ void phy_start(struct phy_device *phydev) + /* if phy was suspended, bring the physical link up again */ + if (do_resume) + phy_resume(phydev); ++ ++ phy_trigger_machine(phydev); + } + EXPORT_SYMBOL(phy_start); + +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 6e65832051d6..5ae664c02528 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -584,7 +584,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk, + } + } + +- pp = eth_gro_receive(head, skb); ++ pp = call_gro_receive(eth_gro_receive, head, skb); + flush = 0; + + out: +diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c +index d637c933c8a9..58a97d420572 100644 +--- a/drivers/ptp/ptp_chardev.c ++++ b/drivers/ptp/ptp_chardev.c +@@ -193,6 +193,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) + if (err) + break; + ++ memset(&precise_offset, 0, sizeof(precise_offset)); + ts = ktime_to_timespec64(xtstamp.device); + precise_offset.device.sec = ts.tv_sec; + precise_offset.device.nsec = ts.tv_nsec; +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index ca86c885dfaa..3aaea713bf37 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -2233,7 +2233,7 @@ struct megasas_instance_template { + }; + + #define MEGASAS_IS_LOGICAL(scp) \ +- (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1 ++ ((scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1) + + #define MEGASAS_DEV_INDEX(scp) \ + (((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index c1ed25adb17e..71e489937c6f 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -1713,16 +1713,13 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) + goto out_done; + } + +- switch (scmd->cmnd[0]) { +- case SYNCHRONIZE_CACHE: +- /* +- * FW takes care of flush cache on its own +- * No need to send it down +- */ ++ /* ++ * FW takes care of flush cache on its own for Virtual Disk. ++ * No need to send it down for VD. For JBOD send SYNCHRONIZE_CACHE to FW. ++ */ ++ if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd)) { + scmd->result = DID_OK << 16; + goto out_done; +- default: +- break; + } + + return instance->instancet->build_and_issue_cmd(instance, scmd); +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 6443cfba7b55..dc3b5962d087 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -789,6 +789,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, + req->trb = trb; + req->trb_dma = dwc3_trb_dma_offset(dep, trb); + req->first_trb_index = dep->trb_enqueue; ++ dep->queued_requests++; + } + + dwc3_ep_inc_enq(dep); +@@ -841,8 +842,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, + + trb->ctrl |= DWC3_TRB_CTRL_HWO; + +- dep->queued_requests++; +- + trace_dwc3_prepare_trb(dep, trb); + } + +@@ -1963,7 +1962,9 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, + unsigned int s_pkt = 0; + unsigned int trb_status; + +- dep->queued_requests--; ++ if (req->trb == trb) ++ dep->queued_requests--; ++ + trace_dwc3_complete_trb(dep, trb); + + /* +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index e8d79d4ebcfe..e942c67ea230 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2154,7 +2154,10 @@ struct napi_gro_cb { + /* Used to determine if flush_id can be ignored */ + u8 is_atomic:1; + +- /* 5 bit hole */ ++ /* Number of gro_receive callbacks this packet already went through */ ++ u8 recursion_counter:4; ++ ++ /* 1 bit hole */ + + /* used to support CHECKSUM_COMPLETE for tunneling protocols */ + __wsum csum; +@@ -2165,6 +2168,40 @@ struct napi_gro_cb { + + #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) + ++#define GRO_RECURSION_LIMIT 15 ++static inline int gro_recursion_inc_test(struct sk_buff *skb) ++{ ++ return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT; ++} ++ ++typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *); ++static inline struct sk_buff **call_gro_receive(gro_receive_t cb, ++ struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (unlikely(gro_recursion_inc_test(skb))) { ++ NAPI_GRO_CB(skb)->flush |= 1; ++ return NULL; ++ } ++ ++ return cb(head, skb); ++} ++ ++typedef struct sk_buff **(*gro_receive_sk_t)(struct sock *, struct sk_buff **, ++ struct sk_buff *); ++static inline struct sk_buff **call_gro_receive_sk(gro_receive_sk_t cb, ++ struct sock *sk, ++ struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (unlikely(gro_recursion_inc_test(skb))) { ++ NAPI_GRO_CB(skb)->flush |= 1; ++ return NULL; ++ } ++ ++ return cb(sk, head, skb); ++} ++ + struct packet_type { + __be16 type; /* This is really htons(ether_type). */ + struct net_device *dev; /* NULL is wildcarded here */ +@@ -3862,7 +3899,7 @@ struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev, + ldev = netdev_all_lower_get_next(dev, &(iter))) + + #define netdev_for_each_all_lower_dev_rcu(dev, ldev, iter) \ +- for (iter = (dev)->all_adj_list.lower.next, \ ++ for (iter = &(dev)->all_adj_list.lower, \ + ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \ + ldev; \ + ldev = netdev_all_lower_get_next_rcu(dev, &(iter))) +diff --git a/include/net/ip.h b/include/net/ip.h +index 9742b92dc933..156b0c11b524 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -549,7 +549,7 @@ int ip_options_rcv_srr(struct sk_buff *skb); + */ + + void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb); +-void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int offset); ++void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int tlen, int offset); + int ip_cmsg_send(struct sock *sk, struct msghdr *msg, + struct ipcm_cookie *ipc, bool allow_ipv6); + int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, +@@ -571,7 +571,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, + + static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) + { +- ip_cmsg_recv_offset(msg, skb, 0); ++ ip_cmsg_recv_offset(msg, skb, 0, 0); + } + + bool icmp_global_allow(void); +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index d97305d0e71f..0a2d2701285d 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -32,6 +32,7 @@ struct route_info { + #define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008 + #define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010 + #define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 ++#define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040 + + /* We do not (yet ?) support IPv6 jumbograms (RFC 2675) + * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header +diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h +index 262f0379d83a..5a78be518101 100644 +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -350,7 +350,7 @@ struct rtnexthop { + #define RTNH_F_OFFLOAD 8 /* offloaded route */ + #define RTNH_F_LINKDOWN 16 /* carrier-down on nexthop */ + +-#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN) ++#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD) + + /* Macros to handle hexthops */ + +diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c +index 8de138d3306b..f2531ad66b68 100644 +--- a/net/8021q/vlan.c ++++ b/net/8021q/vlan.c +@@ -664,7 +664,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head, + + skb_gro_pull(skb, sizeof(*vhdr)); + skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr)); +- pp = ptype->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index c5fea9393946..2136e45f5277 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -972,13 +972,12 @@ static void br_multicast_enable(struct bridge_mcast_own_query *query) + mod_timer(&query->timer, jiffies); + } + +-void br_multicast_enable_port(struct net_bridge_port *port) ++static void __br_multicast_enable_port(struct net_bridge_port *port) + { + struct net_bridge *br = port->br; + +- spin_lock(&br->multicast_lock); + if (br->multicast_disabled || !netif_running(br->dev)) +- goto out; ++ return; + + br_multicast_enable(&port->ip4_own_query); + #if IS_ENABLED(CONFIG_IPV6) +@@ -987,8 +986,14 @@ void br_multicast_enable_port(struct net_bridge_port *port) + if (port->multicast_router == MDB_RTR_TYPE_PERM && + hlist_unhashed(&port->rlist)) + br_multicast_add_router(br, port); ++} + +-out: ++void br_multicast_enable_port(struct net_bridge_port *port) ++{ ++ struct net_bridge *br = port->br; ++ ++ spin_lock(&br->multicast_lock); ++ __br_multicast_enable_port(port); + spin_unlock(&br->multicast_lock); + } + +@@ -1994,8 +1999,9 @@ static void br_multicast_start_querier(struct net_bridge *br, + + int br_multicast_toggle(struct net_bridge *br, unsigned long val) + { +- int err = 0; + struct net_bridge_mdb_htable *mdb; ++ struct net_bridge_port *port; ++ int err = 0; + + spin_lock_bh(&br->multicast_lock); + if (br->multicast_disabled == !val) +@@ -2023,10 +2029,9 @@ rollback: + goto rollback; + } + +- br_multicast_start_querier(br, &br->ip4_own_query); +-#if IS_ENABLED(CONFIG_IPV6) +- br_multicast_start_querier(br, &br->ip6_own_query); +-#endif ++ br_multicast_open(br); ++ list_for_each_entry(port, &br->port_list, list) ++ __br_multicast_enable_port(port); + + unlock: + spin_unlock_bh(&br->multicast_lock); +diff --git a/net/core/dev.c b/net/core/dev.c +index ea6312057a71..44b3ba462ba1 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3035,6 +3035,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d + } + return head; + } ++EXPORT_SYMBOL_GPL(validate_xmit_skb_list); + + static void qdisc_pkt_len_init(struct sk_buff *skb) + { +@@ -4496,6 +4497,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff + NAPI_GRO_CB(skb)->flush = 0; + NAPI_GRO_CB(skb)->free = 0; + NAPI_GRO_CB(skb)->encap_mark = 0; ++ NAPI_GRO_CB(skb)->recursion_counter = 0; + NAPI_GRO_CB(skb)->is_fou = 0; + NAPI_GRO_CB(skb)->is_atomic = 1; + NAPI_GRO_CB(skb)->gro_remcsum_start = 0; +@@ -5500,10 +5502,14 @@ struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev, + { + struct netdev_adjacent *lower; + +- lower = list_first_or_null_rcu(&dev->all_adj_list.lower, +- struct netdev_adjacent, list); ++ lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); ++ ++ if (&lower->list == &dev->all_adj_list.lower) ++ return NULL; ++ ++ *iter = &lower->list; + +- return lower ? lower->dev : NULL; ++ return lower->dev; + } + EXPORT_SYMBOL(netdev_all_lower_get_next_rcu); + +@@ -5578,6 +5584,7 @@ static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, + + static int __netdev_adjacent_dev_insert(struct net_device *dev, + struct net_device *adj_dev, ++ u16 ref_nr, + struct list_head *dev_list, + void *private, bool master) + { +@@ -5587,7 +5594,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, + adj = __netdev_find_adj(adj_dev, dev_list); + + if (adj) { +- adj->ref_nr++; ++ adj->ref_nr += ref_nr; + return 0; + } + +@@ -5597,7 +5604,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, + + adj->dev = adj_dev; + adj->master = master; +- adj->ref_nr = 1; ++ adj->ref_nr = ref_nr; + adj->private = private; + dev_hold(adj_dev); + +@@ -5636,6 +5643,7 @@ free_adj: + + static void __netdev_adjacent_dev_remove(struct net_device *dev, + struct net_device *adj_dev, ++ u16 ref_nr, + struct list_head *dev_list) + { + struct netdev_adjacent *adj; +@@ -5648,10 +5656,10 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, + BUG(); + } + +- if (adj->ref_nr > 1) { +- pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name, +- adj->ref_nr-1); +- adj->ref_nr--; ++ if (adj->ref_nr > ref_nr) { ++ pr_debug("%s to %s ref_nr-%d = %d\n", dev->name, adj_dev->name, ++ ref_nr, adj->ref_nr-ref_nr); ++ adj->ref_nr -= ref_nr; + return; + } + +@@ -5670,21 +5678,22 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, + + static int __netdev_adjacent_dev_link_lists(struct net_device *dev, + struct net_device *upper_dev, ++ u16 ref_nr, + struct list_head *up_list, + struct list_head *down_list, + void *private, bool master) + { + int ret; + +- ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private, +- master); ++ ret = __netdev_adjacent_dev_insert(dev, upper_dev, ref_nr, up_list, ++ private, master); + if (ret) + return ret; + +- ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private, +- false); ++ ret = __netdev_adjacent_dev_insert(upper_dev, dev, ref_nr, down_list, ++ private, false); + if (ret) { +- __netdev_adjacent_dev_remove(dev, upper_dev, up_list); ++ __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list); + return ret; + } + +@@ -5692,9 +5701,10 @@ static int __netdev_adjacent_dev_link_lists(struct net_device *dev, + } + + static int __netdev_adjacent_dev_link(struct net_device *dev, +- struct net_device *upper_dev) ++ struct net_device *upper_dev, ++ u16 ref_nr) + { +- return __netdev_adjacent_dev_link_lists(dev, upper_dev, ++ return __netdev_adjacent_dev_link_lists(dev, upper_dev, ref_nr, + &dev->all_adj_list.upper, + &upper_dev->all_adj_list.lower, + NULL, false); +@@ -5702,17 +5712,19 @@ static int __netdev_adjacent_dev_link(struct net_device *dev, + + static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, + struct net_device *upper_dev, ++ u16 ref_nr, + struct list_head *up_list, + struct list_head *down_list) + { +- __netdev_adjacent_dev_remove(dev, upper_dev, up_list); +- __netdev_adjacent_dev_remove(upper_dev, dev, down_list); ++ __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list); ++ __netdev_adjacent_dev_remove(upper_dev, dev, ref_nr, down_list); + } + + static void __netdev_adjacent_dev_unlink(struct net_device *dev, +- struct net_device *upper_dev) ++ struct net_device *upper_dev, ++ u16 ref_nr) + { +- __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ++ __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ref_nr, + &dev->all_adj_list.upper, + &upper_dev->all_adj_list.lower); + } +@@ -5721,17 +5733,17 @@ static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, + struct net_device *upper_dev, + void *private, bool master) + { +- int ret = __netdev_adjacent_dev_link(dev, upper_dev); ++ int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1); + + if (ret) + return ret; + +- ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, ++ ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, 1, + &dev->adj_list.upper, + &upper_dev->adj_list.lower, + private, master); + if (ret) { +- __netdev_adjacent_dev_unlink(dev, upper_dev); ++ __netdev_adjacent_dev_unlink(dev, upper_dev, 1); + return ret; + } + +@@ -5741,8 +5753,8 @@ static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, + static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, + struct net_device *upper_dev) + { +- __netdev_adjacent_dev_unlink(dev, upper_dev); +- __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ++ __netdev_adjacent_dev_unlink(dev, upper_dev, 1); ++ __netdev_adjacent_dev_unlink_lists(dev, upper_dev, 1, + &dev->adj_list.upper, + &upper_dev->adj_list.lower); + } +@@ -5795,7 +5807,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, + list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { + pr_debug("Interlinking %s with %s, non-neighbour\n", + i->dev->name, j->dev->name); +- ret = __netdev_adjacent_dev_link(i->dev, j->dev); ++ ret = __netdev_adjacent_dev_link(i->dev, j->dev, i->ref_nr); + if (ret) + goto rollback_mesh; + } +@@ -5805,7 +5817,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { + pr_debug("linking %s's upper device %s with %s\n", + upper_dev->name, i->dev->name, dev->name); +- ret = __netdev_adjacent_dev_link(dev, i->dev); ++ ret = __netdev_adjacent_dev_link(dev, i->dev, i->ref_nr); + if (ret) + goto rollback_upper_mesh; + } +@@ -5814,7 +5826,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, + list_for_each_entry(i, &dev->all_adj_list.lower, list) { + pr_debug("linking %s's lower device %s with %s\n", dev->name, + i->dev->name, upper_dev->name); +- ret = __netdev_adjacent_dev_link(i->dev, upper_dev); ++ ret = __netdev_adjacent_dev_link(i->dev, upper_dev, i->ref_nr); + if (ret) + goto rollback_lower_mesh; + } +@@ -5832,7 +5844,7 @@ rollback_lower_mesh: + list_for_each_entry(i, &dev->all_adj_list.lower, list) { + if (i == to_i) + break; +- __netdev_adjacent_dev_unlink(i->dev, upper_dev); ++ __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr); + } + + i = NULL; +@@ -5842,7 +5854,7 @@ rollback_upper_mesh: + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { + if (i == to_i) + break; +- __netdev_adjacent_dev_unlink(dev, i->dev); ++ __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); + } + + i = j = NULL; +@@ -5854,7 +5866,7 @@ rollback_mesh: + list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { + if (i == to_i && j == to_j) + break; +- __netdev_adjacent_dev_unlink(i->dev, j->dev); ++ __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr); + } + if (i == to_i) + break; +@@ -5934,16 +5946,16 @@ void netdev_upper_dev_unlink(struct net_device *dev, + */ + list_for_each_entry(i, &dev->all_adj_list.lower, list) + list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) +- __netdev_adjacent_dev_unlink(i->dev, j->dev); ++ __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr); + + /* remove also the devices itself from lower/upper device + * list + */ + list_for_each_entry(i, &dev->all_adj_list.lower, list) +- __netdev_adjacent_dev_unlink(i->dev, upper_dev); ++ __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr); + + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) +- __netdev_adjacent_dev_unlink(dev, i->dev); ++ __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); + + call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, + &changeupper_info.info); +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index bbd118b19aef..306b8f0e03c1 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -216,8 +216,8 @@ + #define M_QUEUE_XMIT 2 /* Inject packet into qdisc */ + + /* If lock -- protects updating of if_list */ +-#define if_lock(t) spin_lock(&(t->if_lock)); +-#define if_unlock(t) spin_unlock(&(t->if_lock)); ++#define if_lock(t) mutex_lock(&(t->if_lock)); ++#define if_unlock(t) mutex_unlock(&(t->if_lock)); + + /* Used to help with determining the pkts on receive */ + #define PKTGEN_MAGIC 0xbe9be955 +@@ -423,7 +423,7 @@ struct pktgen_net { + }; + + struct pktgen_thread { +- spinlock_t if_lock; /* for list of devices */ ++ struct mutex if_lock; /* for list of devices */ + struct list_head if_list; /* All device here */ + struct list_head th_list; + struct task_struct *tsk; +@@ -2010,11 +2010,13 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d + { + struct pktgen_thread *t; + ++ mutex_lock(&pktgen_thread_lock); ++ + list_for_each_entry(t, &pn->pktgen_threads, th_list) { + struct pktgen_dev *pkt_dev; + +- rcu_read_lock(); +- list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { ++ if_lock(t); ++ list_for_each_entry(pkt_dev, &t->if_list, list) { + if (pkt_dev->odev != dev) + continue; + +@@ -2029,8 +2031,9 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d + dev->name); + break; + } +- rcu_read_unlock(); ++ if_unlock(t); + } ++ mutex_unlock(&pktgen_thread_lock); + } + + static int pktgen_device_event(struct notifier_block *unused, +@@ -2286,7 +2289,7 @@ out: + + static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) + { +- pkt_dev->pkt_overhead = LL_RESERVED_SPACE(pkt_dev->odev); ++ pkt_dev->pkt_overhead = 0; + pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32); + pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev); + pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev); +@@ -2777,13 +2780,13 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, + } + + static struct sk_buff *pktgen_alloc_skb(struct net_device *dev, +- struct pktgen_dev *pkt_dev, +- unsigned int extralen) ++ struct pktgen_dev *pkt_dev) + { ++ unsigned int extralen = LL_RESERVED_SPACE(dev); + struct sk_buff *skb = NULL; +- unsigned int size = pkt_dev->cur_pkt_size + 64 + extralen + +- pkt_dev->pkt_overhead; ++ unsigned int size; + ++ size = pkt_dev->cur_pkt_size + 64 + extralen + pkt_dev->pkt_overhead; + if (pkt_dev->flags & F_NODE) { + int node = pkt_dev->node >= 0 ? pkt_dev->node : numa_node_id(); + +@@ -2796,8 +2799,9 @@ static struct sk_buff *pktgen_alloc_skb(struct net_device *dev, + skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT); + } + ++ /* the caller pre-fetches from skb->data and reserves for the mac hdr */ + if (likely(skb)) +- skb_reserve(skb, LL_RESERVED_SPACE(dev)); ++ skb_reserve(skb, extralen - 16); + + return skb; + } +@@ -2830,16 +2834,14 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, + mod_cur_headers(pkt_dev); + queue_map = pkt_dev->cur_queue_map; + +- datalen = (odev->hard_header_len + 16) & ~0xf; +- +- skb = pktgen_alloc_skb(odev, pkt_dev, datalen); ++ skb = pktgen_alloc_skb(odev, pkt_dev); + if (!skb) { + sprintf(pkt_dev->result, "No memory"); + return NULL; + } + + prefetchw(skb->data); +- skb_reserve(skb, datalen); ++ skb_reserve(skb, 16); + + /* Reserve for ethernet and IP header */ + eth = (__u8 *) skb_push(skb, 14); +@@ -2959,7 +2961,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + mod_cur_headers(pkt_dev); + queue_map = pkt_dev->cur_queue_map; + +- skb = pktgen_alloc_skb(odev, pkt_dev, 16); ++ skb = pktgen_alloc_skb(odev, pkt_dev); + if (!skb) { + sprintf(pkt_dev->result, "No memory"); + return NULL; +@@ -3763,7 +3765,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn) + return -ENOMEM; + } + +- spin_lock_init(&t->if_lock); ++ mutex_init(&t->if_lock); + t->cpu = cpu; + + INIT_LIST_HEAD(&t->if_list); +diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c +index 66dff5e3d772..02acfff36028 100644 +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -439,7 +439,7 @@ struct sk_buff **eth_gro_receive(struct sk_buff **head, + + skb_gro_pull(skb, sizeof(*eh)); + skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); +- pp = ptype->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 55513e654d79..eebbc0f2baa8 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1388,7 +1388,7 @@ struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb) + skb_gro_pull(skb, sizeof(*iph)); + skb_set_transport_header(skb, skb_gro_offset(skb)); + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c +index 321d57f825ce..5351b61ab8d3 100644 +--- a/net/ipv4/fou.c ++++ b/net/ipv4/fou.c +@@ -249,7 +249,7 @@ static struct sk_buff **fou_gro_receive(struct sock *sk, + if (!ops || !ops->callbacks.gro_receive) + goto out_unlock; + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +@@ -441,7 +441,7 @@ next_proto: + if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) + goto out_unlock; + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + flush = 0; + + out_unlock: +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index ecd1e09dbbf1..6871f59cd0c0 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -227,7 +227,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, + /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/ + skb_gro_postpull_rcsum(skb, greh, grehlen); + +- pp = ptype->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + flush = 0; + + out_unlock: +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 71a52f4d4cff..11ef96e2147a 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -98,7 +98,7 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) + } + + static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, +- int offset) ++ int tlen, int offset) + { + __wsum csum = skb->csum; + +@@ -106,8 +106,9 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, + return; + + if (offset != 0) +- csum = csum_sub(csum, csum_partial(skb_transport_header(skb), +- offset, 0)); ++ csum = csum_sub(csum, ++ csum_partial(skb_transport_header(skb) + tlen, ++ offset, 0)); + + put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); + } +@@ -153,7 +154,7 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) + } + + void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, +- int offset) ++ int tlen, int offset) + { + struct inet_sock *inet = inet_sk(skb->sk); + unsigned int flags = inet->cmsg_flags; +@@ -216,7 +217,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, + } + + if (flags & IP_CMSG_CHECKSUM) +- ip_cmsg_recv_checksum(msg, skb, offset); ++ ip_cmsg_recv_checksum(msg, skb, tlen, offset); + } + EXPORT_SYMBOL(ip_cmsg_recv_offset); + +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index 1cb67de106fe..80bc36b25de2 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -96,11 +96,11 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low + container_of(table->data, struct net, ipv4.ping_group_range.range); + unsigned int seq; + do { +- seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); ++ seq = read_seqbegin(&net->ipv4.ping_group_range.lock); + + *low = data[0]; + *high = data[1]; +- } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq)); ++ } while (read_seqretry(&net->ipv4.ping_group_range.lock, seq)); + } + + /* Update system visible IP port range */ +@@ -109,10 +109,10 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig + kgid_t *data = table->data; + struct net *net = + container_of(table->data, struct net, ipv4.ping_group_range.range); +- write_seqlock(&net->ipv4.ip_local_ports.lock); ++ write_seqlock(&net->ipv4.ping_group_range.lock); + data[0] = low; + data[1] = high; +- write_sequnlock(&net->ipv4.ip_local_ports.lock); ++ write_sequnlock(&net->ipv4.ping_group_range.lock); + } + + /* Validate changes from /proc interface. */ +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 5fdcb8d108d4..c0d71e7d663e 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1327,7 +1327,7 @@ try_again: + *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) +- ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr) + off); ++ ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr), off); + + err = copied; + if (flags & MSG_TRUNC) +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index 81f253b6ff36..6de9f977356e 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -293,7 +293,7 @@ unflush: + + skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ + skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); +- pp = udp_sk(sk)->gro_receive(sk, head, skb); ++ pp = call_gro_receive_sk(udp_sk(sk)->gro_receive, sk, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 2f1f5d439788..f5432d65e6bf 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2995,7 +2995,7 @@ static void init_loopback(struct net_device *dev) + * lo device down, release this obsolete dst and + * reallocate a new router for ifa. + */ +- if (sp_ifa->rt->dst.obsolete > 0) { ++ if (!atomic_read(&sp_ifa->rt->rt6i_ref)) { + ip6_rt_put(sp_ifa->rt); + sp_ifa->rt = NULL; + } else { +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index 22e90e56b5a9..a09418bda1f8 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -243,7 +243,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, + + skb_gro_postpull_rcsum(skb, iph, nlen); + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 888543debe4e..41489f39c456 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -155,6 +155,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_ + hash = HASH(&any, local); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(local, &t->parms.laddr) && ++ ipv6_addr_any(&t->parms.raddr) && + (t->dev->flags & IFF_UP)) + return t; + } +@@ -162,6 +163,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_ + hash = HASH(remote, &any); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(remote, &t->parms.raddr) && ++ ipv6_addr_any(&t->parms.laddr) && + (t->dev->flags & IFF_UP)) + return t; + } +@@ -1132,6 +1134,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, + if (err) + return err; + ++ skb->protocol = htons(ETH_P_IPV6); + skb_push(skb, sizeof(struct ipv6hdr)); + skb_reset_network_header(skb); + ipv6h = ipv6_hdr(skb); +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 269218aacbea..23153ac6c9b9 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -656,7 +656,8 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, + struct net_device *dev = rt->dst.dev; + + if (dev && !netif_carrier_ok(dev) && +- idev->cnf.ignore_routes_with_linkdown) ++ idev->cnf.ignore_routes_with_linkdown && ++ !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE)) + goto out; + + if (rt6_check_expired(rt)) +@@ -1050,6 +1051,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, + int strict = 0; + + strict |= flags & RT6_LOOKUP_F_IFACE; ++ strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE; + if (net->ipv6.devconf_all->forwarding == 0) + strict |= RT6_LOOKUP_F_REACHABLE; + +@@ -1783,7 +1785,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net, + }; + struct fib6_table *table; + struct rt6_info *rt; +- int flags = RT6_LOOKUP_F_IFACE; ++ int flags = RT6_LOOKUP_F_IFACE | RT6_LOOKUP_F_IGNORE_LINKSTATE; + + table = fib6_get_table(net, cfg->fc_table); + if (!table) +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 94f4f89d73e7..fc67822c42e0 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1193,6 +1193,16 @@ out: + return NULL; + } + ++static void tcp_v6_restore_cb(struct sk_buff *skb) ++{ ++ /* We need to move header back to the beginning if xfrm6_policy_check() ++ * and tcp_v6_fill_cb() are going to be called again. ++ * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there. ++ */ ++ memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, ++ sizeof(struct inet6_skb_parm)); ++} ++ + /* The socket must have it's spinlock held when we get + * here, unless it is a TCP_LISTEN socket. + * +@@ -1322,6 +1332,7 @@ ipv6_pktoptions: + np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb)); + if (ipv6_opt_accepted(sk, opt_skb, &TCP_SKB_CB(opt_skb)->header.h6)) { + skb_set_owner_r(opt_skb, sk); ++ tcp_v6_restore_cb(opt_skb); + opt_skb = xchg(&np->pktoptions, opt_skb); + } else { + __kfree_skb(opt_skb); +@@ -1355,15 +1366,6 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, + TCP_SKB_CB(skb)->sacked = 0; + } + +-static void tcp_v6_restore_cb(struct sk_buff *skb) +-{ +- /* We need to move header back to the beginning if xfrm6_policy_check() +- * and tcp_v6_fill_cb() are going to be called again. +- */ +- memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, +- sizeof(struct inet6_skb_parm)); +-} +- + static int tcp_v6_rcv(struct sk_buff *skb) + { + const struct tcphdr *th; +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 19ac3a1c308d..c2a8656c22eb 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -427,7 +427,8 @@ try_again: + + if (is_udp4) { + if (inet->cmsg_flags) +- ip_cmsg_recv(msg, skb); ++ ip_cmsg_recv_offset(msg, skb, ++ sizeof(struct udphdr), off); + } else { + if (np->rxopt.all) + ip6_datagram_recv_specific_ctl(sk, msg, skb); +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 627f898c05b9..62bea4591054 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1832,7 +1832,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + /* Record the max length of recvmsg() calls for future allocations */ + nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len); + nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len, +- 16384); ++ SKB_WITH_OVERHEAD(32768)); + + copied = data_skb->len; + if (len < copied) { +@@ -2083,8 +2083,9 @@ static int netlink_dump(struct sock *sk) + + if (alloc_min_size < nlk->max_recvmsg_len) { + alloc_size = nlk->max_recvmsg_len; +- skb = alloc_skb(alloc_size, GFP_KERNEL | +- __GFP_NOWARN | __GFP_NORETRY); ++ skb = alloc_skb(alloc_size, ++ (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) | ++ __GFP_NOWARN | __GFP_NORETRY); + } + if (!skb) { + alloc_size = alloc_min_size; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 33a4697d5539..d2238b204691 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -250,7 +250,7 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); + static int packet_direct_xmit(struct sk_buff *skb) + { + struct net_device *dev = skb->dev; +- netdev_features_t features; ++ struct sk_buff *orig_skb = skb; + struct netdev_queue *txq; + int ret = NETDEV_TX_BUSY; + +@@ -258,9 +258,8 @@ static int packet_direct_xmit(struct sk_buff *skb) + !netif_carrier_ok(dev))) + goto drop; + +- features = netif_skb_features(skb); +- if (skb_needs_linearize(skb, features) && +- __skb_linearize(skb)) ++ skb = validate_xmit_skb_list(skb, dev); ++ if (skb != orig_skb) + goto drop; + + txq = skb_get_tx_queue(dev, skb); +@@ -280,7 +279,7 @@ static int packet_direct_xmit(struct sk_buff *skb) + return ret; + drop: + atomic_long_inc(&dev->tx_dropped); +- kfree_skb(skb); ++ kfree_skb_list(skb); + return NET_XMIT_DROP; + } + +@@ -3952,6 +3951,7 @@ static int packet_notifier(struct notifier_block *this, + } + if (msg == NETDEV_UNREGISTER) { + packet_cached_dev_reset(po); ++ fanout_release(sk); + po->ifindex = -1; + if (po->prot_hook.dev) + dev_put(po->prot_hook.dev); +diff --git a/net/sched/act_api.c b/net/sched/act_api.c +index d09d0687594b..027ddf412c40 100644 +--- a/net/sched/act_api.c ++++ b/net/sched/act_api.c +@@ -341,22 +341,25 @@ int tcf_register_action(struct tc_action_ops *act, + if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup) + return -EINVAL; + ++ /* We have to register pernet ops before making the action ops visible, ++ * otherwise tcf_action_init_1() could get a partially initialized ++ * netns. ++ */ ++ ret = register_pernet_subsys(ops); ++ if (ret) ++ return ret; ++ + write_lock(&act_mod_lock); + list_for_each_entry(a, &act_base, head) { + if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) { + write_unlock(&act_mod_lock); ++ unregister_pernet_subsys(ops); + return -EEXIST; + } + } + list_add_tail(&act->head, &act_base); + write_unlock(&act_mod_lock); + +- ret = register_pernet_subsys(ops); +- if (ret) { +- tcf_unregister_action(act, ops); +- return ret; +- } +- + return 0; + } + EXPORT_SYMBOL(tcf_register_action); +@@ -367,8 +370,6 @@ int tcf_unregister_action(struct tc_action_ops *act, + struct tc_action_ops *a; + int err = -ENOENT; + +- unregister_pernet_subsys(ops); +- + write_lock(&act_mod_lock); + list_for_each_entry(a, &act_base, head) { + if (a == act) { +@@ -378,6 +379,8 @@ int tcf_unregister_action(struct tc_action_ops *act, + } + } + write_unlock(&act_mod_lock); ++ if (!err) ++ unregister_pernet_subsys(ops); + return err; + } + EXPORT_SYMBOL(tcf_unregister_action); +diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c +index 691409de3e1a..4ffc6c13a566 100644 +--- a/net/sched/act_vlan.c ++++ b/net/sched/act_vlan.c +@@ -36,6 +36,12 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, + bstats_update(&v->tcf_bstats, skb); + action = v->tcf_action; + ++ /* Ensure 'data' points at mac_header prior calling vlan manipulating ++ * functions. ++ */ ++ if (skb_at_tc_ingress(skb)) ++ skb_push_rcsum(skb, skb->mac_len); ++ + switch (v->tcfv_action) { + case TCA_VLAN_ACT_POP: + err = skb_vlan_pop(skb); +@@ -57,6 +63,9 @@ drop: + action = TC_ACT_SHOT; + v->tcf_qstats.drops++; + unlock: ++ if (skb_at_tc_ingress(skb)) ++ skb_pull_rcsum(skb, skb->mac_len); ++ + spin_unlock(&v->tcf_lock); + return action; + } +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index a7c5645373af..74bed5e9bb89 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -344,7 +344,8 @@ replay: + if (err == 0) { + struct tcf_proto *next = rtnl_dereference(tp->next); + +- tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); ++ tfilter_notify(net, skb, n, tp, ++ t->tcm_handle, RTM_DELTFILTER); + if (tcf_destroy(tp, false)) + RCU_INIT_POINTER(*back, next); + } +diff --git a/net/sctp/output.c b/net/sctp/output.c +index 31b7bc35895d..81929907a365 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -417,6 +417,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) + __u8 has_data = 0; + int gso = 0; + int pktcount = 0; ++ int auth_len = 0; + struct dst_entry *dst; + unsigned char *auth = NULL; /* pointer to auth in skb data */ + +@@ -505,7 +506,12 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) + list_for_each_entry(chunk, &packet->chunk_list, list) { + int padded = WORD_ROUND(chunk->skb->len); + +- if (pkt_size + padded > tp->pathmtu) ++ if (chunk == packet->auth) ++ auth_len = padded; ++ else if (auth_len + padded + packet->overhead > ++ tp->pathmtu) ++ goto nomem; ++ else if (pkt_size + padded > tp->pathmtu) + break; + pkt_size += padded; + } +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index d88bb2b0b699..920469e7b0ef 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -3422,6 +3422,12 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, + return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, + commands); + ++ /* Report violation if chunk len overflows */ ++ ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); ++ if (ch_end > skb_tail_pointer(skb)) ++ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, ++ commands); ++ + /* Now that we know we at least have a chunk header, + * do things that are type appropriate. + */ +@@ -3453,12 +3459,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, + } + } + +- /* Report violation if chunk len overflows */ +- ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); +- if (ch_end > skb_tail_pointer(skb)) +- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, +- commands); +- + ch = (sctp_chunkhdr_t *) ch_end; + } while (ch_end < skb_tail_pointer(skb)); + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 8ed2d99bde6d..baccbf3c1c60 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4683,7 +4683,7 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, + static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, + int __user *optlen) + { +- if (len <= 0) ++ if (len == 0) + return -EINVAL; + if (len > sizeof(struct sctp_event_subscribe)) + len = sizeof(struct sctp_event_subscribe); +@@ -6426,6 +6426,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, + if (get_user(len, optlen)) + return -EFAULT; + ++ if (len < 0) ++ return -EINVAL; ++ + lock_sock(sk); + + switch (optname) { +diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c +index a5fc9dd24aa9..a56c5e6f4498 100644 +--- a/net/switchdev/switchdev.c ++++ b/net/switchdev/switchdev.c +@@ -774,6 +774,9 @@ int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, + u32 mask = BR_LEARNING | BR_LEARNING_SYNC | BR_FLOOD; + int err; + ++ if (!netif_is_bridge_port(dev)) ++ return -EOPNOTSUPP; ++ + err = switchdev_port_attr_get(dev, &attr); + if (err && err != -EOPNOTSUPP) + return err; +@@ -929,6 +932,9 @@ int switchdev_port_bridge_setlink(struct net_device *dev, + struct nlattr *afspec; + int err = 0; + ++ if (!netif_is_bridge_port(dev)) ++ return -EOPNOTSUPP; ++ + protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), + IFLA_PROTINFO); + if (protinfo) { +@@ -962,6 +968,9 @@ int switchdev_port_bridge_dellink(struct net_device *dev, + { + struct nlattr *afspec; + ++ if (!netif_is_bridge_port(dev)) ++ return -EOPNOTSUPP; ++ + afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), + IFLA_AF_SPEC); + if (afspec)