--- /dev/null
+From 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 23 Aug 2012 13:12:52 +0100
+Subject: drm/i915: Use cpu relocations if the object is in the GTT but not mappable
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 upstream.
+
+This prevents the case of unbinding the object in order to process the
+relocations through the GTT and then rebinding it only to then proceed
+to use cpu relocations as the object is now in the CPU write domain. By
+choosing to use cpu relocations up front, we can therefore avoid the
+rebind penalty.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+@@ -269,6 +269,7 @@ eb_destroy(struct eb_objects *eb)
+ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
+ {
+ return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
++ !obj->map_and_fenceable ||
+ obj->cache_level != I915_CACHE_NONE);
+ }
+
--- /dev/null
+From 13e570f1d520d1383b4d8837fb5adb1f24a31661 Mon Sep 17 00:00:00 2001
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Thu, 4 Oct 2012 20:15:49 +0000
+Subject: infiniband: pass rdma_cm module to netlink_dump_start
+
+
+From: Gao feng <gaofeng@cn.fujitsu.com>
+
+[ Upstream commit 809d5fc9bf6589276a12bd4fd611e4c7ff9940c3 ]
+
+set netlink_dump_control.module to avoid panic.
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+Cc: Roland Dreier <roland@kernel.org>
+Cc: Sean Hefty <sean.hefty@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/cma.c | 3 ++-
+ drivers/infiniband/core/netlink.c | 1 +
+ include/rdma/rdma_netlink.h | 1 +
+ 3 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -3495,7 +3495,8 @@ out:
+ }
+
+ static const struct ibnl_client_cbs cma_cb_table[] = {
+- [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats },
++ [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats,
++ .module = THIS_MODULE },
+ };
+
+ static int __init cma_init(void)
+--- a/drivers/infiniband/core/netlink.c
++++ b/drivers/infiniband/core/netlink.c
+@@ -154,6 +154,7 @@ static int ibnl_rcv_msg(struct sk_buff *
+ {
+ struct netlink_dump_control c = {
+ .dump = client->cb_table[op].dump,
++ .module = client->cb_table[op].module,
+ };
+ return netlink_dump_start(nls, skb, nlh, &c);
+ }
+--- a/include/rdma/rdma_netlink.h
++++ b/include/rdma/rdma_netlink.h
+@@ -39,6 +39,7 @@ struct rdma_cm_id_stats {
+
+ struct ibnl_client_cbs {
+ int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb);
++ struct module *module;
+ };
+
+ int ibnl_init(void);
--- /dev/null
+From b48c7e3ddd9bee91e43b7682590a64403b0fce63 Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Mon, 8 Oct 2012 11:41:19 +0000
+Subject: ipv4: Add FLOWI_FLAG_KNOWN_NH
+
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit c92b96553a80c1dbe2ebe128bbe37c8f98f148bf ]
+
+Add flag to request that output route should be
+returned with known rt_gateway, in case we want to use
+it as nexthop for neighbour resolving.
+
+ The returned route can be cached as follows:
+
+- in NH exception: because the cached routes are not shared
+ with other destinations
+- in FIB NH: when using gateway because all destinations for
+ NH share same gateway
+
+ As last option, to return rt_gateway!=0 we have to
+set DST_NOCACHE.
+
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/flow.h | 1 +
+ net/ipv4/route.c | 21 +++++++++++++++++----
+ 2 files changed, 18 insertions(+), 4 deletions(-)
+
+--- a/include/net/flow.h
++++ b/include/net/flow.h
+@@ -21,6 +21,7 @@ struct flowi_common {
+ __u8 flowic_flags;
+ #define FLOWI_FLAG_ANYSRC 0x01
+ #define FLOWI_FLAG_CAN_SLEEP 0x02
++#define FLOWI_FLAG_KNOWN_NH 0x04
+ __u32 flowic_secid;
+ };
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1762,6 +1762,7 @@ static struct rtable *__mkroute_output(c
+ struct in_device *in_dev;
+ u16 type = res->type;
+ struct rtable *rth;
++ bool do_cache;
+
+ in_dev = __in_dev_get_rcu(dev_out);
+ if (!in_dev)
+@@ -1798,24 +1799,36 @@ static struct rtable *__mkroute_output(c
+ }
+
+ fnhe = NULL;
++ do_cache = fi != NULL;
+ if (fi) {
+ struct rtable __rcu **prth;
++ struct fib_nh *nh = &FIB_RES_NH(*res);
+
+- fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr);
++ fnhe = find_exception(nh, fl4->daddr);
+ if (fnhe)
+ prth = &fnhe->fnhe_rth;
+- else
+- prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output);
++ 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 = __this_cpu_ptr(nh->nh_pcpu_rth_output);
++ }
+ rth = rcu_dereference(*prth);
+ if (rt_cache_valid(rth)) {
+ dst_hold(&rth->dst);
+ return rth;
+ }
+ }
++
++add:
+ rth = rt_dst_alloc(dev_out,
+ IN_DEV_CONF_GET(in_dev, NOPOLICY),
+ IN_DEV_CONF_GET(in_dev, NOXFRM),
+- fi);
++ do_cache);
+ if (!rth)
+ return ERR_PTR(-ENOBUFS);
+
--- /dev/null
+From 42ca21062a7faeec9140494e39d1d3f931f459e9 Mon Sep 17 00:00:00 2001
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Sun, 7 Oct 2012 22:47:25 +0000
+Subject: ipv4: Always invalidate or update the route on pmtu events
+
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit d851c12b60471188e15e5c8405b289073e8dd025 ]
+
+Some protocols, like IPsec still cache routes. So we need to invalidate
+the old route on pmtu events to avoid the reuse of stale routes.
+We also need to update the mtu and expire time of the route if we already
+use a nh exception route, otherwise we ignore newly learned pmtu values
+after the first expiration.
+
+With this patch we always invalidate or update the route on pmtu events.
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/route.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -904,22 +904,29 @@ out: kfree_skb(skb);
+ return 0;
+ }
+
+-static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
++static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
+ {
++ struct dst_entry *dst = &rt->dst;
+ struct fib_result res;
+
+ if (mtu < ip_rt_min_pmtu)
+ mtu = ip_rt_min_pmtu;
+
++ if (!rt->rt_pmtu) {
++ dst->obsolete = DST_OBSOLETE_KILL;
++ } else {
++ rt->rt_pmtu = mtu;
++ dst->expires = max(1UL, jiffies + ip_rt_mtu_expires);
++ }
++
+ rcu_read_lock();
+- if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
++ if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) {
+ struct fib_nh *nh = &FIB_RES_NH(res);
+
+ update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
+ jiffies + ip_rt_mtu_expires);
+ }
+ rcu_read_unlock();
+- return mtu;
+ }
+
+ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
+@@ -929,14 +936,7 @@ static void ip_rt_update_pmtu(struct dst
+ struct flowi4 fl4;
+
+ ip_rt_build_flow_key(&fl4, sk, skb);
+- mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);
+-
+- if (!rt->rt_pmtu) {
+- dst->obsolete = DST_OBSOLETE_KILL;
+- } else {
+- rt->rt_pmtu = mtu;
+- rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
+- }
++ __ip_rt_update_pmtu(rt, &fl4, mtu);
+ }
+
+ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
--- /dev/null
+From 770f58d7866dfb0bc61a797ae601b7e481d741d5 Mon Sep 17 00:00:00 2001
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Sun, 7 Oct 2012 22:48:18 +0000
+Subject: ipv4: Don't create nh exeption when the device mtu is smaller than the reported pmtu
+
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit 7f92d334ba19a0d8e96f8f8f092219553367d921 ]
+
+When a local tool like tracepath tries to send packets bigger than
+the device mtu, we create a nh exeption and set the pmtu to device
+mtu. The device mtu does not expire, so check if the device mtu is
+smaller than the reported pmtu and don't crerate a nh exeption in
+that case.
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/route.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -909,6 +909,9 @@ static void __ip_rt_update_pmtu(struct r
+ struct dst_entry *dst = &rt->dst;
+ struct fib_result res;
+
++ if (dst->dev->mtu < mtu)
++ return;
++
+ if (mtu < ip_rt_min_pmtu)
+ mtu = ip_rt_min_pmtu;
+
--- /dev/null
+From 26b59d48e8de1d793e3b8aefc4d2a81b59feece7 Mon Sep 17 00:00:00 2001
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Mon, 8 Oct 2012 00:56:54 +0000
+Subject: ipv4: Don't report stale pmtu values to userspace
+
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit ee9a8f7ab2edf801b8b514c310455c94acc232f6 ]
+
+We report cached pmtu values even if they are already expired.
+Change this to not report these values after they are expired
+and fix a race in the expire time calculation, as suggested by
+Eric Dumazet.
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/route.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -2187,8 +2187,18 @@ static int rt_fill_info(struct net *net,
+ nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway))
+ goto nla_put_failure;
+
++ expires = rt->dst.expires;
++ if (expires) {
++ unsigned long now = jiffies;
++
++ if (time_before(now, expires))
++ expires -= now;
++ else
++ expires = 0;
++ }
++
+ memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics));
+- if (rt->rt_pmtu)
++ if (rt->rt_pmtu && expires)
+ metrics[RTAX_MTU - 1] = rt->rt_pmtu;
+ if (rtnetlink_put_metrics(skb, metrics) < 0)
+ goto nla_put_failure;
+@@ -2198,13 +2208,6 @@ static int rt_fill_info(struct net *net,
+ goto nla_put_failure;
+
+ error = rt->dst.error;
+- expires = rt->dst.expires;
+- if (expires) {
+- if (time_before(jiffies, expires))
+- expires -= jiffies;
+- else
+- expires = 0;
+- }
+
+ if (rt_is_input_route(rt)) {
+ if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
--- /dev/null
+From 9ec66bfc332d28cf6c9d5ec16fb8e1b42412e815 Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Mon, 8 Oct 2012 11:41:16 +0000
+Subject: ipv4: fix forwarding for strict source routes
+
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit e0adef0f7456d5d3a3bfe8ea61c7dddf146b40e1 ]
+
+After the change "Adjust semantics of rt->rt_gateway"
+(commit f8126f1d51) rt_gateway can be 0 but ip_forward() compares
+it directly with nexthop. What we want here is to check if traffic
+is to directly connected nexthop and to fail if using gateway.
+
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_forward.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv4/ip_forward.c
++++ b/net/ipv4/ip_forward.c
+@@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb)
+
+ rt = skb_rtable(skb);
+
+- if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
++ if (opt->is_strictroute && rt->rt_gateway)
+ goto sr_failed;
+
+ if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
--- /dev/null
+From 9412e270cddca255cb5dc3e28d36fc8c32eaec95 Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Mon, 8 Oct 2012 11:41:15 +0000
+Subject: ipv4: fix sending of redirects
+
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit e81da0e113a1b7fc7449ae6213f65f89ccac6d06 ]
+
+After "Cache input routes in fib_info nexthops" (commit
+d2d68ba9fe) and "Elide fib_validate_source() completely when possible"
+(commit 7a9bc9b81a) we can not send ICMP redirects. It seems we
+should not cache the RTCF_DOREDIRECT flag in nh_rth_input because
+the same fib_info can be used for traffic that is not redirected,
+eg. from other input devices or from sources that are not in same subnet.
+
+ As result, we have to disable the caching of RTCF_DOREDIRECT
+flag and to force source validation for the case when forwarding
+traffic to the input device. If traffic comes from directly connected
+source we allow redirection as it was done before both changes.
+
+ Avoid setting RTCF_DOREDIRECT if IN_DEV_TX_REDIRECTS
+is disabled, this can avoid source address validation and to
+help caching the routes.
+
+ After the change "Adjust semantics of rt->rt_gateway"
+(commit f8126f1d51) we should make sure our ICMP_REDIR_HOST messages
+contain daddr instead of 0.0.0.0 when target is directly connected.
+
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/fib_frontend.c | 3 ++-
+ net/ipv4/route.c | 30 ++++++++++++++++--------------
+ 2 files changed, 18 insertions(+), 15 deletions(-)
+
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -322,7 +322,8 @@ int fib_validate_source(struct sk_buff *
+ {
+ int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
+
+- if (!r && !fib_num_tclassid_users(dev_net(dev))) {
++ if (!r && !fib_num_tclassid_users(dev_net(dev)) &&
++ (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) {
+ *itag = 0;
+ return 0;
+ }
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -802,7 +802,8 @@ void ip_rt_send_redirect(struct sk_buff
+ net = dev_net(rt->dst.dev);
+ peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1);
+ if (!peer) {
+- icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
++ icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST,
++ rt_nexthop(rt, ip_hdr(skb)->daddr));
+ return;
+ }
+
+@@ -827,7 +828,9 @@ void ip_rt_send_redirect(struct sk_buff
+ time_after(jiffies,
+ (peer->rate_last +
+ (ip_rt_redirect_load << peer->rate_tokens)))) {
+- icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
++ __be32 gw = rt_nexthop(rt, ip_hdr(skb)->daddr);
++
++ icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
+ peer->rate_last = jiffies;
+ ++peer->rate_tokens;
+ #ifdef CONFIG_IP_ROUTE_VERBOSE
+@@ -835,7 +838,7 @@ void ip_rt_send_redirect(struct sk_buff
+ peer->rate_tokens == ip_rt_redirect_number)
+ net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n",
+ &ip_hdr(skb)->saddr, inet_iif(skb),
+- &ip_hdr(skb)->daddr, &rt->rt_gateway);
++ &ip_hdr(skb)->daddr, &gw);
+ #endif
+ }
+ out_put_peer:
+@@ -1445,10 +1448,13 @@ static int __mkroute_input(struct sk_buf
+ goto cleanup;
+ }
+
+- if (out_dev == in_dev && err &&
++ do_cache = res->fi && !itag;
++ if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
+ (IN_DEV_SHARED_MEDIA(out_dev) ||
+- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
++ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) {
+ flags |= RTCF_DOREDIRECT;
++ do_cache = false;
++ }
+
+ if (skb->protocol != htons(ETH_P_IP)) {
+ /* Not IP (i.e. ARP). Do not create route, if it is
+@@ -1465,15 +1471,11 @@ static int __mkroute_input(struct sk_buf
+ }
+ }
+
+- do_cache = false;
+- if (res->fi) {
+- if (!itag) {
+- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+- if (rt_cache_valid(rth)) {
+- skb_dst_set_noref(skb, &rth->dst);
+- goto out;
+- }
+- do_cache = true;
++ if (do_cache) {
++ rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
++ if (rt_cache_valid(rth)) {
++ skb_dst_set_noref(skb, &rth->dst);
++ goto out;
+ }
+ }
+
--- /dev/null
+From 00ea0afa32f0f8568ac2d5727c43c6d00d25e517 Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Mon, 8 Oct 2012 11:41:18 +0000
+Subject: ipv4: introduce rt_uses_gateway
+
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 155e8336c373d14d87a7f91e356d85ef4b93b8f9 ]
+
+Add new flag to remember when route is via gateway.
+We will use it to allow rt_gateway to contain address of
+directly connected host for the cases when DST_NOCACHE is
+used or when the NH exception caches per-destination route
+without DST_NOCACHE flag, i.e. when routes are not used for
+other destinations. By this way we force the neighbour
+resolving to work with the routed destination but we
+can use different address in the packet, feature needed
+for IPVS-DR where original packet for virtual IP is routed
+via route to real IP.
+
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/route.h | 3 +-
+ net/ipv4/inet_connection_sock.c | 4 +--
+ net/ipv4/ip_forward.c | 2 -
+ net/ipv4/ip_output.c | 4 +--
+ net/ipv4/route.c | 48 +++++++++++++++++++++-------------------
+ net/ipv4/xfrm4_policy.c | 1
+ 6 files changed, 34 insertions(+), 28 deletions(-)
+
+--- a/include/net/route.h
++++ b/include/net/route.h
+@@ -48,7 +48,8 @@ struct rtable {
+ int rt_genid;
+ unsigned int rt_flags;
+ __u16 rt_type;
+- __u16 rt_is_input;
++ __u8 rt_is_input;
++ __u8 rt_uses_gateway;
+
+ int rt_iif;
+
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -386,7 +386,7 @@ struct dst_entry *inet_csk_route_req(str
+ rt = ip_route_output_flow(net, fl4, sk);
+ if (IS_ERR(rt))
+ goto no_route;
+- if (opt && opt->opt.is_strictroute && rt->rt_gateway)
++ if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
+ goto route_err;
+ return &rt->dst;
+
+@@ -422,7 +422,7 @@ struct dst_entry *inet_csk_route_child_s
+ rt = ip_route_output_flow(net, fl4, sk);
+ if (IS_ERR(rt))
+ goto no_route;
+- if (opt && opt->opt.is_strictroute && rt->rt_gateway)
++ if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
+ goto route_err;
+ rcu_read_unlock();
+ return &rt->dst;
+--- a/net/ipv4/ip_forward.c
++++ b/net/ipv4/ip_forward.c
+@@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb)
+
+ rt = skb_rtable(skb);
+
+- if (opt->is_strictroute && rt->rt_gateway)
++ if (opt->is_strictroute && rt->rt_uses_gateway)
+ goto sr_failed;
+
+ if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -193,7 +193,7 @@ static inline int ip_finish_output2(stru
+ }
+
+ rcu_read_lock_bh();
+- nexthop = rt->rt_gateway ? rt->rt_gateway : ip_hdr(skb)->daddr;
++ nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);
+ neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
+ if (unlikely(!neigh))
+ neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
+@@ -371,7 +371,7 @@ int ip_queue_xmit(struct sk_buff *skb, s
+ skb_dst_set_noref(skb, &rt->dst);
+
+ packet_routed:
+- if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gateway)
++ if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway)
+ goto no_route;
+
+ /* OK, we know where to send it, allocate and build IP header. */
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1129,7 +1129,7 @@ static unsigned int ipv4_mtu(const struc
+ mtu = dst->dev->mtu;
+
+ if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
+- if (rt->rt_gateway && mtu > 576)
++ if (rt->rt_uses_gateway && mtu > 576)
+ mtu = 576;
+ }
+
+@@ -1180,7 +1180,9 @@ static bool rt_bind_exception(struct rta
+ if (fnhe->fnhe_gw) {
+ rt->rt_flags |= RTCF_REDIRECTED;
+ rt->rt_gateway = fnhe->fnhe_gw;
+- }
++ rt->rt_uses_gateway = 1;
++ } else if (!rt->rt_gateway)
++ rt->rt_gateway = daddr;
+
+ orig = rcu_dereference(fnhe->fnhe_rth);
+ rcu_assign_pointer(fnhe->fnhe_rth, rt);
+@@ -1189,13 +1191,6 @@ static bool rt_bind_exception(struct rta
+
+ fnhe->fnhe_stamp = jiffies;
+ ret = true;
+- } else {
+- /* Routes we intend to cache in nexthop exception have
+- * the DST_NOCACHE bit clear. However, if we are
+- * unsuccessful at storing this route into the cache
+- * we really need to set it.
+- */
+- rt->dst.flags |= DST_NOCACHE;
+ }
+ spin_unlock_bh(&fnhe_lock);
+
+@@ -1218,15 +1213,8 @@ static bool rt_cache_route(struct fib_nh
+ if (prev == orig) {
+ if (orig)
+ rt_free(orig);
+- } else {
+- /* Routes we intend to cache in the FIB nexthop have
+- * the DST_NOCACHE bit clear. However, if we are
+- * unsuccessful at storing this route into the cache
+- * we really need to set it.
+- */
+- rt->dst.flags |= DST_NOCACHE;
++ } else
+ ret = false;
+- }
+
+ return ret;
+ }
+@@ -1287,8 +1275,10 @@ static void rt_set_nexthop(struct rtable
+ if (fi) {
+ struct fib_nh *nh = &FIB_RES_NH(*res);
+
+- if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
++ if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) {
+ rt->rt_gateway = nh->nh_gw;
++ rt->rt_uses_gateway = 1;
++ }
+ dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+ #ifdef CONFIG_IP_ROUTE_CLASSID
+ rt->dst.tclassid = nh->nh_tclassid;
+@@ -1297,8 +1287,18 @@ static void rt_set_nexthop(struct rtable
+ cached = rt_bind_exception(rt, fnhe, daddr);
+ else if (!(rt->dst.flags & DST_NOCACHE))
+ cached = rt_cache_route(nh, rt);
+- }
+- if (unlikely(!cached))
++ if (unlikely(!cached)) {
++ /* Routes we intend to cache in nexthop exception or
++ * FIB nexthop have the DST_NOCACHE bit clear.
++ * However, if we are unsuccessful at storing this
++ * route into the cache we really need to set it.
++ */
++ rt->dst.flags |= DST_NOCACHE;
++ if (!rt->rt_gateway)
++ rt->rt_gateway = daddr;
++ rt_add_uncached_list(rt);
++ }
++ } else
+ rt_add_uncached_list(rt);
+
+ #ifdef CONFIG_IP_ROUTE_CLASSID
+@@ -1366,6 +1366,7 @@ static int ip_route_input_mc(struct sk_b
+ rth->rt_iif = 0;
+ rth->rt_pmtu = 0;
+ rth->rt_gateway = 0;
++ rth->rt_uses_gateway = 0;
+ INIT_LIST_HEAD(&rth->rt_uncached);
+ if (our) {
+ rth->dst.input= ip_local_deliver;
+@@ -1435,7 +1436,6 @@ static int __mkroute_input(struct sk_buf
+ return -EINVAL;
+ }
+
+-
+ err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res),
+ in_dev->dev, in_dev, &itag);
+ if (err < 0) {
+@@ -1491,6 +1491,7 @@ static int __mkroute_input(struct sk_buf
+ rth->rt_iif = 0;
+ rth->rt_pmtu = 0;
+ rth->rt_gateway = 0;
++ rth->rt_uses_gateway = 0;
+ INIT_LIST_HEAD(&rth->rt_uncached);
+
+ rth->dst.input = ip_forward;
+@@ -1658,6 +1659,7 @@ local_input:
+ rth->rt_iif = 0;
+ rth->rt_pmtu = 0;
+ rth->rt_gateway = 0;
++ rth->rt_uses_gateway = 0;
+ INIT_LIST_HEAD(&rth->rt_uncached);
+ if (res.type == RTN_UNREACHABLE) {
+ rth->dst.input= ip_error;
+@@ -1826,6 +1828,7 @@ static struct rtable *__mkroute_output(c
+ rth->rt_iif = orig_oif ? : 0;
+ rth->rt_pmtu = 0;
+ rth->rt_gateway = 0;
++ rth->rt_uses_gateway = 0;
+ INIT_LIST_HEAD(&rth->rt_uncached);
+
+ RT_CACHE_STAT_INC(out_slow_tot);
+@@ -2104,6 +2107,7 @@ struct dst_entry *ipv4_blackhole_route(s
+ rt->rt_flags = ort->rt_flags;
+ rt->rt_type = ort->rt_type;
+ rt->rt_gateway = ort->rt_gateway;
++ rt->rt_uses_gateway = ort->rt_uses_gateway;
+
+ INIT_LIST_HEAD(&rt->rt_uncached);
+
+@@ -2182,7 +2186,7 @@ static int rt_fill_info(struct net *net,
+ if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr))
+ goto nla_put_failure;
+ }
+- if (rt->rt_gateway &&
++ if (rt->rt_uses_gateway &&
+ nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway))
+ goto nla_put_failure;
+
+--- a/net/ipv4/xfrm4_policy.c
++++ b/net/ipv4/xfrm4_policy.c
+@@ -91,6 +91,7 @@ static int xfrm4_fill_dst(struct xfrm_ds
+ RTCF_LOCAL);
+ xdst->u.rt.rt_type = rt->rt_type;
+ xdst->u.rt.rt_gateway = rt->rt_gateway;
++ xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway;
+ xdst->u.rt.rt_pmtu = rt->rt_pmtu;
+ INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
+
--- /dev/null
+From 473bd4d9b43f5b02a022d6c9473decd1ca19472a Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Mon, 8 Oct 2012 11:41:17 +0000
+Subject: ipv4: make sure nh_pcpu_rth_output is always allocated
+
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit f8a17175c63fd3e8b573719f7538816f8c96abf4 ]
+
+Avoid checking nh_pcpu_rth_output in fast path,
+abort fib_info creation on alloc_percpu failure.
+
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/fib_semantics.c | 2 ++
+ net/ipv4/route.c | 3 ---
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -840,6 +840,8 @@ struct fib_info *fib_create_info(struct
+ change_nexthops(fi) {
+ nexthop_nh->nh_parent = fi;
+ nexthop_nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *);
++ if (!nexthop_nh->nh_pcpu_rth_output)
++ goto failure;
+ } endfor_nexthops(fi)
+
+ if (cfg->fc_mx) {
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1210,8 +1210,6 @@ static bool rt_cache_route(struct fib_nh
+ if (rt_is_input_route(rt)) {
+ p = (struct rtable **)&nh->nh_rth_input;
+ } else {
+- if (!nh->nh_pcpu_rth_output)
+- goto nocache;
+ p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output);
+ }
+ orig = *p;
+@@ -1226,7 +1224,6 @@ static bool rt_cache_route(struct fib_nh
+ * unsuccessful at storing this route into the cache
+ * we really need to set it.
+ */
+-nocache:
+ rt->dst.flags |= DST_NOCACHE;
+ ret = false;
+ }
--- /dev/null
+From 7da2aac0abf5e94c82806375aec7199fc765f3aa Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 16 Oct 2012 07:37:27 +0000
+Subject: ipv6: addrconf: fix /proc/net/if_inet6
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 9f0d3c2781baa1102108e16efbe640dd74564a7c ]
+
+Commit 1d5783030a1 (ipv6/addrconf: speedup /proc/net/if_inet6 filling)
+added bugs hiding some devices from if_inet6 and breaking applications.
+
+"ip -6 addr" could still display all IPv6 addresses, while "ifconfig -a"
+couldnt.
+
+One way to reproduce the bug is by starting in a shell :
+
+unshare -n /bin/bash
+ifconfig lo up
+
+And in original net namespace, lo device disappeared from if_inet6
+
+Reported-by: Jan Hinnerk Stosch <janhinnerk.stosch@gmail.com>
+Tested-by: Jan Hinnerk Stosch <janhinnerk.stosch@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Mihai Maruseac <mihai.maruseac@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/addrconf.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -3088,14 +3088,15 @@ static struct inet6_ifaddr *if6_get_firs
+ struct hlist_node *n;
+ hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket],
+ addr_lst) {
++ if (!net_eq(dev_net(ifa->idev->dev), net))
++ continue;
+ /* sync with offset */
+ if (p < state->offset) {
+ p++;
+ continue;
+ }
+ state->offset++;
+- if (net_eq(dev_net(ifa->idev->dev), net))
+- return ifa;
++ return ifa;
+ }
+
+ /* prepare for next bucket */
+@@ -3113,18 +3114,20 @@ static struct inet6_ifaddr *if6_get_next
+ struct hlist_node *n = &ifa->addr_lst;
+
+ hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) {
++ if (!net_eq(dev_net(ifa->idev->dev), net))
++ continue;
+ state->offset++;
+- if (net_eq(dev_net(ifa->idev->dev), net))
+- return ifa;
++ return ifa;
+ }
+
+ while (++state->bucket < IN6_ADDR_HSIZE) {
+ state->offset = 0;
+ hlist_for_each_entry_rcu_bh(ifa, n,
+ &inet6_addr_lst[state->bucket], addr_lst) {
++ if (!net_eq(dev_net(ifa->idev->dev), net))
++ continue;
+ state->offset++;
+- if (net_eq(dev_net(ifa->idev->dev), net))
+- return ifa;
++ return ifa;
+ }
+ }
+
--- /dev/null
+From f16e08225fe7ae2d52b3e12cd9e6256d82de4f0b Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 5 Oct 2012 20:43:30 +0000
+Subject: ipv6: GRO should be ECN friendly
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 51ec04038c113a811b177baa85d293feff9ce995 ]
+
+IPv4 side of the problem was addressed in commit a9e050f4e7f9d
+(net: tcp: GRO should be ECN friendly)
+
+This patch does the same, but for IPv6 : A Traffic Class mismatch
+doesnt mean flows are different, but instead should force a flush
+of previous packets.
+
+This patch removes artificial packet reordering problem.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/af_inet6.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -880,22 +880,25 @@ static struct sk_buff **ipv6_gro_receive
+ nlen = skb_network_header_len(skb);
+
+ for (p = *head; p; p = p->next) {
+- struct ipv6hdr *iph2;
++ const struct ipv6hdr *iph2;
++ __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
+
+ if (!NAPI_GRO_CB(p)->same_flow)
+ continue;
+
+ iph2 = ipv6_hdr(p);
++ first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
+
+- /* All fields must match except length. */
++ /* All fields must match except length and Traffic Class. */
+ if (nlen != skb_network_header_len(p) ||
+- memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) ||
++ (first_word & htonl(0xF00FFFFF)) ||
+ memcmp(&iph->nexthdr, &iph2->nexthdr,
+ nlen - offsetof(struct ipv6hdr, nexthdr))) {
+ NAPI_GRO_CB(p)->same_flow = 0;
+ continue;
+ }
+-
++ /* flush if Traffic Class fields are different */
++ NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
+ NAPI_GRO_CB(p)->flush |= flush;
+ }
+
--- /dev/null
+From 8d6957fe79380bad40501151d2a87336cbd122a2 Mon Sep 17 00:00:00 2001
+From: Julian Anastasov <ja@ssi.bg>
+Date: Mon, 8 Oct 2012 11:41:20 +0000
+Subject: ipvs: fix ARP resolving for direct routing mode
+
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit ad4d3ef8b7eb527cca478dc08c02c10936e64115 ]
+
+After the change "Make neigh lookups directly in output packet path"
+(commit a263b30936) IPVS can not reach the real server for DR mode
+because we resolve the destination address from IP header, not from
+route neighbour. Use the new FLOWI_FLAG_KNOWN_NH flag to request
+output routes with known nexthop, so that it has preference
+on resolving.
+
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/ipvs/ip_vs_xmit.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/net/netfilter/ipvs/ip_vs_xmit.c
++++ b/net/netfilter/ipvs/ip_vs_xmit.c
+@@ -49,6 +49,7 @@ enum {
+ IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to
+ * local
+ */
++ IP_VS_RT_MODE_KNOWN_NH = 16,/* Route via remote addr */
+ };
+
+ /*
+@@ -103,6 +104,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb,
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.daddr = dest->addr.ip;
+ fl4.flowi4_tos = rtos;
++ fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
++ FLOWI_FLAG_KNOWN_NH : 0;
+ rt = ip_route_output_key(net, &fl4);
+ if (IS_ERR(rt)) {
+ spin_unlock(&dest->dst_lock);
+@@ -127,6 +130,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb,
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.daddr = daddr;
+ fl4.flowi4_tos = rtos;
++ fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
++ FLOWI_FLAG_KNOWN_NH : 0;
+ rt = ip_route_output_key(net, &fl4);
+ if (IS_ERR(rt)) {
+ IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
+@@ -1014,7 +1019,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struc
+ if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
+ RT_TOS(iph->tos),
+ IP_VS_RT_MODE_LOCAL |
+- IP_VS_RT_MODE_NON_LOCAL, NULL)))
++ IP_VS_RT_MODE_NON_LOCAL |
++ IP_VS_RT_MODE_KNOWN_NH, NULL)))
+ goto tx_error_icmp;
+ if (rt->rt_flags & RTCF_LOCAL) {
+ ip_rt_put(rt);
--- /dev/null
+From a595c1ce4c9d572cf53513570b9f1a263d7867f2 Mon Sep 17 00:00:00 2001
+From: Devin Heitmueller <dheitmueller@kernellabs.com>
+Date: Mon, 6 Aug 2012 22:47:03 -0300
+Subject: media: au0828: fix case where STREAMOFF being called on stopped stream causes BUG()
+
+From: Devin Heitmueller <dheitmueller@kernellabs.com>
+
+commit a595c1ce4c9d572cf53513570b9f1a263d7867f2 upstream.
+
+We weren't checking whether the resource was in use before calling
+res_free(), so applications which called STREAMOFF on a v4l2 device that
+wasn't already streaming would cause a BUG() to be hit (MythTV).
+
+Reported-by: Larry Finger <larry.finger@lwfinger.net>
+Reported-by: Jay Harbeston <jharbestonus@gmail.com>
+Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+
+---
+ drivers/media/video/au0828/au0828-video.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/video/au0828/au0828-video.c
++++ b/drivers/media/video/au0828/au0828-video.c
+@@ -1692,14 +1692,18 @@ static int vidioc_streamoff(struct file
+ (AUVI_INPUT(i).audio_setup)(dev, 0);
+ }
+
+- videobuf_streamoff(&fh->vb_vidq);
+- res_free(fh, AU0828_RESOURCE_VIDEO);
++ if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
++ videobuf_streamoff(&fh->vb_vidq);
++ res_free(fh, AU0828_RESOURCE_VIDEO);
++ }
+ } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ dev->vbi_timeout_running = 0;
+ del_timer_sync(&dev->vbi_timeout);
+
+- videobuf_streamoff(&fh->vb_vbiq);
+- res_free(fh, AU0828_RESOURCE_VBI);
++ if (res_check(fh, AU0828_RESOURCE_VBI)) {
++ videobuf_streamoff(&fh->vb_vbiq);
++ res_free(fh, AU0828_RESOURCE_VBI);
++ }
+ }
+
+ return 0;
--- /dev/null
+From d61270aec5acf274b0c23f2524698d6745c49e51 Mon Sep 17 00:00:00 2001
+From: "ramesh.nagappa@gmail.com" <ramesh.nagappa@gmail.com>
+Date: Fri, 5 Oct 2012 19:10:15 +0000
+Subject: net: Fix skb_under_panic oops in neigh_resolve_output
+
+
+From: "ramesh.nagappa@gmail.com" <ramesh.nagappa@gmail.com>
+
+[ Upstream commit e1f165032c8bade3a6bdf546f8faf61fda4dd01c ]
+
+The retry loop in neigh_resolve_output() and neigh_connected_output()
+call dev_hard_header() with out reseting the skb to network_header.
+This causes the retry to fail with skb_under_panic. The fix is to
+reset the network_header within the retry loop.
+
+Signed-off-by: Ramesh Nagappa <ramesh.nagappa@ericsson.com>
+Reviewed-by: Shawn Lu <shawn.lu@ericsson.com>
+Reviewed-by: Robert Coulson <robert.coulson@ericsson.com>
+Reviewed-by: Billie Alsup <billie.alsup@ericsson.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/neighbour.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -1301,8 +1301,6 @@ int neigh_resolve_output(struct neighbou
+ if (!dst)
+ goto discard;
+
+- __skb_pull(skb, skb_network_offset(skb));
+-
+ if (!neigh_event_send(neigh, skb)) {
+ int err;
+ struct net_device *dev = neigh->dev;
+@@ -1312,6 +1310,7 @@ int neigh_resolve_output(struct neighbou
+ neigh_hh_init(neigh, dst);
+
+ do {
++ __skb_pull(skb, skb_network_offset(skb));
+ seq = read_seqbegin(&neigh->ha_lock);
+ err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+ neigh->ha, NULL, skb->len);
+@@ -1342,9 +1341,8 @@ int neigh_connected_output(struct neighb
+ unsigned int seq;
+ int err;
+
+- __skb_pull(skb, skb_network_offset(skb));
+-
+ do {
++ __skb_pull(skb, skb_network_offset(skb));
+ seq = read_seqbegin(&neigh->ha_lock);
+ err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+ neigh->ha, NULL, skb->len);
--- /dev/null
+From b1299fa4e838883cefa4444e463133e000cff132 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 5 Oct 2012 06:23:55 +0000
+Subject: net: remove skb recycling
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commits acb600def2110b1310466c0e485c0d26299898ae
+ and 66eef59f22275002f621ff9d951886b513d011b3. ]
+
+Over time, skb recycling infrastructure got litle interest and
+many bugs. Generic rx path skb allocation is now using page
+fragments for efficient GRO / TCP coalescing, and recyling
+a tx skb for rx path is not worth the pain.
+
+Last identified bug is that fat skbs can be recycled
+and it can endup using high order pages after few iterations.
+
+With help from Maxime Bizon, who pointed out that commit
+87151b8689d (net: allow pskb_expand_head() to get maximum tailroom)
+introduced this regression for recycled skbs.
+
+Instead of fixing this bug, lets remove skb recycling.
+
+Drivers wanting really hot skbs should use build_skb() anyway,
+to allocate/populate sk_buff right before netif_receive_skb()
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/calxeda/xgmac.c | 19 --------
+ drivers/net/ethernet/freescale/gianfar.c | 27 +-----------
+ drivers/net/ethernet/freescale/gianfar.h | 2
+ drivers/net/ethernet/freescale/ucc_geth.c | 29 ++-----------
+ drivers/net/ethernet/freescale/ucc_geth.h | 2
+ drivers/net/ethernet/marvell/mv643xx_eth.c | 18 --------
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 20 ---------
+ include/linux/skbuff.h | 24 -----------
+ net/core/skbuff.c | 47 ----------------------
+ 10 files changed, 16 insertions(+), 173 deletions(-)
+
+--- a/drivers/net/ethernet/calxeda/xgmac.c
++++ b/drivers/net/ethernet/calxeda/xgmac.c
+@@ -375,7 +375,6 @@ struct xgmac_priv {
+ unsigned int tx_tail;
+
+ void __iomem *base;
+- struct sk_buff_head rx_recycle;
+ unsigned int dma_buf_sz;
+ dma_addr_t dma_rx_phy;
+ dma_addr_t dma_tx_phy;
+@@ -672,9 +671,7 @@ static void xgmac_rx_refill(struct xgmac
+ p = priv->dma_rx + entry;
+
+ if (priv->rx_skbuff[entry] == NULL) {
+- skb = __skb_dequeue(&priv->rx_recycle);
+- if (skb == NULL)
+- skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
++ skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
+ if (unlikely(skb == NULL))
+ break;
+
+@@ -887,17 +884,7 @@ static void xgmac_tx_complete(struct xgm
+ desc_get_buf_len(p), DMA_TO_DEVICE);
+ }
+
+- /*
+- * If there's room in the queue (limit it to size)
+- * we add this skb back into the pool,
+- * if it's the right size.
+- */
+- if ((skb_queue_len(&priv->rx_recycle) <
+- DMA_RX_RING_SZ) &&
+- skb_recycle_check(skb, priv->dma_buf_sz))
+- __skb_queue_head(&priv->rx_recycle, skb);
+- else
+- dev_kfree_skb(skb);
++ dev_kfree_skb(skb);
+ }
+
+ if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
+@@ -1016,7 +1003,6 @@ static int xgmac_open(struct net_device
+ dev->dev_addr);
+ }
+
+- skb_queue_head_init(&priv->rx_recycle);
+ memset(&priv->xstats, 0, sizeof(struct xgmac_extra_stats));
+
+ /* Initialize the XGMAC and descriptors */
+@@ -1053,7 +1039,6 @@ static int xgmac_stop(struct net_device
+ napi_disable(&priv->napi);
+
+ writel(0, priv->base + XGMAC_DMA_INTR_ENA);
+- skb_queue_purge(&priv->rx_recycle);
+
+ /* Disable the MAC core */
+ xgmac_mac_disable(priv->base);
+--- a/drivers/net/ethernet/freescale/gianfar.c
++++ b/drivers/net/ethernet/freescale/gianfar.c
+@@ -1757,7 +1757,6 @@ static void free_skb_resources(struct gf
+ sizeof(struct rxbd8) * priv->total_rx_ring_size,
+ priv->tx_queue[0]->tx_bd_base,
+ priv->tx_queue[0]->tx_bd_dma_base);
+- skb_queue_purge(&priv->rx_recycle);
+ }
+
+ void gfar_start(struct net_device *dev)
+@@ -1935,8 +1934,6 @@ static int gfar_enet_open(struct net_dev
+
+ enable_napi(priv);
+
+- skb_queue_head_init(&priv->rx_recycle);
+-
+ /* Initialize a bunch of registers */
+ init_registers(dev);
+
+@@ -2525,16 +2522,7 @@ static int gfar_clean_tx_ring(struct gfa
+
+ bytes_sent += skb->len;
+
+- /* If there's room in the queue (limit it to rx_buffer_size)
+- * we add this skb back into the pool, if it's the right size
+- */
+- if (skb_queue_len(&priv->rx_recycle) < rx_queue->rx_ring_size &&
+- skb_recycle_check(skb, priv->rx_buffer_size +
+- RXBUF_ALIGNMENT)) {
+- gfar_align_skb(skb);
+- skb_queue_head(&priv->rx_recycle, skb);
+- } else
+- dev_kfree_skb_any(skb);
++ dev_kfree_skb_any(skb);
+
+ tx_queue->tx_skbuff[skb_dirtytx] = NULL;
+
+@@ -2600,7 +2588,7 @@ static void gfar_new_rxbdp(struct gfar_p
+ static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
+ {
+ struct gfar_private *priv = netdev_priv(dev);
+- struct sk_buff *skb = NULL;
++ struct sk_buff *skb;
+
+ skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
+ if (!skb)
+@@ -2613,14 +2601,7 @@ static struct sk_buff *gfar_alloc_skb(st
+
+ struct sk_buff *gfar_new_skb(struct net_device *dev)
+ {
+- struct gfar_private *priv = netdev_priv(dev);
+- struct sk_buff *skb = NULL;
+-
+- skb = skb_dequeue(&priv->rx_recycle);
+- if (!skb)
+- skb = gfar_alloc_skb(dev);
+-
+- return skb;
++ return gfar_alloc_skb(dev);
+ }
+
+ static inline void count_errors(unsigned short status, struct net_device *dev)
+@@ -2779,7 +2760,7 @@ int gfar_clean_rx_ring(struct gfar_priv_
+ if (unlikely(!newskb))
+ newskb = skb;
+ else if (skb)
+- skb_queue_head(&priv->rx_recycle, skb);
++ dev_kfree_skb(skb);
+ } else {
+ /* Increment the number of packets */
+ rx_queue->stats.rx_packets++;
+--- a/drivers/net/ethernet/freescale/gianfar.h
++++ b/drivers/net/ethernet/freescale/gianfar.h
+@@ -1072,8 +1072,6 @@ struct gfar_private {
+
+ u32 cur_filer_idx;
+
+- struct sk_buff_head rx_recycle;
+-
+ /* RX queue filer rule set*/
+ struct ethtool_rx_list rx_list;
+ struct mutex rx_queue_access;
+--- a/drivers/net/ethernet/freescale/ucc_geth.c
++++ b/drivers/net/ethernet/freescale/ucc_geth.c
+@@ -210,14 +210,12 @@ static struct list_head *dequeue(struct
+ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
+ u8 __iomem *bd)
+ {
+- struct sk_buff *skb = NULL;
++ struct sk_buff *skb;
+
+- skb = __skb_dequeue(&ugeth->rx_recycle);
++ skb = netdev_alloc_skb(ugeth->ndev,
++ ugeth->ug_info->uf_info.max_rx_buf_length +
++ UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+ if (!skb)
+- skb = netdev_alloc_skb(ugeth->ndev,
+- ugeth->ug_info->uf_info.max_rx_buf_length +
+- UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+- if (skb == NULL)
+ return NULL;
+
+ /* We need the data buffer to be aligned properly. We will reserve
+@@ -2021,8 +2019,6 @@ static void ucc_geth_memclean(struct ucc
+ iounmap(ugeth->ug_regs);
+ ugeth->ug_regs = NULL;
+ }
+-
+- skb_queue_purge(&ugeth->rx_recycle);
+ }
+
+ static void ucc_geth_set_multi(struct net_device *dev)
+@@ -2231,8 +2227,6 @@ static int ucc_struct_init(struct ucc_ge
+ return -ENOMEM;
+ }
+
+- skb_queue_head_init(&ugeth->rx_recycle);
+-
+ return 0;
+ }
+
+@@ -3275,12 +3269,7 @@ static int ucc_geth_rx(struct ucc_geth_p
+ if (netif_msg_rx_err(ugeth))
+ ugeth_err("%s, %d: ERROR!!! skb - 0x%08x",
+ __func__, __LINE__, (u32) skb);
+- if (skb) {
+- skb->data = skb->head + NET_SKB_PAD;
+- skb->len = 0;
+- skb_reset_tail_pointer(skb);
+- __skb_queue_head(&ugeth->rx_recycle, skb);
+- }
++ dev_kfree_skb(skb);
+
+ ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
+ dev->stats.rx_dropped++;
+@@ -3350,13 +3339,7 @@ static int ucc_geth_tx(struct net_device
+
+ dev->stats.tx_packets++;
+
+- if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
+- skb_recycle_check(skb,
+- ugeth->ug_info->uf_info.max_rx_buf_length +
+- UCC_GETH_RX_DATA_BUF_ALIGNMENT))
+- __skb_queue_head(&ugeth->rx_recycle, skb);
+- else
+- dev_kfree_skb(skb);
++ dev_kfree_skb(skb);
+
+ ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
+ ugeth->skb_dirtytx[txQ] =
+--- a/drivers/net/ethernet/freescale/ucc_geth.h
++++ b/drivers/net/ethernet/freescale/ucc_geth.h
+@@ -1214,8 +1214,6 @@ struct ucc_geth_private {
+ /* index of the first skb which hasn't been transmitted yet. */
+ u16 skb_dirtytx[NUM_TX_QUEUES];
+
+- struct sk_buff_head rx_recycle;
+-
+ struct ugeth_mii_info *mii_info;
+ struct phy_device *phydev;
+ phy_interface_t phy_interface;
+--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
+@@ -412,7 +412,6 @@ struct mv643xx_eth_private {
+ u8 work_rx_refill;
+
+ int skb_size;
+- struct sk_buff_head rx_recycle;
+
+ /*
+ * RX state.
+@@ -673,9 +672,7 @@ static int rxq_refill(struct rx_queue *r
+ struct rx_desc *rx_desc;
+ int size;
+
+- skb = __skb_dequeue(&mp->rx_recycle);
+- if (skb == NULL)
+- skb = netdev_alloc_skb(mp->dev, mp->skb_size);
++ skb = netdev_alloc_skb(mp->dev, mp->skb_size);
+
+ if (skb == NULL) {
+ mp->oom = 1;
+@@ -989,14 +986,7 @@ static int txq_reclaim(struct tx_queue *
+ desc->byte_cnt, DMA_TO_DEVICE);
+ }
+
+- if (skb != NULL) {
+- if (skb_queue_len(&mp->rx_recycle) <
+- mp->rx_ring_size &&
+- skb_recycle_check(skb, mp->skb_size))
+- __skb_queue_head(&mp->rx_recycle, skb);
+- else
+- dev_kfree_skb(skb);
+- }
++ dev_kfree_skb(skb);
+ }
+
+ __netif_tx_unlock(nq);
+@@ -2349,8 +2339,6 @@ static int mv643xx_eth_open(struct net_d
+
+ napi_enable(&mp->napi);
+
+- skb_queue_head_init(&mp->rx_recycle);
+-
+ mp->int_mask = INT_EXT;
+
+ for (i = 0; i < mp->rxq_count; i++) {
+@@ -2445,8 +2433,6 @@ static int mv643xx_eth_stop(struct net_d
+ mib_counters_update(mp);
+ del_timer_sync(&mp->mib_counters_timer);
+
+- skb_queue_purge(&mp->rx_recycle);
+-
+ for (i = 0; i < mp->rxq_count; i++)
+ rxq_deinit(mp->rxq + i);
+ for (i = 0; i < mp->txq_count; i++)
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -50,7 +50,6 @@ struct stmmac_priv {
+ unsigned int dirty_rx;
+ struct sk_buff **rx_skbuff;
+ dma_addr_t *rx_skbuff_dma;
+- struct sk_buff_head rx_recycle;
+
+ struct net_device *dev;
+ dma_addr_t dma_rx_phy;
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -747,18 +747,7 @@ static void stmmac_tx(struct stmmac_priv
+ priv->hw->ring->clean_desc3(p);
+
+ if (likely(skb != NULL)) {
+- /*
+- * If there's room in the queue (limit it to size)
+- * we add this skb back into the pool,
+- * if it's the right size.
+- */
+- if ((skb_queue_len(&priv->rx_recycle) <
+- priv->dma_rx_size) &&
+- skb_recycle_check(skb, priv->dma_buf_sz))
+- __skb_queue_head(&priv->rx_recycle, skb);
+- else
+- dev_kfree_skb(skb);
+-
++ dev_kfree_skb(skb);
+ priv->tx_skbuff[entry] = NULL;
+ }
+
+@@ -1169,7 +1158,6 @@ static int stmmac_open(struct net_device
+ priv->eee_enabled = stmmac_eee_init(priv);
+
+ napi_enable(&priv->napi);
+- skb_queue_head_init(&priv->rx_recycle);
+ netif_start_queue(dev);
+
+ return 0;
+@@ -1222,7 +1210,6 @@ static int stmmac_release(struct net_dev
+ kfree(priv->tm);
+ #endif
+ napi_disable(&priv->napi);
+- skb_queue_purge(&priv->rx_recycle);
+
+ /* Free the IRQ lines */
+ free_irq(dev->irq, dev);
+@@ -1388,10 +1375,7 @@ static inline void stmmac_rx_refill(stru
+ if (likely(priv->rx_skbuff[entry] == NULL)) {
+ struct sk_buff *skb;
+
+- skb = __skb_dequeue(&priv->rx_recycle);
+- if (skb == NULL)
+- skb = netdev_alloc_skb_ip_align(priv->dev,
+- bfsize);
++ skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
+
+ if (unlikely(skb == NULL))
+ break;
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -589,9 +589,6 @@ static inline struct sk_buff *alloc_skb_
+ return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
+ }
+
+-extern void skb_recycle(struct sk_buff *skb);
+-extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
+-
+ extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
+ extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
+ extern struct sk_buff *skb_clone(struct sk_buff *skb,
+@@ -2642,27 +2639,6 @@ static inline void skb_checksum_none_ass
+
+ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
+
+-static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size)
+-{
+- if (irqs_disabled())
+- return false;
+-
+- if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
+- return false;
+-
+- if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
+- return false;
+-
+- skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
+- if (skb_end_offset(skb) < skb_size)
+- return false;
+-
+- if (skb_shared(skb) || skb_cloned(skb))
+- return false;
+-
+- return true;
+-}
+-
+ /**
+ * skb_head_is_locked - Determine if the skb->head is locked down
+ * @skb: skb to check
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -641,53 +641,6 @@ void consume_skb(struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL(consume_skb);
+
+-/**
+- * skb_recycle - clean up an skb for reuse
+- * @skb: buffer
+- *
+- * Recycles the skb to be reused as a receive buffer. This
+- * function does any necessary reference count dropping, and
+- * cleans up the skbuff as if it just came from __alloc_skb().
+- */
+-void skb_recycle(struct sk_buff *skb)
+-{
+- struct skb_shared_info *shinfo;
+-
+- skb_release_head_state(skb);
+-
+- shinfo = skb_shinfo(skb);
+- memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
+- atomic_set(&shinfo->dataref, 1);
+-
+- memset(skb, 0, offsetof(struct sk_buff, tail));
+- skb->data = skb->head + NET_SKB_PAD;
+- skb_reset_tail_pointer(skb);
+-}
+-EXPORT_SYMBOL(skb_recycle);
+-
+-/**
+- * skb_recycle_check - check if skb can be reused for receive
+- * @skb: buffer
+- * @skb_size: minimum receive buffer size
+- *
+- * Checks that the skb passed in is not shared or cloned, and
+- * that it is linear and its head portion at least as large as
+- * skb_size so that it can be recycled as a receive buffer.
+- * If these conditions are met, this function does any necessary
+- * reference count dropping and cleans up the skbuff as if it
+- * just came from __alloc_skb().
+- */
+-bool skb_recycle_check(struct sk_buff *skb, int skb_size)
+-{
+- if (!skb_is_recycleable(skb, skb_size))
+- return false;
+-
+- skb_recycle(skb);
+-
+- return true;
+-}
+-EXPORT_SYMBOL(skb_recycle_check);
+-
+ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+ {
+ new->tstamp = old->tstamp;
--- /dev/null
+From f9bee41ac74a8adb78e5645d21a50dd4758e76e1 Mon Sep 17 00:00:00 2001
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Thu, 4 Oct 2012 20:15:48 +0000
+Subject: netlink: add reference of module in netlink_dump_start
+
+
+From: Gao feng <gaofeng@cn.fujitsu.com>
+
+[ Upstream commit 6dc878a8ca39e93f70c42f3dd7260bde10c1e0f1 ]
+
+I get a panic when I use ss -a and rmmod inet_diag at the
+same time.
+
+It's because netlink_dump uses inet_diag_dump which belongs to module
+inet_diag.
+
+I search the codes and find many modules have the same problem. We
+need to add a reference to the module which the cb->dump belongs to.
+
+Thanks for all help from Stephen,Jan,Eric,Steffen and Pablo.
+
+Change From v3:
+change netlink_dump_start to inline,suggestion from Pablo and
+Eric.
+
+Change From v2:
+delete netlink_dump_done,and call module_put in netlink_dump
+and netlink_sock_destruct.
+
+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/linux/netlink.h | 21 +++++++++++++++++----
+ net/netlink/af_netlink.c | 29 +++++++++++++++++++++--------
+ 2 files changed, 38 insertions(+), 12 deletions(-)
+
+--- a/include/linux/netlink.h
++++ b/include/linux/netlink.h
+@@ -153,6 +153,7 @@ struct nlattr {
+
+ #include <linux/capability.h>
+ #include <linux/skbuff.h>
++#include <linux/export.h>
+
+ struct net;
+
+@@ -232,6 +233,8 @@ struct netlink_callback {
+ struct netlink_callback *cb);
+ int (*done)(struct netlink_callback *cb);
+ void *data;
++ /* the module that dump function belong to */
++ struct module *module;
+ u16 family;
+ u16 min_dump_alloc;
+ unsigned int prev_seq, seq;
+@@ -249,14 +252,24 @@ __nlmsg_put(struct sk_buff *skb, u32 pid
+
+ struct netlink_dump_control {
+ int (*dump)(struct sk_buff *skb, struct netlink_callback *);
+- int (*done)(struct netlink_callback*);
++ int (*done)(struct netlink_callback *);
+ void *data;
++ struct module *module;
+ u16 min_dump_alloc;
+ };
+
+-extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+- const struct nlmsghdr *nlh,
+- struct netlink_dump_control *control);
++extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
++ const struct nlmsghdr *nlh,
++ struct netlink_dump_control *control);
++static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
++ const struct nlmsghdr *nlh,
++ struct netlink_dump_control *control)
++{
++ if (!control->module)
++ control->module = THIS_MODULE;
++
++ return __netlink_dump_start(ssk, skb, nlh, control);
++}
+
+
+ #define NL_NONROOT_RECV 0x1
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -169,6 +169,8 @@ static void netlink_sock_destruct(struct
+ if (nlk->cb) {
+ if (nlk->cb->done)
+ nlk->cb->done(nlk->cb);
++
++ module_put(nlk->cb->module);
+ netlink_destroy_callback(nlk->cb);
+ }
+
+@@ -1760,6 +1762,7 @@ static int netlink_dump(struct sock *sk)
+ nlk->cb = NULL;
+ mutex_unlock(nlk->cb_mutex);
+
++ module_put(cb->module);
+ netlink_consume_callback(cb);
+ return 0;
+
+@@ -1769,9 +1772,9 @@ errout_skb:
+ return err;
+ }
+
+-int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+- const struct nlmsghdr *nlh,
+- struct netlink_dump_control *control)
++int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
++ const struct nlmsghdr *nlh,
++ struct netlink_dump_control *control)
+ {
+ struct netlink_callback *cb;
+ struct sock *sk;
+@@ -1786,6 +1789,7 @@ int netlink_dump_start(struct sock *ssk,
+ cb->done = control->done;
+ cb->nlh = nlh;
+ cb->data = control->data;
++ cb->module = control->module;
+ cb->min_dump_alloc = control->min_dump_alloc;
+ atomic_inc(&skb->users);
+ cb->skb = skb;
+@@ -1796,19 +1800,28 @@ int netlink_dump_start(struct sock *ssk,
+ return -ECONNREFUSED;
+ }
+ nlk = nlk_sk(sk);
+- /* A dump is in progress... */
++
+ mutex_lock(nlk->cb_mutex);
++ /* A dump is in progress... */
+ if (nlk->cb) {
+ mutex_unlock(nlk->cb_mutex);
+ netlink_destroy_callback(cb);
+- sock_put(sk);
+- return -EBUSY;
++ ret = -EBUSY;
++ goto out;
+ }
++ /* add reference of module which cb->dump belongs to */
++ if (!try_module_get(cb->module)) {
++ mutex_unlock(nlk->cb_mutex);
++ netlink_destroy_callback(cb);
++ ret = -EPROTONOSUPPORT;
++ goto out;
++ }
++
+ nlk->cb = cb;
+ mutex_unlock(nlk->cb_mutex);
+
+ ret = netlink_dump(sk);
+-
++out:
+ sock_put(sk);
+
+ if (ret)
+@@ -1819,7 +1832,7 @@ int netlink_dump_start(struct sock *ssk,
+ */
+ return -EINTR;
+ }
+-EXPORT_SYMBOL(netlink_dump_start);
++EXPORT_SYMBOL(__netlink_dump_start);
+
+ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
+ {
--- /dev/null
+From 5997057681cd58c573aabdcc5aa94a6ddb3b2fe5 Mon Sep 17 00:00:00 2001
+From: "jeff.liu" <jeff.liu@oracle.com>
+Date: Mon, 8 Oct 2012 18:57:27 +0000
+Subject: RDS: fix rds-ping spinlock recursion
+
+
+From: "jeff.liu" <jeff.liu@oracle.com>
+
+[ Upstream commit 5175a5e76bbdf20a614fb47ce7a38f0f39e70226 ]
+
+This is the revised patch for fixing rds-ping spinlock recursion
+according to Venkat's suggestions.
+
+RDS ping/pong over TCP feature has been broken for years(2.6.39 to
+3.6.0) since we have to set TCP cork and call kernel_sendmsg() between
+ping/pong which both need to lock "struct sock *sk". However, this
+lock has already been hold before rds_tcp_data_ready() callback is
+triggerred. As a result, we always facing spinlock resursion which
+would resulting in system panic.
+
+Given that RDS ping is only used to test the connectivity and not for
+serious performance measurements, we can queue the pong transmit to
+rds_wq as a delayed response.
+
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+CC: Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
+CC: David S. Miller <davem@davemloft.net>
+CC: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Jie Liu <jeff.liu@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rds/send.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -1122,7 +1122,7 @@ rds_send_pong(struct rds_connection *con
+ rds_stats_inc(s_send_pong);
+
+ if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags))
+- rds_send_xmit(conn);
++ queue_delayed_work(rds_wq, &conn->c_send_w, 0);
+
+ rds_message_put(rm);
+ return 0;
iommu-tegra-smmu-fix-deadly-typo.patch
amd64_edac-__amd64_set_scrub_rate-avoid-overindexing-scrubrates.patch
xtensa-add-missing-system-calls-to-the-syscall-table.patch
+media-au0828-fix-case-where-streamoff-being-called-on-stopped-stream-causes-bug.patch
+drm-i915-use-cpu-relocations-if-the-object-is-in-the-gtt-but-not-mappable.patch
+netlink-add-reference-of-module-in-netlink_dump_start.patch
+infiniband-pass-rdma_cm-module-to-netlink_dump_start.patch
+net-remove-skb-recycling.patch
+net-fix-skb_under_panic-oops-in-neigh_resolve_output.patch
+ipv6-gro-should-be-ecn-friendly.patch
+ipv4-always-invalidate-or-update-the-route-on-pmtu-events.patch
+ipv4-don-t-create-nh-exeption-when-the-device-mtu-is-smaller-than-the-reported-pmtu.patch
+ipv4-don-t-report-stale-pmtu-values-to-userspace.patch
+skge-add-dma-mask-quirk-for-marvell-88e8001-on-asus-p5nsli-motherboard.patch
+vlan-don-t-deliver-frames-for-unknown-vlans-to-protocols.patch
+ipv4-fix-sending-of-redirects.patch
+ipv4-fix-forwarding-for-strict-source-routes.patch
+ipv4-make-sure-nh_pcpu_rth_output-is-always-allocated.patch
+ipv4-introduce-rt_uses_gateway.patch
+ipv4-add-flowi_flag_known_nh.patch
+ipvs-fix-arp-resolving-for-direct-routing-mode.patch
+rds-fix-rds-ping-spinlock-recursion.patch
+tcp-resets-are-misrouted.patch
+ipv6-addrconf-fix-proc-net-if_inet6.patch
+sparc64-fix-ptrace-interaction-with-force_successful_syscall_return.patch
+sparc64-like-x86-we-should-check-current-mm-during-perf-backtrace-generation.patch
+sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch
--- /dev/null
+From bda221213df0740878a8d201d9f8c5b79c670a46 Mon Sep 17 00:00:00 2001
+From: Graham Gower <graham.gower@gmail.com>
+Date: Mon, 8 Oct 2012 08:34:50 +0000
+Subject: skge: Add DMA mask quirk for Marvell 88E8001 on ASUS P5NSLI motherboard
+
+
+From: Graham Gower <graham.gower@gmail.com>
+
+[ Upstream commit a2af139ff1cd85df586690ff626619ab1ee88b0a ]
+
+Marvell 88E8001 on an ASUS P5NSLI motherboard is unable to send/receive
+packets on a system with >4gb ram unless a 32bit DMA mask is used.
+
+This issue has been around for years and a fix was sent 3.5 years ago, but
+there was some debate as to whether it should instead be fixed as a PCI quirk.
+http://www.spinics.net/lists/netdev/msg88670.html
+
+However, 18 months later a similar workaround was introduced for another
+chipset exhibiting the same problem.
+http://www.spinics.net/lists/netdev/msg142287.html
+
+Signed-off-by: Graham Gower <graham.gower@gmail.com>
+Signed-off-by: Jan Ceuleers <jan.ceuleers@computer.org>
+Acked-by: Stephen Hemminger <shemminger@vyatta.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/marvell/skge.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/ethernet/marvell/skge.c
++++ b/drivers/net/ethernet/marvell/skge.c
+@@ -4153,6 +4153,13 @@ static struct dmi_system_id skge_32bit_d
+ DMI_MATCH(DMI_BOARD_NAME, "nForce"),
+ },
+ },
++ {
++ .ident = "ASUS P5NSLI",
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
++ DMI_MATCH(DMI_BOARD_NAME, "P5NSLI")
++ },
++ },
+ {}
+ };
+
--- /dev/null
+From 646af7e56d9541c68783519d0431c1515b7ce3e8 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Tue, 16 Oct 2012 13:05:25 -0700
+Subject: sparc64: Fix bit twiddling in sparc_pmu_enable_event().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit e793d8c6740f8fe704fa216e95685f4d92c4c4b9 ]
+
+There was a serious disconnect in the logic happening in
+sparc_pmu_disable_event() vs. sparc_pmu_enable_event().
+
+Event disable is implemented by programming a NOP event into the PCR.
+
+However, event enable was not reversing this operation. Instead, it
+was setting the User/Priv/Hypervisor trace enable bits.
+
+That's not sparc_pmu_enable_event()'s job, that's what
+sparc_pmu_enable() and sparc_pmu_disable() do .
+
+The intent of sparc_pmu_enable_event() is clear, since it first clear
+out the event type encoding field. So fix this by OR'ing in the event
+encoding rather than the trace enable bits.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/kernel/perf_event.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/sparc/kernel/perf_event.c
++++ b/arch/sparc/kernel/perf_event.c
+@@ -557,11 +557,13 @@ static u64 nop_for_index(int idx)
+
+ static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
+ {
+- u64 val, mask = mask_for_index(idx);
++ u64 enc, val, mask = mask_for_index(idx);
++
++ enc = perf_event_get_enc(cpuc->events[idx]);
+
+ val = cpuc->pcr;
+ val &= ~mask;
+- val |= hwc->config;
++ val |= event_encoding(enc, idx);
+ cpuc->pcr = val;
+
+ pcr_ops->write(cpuc->pcr);
--- /dev/null
+From 434ac3f0b3aaf4f1b009233bca822a8a399514e7 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Wed, 10 Oct 2012 17:25:00 -0700
+Subject: sparc64: fix ptrace interaction with force_successful_syscall_return()
+
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 55c2770e413e96871147b9406a9c41fe9bc5209c ]
+
+we want syscall_trace_leave() called on exit from any syscall;
+skipping its call in case we'd done force_successful_syscall_return()
+is broken...
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/kernel/syscalls.S | 32 ++++++++++++++------------------
+ 1 file changed, 14 insertions(+), 18 deletions(-)
+
+--- a/arch/sparc/kernel/syscalls.S
++++ b/arch/sparc/kernel/syscalls.S
+@@ -212,24 +212,20 @@ linux_sparc_syscall:
+ 3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+ ret_sys_call:
+ ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
+- ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
+ sra %o0, 0, %o0
+ mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
+ sllx %g2, 32, %g2
+
+- /* Check if force_successful_syscall_return()
+- * was invoked.
+- */
+- ldub [%g6 + TI_SYS_NOERROR], %l2
+- brnz,a,pn %l2, 80f
+- stb %g0, [%g6 + TI_SYS_NOERROR]
+-
+ cmp %o0, -ERESTART_RESTARTBLOCK
+ bgeu,pn %xcc, 1f
+- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
+-80:
++ andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
++ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
++
++2:
++ stb %g0, [%g6 + TI_SYS_NOERROR]
+ /* System call success, clear Carry condition code. */
+ andn %g3, %g2, %g3
++3:
+ stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+ bne,pn %icc, linux_syscall_trace2
+ add %l1, 0x4, %l2 ! npc = npc+4
+@@ -238,20 +234,20 @@ ret_sys_call:
+ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+
+ 1:
++ /* Check if force_successful_syscall_return()
++ * was invoked.
++ */
++ ldub [%g6 + TI_SYS_NOERROR], %l2
++ brnz,pn %l2, 2b
++ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
+ /* System call failure, set Carry condition code.
+ * Also, get abs(errno) to return to the process.
+ */
+- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
+ sub %g0, %o0, %o0
+- or %g3, %g2, %g3
+ stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+- stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+- bne,pn %icc, linux_syscall_trace2
+- add %l1, 0x4, %l2 ! npc = npc+4
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
++ ba,pt %xcc, 3b
++ or %g3, %g2, %g3
+
+- b,pt %xcc, rtrap
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+ linux_syscall_trace2:
+ call syscall_trace_leave
+ add %sp, PTREGS_OFF, %o0
--- /dev/null
+From 3149157b67ae8b5a96dce0a444137248cd1c9672 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Sun, 14 Oct 2012 17:59:40 -0700
+Subject: sparc64: Like x86 we should check current->mm during perf backtrace generation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 08280e6c4c2e8049ac61d9e8e3536ec1df629c0d ]
+
+If the MM is not active, only report the top-level PC. Do not try to
+access the address space.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/kernel/perf_event.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/arch/sparc/kernel/perf_event.c
++++ b/arch/sparc/kernel/perf_event.c
+@@ -1426,8 +1426,6 @@ static void perf_callchain_user_64(struc
+ {
+ unsigned long ufp;
+
+- perf_callchain_store(entry, regs->tpc);
+-
+ ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
+ do {
+ struct sparc_stackf *usf, sf;
+@@ -1448,8 +1446,6 @@ static void perf_callchain_user_32(struc
+ {
+ unsigned long ufp;
+
+- perf_callchain_store(entry, regs->tpc);
+-
+ ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
+ do {
+ struct sparc_stackf32 *usf, sf;
+@@ -1468,6 +1464,11 @@ static void perf_callchain_user_32(struc
+ void
+ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+ {
++ perf_callchain_store(entry, regs->tpc);
++
++ if (!current->mm)
++ return;
++
+ flushw_user();
+ if (test_thread_flag(TIF_32BIT))
+ perf_callchain_user_32(entry, regs);
--- /dev/null
+From b65d1b13ade9e4c08343b1e29c32384c336b1d10 Mon Sep 17 00:00:00 2001
+From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+Date: Fri, 12 Oct 2012 04:34:17 +0000
+Subject: tcp: resets are misrouted
+
+
+From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+
+[ Upstream commit 4c67525849e0b7f4bd4fab2487ec9e43ea52ef29 ]
+
+After commit e2446eaa ("tcp_v4_send_reset: binding oif to iif in no
+sock case").. tcp resets are always lost, when routing is asymmetric.
+Yes, backing out that patch will result in misrouting of resets for
+dead connections which used interface binding when were alive, but we
+actually cannot do anything here. What's died that's died and correct
+handling normal unbound connections is obviously a priority.
+
+Comment to comment:
+> This has few benefits:
+> 1. tcp_v6_send_reset already did that.
+
+It was done to route resets for IPv6 link local addresses. It was a
+mistake to do so for global addresses. The patch fixes this as well.
+
+Actually, the problem appears to be even more serious than guaranteed
+loss of resets. As reported by Sergey Soloviev <sol@eqv.ru>, those
+misrouted resets create a lot of arp traffic and huge amount of
+unresolved arp entires putting down to knees NAT firewalls which use
+asymmetric routing.
+
+Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_ipv4.c | 7 ++++---
+ net/ipv6/tcp_ipv6.c | 3 ++-
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -693,10 +693,11 @@ static void tcp_v4_send_reset(struct soc
+ arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+ arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
+ /* When socket is gone, all binding information is lost.
+- * routing might fail in this case. using iif for oif to
+- * make sure we can deliver it
++ * routing might fail in this case. No choice here, if we choose to force
++ * input interface, we will misroute in case of asymmetric route.
+ */
+- arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
++ if (sk)
++ arg.bound_dev_if = sk->sk_bound_dev_if;
+
+ net = dev_net(skb_dst(skb)->dev);
+ arg.tos = ip_hdr(skb)->tos;
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -863,7 +863,8 @@ static void tcp_v6_send_response(struct
+ __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
+
+ fl6.flowi6_proto = IPPROTO_TCP;
+- fl6.flowi6_oif = inet6_iif(skb);
++ if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
++ fl6.flowi6_oif = inet6_iif(skb);
+ fl6.fl6_dport = t1->dest;
+ fl6.fl6_sport = t1->source;
+ security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
--- /dev/null
+From 45311b1ceab2fa44a4605612b7e567814d354ce3 Mon Sep 17 00:00:00 2001
+From: Florian Zumbiehl <florz@florz.de>
+Date: Sun, 7 Oct 2012 15:51:58 +0000
+Subject: vlan: don't deliver frames for unknown vlans to protocols
+
+
+From: Florian Zumbiehl <florz@florz.de>
+
+[ Upstream commit 48cc32d38a52d0b68f91a171a8d00531edc6a46e ]
+
+6a32e4f9dd9219261f8856f817e6655114cfec2f made the vlan code skip marking
+vlan-tagged frames for not locally configured vlans as PACKET_OTHERHOST if
+there was an rx_handler, as the rx_handler could cause the frame to be received
+on a different (virtual) vlan-capable interface where that vlan might be
+configured.
+
+As rx_handlers do not necessarily return RX_HANDLER_ANOTHER, this could cause
+frames for unknown vlans to be delivered to the protocol stack as if they had
+been received untagged.
+
+For example, if an ipv6 router advertisement that's tagged for a locally not
+configured vlan is received on an interface with macvlan interfaces attached,
+macvlan's rx_handler returns RX_HANDLER_PASS after delivering the frame to the
+macvlan interfaces, which caused it to be passed to the protocol stack, leading
+to ipv6 addresses for the announced prefix being configured even though those
+are completely unusable on the underlying interface.
+
+The fix moves marking as PACKET_OTHERHOST after the rx_handler so the
+rx_handler, if there is one, sees the frame unchanged, but afterwards,
+before the frame is delivered to the protocol stack, it gets marked whether
+there is an rx_handler or not.
+
+Signed-off-by: Florian Zumbiehl <florz@florz.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/if_vlan.h | 8 ++++----
+ net/8021q/vlan_core.c | 10 ++--------
+ net/core/dev.c | 7 +++++--
+ 3 files changed, 11 insertions(+), 14 deletions(-)
+
+--- a/include/linux/if_vlan.h
++++ b/include/linux/if_vlan.h
+@@ -82,6 +82,8 @@ static inline int is_vlan_dev(struct net
+ }
+
+ #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT)
++#define vlan_tx_nonzero_tag_present(__skb) \
++ (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK))
+ #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
+
+ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+@@ -91,7 +93,7 @@ extern struct net_device *__vlan_find_de
+ extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
+ extern u16 vlan_dev_vlan_id(const struct net_device *dev);
+
+-extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler);
++extern bool vlan_do_receive(struct sk_buff **skb);
+ extern struct sk_buff *vlan_untag(struct sk_buff *skb);
+
+ extern int vlan_vid_add(struct net_device *dev, unsigned short vid);
+@@ -120,10 +122,8 @@ static inline u16 vlan_dev_vlan_id(const
+ return 0;
+ }
+
+-static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler)
++static inline bool vlan_do_receive(struct sk_buff **skb)
+ {
+- if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler)
+- (*skb)->pkt_type = PACKET_OTHERHOST;
+ return false;
+ }
+
+--- a/net/8021q/vlan_core.c
++++ b/net/8021q/vlan_core.c
+@@ -5,7 +5,7 @@
+ #include <linux/export.h>
+ #include "vlan.h"
+
+-bool vlan_do_receive(struct sk_buff **skbp, bool last_handler)
++bool vlan_do_receive(struct sk_buff **skbp)
+ {
+ struct sk_buff *skb = *skbp;
+ u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
+@@ -13,14 +13,8 @@ bool vlan_do_receive(struct sk_buff **sk
+ struct vlan_pcpu_stats *rx_stats;
+
+ vlan_dev = vlan_find_dev(skb->dev, vlan_id);
+- if (!vlan_dev) {
+- /* Only the last call to vlan_do_receive() should change
+- * pkt_type to PACKET_OTHERHOST
+- */
+- if (vlan_id && last_handler)
+- skb->pkt_type = PACKET_OTHERHOST;
++ if (!vlan_dev)
+ return false;
+- }
+
+ skb = *skbp = skb_share_check(skb, GFP_ATOMIC);
+ if (unlikely(!skb))
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -3275,18 +3275,18 @@ ncls:
+ && !skb_pfmemalloc_protocol(skb))
+ goto drop;
+
+- rx_handler = rcu_dereference(skb->dev->rx_handler);
+ if (vlan_tx_tag_present(skb)) {
+ if (pt_prev) {
+ ret = deliver_skb(skb, pt_prev, orig_dev);
+ pt_prev = NULL;
+ }
+- if (vlan_do_receive(&skb, !rx_handler))
++ if (vlan_do_receive(&skb))
+ goto another_round;
+ else if (unlikely(!skb))
+ goto unlock;
+ }
+
++ rx_handler = rcu_dereference(skb->dev->rx_handler);
+ if (rx_handler) {
+ if (pt_prev) {
+ ret = deliver_skb(skb, pt_prev, orig_dev);
+@@ -3306,6 +3306,9 @@ ncls:
+ }
+ }
+
++ if (vlan_tx_nonzero_tag_present(skb))
++ skb->pkt_type = PACKET_OTHERHOST;
++
+ /* deliver only exact match when indicated */
+ null_or_dev = deliver_exact ? skb->dev : NULL;
+
the 64-bit arguments are aligned correctly to the argument registers.
Signed-off-by: Chris Zankel <chris@zankel.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/xtensa/include/asm/unistd.h | 89 +++++++++++++++++++++++++++++++--------