]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 13 Oct 2007 01:27:47 +0000 (21:27 -0400)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 13 Oct 2007 01:27:47 +0000 (21:27 -0400)
Conflicts:

drivers/macintosh/adbhid.c

12 files changed:
1  2 
drivers/hwmon/Kconfig
drivers/hwmon/applesmc.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/keyboard/gpio_keys.c
drivers/input/mouse/lifebook.c
drivers/input/serio/i8042.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/macintosh/Kconfig
drivers/macintosh/adbhid.c
include/linux/input.h
include/linux/keyboard.h

diff --combined drivers/hwmon/Kconfig
index 99c82b1af8c9ece00be4c2a30acca442b9646c5b,192953b29b2843e243d41102b7367d5181c2d7a4..e8f44b580f0a91a1c1a77b0ce9cc7aaa03d997e3
@@@ -29,17 -29,34 +29,34 @@@ config HWMON_VI
        default n
  
  config SENSORS_ABITUGURU
-       tristate "Abit uGuru"
+       tristate "Abit uGuru (rev 1 & 2)"
        depends on EXPERIMENTAL
        help
-         If you say yes here you get support for the Abit uGuru chips
-         sensor part. The voltage and frequency control parts of the Abit
-         uGuru are not supported. The Abit uGuru chip can be found on Abit
-         uGuru featuring motherboards (most modern Abit motherboards).
+         If you say yes here you get support for the sensor part of the first
+         and second revision of the Abit uGuru chip. The voltage and frequency
+         control parts of the Abit uGuru are not supported. The Abit uGuru
+         chip can be found on Abit uGuru featuring motherboards (most modern
+         Abit motherboards from before end 2005). For more info and a list
+         of which motherboards have which revision see
+         Documentation/hwmon/abituguru
  
          This driver can also be built as a module.  If so, the module
          will be called abituguru.
  
+ config SENSORS_ABITUGURU3
+       tristate "Abit uGuru (rev 3)"
+       depends on HWMON && EXPERIMENTAL
+       help
+         If you say yes here you get support for the sensor part of the
+         third revision of the Abit uGuru chip. Only reading the sensors
+         and their settings is supported. The third revision of the Abit
+         uGuru chip can be found on recent Abit motherboards (since end
+         2005). For more info and a list of which motherboards have which
+         revision see Documentation/hwmon/abituguru3
+         This driver can also be built as a module.  If so, the module
+         will be called abituguru3.
  config SENSORS_AD7418
        tristate "Analog Devices AD7416, AD7417 and AD7418"
        depends on I2C && EXPERIMENTAL
@@@ -131,7 -148,6 +148,7 @@@ config SENSORS_K8TEM
  config SENSORS_AMS
        tristate "Apple Motion Sensor driver"
        depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
 +      select INPUT_POLLDEV
        help
          Support for the motion sensor included in PowerBooks. Includes
          implementations for PMU and I2C.
@@@ -251,12 -267,10 +268,10 @@@ config SENSORS_CORETEM
  
  config SENSORS_IT87
        tristate "ITE IT87xx and compatibles"
-       depends on I2C
-       select I2C_ISA
        select HWMON_VID
        help
          If you say yes here you get support for ITE IT8705F, IT8712F,
-         IT8716F and IT8718F sensor chips, and the SiS960 clone.
+         IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone.
  
          This driver can also be built as a module.  If so, the module
          will be called it87.
@@@ -366,8 -380,8 +381,8 @@@ config SENSORS_LM9
        depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM90,
-         LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
-         MAX6658 sensor chips.
+         LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657,
+         MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips.
  
          The Analog Devices ADT7461 sensor chip is also supported, but only
          if found in ADM1032 compatibility mode.
@@@ -385,6 -399,17 +400,17 @@@ config SENSORS_LM9
          This driver can also be built as a module.  If so, the module
          will be called lm92.
  
+ config SENSORS_LM93
+       tristate "National Semiconductor LM93 and compatibles"
+       depends on HWMON && I2C
+       select HWMON_VID
+       help
+         If you say yes here you get support for National Semiconductor LM93
+         sensor chips.
+         This driver can also be built as a module.  If so, the module
+         will be called lm93.
  config SENSORS_MAX1619
        tristate "Maxim MAX1619 sensor chip"
        depends on I2C
@@@ -406,8 -431,6 +432,6 @@@ config SENSORS_MAX665
  
  config SENSORS_PC87360
        tristate "National Semiconductor PC87360 family"
-       depends on I2C && EXPERIMENTAL
-       select I2C_ISA
        select HWMON_VID
        help
          If you say yes here you get access to the hardware monitoring
@@@ -434,8 -457,7 +458,7 @@@ config SENSORS_PC8742
  
  config SENSORS_SIS5595
        tristate "Silicon Integrated Systems Corp. SiS5595"
-       depends on I2C && PCI && EXPERIMENTAL
-       select I2C_ISA
+       depends on PCI
        help
          If you say yes here you get support for the integrated sensors in
          SiS5595 South Bridges.
          This driver can also be built as a module.  If so, the module
          will be called sis5595.
  
+ config SENSORS_DME1737
+       tristate "SMSC DME1737 and compatibles"
+       depends on I2C && EXPERIMENTAL
+       select HWMON_VID
+       help
+         If you say yes here you get support for the hardware monitoring
+         and fan control features of the SMSC DME1737 (and compatibles
+         like the Asus A8000) Super-I/O chip.
+         This driver can also be built as a module.  If so, the module
+         will be called dme1737.
  config SENSORS_SMSC47M1
        tristate "SMSC LPC47M10x and compatibles"
        help
@@@ -486,10 -520,19 +521,19 @@@ config SENSORS_SMSC47B39
          This driver can also be built as a module.  If so, the module
          will be called smsc47b397.
  
+ config SENSORS_THMC50
+       tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for Texas Instruments THMC50
+         sensor chips and clones: the Analog Devices ADM1022.
+         This driver can also be built as a module.  If so, the module
+         will be called thmc50.
  config SENSORS_VIA686A
        tristate "VIA686A"
-       depends on I2C && PCI
-       select I2C_ISA
+       depends on PCI
        help
          If you say yes here you get support for the integrated sensors in
          Via 686A/B South Bridges.
@@@ -510,9 -553,8 +554,8 @@@ config SENSORS_VT121
  
  config SENSORS_VT8231
        tristate "VIA VT8231"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on PCI
        select HWMON_VID
-       select I2C_ISA
        help
          If you say yes here then you get support for the integrated sensors
          in the VIA VT8231 device.
@@@ -585,17 -627,16 +628,16 @@@ config SENSORS_W83627H
          will be called w83627hf.
  
  config SENSORS_W83627EHF
-       tristate "Winbond W83627EHF"
-       depends on I2C && EXPERIMENTAL
-       select I2C_ISA
+       tristate "Winbond W83627EHF/DHG"
+       select HWMON_VID
        help
-         If you say yes here you get preliminary support for the hardware
+         If you say yes here you get support for the hardware
          monitoring functionality of the Winbond W83627EHF Super-I/O chip.
-         Only fan and temperature inputs are supported at the moment, while
-         the chip does much more than that.
  
          This driver also supports the W83627EHG, which is the lead-free
-         version of the W83627EHF.
+         version of the W83627EHF, and the W83627DHG, which is a similar
+         chip suited for specific Intel processors that use PECI such as
+         the Core 2 Duo.
  
          This driver can also be built as a module.  If so, the module
          will be called w83627ehf.
@@@ -624,7 -665,6 +666,7 @@@ config SENSORS_APPLESM
        depends on INPUT && X86
        select NEW_LEDS
        select LEDS_CLASS
 +      select INPUT_POLLDEV
        default n
        help
          This driver provides support for the Apple System Management
diff --combined drivers/hwmon/applesmc.c
index eb81a6430fe4b0af24b679fd2deef1ecd816b7d2,56213b7f8188ecbf39417ba75a431bc48cddeff3..571f49e80277326fd0f76c367bdb03f778399499
@@@ -28,7 -28,7 +28,7 @@@
  
  #include <linux/delay.h>
  #include <linux/platform_device.h>
 -#include <linux/input.h>
 +#include <linux/input-polldev.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/timer.h>
@@@ -59,9 -59,9 +59,9 @@@
  
  #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */
  #define LIGHT_SENSOR_RIGHT_KEY        "ALV1" /* r-o {alv (6 bytes) */
 -#define BACKLIGHT_KEY                 "LKSB" /* w-o {lkb (2 bytes) */
 +#define BACKLIGHT_KEY         "LKSB" /* w-o {lkb (2 bytes) */
  
 -#define CLAMSHELL_KEY                 "MSLD" /* r-o ui8 (unused) */
 +#define CLAMSHELL_KEY         "MSLD" /* r-o ui8 (unused) */
  
  #define MOTION_SENSOR_X_KEY   "MO_X" /* r-o sp78 (2 bytes) */
  #define MOTION_SENSOR_Y_KEY   "MO_Y" /* r-o sp78 (2 bytes) */
  
  /*
   * Temperature sensors keys (sp78 - 2 bytes).
-  * First set for Macbook(Pro), second for Macmini.
   */
  static const char* temperature_sensors_sets[][13] = {
+ /* Set 0: Macbook Pro */
        { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
          "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
+ /* Set 1: Macbook set */
+       { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
+         "Th1H", "Ts0P", NULL },
+ /* Set 2: Macmini set */
        { "TC0D", "TC0P", NULL }
  };
  
@@@ -99,7 -103,7 +103,7 @@@ static const char* fan_speed_keys[] = 
  #define INIT_TIMEOUT_MSECS    5000    /* wait up to 5s for device init ... */
  #define INIT_WAIT_MSECS               50      /* ... in 50ms increments */
  
 -#define APPLESMC_POLL_PERIOD  (HZ/20) /* poll for input every 1/20s */
 +#define APPLESMC_POLL_INTERVAL        50      /* msecs */
  #define APPLESMC_INPUT_FUZZ   4       /* input event threshold */
  #define APPLESMC_INPUT_FLAT   4
  
@@@ -121,7 -125,8 +125,7 @@@ static const int debug
  static struct platform_device *pdev;
  static s16 rest_x;
  static s16 rest_y;
 -static struct timer_list applesmc_timer;
 -static struct input_dev *applesmc_idev;
 +static struct input_polled_dev *applesmc_idev;
  static struct class_device *hwmon_class_dev;
  
  /* Indicates whether this computer has an accelerometer. */
@@@ -133,7 -138,7 +137,7 @@@ static unsigned int applesmc_light
  /* Indicates which temperature sensors set to use. */
  static unsigned int applesmc_temperature_set;
  
 -static struct mutex applesmc_lock;
 +static DEFINE_MUTEX(applesmc_lock);
  
  /*
   * Last index written to key_at_index sysfs file, and value to use for all other
@@@ -450,12 -455,27 +454,12 @@@ static void applesmc_calibrate(void
        rest_x = -rest_x;
  }
  
 -static int applesmc_idev_open(struct input_dev *dev)
 -{
 -      add_timer(&applesmc_timer);
 -
 -      return 0;
 -}
 -
 -static void applesmc_idev_close(struct input_dev *dev)
 -{
 -      del_timer_sync(&applesmc_timer);
 -}
 -
 -static void applesmc_idev_poll(unsigned long unused)
 +static void applesmc_idev_poll(struct input_polled_dev *dev)
  {
 +      struct input_dev *idev = dev->input;
        s16 x, y;
  
 -      /* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
 -      if (!mutex_trylock(&applesmc_lock)) {
 -              mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
 -              return;
 -      }
 +      mutex_lock(&applesmc_lock);
  
        if (applesmc_read_motion_sensor(SENSOR_X, &x))
                goto out;
                goto out;
  
        x = -x;
 -      input_report_abs(applesmc_idev, ABS_X, x - rest_x);
 -      input_report_abs(applesmc_idev, ABS_Y, y - rest_y);
 -      input_sync(applesmc_idev);
 +      input_report_abs(idev, ABS_X, x - rest_x);
 +      input_report_abs(idev, ABS_Y, y - rest_y);
 +      input_sync(idev);
  
  out:
 -      mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
 -
        mutex_unlock(&applesmc_lock);
  }
  
@@@ -799,7 -821,8 +803,7 @@@ static ssize_t applesmc_key_at_index_re
  
        if (!ret) {
                return info[0];
 -      }
 -      else {
 +      } else {
                return ret;
        }
  }
@@@ -1048,7 -1071,7 +1052,7 @@@ static const struct attribute_group tem
  /*
   * applesmc_dmi_match - found a match.  return one, short-circuiting the hunt.
   */
- static int applesmc_dmi_match(struct dmi_system_id *id)
+ static int applesmc_dmi_match(const struct dmi_system_id *id)
  {
        int i = 0;
        struct dmi_match_data* dmi_data = id->driver_data;
  /* Create accelerometer ressources */
  static int applesmc_create_accelerometer(void)
  {
 +      struct input_dev *idev;
        int ret;
  
        ret = sysfs_create_group(&pdev->dev.kobj,
        if (ret)
                goto out;
  
 -      applesmc_idev = input_allocate_device();
 +      applesmc_idev = input_allocate_polled_device();
        if (!applesmc_idev) {
                ret = -ENOMEM;
                goto out_sysfs;
        }
  
 +      applesmc_idev->poll = applesmc_idev_poll;
 +      applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
 +
        /* initial calibrate for the input device */
        applesmc_calibrate();
  
 -      /* initialize the input class */
 -      applesmc_idev->name = "applesmc";
 -      applesmc_idev->id.bustype = BUS_HOST;
 -      applesmc_idev->dev.parent = &pdev->dev;
 -      applesmc_idev->evbit[0] = BIT(EV_ABS);
 -      applesmc_idev->open = applesmc_idev_open;
 -      applesmc_idev->close = applesmc_idev_close;
 -      input_set_abs_params(applesmc_idev, ABS_X,
 +      /* initialize the input device */
 +      idev = applesmc_idev->input;
 +      idev->name = "applesmc";
 +      idev->id.bustype = BUS_HOST;
 +      idev->dev.parent = &pdev->dev;
 +      idev->evbit[0] = BIT(EV_ABS);
 +      input_set_abs_params(idev, ABS_X,
                        -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
 -      input_set_abs_params(applesmc_idev, ABS_Y,
 +      input_set_abs_params(idev, ABS_Y,
                        -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
  
 -      ret = input_register_device(applesmc_idev);
 +      ret = input_register_polled_device(applesmc_idev);
        if (ret)
                goto out_idev;
  
 -      /* start up our timer for the input device */
 -      init_timer(&applesmc_timer);
 -      applesmc_timer.function = applesmc_idev_poll;
 -      applesmc_timer.expires = jiffies + APPLESMC_POLL_PERIOD;
 -
        return 0;
  
  out_idev:
 -      input_free_device(applesmc_idev);
 +      input_free_polled_device(applesmc_idev);
  
  out_sysfs:
        sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
  /* Release all ressources used by the accelerometer */
  static void applesmc_release_accelerometer(void)
  {
 -      del_timer_sync(&applesmc_timer);
 -      input_unregister_device(applesmc_idev);
 +      input_unregister_polled_device(applesmc_idev);
 +      input_free_polled_device(applesmc_idev);
        sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
  }
  
  static __initdata struct dmi_match_data applesmc_dmi_data[] = {
  /* MacBook Pro: accelerometer, backlight and temperature set 0 */
        { .accelerometer = 1, .light = 1, .temperature_set = 0 },
- /* MacBook: accelerometer and temperature set 0 */
-       { .accelerometer = 1, .light = 0, .temperature_set = 0 },
- /* MacBook: temperature set 1 */
-       { .accelerometer = 0, .light = 0, .temperature_set = 1 }
+ /* MacBook: accelerometer and temperature set 1 */
+       { .accelerometer = 1, .light = 0, .temperature_set = 1 },
+ /* MacMini: temperature set 2 */
+       { .accelerometer = 0, .light = 0, .temperature_set = 2 },
  };
  
  /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@@ -1159,6 -1184,8 +1163,6 @@@ static int __init applesmc_init(void
        int count;
        int i;
  
 -      mutex_init(&applesmc_lock);
 -
        if (!dmi_check_system(applesmc_whitelist)) {
                printk(KERN_WARNING "applesmc: supported laptop not found!\n");
                ret = -ENODEV;
diff --combined drivers/input/evdev.c
index d404aa8680ea1aa83c660a8a5f5ef98059fcb66c,f1c3d6cebd585a5392c96e0ed1a25e9cf275a73a..27026f7d3c036239e651730fbf910d8835f43ab2
@@@ -30,8 -30,6 +30,8 @@@ struct evdev 
        wait_queue_head_t wait;
        struct evdev_client *grab;
        struct list_head client_list;
 +      spinlock_t client_lock; /* protects client_list */
 +      struct mutex mutex;
        struct device dev;
  };
  
@@@ -39,53 -37,39 +39,53 @@@ struct evdev_client 
        struct input_event buffer[EVDEV_BUFFER_SIZE];
        int head;
        int tail;
 +      spinlock_t buffer_lock; /* protects access to buffer, head and tail */
        struct fasync_struct *fasync;
        struct evdev *evdev;
        struct list_head node;
  };
  
  static struct evdev *evdev_table[EVDEV_MINORS];
 +static DEFINE_MUTEX(evdev_table_mutex);
  
 -static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 +static void evdev_pass_event(struct evdev_client *client,
 +                           struct input_event *event)
 +{
 +      /*
 +       * Interrupts are disabled, just acquire the lock
 +       */
 +      spin_lock(&client->buffer_lock);
 +      client->buffer[client->head++] = *event;
 +      client->head &= EVDEV_BUFFER_SIZE - 1;
 +      spin_unlock(&client->buffer_lock);
 +
 +      kill_fasync(&client->fasync, SIGIO, POLL_IN);
 +}
 +
 +/*
 + * Pass incoming event to all connected clients. Note that we are
 + * caleld under a spinlock with interrupts off so we don't need
 + * to use rcu_read_lock() here. Writers will be using syncronize_sched()
 + * instead of synchrnoize_rcu().
 + */
 +static void evdev_event(struct input_handle *handle,
 +                      unsigned int type, unsigned int code, int value)
  {
        struct evdev *evdev = handle->private;
        struct evdev_client *client;
 +      struct input_event event;
  
 -      if (evdev->grab) {
 -              client = evdev->grab;
 -
 -              do_gettimeofday(&client->buffer[client->head].time);
 -              client->buffer[client->head].type = type;
 -              client->buffer[client->head].code = code;
 -              client->buffer[client->head].value = value;
 -              client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 -
 -              kill_fasync(&client->fasync, SIGIO, POLL_IN);
 -      } else
 -              list_for_each_entry(client, &evdev->client_list, node) {
 -
 -                      do_gettimeofday(&client->buffer[client->head].time);
 -                      client->buffer[client->head].type = type;
 -                      client->buffer[client->head].code = code;
 -                      client->buffer[client->head].value = value;
 -                      client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 +      do_gettimeofday(&event.time);
 +      event.type = type;
 +      event.code = code;
 +      event.value = value;
  
 -                      kill_fasync(&client->fasync, SIGIO, POLL_IN);
 -              }
 +      client = rcu_dereference(evdev->grab);
 +      if (client)
 +              evdev_pass_event(client, &event);
 +      else
 +              list_for_each_entry_rcu(client, &evdev->client_list, node)
 +                      evdev_pass_event(client, &event);
  
        wake_up_interruptible(&evdev->wait);
  }
@@@ -104,145 -88,38 +104,145 @@@ static int evdev_flush(struct file *fil
  {
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
 +      int retval;
 +
 +      retval = mutex_lock_interruptible(&evdev->mutex);
 +      if (retval)
 +              return retval;
  
        if (!evdev->exist)
 -              return -ENODEV;
 +              retval = -ENODEV;
 +      else
 +              retval = input_flush_device(&evdev->handle, file);
  
 -      return input_flush_device(&evdev->handle, file);
 +      mutex_unlock(&evdev->mutex);
 +      return retval;
  }
  
  static void evdev_free(struct device *dev)
  {
        struct evdev *evdev = container_of(dev, struct evdev, dev);
  
 -      evdev_table[evdev->minor] = NULL;
        kfree(evdev);
  }
  
 +/*
 + * Grabs an event device (along with underlying input device).
 + * This function is called with evdev->mutex taken.
 + */
 +static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
 +{
 +      int error;
 +
 +      if (evdev->grab)
 +              return -EBUSY;
 +
 +      error = input_grab_device(&evdev->handle);
 +      if (error)
 +              return error;
 +
 +      rcu_assign_pointer(evdev->grab, client);
 +      /*
 +       * We don't use synchronize_rcu() here because read-side
 +       * critical section is protected by a spinlock instead
 +       * of rcu_read_lock().
 +       */
 +      synchronize_sched();
 +
 +      return 0;
 +}
 +
 +static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
 +{
 +      if (evdev->grab != client)
 +              return  -EINVAL;
 +
 +      rcu_assign_pointer(evdev->grab, NULL);
 +      synchronize_sched();
 +      input_release_device(&evdev->handle);
 +
 +      return 0;
 +}
 +
 +static void evdev_attach_client(struct evdev *evdev,
 +                              struct evdev_client *client)
 +{
 +      spin_lock(&evdev->client_lock);
 +      list_add_tail_rcu(&client->node, &evdev->client_list);
 +      spin_unlock(&evdev->client_lock);
 +      synchronize_sched();
 +}
 +
 +static void evdev_detach_client(struct evdev *evdev,
 +                              struct evdev_client *client)
 +{
 +      spin_lock(&evdev->client_lock);
 +      list_del_rcu(&client->node);
 +      spin_unlock(&evdev->client_lock);
 +      synchronize_sched();
 +}
 +
 +static int evdev_open_device(struct evdev *evdev)
 +{
 +      int retval;
 +
 +      retval = mutex_lock_interruptible(&evdev->mutex);
 +      if (retval)
 +              return retval;
 +
 +      if (!evdev->exist)
 +              retval = -ENODEV;
 +      else if (!evdev->open++) {
 +              retval = input_open_device(&evdev->handle);
 +              if (retval)
 +                      evdev->open--;
 +      }
 +
 +      mutex_unlock(&evdev->mutex);
 +      return retval;
 +}
 +
 +static void evdev_close_device(struct evdev *evdev)
 +{
 +      mutex_lock(&evdev->mutex);
 +
 +      if (evdev->exist && !--evdev->open)
 +              input_close_device(&evdev->handle);
 +
 +      mutex_unlock(&evdev->mutex);
 +}
 +
 +/*
 + * Wake up users waiting for IO so they can disconnect from
 + * dead device.
 + */
 +static void evdev_hangup(struct evdev *evdev)
 +{
 +      struct evdev_client *client;
 +
 +      spin_lock(&evdev->client_lock);
 +      list_for_each_entry(client, &evdev->client_list, node)
 +              kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 +      spin_unlock(&evdev->client_lock);
 +
 +      wake_up_interruptible(&evdev->wait);
 +}
 +
  static int evdev_release(struct inode *inode, struct file *file)
  {
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
  
 -      if (evdev->grab == client) {
 -              input_release_device(&evdev->handle);
 -              evdev->grab = NULL;
 -      }
 +      mutex_lock(&evdev->mutex);
 +      if (evdev->grab == client)
 +              evdev_ungrab(evdev, client);
 +      mutex_unlock(&evdev->mutex);
  
        evdev_fasync(-1, file, 0);
 -      list_del(&client->node);
 +      evdev_detach_client(evdev, client);
        kfree(client);
  
 -      if (!--evdev->open && evdev->exist)
 -              input_close_device(&evdev->handle);
 -
 +      evdev_close_device(evdev);
        put_device(&evdev->dev);
  
        return 0;
  
  static int evdev_open(struct inode *inode, struct file *file)
  {
 -      struct evdev_client *client;
        struct evdev *evdev;
 +      struct evdev_client *client;
        int i = iminor(inode) - EVDEV_MINOR_BASE;
        int error;
  
        if (i >= EVDEV_MINORS)
                return -ENODEV;
  
 +      error = mutex_lock_interruptible(&evdev_table_mutex);
 +      if (error)
 +              return error;
        evdev = evdev_table[i];
 +      if (evdev)
 +              get_device(&evdev->dev);
 +      mutex_unlock(&evdev_table_mutex);
  
 -      if (!evdev || !evdev->exist)
 +      if (!evdev)
                return -ENODEV;
  
 -      get_device(&evdev->dev);
 -
        client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
        if (!client) {
                error = -ENOMEM;
                goto err_put_evdev;
        }
  
 +      spin_lock_init(&client->buffer_lock);
        client->evdev = evdev;
 -      list_add_tail(&client->node, &evdev->client_list);
 +      evdev_attach_client(evdev, client);
  
 -      if (!evdev->open++ && evdev->exist) {
 -              error = input_open_device(&evdev->handle);
 -              if (error)
 -                      goto err_free_client;
 -      }
 +      error = evdev_open_device(evdev);
 +      if (error)
 +              goto err_free_client;
  
        file->private_data = client;
        return 0;
  
   err_free_client:
 -      list_del(&client->node);
 +      evdev_detach_client(evdev, client);
        kfree(client);
   err_put_evdev:
        put_device(&evdev->dev);
@@@ -312,7 -186,7 +312,7 @@@ struct input_event_compat 
  #elif defined(CONFIG_S390)
  #  define COMPAT_TEST test_thread_flag(TIF_31BIT)
  #elif defined(CONFIG_MIPS)
- #  define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
+ #  define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
  #else
  #  define COMPAT_TEST test_thread_flag(TIF_32BIT)
  #endif
@@@ -323,14 -197,12 +323,14 @@@ static inline size_t evdev_event_size(v
                sizeof(struct input_event_compat) : sizeof(struct input_event);
  }
  
 -static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
 +static int evdev_event_from_user(const char __user *buffer,
 +                               struct input_event *event)
  {
        if (COMPAT_TEST) {
                struct input_event_compat compat_event;
  
 -              if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat)))
 +              if (copy_from_user(&compat_event, buffer,
 +                                 sizeof(struct input_event_compat)))
                        return -EFAULT;
  
                event->time.tv_sec = compat_event.time.tv_sec;
        return 0;
  }
  
 -static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
 +static int evdev_event_to_user(char __user *buffer,
 +                              const struct input_event *event)
  {
        if (COMPAT_TEST) {
                struct input_event_compat compat_event;
                compat_event.code = event->code;
                compat_event.value = event->value;
  
 -              if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat)))
 +              if (copy_to_user(buffer, &compat_event,
 +                               sizeof(struct input_event_compat)))
                        return -EFAULT;
  
        } else {
@@@ -378,8 -248,7 +378,8 @@@ static inline size_t evdev_event_size(v
        return sizeof(struct input_event);
  }
  
 -static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
 +static int evdev_event_from_user(const char __user *buffer,
 +                               struct input_event *event)
  {
        if (copy_from_user(event, buffer, sizeof(struct input_event)))
                return -EFAULT;
        return 0;
  }
  
 -static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
 +static int evdev_event_to_user(char __user *buffer,
 +                              const struct input_event *event)
  {
        if (copy_to_user(buffer, event, sizeof(struct input_event)))
                return -EFAULT;
  
  #endif /* CONFIG_COMPAT */
  
 -static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 +static ssize_t evdev_write(struct file *file, const char __user *buffer,
 +                         size_t count, loff_t *ppos)
  {
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
        struct input_event event;
 -      int retval = 0;
 +      int retval;
  
 -      if (!evdev->exist)
 -              return -ENODEV;
 +      retval = mutex_lock_interruptible(&evdev->mutex);
 +      if (retval)
 +              return retval;
 +
 +      if (!evdev->exist) {
 +              retval = -ENODEV;
 +              goto out;
 +      }
  
        while (retval < count) {
  
 -              if (evdev_event_from_user(buffer + retval, &event))
 -                      return -EFAULT;
 -              input_inject_event(&evdev->handle, event.type, event.code, event.value);
 +              if (evdev_event_from_user(buffer + retval, &event)) {
 +                      retval = -EFAULT;
 +                      goto out;
 +              }
 +
 +              input_inject_event(&evdev->handle,
 +                                 event.type, event.code, event.value);
                retval += evdev_event_size();
        }
  
 + out:
 +      mutex_unlock(&evdev->mutex);
        return retval;
  }
  
 -static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 +static int evdev_fetch_next_event(struct evdev_client *client,
 +                                struct input_event *event)
 +{
 +      int have_event;
 +
 +      spin_lock_irq(&client->buffer_lock);
 +
 +      have_event = client->head != client->tail;
 +      if (have_event) {
 +              *event = client->buffer[client->tail++];
 +              client->tail &= EVDEV_BUFFER_SIZE - 1;
 +      }
 +
 +      spin_unlock_irq(&client->buffer_lock);
 +
 +      return have_event;
 +}
 +
 +static ssize_t evdev_read(struct file *file, char __user *buffer,
 +                        size_t count, loff_t *ppos)
  {
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
 +      struct input_event event;
        int retval;
  
        if (count < evdev_event_size())
                return -EINVAL;
  
 -      if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
 +      if (client->head == client->tail && evdev->exist &&
 +          (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
  
        retval = wait_event_interruptible(evdev->wait,
        if (!evdev->exist)
                return -ENODEV;
  
 -      while (client->head != client->tail && retval + evdev_event_size() <= count) {
 +      while (retval + evdev_event_size() <= count &&
 +             evdev_fetch_next_event(client, &event)) {
  
 -              struct input_event *event = (struct input_event *) client->buffer + client->tail;
 -
 -              if (evdev_event_to_user(buffer + retval, event))
 +              if (evdev_event_to_user(buffer + retval, &event))
                        return -EFAULT;
  
 -              client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
                retval += evdev_event_size();
        }
  
@@@ -573,8 -409,8 +573,8 @@@ static int str_to_user(const char *str
        return copy_to_user(p, str, len) ? -EFAULT : len;
  }
  
 -static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 -                              void __user *p, int compat_mode)
 +static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 +                         void __user *p, int compat_mode)
  {
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
        int i, t, u, v;
        int error;
  
 -      if (!evdev->exist)
 -              return -ENODEV;
 -
        switch (cmd) {
  
 -              case EVIOCGVERSION:
 -                      return put_user(EV_VERSION, ip);
 +      case EVIOCGVERSION:
 +              return put_user(EV_VERSION, ip);
  
 -              case EVIOCGID:
 -                      if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
 -                              return -EFAULT;
 -                      return 0;
 +      case EVIOCGID:
 +              if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
 +                      return -EFAULT;
 +              return 0;
  
 -              case EVIOCGREP:
 -                      if (!test_bit(EV_REP, dev->evbit))
 -                              return -ENOSYS;
 -                      if (put_user(dev->rep[REP_DELAY], ip))
 -                              return -EFAULT;
 -                      if (put_user(dev->rep[REP_PERIOD], ip + 1))
 -                              return -EFAULT;
 -                      return 0;
 +      case EVIOCGREP:
 +              if (!test_bit(EV_REP, dev->evbit))
 +                      return -ENOSYS;
 +              if (put_user(dev->rep[REP_DELAY], ip))
 +                      return -EFAULT;
 +              if (put_user(dev->rep[REP_PERIOD], ip + 1))
 +                      return -EFAULT;
 +              return 0;
  
 -              case EVIOCSREP:
 -                      if (!test_bit(EV_REP, dev->evbit))
 -                              return -ENOSYS;
 -                      if (get_user(u, ip))
 -                              return -EFAULT;
 -                      if (get_user(v, ip + 1))
 -                              return -EFAULT;
 +      case EVIOCSREP:
 +              if (!test_bit(EV_REP, dev->evbit))
 +                      return -ENOSYS;
 +              if (get_user(u, ip))
 +                      return -EFAULT;
 +              if (get_user(v, ip + 1))
 +                      return -EFAULT;
  
 -                      input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
 -                      input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
 +              input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
 +              input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
  
 -                      return 0;
 +              return 0;
  
 -              case EVIOCGKEYCODE:
 -                      if (get_user(t, ip))
 -                              return -EFAULT;
 +      case EVIOCGKEYCODE:
 +              if (get_user(t, ip))
 +                      return -EFAULT;
  
 -                      error = dev->getkeycode(dev, t, &v);
 -                      if (error)
 -                              return error;
 +              error = dev->getkeycode(dev, t, &v);
 +              if (error)
 +                      return error;
  
 -                      if (put_user(v, ip + 1))
 -                              return -EFAULT;
 +              if (put_user(v, ip + 1))
 +                      return -EFAULT;
  
 -                      return 0;
 +              return 0;
  
 -              case EVIOCSKEYCODE:
 -                      if (get_user(t, ip) || get_user(v, ip + 1))
 -                              return -EFAULT;
 +      case EVIOCSKEYCODE:
 +              if (get_user(t, ip) || get_user(v, ip + 1))
 +                      return -EFAULT;
  
 -                      return dev->setkeycode(dev, t, v);
 +              return dev->setkeycode(dev, t, v);
  
 -              case EVIOCSFF:
 -                      if (copy_from_user(&effect, p, sizeof(effect)))
 -                              return -EFAULT;
 +      case EVIOCSFF:
 +              if (copy_from_user(&effect, p, sizeof(effect)))
 +                      return -EFAULT;
  
 -                      error = input_ff_upload(dev, &effect, file);
 +              error = input_ff_upload(dev, &effect, file);
  
 -                      if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
 -                              return -EFAULT;
 +              if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
 +                      return -EFAULT;
  
 -                      return error;
 +              return error;
  
 -              case EVIOCRMFF:
 -                      return input_ff_erase(dev, (int)(unsigned long) p, file);
 +      case EVIOCRMFF:
 +              return input_ff_erase(dev, (int)(unsigned long) p, file);
  
 -              case EVIOCGEFFECTS:
 -                      i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0;
 -                      if (put_user(i, ip))
 -                              return -EFAULT;
 -                      return 0;
 -
 -              case EVIOCGRAB:
 -                      if (p) {
 -                              if (evdev->grab)
 -                                      return -EBUSY;
 -                              if (input_grab_device(&evdev->handle))
 -                                      return -EBUSY;
 -                              evdev->grab = client;
 -                              return 0;
 -                      } else {
 -                              if (evdev->grab != client)
 -                                      return -EINVAL;
 -                              input_release_device(&evdev->handle);
 -                              evdev->grab = NULL;
 -                              return 0;
 -                      }
 +      case EVIOCGEFFECTS:
 +              i = test_bit(EV_FF, dev->evbit) ?
 +                              dev->ff->max_effects : 0;
 +              if (put_user(i, ip))
 +                      return -EFAULT;
 +              return 0;
  
 -              default:
 +      case EVIOCGRAB:
 +              if (p)
 +                      return evdev_grab(evdev, client);
 +              else
 +                      return evdev_ungrab(evdev, client);
  
 -                      if (_IOC_TYPE(cmd) != 'E')
 -                              return -EINVAL;
 +      default:
  
 -                      if (_IOC_DIR(cmd) == _IOC_READ) {
 +              if (_IOC_TYPE(cmd) != 'E')
 +                      return -EINVAL;
  
 -                              if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
 +              if (_IOC_DIR(cmd) == _IOC_READ) {
  
 -                                      unsigned long *bits;
 -                                      int len;
 +                      if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
  
 -                                      switch (_IOC_NR(cmd) & EV_MAX) {
 -                                              case      0: bits = dev->evbit;  len = EV_MAX;  break;
 -                                              case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
 -                                              case EV_REL: bits = dev->relbit; len = REL_MAX; break;
 -                                              case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
 -                                              case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
 -                                              case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
 -                                              case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
 -                                              case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
 -                                              case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
 -                                              default: return -EINVAL;
 -                                      }
 -                                      return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
 -                              }
 +                              unsigned long *bits;
 +                              int len;
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
 -                                      return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
 -                                                          p, compat_mode);
 +                              switch (_IOC_NR(cmd) & EV_MAX) {
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
 -                                      return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
 -                                                          p, compat_mode);
 +                              case      0: bits = dev->evbit;  len = EV_MAX;  break;
 +                              case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
 +                              case EV_REL: bits = dev->relbit; len = REL_MAX; break;
 +                              case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
 +                              case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
 +                              case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
 +                              case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
 +                              case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
 +                              case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
 +                              default: return -EINVAL;
 +                      }
 +                              return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
 +                      }
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
 -                                      return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
 -                                                          p, compat_mode);
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
 +                              return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
 +                                                  p, compat_mode);
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
 -                                      return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
 -                                                          p, compat_mode);
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
 +                              return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
 +                                                  p, compat_mode);
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
 -                                      return str_to_user(dev->name, _IOC_SIZE(cmd), p);
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
 +                              return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
 +                                                  p, compat_mode);
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
 -                                      return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
 +                              return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
 +                                                  p, compat_mode);
  
 -                              if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
 -                                      return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
 +                              return str_to_user(dev->name, _IOC_SIZE(cmd), p);
  
 -                              if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
 +                              return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
  
 -                                      t = _IOC_NR(cmd) & ABS_MAX;
 +                      if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
 +                              return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
  
 -                                      abs.value = dev->abs[t];
 -                                      abs.minimum = dev->absmin[t];
 -                                      abs.maximum = dev->absmax[t];
 -                                      abs.fuzz = dev->absfuzz[t];
 -                                      abs.flat = dev->absflat[t];
 +                      if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
  
 -                                      if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
 -                                              return -EFAULT;
 +                              t = _IOC_NR(cmd) & ABS_MAX;
  
 -                                      return 0;
 -                              }
 +                              abs.value = dev->abs[t];
 +                              abs.minimum = dev->absmin[t];
 +                              abs.maximum = dev->absmax[t];
 +                              abs.fuzz = dev->absfuzz[t];
 +                              abs.flat = dev->absflat[t];
  
 +                              if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
 +                                      return -EFAULT;
 +
 +                              return 0;
                        }
  
 -                      if (_IOC_DIR(cmd) == _IOC_WRITE) {
 +              }
  
 -                              if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 +              if (_IOC_DIR(cmd) == _IOC_WRITE) {
  
 -                                      t = _IOC_NR(cmd) & ABS_MAX;
 +                      if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
  
 -                                      if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
 -                                              return -EFAULT;
 +                              t = _IOC_NR(cmd) & ABS_MAX;
  
 -                                      dev->abs[t] = abs.value;
 -                                      dev->absmin[t] = abs.minimum;
 -                                      dev->absmax[t] = abs.maximum;
 -                                      dev->absfuzz[t] = abs.fuzz;
 -                                      dev->absflat[t] = abs.flat;
 +                              if (copy_from_user(&abs, p,
 +                                              sizeof(struct input_absinfo)))
 +                                      return -EFAULT;
  
 -                                      return 0;
 -                              }
 +                              /*
 +                               * Take event lock to ensure that we are not
 +                               * changing device parameters in the middle
 +                               * of event.
 +                               */
 +                              spin_lock_irq(&dev->event_lock);
 +
 +                              dev->abs[t] = abs.value;
 +                              dev->absmin[t] = abs.minimum;
 +                              dev->absmax[t] = abs.maximum;
 +                              dev->absfuzz[t] = abs.fuzz;
 +                              dev->absflat[t] = abs.flat;
 +
 +                              spin_unlock_irq(&dev->event_lock);
 +
 +                              return 0;
                        }
 +              }
        }
        return -EINVAL;
  }
  
 +static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 +                              void __user *p, int compat_mode)
 +{
 +      struct evdev_client *client = file->private_data;
 +      struct evdev *evdev = client->evdev;
 +      int retval;
 +
 +      retval = mutex_lock_interruptible(&evdev->mutex);
 +      if (retval)
 +              return retval;
 +
 +      if (!evdev->exist) {
 +              retval = -ENODEV;
 +              goto out;
 +      }
 +
 +      retval = evdev_do_ioctl(file, cmd, p, compat_mode);
 +
 + out:
 +      mutex_unlock(&evdev->mutex);
 +      return retval;
 +}
 +
  static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
        return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0);
  }
  
  #ifdef CONFIG_COMPAT
 -static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
 +static long evdev_ioctl_compat(struct file *file,
 +                              unsigned int cmd, unsigned long arg)
  {
        return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
  }
  #endif
  
  static const struct file_operations evdev_fops = {
 -      .owner =        THIS_MODULE,
 -      .read =         evdev_read,
 -      .write =        evdev_write,
 -      .poll =         evdev_poll,
 -      .open =         evdev_open,
 -      .release =      evdev_release,
 -      .unlocked_ioctl = evdev_ioctl,
 +      .owner          = THIS_MODULE,
 +      .read           = evdev_read,
 +      .write          = evdev_write,
 +      .poll           = evdev_poll,
 +      .open           = evdev_open,
 +      .release        = evdev_release,
 +      .unlocked_ioctl = evdev_ioctl,
  #ifdef CONFIG_COMPAT
 -      .compat_ioctl = evdev_ioctl_compat,
 +      .compat_ioctl   = evdev_ioctl_compat,
  #endif
 -      .fasync =       evdev_fasync,
 -      .flush =        evdev_flush
 +      .fasync         = evdev_fasync,
 +      .flush          = evdev_flush
  };
  
 +static int evdev_install_chrdev(struct evdev *evdev)
 +{
 +      /*
 +       * No need to do any locking here as calls to connect and
 +       * disconnect are serialized by the input core
 +       */
 +      evdev_table[evdev->minor] = evdev;
 +      return 0;
 +}
 +
 +static void evdev_remove_chrdev(struct evdev *evdev)
 +{
 +      /*
 +       * Lock evdev table to prevent race with evdev_open()
 +       */
 +      mutex_lock(&evdev_table_mutex);
 +      evdev_table[evdev->minor] = NULL;
 +      mutex_unlock(&evdev_table_mutex);
 +}
 +
 +/*
 + * Mark device non-existent. This disables writes, ioctls and
 + * prevents new users from opening the device. Already posted
 + * blocking reads will stay, however new ones will fail.
 + */
 +static void evdev_mark_dead(struct evdev *evdev)
 +{
 +      mutex_lock(&evdev->mutex);
 +      evdev->exist = 0;
 +      mutex_unlock(&evdev->mutex);
 +}
 +
 +static void evdev_cleanup(struct evdev *evdev)
 +{
 +      struct input_handle *handle = &evdev->handle;
 +
 +      evdev_mark_dead(evdev);
 +      evdev_hangup(evdev);
 +      evdev_remove_chrdev(evdev);
 +
 +      /* evdev is marked dead so no one else accesses evdev->open */
 +      if (evdev->open) {
 +              input_flush_device(handle, NULL);
 +              input_close_device(handle);
 +      }
 +}
 +
 +/*
 + * Create new evdev device. Note that input core serializes calls
 + * to connect and disconnect so we don't need to lock evdev_table here.
 + */
  static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
                         const struct input_device_id *id)
  {
        int minor;
        int error;
  
 -      for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
 +      for (minor = 0; minor < EVDEV_MINORS; minor++)
 +              if (!evdev_table[minor])
 +                      break;
 +
        if (minor == EVDEV_MINORS) {
                printk(KERN_ERR "evdev: no more free evdev devices\n");
                return -ENFILE;
                return -ENOMEM;
  
        INIT_LIST_HEAD(&evdev->client_list);
 +      spin_lock_init(&evdev->client_lock);
 +      mutex_init(&evdev->mutex);
        init_waitqueue_head(&evdev->wait);
  
 +      snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
        evdev->exist = 1;
        evdev->minor = minor;
 +
        evdev->handle.dev = dev;
        evdev->handle.name = evdev->name;
        evdev->handle.handler = handler;
        evdev->handle.private = evdev;
 -      snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
  
 -      snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
 -               "event%d", minor);
 +      strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id));
 +      evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
        evdev->dev.class = &input_class;
        evdev->dev.parent = &dev->dev;
 -      evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
        evdev->dev.release = evdev_free;
        device_initialize(&evdev->dev);
  
 -      evdev_table[minor] = evdev;
 -
 -      error = device_add(&evdev->dev);
 +      error = input_register_handle(&evdev->handle);
        if (error)
                goto err_free_evdev;
  
 -      error = input_register_handle(&evdev->handle);
 +      error = evdev_install_chrdev(evdev);
 +      if (error)
 +              goto err_unregister_handle;
 +
 +      error = device_add(&evdev->dev);
        if (error)
 -              goto err_delete_evdev;
 +              goto err_cleanup_evdev;
  
        return 0;
  
 - err_delete_evdev:
 -      device_del(&evdev->dev);
 + err_cleanup_evdev:
 +      evdev_cleanup(evdev);
 + err_unregister_handle:
 +      input_unregister_handle(&evdev->handle);
   err_free_evdev:
        put_device(&evdev->dev);
        return error;
  static void evdev_disconnect(struct input_handle *handle)
  {
        struct evdev *evdev = handle->private;
 -      struct evdev_client *client;
  
 -      input_unregister_handle(handle);
        device_del(&evdev->dev);
 -
 -      evdev->exist = 0;
 -
 -      if (evdev->open) {
 -              input_flush_device(handle, NULL);
 -              input_close_device(handle);
 -              list_for_each_entry(client, &evdev->client_list, node)
 -                      kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 -              wake_up_interruptible(&evdev->wait);
 -      }
 -
 +      evdev_cleanup(evdev);
 +      input_unregister_handle(handle);
        put_device(&evdev->dev);
  }
  
@@@ -950,13 -714,13 +950,13 @@@ static const struct input_device_id evd
  MODULE_DEVICE_TABLE(input, evdev_ids);
  
  static struct input_handler evdev_handler = {
 -      .event =        evdev_event,
 -      .connect =      evdev_connect,
 -      .disconnect =   evdev_disconnect,
 -      .fops =         &evdev_fops,
 -      .minor =        EVDEV_MINOR_BASE,
 -      .name =         "evdev",
 -      .id_table =     evdev_ids,
 +      .event          = evdev_event,
 +      .connect        = evdev_connect,
 +      .disconnect     = evdev_disconnect,
 +      .fops           = &evdev_fops,
 +      .minor          = EVDEV_MINOR_BASE,
 +      .name           = "evdev",
 +      .id_table       = evdev_ids,
  };
  
  static int __init evdev_init(void)
diff --combined drivers/input/input.c
index c59544f7e232c39977207de79c8e072578572a31,5dc361c954e2aa92a3632117bdd4575bc9f23382..3070c7aa123718bb81293076924a7665f0710eff
  #include <linux/major.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
 -#include <linux/interrupt.h>
  #include <linux/poll.h>
  #include <linux/device.h>
  #include <linux/mutex.h>
 +#include <linux/rcupdate.h>
  
  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
  MODULE_DESCRIPTION("Input core");
@@@ -31,244 -31,167 +31,244 @@@ MODULE_LICENSE("GPL")
  static LIST_HEAD(input_dev_list);
  static LIST_HEAD(input_handler_list);
  
 +/*
 + * input_mutex protects access to both input_dev_list and input_handler_list.
 + * This also causes input_[un]register_device and input_[un]register_handler
 + * be mutually exclusive which simplifies locking in drivers implementing
 + * input handlers.
 + */
 +static DEFINE_MUTEX(input_mutex);
 +
  static struct input_handler *input_table[8];
  
 -/**
 - * input_event() - report new input event
 - * @dev: device that generated the event
 - * @type: type of the event
 - * @code: event code
 - * @value: value of the event
 - *
 - * This function should be used by drivers implementing various input devices
 - * See also input_inject_event()
 - */
 -void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 +static inline int is_event_supported(unsigned int code,
 +                                   unsigned long *bm, unsigned int max)
  {
 -      struct input_handle *handle;
 +      return code <= max && test_bit(code, bm);
 +}
  
 -      if (type > EV_MAX || !test_bit(type, dev->evbit))
 -              return;
 +static int input_defuzz_abs_event(int value, int old_val, int fuzz)
 +{
 +      if (fuzz) {
 +              if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2)
 +                      return old_val;
  
 -      add_input_randomness(type, code, value);
 +              if (value > old_val - fuzz && value < old_val + fuzz)
 +                      return (old_val * 3 + value) / 4;
  
 -      switch (type) {
 +              if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
 +                      return (old_val + value) / 2;
 +      }
  
 -              case EV_SYN:
 -                      switch (code) {
 -                              case SYN_CONFIG:
 -                                      if (dev->event)
 -                                              dev->event(dev, type, code, value);
 -                                      break;
 -
 -                              case SYN_REPORT:
 -                                      if (dev->sync)
 -                                              return;
 -                                      dev->sync = 1;
 -                                      break;
 -                      }
 -                      break;
 +      return value;
 +}
  
 -              case EV_KEY:
 +/*
 + * Pass event through all open handles. This function is called with
 + * dev->event_lock held and interrupts disabled. Because of that we
 + * do not need to use rcu_read_lock() here although we are using RCU
 + * to access handle list. Note that because of that write-side uses
 + * synchronize_sched() instead of synchronize_ru().
 + */
 +static void input_pass_event(struct input_dev *dev,
 +                           unsigned int type, unsigned int code, int value)
 +{
 +      struct input_handle *handle = rcu_dereference(dev->grab);
  
 -                      if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value)
 -                              return;
 +      if (handle)
 +              handle->handler->event(handle, type, code, value);
 +      else
 +              list_for_each_entry_rcu(handle, &dev->h_list, d_node)
 +                      if (handle->open)
 +                              handle->handler->event(handle,
 +                                                      type, code, value);
 +}
  
 -                      if (value == 2)
 -                              break;
 +/*
 + * Generate software autorepeat event. Note that we take
 + * dev->event_lock here to avoid racing with input_event
 + * which may cause keys get "stuck".
 + */
 +static void input_repeat_key(unsigned long data)
 +{
 +      struct input_dev *dev = (void *) data;
 +      unsigned long flags;
  
 -                      change_bit(code, dev->key);
 +      spin_lock_irqsave(&dev->event_lock, flags);
  
 -                      if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) {
 -                              dev->repeat_key = code;
 -                              mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
 -                      }
 +      if (test_bit(dev->repeat_key, dev->key) &&
 +          is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
  
 -                      break;
 +              input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
  
 -              case EV_SW:
 +              if (dev->sync) {
 +                      /*
 +                       * Only send SYN_REPORT if we are not in a middle
 +                       * of driver parsing a new hardware packet.
 +                       * Otherwise assume that the driver will send
 +                       * SYN_REPORT once it's done.
 +                       */
 +                      input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
 +              }
  
 -                      if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value)
 -                              return;
 +              if (dev->rep[REP_PERIOD])
 +                      mod_timer(&dev->timer, jiffies +
 +                                      msecs_to_jiffies(dev->rep[REP_PERIOD]));
 +      }
  
 -                      change_bit(code, dev->sw);
 +      spin_unlock_irqrestore(&dev->event_lock, flags);
 +}
  
 -                      break;
 +static void input_start_autorepeat(struct input_dev *dev, int code)
 +{
 +      if (test_bit(EV_REP, dev->evbit) &&
 +          dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
 +          dev->timer.data) {
 +              dev->repeat_key = code;
 +              mod_timer(&dev->timer,
 +                        jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
 +      }
 +}
  
 -              case EV_ABS:
 +#define INPUT_IGNORE_EVENT    0
 +#define INPUT_PASS_TO_HANDLERS        1
 +#define INPUT_PASS_TO_DEVICE  2
 +#define INPUT_PASS_TO_ALL     (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
  
 -                      if (code > ABS_MAX || !test_bit(code, dev->absbit))
 -                              return;
 +static void input_handle_event(struct input_dev *dev,
 +                             unsigned int type, unsigned int code, int value)
 +{
 +      int disposition = INPUT_IGNORE_EVENT;
  
 -                      if (dev->absfuzz[code]) {
 -                              if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) &&
 -                                  (value < dev->abs[code] + (dev->absfuzz[code] >> 1)))
 -                                      return;
 +      switch (type) {
  
 -                              if ((value > dev->abs[code] - dev->absfuzz[code]) &&
 -                                  (value < dev->abs[code] + dev->absfuzz[code]))
 -                                      value = (dev->abs[code] * 3 + value) >> 2;
 +      case EV_SYN:
 +              switch (code) {
 +              case SYN_CONFIG:
 +                      disposition = INPUT_PASS_TO_ALL;
 +                      break;
  
 -                              if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) &&
 -                                  (value < dev->abs[code] + (dev->absfuzz[code] << 1)))
 -                                      value = (dev->abs[code] + value) >> 1;
 +              case SYN_REPORT:
 +                      if (!dev->sync) {
 +                              dev->sync = 1;
 +                              disposition = INPUT_PASS_TO_HANDLERS;
                        }
 -
 -                      if (dev->abs[code] == value)
 -                              return;
 -
 -                      dev->abs[code] = value;
                        break;
 +              }
 +              break;
  
 -              case EV_REL:
 +      case EV_KEY:
 +              if (is_event_supported(code, dev->keybit, KEY_MAX) &&
 +                  !!test_bit(code, dev->key) != value) {
  
 -                      if (code > REL_MAX || !test_bit(code, dev->relbit) || (value == 0))
 -                              return;
 +                      if (value != 2) {
 +                              __change_bit(code, dev->key);
 +                              if (value)
 +                                      input_start_autorepeat(dev, code);
 +                      }
  
 -                      break;
 +                      disposition = INPUT_PASS_TO_HANDLERS;
 +              }
 +              break;
  
 -              case EV_MSC:
 +      case EV_SW:
 +              if (is_event_supported(code, dev->swbit, SW_MAX) &&
 +                  !!test_bit(code, dev->sw) != value) {
  
 -                      if (code > MSC_MAX || !test_bit(code, dev->mscbit))
 -                              return;
 +                      __change_bit(code, dev->sw);
 +                      disposition = INPUT_PASS_TO_HANDLERS;
 +              }
 +              break;
  
 -                      if (dev->event)
 -                              dev->event(dev, type, code, value);
 +      case EV_ABS:
 +              if (is_event_supported(code, dev->absbit, ABS_MAX)) {
  
 -                      break;
 +                      value = input_defuzz_abs_event(value,
 +                                      dev->abs[code], dev->absfuzz[code]);
  
 -              case EV_LED:
 +                      if (dev->abs[code] != value) {
 +                              dev->abs[code] = value;
 +                              disposition = INPUT_PASS_TO_HANDLERS;
 +                      }
 +              }
 +              break;
  
 -                      if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value)
 -                              return;
 +      case EV_REL:
 +              if (is_event_supported(code, dev->relbit, REL_MAX) && value)
 +                      disposition = INPUT_PASS_TO_HANDLERS;
  
 -                      change_bit(code, dev->led);
 +              break;
  
 -                      if (dev->event)
 -                              dev->event(dev, type, code, value);
 +      case EV_MSC:
 +              if (is_event_supported(code, dev->mscbit, MSC_MAX))
 +                      disposition = INPUT_PASS_TO_ALL;
  
 -                      break;
 +              break;
  
 -              case EV_SND:
 +      case EV_LED:
 +              if (is_event_supported(code, dev->ledbit, LED_MAX) &&
 +                  !!test_bit(code, dev->led) != value) {
  
 -                      if (code > SND_MAX || !test_bit(code, dev->sndbit))
 -                              return;
 +                      __change_bit(code, dev->led);
 +                      disposition = INPUT_PASS_TO_ALL;
 +              }
 +              break;
 +
 +      case EV_SND:
 +              if (is_event_supported(code, dev->sndbit, SND_MAX)) {
  
                        if (!!test_bit(code, dev->snd) != !!value)
 -                              change_bit(code, dev->snd);
 +                              __change_bit(code, dev->snd);
 +                      disposition = INPUT_PASS_TO_ALL;
 +              }
 +              break;
  
 -                      if (dev->event)
 -                              dev->event(dev, type, code, value);
 +      case EV_REP:
 +              if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
 +                      dev->rep[code] = value;
 +                      disposition = INPUT_PASS_TO_ALL;
 +              }
 +              break;
  
 -                      break;
 +      case EV_FF:
 +              if (value >= 0)
 +                      disposition = INPUT_PASS_TO_ALL;
 +              break;
 +      }
  
 -              case EV_REP:
 +      if (type != EV_SYN)
 +              dev->sync = 0;
  
 -                      if (code > REP_MAX || value < 0 || dev->rep[code] == value)
 -                              return;
 +      if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
 +              dev->event(dev, type, code, value);
  
 -                      dev->rep[code] = value;
 -                      if (dev->event)
 -                              dev->event(dev, type, code, value);
 +      if (disposition & INPUT_PASS_TO_HANDLERS)
 +              input_pass_event(dev, type, code, value);
 +}
  
 -                      break;
 +/**
 + * input_event() - report new input event
 + * @dev: device that generated the event
 + * @type: type of the event
 + * @code: event code
 + * @value: value of the event
 + *
 + * This function should be used by drivers implementing various input
 + * devices. See also input_inject_event().
 + */
  
 -              case EV_FF:
 +void input_event(struct input_dev *dev,
 +               unsigned int type, unsigned int code, int value)
 +{
 +      unsigned long flags;
  
 -                      if (value < 0)
 -                              return;
 +      if (is_event_supported(type, dev->evbit, EV_MAX)) {
  
 -                      if (dev->event)
 -                              dev->event(dev, type, code, value);
 -                      break;
 +              spin_lock_irqsave(&dev->event_lock, flags);
 +              add_input_randomness(type, code, value);
 +              input_handle_event(dev, type, code, value);
 +              spin_unlock_irqrestore(&dev->event_lock, flags);
        }
 -
 -      if (type != EV_SYN)
 -              dev->sync = 0;
 -
 -      if (dev->grab)
 -              dev->grab->handler->event(dev->grab, type, code, value);
 -      else
 -              list_for_each_entry(handle, &dev->h_list, d_node)
 -                      if (handle->open)
 -                              handle->handler->event(handle, type, code, value);
  }
  EXPORT_SYMBOL(input_event);
  
   * @code: event code
   * @value: value of the event
   *
 - * Similar to input_event() but will ignore event if device is "grabbed" and handle
 - * injecting event is not the one that owns the device.
 + * Similar to input_event() but will ignore event if device is
 + * "grabbed" and handle injecting event is not the one that owns
 + * the device.
   */
 -void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 -{
 -      if (!handle->dev->grab || handle->dev->grab == handle)
 -              input_event(handle->dev, type, code, value);
 -}
 -EXPORT_SYMBOL(input_inject_event);
 -
 -static void input_repeat_key(unsigned long data)
 +void input_inject_event(struct input_handle *handle,
 +                      unsigned int type, unsigned int code, int value)
  {
 -      struct input_dev *dev = (void *) data;
 +      struct input_dev *dev = handle->dev;
 +      struct input_handle *grab;
 +      unsigned long flags;
  
 -      if (!test_bit(dev->repeat_key, dev->key))
 -              return;
 +      if (is_event_supported(type, dev->evbit, EV_MAX)) {
 +              spin_lock_irqsave(&dev->event_lock, flags);
  
 -      input_event(dev, EV_KEY, dev->repeat_key, 2);
 -      input_sync(dev);
 +              grab = rcu_dereference(dev->grab);
 +              if (!grab || grab == handle)
 +                      input_handle_event(dev, type, code, value);
  
 -      if (dev->rep[REP_PERIOD])
 -              mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
 +              spin_unlock_irqrestore(&dev->event_lock, flags);
 +      }
  }
 +EXPORT_SYMBOL(input_inject_event);
  
 +/**
 + * input_grab_device - grabs device for exclusive use
 + * @handle: input handle that wants to own the device
 + *
 + * When a device is grabbed by an input handle all events generated by
 + * the device are delivered only to this handle. Also events injected
 + * by other input handles are ignored while device is grabbed.
 + */
  int input_grab_device(struct input_handle *handle)
  {
 -      if (handle->dev->grab)
 -              return -EBUSY;
 +      struct input_dev *dev = handle->dev;
 +      int retval;
  
 -      handle->dev->grab = handle;
 -      return 0;
 +      retval = mutex_lock_interruptible(&dev->mutex);
 +      if (retval)
 +              return retval;
 +
 +      if (dev->grab) {
 +              retval = -EBUSY;
 +              goto out;
 +      }
 +
 +      rcu_assign_pointer(dev->grab, handle);
 +      /*
 +       * Not using synchronize_rcu() because read-side is protected
 +       * by a spinlock with interrupts off instead of rcu_read_lock().
 +       */
 +      synchronize_sched();
 +
 + out:
 +      mutex_unlock(&dev->mutex);
 +      return retval;
  }
  EXPORT_SYMBOL(input_grab_device);
  
 -void input_release_device(struct input_handle *handle)
 +static void __input_release_device(struct input_handle *handle)
  {
        struct input_dev *dev = handle->dev;
  
        if (dev->grab == handle) {
 -              dev->grab = NULL;
 +              rcu_assign_pointer(dev->grab, NULL);
 +              /* Make sure input_pass_event() notices that grab is gone */
 +              synchronize_sched();
  
                list_for_each_entry(handle, &dev->h_list, d_node)
 -                      if (handle->handler->start)
 +                      if (handle->open && handle->handler->start)
                                handle->handler->start(handle);
        }
  }
 +
 +/**
 + * input_release_device - release previously grabbed device
 + * @handle: input handle that owns the device
 + *
 + * Releases previously grabbed device so that other input handles can
 + * start receiving input events. Upon release all handlers attached
 + * to the device have their start() method called so they have a change
 + * to synchronize device state with the rest of the system.
 + */
 +void input_release_device(struct input_handle *handle)
 +{
 +      struct input_dev *dev = handle->dev;
 +
 +      mutex_lock(&dev->mutex);
 +      __input_release_device(handle);
 +      mutex_unlock(&dev->mutex);
 +}
  EXPORT_SYMBOL(input_release_device);
  
 +/**
 + * input_open_device - open input device
 + * @handle: handle through which device is being accessed
 + *
 + * This function should be called by input handlers when they
 + * want to start receive events from given input device.
 + */
  int input_open_device(struct input_handle *handle)
  {
        struct input_dev *dev = handle->dev;
 -      int err;
 +      int retval;
  
 -      err = mutex_lock_interruptible(&dev->mutex);
 -      if (err)
 -              return err;
 +      retval = mutex_lock_interruptible(&dev->mutex);
 +      if (retval)
 +              return retval;
 +
 +      if (dev->going_away) {
 +              retval = -ENODEV;
 +              goto out;
 +      }
  
        handle->open++;
  
        if (!dev->users++ && dev->open)
 -              err = dev->open(dev);
 -
 -      if (err)
 -              handle->open--;
 +              retval = dev->open(dev);
 +
 +      if (retval) {
 +              dev->users--;
 +              if (!--handle->open) {
 +                      /*
 +                       * Make sure we are not delivering any more events
 +                       * through this handle
 +                       */
 +                      synchronize_sched();
 +              }
 +      }
  
 + out:
        mutex_unlock(&dev->mutex);
 -
 -      return err;
 +      return retval;
  }
  EXPORT_SYMBOL(input_open_device);
  
 -int input_flush_device(struct input_handle* handle, struct file* file)
 +int input_flush_device(struct input_handle *handle, struct file *file)
  {
 -      if (handle->dev->flush)
 -              return handle->dev->flush(handle->dev, file);
 +      struct input_dev *dev = handle->dev;
 +      int retval;
  
 -      return 0;
 +      retval = mutex_lock_interruptible(&dev->mutex);
 +      if (retval)
 +              return retval;
 +
 +      if (dev->flush)
 +              retval = dev->flush(dev, file);
 +
 +      mutex_unlock(&dev->mutex);
 +      return retval;
  }
  EXPORT_SYMBOL(input_flush_device);
  
 +/**
 + * input_close_device - close input device
 + * @handle: handle through which device is being accessed
 + *
 + * This function should be called by input handlers when they
 + * want to stop receive events from given input device.
 + */
  void input_close_device(struct input_handle *handle)
  {
        struct input_dev *dev = handle->dev;
  
 -      input_release_device(handle);
 -
        mutex_lock(&dev->mutex);
  
 +      __input_release_device(handle);
 +
        if (!--dev->users && dev->close)
                dev->close(dev);
 -      handle->open--;
 +
 +      if (!--handle->open) {
 +              /*
 +               * synchronize_sched() makes sure that input_pass_event()
 +               * completed and that no more input events are delivered
 +               * through this handle
 +               */
 +              synchronize_sched();
 +      }
  
        mutex_unlock(&dev->mutex);
  }
  EXPORT_SYMBOL(input_close_device);
  
 +/*
 + * Prepare device for unregistering
 + */
 +static void input_disconnect_device(struct input_dev *dev)
 +{
 +      struct input_handle *handle;
 +      int code;
 +
 +      /*
 +       * Mark device as going away. Note that we take dev->mutex here
 +       * not to protect access to dev->going_away but rather to ensure
 +       * that there are no threads in the middle of input_open_device()
 +       */
 +      mutex_lock(&dev->mutex);
 +      dev->going_away = 1;
 +      mutex_unlock(&dev->mutex);
 +
 +      spin_lock_irq(&dev->event_lock);
 +
 +      /*
 +       * Simulate keyup events for all pressed keys so that handlers
 +       * are not left with "stuck" keys. The driver may continue
 +       * generate events even after we done here but they will not
 +       * reach any handlers.
 +       */
 +      if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
 +              for (code = 0; code <= KEY_MAX; code++) {
 +                      if (is_event_supported(code, dev->keybit, KEY_MAX) &&
 +                          test_bit(code, dev->key)) {
 +                              input_pass_event(dev, EV_KEY, code, 0);
 +                      }
 +              }
 +              input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
 +      }
 +
 +      list_for_each_entry(handle, &dev->h_list, d_node)
 +              handle->open = 0;
 +
 +      spin_unlock_irq(&dev->event_lock);
 +}
 +
  static int input_fetch_keycode(struct input_dev *dev, int scancode)
  {
        switch (dev->keycodesize) {
@@@ -678,8 -473,7 +678,8 @@@ static unsigned int input_proc_devices_
  
  static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
  {
 -      /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
 +      if (mutex_lock_interruptible(&input_mutex))
 +              return NULL;
  
        return seq_list_start(&input_dev_list, *pos);
  }
@@@ -691,7 -485,7 +691,7 @@@ static void *input_devices_seq_next(str
  
  static void input_devices_seq_stop(struct seq_file *seq, void *v)
  {
 -      /* release lock here */
 +      mutex_unlock(&input_mutex);
  }
  
  static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
@@@ -775,9 -569,7 +775,9 @@@ static const struct file_operations inp
  
  static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
  {
 -      /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
 +      if (mutex_lock_interruptible(&input_mutex))
 +              return NULL;
 +
        seq->private = (void *)(unsigned long)*pos;
        return seq_list_start(&input_handler_list, *pos);
  }
@@@ -790,7 -582,7 +790,7 @@@ static void *input_handlers_seq_next(st
  
  static void input_handlers_seq_stop(struct seq_file *seq, void *v)
  {
 -      /* release lock here */
 +      mutex_unlock(&input_mutex);
  }
  
  static int input_handlers_seq_show(struct seq_file *seq, void *v)
@@@ -1067,87 -859,66 +1067,66 @@@ static void input_dev_release(struct de
   * Input uevent interface - loading event handlers based on
   * device bitfields.
   */
- static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
-                                  char *buffer, int buffer_size, int *cur_len,
+ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
                                   const char *name, unsigned long *bitmap, int max)
  {
-       if (*cur_index >= num_envp - 1)
-               return -ENOMEM;
-       envp[*cur_index] = buffer + *cur_len;
+       int len;
  
-       *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
-       if (*cur_len >= buffer_size)
+       if (add_uevent_var(env, "%s=", name))
                return -ENOMEM;
  
-       *cur_len += input_print_bitmap(buffer + *cur_len,
-                                       max(buffer_size - *cur_len, 0),
-                                       bitmap, max, 0) + 1;
-       if (*cur_len > buffer_size)
+       len = input_print_bitmap(&env->buf[env->buflen - 1],
+                                sizeof(env->buf) - env->buflen,
+                                bitmap, max, 0);
+       if (len >= (sizeof(env->buf) - env->buflen))
                return -ENOMEM;
  
-       (*cur_index)++;
+       env->buflen += len;
        return 0;
  }
  
- static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
-                                        char *buffer, int buffer_size, int *cur_len,
+ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
                                         struct input_dev *dev)
  {
-       if (*cur_index >= num_envp - 1)
-               return -ENOMEM;
-       envp[*cur_index] = buffer + *cur_len;
+       int len;
  
-       *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
-                            "MODALIAS=");
-       if (*cur_len >= buffer_size)
+       if (add_uevent_var(env, "MODALIAS="))
                return -ENOMEM;
  
-       *cur_len += input_print_modalias(buffer + *cur_len,
-                                        max(buffer_size - *cur_len, 0),
-                                        dev, 0) + 1;
-       if (*cur_len > buffer_size)
+       len = input_print_modalias(&env->buf[env->buflen - 1],
+                                  sizeof(env->buf) - env->buflen,
+                                  dev, 0);
+       if (len >= (sizeof(env->buf) - env->buflen))
                return -ENOMEM;
  
-       (*cur_index)++;
+       env->buflen += len;
        return 0;
  }
  
  #define INPUT_ADD_HOTPLUG_VAR(fmt, val...)                            \
        do {                                                            \
-               int err = add_uevent_var(envp, num_envp, &i,            \
-                                       buffer, buffer_size, &len,      \
-                                       fmt, val);                      \
+               int err = add_uevent_var(env, fmt, val);                \
                if (err)                                                \
                        return err;                                     \
        } while (0)
  
  #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max)                               \
        do {                                                            \
-               int err = input_add_uevent_bm_var(envp, num_envp, &i,   \
-                                       buffer, buffer_size, &len,      \
-                                       name, bm, max);                 \
+               int err = input_add_uevent_bm_var(env, name, bm, max);  \
                if (err)                                                \
                        return err;                                     \
        } while (0)
  
  #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev)                           \
        do {                                                            \
-               int err = input_add_uevent_modalias_var(envp,           \
-                                       num_envp, &i,                   \
-                                       buffer, buffer_size, &len,      \
-                                       dev);                           \
+               int err = input_add_uevent_modalias_var(env, dev);      \
                if (err)                                                \
                        return err;                                     \
        } while (0)
  
- static int input_dev_uevent(struct device *device, char **envp,
-                           int num_envp, char *buffer, int buffer_size)
+ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
  {
        struct input_dev *dev = to_input_dev(device);
-       int i = 0;
-       int len = 0;
  
        INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
                                dev->id.bustype, dev->id.vendor,
  
        INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
  
-       envp[i] = NULL;
        return 0;
  }
  
@@@ -1213,7 -983,6 +1191,7 @@@ struct input_dev *input_allocate_device
                dev->dev.class = &input_class;
                device_initialize(&dev->dev);
                mutex_init(&dev->mutex);
 +              spin_lock_init(&dev->event_lock);
                INIT_LIST_HEAD(&dev->h_list);
                INIT_LIST_HEAD(&dev->node);
  
@@@ -1231,7 -1000,7 +1209,7 @@@ EXPORT_SYMBOL(input_allocate_device)
   * This function should only be used if input_register_device()
   * was not called yet or if it failed. Once device was registered
   * use input_unregister_device() and memory will be freed once last
 - * refrence to the device is dropped.
 + * reference to the device is dropped.
   *
   * Device should be allocated by input_allocate_device().
   *
@@@ -1301,18 -1070,6 +1279,18 @@@ void input_set_capability(struct input_
  }
  EXPORT_SYMBOL(input_set_capability);
  
 +/**
 + * input_register_device - register device with input core
 + * @dev: device to be registered
 + *
 + * This function registers device with input core. The device must be
 + * allocated with input_allocate_device() and all it's capabilities
 + * set up before registering.
 + * If function fails the device must be freed with input_free_device().
 + * Once device has been successfully registered it can be unregistered
 + * with input_unregister_device(); input_free_device() should not be
 + * called in this case.
 + */
  int input_register_device(struct input_dev *dev)
  {
        static atomic_t input_no = ATOMIC_INIT(0);
        const char *path;
        int error;
  
 -      set_bit(EV_SYN, dev->evbit);
 +      __set_bit(EV_SYN, dev->evbit);
  
        /*
         * If delay and period are pre-set by the driver, then autorepeating
        if (!dev->setkeycode)
                dev->setkeycode = input_default_setkeycode;
  
 -      list_add_tail(&dev->node, &input_dev_list);
 -
        snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
                 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
  
                dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
        kfree(path);
  
 +      error = mutex_lock_interruptible(&input_mutex);
 +      if (error) {
 +              device_del(&dev->dev);
 +              return error;
 +      }
 +
 +      list_add_tail(&dev->node, &input_dev_list);
 +
        list_for_each_entry(handler, &input_handler_list, node)
                input_attach_handler(dev, handler);
  
        input_wakeup_procfs_readers();
  
 +      mutex_unlock(&input_mutex);
 +
        return 0;
  }
  EXPORT_SYMBOL(input_register_device);
  
 +/**
 + * input_unregister_device - unregister previously registered device
 + * @dev: device to be unregistered
 + *
 + * This function unregisters an input device. Once device is unregistered
 + * the caller should not try to access it as it may get freed at any moment.
 + */
  void input_unregister_device(struct input_dev *dev)
  {
        struct input_handle *handle, *next;
 -      int code;
  
 -      for (code = 0; code <= KEY_MAX; code++)
 -              if (test_bit(code, dev->key))
 -                      input_report_key(dev, code, 0);
 -      input_sync(dev);
 +      input_disconnect_device(dev);
  
 -      del_timer_sync(&dev->timer);
 +      mutex_lock(&input_mutex);
  
        list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
                handle->handler->disconnect(handle);
        WARN_ON(!list_empty(&dev->h_list));
  
 +      del_timer_sync(&dev->timer);
        list_del_init(&dev->node);
  
 -      device_unregister(&dev->dev);
 -
        input_wakeup_procfs_readers();
 +
 +      mutex_unlock(&input_mutex);
 +
 +      device_unregister(&dev->dev);
  }
  EXPORT_SYMBOL(input_unregister_device);
  
 +/**
 + * input_register_handler - register a new input handler
 + * @handler: handler to be registered
 + *
 + * This function registers a new input handler (interface) for input
 + * devices in the system and attaches it to all input devices that
 + * are compatible with the handler.
 + */
  int input_register_handler(struct input_handler *handler)
  {
        struct input_dev *dev;
 +      int retval;
 +
 +      retval = mutex_lock_interruptible(&input_mutex);
 +      if (retval)
 +              return retval;
  
        INIT_LIST_HEAD(&handler->h_list);
  
        if (handler->fops != NULL) {
 -              if (input_table[handler->minor >> 5])
 -                      return -EBUSY;
 -
 +              if (input_table[handler->minor >> 5]) {
 +                      retval = -EBUSY;
 +                      goto out;
 +              }
                input_table[handler->minor >> 5] = handler;
        }
  
                input_attach_handler(dev, handler);
  
        input_wakeup_procfs_readers();
 -      return 0;
 +
 + out:
 +      mutex_unlock(&input_mutex);
 +      return retval;
  }
  EXPORT_SYMBOL(input_register_handler);
  
 +/**
 + * input_unregister_handler - unregisters an input handler
 + * @handler: handler to be unregistered
 + *
 + * This function disconnects a handler from its input devices and
 + * removes it from lists of known handlers.
 + */
  void input_unregister_handler(struct input_handler *handler)
  {
        struct input_handle *handle, *next;
  
 +      mutex_lock(&input_mutex);
 +
        list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
                handler->disconnect(handle);
        WARN_ON(!list_empty(&handler->h_list));
                input_table[handler->minor >> 5] = NULL;
  
        input_wakeup_procfs_readers();
 +
 +      mutex_unlock(&input_mutex);
  }
  EXPORT_SYMBOL(input_unregister_handler);
  
 +/**
 + * input_register_handle - register a new input handle
 + * @handle: handle to register
 + *
 + * This function puts a new input handle onto device's
 + * and handler's lists so that events can flow through
 + * it once it is opened using input_open_device().
 + *
 + * This function is supposed to be called from handler's
 + * connect() method.
 + */
  int input_register_handle(struct input_handle *handle)
  {
        struct input_handler *handler = handle->handler;
 +      struct input_dev *dev = handle->dev;
 +      int error;
 +
 +      /*
 +       * We take dev->mutex here to prevent race with
 +       * input_release_device().
 +       */
 +      error = mutex_lock_interruptible(&dev->mutex);
 +      if (error)
 +              return error;
 +      list_add_tail_rcu(&handle->d_node, &dev->h_list);
 +      mutex_unlock(&dev->mutex);
 +      /*
 +       * We don't use synchronize_rcu() here because we rely
 +       * on dev->event_lock to protect read-side critical
 +       * section in input_pass_event().
 +       */
 +      synchronize_sched();
  
 -      list_add_tail(&handle->d_node, &handle->dev->h_list);
 +      /*
 +       * Since we are supposed to be called from ->connect()
 +       * which is mutually exclusive with ->disconnect()
 +       * we can't be racing with input_unregister_handle()
 +       * and so separate lock is not needed here.
 +       */
        list_add_tail(&handle->h_node, &handler->h_list);
  
        if (handler->start)
  }
  EXPORT_SYMBOL(input_register_handle);
  
 +/**
 + * input_unregister_handle - unregister an input handle
 + * @handle: handle to unregister
 + *
 + * This function removes input handle from device's
 + * and handler's lists.
 + *
 + * This function is supposed to be called from handler's
 + * disconnect() method.
 + */
  void input_unregister_handle(struct input_handle *handle)
  {
 +      struct input_dev *dev = handle->dev;
 +
        list_del_init(&handle->h_node);
 -      list_del_init(&handle->d_node);
 +
 +      /*
 +       * Take dev->mutex to prevent race with input_release_device().
 +       */
 +      mutex_lock(&dev->mutex);
 +      list_del_rcu(&handle->d_node);
 +      mutex_unlock(&dev->mutex);
 +      synchronize_sched();
  }
  EXPORT_SYMBOL(input_unregister_handle);
  
index 3d6820b4465bb509a391bd4cc70f5449937eaf4c,f0b22b8b2769812a7d46e96b95be5129a0e8a3e7..e2a3293bc67ed37b66949747de99d0e3d4d1dfd9
@@@ -22,7 -22,6 +22,6 @@@
  #include <linux/delay.h>
  #include <linux/platform_device.h>
  #include <linux/input.h>
- #include <linux/irq.h>
  #include <linux/gpio_keys.h>
  
  #include <asm/gpio.h>
@@@ -55,7 -54,6 +54,7 @@@ static int __devinit gpio_keys_probe(st
        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
        struct input_dev *input;
        int i, error;
 +      int wakeup = 0;
  
        input = input_allocate_device();
        if (!input)
                int irq = gpio_to_irq(button->gpio);
                unsigned int type = button->type ?: EV_KEY;
  
 -              set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
 -              error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
 -                                   button->desc ? button->desc : "gpio_keys",
 -                                   pdev);
 +              if (irq < 0) {
 +                      error = irq;
 +                      printk(KERN_ERR
 +                              "gpio-keys: "
 +                              "Unable to get irq number for GPIO %d,"
 +                              "error %d\n",
 +                              button->gpio, error);
 +                      goto fail;
 +              }
 +
 +              error = request_irq(irq, gpio_keys_isr,
 +                                  IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
 +                                      IRQF_TRIGGER_FALLING,
 +                                  button->desc ? button->desc : "gpio_keys",
 +                                  pdev);
                if (error) {
 -                      printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
 +                      printk(KERN_ERR
 +                              "gpio-keys: Unable to claim irq %d; error %d\n",
                                irq, error);
                        goto fail;
                }
  
 +              if (button->wakeup)
 +                      wakeup = 1;
 +
                input_set_capability(input, type, button->code);
        }
  
        error = input_register_device(input);
        if (error) {
 -              printk(KERN_ERR "Unable to register gpio-keys input device\n");
 +              printk(KERN_ERR
 +                      "gpio-keys: Unable to register input device, "
 +                      "error: %d\n", error);
                goto fail;
        }
  
 +      device_init_wakeup(&pdev->dev, wakeup);
 +
        return 0;
  
   fail:
 -      for (i = i - 1; i >= 0; i--)
 +      while (--i >= 0)
                free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
  
 +      platform_set_drvdata(pdev, NULL);
        input_free_device(input);
  
        return error;
@@@ -135,8 -113,6 +134,8 @@@ static int __devexit gpio_keys_remove(s
        struct input_dev *input = platform_get_drvdata(pdev);
        int i;
  
 +      device_init_wakeup(&pdev->dev, 0);
 +
        for (i = 0; i < pdata->nbuttons; i++) {
                int irq = gpio_to_irq(pdata->buttons[i].gpio);
                free_irq(irq, pdev);
        return 0;
  }
  
 +
 +#ifdef CONFIG_PM
 +static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 +      int i;
 +
 +      if (device_may_wakeup(&pdev->dev)) {
 +              for (i = 0; i < pdata->nbuttons; i++) {
 +                      struct gpio_keys_button *button = &pdata->buttons[i];
 +                      if (button->wakeup) {
 +                              int irq = gpio_to_irq(button->gpio);
 +                              enable_irq_wake(irq);
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int gpio_keys_resume(struct platform_device *pdev)
 +{
 +      struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 +      int i;
 +
 +      if (device_may_wakeup(&pdev->dev)) {
 +              for (i = 0; i < pdata->nbuttons; i++) {
 +                      struct gpio_keys_button *button = &pdata->buttons[i];
 +                      if (button->wakeup) {
 +                              int irq = gpio_to_irq(button->gpio);
 +                              disable_irq_wake(irq);
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +#else
 +#define gpio_keys_suspend     NULL
 +#define gpio_keys_resume      NULL
 +#endif
 +
  struct platform_driver gpio_keys_device_driver = {
        .probe          = gpio_keys_probe,
        .remove         = __devexit_p(gpio_keys_remove),
 +      .suspend        = gpio_keys_suspend,
 +      .resume         = gpio_keys_resume,
        .driver         = {
                .name   = "gpio-keys",
        }
index 9561dee120c6208d928a74509da1f22f3dd8af3f,608674d0be8b25e95e5e9b165f0516bed34ff319..d7de4c53b3d8cb8cd853c14ae382f5f47f2fda83
@@@ -27,7 -27,7 +27,7 @@@ struct lifebook_data 
  
  static const char *desired_serio_phys;
  
- static int lifebook_set_serio_phys(struct dmi_system_id *d)
+ static int lifebook_set_serio_phys(const struct dmi_system_id *d)
  {
        desired_serio_phys = d->driver_data;
        return 0;
  
  static unsigned char lifebook_use_6byte_proto;
  
- static int lifebook_set_6byte_proto(struct dmi_system_id *d)
+ static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
  {
        lifebook_use_6byte_proto = 1;
        return 0;
  }
  
- static struct dmi_system_id lifebook_dmi_table[] = {
+ static const struct dmi_system_id lifebook_dmi_table[] = {
        {
                .ident = "FLORA-ie 55mi",
                .matches = {
                },
                .callback = lifebook_set_6byte_proto,
        },
 +      {
 +              .ident = "CF-72",
 +              .matches = {
 +                      DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"),
 +              },
 +              .callback = lifebook_set_serio_phys,
 +              .driver_data = "isa0060/serio3",
 +      },
        {
                .ident = "Lifebook B142",
                .matches = {
@@@ -117,7 -109,7 +117,7 @@@ static psmouse_ret_t lifebook_process_b
  {
        struct lifebook_data *priv = psmouse->private;
        struct input_dev *dev1 = psmouse->dev;
-       struct input_dev *dev2 = priv->dev2;
+       struct input_dev *dev2 = priv ? priv->dev2 : NULL;
        unsigned char *packet = psmouse->packet;
        int relative_packet = packet[0] & 0x08;
  
@@@ -290,7 -282,7 +290,7 @@@ static int lifebook_create_relative_dev
  int lifebook_init(struct psmouse *psmouse)
  {
        struct input_dev *dev1 = psmouse->dev;
 -      int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
 +      int max_coord = lifebook_use_6byte_proto ? 4096 : 1024;
  
        if (lifebook_absolute_mode(psmouse))
                return -1;
index 42aa4ec72661bbf020552f7f27ccb57abaaa35af,c2eea2767e1096ed9d1e5b16e6e09593df8d06f0..11dafc0ee9942145b937a85bbebe27578ed073c6
@@@ -385,8 -385,6 +385,8 @@@ static int i8042_enable_kbd_port(void
        i8042_ctr |= I8042_CTR_KBDINT;
  
        if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 +              i8042_ctr &= ~I8042_CTR_KBDINT;
 +              i8042_ctr |= I8042_CTR_KBDDIS;
                printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n");
                return -EIO;
        }
@@@ -404,8 -402,6 +404,8 @@@ static int i8042_enable_aux_port(void
        i8042_ctr |= I8042_CTR_AUXINT;
  
        if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 +              i8042_ctr &= ~I8042_CTR_AUXINT;
 +              i8042_ctr |= I8042_CTR_AUXDIS;
                printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n");
                return -EIO;
        }
@@@ -516,6 -512,7 +516,7 @@@ static irqreturn_t __devinit i8042_aux_
  {
        unsigned long flags;
        unsigned char str, data;
+       int ret = 0;
  
        spin_lock_irqsave(&i8042_lock, flags);
        str = i8042_read_status();
                if (i8042_irq_being_tested &&
                    data == 0xa5 && (str & I8042_STR_AUXDATA))
                        complete(&i8042_aux_irq_delivered);
+               ret = 1;
        }
        spin_unlock_irqrestore(&i8042_lock, flags);
  
-       return IRQ_HANDLED;
+       return IRQ_RETVAL(ret);
  }
  
  /*
@@@ -1042,7 -1040,7 +1044,7 @@@ static void __devinit i8042_register_po
        }
  }
  
- static void __devinit i8042_unregister_ports(void)
+ static void __devexit i8042_unregister_ports(void)
  {
        int i;
  
index 9b3a26cd1a8d2819e95905cec33021b49a260d2d,741f6c6f1e506f621e55ec8a580db0154db416cc..9fb3d5c309998162c5f14d40c6587e95c95395a5
@@@ -10,7 -10,6 +10,7 @@@
   *  - Gunze AHL61
   *  - DMC TSC-10/25
   *  - IRTOUCHSYSTEMS/UNITOP
 + *  - IdealTEK URTC1000
   *
   * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
   * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@@ -93,7 -92,7 +93,7 @@@ struct usbtouch_usb 
  };
  
  
 -#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO)
 +#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK)
  #define MULTI_PACKET
  #endif
  
@@@ -113,8 -112,6 +113,8 @@@ enum 
        DEVTYPE_GUNZE,
        DEVTYPE_DMC_TSC10,
        DEVTYPE_IRTOUCH,
 +      DEVTYPE_IDEALTEK,
 +      DEVTYPE_GENERAL_TOUCH,
  };
  
  static struct usb_device_id usbtouch_devices[] = {
        {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
  #endif
  
 +#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
 +      {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK},
 +#endif
 +
 +#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
 +      {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH},
 +#endif
 +
        {}
  };
  
@@@ -407,8 -396,7 +407,8 @@@ static int dmc_tsc10_init(struct usbtou
                              TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
        if (ret < 0)
                return ret;
 -      if (buf[0] != 0x06 || buf[1] != 0x00)
 +      if ((buf[0] != 0x06 || buf[1] != 0x00) &&
 +          (buf[0] != 0x15 || buf[1] != 0x01))
                return -ENODEV;
  
        /* start sending data */
@@@ -449,57 -437,6 +449,57 @@@ static int irtouch_read_data(struct usb
  #endif
  
  
 +/*****************************************************************************
 + * IdealTEK URTC1000 Part
 + */
 +#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
 +static int idealtek_get_pkt_len(unsigned char *buf, int len)
 +{
 +      if (buf[0] & 0x80)
 +              return 5;
 +      if (buf[0] == 0x01)
 +              return len;
 +      return 0;
 +}
 +
 +static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 +{
 +      switch (pkt[0] & 0x98) {
 +      case 0x88:
 +              /* touch data in IdealTEK mode */
 +              dev->x = (pkt[1] << 5) | (pkt[2] >> 2);
 +              dev->y = (pkt[3] << 5) | (pkt[4] >> 2);
 +              dev->touch = (pkt[0] & 0x40) ? 1 : 0;
 +              return 1;
 +
 +      case 0x98:
 +              /* touch data in MT emulation mode */
 +              dev->x = (pkt[2] << 5) | (pkt[1] >> 2);
 +              dev->y = (pkt[4] << 5) | (pkt[3] >> 2);
 +              dev->touch = (pkt[0] & 0x40) ? 1 : 0;
 +              return 1;
 +
 +      default:
 +              return 0;
 +      }
 +}
 +#endif
 +
 +/*****************************************************************************
 + * General Touch Part
 + */
 +#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
 +static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 +{
 +      dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ;
 +      dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ;
 +      dev->press = pkt[5] & 0xff;
 +      dev->touch = pkt[0] & 0x01;
 +
 +      return 1;
 +}
 +#endif
 +
  /*****************************************************************************
   * the different device descriptors
   */
@@@ -600,32 -537,6 +600,32 @@@ static struct usbtouch_device_info usbt
                .read_data      = irtouch_read_data,
        },
  #endif
 +
 +#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
 +      [DEVTYPE_IDEALTEK] = {
 +              .min_xc         = 0x0,
 +              .max_xc         = 0x0fff,
 +              .min_yc         = 0x0,
 +              .max_yc         = 0x0fff,
 +              .rept_size      = 8,
 +              .flags          = USBTOUCH_FLG_BUFFER,
 +              .process_pkt    = usbtouch_process_multi,
 +              .get_pkt_len    = idealtek_get_pkt_len,
 +              .read_data      = idealtek_read_data,
 +      },
 +#endif
 +
 +#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
 +      [DEVTYPE_GENERAL_TOUCH] = {
 +              .min_xc         = 0x0,
 +              .max_xc         = 0x0500,
 +              .min_yc         = 0x0,
 +              .max_yc         = 0x0500,
 +              .rept_size      = 7,
 +              .read_data      = general_touch_read_data,
 +      }
 +#endif
 +
  };
  
  
@@@ -856,7 -767,7 +856,7 @@@ static int usbtouch_probe(struct usb_in
                         le16_to_cpu(udev->descriptor.idProduct));
  
        usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
-       strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
+       strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
  
        input_dev->name = usbtouch->name;
        input_dev->phys = usbtouch->phys;
index 20da011d40d0cbe8c4b9c8c886fc3fe9a61aa872,56cd8998fe4b76f35e7e47158cb0147d9f4cb159..77f50b63a9702d25bcfc1c89cb05cf7ee9f58f1b
@@@ -3,6 -3,11 +3,11 @@@ menuconfig MACINTOSH_DRIVER
        bool "Macintosh device drivers"
        depends on PPC || MAC || X86
        default y if (PPC_PMAC || MAC)
+       ---help---
+         Say Y here to get to see options for devices used with Macintosh
+         computers. This option alone does not add any kernel code.
+         If you say N, all options in this submenu will be skipped and disabled.
  
  if MACINTOSH_DRIVERS
  
@@@ -167,7 -172,6 +172,7 @@@ config INPUT_ADBHI
  
  config MAC_EMUMOUSEBTN
        bool "Support for mouse button 2+3 emulation"
 +      select INPUT
        help
          This provides generic support for emulating the 2nd and 3rd mouse
          button with keypresses.  If you say Y here, the emulation is still
index 9ff2189d2e2a3d3d28e91f28f4857816cf852b0a,48d17bf6c927d6e8b528c48758b7c309d4c2773f..8cce016b3d0936ce2cbdb2c2e7a348c137f7cfab
  
  MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");
  
 +static int restore_capslock_events;
 +module_param(restore_capslock_events, int, 0644);
 +MODULE_PARM_DESC(restore_capslock_events,
 +      "Produce keypress events for capslock on both keyup and keydown.");
 +
  #define KEYB_KEYREG   0       /* register # for key up/down data */
  #define KEYB_LEDREG   2       /* register # for leds on ADB keyboard */
  #define MOUSE_DATAREG 0       /* reg# for movement/button codes from mouse */
@@@ -75,7 -70,7 +75,7 @@@ static struct notifier_block adbhid_adb
  #define ADB_KEY_POWER_OLD     0x7e
  #define ADB_KEY_POWER         0x7f
  
- u8 adb_to_linux_keycodes[128] = {
+ u16 adb_to_linux_keycodes[128] = {
        /* 0x00 */ KEY_A,               /*  30 */
        /* 0x01 */ KEY_S,               /*  31 */
        /* 0x02 */ KEY_D,               /*  32 */
        /* 0x3c */ KEY_RIGHT,           /* 106 */
        /* 0x3d */ KEY_DOWN,            /* 108 */
        /* 0x3e */ KEY_UP,              /* 103 */
-       /* 0x3f */ 0,
+       /* 0x3f */ KEY_FN,              /* 0x1d0 */
        /* 0x40 */ 0,
        /* 0x41 */ KEY_KPDOT,           /*  83 */
        /* 0x42 */ 0,
@@@ -213,7 -208,7 +213,7 @@@ struct adbhid 
        int original_handler_id;
        int current_handler_id;
        int mouse_kind;
-       unsigned char *keycode;
+       u16 *keycode;
        char name[64];
        char phys[32];
        int flags;
  #define FLAG_FN_KEY_PRESSED   0x00000001
  #define FLAG_POWER_FROM_FN    0x00000002
  #define FLAG_EMU_FWDEL_DOWN   0x00000004
 +#define FLAG_CAPSLOCK_TRANSLATE       0x00000008
 +#define FLAG_CAPSLOCK_DOWN    0x00000010
  
  static struct adbhid *adbhid[16];
  
@@@ -279,50 -272,19 +279,50 @@@ adbhid_keyboard_input(unsigned char *da
  }
  
  static void
 -adbhid_input_keycode(int id, int keycode, int repeat)
 +adbhid_input_keycode(int id, int scancode, int repeat)
  {
        struct adbhid *ahid = adbhid[id];
 -      int up_flag, key;
 +      int keycode, up_flag;
 +
 +      keycode = scancode & 0x7f;
 +      up_flag = scancode & 0x80;
  
 -      up_flag = (keycode & 0x80);
 -      keycode &= 0x7f;
 +      if (restore_capslock_events) {
 +              if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {
 +                      /* Key pressed, turning on the CapsLock LED.
 +                       * The next 0xff will be interpreted as a release. */
 +                      ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
 +                                      | FLAG_CAPSLOCK_DOWN;
 +              } else if (scancode == 0xff) {
 +                      /* Scancode 0xff usually signifies that the capslock
 +                       * key was either pressed or released. */
 +                      if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) {
 +                              keycode = ADB_KEY_CAPSLOCK;
 +                              if (ahid->flags & FLAG_CAPSLOCK_DOWN) {
 +                                      /* Key released */
 +                                      up_flag = 1;
 +                                      ahid->flags &= ~FLAG_CAPSLOCK_DOWN;
 +                              } else {
 +                                      /* Key pressed */
 +                                      up_flag = 0;
 +                                      ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE;
 +                              }
 +                      } else {
 +                              printk(KERN_INFO "Spurious caps lock event "
 +                                              "(scancode 0xff).");
 +                      }
 +              }
 +      }
  
        switch (keycode) {
 -      case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
 -              input_report_key(ahid->input, KEY_CAPSLOCK, 1);
 -              input_report_key(ahid->input, KEY_CAPSLOCK, 0);
 -              input_sync(ahid->input);
 +      case ADB_KEY_CAPSLOCK:
 +              if (!restore_capslock_events) {
 +                      /* Generate down/up events for CapsLock everytime. */
 +                      input_report_key(ahid->input, KEY_CAPSLOCK, 1);
 +                      input_sync(ahid->input);
 +                      input_report_key(ahid->input, KEY_CAPSLOCK, 0);
 +                      input_sync(ahid->input);
 +              }
                return;
  #ifdef CONFIG_PPC_PMAC
        case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */
                        keycode = ADB_KEY_POWER;
                }
                break;
--      case ADB_KEY_POWER: 
++      case ADB_KEY_POWER:
                /* Fn + Command will produce a bogus "power" keycode */
                if (ahid->flags & FLAG_FN_KEY_PRESSED) {
                        keycode = ADB_KEY_CMD;
                        }
                } else
                        ahid->flags |= FLAG_FN_KEY_PRESSED;
-               /* Swallow the key press */
-               return;
+               break;
        case ADB_KEY_DEL:
                /* Emulate Fn+delete = forward delete */
                if (ahid->flags & FLAG_FN_KEY_PRESSED) {
  #endif /* CONFIG_PPC_PMAC */
        }
  
-       if (adbhid[id]->keycode[keycode]) {
-               input_report_key(adbhid[id]->input,
-                                adbhid[id]->keycode[keycode], !up_flag);
+       key = adbhid[id]->keycode[keycode];
+       if (key) {
+               input_report_key(adbhid[id]->input, key, !up_flag);
                input_sync(adbhid[id]->input);
        } else
                printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
@@@ -795,8 -756,8 +794,8 @@@ adbhid_input_register(int id, int defau
                input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
                input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
                input_dev->event = adbhid_kbd_event;
-               input_dev->keycodemax = 127;
-               input_dev->keycodesize = 1;
+               input_dev->keycodemax = KEY_FN;
+               input_dev->keycodesize = sizeof(hid->keycode[0]);
                break;
  
        case ADB_MOUSE:
diff --combined include/linux/input.h
index d09e5e8be32585df1b3d57f11f6f7c4d5b715867,6eb3aead7f1d93775ba4020e9d252df5210c757a..125e925320fdd611c9f7043d77f25a276cf1618d
@@@ -360,9 -360,16 +360,16 @@@ struct input_absinfo 
  
  #define KEY_BLUETOOTH         237
  #define KEY_WLAN              238
+ #define KEY_UWB                       239
  
  #define KEY_UNKNOWN           240
  
+ #define KEY_VIDEO_NEXT                241     /* drive next video source */
+ #define KEY_VIDEO_PREV                242     /* drive previous video source */
+ #define KEY_BRIGHTNESS_CYCLE  243     /* brightness up, after max is min */
+ #define KEY_BRIGHTNESS_ZERO   244     /* brightness off, use ambient */
+ #define KEY_DISPLAY_OFF               245     /* display device to off state */
  #define BTN_MISC              0x100
  #define BTN_0                 0x100
  #define BTN_1                 0x101
  #define KEY_BRL_DOT6          0x1f6
  #define KEY_BRL_DOT7          0x1f7
  #define KEY_BRL_DOT8          0x1f8
+ #define KEY_BRL_DOT9          0x1f9
+ #define KEY_BRL_DOT10         0x1fa
  
  /* We avoid low common keys in module aliases so they don't get huge. */
  #define KEY_MIN_INTERESTING   KEY_MUTE
@@@ -845,7 -854,7 +854,7 @@@ struct ff_rumble_effect 
   *    defining effect parameters
   *
   * This structure is sent through ioctl from the application to the driver.
 - * To create a new effect aplication should set its @id to -1; the kernel
 + * To create a new effect application should set its @id to -1; the kernel
   * will return assigned @id which can later be used to update or delete
   * this effect.
   *
@@@ -925,82 -934,9 +934,82 @@@ struct ff_effect 
  #define BIT(x)        (1UL<<((x)%BITS_PER_LONG))
  #define LONG(x) ((x)/BITS_PER_LONG)
  
 +/**
 + * struct input_dev - represents an input device
 + * @name: name of the device
 + * @phys: physical path to the device in the system hierarchy
 + * @uniq: unique identification code for the device (if device has it)
 + * @id: id of the device (struct input_id)
 + * @evbit: bitmap of types of events supported by the device (EV_KEY,
 + *    EV_REL, etc.)
 + * @keybit: bitmap of keys/buttons this device has
 + * @relbit: bitmap of relative axes for the device
 + * @absbit: bitmap of absolute axes for the device
 + * @mscbit: bitmap of miscellaneous events supported by the device
 + * @ledbit: bitmap of leds present on the device
 + * @sndbit: bitmap of sound effects supported by the device
 + * @ffbit: bitmap of force feedback effects supported by the device
 + * @swbit: bitmap of switches present on the device
 + * @keycodemax: size of keycode table
 + * @keycodesize: size of elements in keycode table
 + * @keycode: map of scancodes to keycodes for this device
 + * @setkeycode: optional method to alter current keymap, used to implement
 + *    sparse keymaps. If not supplied default mechanism will be used
 + * @getkeycode: optional method to retrieve current keymap. If not supplied
 + *    default mechanism will be used
 + * @ff: force feedback structure associated with the device if device
 + *    supports force feedback effects
 + * @repeat_key: stores key code of the last key pressed; used to implement
 + *    software autorepeat
 + * @timer: timer for software autorepeat
 + * @sync: set to 1 when there were no new events since last EV_SYNC
 + * @abs: current values for reports from absolute axes
 + * @rep: current values for autorepeat parameters (delay, rate)
 + * @key: reflects current state of device's keys/buttons
 + * @led: reflects current state of device's LEDs
 + * @snd: reflects current state of sound effects
 + * @sw: reflects current state of device's switches
 + * @absmax: maximum values for events coming from absolute axes
 + * @absmin: minimum values for events coming from absolute axes
 + * @absfuzz: describes noisiness for axes
 + * @absflat: size of the center flat position (used by joydev)
 + * @open: this method is called when the very first user calls
 + *    input_open_device(). The driver must prepare the device
 + *    to start generating events (start polling thread,
 + *    request an IRQ, submit URB, etc.)
 + * @close: this method is called when the very last user calls
 + *    input_close_device().
 + * @flush: purges the device. Most commonly used to get rid of force
 + *    feedback effects loaded into the device when disconnecting
 + *    from it
 + * @event: event handler for events sent _to_ the device, like EV_LED
 + *    or EV_SND. The device is expected to carry out the requested
 + *    action (turn on a LED, play sound, etc.) The call is protected
 + *    by @event_lock and must not sleep
 + * @grab: input handle that currently has the device grabbed (via
 + *    EVIOCGRAB ioctl). When a handle grabs a device it becomes sole
 + *    recipient for all input events coming from the device
 + * @event_lock: this spinlock is is taken when input core receives
 + *    and processes a new event for the device (in input_event()).
 + *    Code that accesses and/or modifies parameters of a device
 + *    (such as keymap or absmin, absmax, absfuzz, etc.) after device
 + *    has been registered with input core must take this lock.
 + * @mutex: serializes calls to open(), close() and flush() methods
 + * @users: stores number of users (input handlers) that opened this
 + *    device. It is used by input_open_device() and input_close_device()
 + *    to make sure that dev->open() is only called when the first
 + *    user opens device and dev->close() is called when the very
 + *    last user closes the device
 + * @going_away: marks devices that are in a middle of unregistering and
 + *    causes input_open_device*() fail with -ENODEV.
 + * @dev: driver model's view of this device
 + * @h_list: list of input handles associated with the device. When
 + *    accessing the list dev->mutex must be held
 + * @node: used to place the device onto input_dev_list
 + */
  struct input_dev {
  
 -      void *private;
 +      void *private;  /* do not use */
  
        const char *name;
        const char *phys;
        unsigned int repeat_key;
        struct timer_list timer;
  
 -      int state;
 -
        int sync;
  
        int abs[ABS_MAX + 1];
  
        struct input_handle *grab;
  
 -      struct mutex mutex;     /* serializes open and close operations */
 +      spinlock_t event_lock;
 +      struct mutex mutex;
 +
        unsigned int users;
 +      int going_away;
  
        struct device dev;
        union {                 /* temporarily so while we switching to struct device */
@@@ -1120,9 -1055,7 +1129,9 @@@ struct input_handle
  /**
   * struct input_handler - implements one of interfaces for input devices
   * @private: driver-specific data
 - * @event: event handler
 + * @event: event handler. This method is being called by input core with
 + *    interrupts disabled and dev->event_lock spinlock held and so
 + *    it may not sleep
   * @connect: called when attaching a handler to an input device
   * @disconnect: disconnects a handler from input device
   * @start: starts handler for given handle. This function is called by
   * @name: name of the handler, to be shown in /proc/bus/input/handlers
   * @id_table: pointer to a table of input_device_ids this driver can
   *    handle
 - * @blacklist: prointer to a table of input_device_ids this driver should
 + * @blacklist: pointer to a table of input_device_ids this driver should
   *    ignore even if they match @id_table
   * @h_list: list of input handles associated with the handler
   * @node: for placing the driver onto input_handler_list
 + *
 + * Input handlers attach to input devices and create input handles. There
 + * are likely several handlers attached to any given input device at the
 + * same time. All of them will get their copy of input event generated by
 + * the device.
 + *
 + * Note that input core serializes calls to connect() and disconnect()
 + * methods.
   */
  struct input_handler {
  
        struct list_head        node;
  };
  
 +/**
 + * struct input_handle - links input device with an input handler
 + * @private: handler-specific data
 + * @open: counter showing whether the handle is 'open', i.e. should deliver
 + *    events from its device
 + * @name: name given to the handle by handler that created it
 + * @dev: input device the handle is attached to
 + * @handler: handler that works with the device through this handle
 + * @d_node: used to put the handle on device's list of attached handles
 + * @h_node: used to put the handle on handler's list of handles from which
 + *    it gets events
 + */
  struct input_handle {
  
        void *private;
@@@ -1221,10 -1134,10 +1230,10 @@@ static inline void input_set_drvdata(st
        dev->private = data;
  }
  
 -int input_register_device(struct input_dev *);
 +int __must_check input_register_device(struct input_dev *);
  void input_unregister_device(struct input_dev *);
  
 -int input_register_handler(struct input_handler *);
 +int __must_check input_register_handler(struct input_handler *);
  void input_unregister_handler(struct input_handler *);
  
  int input_register_handle(struct input_handle *);
@@@ -1301,7 -1214,7 +1310,7 @@@ extern struct class input_class
   * @max_effects: maximum number of effects supported by device
   * @effects: pointer to an array of effects currently loaded into device
   * @effect_owners: array of effect owners; when file handle owning
 - *    an effect gets closed the effcet is automatically erased
 + *    an effect gets closed the effect is automatically erased
   *
   * Every force-feedback device must implement upload() and playback()
   * methods; erase() is optional. set_gain() and set_autocenter() need
diff --combined include/linux/keyboard.h
index f892b272f3ffeb895cef45d02ebdd87cf19f97b6,7ddbc30aa8e706d5561ca2c5c009140bdcb29d7d..33b5c2e325b92b3d14800ad83b8e1c2406103654
@@@ -416,7 -416,6 +416,7 @@@ extern unsigned short plain_map[NR_KEYS
  #define K_SHIFTRLOCK  K(KT_LOCK,KG_SHIFTR)
  #define K_CTRLLLOCK   K(KT_LOCK,KG_CTRLL)
  #define K_CTRLRLOCK   K(KT_LOCK,KG_CTRLR)
 +#define K_CAPSSHIFTLOCK       K(KT_LOCK,KG_CAPSSHIFT)
  
  #define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT)
  #define K_CTRL_SLOCK  K(KT_SLOCK,KG_CTRL)
  #define K_SHIFTR_SLOCK        K(KT_SLOCK,KG_SHIFTR)
  #define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL)
  #define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR)
 +#define K_CAPSSHIFT_SLOCK     K(KT_SLOCK,KG_CAPSSHIFT)
  
 -#define NR_LOCK               8
 +#define NR_LOCK               9
  
  #define K_BRL_BLANK     K(KT_BRL, 0)
  #define K_BRL_DOT1      K(KT_BRL, 1)
  #define K_BRL_DOT6      K(KT_BRL, 6)
  #define K_BRL_DOT7      K(KT_BRL, 7)
  #define K_BRL_DOT8      K(KT_BRL, 8)
+ #define K_BRL_DOT9      K(KT_BRL, 9)
+ #define K_BRL_DOT10     K(KT_BRL, 10)
  
- #define NR_BRL                9
+ #define NR_BRL                11
  
  #define MAX_DIACR     256
  #endif