]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.17-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Nov 2014 17:12:23 +0000 (09:12 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Nov 2014 17:12:23 +0000 (09:12 -0800)
added patches:
gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch
inet-frags-fix-a-race-between-inet_evict_bucket-and-inet_frag_kill.patch
inet-frags-remove-the-warn_on-from-inet_evict_bucket.patch
ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch
ipv6-fix-ipv6_pktinfo-with-v4-mapped.patch
net-mv643xx_eth-reclaim-tx-skbs-only-when-released-by-the-hw.patch
net-ppp-don-t-call-bpf_prog_create-in-ppp_lock.patch
net-ptp-fix-time-stamp-matching-logic-for-vlan-packets.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
netlink-properly-unbind-in-error-conditions.patch
sit-use-ipip6_tunnel_init-as-the-ndo_init-function.patch
smsc911x-power-up-phydev-before-doing-a-software-reset.patch
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
udptunnel-add-skb_gso_udp_tunnel-during-gro_complete.patch
vio-fix-reuse-of-vio_dring-slot.patch
vti6-use-vti6_dev_init-as-the-ndo_init-function.patch
vxlan-do-not-reuse-sockets-for-a-different-address-family.patch

25 files changed:
queue-3.17/gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch [new file with mode: 0644]
queue-3.17/inet-frags-fix-a-race-between-inet_evict_bucket-and-inet_frag_kill.patch [new file with mode: 0644]
queue-3.17/inet-frags-remove-the-warn_on-from-inet_evict_bucket.patch [new file with mode: 0644]
queue-3.17/ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch [new file with mode: 0644]
queue-3.17/ipv6-fix-ipv6_pktinfo-with-v4-mapped.patch [new file with mode: 0644]
queue-3.17/net-mv643xx_eth-reclaim-tx-skbs-only-when-released-by-the-hw.patch [new file with mode: 0644]
queue-3.17/net-ppp-don-t-call-bpf_prog_create-in-ppp_lock.patch [new file with mode: 0644]
queue-3.17/net-ptp-fix-time-stamp-matching-logic-for-vlan-packets.patch [new file with mode: 0644]
queue-3.17/net-sctp-fix-memory-leak-in-auth-key-management.patch [new file with mode: 0644]
queue-3.17/net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch [new file with mode: 0644]
queue-3.17/netlink-properly-unbind-in-error-conditions.patch [new file with mode: 0644]
queue-3.17/series
queue-3.17/sit-use-ipip6_tunnel_init-as-the-ndo_init-function.patch [new file with mode: 0644]
queue-3.17/smsc911x-power-up-phydev-before-doing-a-software-reset.patch [new file with mode: 0644]
queue-3.17/sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch [new file with mode: 0644]
queue-3.17/sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch [new file with mode: 0644]
queue-3.17/sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch [new file with mode: 0644]
queue-3.17/sunvdc-add-cdrom-and-v1.1-protocol-support.patch [new file with mode: 0644]
queue-3.17/sunvdc-compute-vdisk-geometry-from-capacity.patch [new file with mode: 0644]
queue-3.17/sunvdc-don-t-call-vd_op_get_vtoc.patch [new file with mode: 0644]
queue-3.17/sunvdc-limit-each-sg-segment-to-a-page.patch [new file with mode: 0644]
queue-3.17/udptunnel-add-skb_gso_udp_tunnel-during-gro_complete.patch [new file with mode: 0644]
queue-3.17/vio-fix-reuse-of-vio_dring-slot.patch [new file with mode: 0644]
queue-3.17/vti6-use-vti6_dev_init-as-the-ndo_init-function.patch [new file with mode: 0644]
queue-3.17/vxlan-do-not-reuse-sockets-for-a-different-address-family.patch [new file with mode: 0644]

diff --git a/queue-3.17/gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch b/queue-3.17/gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch
new file mode 100644 (file)
index 0000000..009a96e
--- /dev/null
@@ -0,0 +1,46 @@
+From foo@baz Tue Nov 18 09:07:25 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 |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -957,8 +957,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)
+@@ -1268,6 +1266,7 @@ static int ip6gre_tunnel_init(struct net
+               u64_stats_init(&ip6gre_tunnel_stats->syncp);
+       }
++      dev->iflink = tunnel->parms.link;
+       return 0;
+ }
+@@ -1477,6 +1476,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.17/inet-frags-fix-a-race-between-inet_evict_bucket-and-inet_frag_kill.patch b/queue-3.17/inet-frags-fix-a-race-between-inet_evict_bucket-and-inet_frag_kill.patch
new file mode 100644 (file)
index 0000000..5704bd2
--- /dev/null
@@ -0,0 +1,62 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Nikolay Aleksandrov <nikolay@redhat.com>
+Date: Tue, 28 Oct 2014 10:30:34 +0100
+Subject: inet: frags: fix a race between inet_evict_bucket and inet_frag_kill
+
+From: Nikolay Aleksandrov <nikolay@redhat.com>
+
+[ Upstream commit 65ba1f1ec0eff1c25933468e1d238201c0c2cb29 ]
+
+When the evictor is running it adds some chosen frags to a local list to
+be evicted once the chain lock has been released but at the same time
+the *frag_queue can be running for some of the same queues and it
+may call inet_frag_kill which will wait on the chain lock and
+will then delete the queue from the wrong list since it was added in the
+eviction one. The fix is simple - check if the queue has the evict flag
+set under the chain lock before deleting it, this is safe because the
+evict flag is set only under that lock and having the flag set also means
+that the queue has been detached from the chain list, so no need to delete
+it again.
+An important note to make is that we're safe w.r.t refcnt because
+inet_frag_kill and inet_evict_bucket will sync on the del_timer operation
+where only one of the two can succeed (or if the timer is executing -
+none of them), the cases are:
+1. inet_frag_kill succeeds in del_timer
+ - then the timer ref is removed, but inet_evict_bucket will not add
+   this queue to its expire list but will restart eviction in that chain
+2. inet_evict_bucket succeeds in del_timer
+ - then the timer ref is kept until the evictor "expires" the queue, but
+   inet_frag_kill will remove the initial ref and will set
+   INET_FRAG_COMPLETE which will make the frag_expire fn just to remove
+   its ref.
+In the end all of the queue users will do an inet_frag_put and the one
+that reaches 0 will free it. The refcount balance should be okay.
+
+CC: Florian Westphal <fw@strlen.de>
+CC: Eric Dumazet <eric.dumazet@gmail.com>
+CC: Patrick McLean <chutzpah@gentoo.org>
+
+Fixes: b13d3cbfb8e8 ("inet: frag: move eviction of queues to work queue")
+Suggested-by: Eric Dumazet <eric.dumazet@gmail.com>
+Reported-by: Patrick McLean <chutzpah@gentoo.org>
+Tested-by: Patrick McLean <chutzpah@gentoo.org>
+Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
+Reviewed-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_fragment.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/ipv4/inet_fragment.c
++++ b/net/ipv4/inet_fragment.c
+@@ -285,7 +285,8 @@ static inline void fq_unlink(struct inet
+       struct inet_frag_bucket *hb;
+       hb = get_frag_bucket_locked(fq, f);
+-      hlist_del(&fq->list);
++      if (!(fq->flags & INET_FRAG_EVICTED))
++              hlist_del(&fq->list);
+       spin_unlock(&hb->chain_lock);
+ }
diff --git a/queue-3.17/inet-frags-remove-the-warn_on-from-inet_evict_bucket.patch b/queue-3.17/inet-frags-remove-the-warn_on-from-inet_evict_bucket.patch
new file mode 100644 (file)
index 0000000..74e99f2
--- /dev/null
@@ -0,0 +1,42 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Nikolay Aleksandrov <nikolay@redhat.com>
+Date: Tue, 28 Oct 2014 10:44:01 +0100
+Subject: inet: frags: remove the WARN_ON from inet_evict_bucket
+
+From: Nikolay Aleksandrov <nikolay@redhat.com>
+
+[ Upstream commit d70127e8a942364de8dd140fe73893efda363293 ]
+
+The WARN_ON in inet_evict_bucket can be triggered by a valid case:
+inet_frag_kill and inet_evict_bucket can be running in parallel on the
+same queue which means that there has been at least one more ref added
+by a previous inet_frag_find call, but inet_frag_kill can delete the
+timer before inet_evict_bucket which will cause the WARN_ON() there to
+trigger since we'll have refcnt!=1. Now, this case is valid because the
+queue is being "killed" for some reason (removed from the chain list and
+its timer deleted) so it will get destroyed in the end by one of the
+inet_frag_put() calls which reaches 0 i.e. refcnt is still valid.
+
+CC: Florian Westphal <fw@strlen.de>
+CC: Eric Dumazet <eric.dumazet@gmail.com>
+CC: Patrick McLean <chutzpah@gentoo.org>
+
+Fixes: b13d3cbfb8e8 ("inet: frag: move eviction of queues to work queue")
+Reported-by: Patrick McLean <chutzpah@gentoo.org>
+Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_fragment.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/net/ipv4/inet_fragment.c
++++ b/net/ipv4/inet_fragment.c
+@@ -146,7 +146,6 @@ evict_again:
+                       atomic_inc(&fq->refcnt);
+                       spin_unlock(&hb->chain_lock);
+                       del_timer_sync(&fq->timer);
+-                      WARN_ON(atomic_read(&fq->refcnt) != 1);
+                       inet_frag_put(fq, f);
+                       goto evict_again;
+               }
diff --git a/queue-3.17/ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch b/queue-3.17/ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch
new file mode 100644 (file)
index 0000000..758b0cb
--- /dev/null
@@ -0,0 +1,60 @@
+From foo@baz Tue Nov 18 09:07:25 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
+@@ -272,9 +272,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)
+@@ -1462,6 +1459,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,
+@@ -1546,16 +1544,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.17/ipv6-fix-ipv6_pktinfo-with-v4-mapped.patch b/queue-3.17/ipv6-fix-ipv6_pktinfo-with-v4-mapped.patch
new file mode 100644 (file)
index 0000000..62db1ea
--- /dev/null
@@ -0,0 +1,32 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 10 Nov 2014 17:54:25 -0800
+Subject: ipv6: fix IPV6_PKTINFO with v4 mapped
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 5337b5b75cd9bd3624a6820e3c2a084d2480061c ]
+
+Use IS_ENABLED(CONFIG_IPV6), to enable this code if IPv6 is
+a module.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Fixes: c8e6ad0829a7 ("ipv6: honor IPV6_PKTINFO with v4 mapped addresses on sendmsg")
+Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_sockglue.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -195,7 +195,7 @@ int ip_cmsg_send(struct net *net, struct
+       for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+               if (!CMSG_OK(msg, cmsg))
+                       return -EINVAL;
+-#if defined(CONFIG_IPV6)
++#if IS_ENABLED(CONFIG_IPV6)
+               if (allow_ipv6 &&
+                   cmsg->cmsg_level == SOL_IPV6 &&
+                   cmsg->cmsg_type == IPV6_PKTINFO) {
diff --git a/queue-3.17/net-mv643xx_eth-reclaim-tx-skbs-only-when-released-by-the-hw.patch b/queue-3.17/net-mv643xx_eth-reclaim-tx-skbs-only-when-released-by-the-hw.patch
new file mode 100644 (file)
index 0000000..3763f81
--- /dev/null
@@ -0,0 +1,73 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Karl Beldan <karl.beldan@rivierawaves.com>
+Date: Wed, 5 Nov 2014 15:32:59 +0100
+Subject: net: mv643xx_eth: reclaim TX skbs only when released by the HW
+
+From: Karl Beldan <karl.beldan@rivierawaves.com>
+
+[ Upstream commit 2c2a9cbd64387d6b70ac5db013e9bfe9412c7354 ]
+
+ATM, txq_reclaim will dequeue and free an skb for each tx desc released
+by the hw that has TX_LAST_DESC set. However, in case of TSO, each
+hw desc embedding the last part of a segment has TX_LAST_DESC set,
+losing the one-to-one 'last skb frag'/'TX_LAST_DESC set' correspondance,
+which causes data corruption.
+
+Fix this by checking TX_ENABLE_INTERRUPT instead of TX_LAST_DESC, and
+warn when trying to dequeue from an empty txq (which can be symptomatic
+of releasing skbs prematurely).
+
+Fixes: 3ae8f4e0b98 ('net: mv643xx_eth: Implement software TSO')
+Reported-by: Slawomir Gajzner <slawomir.gajzner@gmail.com>
+Reported-by: Julien D'Ascenzio <jdascenzio@yahoo.fr>
+Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
+Cc: Ian Campbell <ijc@hellion.org.uk>
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/marvell/mv643xx_eth.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
+@@ -1047,7 +1047,6 @@ static int txq_reclaim(struct tx_queue *
+               int tx_index;
+               struct tx_desc *desc;
+               u32 cmd_sts;
+-              struct sk_buff *skb;
+               tx_index = txq->tx_used_desc;
+               desc = &txq->tx_desc_area[tx_index];
+@@ -1066,19 +1065,22 @@ static int txq_reclaim(struct tx_queue *
+               reclaimed++;
+               txq->tx_desc_count--;
+-              skb = NULL;
+-              if (cmd_sts & TX_LAST_DESC)
+-                      skb = __skb_dequeue(&txq->tx_skb);
++              if (!IS_TSO_HEADER(txq, desc->buf_ptr))
++                      dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
++                                       desc->byte_cnt, DMA_TO_DEVICE);
++
++              if (cmd_sts & TX_ENABLE_INTERRUPT) {
++                      struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
++
++                      if (!WARN_ON(!skb))
++                              dev_kfree_skb(skb);
++              }
+               if (cmd_sts & ERROR_SUMMARY) {
+                       netdev_info(mp->dev, "tx error\n");
+                       mp->dev->stats.tx_errors++;
+               }
+-              if (!IS_TSO_HEADER(txq, desc->buf_ptr))
+-                      dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
+-                                       desc->byte_cnt, DMA_TO_DEVICE);
+-              dev_kfree_skb(skb);
+       }
+       __netif_tx_unlock_bh(nq);
diff --git a/queue-3.17/net-ppp-don-t-call-bpf_prog_create-in-ppp_lock.patch b/queue-3.17/net-ppp-don-t-call-bpf_prog_create-in-ppp_lock.patch
new file mode 100644 (file)
index 0000000..59846c1
--- /dev/null
@@ -0,0 +1,94 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 10 Nov 2014 11:50:21 +0100
+Subject: net: ppp: Don't call bpf_prog_create() in ppp_lock
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 5748eb8f8e989a9da1ac7c96dc73d68cbdedf7df ]
+
+In ppp_ioctl(), bpf_prog_create() is called inside ppp_lock, which
+eventually calls vmalloc() and hits BUG_ON() in vmalloc.c.  This patch
+works around the problem by moving the allocation outside the lock.
+
+The bug was revealed by the recent change in net/core/filter.c, as it
+allocates via vmalloc() instead of kmalloc() now.
+
+Reported-and-tested-by: Stefan Seyfried <stefan.seyfried@googlemail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ppp/ppp_generic.c |   40 ++++++++++++++++++++--------------------
+ 1 file changed, 20 insertions(+), 20 deletions(-)
+
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -755,23 +755,23 @@ static long ppp_ioctl(struct file *file,
+               err = get_filter(argp, &code);
+               if (err >= 0) {
++                      struct bpf_prog *pass_filter = NULL;
+                       struct sock_fprog_kern fprog = {
+                               .len = err,
+                               .filter = code,
+                       };
+-                      ppp_lock(ppp);
+-                      if (ppp->pass_filter) {
+-                              bpf_prog_destroy(ppp->pass_filter);
+-                              ppp->pass_filter = NULL;
++                      err = 0;
++                      if (fprog.filter)
++                              err = bpf_prog_create(&pass_filter, &fprog);
++                      if (!err) {
++                              ppp_lock(ppp);
++                              if (ppp->pass_filter)
++                                      bpf_prog_destroy(ppp->pass_filter);
++                              ppp->pass_filter = pass_filter;
++                              ppp_unlock(ppp);
+                       }
+-                      if (fprog.filter != NULL)
+-                              err = bpf_prog_create(&ppp->pass_filter,
+-                                                    &fprog);
+-                      else
+-                              err = 0;
+                       kfree(code);
+-                      ppp_unlock(ppp);
+               }
+               break;
+       }
+@@ -781,23 +781,23 @@ static long ppp_ioctl(struct file *file,
+               err = get_filter(argp, &code);
+               if (err >= 0) {
++                      struct bpf_prog *active_filter = NULL;
+                       struct sock_fprog_kern fprog = {
+                               .len = err,
+                               .filter = code,
+                       };
+-                      ppp_lock(ppp);
+-                      if (ppp->active_filter) {
+-                              bpf_prog_destroy(ppp->active_filter);
+-                              ppp->active_filter = NULL;
++                      err = 0;
++                      if (fprog.filter)
++                              err = bpf_prog_create(&active_filter, &fprog);
++                      if (!err) {
++                              ppp_lock(ppp);
++                              if (ppp->active_filter)
++                                      bpf_prog_destroy(ppp->active_filter);
++                              ppp->active_filter = active_filter;
++                              ppp_unlock(ppp);
+                       }
+-                      if (fprog.filter != NULL)
+-                              err = bpf_prog_create(&ppp->active_filter,
+-                                                    &fprog);
+-                      else
+-                              err = 0;
+                       kfree(code);
+-                      ppp_unlock(ppp);
+               }
+               break;
+       }
diff --git a/queue-3.17/net-ptp-fix-time-stamp-matching-logic-for-vlan-packets.patch b/queue-3.17/net-ptp-fix-time-stamp-matching-logic-for-vlan-packets.patch
new file mode 100644 (file)
index 0000000..027ff86
--- /dev/null
@@ -0,0 +1,58 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Richard Cochran <richardcochran@gmail.com>
+Date: Wed, 12 Nov 2014 11:33:52 +0100
+Subject: net: ptp: fix time stamp matching logic for VLAN packets.
+
+From: Richard Cochran <richardcochran@gmail.com>
+
+[ Upstream commit cca04b2854ecfb7cd1b8ee84ab38bc99af59f526 ]
+
+Commit ae5c6c6d "ptp: Classify ptp over ip over vlan packets" changed the
+code in two drivers that matches time stamps with PTP frames, with the goal
+of allowing VLAN tagged PTP packets to receive hardware time stamps.
+
+However, that commit failed to account for the VLAN header when parsing
+IPv4 packets. This patch fixes those two drivers to correctly match VLAN
+tagged IPv4/UDP PTP messages with their time stamps.
+
+This patch should also be applied to v3.17.
+
+Signed-off-by: Richard Cochran <richardcochran@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/ti/cpts.c |    2 +-
+ drivers/net/phy/dp83640.c      |    4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/ti/cpts.c
++++ b/drivers/net/ethernet/ti/cpts.c
+@@ -264,7 +264,7 @@ static int cpts_match(struct sk_buff *sk
+       switch (ptp_class & PTP_CLASS_PMASK) {
+       case PTP_CLASS_IPV4:
+-              offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
++              offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+               break;
+       case PTP_CLASS_IPV6:
+               offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+--- a/drivers/net/phy/dp83640.c
++++ b/drivers/net/phy/dp83640.c
+@@ -784,7 +784,7 @@ static int match(struct sk_buff *skb, un
+       switch (type & PTP_CLASS_PMASK) {
+       case PTP_CLASS_IPV4:
+-              offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
++              offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+               break;
+       case PTP_CLASS_IPV6:
+               offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+@@ -927,7 +927,7 @@ static int is_sync(struct sk_buff *skb,
+       switch (type & PTP_CLASS_PMASK) {
+       case PTP_CLASS_IPV4:
+-              offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
++              offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+               break;
+       case PTP_CLASS_IPV6:
+               offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
diff --git a/queue-3.17/net-sctp-fix-memory-leak-in-auth-key-management.patch b/queue-3.17/net-sctp-fix-memory-leak-in-auth-key-management.patch
new file mode 100644 (file)
index 0000000..64b80fa
--- /dev/null
@@ -0,0 +1,57 @@
+From foo@baz Tue Nov 18 09:07:25 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
+@@ -862,8 +862,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.17/net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch b/queue-3.17/net-sctp-fix-null-pointer-dereference-in-af-from_addr_param-on-malformed-packet.patch
new file mode 100644 (file)
index 0000000..01d36cf
--- /dev/null
@@ -0,0 +1,77 @@
+From foo@baz Tue Nov 18 09:07:25 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
+@@ -2609,6 +2609,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.17/netlink-properly-unbind-in-error-conditions.patch b/queue-3.17/netlink-properly-unbind-in-error-conditions.patch
new file mode 100644 (file)
index 0000000..70d0b3d
--- /dev/null
@@ -0,0 +1,54 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
+Date: Thu, 13 Nov 2014 04:24:10 +0900
+Subject: netlink: Properly unbind in error conditions.
+
+From: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
+
+[ Upstream commit 6251edd932ce3faadbfe27b0a0fe79780e0972e9 ]
+
+Even if netlink_kernel_cfg::unbind is implemented the unbind() method is
+not called, because cfg->unbind is omitted in __netlink_kernel_create().
+And fix wrong argument of test_bit() and off by one problem.
+
+At this point, no unbind() method is implemented, so there is no real
+issue.
+
+Fixes: 4f520900522f ("netlink: have netlink per-protocol bind function return an error code.")
+Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
+Cc: Richard Guy Briggs <rgb@redhat.com>
+Acked-by: Richard Guy Briggs <rgb@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netlink/af_netlink.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1440,7 +1440,7 @@ static void netlink_unbind(int group, lo
+               return;
+       for (undo = 0; undo < group; undo++)
+-              if (test_bit(group, &groups))
++              if (test_bit(undo, &groups))
+                       nlk->netlink_unbind(undo);
+ }
+@@ -1492,7 +1492,7 @@ static int netlink_bind(struct socket *s
+                       netlink_insert(sk, net, nladdr->nl_pid) :
+                       netlink_autobind(sock);
+               if (err) {
+-                      netlink_unbind(nlk->ngroups - 1, groups, nlk);
++                      netlink_unbind(nlk->ngroups, groups, nlk);
+                       return err;
+               }
+       }
+@@ -2509,6 +2509,7 @@ __netlink_kernel_create(struct net *net,
+               nl_table[unit].module = module;
+               if (cfg) {
+                       nl_table[unit].bind = cfg->bind;
++                      nl_table[unit].unbind = cfg->unbind;
+                       nl_table[unit].flags = cfg->flags;
+                       if (cfg->compare)
+                               nl_table[unit].compare = cfg->compare;
index a12bfb6519755cc6621d5354a32ad090add4987c..961fb90bfd7b2fa51c998f7dc0411486215ee8fa 100644 (file)
@@ -1 +1,25 @@
 x86-build-add-arch-x86-purgatory-make-generated-files-to-gitignore.patch
+inet-frags-fix-a-race-between-inet_evict_bucket-and-inet_frag_kill.patch
+inet-frags-remove-the-warn_on-from-inet_evict_bucket.patch
+ip6_tunnel-use-ip6_tnl_dev_init-as-the-ndo_init-function.patch
+vti6-use-vti6_dev_init-as-the-ndo_init-function.patch
+sit-use-ipip6_tunnel_init-as-the-ndo_init-function.patch
+gre6-move-the-setting-of-dev-iflink-into-the-ndo_init-functions.patch
+net-mv643xx_eth-reclaim-tx-skbs-only-when-released-by-the-hw.patch
+udptunnel-add-skb_gso_udp_tunnel-during-gro_complete.patch
+vxlan-do-not-reuse-sockets-for-a-different-address-family.patch
+net-ppp-don-t-call-bpf_prog_create-in-ppp_lock.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
+ipv6-fix-ipv6_pktinfo-with-v4-mapped.patch
+net-ptp-fix-time-stamp-matching-logic-for-vlan-packets.patch
+netlink-properly-unbind-in-error-conditions.patch
+smsc911x-power-up-phydev-before-doing-a-software-reset.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.17/sit-use-ipip6_tunnel_init-as-the-ndo_init-function.patch b/queue-3.17/sit-use-ipip6_tunnel_init-as-the-ndo_init-function.patch
new file mode 100644 (file)
index 0000000..75f45d6
--- /dev/null
@@ -0,0 +1,75 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Mon, 3 Nov 2014 09:19:29 +0100
+Subject: sit: Use ipip6_tunnel_init as the ndo_init function.
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit ebe084aafb7e93adf210e80043c9f69adf56820d ]
+
+ipip6_tunnel_init() sets the dev->iflink via a call to
+ipip6_tunnel_bind_dev(). After that, register_netdevice()
+sets dev->iflink = -1. So we loose the iflink configuration
+for ipv6 tunnels. Fix this by using ipip6_tunnel_init() as the
+ndo_init function. Then ipip6_tunnel_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/sit.c |   15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -195,10 +195,8 @@ static int ipip6_tunnel_create(struct ne
+       struct sit_net *sitn = net_generic(net, sit_net_id);
+       int err;
+-      err = ipip6_tunnel_init(dev);
+-      if (err < 0)
+-              goto out;
+-      ipip6_tunnel_clone_6rd(dev, sitn);
++      memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
++      memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
+       if ((__force u16)t->parms.i_flags & SIT_ISATAP)
+               dev->priv_flags |= IFF_ISATAP;
+@@ -207,7 +205,8 @@ static int ipip6_tunnel_create(struct ne
+       if (err < 0)
+               goto out;
+-      strcpy(t->parms.name, dev->name);
++      ipip6_tunnel_clone_6rd(dev, sitn);
++
+       dev->rtnl_link_ops = &sit_link_ops;
+       dev_hold(dev);
+@@ -1314,6 +1313,7 @@ static int ipip6_tunnel_change_mtu(struc
+ }
+ static const struct net_device_ops ipip6_netdev_ops = {
++      .ndo_init       = ipip6_tunnel_init,
+       .ndo_uninit     = ipip6_tunnel_uninit,
+       .ndo_start_xmit = sit_tunnel_xmit,
+       .ndo_do_ioctl   = ipip6_tunnel_ioctl,
+@@ -1359,9 +1359,7 @@ static int ipip6_tunnel_init(struct net_
+       tunnel->dev = dev;
+       tunnel->net = dev_net(dev);
+-
+-      memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
+-      memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
++      strcpy(tunnel->parms.name, dev->name);
+       ipip6_tunnel_bind_dev(dev);
+       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+@@ -1386,7 +1384,6 @@ static int __net_init ipip6_fb_tunnel_in
+       tunnel->dev = dev;
+       tunnel->net = dev_net(dev);
+-      strcpy(tunnel->parms.name, dev->name);
+       iph->version            = 4;
+       iph->protocol           = IPPROTO_IPV6;
diff --git a/queue-3.17/smsc911x-power-up-phydev-before-doing-a-software-reset.patch b/queue-3.17/smsc911x-power-up-phydev-before-doing-a-software-reset.patch
new file mode 100644 (file)
index 0000000..b461815
--- /dev/null
@@ -0,0 +1,94 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Enric Balletbo i Serra <eballetbo@iseebcn.com>
+Date: Thu, 13 Nov 2014 09:14:34 +0100
+Subject: smsc911x: power-up phydev before doing a software reset.
+
+From: Enric Balletbo i Serra <eballetbo@iseebcn.com>
+
+[ Upstream commit ccf899a27c08038db91765ff12bb0380dcd85887 ]
+
+With commit be9dad1f9f26604fb ("net: phy: suspend phydev when going
+to HALTED"), the PHY device will be put in a low-power mode using
+BMCR_PDOWN if the the interface is set down. The smsc911x driver does
+a software_reset opening the device driver (ndo_open). In such case,
+the PHY must be powered-up before access to any register and before
+calling the software_reset function. Otherwise, as the PHY is powered
+down the software reset fails and the interface can not be enabled
+again.
+
+This patch fixes this scenario that is easy to reproduce setting down
+the network interface and setting up again.
+
+    $ ifconfig eth0 down
+    $ ifconfig eth0 up
+    ifconfig: SIOCSIFFLAGS: Input/output error
+
+Signed-off-by: Enric Balletbo i Serra <eballetbo@iseebcn.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/smsc/smsc911x.c |   46 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
+
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -1342,6 +1342,42 @@ static void smsc911x_rx_multicast_update
+       spin_unlock(&pdata->mac_lock);
+ }
++static int smsc911x_phy_general_power_up(struct smsc911x_data *pdata)
++{
++      int rc = 0;
++
++      if (!pdata->phy_dev)
++              return rc;
++
++      /* If the internal PHY is in General Power-Down mode, all, except the
++       * management interface, is powered-down and stays in that condition as
++       * long as Phy register bit 0.11 is HIGH.
++       *
++       * In that case, clear the bit 0.11, so the PHY powers up and we can
++       * access to the phy registers.
++       */
++      rc = phy_read(pdata->phy_dev, MII_BMCR);
++      if (rc < 0) {
++              SMSC_WARN(pdata, drv, "Failed reading PHY control reg");
++              return rc;
++      }
++
++      /* If the PHY general power-down bit is not set is not necessary to
++       * disable the general power down-mode.
++       */
++      if (rc & BMCR_PDOWN) {
++              rc = phy_write(pdata->phy_dev, MII_BMCR, rc & ~BMCR_PDOWN);
++              if (rc < 0) {
++                      SMSC_WARN(pdata, drv, "Failed writing PHY control reg");
++                      return rc;
++              }
++
++              usleep_range(1000, 1500);
++      }
++
++      return 0;
++}
++
+ static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata)
+ {
+       int rc = 0;
+@@ -1415,6 +1451,16 @@ static int smsc911x_soft_reset(struct sm
+       int ret;
+       /*
++       * Make sure to power-up the PHY chip before doing a reset, otherwise
++       * the reset fails.
++       */
++      ret = smsc911x_phy_general_power_up(pdata);
++      if (ret) {
++              SMSC_WARN(pdata, drv, "Failed to power-up the PHY chip");
++              return ret;
++      }
++
++      /*
+        * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that
+        * are initialized in a Energy Detect Power-Down mode that prevents
+        * the MAC chip to be software reseted. So we have to wakeup the PHY
diff --git a/queue-3.17/sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch b/queue-3.17/sparc32-implement-xchg-and-atomic_xchg-using-atomic_hash-locks.patch
new file mode 100644 (file)
index 0000000..f2b61f4
--- /dev/null
@@ -0,0 +1,100 @@
+From foo@baz Tue Nov 18 09:08:30 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
+@@ -22,7 +22,7 @@
+ int __atomic_add_return(int, atomic_t *);
+ int atomic_cmpxchg(atomic_t *, int, int);
+-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
++int atomic_xchg(atomic_t *, int);
+ int __atomic_add_unless(atomic_t *, int, int);
+ 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;
+-}
+-
++unsigned long __xchg_u32(volatile u32 *m, u32 new);
+ 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.17/sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch b/queue-3.17/sparc64-do-irq_-enter-exit-around-generic_smp_call_function.patch
new file mode 100644 (file)
index 0000000..258d50a
--- /dev/null
@@ -0,0 +1,80 @@
+From foo@baz Tue Nov 18 09:08:30 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
+@@ -816,13 +816,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.17/sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch b/queue-3.17/sparc64-fix-crashes-in-schizo_pcierr_intr_other.patch
new file mode 100644 (file)
index 0000000..df107a2
--- /dev/null
@@ -0,0 +1,99 @@
+From foo@baz Tue Nov 18 09:08:30 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.17/sunvdc-add-cdrom-and-v1.1-protocol-support.patch b/queue-3.17/sunvdc-add-cdrom-and-v1.1-protocol-support.patch
new file mode 100644 (file)
index 0000000..7bdb0e5
--- /dev/null
@@ -0,0 +1,246 @@
+From foo@baz Tue Nov 18 09:08:30 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.17/sunvdc-compute-vdisk-geometry-from-capacity.patch b/queue-3.17/sunvdc-compute-vdisk-geometry-from-capacity.patch
new file mode 100644 (file)
index 0000000..dce8706
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Tue Nov 18 09:08:30 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.17/sunvdc-don-t-call-vd_op_get_vtoc.patch b/queue-3.17/sunvdc-don-t-call-vd_op_get_vtoc.patch
new file mode 100644 (file)
index 0000000..96e75fc
--- /dev/null
@@ -0,0 +1,48 @@
+From foo@baz Tue Nov 18 09:08:30 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.17/sunvdc-limit-each-sg-segment-to-a-page.patch b/queue-3.17/sunvdc-limit-each-sg-segment-to-a-page.patch
new file mode 100644 (file)
index 0000000..c31e4c3
--- /dev/null
@@ -0,0 +1,40 @@
+From foo@baz Tue Nov 18 09:08:30 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.17/udptunnel-add-skb_gso_udp_tunnel-during-gro_complete.patch b/queue-3.17/udptunnel-add-skb_gso_udp_tunnel-during-gro_complete.patch
new file mode 100644 (file)
index 0000000..f61c760
--- /dev/null
@@ -0,0 +1,53 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Jesse Gross <jesse@nicira.com>
+Date: Mon, 10 Nov 2014 11:45:13 -0800
+Subject: udptunnel: Add SKB_GSO_UDP_TUNNEL during gro_complete.
+
+From: Jesse Gross <jesse@nicira.com>
+
+[ Upstream commit cfdf1e1ba5bf55e095cf4bcaa9585c4759f239e8 ]
+
+When doing GRO processing for UDP tunnels, we never add
+SKB_GSO_UDP_TUNNEL to gso_type - only the type of the inner protocol
+is added (such as SKB_GSO_TCPV4). The result is that if the packet is
+later resegmented we will do GSO but not treat it as a tunnel. This
+results in UDP fragmentation of the outer header instead of (i.e.) TCP
+segmentation of the inner header as was originally on the wire.
+
+Signed-off-by: Jesse Gross <jesse@nicira.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vxlan.c      |    2 ++
+ include/net/udp_tunnel.h |    9 +++++++++
+ 2 files changed, 11 insertions(+)
+
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -620,6 +620,8 @@ static int vxlan_gro_complete(struct sk_
+       int vxlan_len  = sizeof(struct vxlanhdr) + sizeof(struct ethhdr);
+       int err = -ENOSYS;
++      udp_tunnel_gro_complete(skb, nhoff);
++
+       eh = (struct ethhdr *)(skb->data + nhoff + sizeof(struct vxlanhdr));
+       type = eh->h_proto;
+--- a/include/net/udp_tunnel.h
++++ b/include/net/udp_tunnel.h
+@@ -26,6 +26,15 @@ struct udp_port_cfg {
+                               use_udp6_rx_checksums:1;
+ };
++static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff)
++{
++      struct udphdr *uh;
++
++      uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr));
++      skb_shinfo(skb)->gso_type |= uh->check ?
++                              SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
++}
++
+ int udp_sock_create(struct net *net, struct udp_port_cfg *cfg,
+                   struct socket **sockp);
diff --git a/queue-3.17/vio-fix-reuse-of-vio_dring-slot.patch b/queue-3.17/vio-fix-reuse-of-vio_dring-slot.patch
new file mode 100644 (file)
index 0000000..780c697
--- /dev/null
@@ -0,0 +1,145 @@
+From foo@baz Tue Nov 18 09:08:30 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
+@@ -693,7 +693,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);
+@@ -749,7 +749,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);
diff --git a/queue-3.17/vti6-use-vti6_dev_init-as-the-ndo_init-function.patch b/queue-3.17/vti6-use-vti6_dev_init-as-the-ndo_init-function.patch
new file mode 100644 (file)
index 0000000..71203d7
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Mon, 3 Nov 2014 09:19:28 +0100
+Subject: vti6: Use vti6_dev_init as the ndo_init function.
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit 16a0231bf7dc3fb37e9b1f1cb1a277dc220b5c5e ]
+
+vti6_dev_init() sets the dev->iflink via a call to
+vti6_link_config(). After that, register_netdevice()
+sets dev->iflink = -1. So we loose the iflink configuration
+for vti6 tunnels. Fix this by using vti6_dev_init() as the
+ndo_init function. Then vti6_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_vti.c |   11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -172,10 +172,6 @@ static int vti6_tnl_create2(struct net_d
+       struct vti6_net *ip6n = net_generic(net, vti6_net_id);
+       int err;
+-      err = vti6_dev_init(dev);
+-      if (err < 0)
+-              goto out;
+-
+       err = register_netdevice(dev);
+       if (err < 0)
+               goto out;
+@@ -783,6 +779,7 @@ static int vti6_change_mtu(struct net_de
+ }
+ static const struct net_device_ops vti6_netdev_ops = {
++      .ndo_init       = vti6_dev_init,
+       .ndo_uninit     = vti6_dev_uninit,
+       .ndo_start_xmit = vti6_tnl_xmit,
+       .ndo_do_ioctl   = vti6_ioctl,
+@@ -852,16 +849,10 @@ static int __net_init vti6_fb_tnl_dev_in
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct net *net = dev_net(dev);
+       struct vti6_net *ip6n = net_generic(net, vti6_net_id);
+-      int err = vti6_dev_init_gen(dev);
+-
+-      if (err)
+-              return err;
+       t->parms.proto = IPPROTO_IPV6;
+       dev_hold(dev);
+-      vti6_link_config(t);
+-
+       rcu_assign_pointer(ip6n->tnls_wc[0], t);
+       return 0;
+ }
diff --git a/queue-3.17/vxlan-do-not-reuse-sockets-for-a-different-address-family.patch b/queue-3.17/vxlan-do-not-reuse-sockets-for-a-different-address-family.patch
new file mode 100644 (file)
index 0000000..96f1568
--- /dev/null
@@ -0,0 +1,142 @@
+From foo@baz Tue Nov 18 09:07:25 PST 2014
+From: Marcelo Leitner <mleitner@redhat.com>
+Date: Thu, 13 Nov 2014 14:43:08 -0200
+Subject: vxlan: Do not reuse sockets for a different address family
+
+From: Marcelo Leitner <mleitner@redhat.com>
+
+[ Upstream commit 19ca9fc1445b76b60d34148f7ff837b055f5dcf3 ]
+
+Currently, we only match against local port number in order to reuse
+socket. But if this new vxlan wants an IPv6 socket and a IPv4 one bound
+to that port, vxlan will reuse an IPv4 socket as IPv6 and a panic will
+follow. The following steps reproduce it:
+
+   # ip link add vxlan6 type vxlan id 42 group 229.10.10.10 \
+       srcport 5000 6000 dev eth0
+   # ip link add vxlan7 type vxlan id 43 group ff0e::110 \
+       srcport 5000 6000 dev eth0
+   # ip link set vxlan6 up
+   # ip link set vxlan7 up
+   <panic>
+
+[    4.187481] BUG: unable to handle kernel NULL pointer dereference at 0000000000000058
+...
+[    4.188076] Call Trace:
+[    4.188085]  [<ffffffff81667c4a>] ? ipv6_sock_mc_join+0x3a/0x630
+[    4.188098]  [<ffffffffa05a6ad6>] vxlan_igmp_join+0x66/0xd0 [vxlan]
+[    4.188113]  [<ffffffff810a3430>] process_one_work+0x220/0x710
+[    4.188125]  [<ffffffff810a33c4>] ? process_one_work+0x1b4/0x710
+[    4.188138]  [<ffffffff810a3a3b>] worker_thread+0x11b/0x3a0
+[    4.188149]  [<ffffffff810a3920>] ? process_one_work+0x710/0x710
+
+So address family must also match in order to reuse a socket.
+
+Reported-by: Jean-Tsung Hsiao <jhsiao@redhat.com>
+Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vxlan.c |   29 +++++++++++++++++++----------
+ 1 file changed, 19 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -274,13 +274,15 @@ static inline struct vxlan_rdst *first_r
+       return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
+ }
+-/* Find VXLAN socket based on network namespace and UDP port */
+-static struct vxlan_sock *vxlan_find_sock(struct net *net, __be16 port)
++/* Find VXLAN socket based on network namespace, address family and UDP port */
++static struct vxlan_sock *vxlan_find_sock(struct net *net,
++                                        sa_family_t family, __be16 port)
+ {
+       struct vxlan_sock *vs;
+       hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
+-              if (inet_sk(vs->sock->sk)->inet_sport == port)
++              if (inet_sk(vs->sock->sk)->inet_sport == port &&
++                  inet_sk(vs->sock->sk)->sk.sk_family == family)
+                       return vs;
+       }
+       return NULL;
+@@ -299,11 +301,12 @@ static struct vxlan_dev *vxlan_vs_find_v
+ }
+ /* Look up VNI in a per net namespace table */
+-static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port)
++static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id,
++                                      sa_family_t family, __be16 port)
+ {
+       struct vxlan_sock *vs;
+-      vs = vxlan_find_sock(net, port);
++      vs = vxlan_find_sock(net, family, port);
+       if (!vs)
+               return NULL;
+@@ -1822,7 +1825,8 @@ static void vxlan_xmit_one(struct sk_buf
+                       struct vxlan_dev *dst_vxlan;
+                       ip_rt_put(rt);
+-                      dst_vxlan = vxlan_find_vni(vxlan->net, vni, dst_port);
++                      dst_vxlan = vxlan_find_vni(vxlan->net, vni,
++                                                 dst->sa.sa_family, dst_port);
+                       if (!dst_vxlan)
+                               goto tx_error;
+                       vxlan_encap_bypass(skb, vxlan, dst_vxlan);
+@@ -1876,7 +1880,8 @@ static void vxlan_xmit_one(struct sk_buf
+                       struct vxlan_dev *dst_vxlan;
+                       dst_release(ndst);
+-                      dst_vxlan = vxlan_find_vni(vxlan->net, vni, dst_port);
++                      dst_vxlan = vxlan_find_vni(vxlan->net, vni,
++                                                 dst->sa.sa_family, dst_port);
+                       if (!dst_vxlan)
+                               goto tx_error;
+                       vxlan_encap_bypass(skb, vxlan, dst_vxlan);
+@@ -2036,13 +2041,15 @@ static int vxlan_init(struct net_device
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+       struct vxlan_sock *vs;
++      bool ipv6 = vxlan->flags & VXLAN_F_IPV6;
+       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+       if (!dev->tstats)
+               return -ENOMEM;
+       spin_lock(&vn->sock_lock);
+-      vs = vxlan_find_sock(vxlan->net, vxlan->dst_port);
++      vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
++                           vxlan->dst_port);
+       if (vs) {
+               /* If we have a socket with same port already, reuse it */
+               atomic_inc(&vs->refcnt);
+@@ -2441,6 +2448,7 @@ struct vxlan_sock *vxlan_sock_add(struct
+ {
+       struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+       struct vxlan_sock *vs;
++      bool ipv6 = flags & VXLAN_F_IPV6;
+       vs = vxlan_socket_create(net, port, rcv, data, flags);
+       if (!IS_ERR(vs))
+@@ -2450,7 +2458,7 @@ struct vxlan_sock *vxlan_sock_add(struct
+               return vs;
+       spin_lock(&vn->sock_lock);
+-      vs = vxlan_find_sock(net, port);
++      vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port);
+       if (vs) {
+               if (vs->rcv == rcv)
+                       atomic_inc(&vs->refcnt);
+@@ -2609,7 +2617,8 @@ static int vxlan_newlink(struct net *net
+           nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
+               vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX;
+-      if (vxlan_find_vni(net, vni, vxlan->dst_port)) {
++      if (vxlan_find_vni(net, vni, use_ipv6 ? AF_INET6 : AF_INET,
++                         vxlan->dst_port)) {
+               pr_info("duplicate VNI %u\n", vni);
+               return -EEXIST;
+       }