--- /dev/null
+From bee09ed91cacdbffdbcd3b05de8409c77ec9fcd6 Mon Sep 17 00:00:00 2001
+From: Robert Richter <rric@kernel.org>
+Date: Wed, 15 Jan 2014 15:57:29 +0100
+Subject: perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h
+
+From: Robert Richter <rric@kernel.org>
+
+commit bee09ed91cacdbffdbcd3b05de8409c77ec9fcd6 upstream.
+
+On AMD family 10h we see following error messages while waking up from
+S3 for all non-boot CPUs leading to a failed IBS initialization:
+
+ Enabling non-boot CPUs ...
+ smpboot: Booting Node 0 Processor 1 APIC 0x1
+ [Firmware Bug]: cpu 1, try to use APIC500 (LVT offset 0) for vector 0x400, but the register is already in use for vector 0xf9 on another cpu
+ perf: IBS APIC setup failed on cpu #1
+ process: Switch to broadcast mode on CPU1
+ CPU1 is up
+ ...
+ ACPI: Waking up from system sleep state S3
+
+Reason for this is that during suspend the LVT offset for the IBS
+vector gets lost and needs to be reinialized while resuming.
+
+The offset is read from the IBSCTL msr. On family 10h the offset needs
+to be 1 as offset 0 is used for the MCE threshold interrupt, but
+firmware assings it for IBS to 0 too. The kernel needs to reprogram
+the vector. The msr is a readonly node msr, but a new value can be
+written via pci config space access. The reinitialization is
+implemented for family 10h in setup_ibs_ctl() which is forced during
+IBS setup.
+
+This patch fixes IBS setup after waking up from S3 by adding
+resume/supend hooks for the boot cpu which does the offset
+reinitialization.
+
+Marking it as stable to let distros pick up this fix.
+
+Signed-off-by: Robert Richter <rric@kernel.org>
+Signed-off-by: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: http://lkml.kernel.org/r/1389797849-5565-1-git-send-email-rric.net@gmail.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/cpu/perf_event_amd_ibs.c | 53 ++++++++++++++++++++++++++-----
+ 1 file changed, 45 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
++++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+@@ -9,6 +9,7 @@
+ #include <linux/perf_event.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
++#include <linux/syscore_ops.h>
+
+ #include <asm/apic.h>
+
+@@ -209,6 +210,18 @@ out:
+ return ret;
+ }
+
++static void ibs_eilvt_setup(void)
++{
++ /*
++ * Force LVT offset assignment for family 10h: The offsets are
++ * not assigned by the BIOS for this family, so the OS is
++ * responsible for doing it. If the OS assignment fails, fall
++ * back to BIOS settings and try to setup this.
++ */
++ if (boot_cpu_data.x86 == 0x10)
++ force_ibs_eilvt_setup();
++}
++
+ static inline int get_ibs_lvt_offset(void)
+ {
+ u64 val;
+@@ -244,6 +257,36 @@ static void clear_APIC_ibs(void *dummy)
+ setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+ }
+
++#ifdef CONFIG_PM
++
++static int perf_ibs_suspend(void)
++{
++ clear_APIC_ibs(NULL);
++ return 0;
++}
++
++static void perf_ibs_resume(void)
++{
++ ibs_eilvt_setup();
++ setup_APIC_ibs(NULL);
++}
++
++static struct syscore_ops perf_ibs_syscore_ops = {
++ .resume = perf_ibs_resume,
++ .suspend = perf_ibs_suspend,
++};
++
++static void perf_ibs_pm_init(void)
++{
++ register_syscore_ops(&perf_ibs_syscore_ops);
++}
++
++#else
++
++static inline void perf_ibs_pm_init(void) { }
++
++#endif
++
+ static int __cpuinit
+ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
+ {
+@@ -270,18 +313,12 @@ static __init int amd_ibs_init(void)
+ if (!caps)
+ return -ENODEV; /* ibs not supported by the cpu */
+
+- /*
+- * Force LVT offset assignment for family 10h: The offsets are
+- * not assigned by the BIOS for this family, so the OS is
+- * responsible for doing it. If the OS assignment fails, fall
+- * back to BIOS settings and try to setup this.
+- */
+- if (boot_cpu_data.x86 == 0x10)
+- force_ibs_eilvt_setup();
++ ibs_eilvt_setup();
+
+ if (!ibs_eilvt_valid())
+ goto out;
+
++ perf_ibs_pm_init();
+ get_online_cpus();
+ ibs_caps = caps;
+ /* make ibs_caps visible to other cpus: */
--- /dev/null
+From 0283f7a100882684ad32b768f9f1ad81658a0b92 Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Fri, 13 Dec 2013 12:00:30 +0000
+Subject: staging: comedi: 8255_pci: fix for newer PCI-DIO48H
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 0283f7a100882684ad32b768f9f1ad81658a0b92 upstream.
+
+At some point, Measurement Computing / ComputerBoards redesigned the
+PCI-DIO48H to use a PLX PCI interface chip instead of an AMCC chip.
+This meant they had to put their hardware registers in the PCI BAR 2
+region instead of PCI BAR 1. Unfortunately, they kept the same PCI
+device ID for the new design. This means the driver recognizes the
+newer cards, but doesn't work (and is likely to screw up the local
+configuration registers of the PLX chip) because it's using the wrong
+region.
+
+Since the PCI subvendor and subdevice IDs were both zero on the old
+design, but are the same as the vendor and device on the new design, we
+can tell the old design and new design apart easily enough. Split the
+existing entry for the PCI-DIO48H in `pci_8255_boards[]` into two new
+entries, referenced by different entries in the PCI device ID table
+`pci_8255_pci_table[]`. Use the same board name for both entries.
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/cb_pcidio.c | 21 ++++++++-------------
+ 1 file changed, 8 insertions(+), 13 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -56,10 +56,6 @@ struct pcidio_board {
+ const char *name; /* name of the board */
+ int dev_id;
+ int n_8255; /* number of 8255 chips on board */
+-
+- /* indices of base address regions */
+- int pcicontroler_badrindex;
+- int dioregs_badrindex;
+ };
+
+ static const struct pcidio_board pcidio_boards[] = {
+@@ -67,22 +63,16 @@ static const struct pcidio_board pcidio_
+ .name = "pci-dio24",
+ .dev_id = 0x0028,
+ .n_8255 = 1,
+- .pcicontroler_badrindex = 1,
+- .dioregs_badrindex = 2,
+ },
+ {
+ .name = "pci-dio24h",
+ .dev_id = 0x0014,
+ .n_8255 = 1,
+- .pcicontroler_badrindex = 1,
+- .dioregs_badrindex = 2,
+ },
+ {
+ .name = "pci-dio48h",
+ .dev_id = 0x000b,
+ .n_8255 = 2,
+- .pcicontroler_badrindex = 0,
+- .dioregs_badrindex = 1,
+ },
+ };
+
+@@ -239,10 +229,15 @@ found:
+ if (comedi_pci_enable(pcidev, thisboard->name))
+ return -EIO;
+
+- devpriv->dio_reg_base
+- =
++ /*
++ * Use PCI BAR 2 region if non-zero length, else use PCI BAR 1 region.
++ * PCI BAR 1 is only used for older PCI-DIO48H boards. At some point
++ * the PCI-DIO48H was redesigned to use the same PCI interface chip
++ * (and same PCI BAR region) as the other boards.
++ */
++ devpriv->dio_reg_base =
+ pci_resource_start(devpriv->pci_dev,
+- pcidio_boards[index].dioregs_badrindex);
++ (pci_resource_len(pcidev, 2) ? 2 : 1));
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a