From: Greg Kroah-Hartman Date: Thu, 25 Oct 2012 22:58:47 +0000 (-0700) Subject: 3.6-stable patches X-Git-Tag: v3.0.49~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a3af7eaafb6046b7dc1abdb9d7829fbddddbdd5e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.6-stable patches added patches: drm-i915-use-cpu-relocations-if-the-object-is-in-the-gtt-but-not-mappable.patch infiniband-pass-rdma_cm-module-to-netlink_dump_start.patch ipv4-add-flowi_flag_known_nh.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 ipv4-fix-forwarding-for-strict-source-routes.patch ipv4-fix-sending-of-redirects.patch ipv4-introduce-rt_uses_gateway.patch ipv4-make-sure-nh_pcpu_rth_output-is-always-allocated.patch ipv6-addrconf-fix-proc-net-if_inet6.patch ipv6-gro-should-be-ecn-friendly.patch ipvs-fix-arp-resolving-for-direct-routing-mode.patch media-au0828-fix-case-where-streamoff-being-called-on-stopped-stream-causes-bug.patch net-fix-skb_under_panic-oops-in-neigh_resolve_output.patch netlink-add-reference-of-module-in-netlink_dump_start.patch net-remove-skb-recycling.patch rds-fix-rds-ping-spinlock-recursion.patch skge-add-dma-mask-quirk-for-marvell-88e8001-on-asus-p5nsli-motherboard.patch sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch sparc64-fix-ptrace-interaction-with-force_successful_syscall_return.patch sparc64-like-x86-we-should-check-current-mm-during-perf-backtrace-generation.patch tcp-resets-are-misrouted.patch vlan-don-t-deliver-frames-for-unknown-vlans-to-protocols.patch --- diff --git a/queue-3.6/drm-i915-use-cpu-relocations-if-the-object-is-in-the-gtt-but-not-mappable.patch b/queue-3.6/drm-i915-use-cpu-relocations-if-the-object-is-in-the-gtt-but-not-mappable.patch new file mode 100644 index 00000000000..e26967445f9 --- /dev/null +++ b/queue-3.6/drm-i915-use-cpu-relocations-if-the-object-is-in-the-gtt-but-not-mappable.patch @@ -0,0 +1,34 @@ +From 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +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 + +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 +Signed-off-by: Daniel Vetter +Cc: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + diff --git a/queue-3.6/infiniband-pass-rdma_cm-module-to-netlink_dump_start.patch b/queue-3.6/infiniband-pass-rdma_cm-module-to-netlink_dump_start.patch new file mode 100644 index 00000000000..c5cbf2ef18b --- /dev/null +++ b/queue-3.6/infiniband-pass-rdma_cm-module-to-netlink_dump_start.patch @@ -0,0 +1,55 @@ +From 13e570f1d520d1383b4d8837fb5adb1f24a31661 Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Thu, 4 Oct 2012 20:15:49 +0000 +Subject: infiniband: pass rdma_cm module to netlink_dump_start + + +From: Gao feng + +[ Upstream commit 809d5fc9bf6589276a12bd4fd611e4c7ff9940c3 ] + +set netlink_dump_control.module to avoid panic. + +Signed-off-by: Gao feng +Cc: Roland Dreier +Cc: Sean Hefty +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-3.6/ipv4-add-flowi_flag_known_nh.patch b/queue-3.6/ipv4-add-flowi_flag_known_nh.patch new file mode 100644 index 00000000000..c2d7443c7b8 --- /dev/null +++ b/queue-3.6/ipv4-add-flowi_flag_known_nh.patch @@ -0,0 +1,93 @@ +From b48c7e3ddd9bee91e43b7682590a64403b0fce63 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 8 Oct 2012 11:41:19 +0000 +Subject: ipv4: Add FLOWI_FLAG_KNOWN_NH + + +From: Julian Anastasov + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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); + diff --git a/queue-3.6/ipv4-always-invalidate-or-update-the-route-on-pmtu-events.patch b/queue-3.6/ipv4-always-invalidate-or-update-the-route-on-pmtu-events.patch new file mode 100644 index 00000000000..9f591f054bb --- /dev/null +++ b/queue-3.6/ipv4-always-invalidate-or-update-the-route-on-pmtu-events.patch @@ -0,0 +1,76 @@ +From 42ca21062a7faeec9140494e39d1d3f931f459e9 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Sun, 7 Oct 2012 22:47:25 +0000 +Subject: ipv4: Always invalidate or update the route on pmtu events + + +From: Steffen Klassert + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-3.6/ipv4-don-t-create-nh-exeption-when-the-device-mtu-is-smaller-than-the-reported-pmtu.patch b/queue-3.6/ipv4-don-t-create-nh-exeption-when-the-device-mtu-is-smaller-than-the-reported-pmtu.patch new file mode 100644 index 00000000000..450fbf42c1a --- /dev/null +++ b/queue-3.6/ipv4-don-t-create-nh-exeption-when-the-device-mtu-is-smaller-than-the-reported-pmtu.patch @@ -0,0 +1,35 @@ +From 770f58d7866dfb0bc61a797ae601b7e481d741d5 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +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 + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; + diff --git a/queue-3.6/ipv4-don-t-report-stale-pmtu-values-to-userspace.patch b/queue-3.6/ipv4-don-t-report-stale-pmtu-values-to-userspace.patch new file mode 100644 index 00000000000..ce44da2d629 --- /dev/null +++ b/queue-3.6/ipv4-don-t-report-stale-pmtu-values-to-userspace.patch @@ -0,0 +1,58 @@ +From 26b59d48e8de1d793e3b8aefc4d2a81b59feece7 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Mon, 8 Oct 2012 00:56:54 +0000 +Subject: ipv4: Don't report stale pmtu values to userspace + + +From: Steffen Klassert + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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)) diff --git a/queue-3.6/ipv4-fix-forwarding-for-strict-source-routes.patch b/queue-3.6/ipv4-fix-forwarding-for-strict-source-routes.patch new file mode 100644 index 00000000000..5ad49088d8f --- /dev/null +++ b/queue-3.6/ipv4-fix-forwarding-for-strict-source-routes.patch @@ -0,0 +1,33 @@ +From 9ec66bfc332d28cf6c9d5ec16fb8e1b42412e815 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 8 Oct 2012 11:41:16 +0000 +Subject: ipv4: fix forwarding for strict source routes + + +From: Julian Anastasov + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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) && diff --git a/queue-3.6/ipv4-fix-sending-of-redirects.patch b/queue-3.6/ipv4-fix-sending-of-redirects.patch new file mode 100644 index 00000000000..2b14873b113 --- /dev/null +++ b/queue-3.6/ipv4-fix-sending-of-redirects.patch @@ -0,0 +1,119 @@ +From 9412e270cddca255cb5dc3e28d36fc8c32eaec95 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 8 Oct 2012 11:41:15 +0000 +Subject: ipv4: fix sending of redirects + + +From: Julian Anastasov + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } + } + diff --git a/queue-3.6/ipv4-introduce-rt_uses_gateway.patch b/queue-3.6/ipv4-introduce-rt_uses_gateway.patch new file mode 100644 index 00000000000..c038a97631b --- /dev/null +++ b/queue-3.6/ipv4-introduce-rt_uses_gateway.patch @@ -0,0 +1,249 @@ +From 00ea0afa32f0f8568ac2d5727c43c6d00d25e517 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 8 Oct 2012 11:41:18 +0000 +Subject: ipv4: introduce rt_uses_gateway + + +From: Julian Anastasov + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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); + diff --git a/queue-3.6/ipv4-make-sure-nh_pcpu_rth_output-is-always-allocated.patch b/queue-3.6/ipv4-make-sure-nh_pcpu_rth_output-is-always-allocated.patch new file mode 100644 index 00000000000..d10672389f8 --- /dev/null +++ b/queue-3.6/ipv4-make-sure-nh_pcpu_rth_output-is-always-allocated.patch @@ -0,0 +1,51 @@ +From 473bd4d9b43f5b02a022d6c9473decd1ca19472a Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 8 Oct 2012 11:41:17 +0000 +Subject: ipv4: make sure nh_pcpu_rth_output is always allocated + + +From: Julian Anastasov + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } diff --git a/queue-3.6/ipv6-addrconf-fix-proc-net-if_inet6.patch b/queue-3.6/ipv6-addrconf-fix-proc-net-if_inet6.patch new file mode 100644 index 00000000000..f34a3cfd18c --- /dev/null +++ b/queue-3.6/ipv6-addrconf-fix-proc-net-if_inet6.patch @@ -0,0 +1,78 @@ +From 7da2aac0abf5e94c82806375aec7199fc765f3aa Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 16 Oct 2012 07:37:27 +0000 +Subject: ipv6: addrconf: fix /proc/net/if_inet6 + + +From: Eric Dumazet + +[ 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 +Tested-by: Jan Hinnerk Stosch +Signed-off-by: Eric Dumazet +Cc: Mihai Maruseac +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } + } + diff --git a/queue-3.6/ipv6-gro-should-be-ecn-friendly.patch b/queue-3.6/ipv6-gro-should-be-ecn-friendly.patch new file mode 100644 index 00000000000..fc1f1e0b431 --- /dev/null +++ b/queue-3.6/ipv6-gro-should-be-ecn-friendly.patch @@ -0,0 +1,59 @@ +From f16e08225fe7ae2d52b3e12cd9e6256d82de4f0b Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 5 Oct 2012 20:43:30 +0000 +Subject: ipv6: GRO should be ECN friendly + + +From: Eric Dumazet + +[ 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 +Cc: Herbert Xu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; /* */ + + 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; + } + diff --git a/queue-3.6/ipvs-fix-arp-resolving-for-direct-routing-mode.patch b/queue-3.6/ipvs-fix-arp-resolving-for-direct-routing-mode.patch new file mode 100644 index 00000000000..55e453e28ed --- /dev/null +++ b/queue-3.6/ipvs-fix-arp-resolving-for-direct-routing-mode.patch @@ -0,0 +1,62 @@ +From 8d6957fe79380bad40501151d2a87336cbd122a2 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 8 Oct 2012 11:41:20 +0000 +Subject: ipvs: fix ARP resolving for direct routing mode + + +From: Julian Anastasov + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-3.6/media-au0828-fix-case-where-streamoff-being-called-on-stopped-stream-causes-bug.patch b/queue-3.6/media-au0828-fix-case-where-streamoff-being-called-on-stopped-stream-causes-bug.patch new file mode 100644 index 00000000000..f534c179844 --- /dev/null +++ b/queue-3.6/media-au0828-fix-case-where-streamoff-being-called-on-stopped-stream-causes-bug.patch @@ -0,0 +1,47 @@ +From a595c1ce4c9d572cf53513570b9f1a263d7867f2 Mon Sep 17 00:00:00 2001 +From: Devin Heitmueller +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 + +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 +Reported-by: Jay Harbeston +Signed-off-by: Devin Heitmueller +Signed-off-by: Mauro Carvalho Chehab + +--- + 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; diff --git a/queue-3.6/net-fix-skb_under_panic-oops-in-neigh_resolve_output.patch b/queue-3.6/net-fix-skb_under_panic-oops-in-neigh_resolve_output.patch new file mode 100644 index 00000000000..7d80a684367 --- /dev/null +++ b/queue-3.6/net-fix-skb_under_panic-oops-in-neigh_resolve_output.patch @@ -0,0 +1,55 @@ +From d61270aec5acf274b0c23f2524698d6745c49e51 Mon Sep 17 00:00:00 2001 +From: "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" + +[ 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 +Reviewed-by: Shawn Lu +Reviewed-by: Robert Coulson +Reviewed-by: Billie Alsup +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-3.6/net-remove-skb-recycling.patch b/queue-3.6/net-remove-skb-recycling.patch new file mode 100644 index 00000000000..26335181042 --- /dev/null +++ b/queue-3.6/net-remove-skb-recycling.patch @@ -0,0 +1,473 @@ +From b1299fa4e838883cefa4444e463133e000cff132 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 5 Oct 2012 06:23:55 +0000 +Subject: net: remove skb recycling + + +From: Eric Dumazet + +[ 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 +Cc: Maxime Bizon +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-3.6/netlink-add-reference-of-module-in-netlink_dump_start.patch b/queue-3.6/netlink-add-reference-of-module-in-netlink_dump_start.patch new file mode 100644 index 00000000000..e3867dfa2e6 --- /dev/null +++ b/queue-3.6/netlink-add-reference-of-module-in-netlink_dump_start.patch @@ -0,0 +1,167 @@ +From f9bee41ac74a8adb78e5645d21a50dd4758e76e1 Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Thu, 4 Oct 2012 20:15:48 +0000 +Subject: netlink: add reference of module in netlink_dump_start + + +From: Gao feng + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include ++#include + + 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) + { diff --git a/queue-3.6/rds-fix-rds-ping-spinlock-recursion.patch b/queue-3.6/rds-fix-rds-ping-spinlock-recursion.patch new file mode 100644 index 00000000000..4f3dce50c89 --- /dev/null +++ b/queue-3.6/rds-fix-rds-ping-spinlock-recursion.patch @@ -0,0 +1,46 @@ +From 5997057681cd58c573aabdcc5aa94a6ddb3b2fe5 Mon Sep 17 00:00:00 2001 +From: "jeff.liu" +Date: Mon, 8 Oct 2012 18:57:27 +0000 +Subject: RDS: fix rds-ping spinlock recursion + + +From: "jeff.liu" + +[ 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 +CC: Venkat Venkatsubra +CC: David S. Miller +CC: James Morris +Signed-off-by: Jie Liu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-3.6/series b/queue-3.6/series index 1fa6228a2e4..cfbec7663ce 100644 --- a/queue-3.6/series +++ b/queue-3.6/series @@ -58,3 +58,27 @@ pinctrl-fix-missing-unlock-on-error-in.patch 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 diff --git a/queue-3.6/skge-add-dma-mask-quirk-for-marvell-88e8001-on-asus-p5nsli-motherboard.patch b/queue-3.6/skge-add-dma-mask-quirk-for-marvell-88e8001-on-asus-p5nsli-motherboard.patch new file mode 100644 index 00000000000..9d05ff2b301 --- /dev/null +++ b/queue-3.6/skge-add-dma-mask-quirk-for-marvell-88e8001-on-asus-p5nsli-motherboard.patch @@ -0,0 +1,46 @@ +From bda221213df0740878a8d201d9f8c5b79c670a46 Mon Sep 17 00:00:00 2001 +From: Graham Gower +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 + +[ 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 +Signed-off-by: Jan Ceuleers +Acked-by: Stephen Hemminger +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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") ++ }, ++ }, + {} + }; + diff --git a/queue-3.6/sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch b/queue-3.6/sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch new file mode 100644 index 00000000000..bae08c1172d --- /dev/null +++ b/queue-3.6/sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch @@ -0,0 +1,49 @@ +From 646af7e56d9541c68783519d0431c1515b7ce3e8 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 16 Oct 2012 13:05:25 -0700 +Subject: sparc64: Fix bit twiddling in sparc_pmu_enable_event(). + + +From: "David S. Miller" + +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-3.6/sparc64-fix-ptrace-interaction-with-force_successful_syscall_return.patch b/queue-3.6/sparc64-fix-ptrace-interaction-with-force_successful_syscall_return.patch new file mode 100644 index 00000000000..73b9d411243 --- /dev/null +++ b/queue-3.6/sparc64-fix-ptrace-interaction-with-force_successful_syscall_return.patch @@ -0,0 +1,83 @@ +From 434ac3f0b3aaf4f1b009233bca822a8a399514e7 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Wed, 10 Oct 2012 17:25:00 -0700 +Subject: sparc64: fix ptrace interaction with force_successful_syscall_return() + + +From: Al Viro + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-3.6/sparc64-like-x86-we-should-check-current-mm-during-perf-backtrace-generation.patch b/queue-3.6/sparc64-like-x86-we-should-check-current-mm-during-perf-backtrace-generation.patch new file mode 100644 index 00000000000..8d901d7c915 --- /dev/null +++ b/queue-3.6/sparc64-like-x86-we-should-check-current-mm-during-perf-backtrace-generation.patch @@ -0,0 +1,51 @@ +From 3149157b67ae8b5a96dce0a444137248cd1c9672 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +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" + +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-3.6/tcp-resets-are-misrouted.patch b/queue-3.6/tcp-resets-are-misrouted.patch new file mode 100644 index 00000000000..7a6760cdbd0 --- /dev/null +++ b/queue-3.6/tcp-resets-are-misrouted.patch @@ -0,0 +1,66 @@ +From b65d1b13ade9e4c08343b1e29c32384c336b1d10 Mon Sep 17 00:00:00 2001 +From: Alexey Kuznetsov +Date: Fri, 12 Oct 2012 04:34:17 +0000 +Subject: tcp: resets are misrouted + + +From: Alexey Kuznetsov + +[ 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 , 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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)); diff --git a/queue-3.6/vlan-don-t-deliver-frames-for-unknown-vlans-to-protocols.patch b/queue-3.6/vlan-don-t-deliver-frames-for-unknown-vlans-to-protocols.patch new file mode 100644 index 00000000000..8276628ad47 --- /dev/null +++ b/queue-3.6/vlan-don-t-deliver-frames-for-unknown-vlans-to-protocols.patch @@ -0,0 +1,133 @@ +From 45311b1ceab2fa44a4605612b7e567814d354ce3 Mon Sep 17 00:00:00 2001 +From: Florian Zumbiehl +Date: Sun, 7 Oct 2012 15:51:58 +0000 +Subject: vlan: don't deliver frames for unknown vlans to protocols + + +From: Florian Zumbiehl + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #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; + diff --git a/queue-3.6/xtensa-add-missing-system-calls-to-the-syscall-table.patch b/queue-3.6/xtensa-add-missing-system-calls-to-the-syscall-table.patch index a8b763b2bd0..9b05abdf87a 100644 --- a/queue-3.6/xtensa-add-missing-system-calls-to-the-syscall-table.patch +++ b/queue-3.6/xtensa-add-missing-system-calls-to-the-syscall-table.patch @@ -41,6 +41,7 @@ Note that we have to use the 'sys_sync_file_range2' version, so that the 64-bit arguments are aligned correctly to the argument registers. Signed-off-by: Chris Zankel +Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/include/asm/unistd.h | 89 +++++++++++++++++++++++++++++++--------