]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jun 2017 07:40:35 +0000 (09:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jun 2017 07:40:35 +0000 (09:40 +0200)
added patches:
gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch
ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch
ibmvnic-fix-endian-errors-in-error-reporting-output.patch
ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch
ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch
net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch
net-xilinx_emaclite-fix-receive-buffer-overflow.patch
tcp-tcp_probe-use-spin_lock_bh.patch
tipc-fix-tipc_sk_reinit-race-conditions.patch

queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch [new file with mode: 0644]
queue-4.9/ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch [new file with mode: 0644]
queue-4.9/ibmvnic-fix-endian-errors-in-error-reporting-output.patch [new file with mode: 0644]
queue-4.9/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch [new file with mode: 0644]
queue-4.9/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch [new file with mode: 0644]
queue-4.9/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch [new file with mode: 0644]
queue-4.9/net-xilinx_emaclite-fix-receive-buffer-overflow.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/tcp-tcp_probe-use-spin_lock_bh.patch [new file with mode: 0644]
queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch [new file with mode: 0644]

diff --git a/queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch b/queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch
new file mode 100644 (file)
index 0000000..c03c5a0
--- /dev/null
@@ -0,0 +1,73 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Tue, 23 May 2017 21:53:36 -0400
+Subject: gfs2: Use rhashtable walk interface in glock_hash_walk
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+
+[ Upstream commit 6a25478077d987edc5e2f880590a2bc5fcab4441 ]
+
+The function glock_hash_walk walks the rhashtable by hand.  This
+is broken because if it catches the hash table in the middle of
+a rehash, then it will miss entries.
+
+This patch replaces the manual walk by using the rhashtable walk
+interface.
+
+Fixes: 88ffbf3e037e ("GFS2: Use resizable hash table for glocks")
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/gfs2/glock.c |   30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -1425,26 +1425,32 @@ static struct shrinker glock_shrinker =
+  * @sdp: the filesystem
+  * @bucket: the bucket
+  *
++ * Note that the function can be called multiple times on the same
++ * object.  So the user must ensure that the function can cope with
++ * that.
+  */
+ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
+ {
+       struct gfs2_glock *gl;
+-      struct rhash_head *pos;
+-      const struct bucket_table *tbl;
+-      int i;
+-
+-      rcu_read_lock();
+-      tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
+-      for (i = 0; i < tbl->size; i++) {
+-              rht_for_each_entry_rcu(gl, pos, tbl, i, gl_node) {
++      struct rhashtable_iter iter;
++
++      rhashtable_walk_enter(&gl_hash_table, &iter);
++
++      do {
++              gl = ERR_PTR(rhashtable_walk_start(&iter));
++              if (gl)
++                      continue;
++
++              while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl))
+                       if ((gl->gl_name.ln_sbd == sdp) &&
+                           lockref_get_not_dead(&gl->gl_lockref))
+                               examiner(gl);
+-              }
+-      }
+-      rcu_read_unlock();
+-      cond_resched();
++
++              rhashtable_walk_stop(&iter);
++      } while (cond_resched(), gl == ERR_PTR(-EAGAIN));
++
++      rhashtable_walk_exit(&iter);
+ }
+ /**
diff --git a/queue-4.9/ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch b/queue-4.9/ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch
new file mode 100644 (file)
index 0000000..a92a503
--- /dev/null
@@ -0,0 +1,39 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Date: Tue, 23 May 2017 21:53:27 -0400
+Subject: ibmvnic: Fix endian error when requesting device capabilities
+
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+
+
+[ Upstream commit 28f4d16570dcf440e54a4d72666d5be452f27d0e ]
+
+When a vNIC client driver requests a faulty device setting, the
+server returns an acceptable value for the client to request.
+This 64 bit value was incorrectly being swapped as a 32 bit value,
+resulting in loss of data. This patch corrects that by using
+the 64 bit swap function.
+
+Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2400,10 +2400,10 @@ static void handle_request_cap_rsp(union
+       case PARTIALSUCCESS:
+               dev_info(dev, "req=%lld, rsp=%ld in %s queue, retrying.\n",
+                        *req_value,
+-                       (long int)be32_to_cpu(crq->request_capability_rsp.
++                       (long int)be64_to_cpu(crq->request_capability_rsp.
+                                              number), name);
+               release_sub_crqs_no_irqs(adapter);
+-              *req_value = be32_to_cpu(crq->request_capability_rsp.number);
++              *req_value = be64_to_cpu(crq->request_capability_rsp.number);
+               init_sub_crqs(adapter, 1);
+               return;
+       default:
diff --git a/queue-4.9/ibmvnic-fix-endian-errors-in-error-reporting-output.patch b/queue-4.9/ibmvnic-fix-endian-errors-in-error-reporting-output.patch
new file mode 100644 (file)
index 0000000..50dd8fd
--- /dev/null
@@ -0,0 +1,50 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Date: Tue, 23 May 2017 21:53:26 -0400
+Subject: ibmvnic: Fix endian errors in error reporting output
+
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+
+
+[ Upstream commit 75224c93fa985f4a6fb983f53208f5c5aa555fbf ]
+
+Error reports received from firmware were not being converted from
+big endian values, leading to bogus error codes reported on little
+endian systems.
+
+Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2197,12 +2197,12 @@ static void handle_error_info_rsp(union
+       if (!found) {
+               dev_err(dev, "Couldn't find error id %x\n",
+-                      crq->request_error_rsp.error_id);
++                      be32_to_cpu(crq->request_error_rsp.error_id));
+               return;
+       }
+       dev_err(dev, "Detailed info for error id %x:",
+-              crq->request_error_rsp.error_id);
++              be32_to_cpu(crq->request_error_rsp.error_id));
+       for (i = 0; i < error_buff->len; i++) {
+               pr_cont("%02x", (int)error_buff->buff[i]);
+@@ -2281,8 +2281,8 @@ static void handle_error_indication(unio
+       dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
+               crq->error_indication.
+                   flags & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
+-              crq->error_indication.error_id,
+-              crq->error_indication.error_cause);
++              be32_to_cpu(crq->error_indication.error_id),
++              be16_to_cpu(crq->error_indication.error_cause));
+       error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC);
+       if (!error_buff)
diff --git a/queue-4.9/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch b/queue-4.9/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch
new file mode 100644 (file)
index 0000000..213d385
--- /dev/null
@@ -0,0 +1,100 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+Date: Tue, 23 May 2017 21:53:33 -0400
+Subject: ipv6: Handle IPv4-mapped src to in6addr_any dst.
+
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+
+
+[ Upstream commit 052d2369d1b479cdbbe020fdd6d057d3c342db74 ]
+
+This patch adds a check on the type of the source address for the case
+where the destination address is in6addr_any. If the source is an
+IPv4-mapped IPv6 source address, the destination is changed to
+::ffff:127.0.0.1, and otherwise the destination is changed to ::1. This
+is done in three locations to handle UDP calls to either connect() or
+sendmsg() and TCP calls to connect(). Note that udpv6_sendmsg() delays
+handling an in6addr_any destination until very late, so the patch only
+needs to handle the case where the source is an IPv4-mapped IPv6
+address.
+
+Signed-off-by: Jonathan T. Leighton <jtleight@udel.edu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/datagram.c |   14 +++++++++-----
+ net/ipv6/tcp_ipv6.c |   11 ++++++++---
+ net/ipv6/udp.c      |    4 ++++
+ 3 files changed, 21 insertions(+), 8 deletions(-)
+
+--- a/net/ipv6/datagram.c
++++ b/net/ipv6/datagram.c
+@@ -166,18 +166,22 @@ int __ip6_datagram_connect(struct sock *
+       if (np->sndflow)
+               fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
+-      addr_type = ipv6_addr_type(&usin->sin6_addr);
+-
+-      if (addr_type == IPV6_ADDR_ANY) {
++      if (ipv6_addr_any(&usin->sin6_addr)) {
+               /*
+                *      connect to self
+                */
+-              usin->sin6_addr.s6_addr[15] = 0x01;
++              if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
++                      ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
++                                             &usin->sin6_addr);
++              else
++                      usin->sin6_addr = in6addr_loopback;
+       }
++      addr_type = ipv6_addr_type(&usin->sin6_addr);
++
+       daddr = &usin->sin6_addr;
+-      if (addr_type == IPV6_ADDR_MAPPED) {
++      if (addr_type & IPV6_ADDR_MAPPED) {
+               struct sockaddr_in sin;
+               if (__ipv6_only_sock(sk)) {
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -148,8 +148,13 @@ static int tcp_v6_connect(struct sock *s
+        *      connect() to INADDR_ANY means loopback (BSD'ism).
+        */
+-      if (ipv6_addr_any(&usin->sin6_addr))
+-              usin->sin6_addr.s6_addr[15] = 0x1;
++      if (ipv6_addr_any(&usin->sin6_addr)) {
++              if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
++                      ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
++                                             &usin->sin6_addr);
++              else
++                      usin->sin6_addr = in6addr_loopback;
++      }
+       addr_type = ipv6_addr_type(&usin->sin6_addr);
+@@ -188,7 +193,7 @@ static int tcp_v6_connect(struct sock *s
+        *      TCP over IPv4
+        */
+-      if (addr_type == IPV6_ADDR_MAPPED) {
++      if (addr_type & IPV6_ADDR_MAPPED) {
+               u32 exthdrlen = icsk->icsk_ext_hdr_len;
+               struct sockaddr_in sin;
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -1049,6 +1049,10 @@ int udpv6_sendmsg(struct sock *sk, struc
+                       if (addr_len < SIN6_LEN_RFC2133)
+                               return -EINVAL;
+                       daddr = &sin6->sin6_addr;
++                      if (ipv6_addr_any(daddr) &&
++                          ipv6_addr_v4mapped(&np->saddr))
++                              ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
++                                                     daddr);
+                       break;
+               case AF_INET:
+                       goto do_udp_sendmsg;
diff --git a/queue-4.9/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch b/queue-4.9/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch
new file mode 100644 (file)
index 0000000..ef5feab
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+Date: Tue, 23 May 2017 21:53:34 -0400
+Subject: ipv6: Inhibit IPv4-mapped src address on the wire.
+
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+
+
+[ Upstream commit ec5e3b0a1d41fbda0cc33a45bc9e54e91d9d12c7 ]
+
+This patch adds a check for the problematic case of an IPv4-mapped IPv6
+source address and a destination address that is neither an IPv4-mapped
+IPv6 address nor in6addr_any, and returns an appropriate error. The
+check in done before returning from looking up the route.
+
+Signed-off-by: Jonathan T. Leighton <jtleight@udel.edu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_output.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1019,6 +1019,9 @@ static int ip6_dst_lookup_tail(struct ne
+               }
+       }
+ #endif
++      if (ipv6_addr_v4mapped(&fl6->saddr) &&
++          !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr)))
++              return -EAFNOSUPPORT;
+       return 0;
diff --git a/queue-4.9/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch b/queue-4.9/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch
new file mode 100644 (file)
index 0000000..b4011db
--- /dev/null
@@ -0,0 +1,331 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Tue, 23 May 2017 21:53:28 -0400
+Subject: net: xilinx_emaclite: fix freezes due to unordered I/O
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+
+[ Upstream commit acf138f1b00bdd1b7cd9894562ed0c2a1670888e ]
+
+The xilinx_emaclite uses __raw_writel and __raw_readl for register
+accesses. Those functions do not imply any kind of memory barriers and
+they may be reordered.
+
+The driver does not seem to take that into account, though, and the
+driver does not satisfy the ordering requirements of the hardware.
+For clear examples, see xemaclite_mdio_write() and xemaclite_mdio_read()
+which try to set MDIO address before initiating the transaction.
+
+I'm seeing system freezes with the driver with GCC 5.4 and current
+Linux kernels on Zynq-7000 SoC immediately when trying to use the
+interface.
+
+In commit 123c1407af87 ("net: emaclite: Do not use microblaze and ppc
+IO functions") the driver was switched from non-generic
+in_be32/out_be32 (memory barriers, big endian) to
+__raw_readl/__raw_writel (no memory barriers, native endian), so
+apparently the device follows system endianness and the driver was
+originally written with the assumption of memory barriers.
+
+Rather than try to hunt for each case of missing barrier, just switch
+the driver to use iowrite32/ioread32/iowrite32be/ioread32be depending
+on endianness instead.
+
+Tested on little-endian Zynq-7000 ARM SoC FPGA.
+
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Fixes: 123c1407af87 ("net: emaclite: Do not use microblaze and ppc IO
+functions")
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/xilinx/xilinx_emaclite.c |  116 +++++++++++++-------------
+ 1 file changed, 62 insertions(+), 54 deletions(-)
+
+--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+@@ -100,6 +100,14 @@
+ /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
+ #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
++#ifdef __BIG_ENDIAN
++#define xemaclite_readl               ioread32be
++#define xemaclite_writel      iowrite32be
++#else
++#define xemaclite_readl               ioread32
++#define xemaclite_writel      iowrite32
++#endif
++
+ /**
+  * struct net_local - Our private per device data
+  * @ndev:             instance of the network device
+@@ -156,15 +164,15 @@ static void xemaclite_enable_interrupts(
+       u32 reg_data;
+       /* Enable the Tx interrupts for the first Buffer */
+-      reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+-      __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
+-                   drvdata->base_addr + XEL_TSR_OFFSET);
++      reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
++      xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
++                       drvdata->base_addr + XEL_TSR_OFFSET);
+       /* Enable the Rx interrupts for the first buffer */
+-      __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
++      xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
+       /* Enable the Global Interrupt Enable */
+-      __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
++      xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+ }
+ /**
+@@ -179,17 +187,17 @@ static void xemaclite_disable_interrupts
+       u32 reg_data;
+       /* Disable the Global Interrupt Enable */
+-      __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
++      xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+       /* Disable the Tx interrupts for the first buffer */
+-      reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+-      __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
+-                   drvdata->base_addr + XEL_TSR_OFFSET);
++      reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
++      xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
++                       drvdata->base_addr + XEL_TSR_OFFSET);
+       /* Disable the Rx interrupts for the first buffer */
+-      reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
+-      __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
+-                   drvdata->base_addr + XEL_RSR_OFFSET);
++      reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET);
++      xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
++                       drvdata->base_addr + XEL_RSR_OFFSET);
+ }
+ /**
+@@ -321,7 +329,7 @@ static int xemaclite_send_data(struct ne
+               byte_count = ETH_FRAME_LEN;
+       /* Check if the expected buffer is available */
+-      reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
++      reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
+       if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
+            XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
+@@ -334,7 +342,7 @@ static int xemaclite_send_data(struct ne
+               addr = (void __iomem __force *)((u32 __force)addr ^
+                                                XEL_BUFFER_OFFSET);
+-              reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
++              reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
+               if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
+                    XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
+@@ -345,16 +353,16 @@ static int xemaclite_send_data(struct ne
+       /* Write the frame to the buffer */
+       xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
+-      __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
+-                   addr + XEL_TPLR_OFFSET);
++      xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK),
++                       addr + XEL_TPLR_OFFSET);
+       /* Update the Tx Status Register to indicate that there is a
+        * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
+        * is used by the interrupt handler to check whether a frame
+        * has been transmitted */
+-      reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
++      reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
+       reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
+-      __raw_writel(reg_data, addr + XEL_TSR_OFFSET);
++      xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET);
+       return 0;
+ }
+@@ -379,7 +387,7 @@ static u16 xemaclite_recv_data(struct ne
+       addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
+       /* Verify which buffer has valid data */
+-      reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
++      reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
+       if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
+               if (drvdata->rx_ping_pong != 0)
+@@ -396,14 +404,14 @@ static u16 xemaclite_recv_data(struct ne
+                       return 0;       /* No data was available */
+               /* Verify that buffer has valid data */
+-              reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
++              reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
+               if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
+                    XEL_RSR_RECV_DONE_MASK)
+                       return 0;       /* No data was available */
+       }
+       /* Get the protocol type of the ethernet frame that arrived */
+-      proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
++      proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET +
+                       XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
+                       XEL_RPLR_LENGTH_MASK);
+@@ -412,7 +420,7 @@ static u16 xemaclite_recv_data(struct ne
+       if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
+               if (proto_type == ETH_P_IP) {
+-                      length = ((ntohl(__raw_readl(addr +
++                      length = ((ntohl(xemaclite_readl(addr +
+                                       XEL_HEADER_IP_LENGTH_OFFSET +
+                                       XEL_RXBUFF_OFFSET)) >>
+                                       XEL_HEADER_SHIFT) &
+@@ -434,9 +442,9 @@ static u16 xemaclite_recv_data(struct ne
+                               data, length);
+       /* Acknowledge the frame */
+-      reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
++      reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
+       reg_data &= ~XEL_RSR_RECV_DONE_MASK;
+-      __raw_writel(reg_data, addr + XEL_RSR_OFFSET);
++      xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET);
+       return length;
+ }
+@@ -463,14 +471,14 @@ static void xemaclite_update_address(str
+       xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
+-      __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
++      xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
+       /* Update the MAC address in the EmacLite */
+-      reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+-      __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
++      reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
++      xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
+       /* Wait for EmacLite to finish with the MAC address update */
+-      while ((__raw_readl(addr + XEL_TSR_OFFSET) &
++      while ((xemaclite_readl(addr + XEL_TSR_OFFSET) &
+               XEL_TSR_PROG_MAC_ADDR) != 0)
+               ;
+ }
+@@ -640,32 +648,32 @@ static irqreturn_t xemaclite_interrupt(i
+       u32 tx_status;
+       /* Check if there is Rx Data available */
+-      if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
++      if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) &
+                        XEL_RSR_RECV_DONE_MASK) ||
+-          (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
++          (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
+                        & XEL_RSR_RECV_DONE_MASK))
+               xemaclite_rx_handler(dev);
+       /* Check if the Transmission for the first buffer is completed */
+-      tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
++      tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET);
+       if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
+               (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
+               tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
+-              __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
++              xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET);
+               tx_complete = true;
+       }
+       /* Check if the Transmission for the second buffer is completed */
+-      tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
++      tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+       if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
+               (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
+               tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
+-              __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
+-                           XEL_TSR_OFFSET);
++              xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
++                               XEL_TSR_OFFSET);
+               tx_complete = true;
+       }
+@@ -698,7 +706,7 @@ static int xemaclite_mdio_wait(struct ne
+       /* wait for the MDIO interface to not be busy or timeout
+          after some time.
+       */
+-      while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
++      while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
+                       XEL_MDIOCTRL_MDIOSTS_MASK) {
+               if (time_before_eq(end, jiffies)) {
+                       WARN_ON(1);
+@@ -734,17 +742,17 @@ static int xemaclite_mdio_read(struct mi
+        * MDIO Address register. Set the Status bit in the MDIO Control
+        * register to start a MDIO read transaction.
+        */
+-      ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+-      __raw_writel(XEL_MDIOADDR_OP_MASK |
+-                   ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+-                   lp->base_addr + XEL_MDIOADDR_OFFSET);
+-      __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+-                   lp->base_addr + XEL_MDIOCTRL_OFFSET);
++      ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
++      xemaclite_writel(XEL_MDIOADDR_OP_MASK |
++                       ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
++                       lp->base_addr + XEL_MDIOADDR_OFFSET);
++      xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
++                       lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       if (xemaclite_mdio_wait(lp))
+               return -ETIMEDOUT;
+-      rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
++      rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET);
+       dev_dbg(&lp->ndev->dev,
+               "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
+@@ -781,13 +789,13 @@ static int xemaclite_mdio_write(struct m
+        * Data register. Finally, set the Status bit in the MDIO Control
+        * register to start a MDIO write transaction.
+        */
+-      ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+-      __raw_writel(~XEL_MDIOADDR_OP_MASK &
+-                   ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+-                   lp->base_addr + XEL_MDIOADDR_OFFSET);
+-      __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
+-      __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+-                   lp->base_addr + XEL_MDIOCTRL_OFFSET);
++      ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
++      xemaclite_writel(~XEL_MDIOADDR_OP_MASK &
++                       ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
++                       lp->base_addr + XEL_MDIOADDR_OFFSET);
++      xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
++      xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
++                       lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       return 0;
+ }
+@@ -834,8 +842,8 @@ static int xemaclite_mdio_setup(struct n
+       /* Enable the MDIO bus by asserting the enable bit in MDIO Control
+        * register.
+        */
+-      __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
+-                   lp->base_addr + XEL_MDIOCTRL_OFFSET);
++      xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK,
++                       lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       bus = mdiobus_alloc();
+       if (!bus) {
+@@ -1140,8 +1148,8 @@ static int xemaclite_of_probe(struct pla
+       }
+       /* Clear the Tx CSR's in case this is a restart */
+-      __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
+-      __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
++      xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET);
++      xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+       /* Set the MAC address in the EmacLite device */
+       xemaclite_update_address(lp, ndev->dev_addr);
diff --git a/queue-4.9/net-xilinx_emaclite-fix-receive-buffer-overflow.patch b/queue-4.9/net-xilinx_emaclite-fix-receive-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..ae683aa
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Tue, 23 May 2017 21:53:29 -0400
+Subject: net: xilinx_emaclite: fix receive buffer overflow
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+
+[ Upstream commit cd224553641848dd17800fe559e4ff5d208553e8 ]
+
+xilinx_emaclite looks at the received data to try to determine the
+Ethernet packet length but does not properly clamp it if
+proto_type == ETH_P_IP or 1500 < proto_type <= 1518, causing a buffer
+overflow and a panic via skb_panic() as the length exceeds the allocated
+skb size.
+
+Fix those cases.
+
+Also add an additional unconditional check with WARN_ON() at the end.
+
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Fixes: bb81b2ddfa19 ("net: add Xilinx emac lite device driver")
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/xilinx/xilinx_emaclite.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+@@ -377,7 +377,7 @@ static int xemaclite_send_data(struct ne
+  *
+  * Return:    Total number of bytes received
+  */
+-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
++static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
+ {
+       void __iomem *addr;
+       u16 length, proto_type;
+@@ -417,7 +417,7 @@ static u16 xemaclite_recv_data(struct ne
+       /* Check if received ethernet frame is a raw ethernet frame
+        * or an IP packet or an ARP packet */
+-      if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
++      if (proto_type > ETH_DATA_LEN) {
+               if (proto_type == ETH_P_IP) {
+                       length = ((ntohl(xemaclite_readl(addr +
+@@ -425,6 +425,7 @@ static u16 xemaclite_recv_data(struct ne
+                                       XEL_RXBUFF_OFFSET)) >>
+                                       XEL_HEADER_SHIFT) &
+                                       XEL_RPLR_LENGTH_MASK);
++                      length = min_t(u16, length, ETH_DATA_LEN);
+                       length += ETH_HLEN + ETH_FCS_LEN;
+               } else if (proto_type == ETH_P_ARP)
+@@ -437,6 +438,9 @@ static u16 xemaclite_recv_data(struct ne
+               /* Use the length in the frame, plus the header and trailer */
+               length = proto_type + ETH_HLEN + ETH_FCS_LEN;
++      if (WARN_ON(length > maxlen))
++              length = maxlen;
++
+       /* Read from the EmacLite device */
+       xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
+                               data, length);
+@@ -611,7 +615,7 @@ static void xemaclite_rx_handler(struct
+       skb_reserve(skb, 2);
+-      len = xemaclite_recv_data(lp, (u8 *) skb->data);
++      len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
+       if (!len) {
+               dev->stats.rx_errors++;
index 163d937f1158725091e7b7d2466ccc2f4a9e515d..0fd339af3363e0d8e2e0597d7acf8b19dd99974e 100644 (file)
@@ -2,3 +2,12 @@ pci-pm-add-needs_resume-flag-to-avoid-suspend-complete-optimization.patch
 drm-i915-prevent-the-system-suspend-complete-optimization.patch
 partitions-msdos-freebsd-ufs2-file-systems-are-not-recognized.patch
 netfilter-nf_conntrack_sip-fix-wrong-memory-initialisation.patch
+ibmvnic-fix-endian-errors-in-error-reporting-output.patch
+ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch
+net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch
+net-xilinx_emaclite-fix-receive-buffer-overflow.patch
+tcp-tcp_probe-use-spin_lock_bh.patch
+ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch
+ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch
+tipc-fix-tipc_sk_reinit-race-conditions.patch
+gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch
diff --git a/queue-4.9/tcp-tcp_probe-use-spin_lock_bh.patch b/queue-4.9/tcp-tcp_probe-use-spin_lock_bh.patch
new file mode 100644 (file)
index 0000000..203f145
--- /dev/null
@@ -0,0 +1,45 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 23 May 2017 21:53:32 -0400
+Subject: tcp: tcp_probe: use spin_lock_bh()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit e70ac171658679ecf6bea4bbd9e9325cd6079d2b ]
+
+tcp_rcv_established() can now run in process context.
+
+We need to disable BH while acquiring tcp probe spinlock,
+or risk a deadlock.
+
+Fixes: 5413d1babe8f ("net: do not block BH while processing socket backlog")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Ricardo Nabinger Sanchez <rnsanchez@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_probe.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_probe.c
++++ b/net/ipv4/tcp_probe.c
+@@ -117,7 +117,7 @@ static void jtcp_rcv_established(struct
+            (fwmark > 0 && skb->mark == fwmark)) &&
+           (full || tp->snd_cwnd != tcp_probe.lastcwnd)) {
+-              spin_lock(&tcp_probe.lock);
++              spin_lock_bh(&tcp_probe.lock);
+               /* If log fills, just silently drop */
+               if (tcp_probe_avail() > 1) {
+                       struct tcp_log *p = tcp_probe.log + tcp_probe.head;
+@@ -157,7 +157,7 @@ static void jtcp_rcv_established(struct
+                       tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1);
+               }
+               tcp_probe.lastcwnd = tp->snd_cwnd;
+-              spin_unlock(&tcp_probe.lock);
++              spin_unlock_bh(&tcp_probe.lock);
+               wake_up(&tcp_probe.wait);
+       }
diff --git a/queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch b/queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch
new file mode 100644 (file)
index 0000000..2d50531
--- /dev/null
@@ -0,0 +1,106 @@
+From foo@baz Thu Jun 15 09:31:48 CEST 2017
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Tue, 23 May 2017 21:53:35 -0400
+Subject: tipc: Fix tipc_sk_reinit race conditions
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+
+[ Upstream commit 9dbbfb0ab6680c6a85609041011484e6658e7d3c ]
+
+There are two problems with the function tipc_sk_reinit.  Firstly
+it's doing a manual walk over an rhashtable.  This is broken as
+an rhashtable can be resized and if you manually walk over it
+during a resize then you may miss entries.
+
+Secondly it's missing memory barriers as previously the code used
+spinlocks which provide the barriers implicitly.
+
+This patch fixes both problems.
+
+Fixes: 07f6c4bc048a ("tipc: convert tipc reference table to...")
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Acked-by: Ying Xue <ying.xue@windriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tipc/net.c    |    4 ++++
+ net/tipc/socket.c |   30 +++++++++++++++++++-----------
+ 2 files changed, 23 insertions(+), 11 deletions(-)
+
+--- a/net/tipc/net.c
++++ b/net/tipc/net.c
+@@ -110,6 +110,10 @@ int tipc_net_start(struct net *net, u32
+       char addr_string[16];
+       tn->own_addr = addr;
++
++      /* Ensure that the new address is visible before we reinit. */
++      smp_mb();
++
+       tipc_named_reinit(net);
+       tipc_sk_reinit(net);
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -335,8 +335,6 @@ static int tipc_sk_create(struct net *ne
+       INIT_LIST_HEAD(&tsk->publications);
+       msg = &tsk->phdr;
+       tn = net_generic(sock_net(sk), tipc_net_id);
+-      tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG,
+-                    NAMED_H_SIZE, 0);
+       /* Finish initializing socket data structures */
+       sock->ops = ops;
+@@ -346,6 +344,13 @@ static int tipc_sk_create(struct net *ne
+               pr_warn("Socket create failed; port number exhausted\n");
+               return -EINVAL;
+       }
++
++      /* Ensure tsk is visible before we read own_addr. */
++      smp_mb();
++
++      tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG,
++                    NAMED_H_SIZE, 0);
++
+       msg_set_origport(msg, tsk->portid);
+       setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
+       sk->sk_backlog_rcv = tipc_backlog_rcv;
+@@ -2264,24 +2269,27 @@ static int tipc_sk_withdraw(struct tipc_
+ void tipc_sk_reinit(struct net *net)
+ {
+       struct tipc_net *tn = net_generic(net, tipc_net_id);
+-      const struct bucket_table *tbl;
+-      struct rhash_head *pos;
++      struct rhashtable_iter iter;
+       struct tipc_sock *tsk;
+       struct tipc_msg *msg;
+-      int i;
+-      rcu_read_lock();
+-      tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht);
+-      for (i = 0; i < tbl->size; i++) {
+-              rht_for_each_entry_rcu(tsk, pos, tbl, i, node) {
++      rhashtable_walk_enter(&tn->sk_rht, &iter);
++
++      do {
++              tsk = ERR_PTR(rhashtable_walk_start(&iter));
++              if (tsk)
++                      continue;
++
++              while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) {
+                       spin_lock_bh(&tsk->sk.sk_lock.slock);
+                       msg = &tsk->phdr;
+                       msg_set_prevnode(msg, tn->own_addr);
+                       msg_set_orignode(msg, tn->own_addr);
+                       spin_unlock_bh(&tsk->sk.sk_lock.slock);
+               }
+-      }
+-      rcu_read_unlock();
++
++              rhashtable_walk_stop(&iter);
++      } while (tsk == ERR_PTR(-EAGAIN));
+ }
+ static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid)