--- /dev/null
+From 5e6533a6f52f1a8283b2f818f5828be99a417dd6 Mon Sep 17 00:00:00 2001
+From: Tomas Winkler <tomas.winkler@intel.com>
+Date: Tue, 25 Mar 2014 21:25:18 +0200
+Subject: mei: me: do not load the driver if the FW doesn't support MEI interface
+
+From: Tomas Winkler <tomas.winkler@intel.com>
+
+commit 5e6533a6f52f1a8283b2f818f5828be99a417dd6 upstream.
+
+NM and SPS FW types that may run on ME device on server platforms
+do not have valid MEI/HECI interface and driver should not
+be bound to it as this might lead to system hung.
+In practice not all BIOSes effectively hide such devices from the
+OS and in some cases it is not possible.
+
+We determine FW type by examining Host FW status registers in order to
+unbind the driver.
+In this patch we are adding check for ME on Cougar Point, Lynx Point
+Devices
+
+Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
+Tested-by: Nikola Ciprich <nikola.ciprich@linuxbox.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/misc/mei/hw-me-regs.h | 5 +++++
+ drivers/misc/mei/pci-me.c | 30 +++++++++++++++++++++++-------
+ 2 files changed, 28 insertions(+), 7 deletions(-)
+
+--- a/drivers/misc/mei/hw-me-regs.h
++++ b/drivers/misc/mei/hw-me-regs.h
+@@ -115,6 +115,11 @@
+ #define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */
+
+ #define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
++
++/* Host Firmware Status Registers in PCI Config Space */
++#define PCI_CFG_HFS_1 0x40
++#define PCI_CFG_HFS_2 0x48
++
+ /*
+ * MEI HW Section
+ */
+--- a/drivers/misc/mei/pci-me.c
++++ b/drivers/misc/mei/pci-me.c
+@@ -105,15 +105,31 @@ static bool mei_me_quirk_probe(struct pc
+ const struct pci_device_id *ent)
+ {
+ u32 reg;
+- if (ent->device == MEI_DEV_ID_PBG_1) {
+- pci_read_config_dword(pdev, 0x48, ®);
+- /* make sure that bit 9 is up and bit 10 is down */
+- if ((reg & 0x600) == 0x200) {
+- dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
+- return false;
+- }
++ /* Cougar Point || Patsburg */
++ if (ent->device == MEI_DEV_ID_CPT_1 ||
++ ent->device == MEI_DEV_ID_PBG_1) {
++ pci_read_config_dword(pdev, PCI_CFG_HFS_2, ®);
++ /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
++ if ((reg & 0x600) == 0x200)
++ goto no_mei;
+ }
++
++ /* Lynx Point */
++ if (ent->device == MEI_DEV_ID_LPT_H ||
++ ent->device == MEI_DEV_ID_LPT_W ||
++ ent->device == MEI_DEV_ID_LPT_HR) {
++ /* Read ME FW Status check for SPS Firmware */
++ pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®);
++ /* if bits [19:16] = 15, running SPS Firmware */
++ if ((reg & 0xf0000) == 0xf0000)
++ goto no_mei;
++ }
++
+ return true;
++
++no_mei:
++ dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
++ return false;
+ }
+ /**
+ * mei_probe - Device Initialization Routine
--- /dev/null
+From 2253e8d79237c69086ded391e6767afe16972527 Mon Sep 17 00:00:00 2001
+From: Sebastian Ott <sebott@linux.vnet.ibm.com>
+Date: Mon, 27 Jan 2014 13:26:10 +0100
+Subject: s390/cio: fix driver callback initialization for ccw consoles
+
+From: Sebastian Ott <sebott@linux.vnet.ibm.com>
+
+commit 2253e8d79237c69086ded391e6767afe16972527 upstream.
+
+ccw consoles are in use before they can be properly registered with
+the driver core. For devices which are in use by a device driver we
+rely on the ccw_device's pointer to the driver callbacks to be valid.
+For ccw consoles this pointer is NULL until they are registered later
+during boot and we dereferenced this pointer. This worked by
+chance on 64 bit builds (cdev->drv was NULL but the optional callback
+cdev->drv->path_event was also NULL by coincidence) and was unnoticed
+until we received reports about boot failures on 31 bit systems.
+Fix it by initializing the driver pointer for ccw consoles.
+
+Reported-by: Mike Frysinger <vapier@gentoo.org>
+Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/s390/include/asm/ccwdev.h | 2 +-
+ drivers/s390/char/con3215.c | 2 +-
+ drivers/s390/char/con3270.c | 6 +-----
+ drivers/s390/char/raw3270.c | 10 +++++++++-
+ drivers/s390/char/raw3270.h | 2 +-
+ drivers/s390/cio/device.c | 3 ++-
+ 6 files changed, 15 insertions(+), 10 deletions(-)
+
+--- a/arch/s390/include/asm/ccwdev.h
++++ b/arch/s390/include/asm/ccwdev.h
+@@ -219,7 +219,7 @@ extern void ccw_device_get_id(struct ccw
+ #define to_ccwdev(n) container_of(n, struct ccw_device, dev)
+ #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
+
+-extern struct ccw_device *ccw_device_probe_console(void);
++extern struct ccw_device *ccw_device_probe_console(struct ccw_driver *);
+ extern void ccw_device_wait_idle(struct ccw_device *);
+ extern int ccw_device_force_console(struct ccw_device *);
+
+--- a/drivers/s390/char/con3215.c
++++ b/drivers/s390/char/con3215.c
+@@ -922,7 +922,7 @@ static int __init con3215_init(void)
+ raw3215_freelist = req;
+ }
+
+- cdev = ccw_device_probe_console();
++ cdev = ccw_device_probe_console(&raw3215_ccw_driver);
+ if (IS_ERR(cdev))
+ return -ENODEV;
+
+--- a/drivers/s390/char/con3270.c
++++ b/drivers/s390/char/con3270.c
+@@ -576,7 +576,6 @@ static struct console con3270 = {
+ static int __init
+ con3270_init(void)
+ {
+- struct ccw_device *cdev;
+ struct raw3270 *rp;
+ void *cbuf;
+ int i;
+@@ -591,10 +590,7 @@ con3270_init(void)
+ cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
+ }
+
+- cdev = ccw_device_probe_console();
+- if (IS_ERR(cdev))
+- return -ENODEV;
+- rp = raw3270_setup_console(cdev);
++ rp = raw3270_setup_console();
+ if (IS_ERR(rp))
+ return PTR_ERR(rp);
+
+--- a/drivers/s390/char/raw3270.c
++++ b/drivers/s390/char/raw3270.c
+@@ -776,16 +776,24 @@ raw3270_setup_device(struct ccw_device *
+ }
+
+ #ifdef CONFIG_TN3270_CONSOLE
++/* Tentative definition - see below for actual definition. */
++static struct ccw_driver raw3270_ccw_driver;
++
+ /*
+ * Setup 3270 device configured as console.
+ */
+-struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
++struct raw3270 __init *raw3270_setup_console(void)
+ {
++ struct ccw_device *cdev;
+ unsigned long flags;
+ struct raw3270 *rp;
+ char *ascebc;
+ int rc;
+
++ cdev = ccw_device_probe_console(&raw3270_ccw_driver);
++ if (IS_ERR(cdev))
++ return ERR_CAST(cdev);
++
+ rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
+ ascebc = kzalloc(256, GFP_KERNEL);
+ rc = raw3270_setup_device(cdev, rp, ascebc);
+--- a/drivers/s390/char/raw3270.h
++++ b/drivers/s390/char/raw3270.h
+@@ -190,7 +190,7 @@ raw3270_put_view(struct raw3270_view *vi
+ wake_up(&raw3270_wait_queue);
+ }
+
+-struct raw3270 *raw3270_setup_console(struct ccw_device *cdev);
++struct raw3270 *raw3270_setup_console(void);
+ void raw3270_wait_cons_dev(struct raw3270 *);
+
+ /* Notifier for device addition/removal */
+--- a/drivers/s390/cio/device.c
++++ b/drivers/s390/cio/device.c
+@@ -1610,7 +1610,7 @@ out_unlock:
+ return rc;
+ }
+
+-struct ccw_device *ccw_device_probe_console(void)
++struct ccw_device *ccw_device_probe_console(struct ccw_driver *drv)
+ {
+ struct io_subchannel_private *io_priv;
+ struct ccw_device *cdev;
+@@ -1632,6 +1632,7 @@ struct ccw_device *ccw_device_probe_cons
+ kfree(io_priv);
+ return cdev;
+ }
++ cdev->drv = drv;
+ set_io_private(sch, io_priv);
+ ret = ccw_device_console_enable(cdev, sch);
+ if (ret) {