--- /dev/null
+From c1d867a54d426b45da017fbe8e585f8a3064ce8d Mon Sep 17 00:00:00 2001
+From: Dave Jones <davej@redhat.com>
+Date: Thu, 23 Jan 2014 15:55:43 -0800
+Subject: fs/proc/proc_devtree.c: remove empty /proc/device-tree when no openfirmware exists.
+
+From: Dave Jones <davej@redhat.com>
+
+commit c1d867a54d426b45da017fbe8e585f8a3064ce8d upstream.
+
+Distribution kernels might want to build in support for /proc/device-tree
+for kernels that might end up running on hardware that doesn't support
+openfirmware. This results in an empty /proc/device-tree existing.
+Remove it if the OFW root node doesn't exist.
+
+This situation actually confuses grub2, resulting in install failures.
+grub2 sees the /proc/device-tree and picks the wrong install target cf.
+http://bzr.savannah.gnu.org/lh/grub/trunk/grub/annotate/4300/util/grub-install.in#L311
+grub should be more robust, but still, leaving an empty proc dir seems
+pointless.
+
+Addresses https://bugzilla.redhat.com/show_bug.cgi?id=818378.
+
+Signed-off-by: Dave Jones <davej@redhat.com>
+Cc: Al Viro <viro@ZenIV.linux.org.uk>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/proc/proc_devtree.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/proc/proc_devtree.c
++++ b/fs/proc/proc_devtree.c
+@@ -232,6 +232,7 @@ void __init proc_device_tree_init(void)
+ return;
+ root = of_find_node_by_path("/");
+ if (root == NULL) {
++ remove_proc_entry("device-tree", NULL);
+ pr_debug("/proc/device-tree: can't find root\n");
+ return;
+ }
--- /dev/null
+From c15bdfd5b9831e4cab8cfc118243956e267dd30e Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 16 Dec 2013 07:09:25 -0800
+Subject: Input: elantech - improve clickpad detection
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit c15bdfd5b9831e4cab8cfc118243956e267dd30e upstream.
+
+The current assumption in the elantech driver that hw version 3 touchpads
+are never clickpads and hw version 4 touchpads are always clickpads is
+wrong.
+
+There are several bug reports for this, ie:
+https://bugzilla.redhat.com/show_bug.cgi?id=1030802
+http://superuser.com/questions/619582/right-elantech-touchpad-button-not-working-in-linux
+
+I've spend a couple of hours wading through various bugzillas, launchpads
+and forum posts to create a list of fw-versions and capabilities for
+different laptop models to find a good method to differentiate between
+clickpads and versions with separate hardware buttons.
+
+Which shows that a device being a clickpad is reliable indicated by bit 12
+being set in the fw_version. I've included the gathered list inside the
+driver, so that we've this info at hand if we need to revisit this later.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/mouse/elantech.c | 45 ++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 42 insertions(+), 3 deletions(-)
+
+--- a/drivers/input/mouse/elantech.c
++++ b/drivers/input/mouse/elantech.c
+@@ -486,6 +486,7 @@ static void elantech_input_sync_v4(struc
+ unsigned char *packet = psmouse->packet;
+
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
++ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+ input_mt_report_pointer_emulation(dev, true);
+ input_sync(dev);
+ }
+@@ -984,6 +985,44 @@ static int elantech_get_resolution_v4(st
+ }
+
+ /*
++ * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in
++ * fw_version for this is based on the following fw_version & caps table:
++ *
++ * Laptop-model: fw_version: caps: buttons:
++ * Acer S3 0x461f00 10, 13, 0e clickpad
++ * Acer S7-392 0x581f01 50, 17, 0d clickpad
++ * Acer V5-131 0x461f02 01, 16, 0c clickpad
++ * Acer V5-551 0x461f00 ? clickpad
++ * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
++ * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
++ * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
++ * Asus UX31 0x361f00 20, 15, 0e clickpad
++ * Asus UX32VD 0x361f02 00, 15, 0e clickpad
++ * Avatar AVIU-145A2 0x361f00 ? clickpad
++ * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
++ * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
++ * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
++ * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
++ * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
++ * Samsung NP900X3E-A02 0x575f03 ? clickpad
++ * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad
++ * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons
++ * Samsung RF710 0x450f00 ? 2 hw buttons
++ * System76 Pangolin 0x250f01 ? 2 hw buttons
++ * (*) + 3 trackpoint buttons
++ */
++static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
++{
++ struct input_dev *dev = psmouse->dev;
++ struct elantech_data *etd = psmouse->private;
++
++ if (etd->fw_version & 0x001000) {
++ __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
++ __clear_bit(BTN_RIGHT, dev->keybit);
++ }
++}
++
++/*
+ * Set the appropriate event bits for the input subsystem
+ */
+ static int elantech_set_input_params(struct psmouse *psmouse)
+@@ -1026,6 +1065,8 @@ static int elantech_set_input_params(str
+ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+ /* fall through */
+ case 3:
++ if (etd->hw_version == 3)
++ elantech_set_buttonpad_prop(psmouse);
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+ if (etd->reports_pressure) {
+@@ -1047,9 +1088,7 @@ static int elantech_set_input_params(str
+ */
+ psmouse_warn(psmouse, "couldn't query resolution data.\n");
+ }
+- /* v4 is clickpad, with only one button. */
+- __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+- __clear_bit(BTN_RIGHT, dev->keybit);
++ elantech_set_buttonpad_prop(psmouse);
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ /* For X to recognize me as touchpad. */
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
--- /dev/null
+From 961794a00eab03f4344b7d5e825e8e789e55da87 Mon Sep 17 00:00:00 2001
+From: Ping Cheng <pinglinux@gmail.com>
+Date: Thu, 5 Dec 2013 12:54:53 -0800
+Subject: Input: wacom - add reporting of SW_MUTE_DEVICE events
+
+From: Ping Cheng <pinglinux@gmail.com>
+
+commit 961794a00eab03f4344b7d5e825e8e789e55da87 upstream.
+
+New Intuos series models added a hardware switch to turn touch
+data on/off. The state of the switch is reported periodically
+from the tablet. To report the state the driver will emit SW_MUTE_DEVICE
+events.
+
+Reviewed_by: Chris Bagwell <chris@cnpbagwell.com>
+Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
+Tested-by: Jason Gerecke <killertofu@gmail.com>
+Signed-off-by: Ping Cheng <pingc@wacom.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/tablet/wacom_sys.c | 12 ++++++++++++
+ drivers/input/tablet/wacom_wac.c | 30 +++++++++++++++++++++++++++---
+ drivers/input/tablet/wacom_wac.h | 5 +++++
+ 3 files changed, 44 insertions(+), 3 deletions(-)
+
+--- a/drivers/input/tablet/wacom_sys.c
++++ b/drivers/input/tablet/wacom_sys.c
+@@ -1197,6 +1197,8 @@ static void wacom_wireless_work(struct w
+ wacom_wac1->features.device_type = BTN_TOOL_PEN;
+ snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen",
+ wacom_wac1->features.name);
++ wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
++ wacom_wac1->shared->type = wacom_wac1->features.type;
+ error = wacom_register_input(wacom1);
+ if (error)
+ goto fail;
+@@ -1218,6 +1220,10 @@ static void wacom_wireless_work(struct w
+ error = wacom_register_input(wacom2);
+ if (error)
+ goto fail;
++
++ if (wacom_wac1->features.type == INTUOSHT &&
++ wacom_wac1->features.touch_max)
++ wacom_wac->shared->touch_input = wacom_wac2->input;
+ }
+
+ error = wacom_initialize_battery(wacom);
+@@ -1396,6 +1402,12 @@ static int wacom_probe(struct usb_interf
+ goto fail5;
+ }
+ }
++
++ if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) {
++ if (wacom_wac->features.device_type == BTN_TOOL_FINGER)
++ wacom_wac->shared->touch_input = wacom_wac->input;
++ }
++
+ return 0;
+
+ fail5: wacom_destroy_leds(wacom);
+--- a/drivers/input/tablet/wacom_wac.c
++++ b/drivers/input/tablet/wacom_wac.c
+@@ -1219,13 +1219,23 @@ static int wacom_bpt3_touch(struct wacom
+
+ static int wacom_bpt_pen(struct wacom_wac *wacom)
+ {
++ struct wacom_features *features = &wacom->features;
+ struct input_dev *input = wacom->input;
+ unsigned char *data = wacom->data;
+ int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
+
+- if (data[0] != WACOM_REPORT_PENABLED)
++ if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB)
+ return 0;
+
++ if (data[0] == WACOM_REPORT_USB) {
++ if (features->type == INTUOSHT && features->touch_max) {
++ input_report_switch(wacom->shared->touch_input,
++ SW_MUTE_DEVICE, data[8] & 0x40);
++ input_sync(wacom->shared->touch_input);
++ }
++ return 0;
++ }
++
+ prox = (data[1] & 0x20) == 0x20;
+
+ /*
+@@ -1258,8 +1268,8 @@ static int wacom_bpt_pen(struct wacom_wa
+ * touching and applying pressure; do not report negative
+ * distance.
+ */
+- if (data[8] <= wacom->features.distance_max)
+- d = wacom->features.distance_max - data[8];
++ if (data[8] <= features->distance_max)
++ d = features->distance_max - data[8];
+
+ pen = data[1] & 0x01;
+ btn1 = data[1] & 0x02;
+@@ -1310,6 +1320,13 @@ static int wacom_wireless_irq(struct wac
+ if (connected) {
+ int pid, battery;
+
++ if ((wacom->shared->type == INTUOSHT) &&
++ wacom->shared->touch_max) {
++ input_report_switch(wacom->shared->touch_input,
++ SW_MUTE_DEVICE, data[5] & 0x40);
++ input_sync(wacom->shared->touch_input);
++ }
++
+ pid = get_unaligned_be16(&data[6]);
+ battery = data[5] & 0x3f;
+ if (wacom->pid != pid) {
+@@ -1779,6 +1796,13 @@ int wacom_setup_input_capabilities(struc
+ break;
+
+ case INTUOSHT:
++ if (features->touch_max &&
++ features->device_type == BTN_TOOL_FINGER) {
++ input_dev->evbit[0] |= BIT_MASK(EV_SW);
++ __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
++ }
++ /* fall through */
++
+ case BAMBOO_PT:
+ __clear_bit(ABS_MISC, input_dev->absbit);
+
+--- a/drivers/input/tablet/wacom_wac.h
++++ b/drivers/input/tablet/wacom_wac.h
+@@ -55,6 +55,7 @@
+ #define WACOM_REPORT_TPC1FGE 18
+ #define WACOM_REPORT_24HDT 1
+ #define WACOM_REPORT_WL 128
++#define WACOM_REPORT_USB 192
+
+ /* device quirks */
+ #define WACOM_QUIRK_MULTI_INPUT 0x0001
+@@ -131,6 +132,10 @@ struct wacom_features {
+ struct wacom_shared {
+ bool stylus_in_proximity;
+ bool touch_down;
++ /* for wireless device to access USB interfaces */
++ unsigned touch_max;
++ int type;
++ struct input_dev *touch_input;
+ };
+
+ struct wacom_wac {
--- /dev/null
+From b5fd2a3e92ca5c8c1f3c20d31ac5daed3ec4d604 Mon Sep 17 00:00:00 2001
+From: Ping Cheng <pinglinux@gmail.com>
+Date: Mon, 25 Nov 2013 18:44:55 -0800
+Subject: Input: wacom - add support for three new Intuos devices
+
+From: Ping Cheng <pinglinux@gmail.com>
+
+commit b5fd2a3e92ca5c8c1f3c20d31ac5daed3ec4d604 upstream.
+
+Two tablets in this series support both pen and touch. One (Intuos S)
+only supports pen. This patch also updates the driver to process wireless
+devices that do not support touch interface.
+
+Tested-by: Jason Gerecke <killertofu@gmail.com>
+Reviewed-by: Chris Bagwell <chris@cnpbagwell.com>
+Signed-off-by: Ping Cheng <pingc@wacom.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/tablet/wacom_sys.c | 6 +--
+ drivers/input/tablet/wacom_wac.c | 61 +++++++++++++++++++++++++++++----------
+ drivers/input/tablet/wacom_wac.h | 2 +
+ 3 files changed, 51 insertions(+), 18 deletions(-)
+
+--- a/drivers/input/tablet/wacom_sys.c
++++ b/drivers/input/tablet/wacom_sys.c
+@@ -1202,7 +1202,8 @@ static void wacom_wireless_work(struct w
+ goto fail;
+
+ /* Touch interface */
+- if (wacom_wac1->features.touch_max) {
++ if (wacom_wac1->features.touch_max ||
++ wacom_wac1->features.type == INTUOSHT) {
+ wacom_wac2->features =
+ *((struct wacom_features *)id->driver_info);
+ wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
+@@ -1325,7 +1326,7 @@ static int wacom_probe(struct usb_interf
+ * HID descriptor. If this is the touch interface (wMaxPacketSize
+ * of WACOM_PKGLEN_BBTOUCH3), override the table values.
+ */
+- if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
++ if (features->type >= INTUOS5S && features->type <= INTUOSHT) {
+ if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
+ features->device_type = BTN_TOOL_FINGER;
+ features->pktlen = WACOM_PKGLEN_BBTOUCH3;
+@@ -1395,7 +1396,6 @@ static int wacom_probe(struct usb_interf
+ goto fail5;
+ }
+ }
+-
+ return 0;
+
+ fail5: wacom_destroy_leds(wacom);
+--- a/drivers/input/tablet/wacom_wac.c
++++ b/drivers/input/tablet/wacom_wac.c
+@@ -1176,10 +1176,16 @@ static void wacom_bpt3_touch_msg(struct
+ static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
+ {
+ struct input_dev *input = wacom->input;
++ struct wacom_features *features = &wacom->features;
+
+- input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
++ if (features->type == INTUOSHT) {
++ input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0);
++ input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
++ } else {
++ input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
++ input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
++ }
+ input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
+- input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+ input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
+ }
+
+@@ -1217,7 +1223,7 @@ static int wacom_bpt_pen(struct wacom_wa
+ unsigned char *data = wacom->data;
+ int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
+
+- if (data[0] != 0x02)
++ if (data[0] != WACOM_REPORT_PENABLED)
+ return 0;
+
+ prox = (data[1] & 0x20) == 0x20;
+@@ -1297,7 +1303,7 @@ static int wacom_wireless_irq(struct wac
+ unsigned char *data = wacom->data;
+ int connected;
+
+- if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80)
++ if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL)
+ return 0;
+
+ connected = data[1] & 0x01;
+@@ -1391,6 +1397,7 @@ void wacom_wac_irq(struct wacom_wac *wac
+ break;
+
+ case BAMBOO_PT:
++ case INTUOSHT:
+ sync = wacom_bpt_irq(wacom_wac, len);
+ break;
+
+@@ -1459,7 +1466,7 @@ void wacom_setup_device_quirks(struct wa
+
+ /* these device have multiple inputs */
+ if (features->type >= WIRELESS ||
+- (features->type >= INTUOS5S && features->type <= INTUOSPL) ||
++ (features->type >= INTUOS5S && features->type <= INTUOSHT) ||
+ (features->oVid && features->oPid))
+ features->quirks |= WACOM_QUIRK_MULTI_INPUT;
+
+@@ -1771,33 +1778,43 @@ int wacom_setup_input_capabilities(struc
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+ break;
+
++ case INTUOSHT:
+ case BAMBOO_PT:
+ __clear_bit(ABS_MISC, input_dev->absbit);
+
+- __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+-
+ if (features->device_type == BTN_TOOL_FINGER) {
+- unsigned int flags = INPUT_MT_POINTER;
+
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_FORWARD, input_dev->keybit);
+ __set_bit(BTN_BACK, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+
+- if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
+- input_set_abs_params(input_dev,
++ if (features->touch_max) {
++ /* touch interface */
++ unsigned int flags = INPUT_MT_POINTER;
++
++ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
++ if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
++ input_set_abs_params(input_dev,
+ ABS_MT_TOUCH_MAJOR,
+ 0, features->x_max, 0, 0);
+- input_set_abs_params(input_dev,
++ input_set_abs_params(input_dev,
+ ABS_MT_TOUCH_MINOR,
+ 0, features->y_max, 0, 0);
++ } else {
++ __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
++ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
++ flags = 0;
++ }
++ input_mt_init_slots(input_dev, features->touch_max, flags);
+ } else {
+- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+- __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+- flags = 0;
++ /* buttons/keys only interface */
++ __clear_bit(ABS_X, input_dev->absbit);
++ __clear_bit(ABS_Y, input_dev->absbit);
++ __clear_bit(BTN_TOUCH, input_dev->keybit);
+ }
+- input_mt_init_slots(input_dev, features->touch_max, flags);
+ } else if (features->device_type == BTN_TOOL_PEN) {
++ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+@@ -2200,6 +2217,17 @@ static const struct wacom_features wacom
+ static const struct wacom_features wacom_features_0x301 =
+ { "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
++static const struct wacom_features wacom_features_0x302 =
++ { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023,
++ 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
++ .touch_max = 16 };
++static const struct wacom_features wacom_features_0x303 =
++ { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023,
++ 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
++ .touch_max = 16 };
++static const struct wacom_features wacom_features_0x30E =
++ { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023,
++ 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ static const struct wacom_features wacom_features_0x6004 =
+ { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
+ 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+@@ -2337,6 +2365,9 @@ const struct usb_device_id wacom_ids[] =
+ { USB_DEVICE_WACOM(0x10F) },
+ { USB_DEVICE_WACOM(0x300) },
+ { USB_DEVICE_WACOM(0x301) },
++ { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) },
++ { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) },
++ { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x304) },
+ { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
+--- a/drivers/input/tablet/wacom_wac.h
++++ b/drivers/input/tablet/wacom_wac.h
+@@ -54,6 +54,7 @@
+ #define WACOM_REPORT_TPCST 16
+ #define WACOM_REPORT_TPC1FGE 18
+ #define WACOM_REPORT_24HDT 1
++#define WACOM_REPORT_WL 128
+
+ /* device quirks */
+ #define WACOM_QUIRK_MULTI_INPUT 0x0001
+@@ -81,6 +82,7 @@ enum {
+ INTUOSPS,
+ INTUOSPM,
+ INTUOSPL,
++ INTUOSHT,
+ WACOM_21UX2,
+ WACOM_22HD,
+ DTK,
--- /dev/null
+From 1d0d6df02750b4a6f466768cbfbf860e24f4c8d4 Mon Sep 17 00:00:00 2001
+From: Ping Cheng <pinglinux@gmail.com>
+Date: Mon, 25 Nov 2013 18:43:45 -0800
+Subject: Input: wacom - make sure touch_max is set for touch devices
+
+From: Ping Cheng <pinglinux@gmail.com>
+
+commit 1d0d6df02750b4a6f466768cbfbf860e24f4c8d4 upstream.
+
+Old single touch Tablet PCs do not have touch_max set at
+wacom_features. Since touch device at lease supports one
+finger, assign touch_max to 1 when touch usage is defined
+in its HID Descriptor and touch_max is not pre-defined.
+
+Tested-by: Jason Gerecke <killertofu@gmail.com>
+Signed-off-by: Ping Cheng <pingc@wacom.com>
+Reviewed-by: Chris Bagwell <chris@cnpbagwell.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/tablet/wacom_sys.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/input/tablet/wacom_sys.c
++++ b/drivers/input/tablet/wacom_sys.c
+@@ -304,7 +304,7 @@ static int wacom_parse_hid(struct usb_in
+ struct usb_device *dev = interface_to_usbdev(intf);
+ char limit = 0;
+ /* result has to be defined as int for some devices */
+- int result = 0;
++ int result = 0, touch_max = 0;
+ int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+ unsigned char *report;
+
+@@ -351,7 +351,8 @@ static int wacom_parse_hid(struct usb_in
+ if (usage == WCM_DESKTOP) {
+ if (finger) {
+ features->device_type = BTN_TOOL_FINGER;
+-
++ /* touch device at least supports one touch point */
++ touch_max = 1;
+ switch (features->type) {
+ case TABLETPC2FG:
+ features->pktlen = WACOM_PKGLEN_TPC2FG;
+@@ -504,6 +505,8 @@ static int wacom_parse_hid(struct usb_in
+ }
+
+ out:
++ if (!features->touch_max && touch_max)
++ features->touch_max = touch_max;
+ result = 0;
+ kfree(report);
+ return result;
--- /dev/null
+From 989c6b34f6a9480e397b170cc62237e89bf4fdb9 Mon Sep 17 00:00:00 2001
+From: Marcelo Tosatti <mtosatti@redhat.com>
+Date: Thu, 19 Dec 2013 15:28:51 -0200
+Subject: KVM: MMU: handle invalid root_hpa at __direct_map
+
+From: Marcelo Tosatti <mtosatti@redhat.com>
+
+commit 989c6b34f6a9480e397b170cc62237e89bf4fdb9 upstream.
+
+It is possible for __direct_map to be called on invalid root_hpa
+(-1), two examples:
+
+1) try_async_pf -> can_do_async_pf
+ -> vmx_interrupt_allowed -> nested_vmx_vmexit
+2) vmx_handle_exit -> vmx_interrupt_allowed -> nested_vmx_vmexit
+
+Then to load_vmcs12_host_state and kvm_mmu_reset_context.
+
+Check for this possibility, let fault exception be regenerated.
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=924916
+
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/mmu.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/x86/kvm/mmu.c
++++ b/arch/x86/kvm/mmu.c
+@@ -2659,6 +2659,9 @@ static int __direct_map(struct kvm_vcpu
+ int emulate = 0;
+ gfn_t pseudo_gfn;
+
++ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
++ return 0;
++
+ for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
+ if (iterator.level == level) {
+ mmu_set_spte(vcpu, iterator.sptep, ACC_ALL,
--- /dev/null
+From 26a865f4aa8e66a6d94958de7656f7f1b03c6c56 Mon Sep 17 00:00:00 2001
+From: Marcelo Tosatti <mtosatti@redhat.com>
+Date: Fri, 3 Jan 2014 17:00:51 -0200
+Subject: KVM: VMX: fix use after free of vmx->loaded_vmcs
+
+From: Marcelo Tosatti <mtosatti@redhat.com>
+
+commit 26a865f4aa8e66a6d94958de7656f7f1b03c6c56 upstream.
+
+After free_loaded_vmcs executes, the "loaded_vmcs" structure
+is kfreed, and now vmx->loaded_vmcs points to a kfreed area.
+Subsequent free_loaded_vmcs then attempts to manipulate
+vmx->loaded_vmcs.
+
+Switch the order to avoid the problem.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1047892
+
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/vmx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -7332,8 +7332,8 @@ static void vmx_free_vcpu(struct kvm_vcp
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ free_vpid(vmx);
+- free_nested(vmx);
+ free_loaded_vmcs(vmx->loaded_vmcs);
++ free_nested(vmx);
+ kfree(vmx->guest_msrs);
+ kvm_vcpu_uninit(vcpu);
+ kmem_cache_free(kvm_vcpu_cache, vmx);
--- /dev/null
+From 37f6a4e237303549c8676dfe1fd1991ceab512eb Mon Sep 17 00:00:00 2001
+From: Marcelo Tosatti <mtosatti@redhat.com>
+Date: Fri, 3 Jan 2014 17:09:32 -0200
+Subject: KVM: x86: handle invalid root_hpa everywhere
+
+From: Marcelo Tosatti <mtosatti@redhat.com>
+
+commit 37f6a4e237303549c8676dfe1fd1991ceab512eb upstream.
+
+Rom Freiman <rom@stratoscale.com> notes other code paths vulnerable to
+bug fixed by 989c6b34f6a9480e397b.
+
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/mmu.c | 9 +++++++++
+ arch/x86/kvm/paging_tmpl.h | 8 ++++++++
+ 2 files changed, 17 insertions(+)
+
+--- a/arch/x86/kvm/mmu.c
++++ b/arch/x86/kvm/mmu.c
+@@ -2832,6 +2832,9 @@ static bool fast_page_fault(struct kvm_v
+ bool ret = false;
+ u64 spte = 0ull;
+
++ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
++ return false;
++
+ if (!page_fault_can_be_fast(error_code))
+ return false;
+
+@@ -3227,6 +3230,9 @@ static u64 walk_shadow_page_get_mmio_spt
+ struct kvm_shadow_walk_iterator iterator;
+ u64 spte = 0ull;
+
++ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
++ return spte;
++
+ walk_shadow_page_lockless_begin(vcpu);
+ for_each_shadow_entry_lockless(vcpu, addr, iterator, spte)
+ if (!is_shadow_present_pte(spte))
+@@ -4513,6 +4519,9 @@ int kvm_mmu_get_spte_hierarchy(struct kv
+ u64 spte;
+ int nr_sptes = 0;
+
++ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
++ return nr_sptes;
++
+ walk_shadow_page_lockless_begin(vcpu);
+ for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
+ sptes[iterator.level-1] = spte;
+--- a/arch/x86/kvm/paging_tmpl.h
++++ b/arch/x86/kvm/paging_tmpl.h
+@@ -569,6 +569,9 @@ static int FNAME(fetch)(struct kvm_vcpu
+ if (FNAME(gpte_changed)(vcpu, gw, top_level))
+ goto out_gpte_changed;
+
++ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
++ goto out_gpte_changed;
++
+ for (shadow_walk_init(&it, vcpu, addr);
+ shadow_walk_okay(&it) && it.level > gw->level;
+ shadow_walk_next(&it)) {
+@@ -820,6 +823,11 @@ static void FNAME(invlpg)(struct kvm_vcp
+ */
+ mmu_topup_memory_caches(vcpu);
+
++ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) {
++ WARN_ON(1);
++ return;
++ }
++
+ spin_lock(&vcpu->kvm->mmu_lock);
+ for_each_shadow_entry(vcpu, gva, iterator) {
+ level = iterator.level;
--- /dev/null
+From 7e4e7867b1e551b7b8f326da3604c47332972bc6 Mon Sep 17 00:00:00 2001
+From: Gavin Shan <shangw@linux.vnet.ibm.com>
+Date: Wed, 15 Jan 2014 13:16:11 +0800
+Subject: powerpc/eeh: Handle multiple EEH errors
+
+From: Gavin Shan <shangw@linux.vnet.ibm.com>
+
+commit 7e4e7867b1e551b7b8f326da3604c47332972bc6 upstream.
+
+For one PCI error relevant OPAL event, we possibly have multiple
+EEH errors for that. For example, multiple frozen PEs detected on
+different PHBs. Unfortunately, we didn't cover the case. The patch
+enumarates the return value from eeh_ops::next_error() and change
+eeh_handle_special_event() and eeh_ops::next_error() to handle all
+existing EEH errors.
+
+As Ben pointed out, we needn't list_for_each_entry_safe() since we
+are not deleting any PHB from the hose_list and the EEH serialized
+lock should be held while purging EEH events. The patch covers those
+suggestions as well.
+
+Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/eeh.h | 10 ++
+ arch/powerpc/kernel/eeh_driver.c | 150 +++++++++++++++---------------
+ arch/powerpc/platforms/powernv/eeh-ioda.c | 39 ++++---
+ 3 files changed, 112 insertions(+), 87 deletions(-)
+
+--- a/arch/powerpc/include/asm/eeh.h
++++ b/arch/powerpc/include/asm/eeh.h
+@@ -117,6 +117,16 @@ static inline struct pci_dev *eeh_dev_to
+ return edev ? edev->pdev : NULL;
+ }
+
++/* Return values from eeh_ops::next_error */
++enum {
++ EEH_NEXT_ERR_NONE = 0,
++ EEH_NEXT_ERR_INF,
++ EEH_NEXT_ERR_FROZEN_PE,
++ EEH_NEXT_ERR_FENCED_PHB,
++ EEH_NEXT_ERR_DEAD_PHB,
++ EEH_NEXT_ERR_DEAD_IOC
++};
++
+ /*
+ * The struct is used to trace the registered EEH operation
+ * callback functions. Actually, those operation callback
+--- a/arch/powerpc/kernel/eeh_driver.c
++++ b/arch/powerpc/kernel/eeh_driver.c
+@@ -626,84 +626,90 @@ static void eeh_handle_special_event(voi
+ {
+ struct eeh_pe *pe, *phb_pe;
+ struct pci_bus *bus;
+- struct pci_controller *hose, *tmp;
++ struct pci_controller *hose;
+ unsigned long flags;
+- int rc = 0;
++ int rc;
+
+- /*
+- * The return value from next_error() has been classified as follows.
+- * It might be good to enumerate them. However, next_error() is only
+- * supported by PowerNV platform for now. So it would be fine to use
+- * integer directly:
+- *
+- * 4 - Dead IOC 3 - Dead PHB
+- * 2 - Fenced PHB 1 - Frozen PE
+- * 0 - No error found
+- *
+- */
+- rc = eeh_ops->next_error(&pe);
+- if (rc <= 0)
+- return;
+-
+- switch (rc) {
+- case 4:
+- /* Mark all PHBs in dead state */
+- eeh_serialize_lock(&flags);
+- list_for_each_entry_safe(hose, tmp,
+- &hose_list, list_node) {
+- phb_pe = eeh_phb_pe_get(hose);
+- if (!phb_pe) continue;
+
+- eeh_pe_state_mark(phb_pe,
+- EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
++ do {
++ rc = eeh_ops->next_error(&pe);
++
++ switch (rc) {
++ case EEH_NEXT_ERR_DEAD_IOC:
++ /* Mark all PHBs in dead state */
++ eeh_serialize_lock(&flags);
++
++ /* Purge all events */
++ eeh_remove_event(NULL);
++
++ list_for_each_entry(hose, &hose_list, list_node) {
++ phb_pe = eeh_phb_pe_get(hose);
++ if (!phb_pe) continue;
++
++ eeh_pe_state_mark(phb_pe,
++ EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
++ }
++
++ eeh_serialize_unlock(flags);
++
++ break;
++ case EEH_NEXT_ERR_FROZEN_PE:
++ case EEH_NEXT_ERR_FENCED_PHB:
++ case EEH_NEXT_ERR_DEAD_PHB:
++ /* Mark the PE in fenced state */
++ eeh_serialize_lock(&flags);
++
++ /* Purge all events of the PHB */
++ eeh_remove_event(pe);
++
++ if (rc == EEH_NEXT_ERR_DEAD_PHB)
++ eeh_pe_state_mark(pe,
++ EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
++ else
++ eeh_pe_state_mark(pe,
++ EEH_PE_ISOLATED | EEH_PE_RECOVERING);
++
++ eeh_serialize_unlock(flags);
++
++ break;
++ case EEH_NEXT_ERR_NONE:
++ return;
++ default:
++ pr_warn("%s: Invalid value %d from next_error()\n",
++ __func__, rc);
++ return;
+ }
+- eeh_serialize_unlock(flags);
+
+- /* Purge all events */
+- eeh_remove_event(NULL);
+- break;
+- case 3:
+- case 2:
+- case 1:
+- /* Mark the PE in fenced state */
+- eeh_serialize_lock(&flags);
+- if (rc == 3)
+- eeh_pe_state_mark(pe,
+- EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+- else
+- eeh_pe_state_mark(pe,
+- EEH_PE_ISOLATED | EEH_PE_RECOVERING);
+- eeh_serialize_unlock(flags);
+-
+- /* Purge all events of the PHB */
+- eeh_remove_event(pe);
+- break;
+- default:
+- pr_err("%s: Invalid value %d from next_error()\n",
+- __func__, rc);
+- return;
+- }
+-
+- /*
+- * For fenced PHB and frozen PE, it's handled as normal
+- * event. We have to remove the affected PHBs for dead
+- * PHB and IOC
+- */
+- if (rc == 2 || rc == 1)
+- eeh_handle_normal_event(pe);
+- else {
+- list_for_each_entry_safe(hose, tmp,
+- &hose_list, list_node) {
+- phb_pe = eeh_phb_pe_get(hose);
+- if (!phb_pe || !(phb_pe->state & EEH_PE_PHB_DEAD))
+- continue;
+-
+- bus = eeh_pe_bus_get(phb_pe);
+- /* Notify all devices that they're about to go down. */
+- eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
+- pcibios_remove_pci_devices(bus);
++ /*
++ * For fenced PHB and frozen PE, it's handled as normal
++ * event. We have to remove the affected PHBs for dead
++ * PHB and IOC
++ */
++ if (rc == EEH_NEXT_ERR_FROZEN_PE ||
++ rc == EEH_NEXT_ERR_FENCED_PHB) {
++ eeh_handle_normal_event(pe);
++ } else {
++ list_for_each_entry(hose, &hose_list, list_node) {
++ phb_pe = eeh_phb_pe_get(hose);
++ if (!phb_pe ||
++ !(phb_pe->state & EEH_PE_PHB_DEAD))
++ continue;
++
++ /* Notify all devices to be down */
++ bus = eeh_pe_bus_get(phb_pe);
++ eeh_pe_dev_traverse(pe,
++ eeh_report_failure, NULL);
++ pcibios_remove_pci_devices(bus);
++ }
+ }
+- }
++
++ /*
++ * If we have detected dead IOC, we needn't proceed
++ * any more since all PHBs would have been removed
++ */
++ if (rc == EEH_NEXT_ERR_DEAD_IOC)
++ break;
++ } while (rc != EEH_NEXT_ERR_NONE);
+ }
+
+ /**
+--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
++++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
+@@ -718,12 +718,12 @@ static int ioda_eeh_get_pe(struct pci_co
+ */
+ static int ioda_eeh_next_error(struct eeh_pe **pe)
+ {
+- struct pci_controller *hose, *tmp;
++ struct pci_controller *hose;
+ struct pnv_phb *phb;
+ u64 frozen_pe_no;
+ u16 err_type, severity;
+ long rc;
+- int ret = 1;
++ int ret = EEH_NEXT_ERR_NONE;
+
+ /*
+ * While running here, it's safe to purge the event queue.
+@@ -733,7 +733,7 @@ static int ioda_eeh_next_error(struct ee
+ eeh_remove_event(NULL);
+ opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
+
+- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
++ list_for_each_entry(hose, &hose_list, list_node) {
+ /*
+ * If the subordinate PCI buses of the PHB has been
+ * removed, we needn't take care of it any more.
+@@ -772,19 +772,19 @@ static int ioda_eeh_next_error(struct ee
+ switch (err_type) {
+ case OPAL_EEH_IOC_ERROR:
+ if (severity == OPAL_EEH_SEV_IOC_DEAD) {
+- list_for_each_entry_safe(hose, tmp,
+- &hose_list, list_node) {
++ list_for_each_entry(hose, &hose_list,
++ list_node) {
+ phb = hose->private_data;
+ phb->eeh_state |= PNV_EEH_STATE_REMOVED;
+ }
+
+ pr_err("EEH: dead IOC detected\n");
+- ret = 4;
+- goto out;
++ ret = EEH_NEXT_ERR_DEAD_IOC;
+ } else if (severity == OPAL_EEH_SEV_INF) {
+ pr_info("EEH: IOC informative error "
+ "detected\n");
+ ioda_eeh_hub_diag(hose);
++ ret = EEH_NEXT_ERR_NONE;
+ }
+
+ break;
+@@ -796,21 +796,20 @@ static int ioda_eeh_next_error(struct ee
+ pr_err("EEH: dead PHB#%x detected\n",
+ hose->global_number);
+ phb->eeh_state |= PNV_EEH_STATE_REMOVED;
+- ret = 3;
+- goto out;
++ ret = EEH_NEXT_ERR_DEAD_PHB;
+ } else if (severity == OPAL_EEH_SEV_PHB_FENCED) {
+ if (ioda_eeh_get_phb_pe(hose, pe))
+ break;
+
+ pr_err("EEH: fenced PHB#%x detected\n",
+ hose->global_number);
+- ret = 2;
+- goto out;
++ ret = EEH_NEXT_ERR_FENCED_PHB;
+ } else if (severity == OPAL_EEH_SEV_INF) {
+ pr_info("EEH: PHB#%x informative error "
+ "detected\n",
+ hose->global_number);
+ ioda_eeh_phb_diag(hose);
++ ret = EEH_NEXT_ERR_NONE;
+ }
+
+ break;
+@@ -820,13 +819,23 @@ static int ioda_eeh_next_error(struct ee
+
+ pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
+ (*pe)->addr, (*pe)->phb->global_number);
+- ret = 1;
+- goto out;
++ ret = EEH_NEXT_ERR_FROZEN_PE;
++ break;
++ default:
++ pr_warn("%s: Unexpected error type %d\n",
++ __func__, err_type);
+ }
++
++ /*
++ * If we have no errors on the specific PHB or only
++ * informative error there, we continue poking it.
++ * Otherwise, we need actions to be taken by upper
++ * layer.
++ */
++ if (ret > EEH_NEXT_ERR_INF)
++ break;
+ }
+
+- ret = 0;
+-out:
+ return ret;
+ }
+
--- /dev/null
+From 947166043732b69878123bf31f51933ad0316080 Mon Sep 17 00:00:00 2001
+From: Gavin Shan <shangw@linux.vnet.ibm.com>
+Date: Tue, 25 Feb 2014 15:28:37 +0800
+Subject: powerpc/powernv: Dump PHB diag-data immediately
+
+From: Gavin Shan <shangw@linux.vnet.ibm.com>
+
+commit 947166043732b69878123bf31f51933ad0316080 upstream.
+
+The PHB diag-data is important to help locating the root cause for
+EEH errors such as frozen PE or fenced PHB. However, the EEH core
+enables IO path by clearing part of HW registers before collecting
+this data causing it to be corrupted.
+
+This patch fixes this by dumping the PHB diag-data immediately when
+frozen/fenced state on PE or PHB is detected for the first time in
+eeh_ops::get_state() or next_error() backend.
+
+Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
+CC: <stable@vger.kernel.org>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/platforms/powernv/eeh-ioda.c | 99 +++++++++++++-----------------
+ 1 file changed, 43 insertions(+), 56 deletions(-)
+
+--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
++++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
+@@ -114,6 +114,7 @@ DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_db
+ ioda_eeh_inbB_dbgfs_set, "0x%llx\n");
+ #endif /* CONFIG_DEBUG_FS */
+
++
+ /**
+ * ioda_eeh_post_init - Chip dependent post initialization
+ * @hose: PCI controller
+@@ -221,6 +222,22 @@ static int ioda_eeh_set_option(struct ee
+ return ret;
+ }
+
++static void ioda_eeh_phb_diag(struct pci_controller *hose)
++{
++ struct pnv_phb *phb = hose->private_data;
++ long rc;
++
++ rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
++ PNV_PCI_DIAG_BUF_SIZE);
++ if (rc != OPAL_SUCCESS) {
++ pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
++ __func__, hose->global_number, rc);
++ return;
++ }
++
++ pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
++}
++
+ /**
+ * ioda_eeh_get_state - Retrieve the state of PE
+ * @pe: EEH PE
+@@ -272,6 +289,9 @@ static int ioda_eeh_get_state(struct eeh
+ result |= EEH_STATE_DMA_ACTIVE;
+ result |= EEH_STATE_MMIO_ENABLED;
+ result |= EEH_STATE_DMA_ENABLED;
++ } else if (!(pe->state & EEH_PE_ISOLATED)) {
++ eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
++ ioda_eeh_phb_diag(hose);
+ }
+
+ return result;
+@@ -315,6 +335,15 @@ static int ioda_eeh_get_state(struct eeh
+ __func__, fstate, hose->global_number, pe_no);
+ }
+
++ /* Dump PHB diag-data for frozen PE */
++ if (result != EEH_STATE_NOT_SUPPORT &&
++ (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) !=
++ (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
++ !(pe->state & EEH_PE_ISOLATED)) {
++ eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
++ ioda_eeh_phb_diag(hose);
++ }
++
+ return result;
+ }
+
+@@ -530,45 +559,6 @@ static int ioda_eeh_reset(struct eeh_pe
+ }
+
+ /**
+- * ioda_eeh_get_log - Retrieve error log
+- * @pe: EEH PE
+- * @severity: Severity level of the log
+- * @drv_log: buffer to store the log
+- * @len: space of the log buffer
+- *
+- * The function is used to retrieve error log from P7IOC.
+- */
+-static int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
+- char *drv_log, unsigned long len)
+-{
+- s64 ret;
+- unsigned long flags;
+- struct pci_controller *hose = pe->phb;
+- struct pnv_phb *phb = hose->private_data;
+-
+- spin_lock_irqsave(&phb->lock, flags);
+-
+- ret = opal_pci_get_phb_diag_data2(phb->opal_id,
+- phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
+- if (ret) {
+- spin_unlock_irqrestore(&phb->lock, flags);
+- pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n",
+- __func__, hose->global_number, pe->addr, ret);
+- return -EIO;
+- }
+-
+- /*
+- * FIXME: We probably need log the error in somewhere.
+- * Lets make it up in future.
+- */
+- /* pr_info("%s", phb->diag.blob); */
+-
+- spin_unlock_irqrestore(&phb->lock, flags);
+-
+- return 0;
+-}
+-
+-/**
+ * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
+ * @pe: EEH PE
+ *
+@@ -649,22 +639,6 @@ static void ioda_eeh_hub_diag(struct pci
+ }
+ }
+
+-static void ioda_eeh_phb_diag(struct pci_controller *hose)
+-{
+- struct pnv_phb *phb = hose->private_data;
+- long rc;
+-
+- rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+- PNV_PCI_DIAG_BUF_SIZE);
+- if (rc != OPAL_SUCCESS) {
+- pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
+- __func__, hose->global_number, rc);
+- return;
+- }
+-
+- pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+-}
+-
+ static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
+ struct eeh_pe **pe)
+ {
+@@ -827,6 +801,20 @@ static int ioda_eeh_next_error(struct ee
+ }
+
+ /*
++ * EEH core will try recover from fenced PHB or
++ * frozen PE. In the time for frozen PE, EEH core
++ * enable IO path for that before collecting logs,
++ * but it ruins the site. So we have to dump the
++ * log in advance here.
++ */
++ if ((ret == EEH_NEXT_ERR_FROZEN_PE ||
++ ret == EEH_NEXT_ERR_FENCED_PHB) &&
++ !((*pe)->state & EEH_PE_ISOLATED)) {
++ eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
++ ioda_eeh_phb_diag(hose);
++ }
++
++ /*
+ * If we have no errors on the specific PHB or only
+ * informative error there, we continue poking it.
+ * Otherwise, we need actions to be taken by upper
+@@ -844,7 +832,6 @@ struct pnv_eeh_ops ioda_eeh_ops = {
+ .set_option = ioda_eeh_set_option,
+ .get_state = ioda_eeh_get_state,
+ .reset = ioda_eeh_reset,
+- .get_log = ioda_eeh_get_log,
+ .configure_bridge = ioda_eeh_configure_bridge,
+ .next_error = ioda_eeh_next_error
+ };
--- /dev/null
+From af87d2fe95444d107e0c0cf0ba7e20e6716a7bfd Mon Sep 17 00:00:00 2001
+From: Gavin Shan <shangw@linux.vnet.ibm.com>
+Date: Tue, 25 Feb 2014 15:28:38 +0800
+Subject: powerpc/powernv: Refactor PHB diag-data dump
+
+From: Gavin Shan <shangw@linux.vnet.ibm.com>
+
+commit af87d2fe95444d107e0c0cf0ba7e20e6716a7bfd upstream.
+
+As Ben suggested, the patch prints PHB diag-data with multiple
+fields in one line and omits the line if the fields of that
+line are all zero.
+
+With the patch applied, the PHB3 diag-data dump looks like:
+
+PHB3 PHB#3 Diag-data (Version: 1)
+
+ brdgCtl: 00000002
+ RootSts: 0000000f 00400000 b0830008 00100147 00002000
+ nFir: 0000000000000000 0030006e00000000 0000000000000000
+ PhbSts: 0000001c00000000 0000000000000000
+ Lem: 0000000000100000 42498e327f502eae 0000000000000000
+ InAErr: 8000000000000000 8000000000000000 0402030000000000 0000000000000000
+ PE[ 8] A/B: 8480002b00000000 8000000000000000
+
+[ The current diag data is so big that it overflows the printk
+ buffer pretty quickly in cases when we get a handful of errors
+ at once which can happen. --BenH
+]
+
+Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/platforms/powernv/pci.c | 220 +++++++++++++++++++----------------
+ 1 file changed, 125 insertions(+), 95 deletions(-)
+
+--- a/arch/powerpc/platforms/powernv/pci.c
++++ b/arch/powerpc/platforms/powernv/pci.c
+@@ -134,57 +134,72 @@ static void pnv_pci_dump_p7ioc_diag_data
+ pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
+ hose->global_number, common->version);
+
+- pr_info(" brdgCtl: %08x\n", data->brdgCtl);
+-
+- pr_info(" portStatusReg: %08x\n", data->portStatusReg);
+- pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus);
+- pr_info(" busAgentStatus: %08x\n", data->busAgentStatus);
+-
+- pr_info(" deviceStatus: %08x\n", data->deviceStatus);
+- pr_info(" slotStatus: %08x\n", data->slotStatus);
+- pr_info(" linkStatus: %08x\n", data->linkStatus);
+- pr_info(" devCmdStatus: %08x\n", data->devCmdStatus);
+- pr_info(" devSecStatus: %08x\n", data->devSecStatus);
+-
+- pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus);
+- pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus);
+- pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus);
+- pr_info(" tlpHdr1: %08x\n", data->tlpHdr1);
+- pr_info(" tlpHdr2: %08x\n", data->tlpHdr2);
+- pr_info(" tlpHdr3: %08x\n", data->tlpHdr3);
+- pr_info(" tlpHdr4: %08x\n", data->tlpHdr4);
+- pr_info(" sourceId: %08x\n", data->sourceId);
+- pr_info(" errorClass: %016llx\n", data->errorClass);
+- pr_info(" correlator: %016llx\n", data->correlator);
+- pr_info(" p7iocPlssr: %016llx\n", data->p7iocPlssr);
+- pr_info(" p7iocCsr: %016llx\n", data->p7iocCsr);
+- pr_info(" lemFir: %016llx\n", data->lemFir);
+- pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask);
+- pr_info(" lemWOF: %016llx\n", data->lemWOF);
+- pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus);
+- pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus);
+- pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0);
+- pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1);
+- pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus);
+- pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
+- pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0);
+- pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1);
+- pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus);
+- pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
+- pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0);
+- pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1);
+- pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus);
+- pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
+- pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0);
+- pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1);
++ if (data->brdgCtl)
++ pr_info(" brdgCtl: %08x\n",
++ data->brdgCtl);
++ if (data->portStatusReg || data->rootCmplxStatus ||
++ data->busAgentStatus)
++ pr_info(" UtlSts: %08x %08x %08x\n",
++ data->portStatusReg, data->rootCmplxStatus,
++ data->busAgentStatus);
++ if (data->deviceStatus || data->slotStatus ||
++ data->linkStatus || data->devCmdStatus ||
++ data->devSecStatus)
++ pr_info(" RootSts: %08x %08x %08x %08x %08x\n",
++ data->deviceStatus, data->slotStatus,
++ data->linkStatus, data->devCmdStatus,
++ data->devSecStatus);
++ if (data->rootErrorStatus || data->uncorrErrorStatus ||
++ data->corrErrorStatus)
++ pr_info(" RootErrSts: %08x %08x %08x\n",
++ data->rootErrorStatus, data->uncorrErrorStatus,
++ data->corrErrorStatus);
++ if (data->tlpHdr1 || data->tlpHdr2 ||
++ data->tlpHdr3 || data->tlpHdr4)
++ pr_info(" RootErrLog: %08x %08x %08x %08x\n",
++ data->tlpHdr1, data->tlpHdr2,
++ data->tlpHdr3, data->tlpHdr4);
++ if (data->sourceId || data->errorClass ||
++ data->correlator)
++ pr_info(" RootErrLog1: %08x %016llx %016llx\n",
++ data->sourceId, data->errorClass,
++ data->correlator);
++ if (data->p7iocPlssr || data->p7iocCsr)
++ pr_info(" PhbSts: %016llx %016llx\n",
++ data->p7iocPlssr, data->p7iocCsr);
++ if (data->lemFir || data->lemErrorMask ||
++ data->lemWOF)
++ pr_info(" Lem: %016llx %016llx %016llx\n",
++ data->lemFir, data->lemErrorMask,
++ data->lemWOF);
++ if (data->phbErrorStatus || data->phbFirstErrorStatus ||
++ data->phbErrorLog0 || data->phbErrorLog1)
++ pr_info(" PhbErr: %016llx %016llx %016llx %016llx\n",
++ data->phbErrorStatus, data->phbFirstErrorStatus,
++ data->phbErrorLog0, data->phbErrorLog1);
++ if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
++ data->mmioErrorLog0 || data->mmioErrorLog1)
++ pr_info(" OutErr: %016llx %016llx %016llx %016llx\n",
++ data->mmioErrorStatus, data->mmioFirstErrorStatus,
++ data->mmioErrorLog0, data->mmioErrorLog1);
++ if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
++ data->dma0ErrorLog0 || data->dma0ErrorLog1)
++ pr_info(" InAErr: %016llx %016llx %016llx %016llx\n",
++ data->dma0ErrorStatus, data->dma0FirstErrorStatus,
++ data->dma0ErrorLog0, data->dma0ErrorLog1);
++ if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
++ data->dma1ErrorLog0 || data->dma1ErrorLog1)
++ pr_info(" InBErr: %016llx %016llx %016llx %016llx\n",
++ data->dma1ErrorStatus, data->dma1FirstErrorStatus,
++ data->dma1ErrorLog0, data->dma1ErrorLog1);
+
+ for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
+ if ((data->pestA[i] >> 63) == 0 &&
+ (data->pestB[i] >> 63) == 0)
+ continue;
+
+- pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]);
+- pr_info(" PESTB: %016llx\n", data->pestB[i]);
++ pr_info(" PE[%3d] A/B: %016llx %016llx\n",
++ i, data->pestA[i], data->pestB[i]);
+ }
+ }
+
+@@ -197,62 +212,77 @@ static void pnv_pci_dump_phb3_diag_data(
+ data = (struct OpalIoPhb3ErrorData*)common;
+ pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n",
+ hose->global_number, common->version);
+-
+- pr_info(" brdgCtl: %08x\n", data->brdgCtl);
+-
+- pr_info(" portStatusReg: %08x\n", data->portStatusReg);
+- pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus);
+- pr_info(" busAgentStatus: %08x\n", data->busAgentStatus);
+-
+- pr_info(" deviceStatus: %08x\n", data->deviceStatus);
+- pr_info(" slotStatus: %08x\n", data->slotStatus);
+- pr_info(" linkStatus: %08x\n", data->linkStatus);
+- pr_info(" devCmdStatus: %08x\n", data->devCmdStatus);
+- pr_info(" devSecStatus: %08x\n", data->devSecStatus);
+-
+- pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus);
+- pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus);
+- pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus);
+- pr_info(" tlpHdr1: %08x\n", data->tlpHdr1);
+- pr_info(" tlpHdr2: %08x\n", data->tlpHdr2);
+- pr_info(" tlpHdr3: %08x\n", data->tlpHdr3);
+- pr_info(" tlpHdr4: %08x\n", data->tlpHdr4);
+- pr_info(" sourceId: %08x\n", data->sourceId);
+- pr_info(" errorClass: %016llx\n", data->errorClass);
+- pr_info(" correlator: %016llx\n", data->correlator);
+-
+- pr_info(" nFir: %016llx\n", data->nFir);
+- pr_info(" nFirMask: %016llx\n", data->nFirMask);
+- pr_info(" nFirWOF: %016llx\n", data->nFirWOF);
+- pr_info(" PhbPlssr: %016llx\n", data->phbPlssr);
+- pr_info(" PhbCsr: %016llx\n", data->phbCsr);
+- pr_info(" lemFir: %016llx\n", data->lemFir);
+- pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask);
+- pr_info(" lemWOF: %016llx\n", data->lemWOF);
+- pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus);
+- pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus);
+- pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0);
+- pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1);
+- pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus);
+- pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
+- pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0);
+- pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1);
+- pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus);
+- pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
+- pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0);
+- pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1);
+- pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus);
+- pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
+- pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0);
+- pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1);
++ if (data->brdgCtl)
++ pr_info(" brdgCtl: %08x\n",
++ data->brdgCtl);
++ if (data->portStatusReg || data->rootCmplxStatus ||
++ data->busAgentStatus)
++ pr_info(" UtlSts: %08x %08x %08x\n",
++ data->portStatusReg, data->rootCmplxStatus,
++ data->busAgentStatus);
++ if (data->deviceStatus || data->slotStatus ||
++ data->linkStatus || data->devCmdStatus ||
++ data->devSecStatus)
++ pr_info(" RootSts: %08x %08x %08x %08x %08x\n",
++ data->deviceStatus, data->slotStatus,
++ data->linkStatus, data->devCmdStatus,
++ data->devSecStatus);
++ if (data->rootErrorStatus || data->uncorrErrorStatus ||
++ data->corrErrorStatus)
++ pr_info(" RootErrSts: %08x %08x %08x\n",
++ data->rootErrorStatus, data->uncorrErrorStatus,
++ data->corrErrorStatus);
++ if (data->tlpHdr1 || data->tlpHdr2 ||
++ data->tlpHdr3 || data->tlpHdr4)
++ pr_info(" RootErrLog: %08x %08x %08x %08x\n",
++ data->tlpHdr1, data->tlpHdr2,
++ data->tlpHdr3, data->tlpHdr4);
++ if (data->sourceId || data->errorClass ||
++ data->correlator)
++ pr_info(" RootErrLog1: %08x %016llx %016llx\n",
++ data->sourceId, data->errorClass,
++ data->correlator);
++ if (data->nFir || data->nFirMask ||
++ data->nFirWOF)
++ pr_info(" nFir: %016llx %016llx %016llx\n",
++ data->nFir, data->nFirMask,
++ data->nFirWOF);
++ if (data->phbPlssr || data->phbCsr)
++ pr_info(" PhbSts: %016llx %016llx\n",
++ data->phbPlssr, data->phbCsr);
++ if (data->lemFir || data->lemErrorMask ||
++ data->lemWOF)
++ pr_info(" Lem: %016llx %016llx %016llx\n",
++ data->lemFir, data->lemErrorMask,
++ data->lemWOF);
++ if (data->phbErrorStatus || data->phbFirstErrorStatus ||
++ data->phbErrorLog0 || data->phbErrorLog1)
++ pr_info(" PhbErr: %016llx %016llx %016llx %016llx\n",
++ data->phbErrorStatus, data->phbFirstErrorStatus,
++ data->phbErrorLog0, data->phbErrorLog1);
++ if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
++ data->mmioErrorLog0 || data->mmioErrorLog1)
++ pr_info(" OutErr: %016llx %016llx %016llx %016llx\n",
++ data->mmioErrorStatus, data->mmioFirstErrorStatus,
++ data->mmioErrorLog0, data->mmioErrorLog1);
++ if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
++ data->dma0ErrorLog0 || data->dma0ErrorLog1)
++ pr_info(" InAErr: %016llx %016llx %016llx %016llx\n",
++ data->dma0ErrorStatus, data->dma0FirstErrorStatus,
++ data->dma0ErrorLog0, data->dma0ErrorLog1);
++ if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
++ data->dma1ErrorLog0 || data->dma1ErrorLog1)
++ pr_info(" InBErr: %016llx %016llx %016llx %016llx\n",
++ data->dma1ErrorStatus, data->dma1FirstErrorStatus,
++ data->dma1ErrorLog0, data->dma1ErrorLog1);
+
+ for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
+ if ((data->pestA[i] >> 63) == 0 &&
+ (data->pestB[i] >> 63) == 0)
+ continue;
+
+- pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]);
+- pr_info(" PESTB: %016llx\n", data->pestB[i]);
++ pr_info(" PE[%3d] A/B: %016llx %016llx\n",
++ i, data->pestA[i], data->pestB[i]);
+ }
+ }
+
p54-clamp-properly-instead-of-just-truncating.patch
regulator-core-replace-direct-ops-disable-usage.patch
powerpc-powernv-move-phb-diag-dump-functions-around.patch
+powerpc-eeh-handle-multiple-eeh-errors.patch
+powerpc-powernv-dump-phb-diag-data-immediately.patch
+powerpc-powernv-refactor-phb-diag-data-dump.patch
+fs-proc-proc_devtree.c-remove-empty-proc-device-tree-when-no-openfirmware-exists.patch
+input-elantech-improve-clickpad-detection.patch
+kvm-mmu-handle-invalid-root_hpa-at-__direct_map.patch
+kvm-x86-handle-invalid-root_hpa-everywhere.patch
+kvm-vmx-fix-use-after-free-of-vmx-loaded_vmcs.patch
+input-wacom-make-sure-touch_max-is-set-for-touch-devices.patch
+input-wacom-add-support-for-three-new-intuos-devices.patch
+input-wacom-add-reporting-of-sw_mute_device-events.patch