--- /dev/null
+From 5607dddbfca774fb38bffadcb077fe03aa4ac5c6 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 27 Mar 2018 16:07:52 +0300
+Subject: ALSA: pcm: potential uninitialized return values
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 5607dddbfca774fb38bffadcb077fe03aa4ac5c6 upstream.
+
+Smatch complains that "tmp" can be uninitialized if we do a zero size
+write.
+
+Fixes: 02a5d6925cd3 ("ALSA: pcm: Avoid potential races between OSS ioctls and read/write")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1361,7 +1361,7 @@ static ssize_t snd_pcm_oss_write2(struct
+ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
+ {
+ size_t xfer = 0;
+- ssize_t tmp;
++ ssize_t tmp = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (atomic_read(&substream->mmap_count))
+@@ -1468,7 +1468,7 @@ static ssize_t snd_pcm_oss_read2(struct
+ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes)
+ {
+ size_t xfer = 0;
+- ssize_t tmp;
++ ssize_t tmp = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (atomic_read(&substream->mmap_count))
--- /dev/null
+From 9066ae7ff5d89c0b5daa271e2d573540097a94fa Mon Sep 17 00:00:00 2001
+From: Stefan Roese <sr@denx.de>
+Date: Mon, 26 Mar 2018 16:10:21 +0200
+Subject: ALSA: pcm: Use dma_bytes as size parameter in dma_mmap_coherent()
+
+From: Stefan Roese <sr@denx.de>
+
+commit 9066ae7ff5d89c0b5daa271e2d573540097a94fa upstream.
+
+When trying to use the driver (e.g. aplay *.wav), the 4MiB DMA buffer
+will get mmapp'ed in 16KiB chunks. But this fails with the 2nd 16KiB
+area, as the page offset is outside of the VMA range (size), which is
+currently used as size parameter in snd_pcm_lib_default_mmap(). By
+using the DMA buffer size (dma_bytes) instead, the complete DMA buffer
+can be mmapp'ed and the issue is fixed.
+
+This issue was detected on an ARM platform (TI AM57xx) using the RME
+HDSP MADI PCIe soundcard.
+
+Fixes: 657b1989dacf ("ALSA: pcm - Use dma_mmap_coherent() if available")
+Signed-off-by: Stefan Roese <sr@denx.de>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/pcm_native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3410,7 +3410,7 @@ int snd_pcm_lib_default_mmap(struct snd_
+ area,
+ substream->runtime->dma_area,
+ substream->runtime->dma_addr,
+- area->vm_end - area->vm_start);
++ substream->runtime->dma_bytes);
+ #endif /* CONFIG_X86 */
+ /* mmap with fault handler */
+ area->vm_ops = &snd_pcm_vm_ops_data_fault;
--- /dev/null
+From b00214865d65100163574ba250008f182cf90869 Mon Sep 17 00:00:00 2001
+From: Nobutaka Okabe <nob77413@gmail.com>
+Date: Fri, 23 Mar 2018 19:49:44 +0900
+Subject: ALSA: usb-audio: Add native DSD support for TEAC UD-301
+
+From: Nobutaka Okabe <nob77413@gmail.com>
+
+commit b00214865d65100163574ba250008f182cf90869 upstream.
+
+Add native DSD support quirk for TEAC UD-301 DAC,
+by adding the PID/VID 0644:804a.
+
+Signed-off-by: Nobutaka Okabe <nob77413@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1175,6 +1175,7 @@ static bool is_teac_dsd_dac(unsigned int
+ switch (id) {
+ case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */
+ case USB_ID(0x0644, 0x8044): /* Esoteric D-05X */
++ case USB_ID(0x0644, 0x804a): /* TEAC UD-301 */
+ return true;
+ }
+ return false;
--- /dev/null
+From 1328f02005bbbaed15b9d5b7f3ab5ec9d4d5268a Mon Sep 17 00:00:00 2001
+From: Fabio Estevam <festevam@gmail.com>
+Date: Mon, 22 Jan 2018 12:20:26 +0100
+Subject: ARM: 8746/1: vfp: Go back to clearing vfp_current_hw_state[]
+
+From: Fabio Estevam <festevam@gmail.com>
+
+commit 1328f02005bbbaed15b9d5b7f3ab5ec9d4d5268a upstream.
+
+Commit 384b38b66947 ("ARM: 7873/1: vfp: clear vfp_current_hw_state
+for dying cpu") fixed the cpu dying notifier by clearing
+vfp_current_hw_state[]. However commit e5b61bafe704 ("arm: Convert VFP
+hotplug notifiers to state machine") incorrectly used the original
+vfp_force_reload() function in the cpu dying notifier.
+
+Fix it by going back to clearing vfp_current_hw_state[].
+
+Fixes: e5b61bafe704 ("arm: Convert VFP hotplug notifiers to state machine")
+Cc: linux-stable <stable@vger.kernel.org>
+Reported-by: Kohji Okuno <okuno.kohji@jp.panasonic.com>
+Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/vfp/vfpmodule.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -648,7 +648,7 @@ int vfp_restore_user_hwstate(struct user
+ */
+ static int vfp_dying_cpu(unsigned int cpu)
+ {
+- vfp_force_reload(cpu, current_thread_info());
++ vfp_current_hw_state[cpu] = NULL;
+ return 0;
+ }
+
--- /dev/null
+From 85784f9395987a422fa04263e7c0fb13da11eb5c Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zyan@redhat.com>
+Date: Fri, 16 Mar 2018 11:22:29 +0800
+Subject: ceph: only dirty ITER_IOVEC pages for direct read
+
+From: Yan, Zheng <zyan@redhat.com>
+
+commit 85784f9395987a422fa04263e7c0fb13da11eb5c upstream.
+
+If a page is already locked, attempting to dirty it leads to a deadlock
+in lock_page(). This is what currently happens to ITER_BVEC pages when
+a dio-enabled loop device is backed by ceph:
+
+ $ losetup --direct-io /dev/loop0 /mnt/cephfs/img
+ $ xfs_io -c 'pread 0 4k' /dev/loop0
+
+Follow other file systems and only dirty ITER_IOVEC pages.
+
+Cc: stable@kernel.org
+Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ceph/file.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/ceph/file.c
++++ b/fs/ceph/file.c
+@@ -598,7 +598,8 @@ static ssize_t ceph_sync_read(struct kio
+ struct ceph_aio_request {
+ struct kiocb *iocb;
+ size_t total_len;
+- int write;
++ bool write;
++ bool should_dirty;
+ int error;
+ struct list_head osd_reqs;
+ unsigned num_reqs;
+@@ -708,7 +709,7 @@ static void ceph_aio_complete_req(struct
+ }
+ }
+
+- ceph_put_page_vector(osd_data->pages, num_pages, !aio_req->write);
++ ceph_put_page_vector(osd_data->pages, num_pages, aio_req->should_dirty);
+ ceph_osdc_put_request(req);
+
+ if (rc < 0)
+@@ -890,6 +891,7 @@ ceph_direct_read_write(struct kiocb *ioc
+ size_t count = iov_iter_count(iter);
+ loff_t pos = iocb->ki_pos;
+ bool write = iov_iter_rw(iter) == WRITE;
++ bool should_dirty = !write && iter_is_iovec(iter);
+
+ if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+ return -EROFS;
+@@ -954,6 +956,7 @@ ceph_direct_read_write(struct kiocb *ioc
+ if (aio_req) {
+ aio_req->iocb = iocb;
+ aio_req->write = write;
++ aio_req->should_dirty = should_dirty;
+ INIT_LIST_HEAD(&aio_req->osd_reqs);
+ if (write) {
+ aio_req->mtime = mtime;
+@@ -1012,7 +1015,7 @@ ceph_direct_read_write(struct kiocb *ioc
+ len = ret;
+ }
+
+- ceph_put_page_vector(pages, num_pages, !write);
++ ceph_put_page_vector(pages, num_pages, should_dirty);
+
+ ceph_osdc_put_request(req);
+ if (ret < 0)
--- /dev/null
+From 3d942ee079b917b24e2a0c5f18d35ac8ec9fee48 Mon Sep 17 00:00:00 2001
+From: Mike Kravetz <mike.kravetz@oracle.com>
+Date: Wed, 28 Mar 2018 16:01:01 -0700
+Subject: ipc/shm.c: add split function to shm_vm_ops
+
+From: Mike Kravetz <mike.kravetz@oracle.com>
+
+commit 3d942ee079b917b24e2a0c5f18d35ac8ec9fee48 upstream.
+
+If System V shmget/shmat operations are used to create a hugetlbfs
+backed mapping, it is possible to munmap part of the mapping and split
+the underlying vma such that it is not huge page aligned. This will
+untimately result in the following BUG:
+
+ kernel BUG at /build/linux-jWa1Fv/linux-4.15.0/mm/hugetlb.c:3310!
+ Oops: Exception in kernel mode, sig: 5 [#1]
+ LE SMP NR_CPUS=2048 NUMA PowerNV
+ Modules linked in: kcm nfc af_alg caif_socket caif phonet fcrypt
+ CPU: 18 PID: 43243 Comm: trinity-subchil Tainted: G C E 4.15.0-10-generic #11-Ubuntu
+ NIP: c00000000036e764 LR: c00000000036ee48 CTR: 0000000000000009
+ REGS: c000003fbcdcf810 TRAP: 0700 Tainted: G C E (4.15.0-10-generic)
+ MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24002222 XER: 20040000
+ CFAR: c00000000036ee44 SOFTE: 1
+ NIP __unmap_hugepage_range+0xa4/0x760
+ LR __unmap_hugepage_range_final+0x28/0x50
+ Call Trace:
+ 0x7115e4e00000 (unreliable)
+ __unmap_hugepage_range_final+0x28/0x50
+ unmap_single_vma+0x11c/0x190
+ unmap_vmas+0x94/0x140
+ exit_mmap+0x9c/0x1d0
+ mmput+0xa8/0x1d0
+ do_exit+0x360/0xc80
+ do_group_exit+0x60/0x100
+ SyS_exit_group+0x24/0x30
+ system_call+0x58/0x6c
+ ---[ end trace ee88f958a1c62605 ]---
+
+This bug was introduced by commit 31383c6865a5 ("mm, hugetlbfs:
+introduce ->split() to vm_operations_struct"). A split function was
+added to vm_operations_struct to determine if a mapping can be split.
+This was mostly for device-dax and hugetlbfs mappings which have
+specific alignment constraints.
+
+Mappings initiated via shmget/shmat have their original vm_ops
+overwritten with shm_vm_ops. shm_vm_ops functions will call back to the
+original vm_ops if needed. Add such a split function to shm_vm_ops.
+
+Link: http://lkml.kernel.org/r/20180321161314.7711-1-mike.kravetz@oracle.com
+Fixes: 31383c6865a5 ("mm, hugetlbfs: introduce ->split() to vm_operations_struct")
+Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
+Reported-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
+Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
+Tested-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
+Reviewed-by: Dan Williams <dan.j.williams@intel.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -381,6 +381,17 @@ static int shm_fault(struct vm_area_stru
+ return sfd->vm_ops->fault(vma, vmf);
+ }
+
++static int shm_split(struct vm_area_struct *vma, unsigned long addr)
++{
++ struct file *file = vma->vm_file;
++ struct shm_file_data *sfd = shm_file_data(file);
++
++ if (sfd->vm_ops && sfd->vm_ops->split)
++ return sfd->vm_ops->split(vma, addr);
++
++ return 0;
++}
++
+ #ifdef CONFIG_NUMA
+ static int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+ {
+@@ -503,6 +514,7 @@ static const struct vm_operations_struct
+ .open = shm_open, /* callback for a new vm-area open */
+ .close = shm_close, /* callback for when the vm-area is released */
+ .fault = shm_fault,
++ .split = shm_split,
+ #if defined(CONFIG_NUMA)
+ .set_policy = shm_set_policy,
+ .get_policy = shm_get_policy,
--- /dev/null
+From 87a73eb5b56fd6e07c8e499fe8608ef2d8912b82 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Sat, 3 Mar 2018 23:29:03 +0100
+Subject: mtd: jedec_probe: Fix crash in jedec_read_mfr()
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+commit 87a73eb5b56fd6e07c8e499fe8608ef2d8912b82 upstream.
+
+It turns out that the loop where we read manufacturer
+jedec_read_mfd() can under some circumstances get a
+CFI_MFR_CONTINUATION repeatedly, making the loop go
+over all banks and eventually hit the end of the
+map and crash because of an access violation:
+
+Unable to handle kernel paging request at virtual address c4980000
+pgd = (ptrval)
+[c4980000] *pgd=03808811, *pte=00000000, *ppte=00000000
+Internal error: Oops: 7 [#1] PREEMPT ARM
+CPU: 0 PID: 1 Comm: swapper Not tainted 4.16.0-rc1+ #150
+Hardware name: Gemini (Device Tree)
+PC is at jedec_probe_chip+0x6ec/0xcd0
+LR is at 0x4
+pc : [<c03a2bf4>] lr : [<00000004>] psr: 60000013
+sp : c382dd18 ip : 0000ffff fp : 00000000
+r10: c0626388 r9 : 00020000 r8 : c0626340
+r7 : 00000000 r6 : 00000001 r5 : c3a71afc r4 : c382dd70
+r3 : 00000001 r2 : c4900000 r1 : 00000002 r0 : 00080000
+Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
+Control: 0000397f Table: 00004000 DAC: 00000053
+Process swapper (pid: 1, stack limit = 0x(ptrval))
+
+Fix this by breaking the loop with a return 0 if
+the offset exceeds the map size.
+
+Fixes: 5c9c11e1c47c ("[MTD] [NOR] Add support for flash chips with ID in bank other than 0")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/chips/jedec_probe.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/mtd/chips/jedec_probe.c
++++ b/drivers/mtd/chips/jedec_probe.c
+@@ -1889,6 +1889,8 @@ static inline u32 jedec_read_mfr(struct
+ do {
+ uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi);
+ mask = (1 << (cfi->device_type * 8)) - 1;
++ if (ofs >= map->size)
++ return 0;
+ result = map_read(map, base + ofs);
+ bank++;
+ } while ((result.x[0] & mask) == CFI_MFR_CONTINUATION);
--- /dev/null
+From f67b15037a7a50c57f72e69a6d59941ad90a0f0f Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Mon, 26 Mar 2018 15:39:07 -1000
+Subject: perf/hwbp: Simplify the perf-hwbp code, fix documentation
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit f67b15037a7a50c57f72e69a6d59941ad90a0f0f upstream.
+
+Annoyingly, modify_user_hw_breakpoint() unnecessarily complicates the
+modification of a breakpoint - simplify it and remove the pointless
+local variables.
+
+Also update the stale Docbook while at it.
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: <stable@vger.kernel.org>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
+Cc: Frederic Weisbecker <fweisbec@gmail.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Stephane Eranian <eranian@google.com>
+Cc: Vince Weaver <vincent.weaver@maine.edu>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/events/hw_breakpoint.c | 30 +++++++-----------------------
+ 1 file changed, 7 insertions(+), 23 deletions(-)
+
+--- a/kernel/events/hw_breakpoint.c
++++ b/kernel/events/hw_breakpoint.c
+@@ -427,16 +427,9 @@ EXPORT_SYMBOL_GPL(register_user_hw_break
+ * modify_user_hw_breakpoint - modify a user-space hardware breakpoint
+ * @bp: the breakpoint structure to modify
+ * @attr: new breakpoint attributes
+- * @triggered: callback to trigger when we hit the breakpoint
+- * @tsk: pointer to 'task_struct' of the process to which the address belongs
+ */
+ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr)
+ {
+- u64 old_addr = bp->attr.bp_addr;
+- u64 old_len = bp->attr.bp_len;
+- int old_type = bp->attr.bp_type;
+- int err = 0;
+-
+ /*
+ * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it
+ * will not be possible to raise IPIs that invoke __perf_event_disable.
+@@ -451,27 +444,18 @@ int modify_user_hw_breakpoint(struct per
+ bp->attr.bp_addr = attr->bp_addr;
+ bp->attr.bp_type = attr->bp_type;
+ bp->attr.bp_len = attr->bp_len;
++ bp->attr.disabled = 1;
+
+- if (attr->disabled)
+- goto end;
+-
+- err = validate_hw_breakpoint(bp);
+- if (!err)
+- perf_event_enable(bp);
++ if (!attr->disabled) {
++ int err = validate_hw_breakpoint(bp);
+
+- if (err) {
+- bp->attr.bp_addr = old_addr;
+- bp->attr.bp_type = old_type;
+- bp->attr.bp_len = old_len;
+- if (!bp->attr.disabled)
+- perf_event_enable(bp);
++ if (err)
++ return err;
+
+- return err;
++ perf_event_enable(bp);
++ bp->attr.disabled = 0;
+ }
+
+-end:
+- bp->attr.disabled = attr->disabled;
+-
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint);
--- /dev/null
+From 52396500f97c53860164debc7d4f759077853423 Mon Sep 17 00:00:00 2001
+From: Nicholas Piggin <npiggin@gmail.com>
+Date: Fri, 23 Mar 2018 15:53:38 +1000
+Subject: powerpc/64s: Fix i-side SLB miss bad address handler saving nonvolatile GPRs
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+commit 52396500f97c53860164debc7d4f759077853423 upstream.
+
+The SLB bad address handler's trap number fixup does not preserve the
+low bit that indicates nonvolatile GPRs have not been saved. This
+leads save_nvgprs to skip saving them, and subsequent functions and
+return from interrupt will think they are saved.
+
+This causes kernel branch-to-garbage debugging to not have correct
+registers, can also cause userspace to have its registers clobbered
+after a segfault.
+
+Fixes: f0f558b131db ("powerpc/mm: Preserve CFAR value on SLB miss caused by access to bogus address")
+Cc: stable@vger.kernel.org # v4.9+
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/exceptions-64s.S | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/powerpc/kernel/exceptions-64s.S
++++ b/arch/powerpc/kernel/exceptions-64s.S
+@@ -723,7 +723,7 @@ EXC_COMMON_BEGIN(bad_addr_slb)
+ ld r3, PACA_EXSLB+EX_DAR(r13)
+ std r3, _DAR(r1)
+ beq cr6, 2f
+- li r10, 0x480 /* fix trap number for I-SLB miss */
++ li r10, 0x481 /* fix trap number for I-SLB miss */
+ std r10, _TRAP(r1)
+ 2: bl save_nvgprs
+ addi r3, r1, STACK_FRAME_OVERHEAD
--- /dev/null
+From ff6781fd1bb404d8a551c02c35c70cec1da17ff1 Mon Sep 17 00:00:00 2001
+From: Nicholas Piggin <npiggin@gmail.com>
+Date: Wed, 21 Mar 2018 12:22:28 +1000
+Subject: powerpc/64s: Fix lost pending interrupt due to race causing lost update to irq_happened
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+commit ff6781fd1bb404d8a551c02c35c70cec1da17ff1 upstream.
+
+force_external_irq_replay() can be called in the do_IRQ path with
+interrupts hard enabled and soft disabled if may_hard_irq_enable() set
+MSR[EE]=1. It updates local_paca->irq_happened with a load, modify,
+store sequence. If a maskable interrupt hits during this sequence, it
+will go to the masked handler to be marked pending in irq_happened.
+This update will be lost when the interrupt returns and the store
+instruction executes. This can result in unpredictable latencies,
+timeouts, lockups, etc.
+
+Fix this by ensuring hard interrupts are disabled before modifying
+irq_happened.
+
+This could cause any maskable asynchronous interrupt to get lost, but
+it was noticed on P9 SMP system doing RDMA NVMe target over 100GbE,
+so very high external interrupt rate and high IPI rate. The hang was
+bisected down to enabling doorbell interrupts for IPIs. These provided
+an interrupt type that could run at high rates in the do_IRQ path,
+stressing the race.
+
+Fixes: 1d607bb3bd60 ("powerpc/irq: Add mechanism to force a replay of interrupts")
+Cc: stable@vger.kernel.org # v4.8+
+Reported-by: Carol L. Soto <clsoto@us.ibm.com>
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/irq.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/powerpc/kernel/irq.c
++++ b/arch/powerpc/kernel/irq.c
+@@ -372,6 +372,14 @@ void force_external_irq_replay(void)
+ */
+ WARN_ON(!arch_irqs_disabled());
+
++ /*
++ * Interrupts must always be hard disabled before irq_happened is
++ * modified (to prevent lost update in case of interrupt between
++ * load and store).
++ */
++ __hard_irq_disable();
++ local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
++
+ /* Indicate in the PACA that we have an interrupt to replay */
+ local_paca->irq_happened |= PACA_IRQ_EE;
+ }