--- /dev/null
+From f8585539df0a1527c78b5d760665c89fe1c105a9 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Date: Thu, 16 May 2019 23:31:59 +0200
+Subject: fbdev/efifb: Ignore framebuffer memmap entries that lack any memory types
+
+From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+
+commit f8585539df0a1527c78b5d760665c89fe1c105a9 upstream.
+
+The following commit:
+
+ 38ac0287b7f4 ("fbdev/efifb: Honour UEFI memory map attributes when mapping the FB")
+
+updated the EFI framebuffer code to use memory mappings for the linear
+framebuffer that are permitted by the memory attributes described by the
+EFI memory map for the particular region, if the framebuffer happens to
+be covered by the EFI memory map (which is typically only the case for
+framebuffers in shared memory). This is required since non-x86 systems
+may require cacheable attributes for memory mappings that are shared
+with other masters (such as GPUs), and this information cannot be
+described by the Graphics Output Protocol (GOP) EFI protocol itself,
+and so we rely on the EFI memory map for this.
+
+As reported by James, this breaks some x86 systems:
+
+ [ 1.173368] efifb: probing for efifb
+ [ 1.173386] efifb: abort, cannot remap video memory 0x1d5000 @ 0xcf800000
+ [ 1.173395] Trying to free nonexistent resource <00000000cf800000-00000000cf9d4bff>
+ [ 1.173413] efi-framebuffer: probe of efi-framebuffer.0 failed with error -5
+
+The problem turns out to be that the memory map entry that describes the
+framebuffer has no memory attributes listed at all, and so we end up with
+a mem_flags value of 0x0.
+
+So work around this by ensuring that the memory map entry's attribute field
+has a sane value before using it to mask the set of usable attributes.
+
+Reported-by: James Hilliard <james.hilliard1@gmail.com>
+Tested-by: James Hilliard <james.hilliard1@gmail.com>
+Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Cc: <stable@vger.kernel.org> # v4.19+
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: James Morse <james.morse@arm.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Matt Fleming <matt@codeblueprint.co.uk>
+Cc: Peter Jones <pjones@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: linux-efi@vger.kernel.org
+Fixes: 38ac0287b7f4 ("fbdev/efifb: Honour UEFI memory map attributes when ...")
+Link: http://lkml.kernel.org/r/20190516213159.3530-2-ard.biesheuvel@linaro.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/efifb.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/video/fbdev/efifb.c
++++ b/drivers/video/fbdev/efifb.c
+@@ -476,8 +476,12 @@ static int efifb_probe(struct platform_d
+ * If the UEFI memory map covers the efifb region, we may only
+ * remap it using the attributes the memory map prescribes.
+ */
+- mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
+- mem_flags &= md.attribute;
++ md.attribute &= EFI_MEMORY_UC | EFI_MEMORY_WC |
++ EFI_MEMORY_WT | EFI_MEMORY_WB;
++ if (md.attribute) {
++ mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
++ mem_flags &= md.attribute;
++ }
+ }
+ if (mem_flags & EFI_MEMORY_WC)
+ info->screen_base = ioremap_wc(efifb_fix.smem_start,
--- /dev/null
+From ec1587d5073f29820e358f3a383850d61601d981 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:59 +0200
+Subject: fbdev: sm712fb: fix boot screen glitch when sm712fb replaces VGA
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit ec1587d5073f29820e358f3a383850d61601d981 upstream.
+
+When the machine is booted in VGA mode, loading sm712fb would cause
+a glitch of random pixels shown on the screen. To prevent it from
+happening, we first clear the entire framebuffer, and we also need
+to stop calling smtcfb_setmode() during initialization, the fbdev
+layer will call it for us later when it's ready.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712fb.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1493,7 +1493,11 @@ static int smtcfb_pci_probe(struct pci_d
+ if (err)
+ goto failed;
+
+- smtcfb_setmode(sfb);
++ /*
++ * The screen would be temporarily garbled when sm712fb takes over
++ * vesafb or VGA text mode. Zero the framebuffer.
++ */
++ memset_io(sfb->lfb, 0, sfb->fb->fix.smem_len);
+
+ err = register_framebuffer(info);
+ if (err < 0)
--- /dev/null
+From 5481115e25e42b9215f2619452aa99c95f08492f Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:58 +0200
+Subject: fbdev: sm712fb: fix brightness control on reboot, don't set SR30
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit 5481115e25e42b9215f2619452aa99c95f08492f upstream.
+
+On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), rebooting with
+sm712fb framebuffer driver would cause the role of brightness up/down
+button to swap.
+
+Experiments showed the FPR30 register caused this behavior. Moreover,
+even if this register don't have side-effect on other systems, over-
+writing it is also highly questionable, since it was originally
+configurated by the motherboard manufacturer by hardwiring pull-down
+resistors to indicate the type of LCD panel. We should not mess with
+it.
+
+Stop writing to the SR30 (a.k.a FPR30) register.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712fb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1145,8 +1145,8 @@ static void sm7xx_set_timing(struct smtc
+
+ /* init SEQ register SR30 - SR75 */
+ for (i = 0; i < SIZE_SR30_SR75; i++)
+- if ((i + 0x30) != 0x62 && (i + 0x30) != 0x6a &&
+- (i + 0x30) != 0x6b)
++ if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
++ (i + 0x30) != 0x6a && (i + 0x30) != 0x6b)
+ smtc_seqw(i + 0x30,
+ vgamode[j].init_sr30_sr75[i]);
+
--- /dev/null
+From f627caf55b8e735dcec8fa6538e9668632b55276 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:59 +0200
+Subject: fbdev: sm712fb: fix crashes and garbled display during DPMS modesetting
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit f627caf55b8e735dcec8fa6538e9668632b55276 upstream.
+
+On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), blanking the display
+or starting the X server will crash and freeze the system, or garble the
+display.
+
+Experiments showed this problem can mostly be solved by adjusting the
+order of register writes. Also, sm712fb failed to consider the difference
+of clock frequency when unblanking the display, and programs the clock for
+SM712 to SM720.
+
+Fix them by adjusting the order of register writes, and adding an
+additional check for SM720 for programming the clock frequency.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712fb.c | 64 ++++++++++++++++++++++++------------------
+ 1 file changed, 38 insertions(+), 26 deletions(-)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -886,67 +886,79 @@ static inline unsigned int chan_to_field
+
+ static int smtc_blank(int blank_mode, struct fb_info *info)
+ {
++ struct smtcfb_info *sfb = info->par;
++
+ /* clear DPMS setting */
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ /* Screen On: HSync: On, VSync : On */
++
++ switch (sfb->chip_id) {
++ case 0x710:
++ case 0x712:
++ smtc_seqw(0x6a, 0x16);
++ smtc_seqw(0x6b, 0x02);
++ case 0x720:
++ smtc_seqw(0x6a, 0x0d);
++ smtc_seqw(0x6b, 0x02);
++ break;
++ }
++
++ smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
+ smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
+- smtc_seqw(0x6a, 0x16);
+- smtc_seqw(0x6b, 0x02);
+ smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
+ smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
+- smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
+- smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
+ smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
++ smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
+ break;
+ case FB_BLANK_NORMAL:
+ /* Screen Off: HSync: On, VSync : On Soft blank */
++ smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
++ smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
++ smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
+ smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
++ smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
+ smtc_seqw(0x6a, 0x16);
+ smtc_seqw(0x6b, 0x02);
+- smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
+- smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
+- smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
+- smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ /* Screen On: HSync: On, VSync : Off */
++ smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
++ smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
++ smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
+ smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
+- smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+- smtc_seqw(0x6a, 0x0c);
+- smtc_seqw(0x6b, 0x02);
+ smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
++ smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+ smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
+- smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
+- smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
+- smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+ smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
++ smtc_seqw(0x6a, 0x0c);
++ smtc_seqw(0x6b, 0x02);
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ /* Screen On: HSync: Off, VSync : On */
++ smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
++ smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
++ smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
+ smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
+- smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+- smtc_seqw(0x6a, 0x0c);
+- smtc_seqw(0x6b, 0x02);
+ smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
++ smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+ smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
+- smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
+- smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
+- smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+ smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
++ smtc_seqw(0x6a, 0x0c);
++ smtc_seqw(0x6b, 0x02);
+ break;
+ case FB_BLANK_POWERDOWN:
+ /* Screen On: HSync: Off, VSync : Off */
++ smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
++ smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
++ smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
+ smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
+- smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+- smtc_seqw(0x6a, 0x0c);
+- smtc_seqw(0x6b, 0x02);
+ smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
++ smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+ smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
+- smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
+- smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
+- smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+ smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
++ smtc_seqw(0x6a, 0x0c);
++ smtc_seqw(0x6b, 0x02);
+ break;
+ default:
+ return -EINVAL;
--- /dev/null
+From 9e0e59993df0601cddb95c4f6c61aa3d5e753c00 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:59 +0200
+Subject: fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit 9e0e59993df0601cddb95c4f6c61aa3d5e753c00 upstream.
+
+On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), running fbtest or X
+will crash the machine instantly, because the VRAM/framebuffer is not
+mapped correctly.
+
+On SM712, the framebuffer starts at the beginning of address space, but
+SM720's framebuffer starts at the 1 MiB offset from the beginning. However,
+sm712fb fails to take this into account, as a result, writing to the
+framebuffer will destroy all the registers and kill the system immediately.
+Another problem is the driver assumes 8 MiB of VRAM for SM720, but some
+SM720 system, such as this IBM Thinkpad, only has 4 MiB of VRAM.
+
+Fix this problem by removing the hardcoded VRAM size, adding a function to
+query the amount of VRAM from register MCR76 on SM720, and adding proper
+framebuffer offset.
+
+Please note that the memory map may have additional problems on Big-Endian
+system, which is not available for testing by myself. But I highly suspect
+that the original code is also broken on Big-Endian machines for SM720, so
+at least we are not making the problem worse. More, the driver also assumed
+SM710/SM712 has 4 MiB of VRAM, but it has a 2 MiB version as well, and used
+in earlier laptops, such as IBM Thinkpad 240X, the driver would probably
+crash on them. I've never seen one of those machines and cannot fix it, but
+I have documented these problems in the comments.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712.h | 5 ----
+ drivers/video/fbdev/sm712fb.c | 48 ++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 44 insertions(+), 9 deletions(-)
+
+--- a/drivers/video/fbdev/sm712.h
++++ b/drivers/video/fbdev/sm712.h
+@@ -19,11 +19,6 @@
+ #define SCREEN_Y_RES 600
+ #define SCREEN_BPP 16
+
+-/*Assume SM712 graphics chip has 4MB VRAM */
+-#define SM712_VIDEOMEMORYSIZE 0x00400000
+-/*Assume SM722 graphics chip has 8MB VRAM */
+-#define SM722_VIDEOMEMORYSIZE 0x00800000
+-
+ #define dac_reg (0x3c8)
+ #define dac_val (0x3c9)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1329,6 +1329,11 @@ static int smtc_map_smem(struct smtcfb_i
+ {
+ sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
+
++ if (sfb->chip_id == 0x720)
++ /* on SM720, the framebuffer starts at the 1 MB offset */
++ sfb->fb->fix.smem_start += 0x00200000;
++
++ /* XXX: is it safe for SM720 on Big-Endian? */
+ if (sfb->fb->var.bits_per_pixel == 32)
+ sfb->fb->fix.smem_start += big_addr;
+
+@@ -1366,12 +1371,45 @@ static inline void sm7xx_init_hw(void)
+ outb_p(0x11, 0x3c5);
+ }
+
++static u_long sm7xx_vram_probe(struct smtcfb_info *sfb)
++{
++ u8 vram;
++
++ switch (sfb->chip_id) {
++ case 0x710:
++ case 0x712:
++ /*
++ * Assume SM712 graphics chip has 4MB VRAM.
++ *
++ * FIXME: SM712 can have 2MB VRAM, which is used on earlier
++ * laptops, such as IBM Thinkpad 240X. This driver would
++ * probably crash on those machines. If anyone gets one of
++ * those and is willing to help, run "git blame" and send me
++ * an E-mail.
++ */
++ return 0x00400000;
++ case 0x720:
++ outb_p(0x76, 0x3c4);
++ vram = inb_p(0x3c5) >> 6;
++
++ if (vram == 0x00)
++ return 0x00800000; /* 8 MB */
++ else if (vram == 0x01)
++ return 0x01000000; /* 16 MB */
++ else if (vram == 0x02)
++ return 0x00400000; /* illegal, fallback to 4 MB */
++ else if (vram == 0x03)
++ return 0x00400000; /* 4 MB */
++ }
++ return 0; /* unknown hardware */
++}
++
+ static int smtcfb_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+ struct smtcfb_info *sfb;
+ struct fb_info *info;
+- u_long smem_size = 0x00800000; /* default 8MB */
++ u_long smem_size;
+ int err;
+ unsigned long mmio_base;
+
+@@ -1428,12 +1466,15 @@ static int smtcfb_pci_probe(struct pci_d
+ mmio_base = pci_resource_start(pdev, 0);
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
+
++ smem_size = sm7xx_vram_probe(sfb);
++ dev_info(&pdev->dev, "%lu MiB of VRAM detected.\n",
++ smem_size / 1048576);
++
+ switch (sfb->chip_id) {
+ case 0x710:
+ case 0x712:
+ sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
+ sfb->fb->fix.mmio_len = 0x00400000;
+- smem_size = SM712_VIDEOMEMORYSIZE;
+ sfb->lfb = ioremap(mmio_base, mmio_addr);
+ if (!sfb->lfb) {
+ dev_err(&pdev->dev,
+@@ -1465,8 +1506,7 @@ static int smtcfb_pci_probe(struct pci_d
+ case 0x720:
+ sfb->fb->fix.mmio_start = mmio_base;
+ sfb->fb->fix.mmio_len = 0x00200000;
+- smem_size = SM722_VIDEOMEMORYSIZE;
+- sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
++ sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size);
+ sfb->lfb = sfb->dp_regs + 0x00200000;
+ sfb->mmio = (smtc_regbaseaddress =
+ sfb->dp_regs + 0x000c0000);
--- /dev/null
+From 6053d3a4793e5bde6299ac5388e76a3bf679ff65 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:59 +0200
+Subject: fbdev: sm712fb: fix support for 1024x768-16 mode
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit 6053d3a4793e5bde6299ac5388e76a3bf679ff65 upstream.
+
+In order to support the 1024x600 panel on Yeeloong Loongson MIPS
+laptop, the original 1024x768-16 table was modified to 1024x600-16,
+without leaving the original. It causes problem on x86 laptop as
+the 1024x768-16 support was still claimed but not working.
+
+Fix it by introducing the 1024x768-16 mode.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712fb.c | 59 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -530,6 +530,65 @@ static const struct modeinit vgamode[] =
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
++ { /* 1024 x 768 16Bpp 60Hz */
++ 1024, 768, 16, 60,
++ /* Init_MISC */
++ 0xEB,
++ { /* Init_SR0_SR4 */
++ 0x03, 0x01, 0x0F, 0x03, 0x0E,
++ },
++ { /* Init_SR10_SR24 */
++ 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
++ 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0xC4, 0x30, 0x02, 0x01, 0x01,
++ },
++ { /* Init_SR30_SR75 */
++ 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
++ 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
++ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
++ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
++ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
++ 0x0F, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
++ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
++ 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
++ 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
++ },
++ { /* Init_SR80_SR93 */
++ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
++ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
++ 0x00, 0x00, 0x00, 0x00,
++ },
++ { /* Init_SRA0_SRAF */
++ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
++ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
++ },
++ { /* Init_GR00_GR08 */
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
++ 0xFF,
++ },
++ { /* Init_AR00_AR14 */
++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
++ 0x41, 0x00, 0x0F, 0x00, 0x00,
++ },
++ { /* Init_CR00_CR18 */
++ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
++ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
++ 0xFF,
++ },
++ { /* Init_CR30_CR4D */
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
++ 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
++ 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
++ 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
++ },
++ { /* Init_CR90_CRA7 */
++ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
++ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
++ },
++ },
+ { /* mode#5: 1024 x 768 24Bpp 60Hz */
+ 1024, 768, 24, 60,
+ /* Init_MISC */
--- /dev/null
+From dcf9070595e100942c539e229dde4770aaeaa4e9 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:58 +0200
+Subject: fbdev: sm712fb: fix VRAM detection, don't set SR70/71/74/75
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit dcf9070595e100942c539e229dde4770aaeaa4e9 upstream.
+
+On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), the amount of Video
+RAM is not detected correctly by the xf86-video-siliconmotion driver.
+This is because sm712fb overwrites the GPR71 Scratch Pad Register, which
+is set by BIOS on x86 and used to indicate amount of VRAM.
+
+Other Scratch Pad Registers, including GPR70/74/75, don't have the same
+side-effect, but overwriting to them is still questionable, as they are
+not related to modesetting.
+
+Stop writing to SR70/71/74/75 (a.k.a GPR70/71/74/75).
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712fb.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1146,7 +1146,9 @@ static void sm7xx_set_timing(struct smtc
+ /* init SEQ register SR30 - SR75 */
+ for (i = 0; i < SIZE_SR30_SR75; i++)
+ if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
+- (i + 0x30) != 0x6a && (i + 0x30) != 0x6b)
++ (i + 0x30) != 0x6a && (i + 0x30) != 0x6b &&
++ (i + 0x30) != 0x70 && (i + 0x30) != 0x71 &&
++ (i + 0x30) != 0x74 && (i + 0x30) != 0x75)
+ smtc_seqw(i + 0x30,
+ vgamode[j].init_sr30_sr75[i]);
+
--- /dev/null
+From 8069053880e0ee3a75fd6d7e0a30293265fe3de4 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:58 +0200
+Subject: fbdev: sm712fb: fix white screen of death on reboot, don't set CR3B-CR3F
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit 8069053880e0ee3a75fd6d7e0a30293265fe3de4 upstream.
+
+On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), rebooting with
+sm712fb framebuffer driver would cause a white screen of death on
+the next POST, presumably the proper timings for the LCD panel was
+not reprogrammed properly by the BIOS.
+
+Experiments showed a few CRTC Scratch Registers, including CRT3D,
+CRT3E and CRT3F may be used internally by BIOS as some flags. CRT3B is
+a hardware testing register, we shouldn't mess with it. CRT3C has
+blanking signal and line compare control, which is not needed for this
+driver.
+
+Stop writing to CR3B-CR3F (a.k.a CRT3B-CRT3F) registers. Even if these
+registers don't have side-effect on other systems, writing to them is
+also highly questionable.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712fb.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1173,8 +1173,12 @@ static void sm7xx_set_timing(struct smtc
+ smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
+
+ /* init CRTC register CR30 - CR4D */
+- for (i = 0; i < SIZE_CR30_CR4D; i++)
++ for (i = 0; i < SIZE_CR30_CR4D; i++) {
++ if ((i + 0x30) >= 0x3B && (i + 0x30) <= 0x3F)
++ /* side-effect, don't write to CR3B-CR3F */
++ continue;
+ smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
++ }
+
+ /* init CRTC register CR90 - CRA7 */
+ for (i = 0; i < SIZE_CR90_CRA7; i++)
--- /dev/null
+From 4ed7d2ccb7684510ec5f7a8f7ef534bc6a3d55b2 Mon Sep 17 00:00:00 2001
+From: Yifeng Li <tomli@tomli.me>
+Date: Mon, 1 Apr 2019 17:46:59 +0200
+Subject: fbdev: sm712fb: use 1024x768 by default on non-MIPS, fix garbled display
+
+From: Yifeng Li <tomli@tomli.me>
+
+commit 4ed7d2ccb7684510ec5f7a8f7ef534bc6a3d55b2 upstream.
+
+Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
+target platform of this driver, but nearly all old x86 laptops have
+1024x768. Lighting 768 panels using 600's timings would partially
+garble the display. Since it's not possible to distinguish them reliably,
+we change the default to 768, but keep 600 as-is on MIPS.
+
+Further, earlier laptops, such as IBM Thinkpad 240X, has a 800x600 LCD
+panel, this driver would probably garbled those display. As we don't
+have one for testing, the original behavior of the driver is kept as-is,
+but the problem has been documented is the comments.
+
+Signed-off-by: Yifeng Li <tomli@tomli.me>
+Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Cc: Teddy Wang <teddy.wang@siliconmotion.com>
+Cc: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbdev/sm712.h | 7 +++--
+ drivers/video/fbdev/sm712fb.c | 53 +++++++++++++++++++++++++++++++-----------
+ 2 files changed, 44 insertions(+), 16 deletions(-)
+
+--- a/drivers/video/fbdev/sm712.h
++++ b/drivers/video/fbdev/sm712.h
+@@ -15,9 +15,10 @@
+
+ #define FB_ACCEL_SMI_LYNX 88
+
+-#define SCREEN_X_RES 1024
+-#define SCREEN_Y_RES 600
+-#define SCREEN_BPP 16
++#define SCREEN_X_RES 1024
++#define SCREEN_Y_RES_PC 768
++#define SCREEN_Y_RES_NETBOOK 600
++#define SCREEN_BPP 16
+
+ #define dac_reg (0x3c8)
+ #define dac_val (0x3c9)
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1463,6 +1463,43 @@ static u_long sm7xx_vram_probe(struct sm
+ return 0; /* unknown hardware */
+ }
+
++static void sm7xx_resolution_probe(struct smtcfb_info *sfb)
++{
++ /* get mode parameter from smtc_scr_info */
++ if (smtc_scr_info.lfb_width != 0) {
++ sfb->fb->var.xres = smtc_scr_info.lfb_width;
++ sfb->fb->var.yres = smtc_scr_info.lfb_height;
++ sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
++ goto final;
++ }
++
++ /*
++ * No parameter, default resolution is 1024x768-16.
++ *
++ * FIXME: earlier laptops, such as IBM Thinkpad 240X, has a 800x600
++ * panel, also see the comments about Thinkpad 240X above.
++ */
++ sfb->fb->var.xres = SCREEN_X_RES;
++ sfb->fb->var.yres = SCREEN_Y_RES_PC;
++ sfb->fb->var.bits_per_pixel = SCREEN_BPP;
++
++#ifdef CONFIG_MIPS
++ /*
++ * Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
++ * target platform of this driver, but nearly all old x86 laptops have
++ * 1024x768. Lighting 768 panels using 600's timings would partially
++ * garble the display, so we don't want that. But it's not possible to
++ * distinguish them reliably.
++ *
++ * So we change the default to 768, but keep 600 as-is on MIPS.
++ */
++ sfb->fb->var.yres = SCREEN_Y_RES_NETBOOK;
++#endif
++
++final:
++ big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
++}
++
+ static int smtcfb_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+@@ -1508,19 +1545,6 @@ static int smtcfb_pci_probe(struct pci_d
+
+ sm7xx_init_hw();
+
+- /* get mode parameter from smtc_scr_info */
+- if (smtc_scr_info.lfb_width != 0) {
+- sfb->fb->var.xres = smtc_scr_info.lfb_width;
+- sfb->fb->var.yres = smtc_scr_info.lfb_height;
+- sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
+- } else {
+- /* default resolution 1024x600 16bit mode */
+- sfb->fb->var.xres = SCREEN_X_RES;
+- sfb->fb->var.yres = SCREEN_Y_RES;
+- sfb->fb->var.bits_per_pixel = SCREEN_BPP;
+- }
+-
+- big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
+ /* Map address and memory detection */
+ mmio_base = pci_resource_start(pdev, 0);
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
+@@ -1582,6 +1606,9 @@ static int smtcfb_pci_probe(struct pci_d
+ goto failed_fb;
+ }
+
++ /* probe and decide resolution */
++ sm7xx_resolution_probe(sfb);
++
+ /* can support 32 bpp */
+ if (sfb->fb->var.bits_per_pixel == 15)
+ sfb->fb->var.bits_per_pixel = 16;
--- /dev/null
+From b906c056b6023c390f18347169071193fda57dde Mon Sep 17 00:00:00 2001
+From: Dmitry Osipenko <digetx@gmail.com>
+Date: Fri, 12 Apr 2019 01:12:48 +0300
+Subject: memory: tegra: Fix integer overflow on tick value calculation
+
+From: Dmitry Osipenko <digetx@gmail.com>
+
+commit b906c056b6023c390f18347169071193fda57dde upstream.
+
+Multiplying the Memory Controller clock rate by the tick count results
+in an integer overflow and in result the truncated tick value is being
+programmed into hardware, such that the GR3D memory client performance is
+reduced by two times.
+
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/memory/tegra/mc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/memory/tegra/mc.c
++++ b/drivers/memory/tegra/mc.c
+@@ -280,7 +280,7 @@ static int tegra_mc_setup_latency_allowa
+ u32 value;
+
+ /* compute the number of MC clock cycles per tick */
+- tick = mc->tick * clk_get_rate(mc->clk);
++ tick = (unsigned long long)mc->tick * clk_get_rate(mc->clk);
+ do_div(tick, NSEC_PER_SEC);
+
+ value = readl(mc->regs + MC_EMEM_ARB_CFG);
--- /dev/null
+From 1b1f01b653b408ebe58fec78c566d1075d285c64 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <f.fainelli@gmail.com>
+Date: Thu, 9 May 2019 11:30:47 -0700
+Subject: MIPS: perf: Fix build with CONFIG_CPU_BMIPS5000 enabled
+
+From: Florian Fainelli <f.fainelli@gmail.com>
+
+commit 1b1f01b653b408ebe58fec78c566d1075d285c64 upstream.
+
+arch/mips/kernel/perf_event_mipsxx.c: In function 'mipsxx_pmu_enable_event':
+arch/mips/kernel/perf_event_mipsxx.c:326:21: error: unused variable 'event' [-Werror=unused-variable]
+ struct perf_event *event = container_of(evt, struct perf_event, hw);
+ ^~~~~
+
+Fix this by making use of IS_ENABLED() to simplify the code and avoid
+unnecessary ifdefery.
+
+Fixes: 84002c88599d ("MIPS: perf: Fix perf with MT counting other threads")
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Paul Burton <paul.burton@mips.com>
+Cc: linux-mips@linux-mips.org
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Ralf Baechle <ralf@linux-mips.org>
+Cc: James Hogan <jhogan@kernel.org>
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-mips@vger.kernel.org
+Cc: stable@vger.kernel.org # v4.18+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/mips/kernel/perf_event_mipsxx.c | 21 +++------------------
+ 1 file changed, 3 insertions(+), 18 deletions(-)
+
+--- a/arch/mips/kernel/perf_event_mipsxx.c
++++ b/arch/mips/kernel/perf_event_mipsxx.c
+@@ -64,17 +64,11 @@ struct mips_perf_event {
+ #define CNTR_EVEN 0x55555555
+ #define CNTR_ODD 0xaaaaaaaa
+ #define CNTR_ALL 0xffffffff
+-#ifdef CONFIG_MIPS_MT_SMP
+ enum {
+ T = 0,
+ V = 1,
+ P = 2,
+ } range;
+-#else
+- #define T
+- #define V
+- #define P
+-#endif
+ };
+
+ static struct mips_perf_event raw_event;
+@@ -325,9 +319,7 @@ static void mipsxx_pmu_enable_event(stru
+ {
+ struct perf_event *event = container_of(evt, struct perf_event, hw);
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+-#ifdef CONFIG_MIPS_MT_SMP
+ unsigned int range = evt->event_base >> 24;
+-#endif /* CONFIG_MIPS_MT_SMP */
+
+ WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+@@ -336,21 +328,15 @@ static void mipsxx_pmu_enable_event(stru
+ /* Make sure interrupt enabled. */
+ MIPS_PERFCTRL_IE;
+
+-#ifdef CONFIG_CPU_BMIPS5000
+- {
++ if (IS_ENABLED(CONFIG_CPU_BMIPS5000)) {
+ /* enable the counter for the calling thread */
+ cpuc->saved_ctrl[idx] |=
+ (1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC;
+- }
+-#else
+-#ifdef CONFIG_MIPS_MT_SMP
+- if (range > V) {
++ } else if (IS_ENABLED(CONFIG_MIPS_MT_SMP) && range > V) {
+ /* The counter is processor wide. Set it up to count all TCs. */
+ pr_debug("Enabling perf counter for all TCs\n");
+ cpuc->saved_ctrl[idx] |= M_TC_EN_ALL;
+- } else
+-#endif /* CONFIG_MIPS_MT_SMP */
+- {
++ } else {
+ unsigned int cpu, ctrl;
+
+ /*
+@@ -365,7 +351,6 @@ static void mipsxx_pmu_enable_event(stru
+ cpuc->saved_ctrl[idx] |= ctrl;
+ pr_debug("Enabling perf counter for CPU%d\n", cpu);
+ }
+-#endif /* CONFIG_CPU_BMIPS5000 */
+ /*
+ * We do not actually let the counter run. Leave it until start().
+ */
--- /dev/null
+From 8ea58f1e8b11cca3087b294779bf5959bf89cc10 Mon Sep 17 00:00:00 2001
+From: Nathan Chancellor <natechancellor@gmail.com>
+Date: Thu, 16 May 2019 12:49:42 -0500
+Subject: objtool: Allow AR to be overridden with HOSTAR
+
+From: Nathan Chancellor <natechancellor@gmail.com>
+
+commit 8ea58f1e8b11cca3087b294779bf5959bf89cc10 upstream.
+
+Currently, this Makefile hardcodes GNU ar, meaning that if it is not
+available, there is no way to supply a different one and the build will
+fail.
+
+ $ make AR=llvm-ar CC=clang LD=ld.lld HOSTAR=llvm-ar HOSTCC=clang \
+ HOSTLD=ld.lld HOSTLDFLAGS=-fuse-ld=lld defconfig modules_prepare
+ ...
+ AR /out/tools/objtool/libsubcmd.a
+ /bin/sh: 1: ar: not found
+ ...
+
+Follow the logic of HOST{CC,LD} and allow the user to specify a
+different ar tool via HOSTAR (which is used elsewhere in other
+tools/ Makefiles).
+
+Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
+Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Mukesh Ojha <mojha@codeaurora.org>
+Cc: <stable@vger.kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/80822a9353926c38fd7a152991c6292491a9d0e8.1558028966.git.jpoimboe@redhat.com
+Link: https://github.com/ClangBuiltLinux/linux/issues/481
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/objtool/Makefile | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/tools/objtool/Makefile
++++ b/tools/objtool/Makefile
+@@ -7,11 +7,12 @@ ARCH := x86
+ endif
+
+ # always use the host compiler
++HOSTAR ?= ar
+ HOSTCC ?= gcc
+ HOSTLD ?= ld
++AR = $(HOSTAR)
+ CC = $(HOSTCC)
+ LD = $(HOSTLD)
+-AR = ar
+
+ ifeq ($(srctree),)
+ srctree := $(patsubst %/,%,$(dir $(CURDIR)))
--- /dev/null
+From 31f996efbd5a7825f4d30150469e9d110aea00e8 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Date: Fri, 12 Apr 2019 06:43:06 +0000
+Subject: PCI/AER: Change pci_aer_init() stub to return void
+
+From: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+
+commit 31f996efbd5a7825f4d30150469e9d110aea00e8 upstream.
+
+Commit 60ed982a4e78 ("PCI/AER: Move internal declarations to
+drivers/pci/pci.h") changed pci_aer_init() to return "void", but didn't
+change the stub for when CONFIG_PCIEAER isn't enabled. Change the stub to
+match.
+
+Fixes: 60ed982a4e78 ("PCI/AER: Move internal declarations to drivers/pci/pci.h")
+Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+CC: stable@vger.kernel.org # v4.19+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -596,7 +596,7 @@ void pci_aer_clear_fatal_status(struct p
+ void pci_aer_clear_device_status(struct pci_dev *dev);
+ #else
+ static inline void pci_no_aer(void) { }
+-static inline int pci_aer_init(struct pci_dev *d) { return -ENODEV; }
++static inline void pci_aer_init(struct pci_dev *d) { }
+ static inline void pci_aer_exit(struct pci_dev *d) { }
+ static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
+ static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
--- /dev/null
+From 86fa6a344209d9414ea962b1f1ac6ade9dd7563a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20M=C3=A4tje?= <stefan.maetje@esd.eu>
+Date: Fri, 29 Mar 2019 18:07:34 +0100
+Subject: PCI: Factor out pcie_retrain_link() function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stefan Mätje <stefan.maetje@esd.eu>
+
+commit 86fa6a344209d9414ea962b1f1ac6ade9dd7563a upstream.
+
+Factor out pcie_retrain_link() to use for Pericom Retrain Link quirk. No
+functional change intended.
+
+Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+CC: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pcie/aspm.c | 40 ++++++++++++++++++++++++----------------
+ 1 file changed, 24 insertions(+), 16 deletions(-)
+
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -196,6 +196,29 @@ static void pcie_clkpm_cap_init(struct p
+ link->clkpm_capable = (blacklist) ? 0 : capable;
+ }
+
++static bool pcie_retrain_link(struct pcie_link_state *link)
++{
++ struct pci_dev *parent = link->pdev;
++ unsigned long start_jiffies;
++ u16 reg16;
++
++ pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16);
++ reg16 |= PCI_EXP_LNKCTL_RL;
++ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
++
++ /* Wait for link training end. Break out after waiting for timeout */
++ start_jiffies = jiffies;
++ for (;;) {
++ pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16);
++ if (!(reg16 & PCI_EXP_LNKSTA_LT))
++ break;
++ if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
++ break;
++ msleep(1);
++ }
++ return !(reg16 & PCI_EXP_LNKSTA_LT);
++}
++
+ /*
+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
+ * could use common clock. If they are, configure them to use the
+@@ -205,7 +228,6 @@ static void pcie_aspm_configure_common_c
+ {
+ int same_clock = 1;
+ u16 reg16, parent_reg, child_reg[8];
+- unsigned long start_jiffies;
+ struct pci_dev *child, *parent = link->pdev;
+ struct pci_bus *linkbus = parent->subordinate;
+ /*
+@@ -263,21 +285,7 @@ static void pcie_aspm_configure_common_c
+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
+ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
+
+- /* Retrain link */
+- reg16 |= PCI_EXP_LNKCTL_RL;
+- pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
+-
+- /* Wait for link training end. Break out after waiting for timeout */
+- start_jiffies = jiffies;
+- for (;;) {
+- pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16);
+- if (!(reg16 & PCI_EXP_LNKSTA_LT))
+- break;
+- if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
+- break;
+- msleep(1);
+- }
+- if (!(reg16 & PCI_EXP_LNKSTA_LT))
++ if (pcie_retrain_link(link))
+ return;
+
+ /* Training failed. Restore common clock configurations */
--- /dev/null
+From 6302bf3ef78dd210b5ff4a922afcb7d8eff8a211 Mon Sep 17 00:00:00 2001
+From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+Date: Mon, 18 Mar 2019 16:07:18 +0000
+Subject: PCI: Init PCIe feature bits for managed host bridge alloc
+
+From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+
+commit 6302bf3ef78dd210b5ff4a922afcb7d8eff8a211 upstream.
+
+Two functions allocate a host bridge: devm_pci_alloc_host_bridge() and
+pci_alloc_host_bridge(). At the moment, only the unmanaged one initializes
+the PCIe feature bits, which prevents from using features such as hotplug
+or AER on some systems, when booting with device tree. Make the
+initialization code common.
+
+Fixes: 02bfeb484230 ("PCI/portdrv: Simplify PCIe feature permission checking")
+Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+CC: stable@vger.kernel.org # v4.17+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/probe.c | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -535,16 +535,9 @@ static void pci_release_host_bridge_dev(
+ kfree(to_pci_host_bridge(dev));
+ }
+
+-struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
++static void pci_init_host_bridge(struct pci_host_bridge *bridge)
+ {
+- struct pci_host_bridge *bridge;
+-
+- bridge = kzalloc(sizeof(*bridge) + priv, GFP_KERNEL);
+- if (!bridge)
+- return NULL;
+-
+ INIT_LIST_HEAD(&bridge->windows);
+- bridge->dev.release = pci_release_host_bridge_dev;
+
+ /*
+ * We assume we can manage these PCIe features. Some systems may
+@@ -557,6 +550,18 @@ struct pci_host_bridge *pci_alloc_host_b
+ bridge->native_shpc_hotplug = 1;
+ bridge->native_pme = 1;
+ bridge->native_ltr = 1;
++}
++
++struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
++{
++ struct pci_host_bridge *bridge;
++
++ bridge = kzalloc(sizeof(*bridge) + priv, GFP_KERNEL);
++ if (!bridge)
++ return NULL;
++
++ pci_init_host_bridge(bridge);
++ bridge->dev.release = pci_release_host_bridge_dev;
+
+ return bridge;
+ }
+@@ -571,7 +576,7 @@ struct pci_host_bridge *devm_pci_alloc_h
+ if (!bridge)
+ return NULL;
+
+- INIT_LIST_HEAD(&bridge->windows);
++ pci_init_host_bridge(bridge);
+ bridge->dev.release = devm_pci_release_host_bridge_dev;
+
+ return bridge;
--- /dev/null
+From d28ca864c493637f3c957f4ed9348a94fca6de60 Mon Sep 17 00:00:00 2001
+From: Nikolai Kostrigin <nickel@altlinux.org>
+Date: Mon, 8 Apr 2019 13:37:25 +0300
+Subject: PCI: Mark AMD Stoney Radeon R7 GPU ATS as broken
+
+From: Nikolai Kostrigin <nickel@altlinux.org>
+
+commit d28ca864c493637f3c957f4ed9348a94fca6de60 upstream.
+
+ATS is broken on the Radeon R7 GPU (at least for Stoney Ridge based laptop)
+and causes IOMMU stalls and system failure. Disable ATS on these devices
+to make them usable again with IOMMU enabled.
+
+Thanks to Joerg Roedel <jroedel@suse.de> for help.
+
+[bhelgaas: In the email thread mentioned below, Alex suspects the real
+problem is in sbios or iommu, so it may affect only certain systems, and it
+may affect other devices in those systems as well. However, per Joerg we
+lack the ability to debug further, so this quirk is the best we can do for
+now.]
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=194521
+Link: https://lore.kernel.org/lkml/20190408103725.30426-1-nickel@altlinux.org
+Fixes: 9b44b0b09dec ("PCI: Mark AMD Stoney GPU ATS as broken")
+Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+CC: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -4903,6 +4903,7 @@ static void quirk_no_ats(struct pci_dev
+
+ /* AMD Stoney platform GPU */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_no_ats);
+ #endif /* CONFIG_PCI_ATS */
+
+ /* Freescale PCIe doesn't support MSI in RC mode */
--- /dev/null
+From 6afb7e26978da5e86e57e540fdce65c8b04f398a Mon Sep 17 00:00:00 2001
+From: James Prestwood <james.prestwood@linux.intel.com>
+Date: Mon, 7 Jan 2019 13:32:48 -0800
+Subject: PCI: Mark Atheros AR9462 to avoid bus reset
+
+From: James Prestwood <james.prestwood@linux.intel.com>
+
+commit 6afb7e26978da5e86e57e540fdce65c8b04f398a upstream.
+
+When using PCI passthrough with this device, the host machine locks up
+completely when starting the VM, requiring a hard reboot. Add a quirk to
+avoid bus resets on this device.
+
+Fixes: c3e59ee4e766 ("PCI: Mark Atheros AR93xx to avoid bus reset")
+Link: https://lore.kernel.org/linux-pci/20190107213248.3034-1-james.prestwood@linux.intel.com
+Signed-off-by: James Prestwood <james.prestwood@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+CC: stable@vger.kernel.org # v3.14+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -3408,6 +3408,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_A
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
+
+ /*
+ * Root port on some Cavium CN8xxx chips do not successfully complete a bus
--- /dev/null
+From be20bbcb0a8cb5597cc62b3e28d275919f3431df Mon Sep 17 00:00:00 2001
+From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
+Date: Mon, 25 Mar 2019 20:43:19 +0100
+Subject: PCI: rcar: Add the initialization of PCIe link in resume_noirq()
+
+From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
+
+commit be20bbcb0a8cb5597cc62b3e28d275919f3431df upstream.
+
+Reestablish the PCIe link very early in the resume process in case it
+went down to prevent PCI accesses from hanging the bus. Such accesses
+can happen early in the PCI resume process, as early as the
+SUSPEND_RESUME_NOIRQ step, thus the link must be reestablished in the
+driver resume_noirq() callback.
+
+Fixes: e015f88c368d ("PCI: rcar: Add support for R-Car H3 to pcie-rcar")
+Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
+Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
+Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
+[lorenzo.pieralisi@arm.com: reformatted commit log]
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Cc: stable@vger.kernel.org
+Cc: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Phil Edworthy <phil.edworthy@renesas.com>
+Cc: Simon Horman <horms+renesas@verge.net.au>
+Cc: Wolfram Sang <wsa@the-dreams.de>
+Cc: linux-renesas-soc@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/controller/pcie-rcar.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/pci/controller/pcie-rcar.c
++++ b/drivers/pci/controller/pcie-rcar.c
+@@ -46,6 +46,7 @@
+
+ /* Transfer control */
+ #define PCIETCTLR 0x02000
++#define DL_DOWN BIT(3)
+ #define CFINIT 1
+ #define PCIETSTR 0x02004
+ #define DATA_LINK_ACTIVE 1
+@@ -94,6 +95,7 @@
+ #define MACCTLR 0x011058
+ #define SPEED_CHANGE BIT(24)
+ #define SCRAMBLE_DISABLE BIT(27)
++#define PMSR 0x01105c
+ #define MACS2R 0x011078
+ #define MACCGSPSETR 0x011084
+ #define SPCNGRSN BIT(31)
+@@ -1130,6 +1132,7 @@ static int rcar_pcie_probe(struct platfo
+ pcie = pci_host_bridge_priv(bridge);
+
+ pcie->dev = dev;
++ platform_set_drvdata(pdev, pcie);
+
+ err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);
+ if (err)
+@@ -1221,10 +1224,28 @@ err_free_bridge:
+ return err;
+ }
+
++static int rcar_pcie_resume_noirq(struct device *dev)
++{
++ struct rcar_pcie *pcie = dev_get_drvdata(dev);
++
++ if (rcar_pci_read_reg(pcie, PMSR) &&
++ !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
++ return 0;
++
++ /* Re-establish the PCIe link */
++ rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
++ return rcar_pcie_wait_for_dl(pcie);
++}
++
++static const struct dev_pm_ops rcar_pcie_pm_ops = {
++ .resume_noirq = rcar_pcie_resume_noirq,
++};
++
+ static struct platform_driver rcar_pcie_driver = {
+ .driver = {
+ .name = "rcar-pcie",
+ .of_match_table = rcar_pcie_of_match,
++ .pm = &rcar_pcie_pm_ops,
+ .suppress_bind_attrs = true,
+ },
+ .probe = rcar_pcie_probe,
--- /dev/null
+From e0547c81bfcfad01cbbfa93a5e66bb98ab932f80 Mon Sep 17 00:00:00 2001
+From: Lyude Paul <lyude@redhat.com>
+Date: Tue, 12 Feb 2019 17:02:30 -0500
+Subject: PCI: Reset Lenovo ThinkPad P50 nvgpu at boot if necessary
+
+From: Lyude Paul <lyude@redhat.com>
+
+commit e0547c81bfcfad01cbbfa93a5e66bb98ab932f80 upstream.
+
+On ThinkPad P50 SKUs with an Nvidia Quadro M1000M instead of the M2000M
+variant, the BIOS does not always reset the secondary Nvidia GPU during
+reboot if the laptop is configured in Hybrid Graphics mode. The reason is
+unknown, but the following steps and possibly a good bit of patience will
+reproduce the issue:
+
+ 1. Boot up the laptop normally in Hybrid Graphics mode
+ 2. Make sure nouveau is loaded and that the GPU is awake
+ 3. Allow the Nvidia GPU to runtime suspend itself after being idle
+ 4. Reboot the machine, the more sudden the better (e.g. sysrq-b may help)
+ 5. If nouveau loads up properly, reboot the machine again and go back to
+ step 2 until you reproduce the issue
+
+This results in some very strange behavior: the GPU will be left in exactly
+the same state it was in when the previously booted kernel started the
+reboot. This has all sorts of bad side effects: for starters, this
+completely breaks nouveau starting with a mysterious EVO channel failure
+that happens well before we've actually used the EVO channel for anything:
+
+ nouveau 0000:01:00.0: disp: chid 0 mthd 0000 data 00000400 00001000 00000002
+
+This causes a timeout trying to bring up the GR ctx:
+
+ nouveau 0000:01:00.0: timeout
+ WARNING: CPU: 0 PID: 12 at drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c:1547 gf100_grctx_generate+0x7b2/0x850 [nouveau]
+ Hardware name: LENOVO 20EQS64N0B/20EQS64N0B, BIOS N1EET82W (1.55 ) 12/18/2018
+ Workqueue: events_long drm_dp_mst_link_probe_work [drm_kms_helper]
+ ...
+ nouveau 0000:01:00.0: gr: wait for idle timeout (en: 1, ctxsw: 0, busy: 1)
+ nouveau 0000:01:00.0: gr: wait for idle timeout (en: 1, ctxsw: 0, busy: 1)
+ nouveau 0000:01:00.0: fifo: fault 01 [WRITE] at 0000000000008000 engine 00 [GR] client 15 [HUB/SCC_NB] reason c4 [] on channel -1 [0000000000 unknown]
+
+The GPU never manages to recover. Booting without loading nouveau causes
+issues as well, since the GPU starts sending spurious interrupts that cause
+other device's IRQs to get disabled by the kernel:
+
+ irq 16: nobody cared (try booting with the "irqpoll" option)
+ ...
+ handlers:
+ [<000000007faa9e99>] i801_isr [i2c_i801]
+ Disabling IRQ #16
+ ...
+ serio: RMI4 PS/2 pass-through port at rmi4-00.fn03
+ i801_smbus 0000:00:1f.4: Timeout waiting for interrupt!
+ i801_smbus 0000:00:1f.4: Transaction timeout
+ rmi4_f03 rmi4-00.fn03: rmi_f03_pt_write: Failed to write to F03 TX register (-110).
+ i801_smbus 0000:00:1f.4: Timeout waiting for interrupt!
+ i801_smbus 0000:00:1f.4: Transaction timeout
+ rmi4_physical rmi4-00: rmi_driver_set_irq_bits: Failed to change enabled interrupts!
+
+This causes the touchpad and sometimes other things to get disabled.
+
+Since this happens without nouveau, we can't fix this problem from nouveau
+itself.
+
+Add a PCI quirk for the specific P50 variant of this GPU. Make sure the
+GPU is advertising NoReset- so we don't reset the GPU when the machine is
+in Dedicated graphics mode (where the GPU being initialized by the BIOS is
+normal and expected). Map the GPU MMIO space and read the magic 0x2240c
+register, which will have bit 1 set if the device was POSTed during a
+previous boot. Once we've confirmed all of this, reset the GPU and
+re-disable it - bringing it back to a healthy state.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=203003
+Link: https://lore.kernel.org/lkml/20190212220230.1568-1-lyude@redhat.com
+Signed-off-by: Lyude Paul <lyude@redhat.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: nouveau@lists.freedesktop.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: Karol Herbst <kherbst@redhat.com>
+Cc: Ben Skeggs <skeggsb@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/quirks.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 58 insertions(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -5122,3 +5122,61 @@ SWITCHTEC_QUIRK(0x8573); /* PFXI 48XG3
+ SWITCHTEC_QUIRK(0x8574); /* PFXI 64XG3 */
+ SWITCHTEC_QUIRK(0x8575); /* PFXI 80XG3 */
+ SWITCHTEC_QUIRK(0x8576); /* PFXI 96XG3 */
++
++/*
++ * On Lenovo Thinkpad P50 SKUs with a Nvidia Quadro M1000M, the BIOS does
++ * not always reset the secondary Nvidia GPU between reboots if the system
++ * is configured to use Hybrid Graphics mode. This results in the GPU
++ * being left in whatever state it was in during the *previous* boot, which
++ * causes spurious interrupts from the GPU, which in turn causes us to
++ * disable the wrong IRQ and end up breaking the touchpad. Unsurprisingly,
++ * this also completely breaks nouveau.
++ *
++ * Luckily, it seems a simple reset of the Nvidia GPU brings it back to a
++ * clean state and fixes all these issues.
++ *
++ * When the machine is configured in Dedicated display mode, the issue
++ * doesn't occur. Fortunately the GPU advertises NoReset+ when in this
++ * mode, so we can detect that and avoid resetting it.
++ */
++static void quirk_reset_lenovo_thinkpad_p50_nvgpu(struct pci_dev *pdev)
++{
++ void __iomem *map;
++ int ret;
++
++ if (pdev->subsystem_vendor != PCI_VENDOR_ID_LENOVO ||
++ pdev->subsystem_device != 0x222e ||
++ !pdev->reset_fn)
++ return;
++
++ if (pci_enable_device_mem(pdev))
++ return;
++
++ /*
++ * Based on nvkm_device_ctor() in
++ * drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
++ */
++ map = pci_iomap(pdev, 0, 0x23000);
++ if (!map) {
++ pci_err(pdev, "Can't map MMIO space\n");
++ goto out_disable;
++ }
++
++ /*
++ * Make sure the GPU looks like it's been POSTed before resetting
++ * it.
++ */
++ if (ioread32(map + 0x2240c) & 0x2) {
++ pci_info(pdev, FW_BUG "GPU left initialized by EFI, resetting\n");
++ ret = pci_reset_function(pdev);
++ if (ret < 0)
++ pci_err(pdev, "Failed to reset GPU: %d\n", ret);
++ }
++
++ iounmap(map);
++out_disable:
++ pci_disable_device(pdev);
++}
++DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, 0x13b1,
++ PCI_CLASS_DISPLAY_VGA, 8,
++ quirk_reset_lenovo_thinkpad_p50_nvgpu);
--- /dev/null
+From 4ec73791a64bab25cabf16a6067ee478692e506d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20M=C3=A4tje?= <stefan.maetje@esd.eu>
+Date: Fri, 29 Mar 2019 18:07:35 +0100
+Subject: PCI: Work around Pericom PCIe-to-PCI bridge Retrain Link erratum
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stefan Mätje <stefan.maetje@esd.eu>
+
+commit 4ec73791a64bab25cabf16a6067ee478692e506d upstream.
+
+Due to an erratum in some Pericom PCIe-to-PCI bridges in reverse mode
+(conventional PCI on primary side, PCIe on downstream side), the Retrain
+Link bit needs to be cleared manually to allow the link training to
+complete successfully.
+
+If it is not cleared manually, the link training is continuously restarted
+and no devices below the PCI-to-PCIe bridge can be accessed. That means
+drivers for devices below the bridge will be loaded but won't work and may
+even crash because the driver is only reading 0xffff.
+
+See the Pericom Errata Sheet PI7C9X111SLB_errata_rev1.2_102711.pdf for
+details. Devices known as affected so far are: PI7C9X110, PI7C9X111SL,
+PI7C9X130.
+
+Add a new flag, clear_retrain_link, in struct pci_dev. Quirks for affected
+devices set this bit.
+
+Note that pcie_retrain_link() lives in aspm.c because that's currently the
+only place we use it, but this erratum is not specific to ASPM, and we may
+retrain links for other reasons in the future.
+
+Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu>
+[bhelgaas: apply regardless of CONFIG_PCIEASPM]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+CC: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pcie/aspm.c | 9 +++++++++
+ drivers/pci/quirks.c | 17 +++++++++++++++++
+ include/linux/pci.h | 2 ++
+ 3 files changed, 28 insertions(+)
+
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -205,6 +205,15 @@ static bool pcie_retrain_link(struct pci
+ pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16);
+ reg16 |= PCI_EXP_LNKCTL_RL;
+ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
++ if (parent->clear_retrain_link) {
++ /*
++ * Due to an erratum in some devices the Retrain Link bit
++ * needs to be cleared again manually to allow the link
++ * training to succeed.
++ */
++ reg16 &= ~PCI_EXP_LNKCTL_RL;
++ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
++ }
+
+ /* Wait for link training end. Break out after waiting for timeout */
+ start_jiffies = jiffies;
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2245,6 +2245,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
+
++/*
++ * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
++ * Link bit cleared after starting the link retrain process to allow this
++ * process to finish.
++ *
++ * Affected devices: PI7C9X110, PI7C9X111SL, PI7C9X130. See also the
++ * Pericom Errata Sheet PI7C9X111SLB_errata_rev1.2_102711.pdf.
++ */
++static void quirk_enable_clear_retrain_link(struct pci_dev *dev)
++{
++ dev->clear_retrain_link = 1;
++ pci_info(dev, "Enable PCIe Retrain Link quirk\n");
++}
++DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe110, quirk_enable_clear_retrain_link);
++DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe111, quirk_enable_clear_retrain_link);
++DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe130, quirk_enable_clear_retrain_link);
++
+ static void fixup_rev1_53c810(struct pci_dev *dev)
+ {
+ u32 class = dev->class;
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -348,6 +348,8 @@ struct pci_dev {
+ unsigned int hotplug_user_indicators:1; /* SlotCtl indicators
+ controlled exclusively by
+ user sysfs */
++ unsigned int clear_retrain_link:1; /* Need to clear Retrain Link
++ bit manually */
+ unsigned int d3_delay; /* D3->D0 transition time in ms */
+ unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */
+
--- /dev/null
+From 61b6e08dc8e3ea80b7485c9b3f875ddd45c8466b Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Fri, 10 May 2019 15:41:42 +0300
+Subject: perf intel-pt: Fix improved sample timestamp
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit 61b6e08dc8e3ea80b7485c9b3f875ddd45c8466b upstream.
+
+The decoder uses its current timestamp in samples. Usually that is a
+timestamp that has already passed, but in some cases it is a timestamp
+for a branch that the decoder is walking towards, and consequently
+hasn't reached.
+
+The intel_pt_sample_time() function decides which is which, but was not
+handling TNT packets exactly correctly.
+
+In the case of TNT, the timestamp applies to the first branch, so the
+decoder must first walk to that branch.
+
+That means intel_pt_sample_time() should return true for TNT, and this
+patch makes that change. However, if the first branch is a non-taken
+branch (i.e. a 'N'), then intel_pt_sample_time() needs to return false
+for subsequent taken branches in the same TNT packet.
+
+To handle that, introduce a new state INTEL_PT_STATE_TNT_CONT to
+distinguish the cases.
+
+Note that commit 3f04d98e972b5 ("perf intel-pt: Improve sample
+timestamp") was also a stable fix and appears, for example, in v4.4
+stable tree as commit a4ebb58fd124 ("perf intel-pt: Improve sample
+timestamp").
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: stable@vger.kernel.org # v4.4+
+Fixes: 3f04d98e972b5 ("perf intel-pt: Improve sample timestamp")
+Link: http://lkml.kernel.org/r/20190510124143.27054-3-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -58,6 +58,7 @@ enum intel_pt_pkt_state {
+ INTEL_PT_STATE_NO_IP,
+ INTEL_PT_STATE_ERR_RESYNC,
+ INTEL_PT_STATE_IN_SYNC,
++ INTEL_PT_STATE_TNT_CONT,
+ INTEL_PT_STATE_TNT,
+ INTEL_PT_STATE_TIP,
+ INTEL_PT_STATE_TIP_PGD,
+@@ -72,8 +73,9 @@ static inline bool intel_pt_sample_time(
+ case INTEL_PT_STATE_NO_IP:
+ case INTEL_PT_STATE_ERR_RESYNC:
+ case INTEL_PT_STATE_IN_SYNC:
+- case INTEL_PT_STATE_TNT:
++ case INTEL_PT_STATE_TNT_CONT:
+ return true;
++ case INTEL_PT_STATE_TNT:
+ case INTEL_PT_STATE_TIP:
+ case INTEL_PT_STATE_TIP_PGD:
+ case INTEL_PT_STATE_FUP:
+@@ -1261,7 +1263,9 @@ static int intel_pt_walk_tnt(struct inte
+ return -ENOENT;
+ }
+ decoder->tnt.count -= 1;
+- if (!decoder->tnt.count)
++ if (decoder->tnt.count)
++ decoder->pkt_state = INTEL_PT_STATE_TNT_CONT;
++ else
+ decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+ decoder->tnt.payload <<= 1;
+ decoder->state.from_ip = decoder->ip;
+@@ -1292,7 +1296,9 @@ static int intel_pt_walk_tnt(struct inte
+
+ if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
+ decoder->tnt.count -= 1;
+- if (!decoder->tnt.count)
++ if (decoder->tnt.count)
++ decoder->pkt_state = INTEL_PT_STATE_TNT_CONT;
++ else
+ decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+ if (decoder->tnt.payload & BIT63) {
+ decoder->tnt.payload <<= 1;
+@@ -2372,6 +2378,7 @@ const struct intel_pt_state *intel_pt_de
+ err = intel_pt_walk_trace(decoder);
+ break;
+ case INTEL_PT_STATE_TNT:
++ case INTEL_PT_STATE_TNT_CONT:
+ err = intel_pt_walk_tnt(decoder);
+ if (err == -EAGAIN)
+ err = intel_pt_walk_trace(decoder);
--- /dev/null
+From 7ba8fa20e26eb3c0c04d747f7fd2223694eac4d5 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Fri, 10 May 2019 15:41:41 +0300
+Subject: perf intel-pt: Fix instructions sampling rate
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit 7ba8fa20e26eb3c0c04d747f7fd2223694eac4d5 upstream.
+
+The timestamp used to determine if an instruction sample is made, is an
+estimate based on the number of instructions since the last known
+timestamp. A consequence is that it might go backwards, which results in
+extra samples. Change it so that a sample is only made when the
+timestamp goes forwards.
+
+Note this does not affect a sampling period of 0 or sampling periods
+specified as a count of instructions.
+
+Example:
+
+ Before:
+
+ $ perf script --itrace=i10us
+ ls 13812 [003] 2167315.222583: 3270 instructions:u: 7fac71e2e494 __GI___tunables_init+0xf4 (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 30902 instructions:u: 7fac71e2da0f _dl_cache_libcmp+0x2f (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 10 instructions:u: 7fac71e2d9ff _dl_cache_libcmp+0x1f (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 8 instructions:u: 7fac71e2d9ea _dl_cache_libcmp+0xa (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 14 instructions:u: 7fac71e2d9ea _dl_cache_libcmp+0xa (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 6 instructions:u: 7fac71e2d9ff _dl_cache_libcmp+0x1f (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 14 instructions:u: 7fac71e2d9ff _dl_cache_libcmp+0x1f (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 4 instructions:u: 7fac71e2dab2 _dl_cache_libcmp+0xd2 (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222728: 16423 instructions:u: 7fac71e2477a _dl_map_object_deps+0x1ba (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222734: 12731 instructions:u: 7fac71e27938 _dl_name_match_p+0x68 (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ...
+
+ After:
+ $ perf script --itrace=i10us
+ ls 13812 [003] 2167315.222583: 3270 instructions:u: 7fac71e2e494 __GI___tunables_init+0xf4 (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222667: 30902 instructions:u: 7fac71e2da0f _dl_cache_libcmp+0x2f (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ls 13812 [003] 2167315.222728: 16479 instructions:u: 7fac71e2477a _dl_map_object_deps+0x1ba (/lib/x86_64-linux-gnu/ld-2.28.so)
+ ...
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: stable@vger.kernel.org
+Fixes: f4aa081949e7b ("perf tools: Add Intel PT decoder")
+Link: http://lkml.kernel.org/r/20190510124143.27054-2-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -888,16 +888,20 @@ static uint64_t intel_pt_next_period(str
+ timestamp = decoder->timestamp + decoder->timestamp_insn_cnt;
+ masked_timestamp = timestamp & decoder->period_mask;
+ if (decoder->continuous_period) {
+- if (masked_timestamp != decoder->last_masked_timestamp)
++ if (masked_timestamp > decoder->last_masked_timestamp)
+ return 1;
+ } else {
+ timestamp += 1;
+ masked_timestamp = timestamp & decoder->period_mask;
+- if (masked_timestamp != decoder->last_masked_timestamp) {
++ if (masked_timestamp > decoder->last_masked_timestamp) {
+ decoder->last_masked_timestamp = masked_timestamp;
+ decoder->continuous_period = true;
+ }
+ }
++
++ if (masked_timestamp < decoder->last_masked_timestamp)
++ return decoder->period_ticks;
++
+ return decoder->period_ticks - (timestamp - masked_timestamp);
+ }
+
+@@ -926,7 +930,10 @@ static void intel_pt_sample_insn(struct
+ case INTEL_PT_PERIOD_TICKS:
+ timestamp = decoder->timestamp + decoder->timestamp_insn_cnt;
+ masked_timestamp = timestamp & decoder->period_mask;
+- decoder->last_masked_timestamp = masked_timestamp;
++ if (masked_timestamp > decoder->last_masked_timestamp)
++ decoder->last_masked_timestamp = masked_timestamp;
++ else
++ decoder->last_masked_timestamp += decoder->period_ticks;
+ break;
+ case INTEL_PT_PERIOD_NONE:
+ case INTEL_PT_PERIOD_MTC:
--- /dev/null
+From 1b6599a9d8e6c9f7e9b0476012383b1777f7fc93 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Fri, 10 May 2019 15:41:43 +0300
+Subject: perf intel-pt: Fix sample timestamp wrt non-taken branches
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit 1b6599a9d8e6c9f7e9b0476012383b1777f7fc93 upstream.
+
+The sample timestamp is updated to ensure that the timestamp represents
+the time of the sample and not a branch that the decoder is still
+walking towards. The sample timestamp is updated when the decoder
+returns, but the decoder does not return for non-taken branches. Update
+the sample timestamp then also.
+
+Note that commit 3f04d98e972b5 ("perf intel-pt: Improve sample
+timestamp") was also a stable fix and appears, for example, in v4.4
+stable tree as commit a4ebb58fd124 ("perf intel-pt: Improve sample
+timestamp").
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: stable@vger.kernel.org # v4.4+
+Fixes: 3f04d98e972b ("perf intel-pt: Improve sample timestamp")
+Link: http://lkml.kernel.org/r/20190510124143.27054-4-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -1318,8 +1318,11 @@ static int intel_pt_walk_tnt(struct inte
+ return 0;
+ }
+ decoder->ip += intel_pt_insn.length;
+- if (!decoder->tnt.count)
++ if (!decoder->tnt.count) {
++ decoder->sample_timestamp = decoder->timestamp;
++ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
+ return -EAGAIN;
++ }
+ decoder->tnt.payload <<= 1;
+ continue;
+ }
x86_64-add-gap-to-int3-to-allow-for-call-emulation.patch
x86_64-allow-breakpoints-to-emulate-call-instructions.patch
ftrace-x86_64-emulate-call-function-while-updating-in-breakpoint-handler.patch
+tracing-fix-partial-reading-of-trace-event-s-id-file.patch
+tracing-probeevent-fix-to-make-the-type-of-comm-string.patch
+memory-tegra-fix-integer-overflow-on-tick-value-calculation.patch
+perf-intel-pt-fix-instructions-sampling-rate.patch
+perf-intel-pt-fix-improved-sample-timestamp.patch
+perf-intel-pt-fix-sample-timestamp-wrt-non-taken-branches.patch
+mips-perf-fix-build-with-config_cpu_bmips5000-enabled.patch
+objtool-allow-ar-to-be-overridden-with-hostar.patch
+x86-mpx-mm-core-fix-recursive-munmap-corruption.patch
+fbdev-efifb-ignore-framebuffer-memmap-entries-that-lack-any-memory-types.patch
+fbdev-sm712fb-fix-brightness-control-on-reboot-don-t-set-sr30.patch
+fbdev-sm712fb-fix-vram-detection-don-t-set-sr70-71-74-75.patch
+fbdev-sm712fb-fix-white-screen-of-death-on-reboot-don-t-set-cr3b-cr3f.patch
+fbdev-sm712fb-fix-boot-screen-glitch-when-sm712fb-replaces-vga.patch
+fbdev-sm712fb-fix-crashes-during-framebuffer-writes-by-correctly-mapping-vram.patch
+fbdev-sm712fb-fix-support-for-1024x768-16-mode.patch
+fbdev-sm712fb-use-1024x768-by-default-on-non-mips-fix-garbled-display.patch
+fbdev-sm712fb-fix-crashes-and-garbled-display-during-dpms-modesetting.patch
+pci-mark-amd-stoney-radeon-r7-gpu-ats-as-broken.patch
+pci-mark-atheros-ar9462-to-avoid-bus-reset.patch
+pci-reset-lenovo-thinkpad-p50-nvgpu-at-boot-if-necessary.patch
+pci-init-pcie-feature-bits-for-managed-host-bridge-alloc.patch
+pci-aer-change-pci_aer_init-stub-to-return-void.patch
+pci-rcar-add-the-initialization-of-pcie-link-in-resume_noirq.patch
+pci-factor-out-pcie_retrain_link-function.patch
+pci-work-around-pericom-pcie-to-pci-bridge-retrain-link-erratum.patch
--- /dev/null
+From cbe08bcbbe787315c425dde284dcb715cfbf3f39 Mon Sep 17 00:00:00 2001
+From: Elazar Leibovich <elazar@lightbitslabs.com>
+Date: Mon, 31 Dec 2018 13:58:37 +0200
+Subject: tracing: Fix partial reading of trace event's id file
+
+From: Elazar Leibovich <elazar@lightbitslabs.com>
+
+commit cbe08bcbbe787315c425dde284dcb715cfbf3f39 upstream.
+
+When reading only part of the id file, the ppos isn't tracked correctly.
+This is taken care by simple_read_from_buffer.
+
+Reading a single byte, and then the next byte would result EOF.
+
+While this seems like not a big deal, this breaks abstractions that
+reads information from files unbuffered. See for example
+https://github.com/golang/go/issues/29399
+
+This code was mentioned as problematic in
+commit cd458ba9d5a5
+("tracing: Do not (ab)use trace_seq in event_id_read()")
+
+An example C code that show this bug is:
+
+ #include <stdio.h>
+ #include <stdint.h>
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+
+ int main(int argc, char **argv) {
+ if (argc < 2)
+ return 1;
+ int fd = open(argv[1], O_RDONLY);
+ char c;
+ read(fd, &c, 1);
+ printf("First %c\n", c);
+ read(fd, &c, 1);
+ printf("Second %c\n", c);
+ }
+
+Then run with, e.g.
+
+ sudo ./a.out /sys/kernel/debug/tracing/events/tcp/tcp_set_state/id
+
+You'll notice you're getting the first character twice, instead of the
+first two characters in the id file.
+
+Link: http://lkml.kernel.org/r/20181231115837.4932-1-elazar@lightbitslabs.com
+
+Cc: Orit Wasserman <orit.was@gmail.com>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: stable@vger.kernel.org
+Fixes: 23725aeeab10b ("ftrace: provide an id file for each event")
+Signed-off-by: Elazar Leibovich <elazar@lightbitslabs.com>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/trace_events.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -1318,9 +1318,6 @@ event_id_read(struct file *filp, char __
+ char buf[32];
+ int len;
+
+- if (*ppos)
+- return 0;
+-
+ if (unlikely(!id))
+ return -ENODEV;
+
--- /dev/null
+From 3dd1f7f24f8ceec00bbbc364c2ac3c893f0fdc4c Mon Sep 17 00:00:00 2001
+From: Masami Hiramatsu <mhiramat@kernel.org>
+Date: Tue, 7 May 2019 22:56:02 +0900
+Subject: tracing: probeevent: Fix to make the type of $comm string
+
+From: Masami Hiramatsu <mhiramat@kernel.org>
+
+commit 3dd1f7f24f8ceec00bbbc364c2ac3c893f0fdc4c upstream.
+
+Fix to make the type of $comm "string". If we set the other type to $comm
+argument, it shows meaningless value or wrong data. Currently probe events
+allow us to set string array type (e.g. ":string[2]"), or other digit types
+like x8 on $comm. But since clearly $comm is just a string data, it should
+not be fetched by other types including array.
+
+Link: http://lkml.kernel.org/r/155723736241.9149.14582064184468574539.stgit@devnote2
+
+Cc: Andreas Ziegler <andreas.ziegler@fau.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: stable@vger.kernel.org
+Fixes: 533059281ee5 ("tracing: probeevent: Introduce new argument fetching code")
+Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/trace_probe.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/kernel/trace/trace_probe.c
++++ b/kernel/trace/trace_probe.c
+@@ -405,13 +405,14 @@ static int traceprobe_parse_probe_arg_bo
+ return -E2BIG;
+ }
+ }
+- /*
+- * The default type of $comm should be "string", and it can't be
+- * dereferenced.
+- */
+- if (!t && strcmp(arg, "$comm") == 0)
++
++ /* Since $comm can not be dereferred, we can find $comm by strcmp */
++ if (strcmp(arg, "$comm") == 0) {
++ /* The type of $comm must be "string", and not an array. */
++ if (parg->count || (t && strcmp(t, "string")))
++ return -EINVAL;
+ parg->type = find_fetch_type("string");
+- else
++ } else
+ parg->type = find_fetch_type(t);
+ if (!parg->type) {
+ pr_info("Unsupported type: %s\n", t);
--- /dev/null
+From 5a28fc94c9143db766d1ba5480cae82d856ad080 Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Fri, 19 Apr 2019 12:47:47 -0700
+Subject: x86/mpx, mm/core: Fix recursive munmap() corruption
+
+From: Dave Hansen <dave.hansen@linux.intel.com>
+
+commit 5a28fc94c9143db766d1ba5480cae82d856ad080 upstream.
+
+This is a bit of a mess, to put it mildly. But, it's a bug
+that only seems to have showed up in 4.20 but wasn't noticed
+until now, because nobody uses MPX.
+
+MPX has the arch_unmap() hook inside of munmap() because MPX
+uses bounds tables that protect other areas of memory. When
+memory is unmapped, there is also a need to unmap the MPX
+bounds tables. Barring this, unused bounds tables can eat 80%
+of the address space.
+
+But, the recursive do_munmap() that gets called vi arch_unmap()
+wreaks havoc with __do_munmap()'s state. It can result in
+freeing populated page tables, accessing bogus VMA state,
+double-freed VMAs and more.
+
+See the "long story" further below for the gory details.
+
+To fix this, call arch_unmap() before __do_unmap() has a chance
+to do anything meaningful. Also, remove the 'vma' argument
+and force the MPX code to do its own, independent VMA lookup.
+
+== UML / unicore32 impact ==
+
+Remove unused 'vma' argument to arch_unmap(). No functional
+change.
+
+I compile tested this on UML but not unicore32.
+
+== powerpc impact ==
+
+powerpc uses arch_unmap() well to watch for munmap() on the
+VDSO and zeroes out 'current->mm->context.vdso_base'. Moving
+arch_unmap() makes this happen earlier in __do_munmap(). But,
+'vdso_base' seems to only be used in perf and in the signal
+delivery that happens near the return to userspace. I can not
+find any likely impact to powerpc, other than the zeroing
+happening a little earlier.
+
+powerpc does not use the 'vma' argument and is unaffected by
+its removal.
+
+I compile-tested a 64-bit powerpc defconfig.
+
+== x86 impact ==
+
+For the common success case this is functionally identical to
+what was there before. For the munmap() failure case, it's
+possible that some MPX tables will be zapped for memory that
+continues to be in use. But, this is an extraordinarily
+unlikely scenario and the harm would be that MPX provides no
+protection since the bounds table got reset (zeroed).
+
+I can't imagine anyone doing this:
+
+ ptr = mmap();
+ // use ptr
+ ret = munmap(ptr);
+ if (ret)
+ // oh, there was an error, I'll
+ // keep using ptr.
+
+Because if you're doing munmap(), you are *done* with the
+memory. There's probably no good data in there _anyway_.
+
+This passes the original reproducer from Richard Biener as
+well as the existing mpx selftests/.
+
+The long story:
+
+munmap() has a couple of pieces:
+
+ 1. Find the affected VMA(s)
+ 2. Split the start/end one(s) if neceesary
+ 3. Pull the VMAs out of the rbtree
+ 4. Actually zap the memory via unmap_region(), including
+ freeing page tables (or queueing them to be freed).
+ 5. Fix up some of the accounting (like fput()) and actually
+ free the VMA itself.
+
+This specific ordering was actually introduced by:
+
+ dd2283f2605e ("mm: mmap: zap pages with read mmap_sem in munmap")
+
+during the 4.20 merge window. The previous __do_munmap() code
+was actually safe because the only thing after arch_unmap() was
+remove_vma_list(). arch_unmap() could not see 'vma' in the
+rbtree because it was detached, so it is not even capable of
+doing operations unsafe for remove_vma_list()'s use of 'vma'.
+
+Richard Biener reported a test that shows this in dmesg:
+
+ [1216548.787498] BUG: Bad rss-counter state mm:0000000017ce560b idx:1 val:551
+ [1216548.787500] BUG: non-zero pgtables_bytes on freeing mm: 24576
+
+What triggered this was the recursive do_munmap() called via
+arch_unmap(). It was freeing page tables that has not been
+properly zapped.
+
+But, the problem was bigger than this. For one, arch_unmap()
+can free VMAs. But, the calling __do_munmap() has variables
+that *point* to VMAs and obviously can't handle them just
+getting freed while the pointer is still in use.
+
+I tried a couple of things here. First, I tried to fix the page
+table freeing problem in isolation, but I then found the VMA
+issue. I also tried having the MPX code return a flag if it
+modified the rbtree which would force __do_munmap() to re-walk
+to restart. That spiralled out of control in complexity pretty
+fast.
+
+Just moving arch_unmap() and accepting that the bonkers failure
+case might eat some bounds tables seems like the simplest viable
+fix.
+
+This was also reported in the following kernel bugzilla entry:
+
+ https://bugzilla.kernel.org/show_bug.cgi?id=203123
+
+There are some reports that this commit triggered this bug:
+
+ dd2283f2605 ("mm: mmap: zap pages with read mmap_sem in munmap")
+
+While that commit certainly made the issues easier to hit, I believe
+the fundamental issue has been with us as long as MPX itself, thus
+the Fixes: tag below is for one of the original MPX commits.
+
+[ mingo: Minor edits to the changelog and the patch. ]
+
+Reported-by: Richard Biener <rguenther@suse.de>
+Reported-by: H.J. Lu <hjl.tools@gmail.com>
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Yang Shi <yang.shi@linux.alibaba.com>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Guan Xuetao <gxt@pku.edu.cn>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Jeff Dike <jdike@addtoit.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Richard Weinberger <richard@nod.at>
+Cc: Rik van Riel <riel@surriel.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: linux-arch@vger.kernel.org
+Cc: linux-mm@kvack.org
+Cc: linux-um@lists.infradead.org
+Cc: linuxppc-dev@lists.ozlabs.org
+Cc: stable@vger.kernel.org
+Fixes: dd2283f2605e ("mm: mmap: zap pages with read mmap_sem in munmap")
+Link: http://lkml.kernel.org/r/20190419194747.5E1AD6DC@viggo.jf.intel.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/mmu_context.h | 1 -
+ arch/um/include/asm/mmu_context.h | 1 -
+ arch/unicore32/include/asm/mmu_context.h | 1 -
+ arch/x86/include/asm/mmu_context.h | 6 +++---
+ arch/x86/include/asm/mpx.h | 15 ++++++++-------
+ arch/x86/mm/mpx.c | 10 ++++++----
+ include/asm-generic/mm_hooks.h | 1 -
+ mm/mmap.c | 15 ++++++++-------
+ 8 files changed, 25 insertions(+), 25 deletions(-)
+
+--- a/arch/powerpc/include/asm/mmu_context.h
++++ b/arch/powerpc/include/asm/mmu_context.h
+@@ -237,7 +237,6 @@ extern void arch_exit_mmap(struct mm_str
+ #endif
+
+ static inline void arch_unmap(struct mm_struct *mm,
+- struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
+ if (start <= mm->context.vdso_base && mm->context.vdso_base < end)
+--- a/arch/um/include/asm/mmu_context.h
++++ b/arch/um/include/asm/mmu_context.h
+@@ -22,7 +22,6 @@ static inline int arch_dup_mmap(struct m
+ }
+ extern void arch_exit_mmap(struct mm_struct *mm);
+ static inline void arch_unmap(struct mm_struct *mm,
+- struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
+ }
+--- a/arch/unicore32/include/asm/mmu_context.h
++++ b/arch/unicore32/include/asm/mmu_context.h
+@@ -88,7 +88,6 @@ static inline int arch_dup_mmap(struct m
+ }
+
+ static inline void arch_unmap(struct mm_struct *mm,
+- struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
+ }
+--- a/arch/x86/include/asm/mmu_context.h
++++ b/arch/x86/include/asm/mmu_context.h
+@@ -277,8 +277,8 @@ static inline void arch_bprm_mm_init(str
+ mpx_mm_init(mm);
+ }
+
+-static inline void arch_unmap(struct mm_struct *mm, struct vm_area_struct *vma,
+- unsigned long start, unsigned long end)
++static inline void arch_unmap(struct mm_struct *mm, unsigned long start,
++ unsigned long end)
+ {
+ /*
+ * mpx_notify_unmap() goes and reads a rarely-hot
+@@ -298,7 +298,7 @@ static inline void arch_unmap(struct mm_
+ * consistently wrong.
+ */
+ if (unlikely(cpu_feature_enabled(X86_FEATURE_MPX)))
+- mpx_notify_unmap(mm, vma, start, end);
++ mpx_notify_unmap(mm, start, end);
+ }
+
+ /*
+--- a/arch/x86/include/asm/mpx.h
++++ b/arch/x86/include/asm/mpx.h
+@@ -64,12 +64,15 @@ struct mpx_fault_info {
+ };
+
+ #ifdef CONFIG_X86_INTEL_MPX
+-int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs);
+-int mpx_handle_bd_fault(void);
++
++extern int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs);
++extern int mpx_handle_bd_fault(void);
++
+ static inline int kernel_managing_mpx_tables(struct mm_struct *mm)
+ {
+ return (mm->context.bd_addr != MPX_INVALID_BOUNDS_DIR);
+ }
++
+ static inline void mpx_mm_init(struct mm_struct *mm)
+ {
+ /*
+@@ -78,11 +81,10 @@ static inline void mpx_mm_init(struct mm
+ */
+ mm->context.bd_addr = MPX_INVALID_BOUNDS_DIR;
+ }
+-void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma,
+- unsigned long start, unsigned long end);
+
+-unsigned long mpx_unmapped_area_check(unsigned long addr, unsigned long len,
+- unsigned long flags);
++extern void mpx_notify_unmap(struct mm_struct *mm, unsigned long start, unsigned long end);
++extern unsigned long mpx_unmapped_area_check(unsigned long addr, unsigned long len, unsigned long flags);
++
+ #else
+ static inline int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs)
+ {
+@@ -100,7 +102,6 @@ static inline void mpx_mm_init(struct mm
+ {
+ }
+ static inline void mpx_notify_unmap(struct mm_struct *mm,
+- struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
+ }
+--- a/arch/x86/mm/mpx.c
++++ b/arch/x86/mm/mpx.c
+@@ -881,9 +881,10 @@ static int mpx_unmap_tables(struct mm_st
+ * the virtual address region start...end have already been split if
+ * necessary, and the 'vma' is the first vma in this range (start -> end).
+ */
+-void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma,
+- unsigned long start, unsigned long end)
++void mpx_notify_unmap(struct mm_struct *mm, unsigned long start,
++ unsigned long end)
+ {
++ struct vm_area_struct *vma;
+ int ret;
+
+ /*
+@@ -902,11 +903,12 @@ void mpx_notify_unmap(struct mm_struct *
+ * which should not occur normally. Being strict about it here
+ * helps ensure that we do not have an exploitable stack overflow.
+ */
+- do {
++ vma = find_vma(mm, start);
++ while (vma && vma->vm_start < end) {
+ if (vma->vm_flags & VM_MPX)
+ return;
+ vma = vma->vm_next;
+- } while (vma && vma->vm_start < end);
++ }
+
+ ret = mpx_unmap_tables(mm, start, end);
+ if (ret)
+--- a/include/asm-generic/mm_hooks.h
++++ b/include/asm-generic/mm_hooks.h
+@@ -18,7 +18,6 @@ static inline void arch_exit_mmap(struct
+ }
+
+ static inline void arch_unmap(struct mm_struct *mm,
+- struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
+ }
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -2736,9 +2736,17 @@ int __do_munmap(struct mm_struct *mm, un
+ return -EINVAL;
+
+ len = PAGE_ALIGN(len);
++ end = start + len;
+ if (len == 0)
+ return -EINVAL;
+
++ /*
++ * arch_unmap() might do unmaps itself. It must be called
++ * and finish any rbtree manipulation before this code
++ * runs and also starts to manipulate the rbtree.
++ */
++ arch_unmap(mm, start, end);
++
+ /* Find the first overlapping VMA */
+ vma = find_vma(mm, start);
+ if (!vma)
+@@ -2747,7 +2755,6 @@ int __do_munmap(struct mm_struct *mm, un
+ /* we have start < vma->vm_end */
+
+ /* if it doesn't overlap, we have nothing.. */
+- end = start + len;
+ if (vma->vm_start >= end)
+ return 0;
+
+@@ -2817,12 +2824,6 @@ int __do_munmap(struct mm_struct *mm, un
+ /* Detach vmas from rbtree */
+ detach_vmas_to_be_unmapped(mm, vma, prev, end);
+
+- /*
+- * mpx unmap needs to be called with mmap_sem held for write.
+- * It is safe to call it before unmap_region().
+- */
+- arch_unmap(mm, vma, start, end);
+-
+ if (downgrade)
+ downgrade_write(&mm->mmap_sem);
+