]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Nov 2014 17:12:05 +0000 (09:12 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Nov 2014 17:12:05 +0000 (09:12 -0800)
added patches:
gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch
ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch
net-sctp-fix-memory-leak-in-auth-key-management.patch
net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch
series
sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch
sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch
sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch
sunvdc-add-cdrom-and-v1.1-protocol-support.patch
sunvdc-compute-vdisk-geometry-from-capacity.patch
sunvdc-don-t-call-vd_op_get_vtoc.patch
sunvdc-limit-each-sg-segment-to-a-page.patch
vio-fix-reuse-of-vio_dring-slot.patch

13 files changed:
queue-3.10/gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch [new file with mode: 0644]
queue-3.10/ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch [new file with mode: 0644]
queue-3.10/net-sctp-fix-memory-leak-in-auth-key-management.patch [new file with mode: 0644]
queue-3.10/net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch [new file with mode: 0644]
queue-3.10/series [new file with mode: 0644]
queue-3.10/sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch [new file with mode: 0644]
queue-3.10/sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch [new file with mode: 0644]
queue-3.10/sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch [new file with mode: 0644]
queue-3.10/sunvdc-add-cdrom-and-v1.1-protocol-support.patch [new file with mode: 0644]
queue-3.10/sunvdc-compute-vdisk-geometry-from-capacity.patch [new file with mode: 0644]
queue-3.10/sunvdc-don-t-call-vd_op_get_vtoc.patch [new file with mode: 0644]
queue-3.10/sunvdc-limit-each-sg-segment-to-a-page.patch [new file with mode: 0644]
queue-3.10/vio-fix-reuse-of-vio_dring-slot.patch [new file with mode: 0644]

diff --git a/queue-3.10/gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch b/queue-3.10/gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch
new file mode 100644 (file)
index 0000000..082ac5d
--- /dev/null
@@ -0,0 +1,55 @@
+From foo@baz Tue Nov 18 09:07:46 PST 2014
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Mon, 3 Nov 2014 09:19:30 +0100
+Subject: gre6: Move the setting of dev->iflink into the ndo_init functions.
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit f03eb128e3f4276f46442d14f3b8f864f3775821 ]
+
+Otherwise it gets overwritten by register_netdev().
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_gre.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -962,8 +962,6 @@ static void ip6gre_tnl_link_config(struc
+       else
+               dev->flags &= ~IFF_POINTOPOINT;
+-      dev->iflink = p->link;
+-
+       /* Precalculate GRE options length */
+       if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
+               if (t->parms.o_flags&GRE_CSUM)
+@@ -1267,6 +1265,8 @@ static int ip6gre_tunnel_init(struct net
+       if (!dev->tstats)
+               return -ENOMEM;
++      dev->iflink = tunnel->parms.link;
++
+       return 0;
+ }
+@@ -1282,7 +1282,6 @@ static void ip6gre_fb_tunnel_init(struct
+       dev_hold(dev);
+ }
+-
+ static struct inet6_protocol ip6gre_protocol __read_mostly = {
+       .handler     = ip6gre_rcv,
+       .err_handler = ip6gre_err,
+@@ -1458,6 +1457,8 @@ static int ip6gre_tap_init(struct net_de
+       if (!dev->tstats)
+               return -ENOMEM;
++      dev->iflink = tunnel->parms.link;
++
+       return 0;
+ }
diff --git a/queue-3.10/ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch b/queue-3.10/ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch
new file mode 100644 (file)
index 0000000..9649d8d
--- /dev/null
@@ -0,0 +1,60 @@
+From foo@baz Tue Nov 18 09:07:46 PST 2014
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Mon, 3 Nov 2014 09:19:27 +0100
+Subject: ip6_tunnel: Use ip6_tnl_dev_init as the ndo_init function.
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit 6c6151daaf2d8dc2046d9926539feed5f66bf74e ]
+
+ip6_tnl_dev_init() sets the dev->iflink via a call to
+ip6_tnl_link_config(). After that, register_netdevice()
+sets dev->iflink = -1. So we loose the iflink configuration
+for ipv6 tunnels. Fix this by using ip6_tnl_dev_init() as the
+ndo_init function. Then ip6_tnl_dev_init() is called after
+dev->iflink is set to -1 from register_netdevice().
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_tunnel.c |   10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -265,9 +265,6 @@ static int ip6_tnl_create2(struct net_de
+       int err;
+       t = netdev_priv(dev);
+-      err = ip6_tnl_dev_init(dev);
+-      if (err < 0)
+-              goto out;
+       err = register_netdevice(dev);
+       if (err < 0)
+@@ -1433,6 +1430,7 @@ ip6_tnl_change_mtu(struct net_device *de
+ static const struct net_device_ops ip6_tnl_netdev_ops = {
++      .ndo_init       = ip6_tnl_dev_init,
+       .ndo_uninit     = ip6_tnl_dev_uninit,
+       .ndo_start_xmit = ip6_tnl_xmit,
+       .ndo_do_ioctl   = ip6_tnl_ioctl,
+@@ -1514,16 +1512,10 @@ static int __net_init ip6_fb_tnl_dev_ini
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct net *net = dev_net(dev);
+       struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+-      int err = ip6_tnl_dev_init_gen(dev);
+-
+-      if (err)
+-              return err;
+       t->parms.proto = IPPROTO_IPV6;
+       dev_hold(dev);
+-      ip6_tnl_link_config(t);
+-
+       rcu_assign_pointer(ip6n->tnls_wc[0], t);
+       return 0;
+ }
diff --git a/queue-3.10/net-sctp-fix-memory-leak-in-auth-key-management.patch b/queue-3.10/net-sctp-fix-memory-leak-in-auth-key-management.patch
new file mode 100644 (file)
index 0000000..e027fbb
--- /dev/null
@@ -0,0 +1,57 @@
+From foo@baz Tue Nov 18 09:07:46 PST 2014
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Mon, 10 Nov 2014 18:00:09 +0100
+Subject: net: sctp: fix memory leak in auth key management
+
+From: Daniel Borkmann <dborkman@redhat.com>
+
+[ Upstream commit 4184b2a79a7612a9272ce20d639934584a1f3786 ]
+
+A very minimal and simple user space application allocating an SCTP
+socket, setting SCTP_AUTH_KEY setsockopt(2) on it and then closing
+the socket again will leak the memory containing the authentication
+key from user space:
+
+unreferenced object 0xffff8800837047c0 (size 16):
+  comm "a.out", pid 2789, jiffies 4296954322 (age 192.258s)
+  hex dump (first 16 bytes):
+    01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00  ................
+  backtrace:
+    [<ffffffff816d7e8e>] kmemleak_alloc+0x4e/0xb0
+    [<ffffffff811c88d8>] __kmalloc+0xe8/0x270
+    [<ffffffffa0870c23>] sctp_auth_create_key+0x23/0x50 [sctp]
+    [<ffffffffa08718b1>] sctp_auth_set_key+0xa1/0x140 [sctp]
+    [<ffffffffa086b383>] sctp_setsockopt+0xd03/0x1180 [sctp]
+    [<ffffffff815bfd94>] sock_common_setsockopt+0x14/0x20
+    [<ffffffff815beb61>] SyS_setsockopt+0x71/0xd0
+    [<ffffffff816e58a9>] system_call_fastpath+0x12/0x17
+    [<ffffffffffffffff>] 0xffffffffffffffff
+
+This is bad because of two things, we can bring down a machine from
+user space when auth_enable=1, but also we would leave security sensitive
+keying material in memory without clearing it after use. The issue is
+that sctp_auth_create_key() already sets the refcount to 1, but after
+allocation sctp_auth_set_key() does an additional refcount on it, and
+thus leaving it around when we free the socket.
+
+Fixes: 65b07e5d0d0 ("[SCTP]: API updates to suport SCTP-AUTH extensions.")
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Cc: Vlad Yasevich <vyasevich@gmail.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/auth.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/net/sctp/auth.c
++++ b/net/sctp/auth.c
+@@ -874,8 +874,6 @@ int sctp_auth_set_key(struct sctp_endpoi
+               list_add(&cur_key->key_list, sh_keys);
+       cur_key->key = key;
+-      sctp_auth_key_hold(key);
+-
+       return 0;
+ nomem:
+       if (!replace)
diff --git a/queue-3.10/net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch b/queue-3.10/net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch
new file mode 100644 (file)
index 0000000..2cb6c9d
--- /dev/null
@@ -0,0 +1,77 @@
+From foo@baz Tue Nov 18 09:07:46 PST 2014
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Mon, 10 Nov 2014 17:54:26 +0100
+Subject: net: sctp: fix NULL pointer dereference in af->from_addr_param on malformed packet
+
+From: Daniel Borkmann <dborkman@redhat.com>
+
+[ Upstream commit e40607cbe270a9e8360907cb1e62ddf0736e4864 ]
+
+An SCTP server doing ASCONF will panic on malformed INIT ping-of-death
+in the form of:
+
+  ------------ INIT[PARAM: SET_PRIMARY_IP] ------------>
+
+While the INIT chunk parameter verification dissects through many things
+in order to detect malformed input, it misses to actually check parameters
+inside of parameters. E.g. RFC5061, section 4.2.4 proposes a 'set primary
+IP address' parameter in ASCONF, which has as a subparameter an address
+parameter.
+
+So an attacker may send a parameter type other than SCTP_PARAM_IPV4_ADDRESS
+or SCTP_PARAM_IPV6_ADDRESS, param_type2af() will subsequently return 0
+and thus sctp_get_af_specific() returns NULL, too, which we then happily
+dereference unconditionally through af->from_addr_param().
+
+The trace for the log:
+
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000078
+IP: [<ffffffffa01e9c62>] sctp_process_init+0x492/0x990 [sctp]
+PGD 0
+Oops: 0000 [#1] SMP
+[...]
+Pid: 0, comm: swapper Not tainted 2.6.32-504.el6.x86_64 #1 Bochs Bochs
+RIP: 0010:[<ffffffffa01e9c62>]  [<ffffffffa01e9c62>] sctp_process_init+0x492/0x990 [sctp]
+[...]
+Call Trace:
+ <IRQ>
+ [<ffffffffa01f2add>] ? sctp_bind_addr_copy+0x5d/0xe0 [sctp]
+ [<ffffffffa01e1fcb>] sctp_sf_do_5_1B_init+0x21b/0x340 [sctp]
+ [<ffffffffa01e3751>] sctp_do_sm+0x71/0x1210 [sctp]
+ [<ffffffffa01e5c09>] ? sctp_endpoint_lookup_assoc+0xc9/0xf0 [sctp]
+ [<ffffffffa01e61f6>] sctp_endpoint_bh_rcv+0x116/0x230 [sctp]
+ [<ffffffffa01ee986>] sctp_inq_push+0x56/0x80 [sctp]
+ [<ffffffffa01fcc42>] sctp_rcv+0x982/0xa10 [sctp]
+ [<ffffffffa01d5123>] ? ipt_local_in_hook+0x23/0x28 [iptable_filter]
+ [<ffffffff8148bdc9>] ? nf_iterate+0x69/0xb0
+ [<ffffffff81496d10>] ? ip_local_deliver_finish+0x0/0x2d0
+ [<ffffffff8148bf86>] ? nf_hook_slow+0x76/0x120
+ [<ffffffff81496d10>] ? ip_local_deliver_finish+0x0/0x2d0
+[...]
+
+A minimal way to address this is to check for NULL as we do on all
+other such occasions where we know sctp_get_af_specific() could
+possibly return with NULL.
+
+Fixes: d6de3097592b ("[SCTP]: Add the handling of "Set Primary IP Address" parameter to INIT")
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Cc: Vlad Yasevich <vyasevich@gmail.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/sm_make_chunk.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -2596,6 +2596,9 @@ do_addr_param:
+               addr_param = param.v + sizeof(sctp_addip_param_t);
+               af = sctp_get_af_specific(param_type2af(param.p->type));
++              if (af == NULL)
++                      break;
++
+               af->from_addr_param(&addr, addr_param,
+                                   htons(asoc->peer.port), 0);
diff --git a/queue-3.10/series b/queue-3.10/series
new file mode 100644 (file)
index 0000000..03a7245
--- /dev/null
@@ -0,0 +1,12 @@
+ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch
+gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch
+net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch
+net-sctp-fix-memory-leak-in-auth-key-management.patch
+sunvdc-add-cdrom-and-v1.1-protocol-support.patch
+sunvdc-compute-vdisk-geometry-from-capacity.patch
+sunvdc-limit-each-sg-segment-to-a-page.patch
+vio-fix-reuse-of-vio_dring-slot.patch
+sunvdc-don-t-call-vd_op_get_vtoc.patch
+sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch
+sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch
+sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch
diff --git a/queue-3.10/sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch b/queue-3.10/sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch
new file mode 100644 (file)
index 0000000..bc661f6
--- /dev/null
@@ -0,0 +1,100 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: Andreas Larsson <andreas@gaisler.com>
+Date: Wed, 5 Nov 2014 15:52:08 +0100
+Subject: sparc32: Implement xchg and atomic_xchg using ATOMIC_HASH locks
+
+From: Andreas Larsson <andreas@gaisler.com>
+
+[ Upstream commit 1a17fdc4f4ed06b63fac1937470378a5441a663a ]
+
+Atomicity between xchg and cmpxchg cannot be guaranteed when xchg is
+implemented with a swap and cmpxchg is implemented with locks.
+Without this, e.g. mcs_spin_lock and mcs_spin_unlock are broken.
+
+Signed-off-by: Andreas Larsson <andreas@gaisler.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/include/asm/atomic_32.h  |    2 +-
+ arch/sparc/include/asm/cmpxchg_32.h |   12 ++----------
+ arch/sparc/lib/atomic32.c           |   27 +++++++++++++++++++++++++++
+ 3 files changed, 30 insertions(+), 11 deletions(-)
+
+--- a/arch/sparc/include/asm/atomic_32.h
++++ b/arch/sparc/include/asm/atomic_32.h
+@@ -21,7 +21,7 @@
+ extern int __atomic_add_return(int, atomic_t *);
+ extern int atomic_cmpxchg(atomic_t *, int, int);
+-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
++extern int atomic_xchg(atomic_t *, int);
+ extern int __atomic_add_unless(atomic_t *, int, int);
+ extern void atomic_set(atomic_t *, int);
+--- a/arch/sparc/include/asm/cmpxchg_32.h
++++ b/arch/sparc/include/asm/cmpxchg_32.h
+@@ -11,22 +11,14 @@
+ #ifndef __ARCH_SPARC_CMPXCHG__
+ #define __ARCH_SPARC_CMPXCHG__
+-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
+-{
+-      __asm__ __volatile__("swap [%2], %0"
+-                           : "=&r" (val)
+-                           : "0" (val), "r" (m)
+-                           : "memory");
+-      return val;
+-}
+-
++extern unsigned long __xchg_u32(volatile u32 *m, u32 new);
+ extern void __xchg_called_with_bad_pointer(void);
+ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+ {
+       switch (size) {
+       case 4:
+-              return xchg_u32(ptr, x);
++              return __xchg_u32(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+--- a/arch/sparc/lib/atomic32.c
++++ b/arch/sparc/lib/atomic32.c
+@@ -40,6 +40,19 @@ int __atomic_add_return(int i, atomic_t
+ }
+ EXPORT_SYMBOL(__atomic_add_return);
++int atomic_xchg(atomic_t *v, int new)
++{
++      int ret;
++      unsigned long flags;
++
++      spin_lock_irqsave(ATOMIC_HASH(v), flags);
++      ret = v->counter;
++      v->counter = new;
++      spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
++      return ret;
++}
++EXPORT_SYMBOL(atomic_xchg);
++
+ int atomic_cmpxchg(atomic_t *v, int old, int new)
+ {
+       int ret;
+@@ -132,3 +145,17 @@ unsigned long __cmpxchg_u32(volatile u32
+       return (unsigned long)prev;
+ }
+ EXPORT_SYMBOL(__cmpxchg_u32);
++
++unsigned long __xchg_u32(volatile u32 *ptr, u32 new)
++{
++      unsigned long flags;
++      u32 prev;
++
++      spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
++      prev = *ptr;
++      *ptr = new;
++      spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
++
++      return (unsigned long)prev;
++}
++EXPORT_SYMBOL(__xchg_u32);
diff --git a/queue-3.10/sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch b/queue-3.10/sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch
new file mode 100644 (file)
index 0000000..46013d2
--- /dev/null
@@ -0,0 +1,80 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: "David S. Miller" <davem@davemloft.net>
+Date: Fri, 7 Nov 2014 09:50:48 -0800
+Subject: sparc64: Do irq_{enter,exit}() around generic_smp_call_function*().
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit ab5c780913bca0a5763ca05dd5c2cb5cb08ccb26 ]
+
+Otherwise rcu_irq_{enter,exit}() do not happen and we get dumps like:
+
+====================
+[  188.275021] ===============================
+[  188.309351] [ INFO: suspicious RCU usage. ]
+[  188.343737] 3.18.0-rc3-00068-g20f3963-dirty #54 Not tainted
+[  188.394786] -------------------------------
+[  188.429170] include/linux/rcupdate.h:883 rcu_read_lock() used
+illegally while idle!
+[  188.505235]
+other info that might help us debug this:
+
+[  188.554230]
+RCU used illegally from idle CPU!
+rcu_scheduler_active = 1, debug_locks = 0
+[  188.637587] RCU used illegally from extended quiescent state!
+[  188.690684] 3 locks held by swapper/7/0:
+[  188.721932]  #0:  (&x->wait#11){......}, at: [<0000000000495de8>] complete+0x8/0x60
+[  188.797994]  #1:  (&p->pi_lock){-.-.-.}, at: [<000000000048510c>] try_to_wake_up+0xc/0x400
+[  188.881343]  #2:  (rcu_read_lock){......}, at: [<000000000048a910>] select_task_rq_fair+0x90/0xb40
+[  188.973043]stack backtrace:
+[  188.993879] CPU: 7 PID: 0 Comm: swapper/7 Not tainted 3.18.0-rc3-00068-g20f3963-dirty #54
+[  189.076187] Call Trace:
+[  189.089719]  [0000000000499360] lockdep_rcu_suspicious+0xe0/0x100
+[  189.147035]  [000000000048a99c] select_task_rq_fair+0x11c/0xb40
+[  189.202253]  [00000000004852d8] try_to_wake_up+0x1d8/0x400
+[  189.252258]  [000000000048554c] default_wake_function+0xc/0x20
+[  189.306435]  [0000000000495554] __wake_up_common+0x34/0x80
+[  189.356448]  [00000000004955b4] __wake_up_locked+0x14/0x40
+[  189.406456]  [0000000000495e08] complete+0x28/0x60
+[  189.448142]  [0000000000636e28] blk_end_sync_rq+0x8/0x20
+[  189.496057]  [0000000000639898] __blk_mq_end_request+0x18/0x60
+[  189.550249]  [00000000006ee014] scsi_end_request+0x94/0x180
+[  189.601286]  [00000000006ee334] scsi_io_completion+0x1d4/0x600
+[  189.655463]  [00000000006e51c4] scsi_finish_command+0xc4/0xe0
+[  189.708598]  [00000000006ed958] scsi_softirq_done+0x118/0x140
+[  189.761735]  [00000000006398ec] __blk_mq_complete_request_remote+0xc/0x20
+[  189.827383]  [00000000004c75d0] generic_smp_call_function_single_interrupt+0x150/0x1c0
+[  189.906581]  [000000000043e514] smp_call_function_single_client+0x14/0x40
+====================
+
+Based almost entirely upon a patch by Paul E. McKenney.
+
+Reported-by: Meelis Roos <mroos@linux.ee>
+Tested-by: Meelis Roos <mroos@linux.ee>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/kernel/smp_64.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/sparc/kernel/smp_64.c
++++ b/arch/sparc/kernel/smp_64.c
+@@ -821,13 +821,17 @@ void arch_send_call_function_single_ipi(
+ void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)
+ {
+       clear_softint(1 << irq);
++      irq_enter();
+       generic_smp_call_function_interrupt();
++      irq_exit();
+ }
+ void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs)
+ {
+       clear_softint(1 << irq);
++      irq_enter();
+       generic_smp_call_function_single_interrupt();
++      irq_exit();
+ }
+ static void tsb_sync(void *info)
diff --git a/queue-3.10/sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch b/queue-3.10/sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch
new file mode 100644 (file)
index 0000000..82e09cf
--- /dev/null
@@ -0,0 +1,99 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: "David S. Miller" <davem@davemloft.net>
+Date: Sat, 1 Nov 2014 00:33:58 -0400
+Subject: sparc64: Fix crashes in schizo_pcierr_intr_other().
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 7da89a2a3776442a57e918ca0b8678d1b16a7072 ]
+
+Meelis Roos reports crashes during bootup on a V480 that look like
+this:
+
+====================
+[   61.300577] PCI: Scanning PBM /pci@9,600000
+[   61.304867] schizo f009b070: PCI host bridge to bus 0003:00
+[   61.310385] pci_bus 0003:00: root bus resource [io  0x7ffe9000000-0x7ffe9ffffff] (bus address [0x0000-0xffffff])
+[   61.320515] pci_bus 0003:00: root bus resource [mem 0x7fb00000000-0x7fbffffffff] (bus address [0x00000000-0xffffffff])
+[   61.331173] pci_bus 0003:00: root bus resource [bus 00]
+[   61.385344] Unable to handle kernel NULL pointer dereference
+[   61.390970] tsk->{mm,active_mm}->context = 0000000000000000
+[   61.396515] tsk->{mm,active_mm}->pgd = fff000b000002000
+[   61.401716]               \|/ ____ \|/
+[   61.401716]               "@'/ .. \`@"
+[   61.401716]               /_| \__/ |_\
+[   61.401716]                  \__U_/
+[   61.416362] swapper/0(0): Oops [#1]
+[   61.419837] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.18.0-rc1-00422-g2cc9188-dirty #24
+[   61.427975] task: fff000b0fd8e9c40 ti: fff000b0fd928000 task.ti: fff000b0fd928000
+[   61.435426] TSTATE: 0000004480e01602 TPC: 00000000004455e4 TNPC: 00000000004455e8 Y: 00000000    Not tainted
+[   61.445230] TPC: <schizo_pcierr_intr+0x104/0x560>
+[   61.449897] g0: 0000000000000000 g1: 0000000000000000 g2: 0000000000a10f78 g3: 000000000000000a
+[   61.458563] g4: fff000b0fd8e9c40 g5: fff000b0fdd82000 g6: fff000b0fd928000 g7: 000000000000000a
+[   61.467229] o0: 000000000000003d o1: 0000000000000000 o2: 0000000000000006 o3: fff000b0ffa5fc7e
+[   61.475894] o4: 0000000000060000 o5: c000000000000000 sp: fff000b0ffa5f3c1 ret_pc: 00000000004455cc
+[   61.484909] RPC: <schizo_pcierr_intr+0xec/0x560>
+[   61.489500] l0: fff000b0fd8e9c40 l1: 0000000000a20800 l2: 0000000000000000 l3: 000000000119a430
+[   61.498164] l4: 0000000001742400 l5: 00000000011cfbe0 l6: 00000000011319c0 l7: fff000b0fd8ea348
+[   61.506830] i0: 0000000000000000 i1: fff000b0fdb34000 i2: 0000000320000000 i3: 0000000000000000
+[   61.515497] i4: 00060002010b003f i5: 0000040004e02000 i6: fff000b0ffa5f481 i7: 00000000004a9920
+[   61.524175] I7: <handle_irq_event_percpu+0x40/0x140>
+[   61.529099] Call Trace:
+[   61.531531]  [00000000004a9920] handle_irq_event_percpu+0x40/0x140
+[   61.537681]  [00000000004a9a58] handle_irq_event+0x38/0x80
+[   61.543145]  [00000000004ac77c] handle_fasteoi_irq+0xbc/0x200
+[   61.548860]  [00000000004a9084] generic_handle_irq+0x24/0x40
+[   61.554500]  [000000000042be0c] handler_irq+0xac/0x100
+====================
+
+The problem is that pbm->pci_bus->self is NULL.
+
+This code is trying to go through the standard PCI config space
+interfaces to read the PCI controller's PCI_STATUS register.
+
+This doesn't work, because we more often than not do not enumerate
+the PCI controller as a bonafide PCI device during the OF device
+node scan.  Therefore bus->self remains NULL.
+
+Existing common code for PSYCHO and PSYCHO-like PCI controllers
+handles this properly, by doing the config space access directly.
+
+Do the same here, pbm->pci_ops->{read,write}().
+
+Reported-by: Meelis Roos <mroos@linux.ee>
+Tested-by: Meelis Roos <mroos@linux.ee>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/kernel/pci_schizo.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/sparc/kernel/pci_schizo.c
++++ b/arch/sparc/kernel/pci_schizo.c
+@@ -581,7 +581,7 @@ static irqreturn_t schizo_pcierr_intr_ot
+ {
+       unsigned long csr_reg, csr, csr_error_bits;
+       irqreturn_t ret = IRQ_NONE;
+-      u16 stat;
++      u32 stat;
+       csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL;
+       csr = upa_readq(csr_reg);
+@@ -617,7 +617,7 @@ static irqreturn_t schizo_pcierr_intr_ot
+                              pbm->name);
+               ret = IRQ_HANDLED;
+       }
+-      pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat);
++      pbm->pci_ops->read(pbm->pci_bus, 0, PCI_STATUS, 2, &stat);
+       if (stat & (PCI_STATUS_PARITY |
+                   PCI_STATUS_SIG_TARGET_ABORT |
+                   PCI_STATUS_REC_TARGET_ABORT |
+@@ -625,7 +625,7 @@ static irqreturn_t schizo_pcierr_intr_ot
+                   PCI_STATUS_SIG_SYSTEM_ERROR)) {
+               printk("%s: PCI bus error, PCI_STATUS[%04x]\n",
+                      pbm->name, stat);
+-              pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff);
++              pbm->pci_ops->write(pbm->pci_bus, 0, PCI_STATUS, 2, 0xffff);
+               ret = IRQ_HANDLED;
+       }
+       return ret;
diff --git a/queue-3.10/sunvdc-add-cdrom-and-v1.1-protocol-support.patch b/queue-3.10/sunvdc-add-cdrom-and-v1.1-protocol-support.patch
new file mode 100644 (file)
index 0000000..49d22b9
--- /dev/null
@@ -0,0 +1,246 @@
+From foo@baz Tue Nov 18 09:08:46 PST 2014
+From: Allen Pais <allen.pais@oracle.com>
+Date: Fri, 19 Sep 2014 09:42:14 -0400
+Subject: sunvdc: add cdrom and v1.1 protocol support
+
+From: Allen Pais <allen.pais@oracle.com>
+
+[ Upstream commit 9bce21828d54a95143f1b74619705c2dd8e88b92 ]
+
+Interpret the media type from v1.1 protocol to support CDROM/DVD.
+
+For v1.0 protocol, a disk's size continues to be calculated from the
+geometry returned by the vdisk server. The geometry returned by the server
+can be less than the actual number of sectors available in the backing
+image/device due to the rounding in the division used to compute the
+geometry in the vdisk server.
+
+In v1.1 protocol a disk's actual size in sectors is returned during the
+handshake. Use this size when v1.1 protocol is negotiated. Since this size
+will always be larger than the former geometry computed size, disks created
+under v1.0 will be forwards compatible to v1.1, but not vice versa.
+
+Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/include/asm/vio.h |   12 +++-
+ drivers/block/sunvdc.c       |  109 ++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 101 insertions(+), 20 deletions(-)
+
+--- a/arch/sparc/include/asm/vio.h
++++ b/arch/sparc/include/asm/vio.h
+@@ -118,12 +118,18 @@ struct vio_disk_attr_info {
+       u8                      vdisk_type;
+ #define VD_DISK_TYPE_SLICE    0x01 /* Slice in block device   */
+ #define VD_DISK_TYPE_DISK     0x02 /* Entire block device     */
+-      u16                     resv1;
++      u8                      vdisk_mtype;            /* v1.1 */
++#define VD_MEDIA_TYPE_FIXED   0x01 /* Fixed device */
++#define VD_MEDIA_TYPE_CD      0x02 /* CD Device    */
++#define VD_MEDIA_TYPE_DVD     0x03 /* DVD Device   */
++      u8                      resv1;
+       u32                     vdisk_block_size;
+       u64                     operations;
+-      u64                     vdisk_size;
++      u64                     vdisk_size;             /* v1.1 */
+       u64                     max_xfer_size;
+-      u64                     resv2[2];
++      u32                     phys_block_size;        /* v1.2 */
++      u32                     resv2;
++      u64                     resv3[1];
+ };
+ struct vio_disk_desc {
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -9,6 +9,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/genhd.h>
++#include <linux/cdrom.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/completion.h>
+@@ -22,8 +23,8 @@
+ #define DRV_MODULE_NAME               "sunvdc"
+ #define PFX DRV_MODULE_NAME   ": "
+-#define DRV_MODULE_VERSION    "1.0"
+-#define DRV_MODULE_RELDATE    "June 25, 2007"
++#define DRV_MODULE_VERSION    "1.1"
++#define DRV_MODULE_RELDATE    "February 13, 2013"
+ static char version[] =
+       DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+@@ -65,6 +66,7 @@ struct vdc_port {
+       u64                     operations;
+       u32                     vdisk_size;
+       u8                      vdisk_type;
++      u8                      vdisk_mtype;
+       char                    disk_name[32];
+@@ -79,9 +81,16 @@ static inline struct vdc_port *to_vdc_po
+ /* Ordered from largest major to lowest */
+ static struct vio_version vdc_versions[] = {
++      { .major = 1, .minor = 1 },
+       { .major = 1, .minor = 0 },
+ };
++static inline int vdc_version_supported(struct vdc_port *port,
++                                      u16 major, u16 minor)
++{
++      return port->vio.ver.major == major && port->vio.ver.minor >= minor;
++}
++
+ #define VDCBLK_NAME   "vdisk"
+ static int vdc_major;
+ #define PARTITION_SHIFT       3
+@@ -103,9 +112,41 @@ static int vdc_getgeo(struct block_devic
+       return 0;
+ }
++/* Add ioctl/CDROM_GET_CAPABILITY to support cdrom_id in udev
++ * when vdisk_mtype is VD_MEDIA_TYPE_CD or VD_MEDIA_TYPE_DVD.
++ * Needed to be able to install inside an ldom from an iso image.
++ */
++static int vdc_ioctl(struct block_device *bdev, fmode_t mode,
++                   unsigned command, unsigned long argument)
++{
++      int i;
++      struct gendisk *disk;
++
++      switch (command) {
++      case CDROMMULTISESSION:
++              pr_debug(PFX "Multisession CDs not supported\n");
++              for (i = 0; i < sizeof(struct cdrom_multisession); i++)
++                      if (put_user(0, (char __user *)(argument + i)))
++                              return -EFAULT;
++              return 0;
++
++      case CDROM_GET_CAPABILITY:
++              disk = bdev->bd_disk;
++
++              if (bdev->bd_disk && (disk->flags & GENHD_FL_CD))
++                      return 0;
++              return -EINVAL;
++
++      default:
++              pr_debug(PFX "ioctl %08x not supported\n", command);
++              return -EINVAL;
++      }
++}
++
+ static const struct block_device_operations vdc_fops = {
+       .owner          = THIS_MODULE,
+       .getgeo         = vdc_getgeo,
++      .ioctl          = vdc_ioctl,
+ };
+ static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
+@@ -165,9 +206,9 @@ static int vdc_handle_attr(struct vio_dr
+       struct vio_disk_attr_info *pkt = arg;
+       viodbg(HS, "GOT ATTR stype[0x%x] ops[%llx] disk_size[%llu] disk_type[%x] "
+-             "xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n",
++             "mtype[0x%x] xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n",
+              pkt->tag.stype, pkt->operations,
+-             pkt->vdisk_size, pkt->vdisk_type,
++             pkt->vdisk_size, pkt->vdisk_type, pkt->vdisk_mtype,
+              pkt->xfer_mode, pkt->vdisk_block_size,
+              pkt->max_xfer_size);
+@@ -192,8 +233,11 @@ static int vdc_handle_attr(struct vio_dr
+               }
+               port->operations = pkt->operations;
+-              port->vdisk_size = pkt->vdisk_size;
+               port->vdisk_type = pkt->vdisk_type;
++              if (vdc_version_supported(port, 1, 1)) {
++                      port->vdisk_size = pkt->vdisk_size;
++                      port->vdisk_mtype = pkt->vdisk_mtype;
++              }
+               if (pkt->max_xfer_size < port->max_xfer_size)
+                       port->max_xfer_size = pkt->max_xfer_size;
+               port->vdisk_block_size = pkt->vdisk_block_size;
+@@ -663,18 +707,25 @@ static int probe_disk(struct vdc_port *p
+               return err;
+       }
+-      err = generic_request(port, VD_OP_GET_DISKGEOM,
+-                            &port->geom, sizeof(port->geom));
+-      if (err < 0) {
+-              printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
+-                     "error %d\n", err);
+-              return err;
++      if (vdc_version_supported(port, 1, 1)) {
++              /* vdisk_size should be set during the handshake, if it wasn't
++               * then the underlying disk is reserved by another system
++               */
++              if (port->vdisk_size == -1)
++                      return -ENODEV;
++      } else {
++              err = generic_request(port, VD_OP_GET_DISKGEOM,
++                                    &port->geom, sizeof(port->geom));
++              if (err < 0) {
++                      printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
++                             "error %d\n", err);
++                      return err;
++              }
++              port->vdisk_size = ((u64)port->geom.num_cyl *
++                                  (u64)port->geom.num_hd *
++                                  (u64)port->geom.num_sec);
+       }
+-      port->vdisk_size = ((u64)port->geom.num_cyl *
+-                          (u64)port->geom.num_hd *
+-                          (u64)port->geom.num_sec);
+-
+       q = blk_init_queue(do_vdc_request, &port->vio.lock);
+       if (!q) {
+               printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
+@@ -704,9 +755,32 @@ static int probe_disk(struct vdc_port *p
+       set_capacity(g, port->vdisk_size);
+-      printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n",
++      if (vdc_version_supported(port, 1, 1)) {
++              switch (port->vdisk_mtype) {
++              case VD_MEDIA_TYPE_CD:
++                      pr_info(PFX "Virtual CDROM %s\n", port->disk_name);
++                      g->flags |= GENHD_FL_CD;
++                      g->flags |= GENHD_FL_REMOVABLE;
++                      set_disk_ro(g, 1);
++                      break;
++
++              case VD_MEDIA_TYPE_DVD:
++                      pr_info(PFX "Virtual DVD %s\n", port->disk_name);
++                      g->flags |= GENHD_FL_CD;
++                      g->flags |= GENHD_FL_REMOVABLE;
++                      set_disk_ro(g, 1);
++                      break;
++
++              case VD_MEDIA_TYPE_FIXED:
++                      pr_info(PFX "Virtual Hard disk %s\n", port->disk_name);
++                      break;
++              }
++      }
++
++      pr_info(PFX "%s: %u sectors (%u MB) protocol %d.%d\n",
+              g->disk_name,
+-             port->vdisk_size, (port->vdisk_size >> (20 - 9)));
++             port->vdisk_size, (port->vdisk_size >> (20 - 9)),
++             port->vio.ver.major, port->vio.ver.minor);
+       add_disk(g);
+@@ -765,6 +839,7 @@ static int vdc_port_probe(struct vio_dev
+       else
+               snprintf(port->disk_name, sizeof(port->disk_name),
+                        VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26));
++      port->vdisk_size = -1;
+       err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
+                             vdc_versions, ARRAY_SIZE(vdc_versions),
diff --git a/queue-3.10/sunvdc-compute-vdisk-geometry-from-capacity.patch b/queue-3.10/sunvdc-compute-vdisk-geometry-from-capacity.patch
new file mode 100644 (file)
index 0000000..a84dd37
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: Allen Pais <allen.pais@oracle.com>
+Date: Fri, 19 Sep 2014 09:42:26 -0400
+Subject: sunvdc: compute vdisk geometry from capacity
+
+From: Allen Pais <allen.pais@oracle.com>
+
+[ Upstream commit de5b73f08468b4fc5e2f6d1505f650262622f78b ]
+
+The LDom diskserver doesn't return reliable geometry data. In addition,
+the types for all fields in the vio_disk_geom are u16, which were being
+truncated in the cast into the u8's of the Linux struct hd_geometry.
+
+Modify vdc_getgeo() to compute the geometry from the disk's capacity in a
+manner consistent with xen-blkfront::blkif_getgeo().
+
+Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/sunvdc.c |   23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -70,7 +70,6 @@ struct vdc_port {
+       char                    disk_name[32];
+-      struct vio_disk_geom    geom;
+       struct vio_disk_vtoc    label;
+ };
+@@ -103,11 +102,15 @@ static inline u32 vdc_tx_dring_avail(str
+ static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+ {
+       struct gendisk *disk = bdev->bd_disk;
+-      struct vdc_port *port = disk->private_data;
++      sector_t nsect = get_capacity(disk);
++      sector_t cylinders = nsect;
+-      geo->heads = (u8) port->geom.num_hd;
+-      geo->sectors = (u8) port->geom.num_sec;
+-      geo->cylinders = port->geom.num_cyl;
++      geo->heads = 0xff;
++      geo->sectors = 0x3f;
++      sector_div(cylinders, geo->heads * geo->sectors);
++      geo->cylinders = cylinders;
++      if ((sector_t)(geo->cylinders + 1) * geo->heads * geo->sectors < nsect)
++              geo->cylinders = 0xffff;
+       return 0;
+ }
+@@ -714,16 +717,18 @@ static int probe_disk(struct vdc_port *p
+               if (port->vdisk_size == -1)
+                       return -ENODEV;
+       } else {
++              struct vio_disk_geom geom;
++
+               err = generic_request(port, VD_OP_GET_DISKGEOM,
+-                                    &port->geom, sizeof(port->geom));
++                                    &geom, sizeof(geom));
+               if (err < 0) {
+                       printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
+                              "error %d\n", err);
+                       return err;
+               }
+-              port->vdisk_size = ((u64)port->geom.num_cyl *
+-                                  (u64)port->geom.num_hd *
+-                                  (u64)port->geom.num_sec);
++              port->vdisk_size = ((u64)geom.num_cyl *
++                                  (u64)geom.num_hd *
++                                  (u64)geom.num_sec);
+       }
+       q = blk_init_queue(do_vdc_request, &port->vio.lock);
diff --git a/queue-3.10/sunvdc-don-t-call-vd_op_get_vtoc.patch b/queue-3.10/sunvdc-don-t-call-vd_op_get_vtoc.patch
new file mode 100644 (file)
index 0000000..81ed98b
--- /dev/null
@@ -0,0 +1,48 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: Dwight Engen <dwight.engen@oracle.com>
+Date: Thu, 30 Oct 2014 15:55:35 -0400
+Subject: sunvdc: don't call VD_OP_GET_VTOC
+
+From: Dwight Engen <dwight.engen@oracle.com>
+
+[ Upstream commit 85b0c6e62c48bb9179fd5b3e954f362fb346cbd5 ]
+
+The VD_OP_GET_VTOC operation will succeed only if the vdisk backend has a
+VTOC label, otherwise it will fail. In particular, it will return error
+48 (ENOTSUP) if the disk has an EFI label. VTOC disk labels are already
+handled by directly reading the disk in block/partitions/sun.c (enabled by
+CONFIG_SUN_PARTITION which defaults to y on SPARC). Since port->label is
+unused in the driver, remove the call and the field.
+
+Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/sunvdc.c |    9 ---------
+ 1 file changed, 9 deletions(-)
+
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -69,8 +69,6 @@ struct vdc_port {
+       u8                      vdisk_mtype;
+       char                    disk_name[32];
+-
+-      struct vio_disk_vtoc    label;
+ };
+ static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
+@@ -710,13 +708,6 @@ static int probe_disk(struct vdc_port *p
+       if (comp.err)
+               return comp.err;
+-      err = generic_request(port, VD_OP_GET_VTOC,
+-                            &port->label, sizeof(port->label));
+-      if (err < 0) {
+-              printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
+-              return err;
+-      }
+-
+       if (vdc_version_supported(port, 1, 1)) {
+               /* vdisk_size should be set during the handshake, if it wasn't
+                * then the underlying disk is reserved by another system
diff --git a/queue-3.10/sunvdc-limit-each-sg-segment-to-a-page.patch b/queue-3.10/sunvdc-limit-each-sg-segment-to-a-page.patch
new file mode 100644 (file)
index 0000000..e1861ed
--- /dev/null
@@ -0,0 +1,40 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: Dwight Engen <dwight.engen@oracle.com>
+Date: Fri, 19 Sep 2014 09:42:53 -0400
+Subject: sunvdc: limit each sg segment to a page
+
+From: Dwight Engen <dwight.engen@oracle.com>
+
+[ Upstream commit 5eed69ffd248c9f68f56c710caf07db134aef28b ]
+
+ldc_map_sg() could fail its check that the number of pages referred to
+by the sg scatterlist was <= the number of cookies.
+
+This fixes the issue by doing a similar thing to the xen-blkfront driver,
+ensuring that the scatterlist will only ever contain a segment count <=
+port->ring_cookies, and each segment will be page aligned, and <= page
+size. This ensures that the scatterlist is always mappable.
+
+Orabug: 19347817
+OraBZ: 15945
+
+Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/sunvdc.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -747,6 +747,10 @@ static int probe_disk(struct vdc_port *p
+       port->disk = g;
++      /* Each segment in a request is up to an aligned page in size. */
++      blk_queue_segment_boundary(q, PAGE_SIZE - 1);
++      blk_queue_max_segment_size(q, PAGE_SIZE);
++
+       blk_queue_max_segments(q, port->ring_cookies);
+       blk_queue_max_hw_sectors(q, port->max_xfer_size);
+       g->major = vdc_major;
diff --git a/queue-3.10/vio-fix-reuse-of-vio_dring-slot.patch b/queue-3.10/vio-fix-reuse-of-vio_dring-slot.patch
new file mode 100644 (file)
index 0000000..e2c48c2
--- /dev/null
@@ -0,0 +1,145 @@
+From foo@baz Tue Nov 18 09:08:47 PST 2014
+From: Dwight Engen <dwight.engen@oracle.com>
+Date: Fri, 19 Sep 2014 09:43:02 -0400
+Subject: vio: fix reuse of vio_dring slot
+
+From: Dwight Engen <dwight.engen@oracle.com>
+
+[ Upstream commit d0aedcd4f14a22e23b313f42b7e6e6ebfc0fbc31 ]
+
+vio_dring_avail() will allow use of every dring entry, but when the last
+entry is allocated then dr->prod == dr->cons which is indistinguishable from
+the ring empty condition. This causes the next allocation to reuse an entry.
+When this happens in sunvdc, the server side vds driver begins nack'ing the
+messages and ends up resetting the ldc channel. This problem does not effect
+sunvnet since it checks for < 2.
+
+The fix here is to just never allocate the very last dring slot so that full
+and empty are not the same condition. The request start path was changed to
+check for the ring being full a bit earlier, and to stop the blk_queue if
+there is no space left. The blk_queue will be restarted once the ring is
+only half full again. The number of ring entries was increased to 512 which
+matches the sunvnet and Solaris vdc drivers, and greatly reduces the
+frequency of hitting the ring full condition and the associated blk_queue
+stop/starting. The checks in sunvent were adjusted to account for
+vio_dring_avail() returning 1 less.
+
+Orabug: 19441666
+OraBZ: 14983
+
+Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/sparc/include/asm/vio.h       |    2 -
+ drivers/block/sunvdc.c             |   39 +++++++++++++++++++++----------------
+ drivers/net/ethernet/sun/sunvnet.c |    4 +--
+ 3 files changed, 26 insertions(+), 19 deletions(-)
+
+--- a/arch/sparc/include/asm/vio.h
++++ b/arch/sparc/include/asm/vio.h
+@@ -265,7 +265,7 @@ static inline u32 vio_dring_avail(struct
+                                 unsigned int ring_size)
+ {
+       return (dr->pending -
+-              ((dr->prod - dr->cons) & (ring_size - 1)));
++              ((dr->prod - dr->cons) & (ring_size - 1)) - 1);
+ }
+ #define VIO_MAX_TYPE_LEN      32
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("Sun LDOM virtual dis
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_MODULE_VERSION);
+-#define VDC_TX_RING_SIZE      256
++#define VDC_TX_RING_SIZE      512
+ #define WAITING_FOR_LINK_UP   0x01
+ #define WAITING_FOR_TX_SPACE  0x02
+@@ -283,7 +283,9 @@ static void vdc_end_one(struct vdc_port
+       __blk_end_request(req, (desc->status ? -EIO : 0), desc->size);
+-      if (blk_queue_stopped(port->disk->queue))
++      /* restart blk queue when ring is half emptied */
++      if (blk_queue_stopped(port->disk->queue) &&
++          vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50)
+               blk_start_queue(port->disk->queue);
+ }
+@@ -435,12 +437,6 @@ static int __send_request(struct request
+       for (i = 0; i < nsg; i++)
+               len += sg[i].length;
+-      if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
+-              blk_stop_queue(port->disk->queue);
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+       desc = vio_dring_cur(dr);
+       err = ldc_map_sg(port->vio.lp, sg, nsg,
+@@ -480,21 +476,32 @@ static int __send_request(struct request
+               port->req_id++;
+               dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+       }
+-out:
+       return err;
+ }
+-static void do_vdc_request(struct request_queue *q)
++static void do_vdc_request(struct request_queue *rq)
+ {
+-      while (1) {
+-              struct request *req = blk_fetch_request(q);
++      struct request *req;
+-              if (!req)
++      while ((req = blk_peek_request(rq)) != NULL) {
++              struct vdc_port *port;
++              struct vio_dring_state *dr;
++
++              port = req->rq_disk->private_data;
++              dr = &port->vio.drings[VIO_DRIVER_TX_RING];
++              if (unlikely(vdc_tx_dring_avail(dr) < 1))
++                      goto wait;
++
++              blk_start_request(req);
++
++              if (__send_request(req) < 0) {
++                      blk_requeue_request(rq, req);
++wait:
++                      /* Avoid pointless unplugs. */
++                      blk_stop_queue(rq);
+                       break;
+-
+-              if (__send_request(req) < 0)
+-                      __blk_end_request_all(req, -EIO);
++              }
+       }
+ }
+--- a/drivers/net/ethernet/sun/sunvnet.c
++++ b/drivers/net/ethernet/sun/sunvnet.c
+@@ -656,7 +656,7 @@ static int vnet_start_xmit(struct sk_buf
+       spin_lock_irqsave(&port->vio.lock, flags);
+       dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+-      if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
++      if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
+               if (!netif_queue_stopped(dev)) {
+                       netif_stop_queue(dev);
+@@ -704,7 +704,7 @@ static int vnet_start_xmit(struct sk_buf
+       dev->stats.tx_bytes += skb->len;
+       dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
+-      if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
++      if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
+               netif_stop_queue(dev);
+               if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
+                       netif_wake_queue(dev);