--- /dev/null
+From 2890decfd9969cac21067ca0c734fbccaf74d634 Mon Sep 17 00:00:00 2001
+From: "Zhang, Jerry" <Jerry.Zhang@amd.com>
+Date: Fri, 14 Jul 2017 18:20:17 +0800
+Subject: drm/amdgpu: read reg in each iterator of psp_wait_for loop
+
+From: Zhang, Jerry <Jerry.Zhang@amd.com>
+
+commit 2890decfd9969cac21067ca0c734fbccaf74d634 upstream.
+
+v2: fix the SOS loading failure for PSP v3.1
+
+Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com> (v1)
+Acked-by: Huang Rui <ray.huang@amd.com> (v1)
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 +--
+ drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 2 --
+ 2 files changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+@@ -95,9 +95,8 @@ int psp_wait_for(struct psp_context *psp
+ int i;
+ struct amdgpu_device *adev = psp->adev;
+
+- val = RREG32(reg_index);
+-
+ for (i = 0; i < adev->usec_timeout; i++) {
++ val = RREG32(reg_index);
+ if (check_changed) {
+ if (val != reg_val)
+ return 0;
+--- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
++++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
+@@ -237,11 +237,9 @@ int psp_v3_1_bootloader_load_sos(struct
+
+ /* there might be handshake issue with hardware which needs delay */
+ mdelay(20);
+-#if 0
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
+ RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
+ 0, true);
+-#endif
+
+ return ret;
+ }
--- /dev/null
+From ecdb19f4b513033e6f2c4326cd5b81e04393e5e1 Mon Sep 17 00:00:00 2001
+From: Alex Estrin <alex.estrin@intel.com>
+Date: Fri, 4 Aug 2017 13:52:13 -0700
+Subject: IB/hfi1: Revert egress pkey check enforcement
+
+From: Alex Estrin <alex.estrin@intel.com>
+
+commit ecdb19f4b513033e6f2c4326cd5b81e04393e5e1 upstream.
+
+Current code has some serious flaws. Disarm the flag
+pending an appropriate patch.
+
+Fixes: 53526500f301 ("IB/hfi1: Permanently enable P_Key checking in HFI")
+Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Alex Estrin <alex.estrin@intel.com>
+Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/hfi1/init.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/infiniband/hw/hfi1/init.c
++++ b/drivers/infiniband/hw/hfi1/init.c
+@@ -483,7 +483,6 @@ void hfi1_init_pportdata(struct pci_dev
+
+ ppd->pkeys[default_pkey_idx] = DEFAULT_P_KEY;
+ ppd->part_enforce |= HFI1_PART_ENFORCE_IN;
+- ppd->part_enforce |= HFI1_PART_ENFORCE_OUT;
+
+ if (loopback) {
+ hfi1_early_err(&pdev->dev,
--- /dev/null
+From 4c25b7a39005c9243a492b577c3e940eeac36a25 Mon Sep 17 00:00:00 2001
+From: Majd Dibbiny <majd@mellanox.com>
+Date: Mon, 12 Jun 2017 10:36:15 +0300
+Subject: IB/mlx5: Fix cached MR allocation flow
+
+From: Majd Dibbiny <majd@mellanox.com>
+
+commit 4c25b7a39005c9243a492b577c3e940eeac36a25 upstream.
+
+When we have a miss in one order of the mkey cache, we try to get
+an mkey from a higher order.
+
+We still need to check that the higher order can be used with UMR
+before using it. Otherwise, we will get an mkey with 0 entries and
+the post send operation that is used to fill it will complete with
+the following error:
+
+mlx5_0:dump_cqe:275:(pid 0): dump error cqe
+00000000 00000000 00000000 00000000
+00000000 00000000 00000000 00000000
+00000000 0f007806 25000025 49ce59d2
+
+Fixes: 49780d42dfc9 ("IB/mlx5: Expose MR cache for mlx5_ib")
+Signed-off-by: Majd Dibbiny <majd@mellanox.com>
+Reviewed-by: Ilya Lesokhin <ilyal@mellanox.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx5/mr.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -48,6 +48,7 @@ enum {
+ #define MLX5_UMR_ALIGN 2048
+
+ static int clean_mr(struct mlx5_ib_mr *mr);
++static int max_umr_order(struct mlx5_ib_dev *dev);
+ static int use_umr(struct mlx5_ib_dev *dev, int order);
+ static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
+
+@@ -491,16 +492,18 @@ static struct mlx5_ib_mr *alloc_cached_m
+ struct mlx5_mr_cache *cache = &dev->cache;
+ struct mlx5_ib_mr *mr = NULL;
+ struct mlx5_cache_ent *ent;
++ int last_umr_cache_entry;
+ int c;
+ int i;
+
+ c = order2idx(dev, order);
+- if (c < 0 || c > MAX_UMR_CACHE_ENTRY) {
++ last_umr_cache_entry = order2idx(dev, max_umr_order(dev));
++ if (c < 0 || c > last_umr_cache_entry) {
+ mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
+ return NULL;
+ }
+
+- for (i = c; i < MAX_UMR_CACHE_ENTRY; i++) {
++ for (i = c; i <= last_umr_cache_entry; i++) {
+ ent = &cache->ent[i];
+
+ mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
+@@ -816,11 +819,16 @@ static int get_octo_len(u64 addr, u64 le
+ return (npages + 1) / 2;
+ }
+
+-static int use_umr(struct mlx5_ib_dev *dev, int order)
++static int max_umr_order(struct mlx5_ib_dev *dev)
+ {
+ if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
+- return order <= MAX_UMR_CACHE_ENTRY + 2;
+- return order <= MLX5_MAX_UMR_SHIFT;
++ return MAX_UMR_CACHE_ENTRY + 2;
++ return MLX5_MAX_UMR_SHIFT;
++}
++
++static int use_umr(struct mlx5_ib_dev *dev, int order)
++{
++ return order <= max_umr_order(dev);
+ }
+
+ static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
--- /dev/null
+From 5b0ef650bd0f820e922fcc42f1985d4621ae19cf Mon Sep 17 00:00:00 2001
+From: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Date: Mon, 21 Aug 2017 18:26:20 -0700
+Subject: IB/{qib, hfi1}: Avoid flow control testing for RDMA write operation
+
+From: Mike Marciniszyn <mike.marciniszyn@intel.com>
+
+commit 5b0ef650bd0f820e922fcc42f1985d4621ae19cf upstream.
+
+Section 9.7.7.2.5 of the 1.3 IBTA spec clearly says that receive
+credits should never apply to RDMA write.
+
+qib and hfi1 were doing that. The following situation will result
+in a QP hang:
+- A prior SEND or RDMA_WRITE with immmediate consumed the last
+ credit for a QP using RC receive buffer credits
+- The prior op is acked so there are no more acks
+- The peer ULP fails to post receive for some reason
+- An RDMA write sees that the credits are exhausted and waits
+- The peer ULP posts receive buffers
+- The ULP posts a send or RDMA write that will be hung
+
+The fix is to avoid the credit test for the RDMA write operation.
+
+Reviewed-by: Kaike Wan <kaike.wan@intel.com>
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/hfi1/rc.c | 3 ++-
+ drivers/infiniband/hw/qib/qib_rc.c | 4 ++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/infiniband/hw/hfi1/rc.c
++++ b/drivers/infiniband/hw/hfi1/rc.c
+@@ -425,7 +425,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp,
+ case IB_WR_RDMA_WRITE:
+ if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
+ qp->s_lsn++;
+- /* FALLTHROUGH */
++ goto no_flow_control;
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ /* If no credit, return. */
+ if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
+@@ -433,6 +433,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp,
+ qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
+ goto bail;
+ }
++no_flow_control:
+ put_ib_reth_vaddr(
+ wqe->rdma_wr.remote_addr,
+ &ohdr->u.rc.reth);
+--- a/drivers/infiniband/hw/qib/qib_rc.c
++++ b/drivers/infiniband/hw/qib/qib_rc.c
+@@ -348,7 +348,7 @@ int qib_make_rc_req(struct rvt_qp *qp, u
+ case IB_WR_RDMA_WRITE:
+ if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
+ qp->s_lsn++;
+- /* FALLTHROUGH */
++ goto no_flow_control;
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ /* If no credit, return. */
+ if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
+@@ -356,7 +356,7 @@ int qib_make_rc_req(struct rvt_qp *qp, u
+ qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
+ goto bail;
+ }
+-
++no_flow_control:
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
+ ohdr->u.rc.reth.rkey =
--- /dev/null
+From 122d6a347329818419b032c5a1776e6b3866d9b9 Mon Sep 17 00:00:00 2001
+From: Cameron Gutman <aicommander@gmail.com>
+Date: Tue, 12 Sep 2017 11:27:44 -0700
+Subject: Input: xpad - validate USB endpoint type during probe
+
+From: Cameron Gutman <aicommander@gmail.com>
+
+commit 122d6a347329818419b032c5a1776e6b3866d9b9 upstream.
+
+We should only see devices with interrupt endpoints. Ignore any other
+endpoints that we find, so we don't send try to send them interrupt URBs
+and trigger a WARN down in the USB stack.
+
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Cameron Gutman <aicommander@gmail.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/joystick/xpad.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -1764,10 +1764,12 @@ static int xpad_probe(struct usb_interfa
+ struct usb_endpoint_descriptor *ep =
+ &intf->cur_altsetting->endpoint[i].desc;
+
+- if (usb_endpoint_dir_in(ep))
+- ep_irq_in = ep;
+- else
+- ep_irq_out = ep;
++ if (usb_endpoint_xfer_int(ep)) {
++ if (usb_endpoint_dir_in(ep))
++ ep_irq_in = ep;
++ else
++ ep_irq_out = ep;
++ }
+ }
+
+ if (!ep_irq_in || !ep_irq_out) {
--- /dev/null
+From f58e76c1c551c7577b25a6fe493d82f5214331b7 Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Wed, 23 Aug 2017 15:29:10 -0700
+Subject: <linux/uaccess.h>: Fix copy_in_user() declaration
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit f58e76c1c551c7577b25a6fe493d82f5214331b7 upstream.
+
+copy_in_user() copies data from user-space address @from to user-
+space address @to. Hence declare both @from and @to as user-space
+pointers.
+
+Fixes: commit d597580d3737 ("generic ...copy_..._user primitives")
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/uaccess.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/include/linux/uaccess.h
++++ b/include/linux/uaccess.h
+@@ -156,7 +156,7 @@ copy_to_user(void __user *to, const void
+ }
+ #ifdef CONFIG_COMPAT
+ static __always_inline unsigned long __must_check
+-copy_in_user(void __user *to, const void *from, unsigned long n)
++copy_in_user(void __user *to, const void __user *from, unsigned long n)
+ {
+ might_fault();
+ if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n))
--- /dev/null
+From b5accbb0dfae36d8d36cd882096943c98d5ede15 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 22 Jun 2017 15:31:13 +0200
+Subject: orangefs: Don't clear SGID when inheriting ACLs
+
+From: Jan Kara <jack@suse.cz>
+
+commit b5accbb0dfae36d8d36cd882096943c98d5ede15 upstream.
+
+When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit
+set, DIR1 is expected to have SGID bit set (and owning group equal to
+the owning group of 'DIR0'). However when 'DIR0' also has some default
+ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on
+'DIR1' to get cleared if user is not member of the owning group.
+
+Fix the problem by creating __orangefs_set_acl() function that does not
+call posix_acl_update_mode() and use it when inheriting ACLs. That
+prevents SGID bit clearing and the mode has been properly set by
+posix_acl_create() anyway.
+
+Fixes: 073931017b49d9458aa351605b43a7e34598caef
+CC: stable@vger.kernel.org
+CC: Mike Marshall <hubcap@omnibond.com>
+CC: pvfs2-developers@beowulf-underground.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Mike Marshall <hubcap@omnibond.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/orangefs/acl.c | 48 ++++++++++++++++++++++++++++--------------------
+ 1 file changed, 28 insertions(+), 20 deletions(-)
+
+--- a/fs/orangefs/acl.c
++++ b/fs/orangefs/acl.c
+@@ -61,9 +61,9 @@ struct posix_acl *orangefs_get_acl(struc
+ return acl;
+ }
+
+-int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
++static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl,
++ int type)
+ {
+- struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
+ int error = 0;
+ void *value = NULL;
+ size_t size = 0;
+@@ -72,22 +72,6 @@ int orangefs_set_acl(struct inode *inode
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ name = XATTR_NAME_POSIX_ACL_ACCESS;
+- if (acl) {
+- umode_t mode;
+-
+- error = posix_acl_update_mode(inode, &mode, &acl);
+- if (error) {
+- gossip_err("%s: posix_acl_update_mode err: %d\n",
+- __func__,
+- error);
+- return error;
+- }
+-
+- if (inode->i_mode != mode)
+- SetModeFlag(orangefs_inode);
+- inode->i_mode = mode;
+- mark_inode_dirty_sync(inode);
+- }
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = XATTR_NAME_POSIX_ACL_DEFAULT;
+@@ -132,6 +116,29 @@ out:
+ return error;
+ }
+
++int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
++{
++ int error;
++
++ if (type == ACL_TYPE_ACCESS && acl) {
++ umode_t mode;
++
++ error = posix_acl_update_mode(inode, &mode, &acl);
++ if (error) {
++ gossip_err("%s: posix_acl_update_mode err: %d\n",
++ __func__,
++ error);
++ return error;
++ }
++
++ if (inode->i_mode != mode)
++ SetModeFlag(ORANGEFS_I(inode));
++ inode->i_mode = mode;
++ mark_inode_dirty_sync(inode);
++ }
++ return __orangefs_set_acl(inode, acl, type);
++}
++
+ int orangefs_init_acl(struct inode *inode, struct inode *dir)
+ {
+ struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
+@@ -146,13 +153,14 @@ int orangefs_init_acl(struct inode *inod
+ return error;
+
+ if (default_acl) {
+- error = orangefs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
++ error = __orangefs_set_acl(inode, default_acl,
++ ACL_TYPE_DEFAULT);
+ posix_acl_release(default_acl);
+ }
+
+ if (acl) {
+ if (!error)
+- error = orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
++ error = __orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+ posix_acl_release(acl);
+ }
+
--- /dev/null
+orangefs-don-t-clear-sgid-when-inheriting-acls.patch
+linux-uaccess.h-fix-copy_in_user-declaration.patch
+ib-hfi1-revert-egress-pkey-check-enforcement.patch
+ib-qib-hfi1-avoid-flow-control-testing-for-rdma-write-operation.patch
+ib-mlx5-fix-cached-mr-allocation-flow.patch
+srcu-provide-ordering-for-cpu-not-involved-in-grace-period.patch
+smp-hotplug-handle-removal-correctly-in-cpuhp_store_callbacks.patch
+input-xpad-validate-usb-endpoint-type-during-probe.patch
+drm-amdgpu-read-reg-in-each-iterator-of-psp_wait_for-loop.patch
--- /dev/null
+From 0c96b27305faf06c068b45e07d28336c80dac286 Mon Sep 17 00:00:00 2001
+From: Ethan Barnes <Ethan.Barnes@wdc.com>
+Date: Wed, 19 Jul 2017 22:36:00 +0000
+Subject: smp/hotplug: Handle removal correctly in cpuhp_store_callbacks()
+
+From: Ethan Barnes <Ethan.Barnes@wdc.com>
+
+commit 0c96b27305faf06c068b45e07d28336c80dac286 upstream.
+
+If cpuhp_store_callbacks() is called for CPUHP_AP_ONLINE_DYN or
+CPUHP_BP_PREPARE_DYN, which are the indicators for dynamically allocated
+states, then cpuhp_store_callbacks() allocates a new dynamic state. The
+first allocation in each range returns CPUHP_AP_ONLINE_DYN or
+CPUHP_BP_PREPARE_DYN.
+
+If cpuhp_remove_state() is invoked for one of these states, then there is
+no protection against the allocation mechanism. So the removal, which
+should clear the callbacks and the name, gets a new state assigned and
+clears that one.
+
+As a consequence the state which should be cleared stays initialized. A
+consecutive CPU hotplug operation dereferences the state callbacks and
+accesses either freed or reused memory, resulting in crashes.
+
+Add a protection against this by checking the name argument for NULL. If
+it's NULL it's a removal. If not, it's an allocation.
+
+[ tglx: Added a comment and massaged changelog ]
+
+Fixes: 5b7aa87e0482 ("cpu/hotplug: Implement setup/removal interface")
+Signed-off-by: Ethan Barnes <ethan.barnes@sandisk.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@kernel.or>
+Cc: "Srivatsa S. Bhat" <srivatsa@mit.edu>
+Cc: Sebastian Siewior <bigeasy@linutronix.d>
+Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
+Link: http://lkml.kernel.org/r/DM2PR04MB398242FC7776D603D9F99C894A60@DM2PR04MB398.namprd04.prod.outlook.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/cpu.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -1252,7 +1252,17 @@ static int cpuhp_store_callbacks(enum cp
+ struct cpuhp_step *sp;
+ int ret = 0;
+
+- if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
++ /*
++ * If name is NULL, then the state gets removed.
++ *
++ * CPUHP_AP_ONLINE_DYN and CPUHP_BP_PREPARE_DYN are handed out on
++ * the first allocation from these dynamic ranges, so the removal
++ * would trigger a new allocation and clear the wrong (already
++ * empty) state, leaving the callbacks of the to be cleared state
++ * dangling, which causes wreckage on the next hotplug operation.
++ */
++ if (name && (state == CPUHP_AP_ONLINE_DYN ||
++ state == CPUHP_BP_PREPARE_DYN)) {
+ ret = cpuhp_reserve_state(state);
+ if (ret < 0)
+ return ret;
--- /dev/null
+From 35732cf9dd38b1efb0f2f22c91c61b51337d1ac3 Mon Sep 17 00:00:00 2001
+From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Date: Wed, 5 Jul 2017 13:30:21 -0700
+Subject: srcu: Provide ordering for CPU not involved in grace period
+
+From: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+commit 35732cf9dd38b1efb0f2f22c91c61b51337d1ac3 upstream.
+
+Tree RCU guarantees that every online CPU has a memory barrier between
+any given grace period and any of that CPU's RCU read-side sections that
+must be ordered against that grace period. Since RCU doesn't always
+know where read-side critical sections are, the actual implementation
+guarantees order against prior and subsequent non-idle non-offline code,
+whether in an RCU read-side critical section or not. As a result, there
+does not need to be a memory barrier at the end of synchronize_rcu()
+and friends because the ordering internal to the grace period has
+ordered every CPU's post-grace-period execution against each CPU's
+pre-grace-period execution, again for all non-idle online CPUs.
+
+In contrast, SRCU can have non-idle online CPUs that are completely
+uninvolved in a given SRCU grace period, for example, a CPU that
+never runs any SRCU read-side critical sections and took no part in
+the grace-period processing. It is in theory possible for a given
+synchronize_srcu()'s wakeup to be delivered to a CPU that was completely
+uninvolved in the prior SRCU grace period, which could mean that the
+code following that synchronize_srcu() would end up being unordered with
+respect to both the grace period and any pre-existing SRCU read-side
+critical sections.
+
+This commit therefore adds an smp_mb() to the end of __synchronize_srcu(),
+which prevents this scenario from occurring.
+
+Reported-by: Lance Roy <ldr709@gmail.com>
+Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Acked-by: Lance Roy <ldr709@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/rcu/srcutree.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/kernel/rcu/srcutree.c
++++ b/kernel/rcu/srcutree.c
+@@ -896,6 +896,15 @@ static void __synchronize_srcu(struct sr
+ __call_srcu(sp, &rcu.head, wakeme_after_rcu, do_norm);
+ wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
++
++ /*
++ * Make sure that later code is ordered after the SRCU grace
++ * period. This pairs with the raw_spin_lock_irq_rcu_node()
++ * in srcu_invoke_callbacks(). Unlike Tree RCU, this is needed
++ * because the current CPU might have been totally uninvolved with
++ * (and thus unordered against) that grace period.
++ */
++ smp_mb();
+ }
+
+ /**