]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.1-stable patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 3 Jan 2012 20:39:43 +0000 (12:39 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 3 Jan 2012 20:39:43 +0000 (12:39 -0800)
added patches:
ipv4-flush-route-cache-after-change-accept_local.patch
ipv4-reintroduce-route-cache-garbage-collector.patch
ipv4-using-prefetch-requires-including-prefetch.h.patch
ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch
llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch
mqprio-avoid-panic-if-no-options-are-provided.patch
net-add-a-flow_cache_flush_deferred-function.patch
net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch
net-have-ipconfig-not-wait-if-no-dev-is-available.patch
net-introduce-dst_nopeer-dst-flag.patch
ppp-fix-pptp-double-release_sock-in-pptp_bind.patch
sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch
sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch
sctp-fix-incorrect-overflow-check-on-autoclose.patch
sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
sparc32-correct-the-return-value-of-memcpy.patch
sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
sparc-kill-custom-io_remap_pfn_range.patch

24 files changed:
queue-3.1/ipv4-flush-route-cache-after-change-accept_local.patch [new file with mode: 0644]
queue-3.1/ipv4-reintroduce-route-cache-garbage-collector.patch [new file with mode: 0644]
queue-3.1/ipv4-using-prefetch-requires-including-prefetch.h.patch [new file with mode: 0644]
queue-3.1/ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch [new file with mode: 0644]
queue-3.1/llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch [new file with mode: 0644]
queue-3.1/mqprio-avoid-panic-if-no-options-are-provided.patch [new file with mode: 0644]
queue-3.1/net-add-a-flow_cache_flush_deferred-function.patch [new file with mode: 0644]
queue-3.1/net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch [new file with mode: 0644]
queue-3.1/net-have-ipconfig-not-wait-if-no-dev-is-available.patch [new file with mode: 0644]
queue-3.1/net-introduce-dst_nopeer-dst-flag.patch [new file with mode: 0644]
queue-3.1/ppp-fix-pptp-double-release_sock-in-pptp_bind.patch [new file with mode: 0644]
queue-3.1/sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch [new file with mode: 0644]
queue-3.1/sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch [new file with mode: 0644]
queue-3.1/sctp-fix-incorrect-overflow-check-on-autoclose.patch [new file with mode: 0644]
queue-3.1/series
queue-3.1/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch [new file with mode: 0644]
queue-3.1/sparc-kill-custom-io_remap_pfn_range.patch [new file with mode: 0644]
queue-3.1/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch [new file with mode: 0644]
queue-3.1/sparc32-correct-the-return-value-of-memcpy.patch [new file with mode: 0644]
queue-3.1/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch [new file with mode: 0644]
queue-3.1/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch [new file with mode: 0644]
queue-3.1/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch [new file with mode: 0644]
queue-3.1/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch [new file with mode: 0644]
queue-3.1/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch [new file with mode: 0644]

diff --git a/queue-3.1/ipv4-flush-route-cache-after-change-accept_local.patch b/queue-3.1/ipv4-flush-route-cache-after-change-accept_local.patch
new file mode 100644 (file)
index 0000000..5fcbde0
--- /dev/null
@@ -0,0 +1,43 @@
+From f9e1e7e59d60d85684a05366d282b6d6bdfdb687 Mon Sep 17 00:00:00 2001
+From: "Peter Pan(潘卫平)" <panweiping3@gmail.com>
+Date: Thu, 1 Dec 2011 15:47:06 +0000
+Subject: ipv4: flush route cache after change accept_local
+
+
+From: Weiping Pan <panweiping3@gmail.com>
+
+[ Upstream commit d01ff0a049f749e0bf10a35bb23edd012718c8c2 ]
+
+After reset ipv4_devconf->data[IPV4_DEVCONF_ACCEPT_LOCAL] to 0,
+we should flush route cache, or it will continue receive packets with local
+source address, which should be dropped.
+
+Signed-off-by: Weiping Pan <panweiping3@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv4/devinet.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -1490,7 +1490,9 @@ static int devinet_conf_proc(ctl_table *
+                            void __user *buffer,
+                            size_t *lenp, loff_t *ppos)
+ {
++      int old_value = *(int *)ctl->data;
+       int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
++      int new_value = *(int *)ctl->data;
+       if (write) {
+               struct ipv4_devconf *cnf = ctl->extra1;
+@@ -1501,6 +1503,9 @@ static int devinet_conf_proc(ctl_table *
+               if (cnf == net->ipv4.devconf_dflt)
+                       devinet_copy_dflt_conf(net, i);
++              if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1)
++                      if ((new_value == 0) && (old_value != 0))
++                              rt_cache_flush(net, 0);
+       }
+       return ret;
diff --git a/queue-3.1/ipv4-reintroduce-route-cache-garbage-collector.patch b/queue-3.1/ipv4-reintroduce-route-cache-garbage-collector.patch
new file mode 100644 (file)
index 0000000..74b3345
--- /dev/null
@@ -0,0 +1,165 @@
+From 92023c1e1af8d82e1dce92a17efd0f1adffa2dd2 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Wed, 21 Dec 2011 15:47:16 -0500
+Subject: ipv4: reintroduce route cache garbage collector
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit 9f28a2fc0bd77511f649c0a788c7bf9a5fd04edb ]
+
+Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer)
+removed IP route cache garbage collector a bit too soon, as this gc was
+responsible for expired routes cleanup, releasing their neighbour
+reference.
+
+As pointed out by Robert Gladewitz, recent kernels can fill and exhaust
+their neighbour cache.
+
+Reintroduce the garbage collection, since we'll have to wait our
+neighbour lookups become refcount-less to not depend on this stuff.
+
+Reported-by: Robert Gladewitz <gladewitz@gmx.de>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv4/route.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 106 insertions(+)
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -134,6 +134,9 @@ static int ip_rt_min_advmss __read_mostl
+ static int rt_chain_length_max __read_mostly  = 20;
+ static int redirect_genid;
++static struct delayed_work expires_work;
++static unsigned long expires_ljiffies;
++
+ /*
+  *    Interface to generic destination cache.
+  */
+@@ -831,6 +834,97 @@ static int has_noalias(const struct rtab
+       return ONE;
+ }
++static void rt_check_expire(void)
++{
++      static unsigned int rover;
++      unsigned int i = rover, goal;
++      struct rtable *rth;
++      struct rtable __rcu **rthp;
++      unsigned long samples = 0;
++      unsigned long sum = 0, sum2 = 0;
++      unsigned long delta;
++      u64 mult;
++
++      delta = jiffies - expires_ljiffies;
++      expires_ljiffies = jiffies;
++      mult = ((u64)delta) << rt_hash_log;
++      if (ip_rt_gc_timeout > 1)
++              do_div(mult, ip_rt_gc_timeout);
++      goal = (unsigned int)mult;
++      if (goal > rt_hash_mask)
++              goal = rt_hash_mask + 1;
++      for (; goal > 0; goal--) {
++              unsigned long tmo = ip_rt_gc_timeout;
++              unsigned long length;
++
++              i = (i + 1) & rt_hash_mask;
++              rthp = &rt_hash_table[i].chain;
++
++              if (need_resched())
++                      cond_resched();
++
++              samples++;
++
++              if (rcu_dereference_raw(*rthp) == NULL)
++                      continue;
++              length = 0;
++              spin_lock_bh(rt_hash_lock_addr(i));
++              while ((rth = rcu_dereference_protected(*rthp,
++                                      lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) {
++                      prefetch(rth->dst.rt_next);
++                      if (rt_is_expired(rth)) {
++                              *rthp = rth->dst.rt_next;
++                              rt_free(rth);
++                              continue;
++                      }
++                      if (rth->dst.expires) {
++                              /* Entry is expired even if it is in use */
++                              if (time_before_eq(jiffies, rth->dst.expires)) {
++nofree:
++                                      tmo >>= 1;
++                                      rthp = &rth->dst.rt_next;
++                                      /*
++                                       * We only count entries on
++                                       * a chain with equal hash inputs once
++                                       * so that entries for different QOS
++                                       * levels, and other non-hash input
++                                       * attributes don't unfairly skew
++                                       * the length computation
++                                       */
++                                      length += has_noalias(rt_hash_table[i].chain, rth);
++                                      continue;
++                              }
++                      } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout))
++                              goto nofree;
++
++                      /* Cleanup aged off entries. */
++                      *rthp = rth->dst.rt_next;
++                      rt_free(rth);
++              }
++              spin_unlock_bh(rt_hash_lock_addr(i));
++              sum += length;
++              sum2 += length*length;
++      }
++      if (samples) {
++              unsigned long avg = sum / samples;
++              unsigned long sd = int_sqrt(sum2 / samples - avg*avg);
++              rt_chain_length_max = max_t(unsigned long,
++                                      ip_rt_gc_elasticity,
++                                      (avg + 4*sd) >> FRACT_BITS);
++      }
++      rover = i;
++}
++
++/*
++ * rt_worker_func() is run in process context.
++ * we call rt_check_expire() to scan part of the hash table
++ */
++static void rt_worker_func(struct work_struct *work)
++{
++      rt_check_expire();
++      schedule_delayed_work(&expires_work, ip_rt_gc_interval);
++}
++
+ /*
+  * Perturbation of rt_genid by a small quantity [1..256]
+  * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
+@@ -3176,6 +3270,13 @@ static ctl_table ipv4_route_table[] = {
+               .proc_handler   = proc_dointvec_jiffies,
+       },
+       {
++              .procname       = "gc_interval",
++              .data           = &ip_rt_gc_interval,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = proc_dointvec_jiffies,
++      },
++      {
+               .procname       = "redirect_load",
+               .data           = &ip_rt_redirect_load,
+               .maxlen         = sizeof(int),
+@@ -3385,6 +3486,11 @@ int __init ip_rt_init(void)
+       devinet_init();
+       ip_fib_init();
++      INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func);
++      expires_ljiffies = jiffies;
++      schedule_delayed_work(&expires_work,
++              net_random() % ip_rt_gc_interval + ip_rt_gc_interval);
++
+       if (ip_rt_proc_init())
+               printk(KERN_ERR "Unable to create route proc files\n");
+ #ifdef CONFIG_XFRM
diff --git a/queue-3.1/ipv4-using-prefetch-requires-including-prefetch.h.patch b/queue-3.1/ipv4-using-prefetch-requires-including-prefetch.h.patch
new file mode 100644 (file)
index 0000000..1a7124b
--- /dev/null
@@ -0,0 +1,29 @@
+From 31a4e30815354c5e49eb20752409ef7c721fc6b0 Mon Sep 17 00:00:00 2001
+From: Stephen Rothwell <sfr@canb.auug.org.au>
+Date: Thu, 22 Dec 2011 17:03:29 +1100
+Subject: ipv4: using prefetch requires including prefetch.h
+
+
+From: Stephen Rothwell <sfr@canb.auug.org.au>
+
+[ Upstream commit b9eda06f80b0db61a73bd87c6b0eb67d8aca55ad ]
+
+Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
+Acked-by: David Miller <davem@davemloft.net>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv4/route.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -91,6 +91,7 @@
+ #include <linux/rcupdate.h>
+ #include <linux/times.h>
+ #include <linux/slab.h>
++#include <linux/prefetch.h>
+ #include <net/dst.h>
+ #include <net/net_namespace.h>
+ #include <net/protocol.h>
diff --git a/queue-3.1/ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch b/queue-3.1/ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch
new file mode 100644 (file)
index 0000000..085474d
--- /dev/null
@@ -0,0 +1,37 @@
+From 5790d60ca9a1775b05c26da9f392a10234fd1ac7 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Tue, 13 Dec 2011 17:35:06 -0500
+Subject: ipv6: Check dest prefix length on original route not copied one in rt6_alloc_cow().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit bb3c36863e8001fc21a88bebfdead4da4c23e848 ]
+
+After commit 8e2ec639173f325977818c45011ee176ef2b11f6 ("ipv6: don't
+use inetpeer to store metrics for routes.") the test in rt6_alloc_cow()
+for setting the ANYCAST flag is now wrong.
+
+'rt' will always now have a plen of 128, because it is set explicitly
+to 128 by ip6_rt_copy.
+
+So to restore the semantics of the test, check the destination prefix
+length of 'ort'.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv6/route.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -725,7 +725,7 @@ static struct rt6_info *rt6_alloc_cow(co
+               int attempts = !in_softirq();
+               if (!(rt->rt6i_flags&RTF_GATEWAY)) {
+-                      if (rt->rt6i_dst.plen != 128 &&
++                      if (ort->rt6i_dst.plen != 128 &&
+                           ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
+                               rt->rt6i_flags |= RTF_ANYCAST;
+                       ipv6_addr_copy(&rt->rt6i_gateway, daddr);
diff --git a/queue-3.1/llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch b/queue-3.1/llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch
new file mode 100644 (file)
index 0000000..16f3288
--- /dev/null
@@ -0,0 +1,57 @@
+From 76bcc2af1348ccf5a40421e1181f2547718a1e51 Mon Sep 17 00:00:00 2001
+From: Alex Juncu <ajuncu@ixiacom.com>
+Date: Thu, 15 Dec 2011 23:01:25 +0000
+Subject: llc: llc_cmsg_rcv was getting called after sk_eat_skb.
+
+
+From: Alex Juncu <ajuncu@ixiacom.com>
+
+[ Upstream commit 9cef310fcdee12b49b8b4c96fd8f611c8873d284 ]
+
+Received non stream protocol packets were calling llc_cmsg_rcv that used a
+skb after that skb was released by sk_eat_skb. This caused received STP
+packets to generate kernel panics.
+
+Signed-off-by: Alexandru Juncu <ajuncu@ixiacom.com>
+Signed-off-by: Kunjan Naik <knaik@ixiacom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/llc/af_llc.c |   14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/net/llc/af_llc.c
++++ b/net/llc/af_llc.c
+@@ -833,15 +833,15 @@ static int llc_ui_recvmsg(struct kiocb *
+               copied += used;
+               len -= used;
++              /* For non stream protcols we get one packet per recvmsg call */
++              if (sk->sk_type != SOCK_STREAM)
++                      goto copy_uaddr;
++
+               if (!(flags & MSG_PEEK)) {
+                       sk_eat_skb(sk, skb, 0);
+                       *seq = 0;
+               }
+-              /* For non stream protcols we get one packet per recvmsg call */
+-              if (sk->sk_type != SOCK_STREAM)
+-                      goto copy_uaddr;
+-
+               /* Partial read */
+               if (used + offset < skb->len)
+                       continue;
+@@ -857,6 +857,12 @@ copy_uaddr:
+       }
+       if (llc_sk(sk)->cmsg_flags)
+               llc_cmsg_rcv(msg, skb);
++
++      if (!(flags & MSG_PEEK)) {
++                      sk_eat_skb(sk, skb, 0);
++                      *seq = 0;
++      }
++
+       goto out;
+ }
diff --git a/queue-3.1/mqprio-avoid-panic-if-no-options-are-provided.patch b/queue-3.1/mqprio-avoid-panic-if-no-options-are-provided.patch
new file mode 100644 (file)
index 0000000..655666e
--- /dev/null
@@ -0,0 +1,32 @@
+From 5e59a51890a259701718b9328560934407176b46 Mon Sep 17 00:00:00 2001
+From: Thomas Graf <tgraf@redhat.com>
+Date: Thu, 22 Dec 2011 02:05:07 +0000
+Subject: mqprio: Avoid panic if no options are provided
+
+
+From: Thomas Graf <tgraf@redhat.com>
+
+[ Upstream commit 7838f2ce36b6ab5c13ef20b1857e3bbd567f1759 ]
+
+Userspace may not provide TCA_OPTIONS, in fact tc currently does
+so not do so if no arguments are specified on the command line.
+Return EINVAL instead of panicing.
+
+Signed-off-by: Thomas Graf <tgraf@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/sched/sch_mqprio.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sched/sch_mqprio.c
++++ b/net/sched/sch_mqprio.c
+@@ -106,7 +106,7 @@ static int mqprio_init(struct Qdisc *sch
+       if (!netif_is_multiqueue(dev))
+               return -EOPNOTSUPP;
+-      if (nla_len(opt) < sizeof(*qopt))
++      if (!opt || nla_len(opt) < sizeof(*qopt))
+               return -EINVAL;
+       qopt = nla_data(opt);
diff --git a/queue-3.1/net-add-a-flow_cache_flush_deferred-function.patch b/queue-3.1/net-add-a-flow_cache_flush_deferred-function.patch
new file mode 100644 (file)
index 0000000..f320efb
--- /dev/null
@@ -0,0 +1,105 @@
+From fe032a0d6c13f13f66f7517ca72f2d8422333401 Mon Sep 17 00:00:00 2001
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Wed, 21 Dec 2011 16:48:08 -0500
+Subject: net: Add a flow_cache_flush_deferred function
+
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit c0ed1c14a72ca9ebacd51fb94a8aca488b0d361e ]
+
+flow_cach_flush() might sleep but can be called from
+atomic context via the xfrm garbage collector. So add
+a flow_cache_flush_deferred() function and use this if
+the xfrm garbage colector is invoked from within the
+packet path.
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Acked-by: Timo Teräs <timo.teras@iki.fi>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ include/net/flow.h     |    1 +
+ net/core/flow.c        |   12 ++++++++++++
+ net/xfrm/xfrm_policy.c |   18 ++++++++++++++----
+ 3 files changed, 27 insertions(+), 4 deletions(-)
+
+--- a/include/net/flow.h
++++ b/include/net/flow.h
+@@ -207,6 +207,7 @@ extern struct flow_cache_object *flow_ca
+               u8 dir, flow_resolve_t resolver, void *ctx);
+ extern void flow_cache_flush(void);
++extern void flow_cache_flush_deferred(void);
+ extern atomic_t flow_cache_genid;
+ #endif
+--- a/net/core/flow.c
++++ b/net/core/flow.c
+@@ -358,6 +358,18 @@ void flow_cache_flush(void)
+       put_online_cpus();
+ }
++static void flow_cache_flush_task(struct work_struct *work)
++{
++      flow_cache_flush();
++}
++
++static DECLARE_WORK(flow_cache_flush_work, flow_cache_flush_task);
++
++void flow_cache_flush_deferred(void)
++{
++      schedule_work(&flow_cache_flush_work);
++}
++
+ static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu)
+ {
+       struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -2276,8 +2276,6 @@ static void __xfrm_garbage_collect(struc
+ {
+       struct dst_entry *head, *next;
+-      flow_cache_flush();
+-
+       spin_lock_bh(&xfrm_policy_sk_bundle_lock);
+       head = xfrm_policy_sk_bundles;
+       xfrm_policy_sk_bundles = NULL;
+@@ -2290,6 +2288,18 @@ static void __xfrm_garbage_collect(struc
+       }
+ }
++static void xfrm_garbage_collect(struct net *net)
++{
++      flow_cache_flush();
++      __xfrm_garbage_collect(net);
++}
++
++static void xfrm_garbage_collect_deferred(struct net *net)
++{
++      flow_cache_flush_deferred();
++      __xfrm_garbage_collect(net);
++}
++
+ static void xfrm_init_pmtu(struct dst_entry *dst)
+ {
+       do {
+@@ -2420,7 +2430,7 @@ int xfrm_policy_register_afinfo(struct x
+               if (likely(dst_ops->neigh_lookup == NULL))
+                       dst_ops->neigh_lookup = xfrm_neigh_lookup;
+               if (likely(afinfo->garbage_collect == NULL))
+-                      afinfo->garbage_collect = __xfrm_garbage_collect;
++                      afinfo->garbage_collect = xfrm_garbage_collect_deferred;
+               xfrm_policy_afinfo[afinfo->family] = afinfo;
+       }
+       write_unlock_bh(&xfrm_policy_afinfo_lock);
+@@ -2514,7 +2524,7 @@ static int xfrm_dev_event(struct notifie
+       switch (event) {
+       case NETDEV_DOWN:
+-              __xfrm_garbage_collect(dev_net(dev));
++              xfrm_garbage_collect(dev_net(dev));
+       }
+       return NOTIFY_DONE;
+ }
diff --git a/queue-3.1/net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch b/queue-3.1/net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch
new file mode 100644 (file)
index 0000000..9b3d69a
--- /dev/null
@@ -0,0 +1,37 @@
+From c9443fa522619b70cc9ea12d7f58e4cf633500c3 Mon Sep 17 00:00:00 2001
+From: Markus Kötter <nepenthesdev@gmail.com>
+Date: Sat, 17 Dec 2011 11:39:08 +0000
+Subject: net: bpf_jit: fix an off-one bug in x86_64 cond jump target
+
+
+From: Markus Kötter <nepenthesdev@gmail.com>
+
+[ Upstream commit a03ffcf873fe0f2565386ca8ef832144c42e67fa ]
+
+x86 jump instruction size is 2 or 5 bytes (near/long jump), not 2 or 6
+bytes.
+
+In case a conditional jump is followed by a long jump, conditional jump
+target is one byte past the start of target instruction.
+
+Signed-off-by: Markus Kötter <nepenthesdev@gmail.com>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/net/bpf_jit_comp.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -568,8 +568,8 @@ cond_branch:                       f_offset = addrs[i + filt
+                                       break;
+                               }
+                               if (filter[i].jt != 0) {
+-                                      if (filter[i].jf)
+-                                              t_offset += is_near(f_offset) ? 2 : 6;
++                                      if (filter[i].jf && f_offset)
++                                              t_offset += is_near(f_offset) ? 2 : 5;
+                                       EMIT_COND_JMP(t_op, t_offset);
+                                       if (filter[i].jf)
+                                               EMIT_JMP(f_offset);
diff --git a/queue-3.1/net-have-ipconfig-not-wait-if-no-dev-is-available.patch b/queue-3.1/net-have-ipconfig-not-wait-if-no-dev-is-available.patch
new file mode 100644 (file)
index 0000000..f1adb9c
--- /dev/null
@@ -0,0 +1,40 @@
+From 2ec3264c7298c2326f33c482e787ec449638ed85 Mon Sep 17 00:00:00 2001
+From: Gerlando Falauto <gerlando.falauto@keymile.com>
+Date: Mon, 19 Dec 2011 22:58:04 +0000
+Subject: net: have ipconfig not wait if no dev is available
+
+
+From: Gerlando Falauto <gerlando.falauto@keymile.com>
+
+[ Upstream commit cd7816d14953c8af910af5bb92f488b0b277e29d ]
+
+previous commit 3fb72f1e6e6165c5f495e8dc11c5bbd14c73385c
+makes IP-Config wait for carrier on at least one network device.
+
+Before waiting (predefined value 120s), check that at least one device
+was successfully brought up. Otherwise (e.g. buggy bootloader
+which does not set the MAC address) there is no point in waiting
+for carrier.
+
+Cc: Micha Nelissen <micha@neli.hopto.org>
+Cc: Holger Brunck <holger.brunck@keymile.com>
+Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv4/ipconfig.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/ipv4/ipconfig.c
++++ b/net/ipv4/ipconfig.c
+@@ -252,6 +252,10 @@ static int __init ic_open_devs(void)
+               }
+       }
++      /* no point in waiting if we could not bring up at least one device */
++      if (!ic_first_dev)
++              goto have_carrier;
++
+       /* wait for a carrier on at least one device */
+       start = jiffies;
+       while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) {
diff --git a/queue-3.1/net-introduce-dst_nopeer-dst-flag.patch b/queue-3.1/net-introduce-dst_nopeer-dst-flag.patch
new file mode 100644 (file)
index 0000000..c79f692
--- /dev/null
@@ -0,0 +1,129 @@
+From 214c4df6cf051ae163659e2b9e5ee200eed06688 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Thu, 22 Dec 2011 04:15:53 +0000
+Subject: net: introduce DST_NOPEER dst flag
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit e688a604807647c9450f9c12a7cb6d027150a895 ]
+
+Chris Boot reported crashes occurring in ipv6_select_ident().
+
+[  461.457562] RIP: 0010:[<ffffffff812dde61>]  [<ffffffff812dde61>]
+ipv6_select_ident+0x31/0xa7
+
+[  461.578229] Call Trace:
+[  461.580742] <IRQ>
+[  461.582870]  [<ffffffff812efa7f>] ? udp6_ufo_fragment+0x124/0x1a2
+[  461.589054]  [<ffffffff812dbfe0>] ? ipv6_gso_segment+0xc0/0x155
+[  461.595140]  [<ffffffff812700c6>] ? skb_gso_segment+0x208/0x28b
+[  461.601198]  [<ffffffffa03f236b>] ? ipv6_confirm+0x146/0x15e
+[nf_conntrack_ipv6]
+[  461.608786]  [<ffffffff81291c4d>] ? nf_iterate+0x41/0x77
+[  461.614227]  [<ffffffff81271d64>] ? dev_hard_start_xmit+0x357/0x543
+[  461.620659]  [<ffffffff81291cf6>] ? nf_hook_slow+0x73/0x111
+[  461.626440]  [<ffffffffa0379745>] ? br_parse_ip_options+0x19a/0x19a
+[bridge]
+[  461.633581]  [<ffffffff812722ff>] ? dev_queue_xmit+0x3af/0x459
+[  461.639577]  [<ffffffffa03747d2>] ? br_dev_queue_push_xmit+0x72/0x76
+[bridge]
+[  461.646887]  [<ffffffffa03791e3>] ? br_nf_post_routing+0x17d/0x18f
+[bridge]
+[  461.653997]  [<ffffffff81291c4d>] ? nf_iterate+0x41/0x77
+[  461.659473]  [<ffffffffa0374760>] ? br_flood+0xfa/0xfa [bridge]
+[  461.665485]  [<ffffffff81291cf6>] ? nf_hook_slow+0x73/0x111
+[  461.671234]  [<ffffffffa0374760>] ? br_flood+0xfa/0xfa [bridge]
+[  461.677299]  [<ffffffffa0379215>] ?
+nf_bridge_update_protocol+0x20/0x20 [bridge]
+[  461.684891]  [<ffffffffa03bb0e5>] ? nf_ct_zone+0xa/0x17 [nf_conntrack]
+[  461.691520]  [<ffffffffa0374760>] ? br_flood+0xfa/0xfa [bridge]
+[  461.697572]  [<ffffffffa0374812>] ? NF_HOOK.constprop.8+0x3c/0x56
+[bridge]
+[  461.704616]  [<ffffffffa0379031>] ?
+nf_bridge_push_encap_header+0x1c/0x26 [bridge]
+[  461.712329]  [<ffffffffa037929f>] ? br_nf_forward_finish+0x8a/0x95
+[bridge]
+[  461.719490]  [<ffffffffa037900a>] ?
+nf_bridge_pull_encap_header+0x1c/0x27 [bridge]
+[  461.727223]  [<ffffffffa0379974>] ? br_nf_forward_ip+0x1c0/0x1d4 [bridge]
+[  461.734292]  [<ffffffff81291c4d>] ? nf_iterate+0x41/0x77
+[  461.739758]  [<ffffffffa03748cc>] ? __br_deliver+0xa0/0xa0 [bridge]
+[  461.746203]  [<ffffffff81291cf6>] ? nf_hook_slow+0x73/0x111
+[  461.751950]  [<ffffffffa03748cc>] ? __br_deliver+0xa0/0xa0 [bridge]
+[  461.758378]  [<ffffffffa037533a>] ? NF_HOOK.constprop.4+0x56/0x56
+[bridge]
+
+This is caused by bridge netfilter special dst_entry (fake_rtable), a
+special shared entry, where attaching an inetpeer makes no sense.
+
+Problem is present since commit 87c48fa3b46 (ipv6: make fragment
+identifications less predictable)
+
+Introduce DST_NOPEER dst flag and make sure ipv6_select_ident() and
+__ip_select_ident() fallback to the 'no peer attached' handling.
+
+Reported-by: Chris Boot <bootc@bootc.net>
+Tested-by: Chris Boot <bootc@bootc.net>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ include/net/dst.h         |    1 +
+ net/bridge/br_netfilter.c |    2 +-
+ net/ipv4/route.c          |    4 ++--
+ net/ipv6/ip6_output.c     |    2 +-
+ 4 files changed, 5 insertions(+), 4 deletions(-)
+
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -53,6 +53,7 @@ struct dst_entry {
+ #define DST_NOHASH            0x0008
+ #define DST_NOCACHE           0x0010
+ #define DST_NOCOUNT           0x0020
++#define DST_NOPEER            0x0040
+       short                   error;
+       short                   obsolete;
+--- a/net/bridge/br_netfilter.c
++++ b/net/bridge/br_netfilter.c
+@@ -141,7 +141,7 @@ void br_netfilter_rtable_init(struct net
+       rt->dst.dev = br->dev;
+       rt->dst.path = &rt->dst;
+       dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
+-      rt->dst.flags   = DST_NOXFRM;
++      rt->dst.flags   = DST_NOXFRM | DST_NOPEER;
+       rt->dst.ops = &fake_dst_ops;
+ }
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1272,7 +1272,7 @@ void __ip_select_ident(struct iphdr *iph
+ {
+       struct rtable *rt = (struct rtable *) dst;
+-      if (rt) {
++      if (rt && !(rt->dst.flags & DST_NOPEER)) {
+               if (rt->peer == NULL)
+                       rt_bind_peer(rt, rt->rt_dst, 1);
+@@ -1283,7 +1283,7 @@ void __ip_select_ident(struct iphdr *iph
+                       iph->id = htons(inet_getid(rt->peer, more));
+                       return;
+               }
+-      } else
++      } else if (!rt)
+               printk(KERN_DEBUG "rt_bind_peer(0) @%p\n",
+                      __builtin_return_address(0));
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -606,7 +606,7 @@ void ipv6_select_ident(struct frag_hdr *
+       static atomic_t ipv6_fragmentation_id;
+       int old, new;
+-      if (rt) {
++      if (rt && !(rt->dst.flags & DST_NOPEER)) {
+               struct inet_peer *peer;
+               if (!rt->rt6i_peer)
diff --git a/queue-3.1/ppp-fix-pptp-double-release_sock-in-pptp_bind.patch b/queue-3.1/ppp-fix-pptp-double-release_sock-in-pptp_bind.patch
new file mode 100644 (file)
index 0000000..8f19e5b
--- /dev/null
@@ -0,0 +1,32 @@
+From 884aad5cf67fed3cc15003dbb9c8cdf9b6833b57 Mon Sep 17 00:00:00 2001
+From: Djalal Harouni <tixxdz@opendz.org>
+Date: Tue, 6 Dec 2011 15:47:12 +0000
+Subject: ppp: fix pptp double release_sock in pptp_bind()
+
+
+From: Djalal Harouni <tixxdz@opendz.org>
+
+[ Upstream commit a454daceb78844a09c08b6e2d8badcb76a5d73b9 ]
+
+Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
+Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/net/pptp.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/net/pptp.c
++++ b/drivers/net/pptp.c
+@@ -423,10 +423,8 @@ static int pptp_bind(struct socket *sock
+       lock_sock(sk);
+       opt->src_addr = sp->sa_addr.pptp;
+-      if (add_chan(po)) {
+-              release_sock(sk);
++      if (add_chan(po))
+               error = -EBUSY;
+-      }
+       release_sock(sk);
+       return error;
diff --git a/queue-3.1/sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch b/queue-3.1/sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch
new file mode 100644 (file)
index 0000000..e65ef49
--- /dev/null
@@ -0,0 +1,36 @@
+From 8c7968a17315bcfa4b907334a35675129d84025f Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Sun, 11 Dec 2011 23:42:53 +0000
+Subject: sch_gred: should not use GFP_KERNEL while holding a spinlock
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit 3f1e6d3fd37bd4f25e5b19f1c7ca21850426c33f ]
+
+gred_change_vq() is called under sch_tree_lock(sch).
+
+This means a spinlock is held, and we are not allowed to sleep in this
+context.
+
+We might pre-allocate memory using GFP_KERNEL before taking spinlock,
+but this is not suitable for stable material.
+
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/sched/sch_gred.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -385,7 +385,7 @@ static inline int gred_change_vq(struct
+       struct gred_sched_data *q;
+       if (table->tab[dp] == NULL) {
+-              table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL);
++              table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC);
+               if (table->tab[dp] == NULL)
+                       return -ENOMEM;
+       }
diff --git a/queue-3.1/sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch b/queue-3.1/sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch
new file mode 100644 (file)
index 0000000..665021d
--- /dev/null
@@ -0,0 +1,97 @@
+From 094b242b70f67ac3996934432f0a0d564e791cf6 Mon Sep 17 00:00:00 2001
+From: Thomas Graf <tgraf@redhat.com>
+Date: Mon, 19 Dec 2011 04:11:40 +0000
+Subject: sctp: Do not account for sizeof(struct sk_buff) in estimated rwnd
+
+
+From: Thomas Graf <tgraf@redhat.com>
+
+[ Upstream commit a76c0adf60f6ca5ff3481992e4ea0383776b24d2 ]
+
+When checking whether a DATA chunk fits into the estimated rwnd a
+full sizeof(struct sk_buff) is added to the needed chunk size. This
+quickly exhausts the available rwnd space and leads to packets being
+sent which are much below the PMTU limit. This can lead to much worse
+performance.
+
+The reason for this behaviour was to avoid putting too much memory
+pressure on the receiver. The concept is not completely irational
+because a Linux receiver does in fact clone an skb for each DATA chunk
+delivered. However, Linux also reserves half the available socket
+buffer space for data structures therefore usage of it is already
+accounted for.
+
+When proposing to change this the last time it was noted that this
+behaviour was introduced to solve a performance issue caused by rwnd
+overusage in combination with small DATA chunks.
+
+Trying to reproduce this I found that with the sk_buff overhead removed,
+the performance would improve significantly unless socket buffer limits
+are increased.
+
+The following numbers have been gathered using a patched iperf
+supporting SCTP over a live 1 Gbit ethernet network. The -l option
+was used to limit DATA chunk sizes. The numbers listed are based on
+the average of 3 test runs each. Default values have been used for
+sk_(r|w)mem.
+
+Chunk
+Size    Unpatched     No Overhead
+-------------------------------------
+   4    15.2 Kbit [!]   12.2 Mbit [!]
+   8    35.8 Kbit [!]   26.0 Mbit [!]
+  16    95.5 Kbit [!]   54.4 Mbit [!]
+  32   106.7 Mbit      102.3 Mbit
+  64   189.2 Mbit      188.3 Mbit
+ 128   331.2 Mbit      334.8 Mbit
+ 256   537.7 Mbit      536.0 Mbit
+ 512   766.9 Mbit      766.6 Mbit
+1024   810.1 Mbit      808.6 Mbit
+
+Signed-off-by: Thomas Graf <tgraf@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/sctp/output.c   |    8 +-------
+ net/sctp/outqueue.c |    6 ++----
+ 2 files changed, 3 insertions(+), 11 deletions(-)
+
+--- a/net/sctp/output.c
++++ b/net/sctp/output.c
+@@ -697,13 +697,7 @@ static void sctp_packet_append_data(stru
+       /* Keep track of how many bytes are in flight to the receiver. */
+       asoc->outqueue.outstanding_bytes += datasize;
+-      /* Update our view of the receiver's rwnd. Include sk_buff overhead
+-       * while updating peer.rwnd so that it reduces the chances of a
+-       * receiver running out of receive buffer space even when receive
+-       * window is still open. This can happen when a sender is sending
+-       * sending small messages.
+-       */
+-      datasize += sizeof(struct sk_buff);
++      /* Update our view of the receiver's rwnd. */
+       if (datasize < rwnd)
+               rwnd -= datasize;
+       else
+--- a/net/sctp/outqueue.c
++++ b/net/sctp/outqueue.c
+@@ -411,8 +411,7 @@ void sctp_retransmit_mark(struct sctp_ou
+                                       chunk->transport->flight_size -=
+                                                       sctp_data_size(chunk);
+                               q->outstanding_bytes -= sctp_data_size(chunk);
+-                              q->asoc->peer.rwnd += (sctp_data_size(chunk) +
+-                                                      sizeof(struct sk_buff));
++                              q->asoc->peer.rwnd += sctp_data_size(chunk);
+                       }
+                       continue;
+               }
+@@ -432,8 +431,7 @@ void sctp_retransmit_mark(struct sctp_ou
+                        * (Section 7.2.4)), add the data size of those
+                        * chunks to the rwnd.
+                        */
+-                      q->asoc->peer.rwnd += (sctp_data_size(chunk) +
+-                                              sizeof(struct sk_buff));
++                      q->asoc->peer.rwnd += sctp_data_size(chunk);
+                       q->outstanding_bytes -= sctp_data_size(chunk);
+                       if (chunk->transport)
+                               transport->flight_size -= sctp_data_size(chunk);
diff --git a/queue-3.1/sctp-fix-incorrect-overflow-check-on-autoclose.patch b/queue-3.1/sctp-fix-incorrect-overflow-check-on-autoclose.patch
new file mode 100644 (file)
index 0000000..f7fbcfd
--- /dev/null
@@ -0,0 +1,121 @@
+From 4dff6c35f9ff1cf62dd4435517adae40a3dd2d8a Mon Sep 17 00:00:00 2001
+From: Xi Wang <xi.wang@gmail.com>
+Date: Fri, 16 Dec 2011 12:44:15 +0000
+Subject: sctp: fix incorrect overflow check on autoclose
+
+
+From: Xi Wang <xi.wang@gmail.com>
+
+[ Upstream commit 2692ba61a82203404abd7dd2a027bda962861f74 ]
+
+Commit 8ffd3208 voids the previous patches f6778aab and 810c0719 for
+limiting the autoclose value.  If userspace passes in -1 on 32-bit
+platform, the overflow check didn't work and autoclose would be set
+to 0xffffffff.
+
+This patch defines a max_autoclose (in seconds) for limiting the value
+and exposes it through sysctl, with the following intentions.
+
+1) Avoid overflowing autoclose * HZ.
+
+2) Keep the default autoclose bound consistent across 32- and 64-bit
+   platforms (INT_MAX / HZ in this patch).
+
+3) Keep the autoclose value consistent between setsockopt() and
+   getsockopt() calls.
+
+Suggested-by: Vlad Yasevich <vladislav.yasevich@hp.com>
+Signed-off-by: Xi Wang <xi.wang@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ include/net/sctp/structs.h |    4 ++++
+ net/sctp/associola.c       |    2 +-
+ net/sctp/protocol.c        |    3 +++
+ net/sctp/socket.c          |    2 --
+ net/sctp/sysctl.c          |   13 +++++++++++++
+ 5 files changed, 21 insertions(+), 3 deletions(-)
+
+--- a/include/net/sctp/structs.h
++++ b/include/net/sctp/structs.h
+@@ -241,6 +241,9 @@ extern struct sctp_globals {
+        * bits is an indicator of when to send and window update SACK.
+        */
+       int rwnd_update_shift;
++
++      /* Threshold for autoclose timeout, in seconds. */
++      unsigned long max_autoclose;
+ } sctp_globals;
+ #define sctp_rto_initial              (sctp_globals.rto_initial)
+@@ -281,6 +284,7 @@ extern struct sctp_globals {
+ #define sctp_auth_enable              (sctp_globals.auth_enable)
+ #define sctp_checksum_disable         (sctp_globals.checksum_disable)
+ #define sctp_rwnd_upd_shift           (sctp_globals.rwnd_update_shift)
++#define sctp_max_autoclose            (sctp_globals.max_autoclose)
+ /* SCTP Socket type: UDP or TCP style. */
+ typedef enum {
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -173,7 +173,7 @@ static struct sctp_association *sctp_ass
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
+-              (unsigned long)sp->autoclose * HZ;
++              min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ;
+       /* Initializes the timers */
+       for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -1285,6 +1285,9 @@ SCTP_STATIC __init int sctp_init(void)
+       sctp_max_instreams              = SCTP_DEFAULT_INSTREAMS;
+       sctp_max_outstreams             = SCTP_DEFAULT_OUTSTREAMS;
++      /* Initialize maximum autoclose timeout. */
++      sctp_max_autoclose              = INT_MAX / HZ;
++
+       /* Initialize handle used for association ids. */
+       idr_init(&sctp_assocs_id);
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -2199,8 +2199,6 @@ static int sctp_setsockopt_autoclose(str
+               return -EINVAL;
+       if (copy_from_user(&sp->autoclose, optval, optlen))
+               return -EFAULT;
+-      /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */
+-      sp->autoclose = min_t(long, sp->autoclose, MAX_SCHEDULE_TIMEOUT / HZ);
+       return 0;
+ }
+--- a/net/sctp/sysctl.c
++++ b/net/sctp/sysctl.c
+@@ -53,6 +53,10 @@ static int sack_timer_min = 1;
+ static int sack_timer_max = 500;
+ static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
+ static int rwnd_scale_max = 16;
++static unsigned long max_autoclose_min = 0;
++static unsigned long max_autoclose_max =
++      (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX)
++      ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ;
+ extern long sysctl_sctp_mem[3];
+ extern int sysctl_sctp_rmem[3];
+@@ -258,6 +262,15 @@ static ctl_table sctp_table[] = {
+               .extra1         = &one,
+               .extra2         = &rwnd_scale_max,
+       },
++      {
++              .procname       = "max_autoclose",
++              .data           = &sctp_max_autoclose,
++              .maxlen         = sizeof(unsigned long),
++              .mode           = 0644,
++              .proc_handler   = &proc_doulongvec_minmax,
++              .extra1         = &max_autoclose_min,
++              .extra2         = &max_autoclose_max,
++      },
+       { /* sentinel */ }
+ };
index f8a114c76d4c777fa966635d6bdb4f4798f34bb3..692017a6f313d5d28c6e1b9acf7f00ac8ef009ff 100644 (file)
@@ -48,3 +48,26 @@ drm-radeon-kms-bail-on-btc-parts-if-mc-ucode-is-missing.patch
 mm-hugetlb-fix-non-atomic-enqueue-of-huge-page.patch
 mm-mempolicy.c-refix-mbind_range-vma-issue.patch
 mpt2sas-crashes-on-shutdown.patch
+sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
+sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
+sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
+sparc-kill-custom-io_remap_pfn_range.patch
+sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
+sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
+sparc32-correct-the-return-value-of-memcpy.patch
+sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
+sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
+net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch
+ppp-fix-pptp-double-release_sock-in-pptp_bind.patch
+llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch
+mqprio-avoid-panic-if-no-options-are-provided.patch
+net-have-ipconfig-not-wait-if-no-dev-is-available.patch
+sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch
+sctp-fix-incorrect-overflow-check-on-autoclose.patch
+sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch
+net-add-a-flow_cache_flush_deferred-function.patch
+ipv4-flush-route-cache-after-change-accept_local.patch
+ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch
+net-introduce-dst_nopeer-dst-flag.patch
+ipv4-reintroduce-route-cache-garbage-collector.patch
+ipv4-using-prefetch-requires-including-prefetch.h.patch
diff --git a/queue-3.1/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch b/queue-3.1/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
new file mode 100644 (file)
index 0000000..4f5b047
--- /dev/null
@@ -0,0 +1,179 @@
+From b167cbdeb37906bc30c1a618202e43373f96d09a Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Mon, 26 Dec 2011 12:30:13 -0500
+Subject: sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ A combination of upstream commits 1d299bc7732c34d85bd43ac1a8745f5a2fed2078 and
+  e88d2468718b0789b4c33da2f7e1cef2a1eee279 ]
+
+Although we provide a proper way for a debugger to control whether
+syscall restart occurs, we run into problems because orig_i0 is not
+saved and restored properly.
+
+Luckily we can solve this problem without having to make debuggers
+aware of the issue.  Across system calls, several registers are
+considered volatile and can be safely clobbered.
+
+Therefore we use the pt_regs save area of one of those registers, %g6,
+as a place to save and restore orig_i0.
+
+Debuggers transparently will do the right thing because they save and
+restore this register already.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/signal32.c  |   18 ++++++++++--------
+ arch/sparc/kernel/signal_32.c |   30 +++++++++++++++++++++++++-----
+ arch/sparc/kernel/signal_64.c |   42 ++++++++++++++++++++++++++++--------------
+ 3 files changed, 63 insertions(+), 27 deletions(-)
+
+--- a/arch/sparc/kernel/signal32.c
++++ b/arch/sparc/kernel/signal32.c
+@@ -822,21 +822,23 @@ static inline void syscall_restart32(uns
+  * want to handle. Thus you cannot kill init even with a SIGKILL even by
+  * mistake.
+  */
+-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+-               int restart_syscall, unsigned long orig_i0)
++void do_signal32(sigset_t *oldset, struct pt_regs * regs)
+ {
+       struct k_sigaction ka;
++      unsigned long orig_i0;
++      int restart_syscall;
+       siginfo_t info;
+       int signr;
+       
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+-      /* If the debugger messes with the program counter, it clears
+-       * the "in syscall" bit, directing us to not perform a syscall
+-       * restart.
+-       */
+-      if (restart_syscall && !pt_regs_is_syscall(regs))
+-              restart_syscall = 0;
++      restart_syscall = 0;
++      orig_i0 = 0;
++      if (pt_regs_is_syscall(regs) &&
++          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
++              restart_syscall = 1;
++              orig_i0 = regs->u_regs[UREG_G6];
++      }
+       if (signr > 0) {
+               if (restart_syscall)
+--- a/arch/sparc/kernel/signal_32.c
++++ b/arch/sparc/kernel/signal_32.c
+@@ -519,10 +519,26 @@ static void do_signal(struct pt_regs *re
+       siginfo_t info;
+       int signr;
++      /* It's a lot of work and synchronization to add a new ptrace
++       * register for GDB to save and restore in order to get
++       * orig_i0 correct for syscall restarts when debugging.
++       *
++       * Although it should be the case that most of the global
++       * registers are volatile across a system call, glibc already
++       * depends upon that fact that we preserve them.  So we can't
++       * just use any global register to save away the orig_i0 value.
++       *
++       * In particular %g2, %g3, %g4, and %g5 are all assumed to be
++       * preserved across a system call trap by various pieces of
++       * code in glibc.
++       *
++       * %g7 is used as the "thread register".   %g6 is not used in
++       * any fixed manner.  %g6 is used as a scratch register and
++       * a compiler temporary, but it's value is never used across
++       * a system call.  Therefore %g6 is usable for orig_i0 storage.
++       */
+       if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
+-              restart_syscall = 1;
+-      else
+-              restart_syscall = 0;
++              regs->u_regs[UREG_G6] = orig_i0;
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+@@ -535,8 +551,12 @@ static void do_signal(struct pt_regs *re
+        * the software "in syscall" bit, directing us to not perform
+        * a syscall restart.
+        */
+-      if (restart_syscall && !pt_regs_is_syscall(regs))
+-              restart_syscall = 0;
++      restart_syscall = 0;
++      if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
++              restart_syscall = 1;
++              orig_i0 = regs->u_regs[UREG_G6];
++      }
++
+       if (signr > 0) {
+               if (restart_syscall)
+--- a/arch/sparc/kernel/signal_64.c
++++ b/arch/sparc/kernel/signal_64.c
+@@ -529,11 +529,27 @@ static void do_signal(struct pt_regs *re
+       siginfo_t info;
+       int signr;
+       
++      /* It's a lot of work and synchronization to add a new ptrace
++       * register for GDB to save and restore in order to get
++       * orig_i0 correct for syscall restarts when debugging.
++       *
++       * Although it should be the case that most of the global
++       * registers are volatile across a system call, glibc already
++       * depends upon that fact that we preserve them.  So we can't
++       * just use any global register to save away the orig_i0 value.
++       *
++       * In particular %g2, %g3, %g4, and %g5 are all assumed to be
++       * preserved across a system call trap by various pieces of
++       * code in glibc.
++       *
++       * %g7 is used as the "thread register".   %g6 is not used in
++       * any fixed manner.  %g6 is used as a scratch register and
++       * a compiler temporary, but it's value is never used across
++       * a system call.  Therefore %g6 is usable for orig_i0 storage.
++       */
+       if (pt_regs_is_syscall(regs) &&
+-          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+-              restart_syscall = 1;
+-      } else
+-              restart_syscall = 0;
++          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
++              regs->u_regs[UREG_G6] = orig_i0;
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+               oldset = &current->saved_sigmask;
+@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *re
+ #ifdef CONFIG_COMPAT
+       if (test_thread_flag(TIF_32BIT)) {
+-              extern void do_signal32(sigset_t *, struct pt_regs *,
+-                                      int restart_syscall,
+-                                      unsigned long orig_i0);
+-              do_signal32(oldset, regs, restart_syscall, orig_i0);
++              extern void do_signal32(sigset_t *, struct pt_regs *);
++              do_signal32(oldset, regs);
+               return;
+       }
+ #endif        
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+-      /* If the debugger messes with the program counter, it clears
+-       * the software "in syscall" bit, directing us to not perform
+-       * a syscall restart.
+-       */
+-      if (restart_syscall && !pt_regs_is_syscall(regs))
+-              restart_syscall = 0;
++      restart_syscall = 0;
++      if (pt_regs_is_syscall(regs) &&
++          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
++              restart_syscall = 1;
++              orig_i0 = regs->u_regs[UREG_G6];
++      }
+       if (signr > 0) {
+               if (restart_syscall)
diff --git a/queue-3.1/sparc-kill-custom-io_remap_pfn_range.patch b/queue-3.1/sparc-kill-custom-io_remap_pfn_range.patch
new file mode 100644 (file)
index 0000000..953c209
--- /dev/null
@@ -0,0 +1,375 @@
+From 14e707a033b1266711adacb4629e7548e31a38e2 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 17 Nov 2011 18:17:59 -0800
+Subject: sparc: Kill custom io_remap_pfn_range().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 3e37fd3153ac95088a74f5e7c569f7567e9f993a ]
+
+To handle the large physical addresses, just make a simple wrapper
+around remap_pfn_range() like MIPS does.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/include/asm/pgtable_32.h |   20 +++-
+ arch/sparc/include/asm/pgtable_64.h |   20 +++-
+ arch/sparc/mm/Makefile              |    1 
+ arch/sparc/mm/generic_32.c          |   98 ---------------------
+ arch/sparc/mm/generic_64.c          |  164 ------------------------------------
+ 5 files changed, 32 insertions(+), 271 deletions(-)
+ delete mode 100644 arch/sparc/mm/generic_32.c
+ delete mode 100644 arch/sparc/mm/generic_64.c
+
+--- a/arch/sparc/include/asm/pgtable_32.h
++++ b/arch/sparc/include/asm/pgtable_32.h
+@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_b
+ #define kern_addr_valid(addr) \
+       (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
+-extern int io_remap_pfn_range(struct vm_area_struct *vma,
+-                            unsigned long from, unsigned long pfn,
+-                            unsigned long size, pgprot_t prot);
+-
+ /*
+  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+  * its high 4 bits.  These macros/functions put it there or get it from there.
+@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_
+ #define GET_IOSPACE(pfn)              (pfn >> (BITS_PER_LONG - 4))
+ #define GET_PFN(pfn)                  (pfn & 0x0fffffffUL)
++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
++                         unsigned long, pgprot_t);
++
++static inline int io_remap_pfn_range(struct vm_area_struct *vma,
++                                   unsigned long from, unsigned long pfn,
++                                   unsigned long size, pgprot_t prot)
++{
++      unsigned long long offset, space, phys_base;
++
++      offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
++      space = GET_IOSPACE(pfn);
++      phys_base = offset | (space << 32ULL);
++
++      return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
++}
++
+ #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+ ({                                                                      \
+--- a/arch/sparc/include/asm/pgtable_64.h
++++ b/arch/sparc/include/asm/pgtable_64.h
+@@ -757,10 +757,6 @@ static inline bool kern_addr_valid(unsig
+ extern int page_in_phys_avail(unsigned long paddr);
+-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+-                             unsigned long pfn,
+-                             unsigned long size, pgprot_t prot);
+-
+ /*
+  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+  * its high 4 bits.  These macros/functions put it there or get it from there.
+@@ -769,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_
+ #define GET_IOSPACE(pfn)              (pfn >> (BITS_PER_LONG - 4))
+ #define GET_PFN(pfn)                  (pfn & 0x0fffffffffffffffUL)
++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
++                         unsigned long, pgprot_t);
++
++static inline int io_remap_pfn_range(struct vm_area_struct *vma,
++                                   unsigned long from, unsigned long pfn,
++                                   unsigned long size, pgprot_t prot)
++{
++      unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
++      int space = GET_IOSPACE(pfn);
++      unsigned long phys_base;
++
++      phys_base = offset | (((unsigned long) space) << 32UL);
++
++      return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
++}
++
+ #include <asm-generic/pgtable.h>
+ /* We provide our own get_unmapped_area to cope with VA holes and
+--- a/arch/sparc/mm/Makefile
++++ b/arch/sparc/mm/Makefile
+@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64)   += ultra.o tlb.o
+ obj-y                   += fault_$(BITS).o
+ obj-y                   += init_$(BITS).o
+ obj-$(CONFIG_SPARC32)   += loadmmu.o
+-obj-y                   += generic_$(BITS).o
+ obj-$(CONFIG_SPARC32)   += extable.o btfixup.o srmmu.o iommu.o io-unit.o
+ obj-$(CONFIG_SPARC32)   += hypersparc.o viking.o tsunami.o swift.o
+ obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
+--- a/arch/sparc/mm/generic_32.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/*
+- * generic.c: Generic Sparc mm routines that are not dependent upon
+- *            MMU type but are Sparc specific.
+- *
+- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/pagemap.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/cacheflush.h>
+-#include <asm/tlbflush.h>
+-
+-/* Remap IO memory, the same way as remap_pfn_range(), but use
+- * the obio memory space.
+- *
+- * They use a pgprot that sets PAGE_IO and does not check the
+- * mem_map table as this is independent of normal memory.
+- */
+-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PMD_MASK;
+-      end = address + size;
+-      if (end > PMD_SIZE)
+-              end = PMD_SIZE;
+-      do {
+-              set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
+-              address += PAGE_SIZE;
+-              offset += PAGE_SIZE;
+-              pte++;
+-      } while (address < end);
+-}
+-
+-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PGDIR_MASK;
+-      end = address + size;
+-      if (end > PGDIR_SIZE)
+-              end = PGDIR_SIZE;
+-      offset -= address;
+-      do {
+-              pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
+-              if (!pte)
+-                      return -ENOMEM;
+-              io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
+-              address = (address + PMD_SIZE) & PMD_MASK;
+-              pmd++;
+-      } while (address < end);
+-      return 0;
+-}
+-
+-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+-                     unsigned long pfn, unsigned long size, pgprot_t prot)
+-{
+-      int error = 0;
+-      pgd_t * dir;
+-      unsigned long beg = from;
+-      unsigned long end = from + size;
+-      struct mm_struct *mm = vma->vm_mm;
+-      int space = GET_IOSPACE(pfn);
+-      unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+-
+-      /* See comment in mm/memory.c remap_pfn_range */
+-      vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+-      vma->vm_pgoff = (offset >> PAGE_SHIFT) |
+-              ((unsigned long)space << 28UL);
+-
+-      offset -= from;
+-      dir = pgd_offset(mm, from);
+-      flush_cache_range(vma, beg, end);
+-
+-      while (from < end) {
+-              pmd_t *pmd = pmd_alloc(mm, dir, from);
+-              error = -ENOMEM;
+-              if (!pmd)
+-                      break;
+-              error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
+-              if (error)
+-                      break;
+-              from = (from + PGDIR_SIZE) & PGDIR_MASK;
+-              dir++;
+-      }
+-
+-      flush_tlb_range(vma, beg, end);
+-      return error;
+-}
+-EXPORT_SYMBOL(io_remap_pfn_range);
+--- a/arch/sparc/mm/generic_64.c
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- * generic.c: Generic Sparc mm routines that are not dependent upon
+- *            MMU type but are Sparc specific.
+- *
+- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/pagemap.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/tlbflush.h>
+-
+-/* Remap IO memory, the same way as remap_pfn_range(), but use
+- * the obio memory space.
+- *
+- * They use a pgprot that sets PAGE_IO and does not check the
+- * mem_map table as this is independent of normal memory.
+- */
+-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
+-                                    unsigned long address,
+-                                    unsigned long size,
+-                                    unsigned long offset, pgprot_t prot,
+-                                    int space)
+-{
+-      unsigned long end;
+-
+-      /* clear hack bit that was used as a write_combine side-effect flag */
+-      offset &= ~0x1UL;
+-      address &= ~PMD_MASK;
+-      end = address + size;
+-      if (end > PMD_SIZE)
+-              end = PMD_SIZE;
+-      do {
+-              pte_t entry;
+-              unsigned long curend = address + PAGE_SIZE;
+-              
+-              entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
+-              if (!(address & 0xffff)) {
+-                      if (PAGE_SIZE < (4 * 1024 * 1024) &&
+-                          !(address & 0x3fffff) &&
+-                          !(offset & 0x3ffffe) &&
+-                          end >= address + 0x400000) {
+-                              entry = mk_pte_io(offset, prot, space,
+-                                                4 * 1024 * 1024);
+-                              curend = address + 0x400000;
+-                              offset += 0x400000;
+-                      } else if (PAGE_SIZE < (512 * 1024) &&
+-                                 !(address & 0x7ffff) &&
+-                                 !(offset & 0x7fffe) &&
+-                                 end >= address + 0x80000) {
+-                              entry = mk_pte_io(offset, prot, space,
+-                                                512 * 1024 * 1024);
+-                              curend = address + 0x80000;
+-                              offset += 0x80000;
+-                      } else if (PAGE_SIZE < (64 * 1024) &&
+-                                 !(offset & 0xfffe) &&
+-                                 end >= address + 0x10000) {
+-                              entry = mk_pte_io(offset, prot, space,
+-                                                64 * 1024);
+-                              curend = address + 0x10000;
+-                              offset += 0x10000;
+-                      } else
+-                              offset += PAGE_SIZE;
+-              } else
+-                      offset += PAGE_SIZE;
+-
+-              if (pte_write(entry))
+-                      entry = pte_mkdirty(entry);
+-              do {
+-                      BUG_ON(!pte_none(*pte));
+-                      set_pte_at(mm, address, pte, entry);
+-                      address += PAGE_SIZE;
+-                      pte_val(entry) += PAGE_SIZE;
+-                      pte++;
+-              } while (address < curend);
+-      } while (address < end);
+-}
+-
+-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PGDIR_MASK;
+-      end = address + size;
+-      if (end > PGDIR_SIZE)
+-              end = PGDIR_SIZE;
+-      offset -= address;
+-      do {
+-              pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
+-              if (!pte)
+-                      return -ENOMEM;
+-              io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
+-              pte_unmap(pte);
+-              address = (address + PMD_SIZE) & PMD_MASK;
+-              pmd++;
+-      } while (address < end);
+-      return 0;
+-}
+-
+-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PUD_MASK;
+-      end = address + size;
+-      if (end > PUD_SIZE)
+-              end = PUD_SIZE;
+-      offset -= address;
+-      do {
+-              pmd_t *pmd = pmd_alloc(mm, pud, address);
+-              if (!pud)
+-                      return -ENOMEM;
+-              io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
+-              address = (address + PUD_SIZE) & PUD_MASK;
+-              pud++;
+-      } while (address < end);
+-      return 0;
+-}
+-
+-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+-              unsigned long pfn, unsigned long size, pgprot_t prot)
+-{
+-      int error = 0;
+-      pgd_t * dir;
+-      unsigned long beg = from;
+-      unsigned long end = from + size;
+-      struct mm_struct *mm = vma->vm_mm;
+-      int space = GET_IOSPACE(pfn);
+-      unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+-      unsigned long phys_base;
+-
+-      phys_base = offset | (((unsigned long) space) << 32UL);
+-
+-      /* See comment in mm/memory.c remap_pfn_range */
+-      vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+-      vma->vm_pgoff = phys_base >> PAGE_SHIFT;
+-
+-      offset -= from;
+-      dir = pgd_offset(mm, from);
+-      flush_cache_range(vma, beg, end);
+-
+-      while (from < end) {
+-              pud_t *pud = pud_alloc(mm, dir, from);
+-              error = -ENOMEM;
+-              if (!pud)
+-                      break;
+-              error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
+-              if (error)
+-                      break;
+-              from = (from + PGDIR_SIZE) & PGDIR_MASK;
+-              dir++;
+-      }
+-
+-      flush_tlb_range(vma, beg, end);
+-      return error;
+-}
+-EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/queue-3.1/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch b/queue-3.1/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
new file mode 100644 (file)
index 0000000..f233d65
--- /dev/null
@@ -0,0 +1,33 @@
+From 20ef5b3fb98a8548235689c61080a7389a41145c Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 14 Dec 2011 10:05:22 -0800
+Subject: sparc32: Be less strict in matching %lo part of relocation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit b1f44e13a525d2ffb7d5afe2273b7169d6f2222e ]
+
+The "(insn & 0x01800000) != 0x01800000" test matches 'restore'
+but that is a legitimate place to see the %lo() part of a 32-bit
+symbol relocation, particularly in tail calls.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Sergei Trofimovich <slyfox@gentoo.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/mm/btfixup.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/sparc/mm/btfixup.c
++++ b/arch/sparc/mm/btfixup.c
+@@ -302,8 +302,7 @@ void __init btfixup(void)
+                               case 'i':       /* INT */
+                                       if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
+                                               set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
+-                                      else if ((insn & 0x80002000) == 0x80002000 &&
+-                                               (insn & 0x01800000) != 0x01800000) /* %LO */
++                                      else if ((insn & 0x80002000) == 0x80002000) /* %LO */
+                                               set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
+                                       else {
+                                               prom_printf(insn_i, p, addr, insn);
diff --git a/queue-3.1/sparc32-correct-the-return-value-of-memcpy.patch b/queue-3.1/sparc32-correct-the-return-value-of-memcpy.patch
new file mode 100644 (file)
index 0000000..3ce69c4
--- /dev/null
@@ -0,0 +1,99 @@
+From 6bf220cd94d4ac023e1ad81ad2ad76f176d45892 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:31:55 -0700
+Subject: sparc32: Correct the return value of memcpy.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit a52312b88c8103e965979a79a07f6b34af82ca4b ]
+
+Properly return the original destination buffer pointer.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S |   22 +++++++---------------
+ 1 file changed, 7 insertions(+), 15 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -13,14 +13,6 @@
+       .align  4;              \
+ x:
+-
+-/* In kernel these functions don't return a value.
+- * One should use macros in asm/string.h for that purpose.
+- * We return 0, so that bugs are more apparent.
+- */
+-#define SETUP_RETL
+-#define RETL_INSN     clr     %o0
+-
+ /* Both these macros have to start with exactly the same insn */
+ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
+       ldd     [%src + (offset) + 0x00], %t0; \
+@@ -154,7 +146,7 @@ FUNC(__memmove)
+ #endif
+ FUNC(memmove)
+       cmp             %o0, %o1
+-      SETUP_RETL
++      mov             %o0, %g7
+       bleu            9f
+        sub            %o0, %o1, %o4
+@@ -178,7 +170,7 @@ FUNC(memmove)
+        sub            %o0, 1, %o0
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ /* NOTE: This code is executed just for the cases,
+          where %src (=%o1) & 3 is != 0.
+@@ -212,7 +204,7 @@ FUNC(memmove)
+ FUNC(memcpy)  /* %o0=dst %o1=src %o2=len */
+       sub             %o0, %o1, %o4
+-      SETUP_RETL
++      mov             %o0, %g7
+ 9:
+       andcc           %o4, 3, %o5
+ 0:
+@@ -308,7 +300,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%o0]
+ 1:
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ 82:   /* ldd_std */
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+@@ -373,7 +365,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%o0]
+ 1:
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ 86:   /* non_aligned */
+       cmp             %o2, 6
+@@ -498,7 +490,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%i0 + 4]
+ 1:
+       ret
+-       restore        %g0, %g0, %o0
++       restore        %g7, %g0, %o0
+ 88:   /* short_end */
+@@ -529,7 +521,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%o0]
+ 1:
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ 90:   /* short_aligned_end */
+       bne             88b
diff --git a/queue-3.1/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch b/queue-3.1/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
new file mode 100644 (file)
index 0000000..a8bab3d
--- /dev/null
@@ -0,0 +1,689 @@
+From 5a1b90af1e95b9ac5339f8d356c0a15a2b92c0d8 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:15:58 -0700
+Subject: sparc32: Remove non-kernel code from memcpy implementation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 045b7de9ca0cf09f1adc3efa467f668b89238390 ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S |  607 ------------------------------------------------
+ 1 file changed, 2 insertions(+), 605 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -7,17 +7,12 @@
+  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+  */
+-#ifdef __KERNEL__
+-
+-#define FUNC(x)                                                                                       \
++#define FUNC(x)               \
+       .globl  x;              \
+       .type   x,@function;    \
+-      .align  4;                                                                                      \
++      .align  4;              \
+ x:
+-#undef FASTER_REVERSE
+-#undef FASTER_NONALIGNED
+-#define FASTER_ALIGNED
+ /* In kernel these functions don't return a value.
+  * One should use macros in asm/string.h for that purpose.
+@@ -26,21 +21,6 @@ x:
+ #define SETUP_RETL
+ #define RETL_INSN     clr     %o0
+-#else
+-
+-/* libc */
+-
+-#include "DEFS.h"
+-
+-#define FASTER_REVERSE
+-#define FASTER_NONALIGNED
+-#define FASTER_ALIGNED
+-
+-#define SETUP_RETL    mov     %o0, %g6
+-#define RETL_INSN     mov     %g6, %o0
+-
+-#endif
+-
+ /* Both these macros have to start with exactly the same insn */
+ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
+       ldd     [%src + (offset) + 0x00], %t0; \
+@@ -164,30 +144,6 @@ x:
+       .text
+       .align  4
+-#ifdef FASTER_REVERSE
+-
+-70:   /* rdword_align */
+-
+-      andcc           %o1, 1, %g0
+-      be              4f
+-       andcc          %o1, 2, %g0
+-
+-      ldub            [%o1 - 1], %g2
+-      sub             %o1, 1, %o1
+-      stb             %g2, [%o0 - 1]
+-      sub             %o2, 1, %o2
+-      be              3f
+-       sub            %o0, 1, %o0
+-4:
+-      lduh            [%o1 - 2], %g2
+-      sub             %o1, 2, %o1
+-      sth             %g2, [%o0 - 2]
+-      sub             %o2, 2, %o2
+-      b               3f
+-       sub            %o0, 2, %o0
+-
+-#endif /* FASTER_REVERSE */
+-
+ 0:
+       retl
+        nop            ! Only bcopy returns here and it retuns void...
+@@ -207,8 +163,6 @@ FUNC(memmove)
+       bleu            0f
+        andcc          %o4, 3, %o5
+-#ifndef FASTER_REVERSE
+-
+       add             %o1, %o2, %o1
+       add             %o0, %o2, %o0
+       sub             %o1, 1, %o1
+@@ -226,294 +180,6 @@ FUNC(memmove)
+       retl
+        RETL_INSN
+-#else /* FASTER_REVERSE */
+-
+-      add             %o1, %o2, %o1
+-      add             %o0, %o2, %o0
+-      bne             77f
+-       cmp            %o2, 15
+-      bleu            91f
+-       andcc          %o1, 3, %g0
+-      bne             70b
+-3:
+-       andcc          %o1, 4, %g0
+-
+-      be              2f
+-       mov            %o2, %g1
+-
+-      ld              [%o1 - 4], %o4
+-      sub             %g1, 4, %g1
+-      st              %o4, [%o0 - 4]
+-      sub             %o1, 4, %o1
+-      sub             %o0, 4, %o0
+-2:
+-      andcc           %g1, 0xffffff80, %g7
+-      be              3f
+-       andcc          %o0, 4, %g0
+-
+-      be              74f + 4
+-5:
+-      RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
+-      sub             %o1, 128, %o1
+-      bne             5b
+-       sub            %o0, 128, %o0
+-3:
+-      andcc           %g1, 0x70, %g7
+-      be              72f
+-       andcc          %g1, 8, %g0
+-
+-      sethi           %hi(72f), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      sub             %o1, %g7, %o1
+-      sub             %o5, %o4, %o5
+-      jmpl            %o5 + %lo(72f), %g0
+-       sub            %o0, %g7, %o0
+-
+-71:   /* rmemcpy_table */
+-      RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
+-
+-72:   /* rmemcpy_table_end */
+-
+-      be              73f
+-       andcc          %g1, 4, %g0
+-
+-      ldd             [%o1 - 0x08], %g2
+-      sub             %o0, 8, %o0
+-      sub             %o1, 8, %o1
+-      st              %g2, [%o0]
+-      st              %g3, [%o0 + 0x04]
+-
+-73:   /* rmemcpy_last7 */
+-
+-      be              1f
+-       andcc          %g1, 2, %g0
+-
+-      ld              [%o1 - 4], %g2
+-      sub             %o1, 4, %o1
+-      st              %g2, [%o0 - 4]
+-      sub             %o0, 4, %o0
+-1:
+-      be              1f
+-       andcc          %g1, 1, %g0
+-
+-      lduh            [%o1 - 2], %g2
+-      sub             %o1, 2, %o1
+-      sth             %g2, [%o0 - 2]
+-      sub             %o0, 2, %o0
+-1:
+-      be              1f
+-       nop
+-
+-      ldub            [%o1 - 1], %g2
+-      stb             %g2, [%o0 - 1]
+-1:
+-      retl
+-       RETL_INSN
+-
+-74:   /* rldd_std */
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
+-      sub             %o1, 128, %o1
+-      bne             74b
+-       sub            %o0, 128, %o0
+-
+-      andcc           %g1, 0x70, %g7
+-      be              72b
+-       andcc          %g1, 8, %g0
+-
+-      sethi           %hi(72b), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      sub             %o1, %g7, %o1
+-      sub             %o5, %o4, %o5
+-      jmpl            %o5 + %lo(72b), %g0
+-       sub            %o0, %g7, %o0
+-
+-75:   /* rshort_end */
+-
+-      and             %o2, 0xe, %o3
+-2:
+-      sethi           %hi(76f), %o5
+-      sll             %o3, 3, %o4
+-      sub             %o0, %o3, %o0
+-      sub             %o5, %o4, %o5
+-      sub             %o1, %o3, %o1
+-      jmpl            %o5 + %lo(76f), %g0
+-       andcc          %o2, 1, %g0
+-
+-      RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
+-
+-76:   /* rshort_table_end */
+-
+-      be              1f
+-       nop
+-      ldub            [%o1 - 1], %g2
+-      stb             %g2, [%o0 - 1]
+-1:
+-      retl
+-       RETL_INSN
+-
+-91:   /* rshort_aligned_end */
+-
+-      bne             75b
+-       andcc          %o2, 8, %g0
+-
+-      be              1f
+-       andcc          %o2, 4, %g0
+-
+-      ld              [%o1 - 0x08], %g2
+-      ld              [%o1 - 0x04], %g3
+-      sub             %o1, 8, %o1
+-      st              %g2, [%o0 - 0x08]
+-      st              %g3, [%o0 - 0x04]
+-      sub             %o0, 8, %o0
+-1:
+-      b               73b
+-       mov            %o2, %g1
+-
+-77:   /* rnon_aligned */
+-      cmp             %o2, 15
+-      bleu            75b
+-       andcc          %o0, 3, %g0
+-      be              64f
+-       andcc          %o0, 1, %g0
+-      be              63f
+-       andcc          %o0, 2, %g0
+-      ldub            [%o1 - 1], %g5
+-      sub             %o1, 1, %o1
+-      stb             %g5, [%o0 - 1]
+-      sub             %o0, 1, %o0
+-      be              64f
+-       sub            %o2, 1, %o2
+-63:
+-      ldub            [%o1 - 1], %g5
+-      sub             %o1, 2, %o1
+-      stb             %g5, [%o0 - 1]
+-      sub             %o0, 2, %o0
+-      ldub            [%o1], %g5
+-      sub             %o2, 2, %o2
+-      stb             %g5, [%o0]
+-64:   
+-      and             %o1, 3, %g2
+-      and             %o1, -4, %o1
+-      and             %o2, 0xc, %g3
+-      add             %o1, 4, %o1
+-      cmp             %g3, 4
+-      sll             %g2, 3, %g4
+-      mov             32, %g2
+-      be              4f
+-       sub            %g2, %g4, %g7
+-
+-      blu             3f
+-       cmp            %g3, 8
+-
+-      be              2f
+-       srl            %o2, 2, %g3
+-
+-      ld              [%o1 - 4], %o3
+-      add             %o0, -8, %o0
+-      ld              [%o1 - 8], %o4
+-      add             %o1, -16, %o1
+-      b               7f
+-       add            %g3, 1, %g3
+-2:
+-      ld              [%o1 - 4], %o4
+-      add             %o0, -4, %o0
+-      ld              [%o1 - 8], %g1
+-      add             %o1, -12, %o1
+-      b               8f
+-       add            %g3, 2, %g3
+-3:
+-      ld              [%o1 - 4], %o5
+-      add             %o0, -12, %o0
+-      ld              [%o1 - 8], %o3
+-      add             %o1, -20, %o1
+-      b               6f
+-       srl            %o2, 2, %g3
+-4:
+-      ld              [%o1 - 4], %g1
+-      srl             %o2, 2, %g3
+-      ld              [%o1 - 8], %o5
+-      add             %o1, -24, %o1
+-      add             %o0, -16, %o0
+-      add             %g3, -1, %g3
+-
+-      ld              [%o1 + 12], %o3
+-5:
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
+-      or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 12]
+-6:
+-      ld              [%o1 + 8], %o4
+-      sll             %o3, %g4, %g2
+-      srl             %o5, %g7, %g5
+-      or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 8]
+-7:
+-      ld              [%o1 + 4], %g1
+-      sll             %o4, %g4, %g2
+-      srl             %o3, %g7, %g5
+-      or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 4]
+-8:
+-      ld              [%o1], %o5
+-      sll             %g1, %g4, %g2
+-      srl             %o4, %g7, %g5
+-      addcc           %g3, -4, %g3
+-      or              %g2, %g5, %g2
+-      add             %o1, -16, %o1
+-      st              %g2, [%o0]
+-      add             %o0, -16, %o0
+-      bne,a           5b      
+-       ld             [%o1 + 12], %o3
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
+-      srl             %g4, 3, %g3
+-      or              %g2, %g5, %g2
+-      add             %o1, %g3, %o1
+-      andcc           %o2, 2, %g0
+-      st              %g2, [%o0 + 12]
+-      be              1f
+-       andcc          %o2, 1, %g0
+-      
+-      ldub            [%o1 + 15], %g5
+-      add             %o1, -2, %o1
+-      stb             %g5, [%o0 + 11]
+-      add             %o0, -2, %o0
+-      ldub            [%o1 + 16], %g5
+-      stb             %g5, [%o0 + 12]
+-1:
+-      be              1f
+-       nop
+-      ldub            [%o1 + 15], %g5
+-      stb             %g5, [%o0 + 11]
+-1:
+-      retl
+-       RETL_INSN
+-
+-#endif /* FASTER_REVERSE */
+-
+ /* NOTE: This code is executed just for the cases,
+          where %src (=%o1) & 3 is != 0.
+        We need to align it to 4. So, for (%src & 3)
+@@ -653,22 +319,6 @@ FUNC(memcpy)      /* %o0=dst %o1=src %o2=len
+       bne             82b
+        add            %o0, 128, %o0
+-#ifndef FASTER_ALIGNED
+-
+-      andcc           %g1, 0x70, %g7
+-      be              80b
+-       andcc          %g1, 8, %g0
+-
+-      sethi           %hi(80b), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      add             %o1, %g7, %o1
+-      sub             %o5, %o4, %o5
+-      jmpl            %o5 + %lo(80b), %g0
+-       add            %o0, %g7, %o0
+-
+-#else /* FASTER_ALIGNED */
+-
+       andcc           %g1, 0x70, %g7
+       be              84f
+        andcc          %g1, 8, %g0
+@@ -723,19 +373,9 @@ FUNC(memcpy)      /* %o0=dst %o1=src %o2=len
+       retl
+        RETL_INSN
+-#endif /* FASTER_ALIGNED */
+-
+ 86:   /* non_aligned */
+       cmp             %o2, 6
+       bleu            88f
+-
+-#ifdef FASTER_NONALIGNED
+-
+-       cmp            %o2, 256
+-      bcc             87f
+-
+-#endif /* FASTER_NONALIGNED */
+-
+        andcc          %o0, 3, %g0
+       be              61f
+        andcc          %o0, 1, %g0
+@@ -855,249 +495,6 @@ FUNC(memcpy)     /* %o0=dst %o1=src %o2=len
+       retl
+        RETL_INSN
+-#ifdef FASTER_NONALIGNED
+-
+-87:   /* faster_nonaligned */
+-
+-      andcc           %o1, 3, %g0
+-      be              3f
+-       andcc          %o1, 1, %g0
+-
+-      be              4f
+-       andcc          %o1, 2, %g0
+-
+-      ldub            [%o1], %g2
+-      add             %o1, 1, %o1
+-      stb             %g2, [%o0]
+-      sub             %o2, 1, %o2
+-      bne             3f
+-       add            %o0, 1, %o0
+-4:
+-      lduh            [%o1], %g2
+-      add             %o1, 2, %o1
+-      srl             %g2, 8, %g3
+-      sub             %o2, 2, %o2
+-      stb             %g3, [%o0]
+-      add             %o0, 2, %o0
+-      stb             %g2, [%o0 - 1]
+-3:
+-       andcc          %o1, 4, %g0
+-
+-      bne             2f
+-       cmp            %o5, 1
+-
+-      ld              [%o1], %o4
+-      srl             %o4, 24, %g2
+-      stb             %g2, [%o0]
+-      srl             %o4, 16, %g3
+-      stb             %g3, [%o0 + 1]
+-      srl             %o4, 8, %g2
+-      stb             %g2, [%o0 + 2]
+-      sub             %o2, 4, %o2
+-      stb             %o4, [%o0 + 3]
+-      add             %o1, 4, %o1
+-      add             %o0, 4, %o0
+-2:
+-      be              33f
+-       cmp            %o5, 2
+-      be              32f
+-       sub            %o2, 4, %o2
+-31:
+-      ld              [%o1], %g2
+-      add             %o1, 4, %o1
+-      srl             %g2, 24, %g3
+-      and             %o0, 7, %g5
+-      stb             %g3, [%o0]
+-      cmp             %g5, 7
+-      sll             %g2, 8, %g1
+-      add             %o0, 4, %o0
+-      be              41f
+-       and            %o2, 0xffffffc0, %o3
+-      ld              [%o0 - 7], %o4
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             4b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      st              %o4, [%o0 - 7]
+-      sth             %g2, [%o0 - 3]
+-      srl             %g1, 8, %g4
+-      b               88f
+-       stb            %g4, [%o0 - 1]
+-32:
+-      ld              [%o1], %g2
+-      add             %o1, 4, %o1
+-      srl             %g2, 16, %g3
+-      and             %o0, 7, %g5
+-      sth             %g3, [%o0]
+-      cmp             %g5, 6
+-      sll             %g2, 16, %g1
+-      add             %o0, 4, %o0
+-      be              42f
+-       and            %o2, 0xffffffc0, %o3
+-      ld              [%o0 - 6], %o4
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             4b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      st              %o4, [%o0 - 6]
+-      b               88f
+-       sth            %g2, [%o0 - 2]
+-33:
+-      ld              [%o1], %g2
+-      sub             %o2, 4, %o2
+-      srl             %g2, 24, %g3
+-      and             %o0, 7, %g5
+-      stb             %g3, [%o0]
+-      cmp             %g5, 5
+-      srl             %g2, 8, %g4
+-      sll             %g2, 24, %g1
+-      sth             %g4, [%o0 + 1]
+-      add             %o1, 4, %o1
+-      be              43f
+-       and            %o2, 0xffffffc0, %o3
+-
+-      ld              [%o0 - 1], %o4
+-      add             %o0, 4, %o0
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             4b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 24, %g2
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 24, %g2
+-1:
+-      st              %o4, [%o0 - 5]
+-      b               88f
+-       stb            %g2, [%o0 - 1]
+-41:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             41b
+-       add            %o0, 64, %o0
+-       
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      sth             %g2, [%o0 - 3]
+-      srl             %g1, 8, %g4
+-      b               88f
+-       stb            %g4, [%o0 - 1]
+-43:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             43b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 24, %g2
+-4:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 24, %g2
+-1:
+-      stb             %g2, [%o0 + 3]
+-      b               88f
+-       add            %o0, 4, %o0
+-42:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             42b
+-       add            %o0, 64, %o0
+-       
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      sth             %g2, [%o0 - 2]
+-
+-      /* Fall through */
+-       
+-#endif /* FASTER_NONALIGNED */
+-
+ 88:   /* short_end */
+       and             %o2, 0xe, %o3
diff --git a/queue-3.1/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch b/queue-3.1/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
new file mode 100644 (file)
index 0000000..dad3da8
--- /dev/null
@@ -0,0 +1,291 @@
+From 0a7316055e710cf551484615c0b1887e156ed972 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:30:14 -0700
+Subject: sparc32: Remove uses of %g7 in memcpy implementation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 21f74d361dfd6a7d0e47574e315f780d8172084a ]
+
+This is setting things up so that we can correct the return
+value, so that it properly returns the original destination
+buffer pointer.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S |  177 ++++++++++++++++++++++++------------------------
+ 1 file changed, 91 insertions(+), 86 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -235,7 +235,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       add             %o1, 4, %o1
+       add             %o0, 4, %o0
+ 2:
+-      andcc           %g1, 0xffffff80, %g7
++      andcc           %g1, 0xffffff80, %g0
+       be              3f
+        andcc          %o0, 4, %g0
+@@ -245,22 +245,23 @@ FUNC(memcpy)     /* %o0=dst %o1=src %o2=len
+       MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
++      sub             %g1, 128, %g1
+       add             %o1, 128, %o1
+-      bne             5b
++      cmp             %g1, 128
++      bge             5b
+        add            %o0, 128, %o0
+ 3:
+-      andcc           %g1, 0x70, %g7
++      andcc           %g1, 0x70, %g4
+       be              80f
+        andcc          %g1, 8, %g0
+       sethi           %hi(80f), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      add             %o1, %g7, %o1
++      srl             %g4, 1, %o4
++      add             %g4, %o4, %o4
++      add             %o1, %g4, %o1
+       sub             %o5, %o4, %o5
+       jmpl            %o5 + %lo(80f), %g0
+-       add            %o0, %g7, %o0
++       add            %o0, %g4, %o0
+ 79:   /* memcpy_table */
+@@ -314,20 +315,21 @@ FUNC(memcpy)     /* %o0=dst %o1=src %o2=len
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
++      subcc           %g1, 128, %g1
+       add             %o1, 128, %o1
+-      bne             82b
++      cmp             %g1, 128
++      bge             82b
+        add            %o0, 128, %o0
+-      andcc           %g1, 0x70, %g7
++      andcc           %g1, 0x70, %g4
+       be              84f
+        andcc          %g1, 8, %g0
+       sethi           %hi(84f), %o5
+-      add             %o1, %g7, %o1
+-      sub             %o5, %g7, %o5
++      add             %o1, %g4, %o1
++      sub             %o5, %g4, %o5
+       jmpl            %o5 + %lo(84f), %g0
+-       add            %o0, %g7, %o0
++       add            %o0, %g4, %o0
+ 83:   /* amemcpy_table */
+@@ -376,124 +378,127 @@ FUNC(memcpy)   /* %o0=dst %o1=src %o2=len
+ 86:   /* non_aligned */
+       cmp             %o2, 6
+       bleu            88f
+-       andcc          %o0, 3, %g0
++       nop
++
++      save            %sp, -96, %sp
++      andcc           %i0, 3, %g0
+       be              61f
+-       andcc          %o0, 1, %g0
++       andcc          %i0, 1, %g0
+       be              60f
+-       andcc          %o0, 2, %g0
++       andcc          %i0, 2, %g0
+-      ldub            [%o1], %g5
+-      add             %o1, 1, %o1
+-      stb             %g5, [%o0]
+-      sub             %o2, 1, %o2
++      ldub            [%i1], %g5
++      add             %i1, 1, %i1
++      stb             %g5, [%i0]
++      sub             %i2, 1, %i2
+       bne             61f
+-       add            %o0, 1, %o0
++       add            %i0, 1, %i0
+ 60:
+-      ldub            [%o1], %g3
+-      add             %o1, 2, %o1
+-      stb             %g3, [%o0]
+-      sub             %o2, 2, %o2
+-      ldub            [%o1 - 1], %g3
+-      add             %o0, 2, %o0
+-      stb             %g3, [%o0 - 1]
++      ldub            [%i1], %g3
++      add             %i1, 2, %i1
++      stb             %g3, [%i0]
++      sub             %i2, 2, %i2
++      ldub            [%i1 - 1], %g3
++      add             %i0, 2, %i0
++      stb             %g3, [%i0 - 1]
+ 61:
+-      and             %o1, 3, %g2
+-      and             %o2, 0xc, %g3
+-      and             %o1, -4, %o1
++      and             %i1, 3, %g2
++      and             %i2, 0xc, %g3
++      and             %i1, -4, %i1
+       cmp             %g3, 4
+       sll             %g2, 3, %g4
+       mov             32, %g2
+       be              4f
+-       sub            %g2, %g4, %g7
++       sub            %g2, %g4, %l0
+       
+       blu             3f
+        cmp            %g3, 0x8
+       be              2f
+-       srl            %o2, 2, %g3
++       srl            %i2, 2, %g3
+-      ld              [%o1], %o3
+-      add             %o0, -8, %o0
+-      ld              [%o1 + 4], %o4
++      ld              [%i1], %i3
++      add             %i0, -8, %i0
++      ld              [%i1 + 4], %i4
+       b               8f
+        add            %g3, 1, %g3
+ 2:
+-      ld              [%o1], %o4
+-      add             %o0, -12, %o0
+-      ld              [%o1 + 4], %o5
++      ld              [%i1], %i4
++      add             %i0, -12, %i0
++      ld              [%i1 + 4], %i5
+       add             %g3, 2, %g3
+       b               9f
+-       add            %o1, -4, %o1
++       add            %i1, -4, %i1
+ 3:
+-      ld              [%o1], %g1
+-      add             %o0, -4, %o0
+-      ld              [%o1 + 4], %o3
+-      srl             %o2, 2, %g3
++      ld              [%i1], %g1
++      add             %i0, -4, %i0
++      ld              [%i1 + 4], %i3
++      srl             %i2, 2, %g3
+       b               7f
+-       add            %o1, 4, %o1
++       add            %i1, 4, %i1
+ 4:
+-      ld              [%o1], %o5
+-      cmp             %o2, 7
+-      ld              [%o1 + 4], %g1
+-      srl             %o2, 2, %g3
++      ld              [%i1], %i5
++      cmp             %i2, 7
++      ld              [%i1 + 4], %g1
++      srl             %i2, 2, %g3
+       bleu            10f
+-       add            %o1, 8, %o1
++       add            %i1, 8, %i1
+-      ld              [%o1], %o3
++      ld              [%i1], %i3
+       add             %g3, -1, %g3
+ 5:
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
++      sll             %i5, %g4, %g2
++      srl             %g1, %l0, %g5
+       or              %g2, %g5, %g2
+-      st              %g2, [%o0]
++      st              %g2, [%i0]
+ 7:
+-      ld              [%o1 + 4], %o4
++      ld              [%i1 + 4], %i4
+       sll             %g1, %g4, %g2
+-      srl             %o3, %g7, %g5
++      srl             %i3, %l0, %g5
+       or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 4]
++      st              %g2, [%i0 + 4]
+ 8:
+-      ld              [%o1 + 8], %o5
+-      sll             %o3, %g4, %g2
+-      srl             %o4, %g7, %g5
++      ld              [%i1 + 8], %i5
++      sll             %i3, %g4, %g2
++      srl             %i4, %l0, %g5
+       or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 8]
++      st              %g2, [%i0 + 8]
+ 9:
+-      ld              [%o1 + 12], %g1
+-      sll             %o4, %g4, %g2
+-      srl             %o5, %g7, %g5
++      ld              [%i1 + 12], %g1
++      sll             %i4, %g4, %g2
++      srl             %i5, %l0, %g5
+       addcc           %g3, -4, %g3
+       or              %g2, %g5, %g2
+-      add             %o1, 16, %o1
+-      st              %g2, [%o0 + 12]
+-      add             %o0, 16, %o0
++      add             %i1, 16, %i1
++      st              %g2, [%i0 + 12]
++      add             %i0, 16, %i0
+       bne,a           5b
+-       ld             [%o1], %o3
++       ld             [%i1], %i3
+ 10:
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
+-      srl             %g7, 3, %g3
++      sll             %i5, %g4, %g2
++      srl             %g1, %l0, %g5
++      srl             %l0, 3, %g3
+       or              %g2, %g5, %g2
+-      sub             %o1, %g3, %o1
+-      andcc           %o2, 2, %g0
+-      st              %g2, [%o0]
++      sub             %i1, %g3, %i1
++      andcc           %i2, 2, %g0
++      st              %g2, [%i0]
+       be              1f
+-       andcc          %o2, 1, %g0
++       andcc          %i2, 1, %g0
+-      ldub            [%o1], %g2
+-      add             %o1, 2, %o1
+-      stb             %g2, [%o0 + 4]
+-      add             %o0, 2, %o0
+-      ldub            [%o1 - 1], %g2
+-      stb             %g2, [%o0 + 3]
++      ldub            [%i1], %g2
++      add             %i1, 2, %i1
++      stb             %g2, [%i0 + 4]
++      add             %i0, 2, %i0
++      ldub            [%i1 - 1], %g2
++      stb             %g2, [%i0 + 3]
+ 1:
+       be              1f
+        nop
+-      ldub            [%o1], %g2
+-      stb             %g2, [%o0 + 4]
++      ldub            [%i1], %g2
++      stb             %g2, [%i0 + 4]
+ 1:
+-      retl
+-       RETL_INSN
++      ret
++       restore        %g0, %g0, %o0
+ 88:   /* short_end */
diff --git a/queue-3.1/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch b/queue-3.1/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
new file mode 100644 (file)
index 0000000..4717d59
--- /dev/null
@@ -0,0 +1,106 @@
+From 612837c3502f6d1dd2d75b27778c6b8597ac4afc Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Mon, 31 Oct 2011 01:05:49 -0700
+Subject: sparc64: Fix masking and shifting in VIS fpcmp emulation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 2e8ecdc008a16b9a6c4b9628bb64d0d1c05f9f92 ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/visemul.c |   32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/sparc/kernel/visemul.c
++++ b/arch/sparc/kernel/visemul.c
+@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a > b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPGT32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a > b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a <= b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPLE32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a <= b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a != b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPNE32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a != b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a == b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPEQ32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a == b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+       }
diff --git a/queue-3.1/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch b/queue-3.1/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
new file mode 100644 (file)
index 0000000..93c95be
--- /dev/null
@@ -0,0 +1,44 @@
+From f852e0fd1bb963a325ffe943a6ad9ef7d9bfb88b Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 22 Dec 2011 13:23:59 -0800
+Subject: sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 7cc8583372a21d98a23b703ad96cab03180b5030 ]
+
+This silently was working for many years and stopped working on
+Niagara-T3 machines.
+
+We need to set the MSIQ to VALID before we can set it's state to IDLE.
+
+On Niagara-T3, setting the state to IDLE first was causing HV_EINVAL
+errors.  The hypervisor documentation says, rather ambiguously, that
+the MSIQ must be "initialized" before one can set the state.
+
+I previously understood this to mean merely that a successful setconf()
+operation has been performed on the MSIQ, which we have done at this
+point.  But it seems to also mean that it has been set VALID too.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/pci_sun4v.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/sparc/kernel/pci_sun4v.c
++++ b/arch/sparc/kernel/pci_sun4v.c
+@@ -848,10 +848,10 @@ static int pci_sun4v_msiq_build_irq(stru
+       if (!irq)
+               return -ENOMEM;
+-      if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+-              return -EINVAL;
+       if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
+               return -EINVAL;
++      if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
++              return -EINVAL;
+       return irq;
+ }
diff --git a/queue-3.1/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch b/queue-3.1/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
new file mode 100644 (file)
index 0000000..108f118
--- /dev/null
@@ -0,0 +1,168 @@
+From 6f47e53783de70866c46a35cfc2d52bb3a8ae394 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 17 Nov 2011 22:44:58 -0800
+Subject: sparc64: Patch sun4v code sequences properly on module load.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 0b64120cceb86e93cb1bda0dc055f13016646907 ]
+
+Some of the sun4v code patching occurs in inline functions visible
+to, and usable by, modules.
+
+Therefore we have to patch them up during module load.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/entry.h    |    7 ++++++
+ arch/sparc/kernel/module.c   |   27 ++++++++++++++++++++++++
+ arch/sparc/kernel/setup_64.c |   48 +++++++++++++++++++++++++------------------
+ 3 files changed, 63 insertions(+), 19 deletions(-)
+
+--- a/arch/sparc/kernel/entry.h
++++ b/arch/sparc/kernel/entry.h
+@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs
+ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
+ #else /* CONFIG_SPARC32 */
++
++#include <asm/trap_block.h>
++
+ struct popc_3insn_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[3];
+@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __p
+       __popc_6insn_patch_end;
+ extern void __init per_cpu_patch(void);
++extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
++                                  struct sun4v_1insn_patch_entry *);
++extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
++                                  struct sun4v_2insn_patch_entry *);
+ extern void __init sun4v_patch(void);
+ extern void __init boot_cpu_id_too_large(int cpu);
+ extern unsigned int dcache_parity_tl1_occurred;
+--- a/arch/sparc/kernel/module.c
++++ b/arch/sparc/kernel/module.c
+@@ -17,6 +17,8 @@
+ #include <asm/processor.h>
+ #include <asm/spitfire.h>
++#include "entry.h"
++
+ #ifdef CONFIG_SPARC64
+ #include <linux/jump_label.h>
+@@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs
+ }
+ #ifdef CONFIG_SPARC64
++static void do_patch_sections(const Elf_Ehdr *hdr,
++                            const Elf_Shdr *sechdrs)
++{
++      const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
++      char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
++
++      for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
++              if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
++                      sun4v_1insn = s;
++              if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
++                      sun4v_2insn = s;
++      }
++
++      if (sun4v_1insn && tlb_type == hypervisor) {
++              void *p = (void *) sun4v_1insn->sh_addr;
++              sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
++      }
++      if (sun4v_2insn && tlb_type == hypervisor) {
++              void *p = (void *) sun4v_2insn->sh_addr;
++              sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
++      }
++}
++
+ int module_finalize(const Elf_Ehdr *hdr,
+                   const Elf_Shdr *sechdrs,
+                   struct module *me)
+@@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr,
+       /* make jump label nops */
+       jump_label_apply_nops(me);
++      do_patch_sections(hdr, sechdrs);
++
+       /* Cheetah's I-cache is fully coherent.  */
+       if (tlb_type == spitfire) {
+               unsigned long va;
+--- a/arch/sparc/kernel/setup_64.c
++++ b/arch/sparc/kernel/setup_64.c
+@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
+       }
+ }
+-void __init sun4v_patch(void)
++void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
++                           struct sun4v_1insn_patch_entry *end)
+ {
+-      extern void sun4v_hvapi_init(void);
+-      struct sun4v_1insn_patch_entry *p1;
+-      struct sun4v_2insn_patch_entry *p2;
+-
+-      if (tlb_type != hypervisor)
+-              return;
++      while (start < end) {
++              unsigned long addr = start->addr;
+-      p1 = &__sun4v_1insn_patch;
+-      while (p1 < &__sun4v_1insn_patch_end) {
+-              unsigned long addr = p1->addr;
+-
+-              *(unsigned int *) (addr +  0) = p1->insn;
++              *(unsigned int *) (addr +  0) = start->insn;
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+-              p1++;
++              start++;
+       }
++}
+-      p2 = &__sun4v_2insn_patch;
+-      while (p2 < &__sun4v_2insn_patch_end) {
+-              unsigned long addr = p2->addr;
++void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
++                           struct sun4v_2insn_patch_entry *end)
++{
++      while (start < end) {
++              unsigned long addr = start->addr;
+-              *(unsigned int *) (addr +  0) = p2->insns[0];
++              *(unsigned int *) (addr +  0) = start->insns[0];
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+-              *(unsigned int *) (addr +  4) = p2->insns[1];
++              *(unsigned int *) (addr +  4) = start->insns[1];
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
+-              p2++;
++              start++;
+       }
++}
++
++void __init sun4v_patch(void)
++{
++      extern void sun4v_hvapi_init(void);
++
++      if (tlb_type != hypervisor)
++              return;
++
++      sun4v_patch_1insn_range(&__sun4v_1insn_patch,
++                              &__sun4v_1insn_patch_end);
++
++      sun4v_patch_2insn_range(&__sun4v_2insn_patch,
++                              &__sun4v_2insn_patch_end);
+       sun4v_hvapi_init();
+ }