--- /dev/null
+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;
+ }
+
--- /dev/null
+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);
+ }
+
--- /dev/null
+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;
+ }
--- /dev/null
+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;
+ }
--- /dev/null
+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) {
--- /dev/null
+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);
--- /dev/null
+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;
+ }
--- /dev/null
+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;
--- /dev/null
+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)
--- /dev/null
+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);
+
--- /dev/null
+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;
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
--- /dev/null
+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;
--- /dev/null
+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
--- /dev/null
+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);
--- /dev/null
+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)
--- /dev/null
+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;
--- /dev/null
+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),
--- /dev/null
+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);
--- /dev/null
+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
--- /dev/null
+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;
--- /dev/null
+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);
+
--- /dev/null
+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);
--- /dev/null
+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;
+ }
--- /dev/null
+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;
+ }