]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'v4.10-rc5' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 24 Jan 2017 20:37:43 +0000 (12:37 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 24 Jan 2017 20:37:43 +0000 (12:37 -0800)
Sync up with mainline to bring up improvements in various subsystems.

1  2 
drivers/input/joystick/xpad.c
drivers/input/keyboard/cros_ec_keyb.c
drivers/input/misc/arizona-haptics.c
drivers/input/misc/tps65218-pwrbutton.c
drivers/input/mouse/trackpoint.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/touchscreen/elants_i2c.c

index c06b717139ad62f7f2d3bdb8e1368127ae7b6510,c7d5b2b643d10798eb7da917f16888a2cff2bc3b..247fd3a6fc035753083792fbfb8a4fc3b04e807e
@@@ -320,18 -320,18 +320,18 @@@ static struct usb_device_id xpad_table[
        XPAD_XBOXONE_VENDOR(0x0738),            /* Mad Catz FightStick TE 2 */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f X-Box 360 controllers */
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f X-Box One controllers */
 +      XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
 +      XPAD_XBOXONE_VENDOR(0x0f0d),            /* Hori Controllers */
        XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x146b),            /* BigBen Interactive Controllers */
 -      XPAD_XBOX360_VENDOR(0x1bad),            /* Harminix Rock Band Guitar and Drums */
 -      XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
 -      XPAD_XBOXONE_VENDOR(0x0f0d),            /* Hori Controllers */
 -      XPAD_XBOX360_VENDOR(0x1689),            /* Razer Onza */
 -      XPAD_XBOX360_VENDOR(0x24c6),            /* PowerA Controllers */
 -      XPAD_XBOXONE_VENDOR(0x24c6),            /* PowerA Controllers */
        XPAD_XBOX360_VENDOR(0x1532),            /* Razer Sabertooth */
        XPAD_XBOX360_VENDOR(0x15e4),            /* Numark X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x162e),            /* Joytech X-Box 360 controllers */
 +      XPAD_XBOX360_VENDOR(0x1689),            /* Razer Onza */
 +      XPAD_XBOX360_VENDOR(0x1bad),            /* Harminix Rock Band Guitar and Drums */
 +      XPAD_XBOX360_VENDOR(0x24c6),            /* PowerA Controllers */
 +      XPAD_XBOXONE_VENDOR(0x24c6),            /* PowerA Controllers */
        { }
  };
  
@@@ -608,28 -608,14 +608,28 @@@ static void xpad360w_process_packet(str
  }
  
  /*
 - *    xpadone_process_buttons
 + *    xpadone_process_packet
 + *
 + *    Completes a request by converting the data into events for the
 + *    input subsystem. This version is for the Xbox One controller.
   *
 - *    Process a button update packet from an Xbox one controller.
 + *    The report format was gleaned from
 + *    https://github.com/kylelemons/xbox/blob/master/xbox.go
   */
 -static void xpadone_process_buttons(struct usb_xpad *xpad,
 -                              struct input_dev *dev,
 -                              unsigned char *data)
 +static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
  {
 +      struct input_dev *dev = xpad->dev;
 +
 +      /* the xbox button has its own special report */
 +      if (data[0] == 0X07) {
 +              input_report_key(dev, BTN_MODE, data[4] & 0x01);
 +              input_sync(dev);
 +              return;
 +      }
 +      /* check invalid packet */
 +      else if (data[0] != 0X20)
 +              return;
 +
        /* menu/view buttons */
        input_report_key(dev, BTN_START,  data[4] & 0x04);
        input_report_key(dev, BTN_SELECT, data[4] & 0x08);
        input_sync(dev);
  }
  
 -/*
 - *    xpadone_process_packet
 - *
 - *    Completes a request by converting the data into events for the
 - *    input subsystem. This version is for the Xbox One controller.
 - *
 - *    The report format was gleaned from
 - *    https://github.com/kylelemons/xbox/blob/master/xbox.go
 - */
 -
 -static void xpadone_process_packet(struct usb_xpad *xpad,
 -                              u16 cmd, unsigned char *data)
 -{
 -      struct input_dev *dev = xpad->dev;
 -
 -      switch (data[0]) {
 -      case 0x20:
 -              xpadone_process_buttons(xpad, dev, data);
 -              break;
 -
 -      case 0x07:
 -              /* the xbox button has its own special report */
 -              input_report_key(dev, BTN_MODE, data[4] & 0x01);
 -              input_sync(dev);
 -              break;
 -      }
 -}
 -
  static void xpad_irq_in(struct urb *urb)
  {
        struct usb_xpad *xpad = urb->context;
@@@ -836,9 -850,10 +836,9 @@@ static void xpad_irq_out(struct urb *ur
        spin_unlock_irqrestore(&xpad->odata_lock, flags);
  }
  
 -static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 +static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
 +                      struct usb_endpoint_descriptor *ep_irq_out)
  {
 -      struct usb_endpoint_descriptor *ep_irq_out;
 -      int ep_irq_out_idx;
        int error;
  
        if (xpad->xtype == XTYPE_UNKNOWN)
  
        xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
                                         GFP_KERNEL, &xpad->odata_dma);
 -      if (!xpad->odata) {
 -              error = -ENOMEM;
 -              goto fail1;
 -      }
 +      if (!xpad->odata)
 +              return -ENOMEM;
  
        spin_lock_init(&xpad->odata_lock);
  
        xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
        if (!xpad->irq_out) {
                error = -ENOMEM;
 -              goto fail2;
 +              goto err_free_coherent;
        }
  
 -      /* Xbox One controller has in/out endpoints swapped. */
 -      ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1;
 -      ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc;
 -
        usb_fill_int_urb(xpad->irq_out, xpad->udev,
                         usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
                         xpad->odata, XPAD_PKT_LEN,
  
        return 0;
  
 - fail2:       usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
 - fail1:       return error;
 +err_free_coherent:
 +      usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
 +      return error;
  }
  
  static void xpad_stop_output(struct usb_xpad *xpad)
@@@ -1357,6 -1377,12 +1357,12 @@@ static int xpad_init_input(struct usb_x
        input_dev->name = xpad->name;
        input_dev->phys = xpad->phys;
        usb_to_input_id(xpad->udev, &input_dev->id);
+       if (xpad->xtype == XTYPE_XBOX360W) {
+               /* x360w controllers and the receiver have different ids */
+               input_dev->id.product = 0x02a1;
+       }
        input_dev->dev.parent = &xpad->intf->dev;
  
        input_set_drvdata(input_dev, xpad);
@@@ -1442,7 -1468,8 +1448,7 @@@ static int xpad_probe(struct usb_interf
  {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_xpad *xpad;
 -      struct usb_endpoint_descriptor *ep_irq_in;
 -      int ep_irq_in_idx;
 +      struct usb_endpoint_descriptor *ep_irq_in, *ep_irq_out;
        int i, error;
  
        if (intf->cur_altsetting->desc.bNumEndpoints != 2)
                goto err_free_in_urb;
        }
  
 -      error = xpad_init_output(intf, xpad);
 -      if (error)
 +      ep_irq_in = ep_irq_out = NULL;
 +
 +      for (i = 0; i < 2; i++) {
 +              struct usb_endpoint_descriptor *ep =
 +                              &intf->cur_altsetting->endpoint[i].desc;
 +
 +              if (usb_endpoint_dir_in(ep))
 +                      ep_irq_in = ep;
 +              else
 +                      ep_irq_out = ep;
 +      }
 +
 +      if (!ep_irq_in || !ep_irq_out) {
 +              error = -ENODEV;
                goto err_free_in_urb;
 +      }
  
 -      /* Xbox One controller has in/out endpoints swapped. */
 -      ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0;
 -      ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc;
 +      error = xpad_init_output(intf, xpad, ep_irq_out);
 +      if (error)
 +              goto err_free_in_urb;
  
        usb_fill_int_urb(xpad->irq_in, udev,
                         usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
index 165c722408aaa37128e9e56ebf88674b0e0ea4f2,25943e9bc8bff96a3df9417c9e7e85d3fa16cbee..87d071ae21da0e04e86dda1f5baae97fccd19d22
@@@ -27,6 -27,7 +27,7 @@@
  #include <linux/input.h>
  #include <linux/interrupt.h>
  #include <linux/kernel.h>
+ #include <linux/notifier.h>
  #include <linux/platform_device.h>
  #include <linux/slab.h>
  #include <linux/input/matrix_keypad.h>
@@@ -44,6 -45,7 +45,7 @@@
   * @dev: Device pointer
   * @idev: Input device
   * @ec: Top level ChromeOS device to use to talk to EC
+  * @notifier: interrupt event notifier for transport devices
   */
  struct cros_ec_keyb {
        unsigned int rows;
@@@ -57,6 -59,7 +59,7 @@@
        struct device *dev;
        struct input_dev *idev;
        struct cros_ec_device *ec;
+       struct notifier_block notifier;
  };
  
  
@@@ -146,67 -149,44 +149,44 @@@ static void cros_ec_keyb_process(struc
        input_sync(ckdev->idev);
  }
  
- static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
- {
-       int ret = 0;
-       struct cros_ec_command *msg;
-       msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
-       msg->version = 0;
-       msg->command = EC_CMD_MKBP_STATE;
-       msg->insize = ckdev->cols;
-       msg->outsize = 0;
-       ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-       if (ret < 0) {
-               dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-               goto exit;
-       }
-       memcpy(kb_state, msg->data, ckdev->cols);
- exit:
-       kfree(msg);
-       return ret;
- }
- static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+ static int cros_ec_keyb_open(struct input_dev *dev)
  {
-       struct cros_ec_keyb *ckdev = data;
-       struct cros_ec_device *ec = ckdev->ec;
-       int ret;
-       uint8_t kb_state[ckdev->cols];
-       if (device_may_wakeup(ec->dev))
-               pm_wakeup_event(ec->dev, 0);
-       ret = cros_ec_keyb_get_state(ckdev, kb_state);
-       if (ret >= 0)
-               cros_ec_keyb_process(ckdev, kb_state, ret);
-       else
-               dev_err(ckdev->dev, "failed to get keyboard state: %d\n", ret);
+       struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
  
-       return IRQ_HANDLED;
+       return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
+                                               &ckdev->notifier);
  }
  
- static int cros_ec_keyb_open(struct input_dev *dev)
+ static void cros_ec_keyb_close(struct input_dev *dev)
  {
        struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-       struct cros_ec_device *ec = ckdev->ec;
  
-       return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-                                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                                       "cros_ec_keyb", ckdev);
+       blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
+                                          &ckdev->notifier);
  }
  
- static void cros_ec_keyb_close(struct input_dev *dev)
+ static int cros_ec_keyb_work(struct notifier_block *nb,
+                            unsigned long queued_during_suspend, void *_notify)
  {
-       struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-       struct cros_ec_device *ec = ckdev->ec;
+       struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+                                                 notifier);
  
-       free_irq(ec->irq, ckdev);
+       if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
+               return NOTIFY_DONE;
+       /*
+        * If EC is not the wake source, discard key state changes during
+        * suspend.
+        */
+       if (queued_during_suspend)
+               return NOTIFY_OK;
+       if (ckdev->ec->event_size != ckdev->cols) {
+               dev_err(ckdev->dev,
+                       "Discarded incomplete key matrix event.\n");
+               return NOTIFY_OK;
+       }
+       cros_ec_keyb_process(ckdev, ckdev->ec->event_data.data.key_matrix,
+                            ckdev->ec->event_size);
+       return NOTIFY_OK;
  }
  
  /*
@@@ -242,7 -222,7 +222,7 @@@ static int cros_ec_keyb_probe(struct pl
        struct device_node *np;
        int err;
  
 -      np = pdev->dev.of_node;
 +      np = dev->of_node;
        if (!np)
                return -ENODEV;
  
        if (!idev)
                return -ENOMEM;
  
-       if (!ec->irq) {
-               dev_err(dev, "no EC IRQ specified\n");
-               return -EINVAL;
-       }
        ckdev->ec = ec;
+       ckdev->notifier.notifier_call = cros_ec_keyb_work;
        ckdev->dev = dev;
 -      dev_set_drvdata(dev, ckdev);
  
        idev->name = CROS_EC_DEV_NAME;
        idev->phys = ec->phys_name;
        return 0;
  }
  
- #ifdef CONFIG_PM_SLEEP
- /* Clear any keys in the buffer */
- static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev)
- {
-       uint8_t old_state[ckdev->cols];
-       uint8_t new_state[ckdev->cols];
-       unsigned long duration;
-       int i, ret;
-       /*
-        * Keep reading until we see that the scan state does not change.
-        * That indicates that we are done.
-        *
-        * Assume that the EC keyscan buffer is at most 32 deep.
-        */
-       duration = jiffies;
-       ret = cros_ec_keyb_get_state(ckdev, new_state);
-       for (i = 1; !ret && i < 32; i++) {
-               memcpy(old_state, new_state, sizeof(old_state));
-               ret = cros_ec_keyb_get_state(ckdev, new_state);
-               if (0 == memcmp(old_state, new_state, sizeof(old_state)))
-                       break;
-       }
-       duration = jiffies - duration;
-       dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i,
-               jiffies_to_usecs(duration));
- }
- static int cros_ec_keyb_resume(struct device *dev)
- {
-       struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
-       /*
-        * When the EC is not a wake source, then it could not have caused the
-        * resume, so we clear the EC's key scan buffer. If the EC was a
-        * wake source (e.g. the lid is open and the user might press a key to
-        * wake) then the key scan buffer should be preserved.
-        */
-       if (!ckdev->ec->was_wake_device)
-               cros_ec_keyb_clear_keyboard(ckdev);
-       return 0;
- }
- #endif
- static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
  #ifdef CONFIG_OF
  static const struct of_device_id cros_ec_keyb_of_match[] = {
        { .compatible = "google,cros-ec-keyb" },
@@@ -371,7 -300,6 +299,6 @@@ static struct platform_driver cros_ec_k
        .driver = {
                .name = "cros-ec-keyb",
                .of_match_table = of_match_ptr(cros_ec_keyb_of_match),
-               .pm     = &cros_ec_keyb_pm_ops,
        },
  };
  
index de1b64703c8c3fd7e86779bb69d12f8457941f86,07ec465f109587e48b946c9513f7b1fbc98a5619..21dc1b8b2a4a9362c4a49fbb998cd401a4037e99
@@@ -37,6 -37,8 +37,8 @@@ static void arizona_haptics_work(struc
                                                       struct arizona_haptics,
                                                       work);
        struct arizona *arizona = haptics->arizona;
+       struct snd_soc_component *component =
+               snd_soc_dapm_to_component(arizona->dapm);
        int ret;
  
        if (!haptics->arizona->dapm) {
@@@ -66,7 -68,7 +68,7 @@@
                        return;
                }
  
-               ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+               ret = snd_soc_component_enable_pin(component, "HAPTICS");
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
                                ret);
@@@ -81,7 -83,7 +83,7 @@@
                }
        } else {
                /* This disable sequence will be a noop if already enabled */
-               ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+               ret = snd_soc_component_disable_pin(component, "HAPTICS");
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
                                ret);
@@@ -140,11 -142,14 +142,14 @@@ static int arizona_haptics_play(struct 
  static void arizona_haptics_close(struct input_dev *input)
  {
        struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct snd_soc_component *component;
  
        cancel_work_sync(&haptics->work);
  
-       if (haptics->arizona->dapm)
-               snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+       if (haptics->arizona->dapm) {
+               component = snd_soc_dapm_to_component(haptics->arizona->dapm);
+               snd_soc_component_disable_pin(component, "HAPTICS");
+       }
  }
  
  static int arizona_haptics_probe(struct platform_device *pdev)
                return ret;
        }
  
 -      platform_set_drvdata(pdev, haptics);
 -
        return 0;
  }
  
index 65384754714d41b41025758705bb1e1d99acf5d5,cc74a41bdb0d24d7e5eddd0f1e019ab01cea71c4..a4455bb12ae0c1896a08aaa9bd198b2aafed19d9
@@@ -95,7 -95,7 +95,7 @@@ static int tps6521x_pb_probe(struct pla
        int error;
        int irq;
  
 -      match = of_match_node(of_tps6521x_pb_match, pdev->dev.of_node);
 +      match = of_match_node(of_tps6521x_pb_match, dev->of_node);
        if (!match)
                return -ENXIO;
  
  
        input_set_capability(idev, EV_KEY, KEY_POWER);
  
 -      pwr->regmap = dev_get_regmap(pdev->dev.parent, NULL);
 +      pwr->regmap = dev_get_regmap(dev->parent, NULL);
        pwr->dev = dev;
        pwr->idev = idev;
 -      platform_set_drvdata(pdev, pwr);
        device_init_wakeup(dev, true);
  
        irq = platform_get_irq(pdev, 0);
                                                IRQF_ONESHOT,
                                          pwr->data->name, pwr);
        if (error) {
 -              dev_err(dev, "failed to request IRQ #%d: %d\n",
 -                      irq, error);
 +              dev_err(dev, "failed to request IRQ #%d: %d\n", irq, error);
                return error;
        }
  
        return 0;
  }
  
+ static const struct platform_device_id tps6521x_pwrbtn_id_table[] = {
+       { "tps65218-pwrbutton", },
+       { "tps65217-pwrbutton", },
+       { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(platform, tps6521x_pwrbtn_id_table);
  static struct platform_driver tps6521x_pb_driver = {
        .probe  = tps6521x_pb_probe,
        .driver = {
                .name   = "tps6521x_pwrbutton",
                .of_match_table = of_tps6521x_pb_match,
        },
+       .id_table = tps6521x_pwrbtn_id_table,
  };
  module_platform_driver(tps6521x_pb_driver);
  
index 75ed6df4973873a2861c9d417028cf4af72e9cc7,7331084973e12f75753159833fdf0d1e06126ae8..922ea02edcc3ef6c091b572275245e7d5fabd3f0
@@@ -15,7 -15,7 +15,7 @@@
  #include <linux/input.h>
  #include <linux/libps2.h>
  #include <linux/proc_fs.h>
- #include <asm/uaccess.h>
+ #include <linux/uaccess.h>
  #include "psmouse.h"
  #include "trackpoint.h"
  
@@@ -379,7 -379,7 +379,7 @@@ int trackpoint_detect(struct psmouse *p
        if (!set_properties)
                return 0;
  
 -      if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
 +      if (trackpoint_read(ps2dev, TP_EXT_BTN, &button_info)) {
                psmouse_warn(psmouse, "failed to get extended button data\n");
                button_info = 0;
        }
  
        trackpoint_defaults(psmouse->private);
  
 -      error = trackpoint_power_on_reset(&psmouse->ps2dev);
 +      error = trackpoint_power_on_reset(ps2dev);
  
        /* Write defaults to TP only if reset fails. */
        if (error)
index a4592ebf9a1d5ea5a11e8ed24d85bd36c0d76e50,a7618776705ab929e42d4c3e870b4911f1a30d9c..05afd16ea9c9efc0bb52efe49510444478e1e220
@@@ -211,6 -211,12 +211,12 @@@ static const struct dmi_system_id __ini
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+               },
+       },
        { }
  };
  
@@@ -805,6 -811,13 +811,13 @@@ static const struct dmi_system_id __ini
                        DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
                },
        },
+       {
+               /* Schenker XMG C504 - Elantech touchpad */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "XMG"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "C504"),
+               },
+       },
        { }
  };
  
@@@ -910,10 -923,6 +923,10 @@@ static struct pnp_driver i8042_pnp_kbd_
        .name           = "i8042 kbd",
        .id_table       = pnp_kbd_devids,
        .probe          = i8042_pnp_kbd_probe,
 +      .driver         = {
 +              .probe_type = PROBE_FORCE_SYNCHRONOUS,
 +              .suppress_bind_attrs = true,
 +      },
  };
  
  static struct pnp_device_id pnp_aux_devids[] = {
@@@ -936,10 -945,6 +949,10 @@@ static struct pnp_driver i8042_pnp_aux_
        .name           = "i8042 aux",
        .id_table       = pnp_aux_devids,
        .probe          = i8042_pnp_aux_probe,
 +      .driver         = {
 +              .probe_type = PROBE_FORCE_SYNCHRONOUS,
 +              .suppress_bind_attrs = true,
 +      },
  };
  
  static void i8042_pnp_exit(void)
@@@ -984,7 -989,11 +997,11 @@@ static int __init i8042_pnp_init(void
  #if defined(__ia64__)
                return -ENODEV;
  #else
-               pr_info("PNP: No PS/2 controller found. Probing ports directly.\n");
+               pr_info("PNP: No PS/2 controller found.\n");
+               if (x86_platform.legacy.i8042 !=
+                               X86_LEGACY_I8042_EXPECTED_PRESENT)
+                       return -ENODEV;
+               pr_info("Probing ports directly.\n");
                return 0;
  #endif
        }
@@@ -1071,8 -1080,8 +1088,8 @@@ static int __init i8042_platform_init(v
  
  #ifdef CONFIG_X86
        u8 a20_on = 0xdf;
-       /* Just return if pre-detection shows no i8042 controller exist */
-       if (!x86_platform.i8042_detect())
+       /* Just return if platform does not have i8042 controller */
+       if (x86_platform.legacy.i8042 == X86_LEGACY_I8042_PLATFORM_ABSENT)
                return -ENODEV;
  #endif
  
index 740e4483f4fdf69e523f9044cac82f829847e5fc,3e6003d32e565c748a43730574b9424eeb294d33..872750eeca9325cbb3a9140b0686da4a2f5cbdfa
@@@ -914,9 -914,9 +914,9 @@@ static irqreturn_t elants_i2c_irq(int i
  
                case QUEUE_HEADER_NORMAL:
                        report_count = ts->buf[FW_HDR_COUNT];
-                       if (report_count > 3) {
+                       if (report_count == 0 || report_count > 3) {
                                dev_err(&client->dev,
-                                       "too large report count: %*ph\n",
+                                       "bad report count: %*ph\n",
                                        HEADER_SIZE, ts->buf);
                                break;
                        }
@@@ -1260,6 -1260,8 +1260,6 @@@ static int elants_i2c_probe(struct i2c_
        input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
        input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
  
 -      input_set_drvdata(ts->input, ts);
 -
        error = input_register_device(ts->input);
        if (error) {
                dev_err(&client->dev,