--- /dev/null
+From 79fb330c51db3b91f5e4cfbd4a305e4a481785a2 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 28 May 2012 22:31:41 +0000
+Subject: asix: allow full size 8021Q frames to be received
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 9dae31009b1a00d926c6fe032d5a88099620adc3 ]
+
+asix driver drops 8021Q full size frames because it doesn't take into
+account VLAN header size.
+
+Tested on AX88772 adapter.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+CC: Allan Chou <allan@asix.com.tw>
+CC: Trond Wuellner <trond@chromium.org>
+CC: Grant Grundler <grundler@chromium.org>
+CC: Paul Stewart <pstew@chromium.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/asix.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/usb/asix.c
++++ b/drivers/net/usb/asix.c
+@@ -35,6 +35,7 @@
+ #include <linux/crc32.h>
+ #include <linux/usb/usbnet.h>
+ #include <linux/slab.h>
++#include <linux/if_vlan.h>
+
+ #define DRIVER_VERSION "22-Dec-2011"
+ #define DRIVER_NAME "asix"
+@@ -321,7 +322,7 @@ static int asix_rx_fixup(struct usbnet *
+ return 0;
+ }
+
+- if ((size > dev->net->mtu + ETH_HLEN) ||
++ if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) ||
+ (size + offset > skb->len)) {
+ netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
+ size);
--- /dev/null
+From cbb5c7c2b1bd52c8929e78b2b0b532e03e6c4e5d Mon Sep 17 00:00:00 2001
+From: Yanmin Zhang <yanmin_zhang@linux.intel.com>
+Date: Wed, 23 May 2012 15:39:45 +0000
+Subject: ipv4: fix the rcu race between free_fib_info and ip_route_output_slow
+
+
+From: Yanmin Zhang <yanmin_zhang@linux.intel.com>
+
+[ Upstream commit e49cc0da7283088c5e03d475ffe2fdcb24a6d5b1 ]
+
+We hit a kernel OOPS.
+
+<3>[23898.789643] BUG: sleeping function called from invalid context at
+/data/buildbot/workdir/ics/hardware/intel/linux-2.6/arch/x86/mm/fault.c:1103
+<3>[23898.862215] in_atomic(): 0, irqs_disabled(): 0, pid: 10526, name:
+Thread-6683
+<4>[23898.967805] HSU serial 0000:00:05.1: 0000:00:05.2:HSU serial prevented me
+to suspend...
+<4>[23899.258526] Pid: 10526, comm: Thread-6683 Tainted: G W
+3.0.8-137685-ge7742f9 #1
+<4>[23899.357404] HSU serial 0000:00:05.1: 0000:00:05.2:HSU serial prevented me
+to suspend...
+<4>[23899.904225] Call Trace:
+<4>[23899.989209] [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.000416] [<c1238c2a>] __might_sleep+0x10a/0x110
+<4>[23900.007357] [<c1228021>] do_page_fault+0xd1/0x3c0
+<4>[23900.013764] [<c18e9ba9>] ? restore_all+0xf/0xf
+<4>[23900.024024] [<c17c007b>] ? napi_complete+0x8b/0x690
+<4>[23900.029297] [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.123739] [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.128955] [<c18ea0c3>] error_code+0x5f/0x64
+<4>[23900.133466] [<c1227f50>] ? pgtable_bad+0x130/0x130
+<4>[23900.138450] [<c17f6298>] ? __ip_route_output_key+0x698/0x7c0
+<4>[23900.144312] [<c17f5f8d>] ? __ip_route_output_key+0x38d/0x7c0
+<4>[23900.150730] [<c17f63df>] ip_route_output_flow+0x1f/0x60
+<4>[23900.156261] [<c181de58>] ip4_datagram_connect+0x188/0x2b0
+<4>[23900.161960] [<c18e981f>] ? _raw_spin_unlock_bh+0x1f/0x30
+<4>[23900.167834] [<c18298d6>] inet_dgram_connect+0x36/0x80
+<4>[23900.173224] [<c14f9e88>] ? _copy_from_user+0x48/0x140
+<4>[23900.178817] [<c17ab9da>] sys_connect+0x9a/0xd0
+<4>[23900.183538] [<c132e93c>] ? alloc_file+0xdc/0x240
+<4>[23900.189111] [<c123925d>] ? sub_preempt_count+0x3d/0x50
+
+Function free_fib_info resets nexthop_nh->nh_dev to NULL before releasing
+fi. Other cpu might be accessing fi. Fixing it by delaying the releasing.
+
+With the patch, we ran MTBF testing on Android mobile for 12 hours
+and didn't trigger the issue.
+
+Thank Eric for very detailed review/checking the issue.
+
+Signed-off-by: Yanmin Zhang <yanmin_zhang@linux.intel.com>
+Signed-off-by: Kun Jiang <kunx.jiang@intel.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/fib_semantics.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -145,6 +145,12 @@ static void free_fib_info_rcu(struct rcu
+ {
+ struct fib_info *fi = container_of(head, struct fib_info, rcu);
+
++ change_nexthops(fi) {
++ if (nexthop_nh->nh_dev)
++ dev_put(nexthop_nh->nh_dev);
++ } endfor_nexthops(fi);
++
++ release_net(fi->fib_net);
+ if (fi->fib_metrics != (u32 *) dst_default_metrics)
+ kfree(fi->fib_metrics);
+ kfree(fi);
+@@ -156,13 +162,7 @@ void free_fib_info(struct fib_info *fi)
+ pr_warn("Freeing alive fib_info %p\n", fi);
+ return;
+ }
+- change_nexthops(fi) {
+- if (nexthop_nh->nh_dev)
+- dev_put(nexthop_nh->nh_dev);
+- nexthop_nh->nh_dev = NULL;
+- } endfor_nexthops(fi);
+ fib_info_cnt--;
+- release_net(fi->fib_net);
+ call_rcu(&fi->rcu, free_fib_info_rcu);
+ }
+
--- /dev/null
+From f5d52863e05bbd77c59a7c0736a5d7f7bf3ff24c Mon Sep 17 00:00:00 2001
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Sat, 26 May 2012 01:30:53 +0000
+Subject: ipv6: fix incorrect ipsec fragment
+
+
+From: Gao feng <gaofeng@cn.fujitsu.com>
+
+[ Upstream commit 0c1833797a5a6ec23ea9261d979aa18078720b74 ]
+
+Since commit ad0081e43a
+"ipv6: Fragment locally generated tunnel-mode IPSec6 packets as needed"
+the fragment of packets is incorrect.
+because tunnel mode needs IPsec headers and trailer for all fragments,
+while on transport mode it is sufficient to add the headers to the
+first fragment and the trailer to the last.
+
+so modify mtu and maxfraglen base on ipsec mode and if fragment is first
+or last.
+
+with my test,it work well(every fragment's size is the mtu)
+and does not trigger slow fragment path.
+
+Changes from v1:
+ though optimization, mtu_prev and maxfraglen_prev can be delete.
+ replace xfrm mode codes with dst_entry's new frag DST_XFRM_TUNNEL.
+ add fuction ip6_append_data_mtu to make codes clearer.
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/dst.h | 1
+ net/ipv6/ip6_output.c | 68 ++++++++++++++++++++++++++++++++++++-------------
+ net/xfrm/xfrm_policy.c | 3 ++
+ 3 files changed, 54 insertions(+), 18 deletions(-)
+
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -60,6 +60,7 @@ struct dst_entry {
+ #define DST_NOCOUNT 0x0020
+ #define DST_NOPEER 0x0040
+ #define DST_FAKE_RTABLE 0x0080
++#define DST_XFRM_TUNNEL 0x0100
+
+ short error;
+ short obsolete;
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1181,6 +1181,29 @@ static inline struct ipv6_rt_hdr *ip6_rt
+ return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
+ }
+
++static void ip6_append_data_mtu(int *mtu,
++ int *maxfraglen,
++ unsigned int fragheaderlen,
++ struct sk_buff *skb,
++ struct rt6_info *rt)
++{
++ if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
++ if (skb == NULL) {
++ /* first fragment, reserve header_len */
++ *mtu = *mtu - rt->dst.header_len;
++
++ } else {
++ /*
++ * this fragment is not first, the headers
++ * space is regarded as data space.
++ */
++ *mtu = dst_mtu(rt->dst.path);
++ }
++ *maxfraglen = ((*mtu - fragheaderlen) & ~7)
++ + fragheaderlen - sizeof(struct frag_hdr);
++ }
++}
++
+ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ int offset, int len, int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+@@ -1190,7 +1213,7 @@ int ip6_append_data(struct sock *sk, int
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct inet_cork *cork;
+- struct sk_buff *skb;
++ struct sk_buff *skb, *skb_prev = NULL;
+ unsigned int maxfraglen, fragheaderlen;
+ int exthdrlen;
+ int dst_exthdrlen;
+@@ -1248,8 +1271,12 @@ int ip6_append_data(struct sock *sk, int
+ inet->cork.fl.u.ip6 = *fl6;
+ np->cork.hop_limit = hlimit;
+ np->cork.tclass = tclass;
+- mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
+- rt->dst.dev->mtu : dst_mtu(&rt->dst);
++ if (rt->dst.flags & DST_XFRM_TUNNEL)
++ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
++ rt->dst.dev->mtu : dst_mtu(&rt->dst);
++ else
++ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
++ rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+ if (np->frag_size < mtu) {
+ if (np->frag_size)
+ mtu = np->frag_size;
+@@ -1345,25 +1372,27 @@ int ip6_append_data(struct sock *sk, int
+ unsigned int fraglen;
+ unsigned int fraggap;
+ unsigned int alloclen;
+- struct sk_buff *skb_prev;
+ alloc_new_skb:
+- skb_prev = skb;
+-
+ /* There's no room in the current skb */
+- if (skb_prev)
+- fraggap = skb_prev->len - maxfraglen;
++ if (skb)
++ fraggap = skb->len - maxfraglen;
+ else
+ fraggap = 0;
++ /* update mtu and maxfraglen if necessary */
++ if (skb == NULL || skb_prev == NULL)
++ ip6_append_data_mtu(&mtu, &maxfraglen,
++ fragheaderlen, skb, rt);
++
++ skb_prev = skb;
+
+ /*
+ * If remaining data exceeds the mtu,
+ * we know we need more fragment(s).
+ */
+ datalen = length + fraggap;
+- if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
+- datalen = maxfraglen - fragheaderlen;
+
+- fraglen = datalen + fragheaderlen;
++ if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
++ datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len;
+ if ((flags & MSG_MORE) &&
+ !(rt->dst.dev->features&NETIF_F_SG))
+ alloclen = mtu;
+@@ -1372,13 +1401,16 @@ alloc_new_skb:
+
+ alloclen += dst_exthdrlen;
+
+- /*
+- * The last fragment gets additional space at tail.
+- * Note: we overallocate on fragments with MSG_MODE
+- * because we have no idea if we're the last one.
+- */
+- if (datalen == length + fraggap)
+- alloclen += rt->dst.trailer_len;
++ if (datalen != length + fraggap) {
++ /*
++ * this is not the last fragment, the trailer
++ * space is regarded as data space.
++ */
++ datalen += rt->dst.trailer_len;
++ }
++
++ alloclen += rt->dst.trailer_len;
++ fraglen = datalen + fragheaderlen;
+
+ /*
+ * We just reserve space for fragment header.
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -1919,6 +1919,9 @@ no_transform:
+ }
+ ok:
+ xfrm_pols_put(pols, drop_pols);
++ if (dst && dst->xfrm &&
++ dst->xfrm->props.mode == XFRM_MODE_TUNNEL)
++ dst->flags |= DST_XFRM_TUNNEL;
+ return dst;
+
+ nopol:
--- /dev/null
+From 2f456e48e2ebd7455a5deb6cad8cc7da917dc028 Mon Sep 17 00:00:00 2001
+From: James Chapman <jchapman@katalix.com>
+Date: Tue, 29 May 2012 23:13:23 +0000
+Subject: l2tp: fix oops in L2TP IP sockets for connect() AF_UNSPEC case
+
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit c51ce49735c183ef2592db70f918ee698716276b ]
+
+An application may call connect() to disconnect a socket using an
+address with family AF_UNSPEC. The L2TP IP sockets were not handling
+this case when the socket is not bound and an attempt to connect()
+using AF_UNSPEC in such cases would result in an oops. This patch
+addresses the problem by protecting the sk_prot->disconnect() call
+against trying to unhash the socket before it is bound.
+
+The patch also adds more checks that the sockaddr supplied to bind()
+and connect() calls is valid.
+
+ RIP: 0010:[<ffffffff82e133b0>] [<ffffffff82e133b0>] inet_unhash+0x50/0xd0
+ RSP: 0018:ffff88001989be28 EFLAGS: 00010293
+ Stack:
+ ffff8800407a8000 0000000000000000 ffff88001989be78 ffffffff82e3a249
+ ffffffff82e3a050 ffff88001989bec8 ffff88001989be88 ffff8800407a8000
+ 0000000000000010 ffff88001989bec8 ffff88001989bea8 ffffffff82e42639
+ Call Trace:
+ [<ffffffff82e3a249>] udp_disconnect+0x1f9/0x290
+ [<ffffffff82e42639>] inet_dgram_connect+0x29/0x80
+ [<ffffffff82d012fc>] sys_connect+0x9c/0x100
+
+Reported-by: Sasha Levin <levinsasha928@gmail.com>
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_ip.c | 30 ++++++++++++++++++++++++------
+ 1 file changed, 24 insertions(+), 6 deletions(-)
+
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -251,9 +251,16 @@ static int l2tp_ip_bind(struct sock *sk,
+ {
+ struct inet_sock *inet = inet_sk(sk);
+ struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *) uaddr;
+- int ret = -EINVAL;
++ int ret;
+ int chk_addr_ret;
+
++ if (!sock_flag(sk, SOCK_ZAPPED))
++ return -EINVAL;
++ if (addr_len < sizeof(struct sockaddr_l2tpip))
++ return -EINVAL;
++ if (addr->l2tp_family != AF_INET)
++ return -EINVAL;
++
+ ret = -EADDRINUSE;
+ read_lock_bh(&l2tp_ip_lock);
+ if (__l2tp_ip_bind_lookup(&init_net, addr->l2tp_addr.s_addr, sk->sk_bound_dev_if, addr->l2tp_conn_id))
+@@ -284,6 +291,8 @@ static int l2tp_ip_bind(struct sock *sk,
+ sk_del_node_init(sk);
+ write_unlock_bh(&l2tp_ip_lock);
+ ret = 0;
++ sock_reset_flag(sk, SOCK_ZAPPED);
++
+ out:
+ release_sock(sk);
+
+@@ -304,13 +313,14 @@ static int l2tp_ip_connect(struct sock *
+ __be32 saddr;
+ int oif, rc;
+
+- rc = -EINVAL;
++ if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
++ return -EINVAL;
++
+ if (addr_len < sizeof(*lsa))
+- goto out;
++ return -EINVAL;
+
+- rc = -EAFNOSUPPORT;
+ if (lsa->l2tp_family != AF_INET)
+- goto out;
++ return -EAFNOSUPPORT;
+
+ lock_sock(sk);
+
+@@ -364,6 +374,14 @@ out:
+ return rc;
+ }
+
++static int l2tp_ip_disconnect(struct sock *sk, int flags)
++{
++ if (sock_flag(sk, SOCK_ZAPPED))
++ return 0;
++
++ return udp_disconnect(sk, flags);
++}
++
+ static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer)
+ {
+@@ -599,7 +617,7 @@ static struct proto l2tp_ip_prot = {
+ .close = l2tp_ip_close,
+ .bind = l2tp_ip_bind,
+ .connect = l2tp_ip_connect,
+- .disconnect = udp_disconnect,
++ .disconnect = l2tp_ip_disconnect,
+ .ioctl = udp_ioctl,
+ .destroy = l2tp_ip_destroy_sock,
+ .setsockopt = ip_setsockopt,
drm-radeon-fix-hd6790-hd6570-backend-programming.patch
drm-ttm-fix-spinlock-imbalance.patch
drm-vmwgfx-fix-nasty-write-past-alloced-memory-area.patch
+asix-allow-full-size-8021q-frames-to-be-received.patch
+ipv4-fix-the-rcu-race-between-free_fib_info-and-ip_route_output_slow.patch
+ipv6-fix-incorrect-ipsec-fragment.patch
+l2tp-fix-oops-in-l2tp-ip-sockets-for-connect-af_unspec-case.patch
+skb-avoid-unnecessary-reallocations-in-__skb_cow.patch
+xfrm-take-net-hdr-len-into-account-for-esp-payload-size-calculation.patch
--- /dev/null
+From 64305df8b10a0ea32cbef6a880c0b8911cca6cb8 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Tue, 29 May 2012 03:35:08 +0000
+Subject: skb: avoid unnecessary reallocations in __skb_cow
+
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+[ Upstream commit 617c8c11236716dcbda877e764b7bf37c6fd8063 ]
+
+At the beginning of __skb_cow, headroom gets set to a minimum of
+NET_SKB_PAD. This causes unnecessary reallocations if the buffer was not
+cloned and the headroom is just below NET_SKB_PAD, but still more than the
+amount requested by the caller.
+This was showing up frequently in my tests on VLAN tx, where
+vlan_insert_tag calls skb_cow_head(skb, VLAN_HLEN).
+
+Locally generated packets should have enough headroom, and for forward
+paths, we already have NET_SKB_PAD bytes of headroom, so we don't need to
+add any extra space here.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/skbuff.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -1881,8 +1881,6 @@ static inline int __skb_cow(struct sk_bu
+ {
+ int delta = 0;
+
+- if (headroom < NET_SKB_PAD)
+- headroom = NET_SKB_PAD;
+ if (headroom > skb_headroom(skb))
+ delta = headroom - skb_headroom(skb);
+
--- /dev/null
+From 23e1aa6f7e9515763ea416c4aa6acb9eb138936d Mon Sep 17 00:00:00 2001
+From: Benjamin Poirier <bpoirier@suse.de>
+Date: Thu, 24 May 2012 11:32:38 +0000
+Subject: xfrm: take net hdr len into account for esp payload size calculation
+
+
+From: Benjamin Poirier <bpoirier@suse.de>
+
+[ Upstream commit 91657eafb64b4cb53ec3a2fbc4afc3497f735788 ]
+
+Corrects the function that determines the esp payload size. The calculations
+done in esp{4,6}_get_mtu() lead to overlength frames in transport mode for
+certain mtu values and suboptimal frames for others.
+
+According to what is done, mainly in esp{,6}_output() and tcp_mtu_to_mss(),
+net_header_len must be taken into account before doing the alignment
+calculation.
+
+Signed-off-by: Benjamin Poirier <bpoirier@suse.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/esp4.c | 24 +++++++++---------------
+ net/ipv6/esp6.c | 18 +++++++-----------
+ 2 files changed, 16 insertions(+), 26 deletions(-)
+
+--- a/net/ipv4/esp4.c
++++ b/net/ipv4/esp4.c
+@@ -459,28 +459,22 @@ static u32 esp4_get_mtu(struct xfrm_stat
+ struct esp_data *esp = x->data;
+ u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
+ u32 align = max_t(u32, blksize, esp->padlen);
+- u32 rem;
+-
+- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
+- rem = mtu & (align - 1);
+- mtu &= ~(align - 1);
++ unsigned int net_adj;
+
+ switch (x->props.mode) {
+- case XFRM_MODE_TUNNEL:
+- break;
+- default:
+ case XFRM_MODE_TRANSPORT:
+- /* The worst case */
+- mtu -= blksize - 4;
+- mtu += min_t(u32, blksize - 4, rem);
+- break;
+ case XFRM_MODE_BEET:
+- /* The worst case. */
+- mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem);
++ net_adj = sizeof(struct iphdr);
++ break;
++ case XFRM_MODE_TUNNEL:
++ net_adj = 0;
+ break;
++ default:
++ BUG();
+ }
+
+- return mtu - 2;
++ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
++ net_adj) & ~(align - 1)) + (net_adj - 2);
+ }
+
+ static void esp4_err(struct sk_buff *skb, u32 info)
+--- a/net/ipv6/esp6.c
++++ b/net/ipv6/esp6.c
+@@ -411,19 +411,15 @@ static u32 esp6_get_mtu(struct xfrm_stat
+ struct esp_data *esp = x->data;
+ u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
+ u32 align = max_t(u32, blksize, esp->padlen);
+- u32 rem;
++ unsigned int net_adj;
+
+- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
+- rem = mtu & (align - 1);
+- mtu &= ~(align - 1);
++ if (x->props.mode != XFRM_MODE_TUNNEL)
++ net_adj = sizeof(struct ipv6hdr);
++ else
++ net_adj = 0;
+
+- if (x->props.mode != XFRM_MODE_TUNNEL) {
+- u32 padsize = ((blksize - 1) & 7) + 1;
+- mtu -= blksize - padsize;
+- mtu += min_t(u32, blksize - padsize, rem);
+- }
+-
+- return mtu - 2;
++ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
++ net_adj) & ~(align - 1)) + (net_adj - 2);
+ }
+
+ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,