]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Oct 2012 22:58:47 +0000 (15:58 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Oct 2012 22:58:47 +0000 (15:58 -0700)
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

26 files changed:
queue-3.6/drm-i915-use-cpu-relocations-if-the-object-is-in-the-gtt-but-not-mappable.patch [new file with mode: 0644]
queue-3.6/infiniband-pass-rdma_cm-module-to-netlink_dump_start.patch [new file with mode: 0644]
queue-3.6/ipv4-add-flowi_flag_known_nh.patch [new file with mode: 0644]
queue-3.6/ipv4-always-invalidate-or-update-the-route-on-pmtu-events.patch [new file with mode: 0644]
queue-3.6/ipv4-don-t-create-nh-exeption-when-the-device-mtu-is-smaller-than-the-reported-pmtu.patch [new file with mode: 0644]
queue-3.6/ipv4-don-t-report-stale-pmtu-values-to-userspace.patch [new file with mode: 0644]
queue-3.6/ipv4-fix-forwarding-for-strict-source-routes.patch [new file with mode: 0644]
queue-3.6/ipv4-fix-sending-of-redirects.patch [new file with mode: 0644]
queue-3.6/ipv4-introduce-rt_uses_gateway.patch [new file with mode: 0644]
queue-3.6/ipv4-make-sure-nh_pcpu_rth_output-is-always-allocated.patch [new file with mode: 0644]
queue-3.6/ipv6-addrconf-fix-proc-net-if_inet6.patch [new file with mode: 0644]
queue-3.6/ipv6-gro-should-be-ecn-friendly.patch [new file with mode: 0644]
queue-3.6/ipvs-fix-arp-resolving-for-direct-routing-mode.patch [new file with mode: 0644]
queue-3.6/media-au0828-fix-case-where-streamoff-being-called-on-stopped-stream-causes-bug.patch [new file with mode: 0644]
queue-3.6/net-fix-skb_under_panic-oops-in-neigh_resolve_output.patch [new file with mode: 0644]
queue-3.6/net-remove-skb-recycling.patch [new file with mode: 0644]
queue-3.6/netlink-add-reference-of-module-in-netlink_dump_start.patch [new file with mode: 0644]
queue-3.6/rds-fix-rds-ping-spinlock-recursion.patch [new file with mode: 0644]
queue-3.6/series
queue-3.6/skge-add-dma-mask-quirk-for-marvell-88e8001-on-asus-p5nsli-motherboard.patch [new file with mode: 0644]
queue-3.6/sparc64-fix-bit-twiddling-in-sparc_pmu_enable_event.patch [new file with mode: 0644]
queue-3.6/sparc64-fix-ptrace-interaction-with-force_successful_syscall_return.patch [new file with mode: 0644]
queue-3.6/sparc64-like-x86-we-should-check-current-mm-during-perf-backtrace-generation.patch [new file with mode: 0644]
queue-3.6/tcp-resets-are-misrouted.patch [new file with mode: 0644]
queue-3.6/vlan-don-t-deliver-frames-for-unknown-vlans-to-protocols.patch [new file with mode: 0644]
queue-3.6/xtensa-add-missing-system-calls-to-the-syscall-table.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 (file)
index 0000000..e269674
--- /dev/null
@@ -0,0 +1,34 @@
+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);
+ }
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 (file)
index 0000000..c5cbf2e
--- /dev/null
@@ -0,0 +1,55 @@
+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);
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 (file)
index 0000000..c2d7443
--- /dev/null
@@ -0,0 +1,93 @@
+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);
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 (file)
index 0000000..9f591f0
--- /dev/null
@@ -0,0 +1,76 @@
+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,
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 (file)
index 0000000..450fbf4
--- /dev/null
@@ -0,0 +1,35 @@
+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;
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 (file)
index 0000000..ce44da2
--- /dev/null
@@ -0,0 +1,58 @@
+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))
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 (file)
index 0000000..5ad4908
--- /dev/null
@@ -0,0 +1,33 @@
+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) &&
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 (file)
index 0000000..2b14873
--- /dev/null
@@ -0,0 +1,119 @@
+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;
+               }
+       }
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 (file)
index 0000000..c038a97
--- /dev/null
@@ -0,0 +1,249 @@
+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);
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 (file)
index 0000000..d106723
--- /dev/null
@@ -0,0 +1,51 @@
+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;
+       }
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 (file)
index 0000000..f34a3cf
--- /dev/null
@@ -0,0 +1,78 @@
+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;
+               }
+       }
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 (file)
index 0000000..fc1f1e0
--- /dev/null
@@ -0,0 +1,59 @@
+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;
+       }
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 (file)
index 0000000..55e453e
--- /dev/null
@@ -0,0 +1,62 @@
+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);
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 (file)
index 0000000..f534c17
--- /dev/null
@@ -0,0 +1,47 @@
+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;
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 (file)
index 0000000..7d80a68
--- /dev/null
@@ -0,0 +1,55 @@
+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);
diff --git a/queue-3.6/net-remove-skb-recycling.patch b/queue-3.6/net-remove-skb-recycling.patch
new file mode 100644 (file)
index 0000000..2633518
--- /dev/null
@@ -0,0 +1,473 @@
+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;
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 (file)
index 0000000..e3867df
--- /dev/null
@@ -0,0 +1,167 @@
+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)
+ {
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 (file)
index 0000000..4f3dce5
--- /dev/null
@@ -0,0 +1,46 @@
+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;
index 1fa6228a2e4bcaec31012d6893bb06932796f579..cfbec7663cef1dafe2aa48f0793bc02b1b2ef09c 100644 (file)
@@ -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 (file)
index 0000000..9d05ff2
--- /dev/null
@@ -0,0 +1,46 @@
+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")
++              },
++      },
+       {}
+ };
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 (file)
index 0000000..bae08c1
--- /dev/null
@@ -0,0 +1,49 @@
+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);
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 (file)
index 0000000..73b9d41
--- /dev/null
@@ -0,0 +1,83 @@
+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
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 (file)
index 0000000..8d901d7
--- /dev/null
@@ -0,0 +1,51 @@
+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);
diff --git a/queue-3.6/tcp-resets-are-misrouted.patch b/queue-3.6/tcp-resets-are-misrouted.patch
new file mode 100644 (file)
index 0000000..7a6760c
--- /dev/null
@@ -0,0 +1,66 @@
+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));
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 (file)
index 0000000..8276628
--- /dev/null
@@ -0,0 +1,133 @@
+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;
index a8b763b2bd0c423ae9a02d45c8cf4148265e7a33..9b05abdf87a96e67b7bcaeff7f3f4f8bddb8efed 100644 (file)
@@ -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 <chris@zankel.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 ---
  arch/xtensa/include/asm/unistd.h |   89 +++++++++++++++++++++++++++++++--------