Merge commit 'v2.6.33-rc5' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 22 Jan 2010 07:55:25 +0000 (23:55 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 22 Jan 2010 07:55:25 +0000 (23:55 -0800)
1  2 
drivers/input/input.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/sh_keysc.c
drivers/input/mouse/hgpk.c
drivers/input/serio/serio.c
include/linux/serio.h

diff --combined drivers/input/input.c
index a31394c1eca818aa2b665c95203a9df5e0b60a69,30b503b8d67bfb64dd8d84a75adad686b9db403a..6c161e220868d6b6593e443e3b98fc80df2d0ee0
@@@ -24,6 -24,7 +24,7 @@@
  #include <linux/mutex.h>
  #include <linux/rcupdate.h>
  #include <linux/smp_lock.h>
+ #include "input-compat.h"
  
  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
  MODULE_DESCRIPTION("Input core");
@@@ -613,12 -614,12 +614,12 @@@ static int input_default_setkeycode(str
                }
        }
  
 -      clear_bit(old_keycode, dev->keybit);
 -      set_bit(keycode, dev->keybit);
 +      __clear_bit(old_keycode, dev->keybit);
 +      __set_bit(keycode, dev->keybit);
  
        for (i = 0; i < dev->keycodemax; i++) {
                if (input_fetch_keycode(dev, i) == old_keycode) {
 -                      set_bit(old_keycode, dev->keybit);
 +                      __set_bit(old_keycode, dev->keybit);
                        break; /* Setting the bit twice is useless, so break */
                }
        }
@@@ -676,9 -677,6 +677,9 @@@ int input_set_keycode(struct input_dev 
        if (retval)
                goto out;
  
 +      /* Make sure KEY_RESERVED did not get enabled. */
 +      __clear_bit(KEY_RESERVED, dev->keybit);
 +
        /*
         * Simulate keyup event if keycode is not present
         * in the keymap anymore
@@@ -767,6 -765,40 +768,40 @@@ static int input_attach_handler(struct 
        return error;
  }
  
+ #ifdef CONFIG_COMPAT
+ static int input_bits_to_string(char *buf, int buf_size,
+                               unsigned long bits, bool skip_empty)
+ {
+       int len = 0;
+       if (INPUT_COMPAT_TEST) {
+               u32 dword = bits >> 32;
+               if (dword || !skip_empty)
+                       len += snprintf(buf, buf_size, "%x ", dword);
+               dword = bits & 0xffffffffUL;
+               if (dword || !skip_empty || len)
+                       len += snprintf(buf + len, max(buf_size - len, 0),
+                                       "%x", dword);
+       } else {
+               if (bits || !skip_empty)
+                       len += snprintf(buf, buf_size, "%lx", bits);
+       }
+       return len;
+ }
+ #else /* !CONFIG_COMPAT */
+ static int input_bits_to_string(char *buf, int buf_size,
+                               unsigned long bits, bool skip_empty)
+ {
+       return bits || !skip_empty ?
+               snprintf(buf, buf_size, "%lx", bits) : 0;
+ }
+ #endif
  
  #ifdef CONFIG_PROC_FS
  
@@@ -835,14 -867,25 +870,25 @@@ static void input_seq_print_bitmap(stru
                                   unsigned long *bitmap, int max)
  {
        int i;
-       for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
-               if (bitmap[i])
-                       break;
+       bool skip_empty = true;
+       char buf[18];
  
        seq_printf(seq, "B: %s=", name);
-       for (; i >= 0; i--)
-               seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+       for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
+               if (input_bits_to_string(buf, sizeof(buf),
+                                        bitmap[i], skip_empty)) {
+                       skip_empty = false;
+                       seq_printf(seq, "%s%s", buf, i > 0 ? " " : "");
+               }
+       }
+       /*
+        * If no output was produced print a single 0.
+        */
+       if (skip_empty)
+               seq_puts(seq, "0");
        seq_putc(seq, '\n');
  }
  
@@@ -1131,14 -1174,23 +1177,23 @@@ static int input_print_bitmap(char *buf
  {
        int i;
        int len = 0;
+       bool skip_empty = true;
+       for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
+               len += input_bits_to_string(buf + len, max(buf_size - len, 0),
+                                           bitmap[i], skip_empty);
+               if (len) {
+                       skip_empty = false;
+                       if (i > 0)
+                               len += snprintf(buf + len, max(buf_size - len, 0), " ");
+               }
+       }
  
-       for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
-               if (bitmap[i])
-                       break;
-       for (; i >= 0; i--)
-               len += snprintf(buf + len, max(buf_size - len, 0),
-                               "%lx%s", bitmap[i], i > 0 ? " " : "");
+       /*
+        * If no output was produced print a single 0.
+        */
+       if (len == 0)
+               len = snprintf(buf, buf_size, "%d", 0);
  
        if (add_cr)
                len += snprintf(buf + len, max(buf_size - len, 0), "\n");
@@@ -1153,7 -1205,8 +1208,8 @@@ static ssize_t input_dev_show_cap_##bm(
  {                                                                     \
        struct input_dev *input_dev = to_input_dev(dev);                \
        int len = input_print_bitmap(buf, PAGE_SIZE,                    \
-                                    input_dev->bm##bit, ev##_MAX, 1);  \
+                                    input_dev->bm##bit, ev##_MAX,      \
+                                    true);                             \
        return min_t(int, len, PAGE_SIZE);                              \
  }                                                                     \
  static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
@@@ -1217,7 -1270,7 +1273,7 @@@ static int input_add_uevent_bm_var(stru
  
        len = input_print_bitmap(&env->buf[env->buflen - 1],
                                 sizeof(env->buf) - env->buflen,
-                                bitmap, max, 0);
+                                bitmap, max, false);
        if (len >= (sizeof(env->buf) - env->buflen))
                return -ENOMEM;
  
@@@ -1497,25 -1550,6 +1553,25 @@@ void input_set_capability(struct input_
  }
  EXPORT_SYMBOL(input_set_capability);
  
 +#define INPUT_CLEANSE_BITMASK(dev, type, bits)                                \
 +      do {                                                            \
 +              if (!test_bit(EV_##type, dev->evbit))                   \
 +                      memset(dev->bits##bit, 0,                       \
 +                              sizeof(dev->bits##bit));                \
 +      } while (0)
 +
 +static void input_cleanse_bitmasks(struct input_dev *dev)
 +{
 +      INPUT_CLEANSE_BITMASK(dev, KEY, key);
 +      INPUT_CLEANSE_BITMASK(dev, REL, rel);
 +      INPUT_CLEANSE_BITMASK(dev, ABS, abs);
 +      INPUT_CLEANSE_BITMASK(dev, MSC, msc);
 +      INPUT_CLEANSE_BITMASK(dev, LED, led);
 +      INPUT_CLEANSE_BITMASK(dev, SND, snd);
 +      INPUT_CLEANSE_BITMASK(dev, FF, ff);
 +      INPUT_CLEANSE_BITMASK(dev, SW, sw);
 +}
 +
  /**
   * input_register_device - register device with input core
   * @dev: device to be registered
@@@ -1535,19 -1569,13 +1591,19 @@@ int input_register_device(struct input_
        const char *path;
        int error;
  
 +      /* Every input device generates EV_SYN/SYN_REPORT events. */
        __set_bit(EV_SYN, dev->evbit);
  
 +      /* KEY_RESERVED is not supposed to be transmitted to userspace. */
 +      __clear_bit(KEY_RESERVED, dev->keybit);
 +
 +      /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
 +      input_cleanse_bitmasks(dev);
 +
        /*
         * If delay and period are pre-set by the driver, then autorepeating
         * is handled by the driver itself and we don't do it in input.c.
         */
 -
        init_timer(&dev->timer);
        if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
                dev->timer.data = (long) dev;
index 5483fb9bd819c21855008fcab4f0f26e3ad43f57,8a28fb7846dc1f16a18a064b6cc631d2ca82afa4..66be6901619d5453165a0552750b6c125ba81fd3
@@@ -86,8 -86,9 +86,8 @@@
  
  /* xbox d-pads should map to buttons, as is required for DDR pads
     but we map them to axes when possible to simplify things */
 -#define MAP_DPAD_TO_BUTTONS    0
 -#define MAP_DPAD_TO_AXES       1
 -#define MAP_DPAD_UNKNOWN       2
 +#define MAP_DPAD_TO_BUTTONS           (1 << 0)
 +#define MAP_TRIGGERS_TO_BUTTONS               (1 << 1)
  
  #define XTYPE_XBOX        0
  #define XTYPE_XBOX360     1
@@@ -98,61 -99,57 +98,61 @@@ static int dpad_to_buttons
  module_param(dpad_to_buttons, bool, S_IRUGO);
  MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
  
 +static int triggers_to_buttons;
 +module_param(triggers_to_buttons, bool, S_IRUGO);
 +MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads");
 +
  static const struct xpad_device {
        u16 idVendor;
        u16 idProduct;
        char *name;
 -      u8 dpad_mapping;
 +      u8 mapping;
        u8 xtype;
  } xpad_device[] = {
 -      { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 +      { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX },
 +      { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
 +      { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },
 +      { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
        { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
        { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 -      { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 -      { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 +      { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
 +      { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
 +      { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
 +      { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX },
 +      { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
 +      { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX },
 +      { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX },
 +      { 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX },
 +      { 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX },
 +      { 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX },
        { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 -      { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 -      { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 +      { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX },
 +      { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
 +      { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 -      { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 -      { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 +      { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
 +      { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },
 +      { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
 +      { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
 +      { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
 +      { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
 +      { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },
 +      { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX },
 +      { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX },
 +      { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
 +      { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX },
 +      { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
 +      { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
 +      { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
        { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 -      { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 +      { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 -      { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 -      { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 +      { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
 +      { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
        { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
 -      { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
 -      { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
 -      { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
 +      { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 +      { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
 +      { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
  };
  
  /* buttons shared with xbox and xbox360 */
@@@ -168,20 -165,13 +168,20 @@@ static const signed short xpad_btn[] = 
        -1                      /* terminating entry */
  };
  
 -/* only used if MAP_DPAD_TO_BUTTONS */
 +/* used when dpad is mapped to nuttons */
  static const signed short xpad_btn_pad[] = {
        BTN_LEFT, BTN_RIGHT,            /* d-pad left, right */
        BTN_0, BTN_1,                   /* d-pad up, down (XXX names??) */
        -1                              /* terminating entry */
  };
  
 +/* used when triggers are mapped to buttons */
 +static const signed short xpad_btn_triggers[] = {
 +      BTN_TL2, BTN_TR2,               /* triggers left/right */
 +      -1
 +};
 +
 +
  static const signed short xpad360_btn[] = {  /* buttons for x360 controller */
        BTN_TL, BTN_TR,         /* Button LB/RB */
        BTN_MODE,               /* The big X button */
  static const signed short xpad_abs[] = {
        ABS_X, ABS_Y,           /* left stick */
        ABS_RX, ABS_RY,         /* right stick */
 -      ABS_Z, ABS_RZ,          /* triggers left/right */
        -1                      /* terminating entry */
  };
  
 -/* only used if MAP_DPAD_TO_AXES */
 +/* used when dpad is mapped to axes */
  static const signed short xpad_abs_pad[] = {
        ABS_HAT0X, ABS_HAT0Y,   /* d-pad axes */
        -1                      /* terminating entry */
  };
  
 +/* used when triggers are mapped to axes */
 +static const signed short xpad_abs_triggers[] = {
 +      ABS_Z, ABS_RZ,          /* triggers left/right */
 +      -1
 +};
 +
  /* Xbox 360 has a vendor-specific class, so we cannot match it with only
   * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
   * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
@@@ -261,7 -246,7 +261,7 @@@ struct usb_xpad 
  
        char phys[64];                  /* physical device path */
  
 -      int dpad_mapping;               /* map d-pad to buttons or to axes */
 +      int mapping;                    /* map d-pad to buttons or to axes */
        int xtype;                      /* type of xbox device */
  };
  
@@@ -292,25 -277,20 +292,25 @@@ static void xpad_process_packet(struct 
                         ~(__s16) le16_to_cpup((__le16 *)(data + 18)));
  
        /* triggers left/right */
 -      input_report_abs(dev, ABS_Z, data[10]);
 -      input_report_abs(dev, ABS_RZ, data[11]);
 +      if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
 +              input_report_key(dev, BTN_TL2, data[10]);
 +              input_report_key(dev, BTN_TR2, data[11]);
 +      } else {
 +              input_report_abs(dev, ABS_Z, data[10]);
 +              input_report_abs(dev, ABS_RZ, data[11]);
 +      }
  
        /* digital pad */
 -      if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
 -              input_report_abs(dev, ABS_HAT0X,
 -                               !!(data[2] & 0x08) - !!(data[2] & 0x04));
 -              input_report_abs(dev, ABS_HAT0Y,
 -                               !!(data[2] & 0x02) - !!(data[2] & 0x01));
 -      } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
 +      if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
                input_report_key(dev, BTN_LEFT,  data[2] & 0x04);
                input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
                input_report_key(dev, BTN_0,     data[2] & 0x01); /* up */
                input_report_key(dev, BTN_1,     data[2] & 0x02); /* down */
 +      } else {
 +              input_report_abs(dev, ABS_HAT0X,
 +                               !!(data[2] & 0x08) - !!(data[2] & 0x04));
 +              input_report_abs(dev, ABS_HAT0Y,
 +                               !!(data[2] & 0x02) - !!(data[2] & 0x01));
        }
  
        /* start/back buttons and stick press left/right */
@@@ -348,17 -328,17 +348,17 @@@ static void xpad360_process_packet(stru
        struct input_dev *dev = xpad->dev;
  
        /* digital pad */
 -      if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
 -              input_report_abs(dev, ABS_HAT0X,
 -                               !!(data[2] & 0x08) - !!(data[2] & 0x04));
 -              input_report_abs(dev, ABS_HAT0Y,
 -                               !!(data[2] & 0x02) - !!(data[2] & 0x01));
 -      } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
 +      if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
                /* dpad as buttons (right, left, down, up) */
                input_report_key(dev, BTN_LEFT, data[2] & 0x04);
                input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
                input_report_key(dev, BTN_0, data[2] & 0x01);   /* up */
                input_report_key(dev, BTN_1, data[2] & 0x02);   /* down */
 +      } else {
 +              input_report_abs(dev, ABS_HAT0X,
 +                               !!(data[2] & 0x08) - !!(data[2] & 0x04));
 +              input_report_abs(dev, ABS_HAT0Y,
 +                               !!(data[2] & 0x02) - !!(data[2] & 0x01));
        }
  
        /* start/back buttons */
                         ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
  
        /* triggers left/right */
 -      input_report_abs(dev, ABS_Z, data[4]);
 -      input_report_abs(dev, ABS_RZ, data[5]);
 +      if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
 +              input_report_key(dev, BTN_TL2, data[4]);
 +              input_report_key(dev, BTN_TR2, data[5]);
 +      } else {
 +              input_report_abs(dev, ABS_Z, data[4]);
 +              input_report_abs(dev, ABS_RZ, data[5]);
 +      }
  
        input_sync(dev);
  }
@@@ -471,7 -446,7 +471,7 @@@ static void xpad_irq_in(struct urb *urb
        }
  
  exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
                     __func__, retval);
@@@ -596,7 -571,7 +596,7 @@@ static int xpad_play_effect(struct inpu
                xpad->odata[6] = 0x00;
                xpad->odata[7] = 0x00;
                xpad->irq_out->transfer_buffer_length = 8;
-               usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+               usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
        }
  
        return 0;
@@@ -737,11 -712,11 +737,11 @@@ static void xpad_set_up_abs(struct inpu
                input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128);
                break;
        case ABS_Z:
 -      case ABS_RZ:    /* the triggers */
 +      case ABS_RZ:    /* the triggers (if mapped to axes) */
                input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
                break;
        case ABS_HAT0X:
 -      case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */
 +      case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */
                input_set_abs_params(input_dev, abs, -1, 1, 0, 0);
                break;
        }
@@@ -777,9 -752,10 +777,9 @@@ static int xpad_probe(struct usb_interf
                goto fail2;
  
        xpad->udev = udev;
 -      xpad->dpad_mapping = xpad_device[i].dpad_mapping;
 +      xpad->mapping = xpad_device[i].mapping;
        xpad->xtype = xpad_device[i].xtype;
 -      if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
 -              xpad->dpad_mapping = !dpad_to_buttons;
 +
        if (xpad->xtype == XTYPE_UNKNOWN) {
                if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
                        if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
                                xpad->xtype = XTYPE_XBOX360;
                } else
                        xpad->xtype = XTYPE_XBOX;
 +
 +              if (dpad_to_buttons)
 +                      xpad->mapping |= MAP_DPAD_TO_BUTTONS;
 +              if (triggers_to_buttons)
 +                      xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS;
        }
 +
        xpad->dev = input_dev;
        usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
        strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
  
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  
 -      /* set up buttons */
 +      /* set up standard buttons and axes */
        for (i = 0; xpad_common_btn[i] >= 0; i++)
 -              set_bit(xpad_common_btn[i], input_dev->keybit);
 -      if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
 -              for (i = 0; xpad360_btn[i] >= 0; i++)
 -                      set_bit(xpad360_btn[i], input_dev->keybit);
 -      else
 -              for (i = 0; xpad_btn[i] >= 0; i++)
 -                      set_bit(xpad_btn[i], input_dev->keybit);
 -      if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
 -              for (i = 0; xpad_btn_pad[i] >= 0; i++)
 -                      set_bit(xpad_btn_pad[i], input_dev->keybit);
 +              __set_bit(xpad_common_btn[i], input_dev->keybit);
  
 -      /* set up axes */
        for (i = 0; xpad_abs[i] >= 0; i++)
                xpad_set_up_abs(input_dev, xpad_abs[i]);
 -      if (xpad->dpad_mapping == MAP_DPAD_TO_AXES)
 +
 +      /* Now set up model-specific ones */
 +      if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) {
 +              for (i = 0; xpad360_btn[i] >= 0; i++)
 +                      __set_bit(xpad360_btn[i], input_dev->keybit);
 +      } else {
 +              for (i = 0; xpad_btn[i] >= 0; i++)
 +                      __set_bit(xpad_btn[i], input_dev->keybit);
 +      }
 +
 +      if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
 +              for (i = 0; xpad_btn_pad[i] >= 0; i++)
 +                      __set_bit(xpad_btn_pad[i], input_dev->keybit);
 +      } else {
                for (i = 0; xpad_abs_pad[i] >= 0; i++)
                    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
 +      }
 +
 +      if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
 +              for (i = 0; xpad_btn_triggers[i] >= 0; i++)
 +                      __set_bit(xpad_btn_triggers[i], input_dev->keybit);
 +      } else {
 +              for (i = 0; xpad_abs_triggers[i] >= 0; i++)
 +                      xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
 +      }
  
        error = xpad_init_output(intf, xpad);
        if (error)
index 6737fe4c0f1237508095a35b9e99ed8d41fb0927,1edb596d927bd885dea073593a3183fc63b45a54..b5142d2d5112a0470cf34e924e9c0063124d56f3
@@@ -1,7 -1,6 +1,7 @@@
  /*
   * File: drivers/input/keyboard/adp5588_keys.c
 - * Description:  keypad driver for ADP5588 I2C QWERTY Keypad and IO Expander
 + * Description:  keypad driver for ADP5588 and ADP5587
 + *             I2C QWERTY Keypad and IO Expander
   * Bugs: Enter bugs at http://blackfin.uclinux.org/
   *
   * Copyright (C) 2008-2009 Analog Devices Inc.
@@@ -320,7 -319,7 +320,7 @@@ static int adp5588_resume(struct devic
        return 0;
  }
  
- static struct dev_pm_ops adp5588_dev_pm_ops = {
+ static const struct dev_pm_ops adp5588_dev_pm_ops = {
        .suspend = adp5588_suspend,
        .resume  = adp5588_resume,
  };
  
  static const struct i2c_device_id adp5588_id[] = {
        { KBUILD_MODNAME, 0 },
 +      { "adp5587-keys", 0 },
        { }
  };
  MODULE_DEVICE_TABLE(i2c, adp5588_id);
@@@ -359,5 -357,5 +359,5 @@@ module_exit(adp5588_exit)
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 -MODULE_DESCRIPTION("ADP5588 Keypad driver");
 +MODULE_DESCRIPTION("ADP5588/87 Keypad driver");
  MODULE_ALIAS("platform:adp5588-keys");
index 7c235013dba3e4d2d94f9b55968967b79355fbb0,7b4056292eaf9387b95fe80c147ad6c9a65920e5..326875be192ed63d77bc40aa0c79c1e0c782c1a3
@@@ -40,26 -40,26 +40,26 @@@ module_param_named(set, atkbd_set, int
  MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
  
  #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
 -static int atkbd_reset;
 +static bool atkbd_reset;
  #else
 -static int atkbd_reset = 1;
 +static bool atkbd_reset = true;
  #endif
  module_param_named(reset, atkbd_reset, bool, 0);
  MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
  
 -static int atkbd_softrepeat;
 +static bool atkbd_softrepeat;
  module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
  MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
  
 -static int atkbd_softraw = 1;
 +static bool atkbd_softraw = true;
  module_param_named(softraw, atkbd_softraw, bool, 0);
  MODULE_PARM_DESC(softraw, "Use software generated rawmode");
  
 -static int atkbd_scroll;
 +static bool atkbd_scroll;
  module_param_named(scroll, atkbd_scroll, bool, 0);
  MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
  
 -static int atkbd_extra;
 +static bool atkbd_extra;
  module_param_named(extra, atkbd_extra, bool, 0);
  MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
  
@@@ -134,7 -134,8 +134,8 @@@ static const unsigned short atkbd_unxla
  #define ATKBD_CMD_GETID               0x02f2
  #define ATKBD_CMD_SETREP      0x10f3
  #define ATKBD_CMD_ENABLE      0x00f4
- #define ATKBD_CMD_RESET_DIS   0x00f5
+ #define ATKBD_CMD_RESET_DIS   0x00f5  /* Reset to defaults and disable */
+ #define ATKBD_CMD_RESET_DEF   0x00f6  /* Reset to defaults */
  #define ATKBD_CMD_SETALL_MBR  0x00fa
  #define ATKBD_CMD_RESET_BAT   0x02ff
  #define ATKBD_CMD_RESEND      0x00fe
@@@ -205,18 -206,18 +206,18 @@@ struct atkbd 
        unsigned short keycode[ATKBD_KEYMAP_SIZE];
        DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE);
        unsigned char set;
 -      unsigned char translated;
 -      unsigned char extra;
 -      unsigned char write;
 -      unsigned char softrepeat;
 -      unsigned char softraw;
 -      unsigned char scroll;
 -      unsigned char enabled;
 +      bool translated;
 +      bool extra;
 +      bool write;
 +      bool softrepeat;
 +      bool softraw;
 +      bool scroll;
 +      bool enabled;
  
        /* Accessed only from interrupt */
        unsigned char emul;
 -      unsigned char resend;
 -      unsigned char release;
 +      bool resend;
 +      bool release;
        unsigned long xl_bit;
        unsigned int last;
        unsigned long time;
  
        struct delayed_work event_work;
        unsigned long event_jiffies;
-       struct mutex event_mutex;
        unsigned long event_mask;
+       /* Serializes reconnect(), attr->set() and event work */
+       struct mutex mutex;
  };
  
  /*
@@@ -298,18 -301,18 +301,18 @@@ static const unsigned int xl_table[] = 
   * Checks if we should mangle the scancode to extract 'release' bit
   * in translated mode.
   */
 -static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
 +static bool atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
  {
        int i;
  
        if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
 -              return 0;
 +              return false;
  
        for (i = 0; i < ARRAY_SIZE(xl_table); i++)
                if (code == xl_table[i])
                        return test_bit(i, &xl_bit);
  
 -      return 1;
 +      return true;
  }
  
  /*
@@@ -356,7 -359,7 +359,7 @@@ static unsigned int atkbd_compat_scanco
   */
  
  static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 -                      unsigned int flags)
 +                                 unsigned int flags)
  {
        struct atkbd *atkbd = serio_get_drvdata(serio);
        struct input_dev *dev = atkbd->dev;
        int value;
        unsigned short keycode;
  
 -#ifdef ATKBD_DEBUG
 -      printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
 -#endif
 +      dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
  
  #if !defined(__i386__) && !defined (__x86_64__)
        if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
 -              printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
 +              dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
                serio_write(serio, ATKBD_CMD_RESEND);
 -              atkbd->resend = 1;
 +              atkbd->resend = true;
                goto out;
        }
  
        if (!flags && data == ATKBD_RET_ACK)
 -              atkbd->resend = 0;
 +              atkbd->resend = false;
  #endif
  
        if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
        }
  
        switch (code) {
 -              case ATKBD_RET_BAT:
 -                      atkbd->enabled = 0;
 -                      serio_reconnect(atkbd->ps2dev.serio);
 -                      goto out;
 -              case ATKBD_RET_EMUL0:
 -                      atkbd->emul = 1;
 -                      goto out;
 -              case ATKBD_RET_EMUL1:
 -                      atkbd->emul = 2;
 -                      goto out;
 -              case ATKBD_RET_RELEASE:
 -                      atkbd->release = 1;
 -                      goto out;
 -              case ATKBD_RET_ACK:
 -              case ATKBD_RET_NAK:
 -                      if (printk_ratelimit())
 -                              printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
 -                                     "Some program might be trying access hardware directly.\n",
 -                                     data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
 -                      goto out;
 -              case ATKBD_RET_ERR:
 -                      atkbd->err_count++;
 -#ifdef ATKBD_DEBUG
 -                      printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
 -#endif
 -                      goto out;
 +      case ATKBD_RET_BAT:
 +              atkbd->enabled = false;
 +              serio_reconnect(atkbd->ps2dev.serio);
 +              goto out;
 +      case ATKBD_RET_EMUL0:
 +              atkbd->emul = 1;
 +              goto out;
 +      case ATKBD_RET_EMUL1:
 +              atkbd->emul = 2;
 +              goto out;
 +      case ATKBD_RET_RELEASE:
 +              atkbd->release = true;
 +              goto out;
 +      case ATKBD_RET_ACK:
 +      case ATKBD_RET_NAK:
 +              if (printk_ratelimit())
 +                      dev_warn(&serio->dev,
 +                               "Spurious %s on %s. "
 +                               "Some program might be trying access hardware directly.\n",
 +                               data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
 +              goto out;
 +      case ATKBD_RET_ERR:
 +              atkbd->err_count++;
 +              dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n",
 +                      serio->phys);
 +              goto out;
        }
  
        code = atkbd_compat_scancode(atkbd, code);
                input_event(dev, EV_MSC, MSC_SCAN, code);
  
        switch (keycode) {
 -              case ATKBD_KEY_NULL:
 -                      break;
 -              case ATKBD_KEY_UNKNOWN:
 -                      printk(KERN_WARNING
 -                             "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
 -                             atkbd->release ? "released" : "pressed",
 -                             atkbd->translated ? "translated" : "raw",
 -                             atkbd->set, code, serio->phys);
 -                      printk(KERN_WARNING
 -                             "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
 -                             code & 0x80 ? "e0" : "", code & 0x7f);
 -                      input_sync(dev);
 -                      break;
 -              case ATKBD_SCR_1:
 -                      scroll = 1 - atkbd->release * 2;
 -                      break;
 -              case ATKBD_SCR_2:
 -                      scroll = 2 - atkbd->release * 4;
 -                      break;
 -              case ATKBD_SCR_4:
 -                      scroll = 4 - atkbd->release * 8;
 -                      break;
 -              case ATKBD_SCR_8:
 -                      scroll = 8 - atkbd->release * 16;
 -                      break;
 -              case ATKBD_SCR_CLICK:
 -                      click = !atkbd->release;
 -                      break;
 -              case ATKBD_SCR_LEFT:
 -                      hscroll = -1;
 -                      break;
 -              case ATKBD_SCR_RIGHT:
 -                      hscroll = 1;
 -                      break;
 -              default:
 -                      if (atkbd->release) {
 -                              value = 0;
 -                              atkbd->last = 0;
 -                      } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
 -                              /* Workaround Toshiba laptop multiple keypress */
 -                              value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
 -                      } else {
 -                              value = 1;
 -                              atkbd->last = code;
 -                              atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
 -                      }
 -
 -                      input_event(dev, EV_KEY, keycode, value);
 -                      input_sync(dev);
 +      case ATKBD_KEY_NULL:
 +              break;
 +      case ATKBD_KEY_UNKNOWN:
 +              dev_warn(&serio->dev,
 +                       "Unknown key %s (%s set %d, code %#x on %s).\n",
 +                       atkbd->release ? "released" : "pressed",
 +                       atkbd->translated ? "translated" : "raw",
 +                       atkbd->set, code, serio->phys);
 +              dev_warn(&serio->dev,
 +                       "Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
 +                       code & 0x80 ? "e0" : "", code & 0x7f);
 +              input_sync(dev);
 +              break;
 +      case ATKBD_SCR_1:
 +              scroll = 1;
 +              break;
 +      case ATKBD_SCR_2:
 +              scroll = 2;
 +              break;
 +      case ATKBD_SCR_4:
 +              scroll = 4;
 +              break;
 +      case ATKBD_SCR_8:
 +              scroll = 8;
 +              break;
 +      case ATKBD_SCR_CLICK:
 +              click = !atkbd->release;
 +              break;
 +      case ATKBD_SCR_LEFT:
 +              hscroll = -1;
 +              break;
 +      case ATKBD_SCR_RIGHT:
 +              hscroll = 1;
 +              break;
 +      default:
 +              if (atkbd->release) {
 +                      value = 0;
 +                      atkbd->last = 0;
 +              } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
 +                      /* Workaround Toshiba laptop multiple keypress */
 +                      value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
 +              } else {
 +                      value = 1;
 +                      atkbd->last = code;
 +                      atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
 +              }
 +
 +              input_event(dev, EV_KEY, keycode, value);
 +              input_sync(dev);
  
 -                      if (value && test_bit(code, atkbd->force_release_mask)) {
 -                              input_report_key(dev, keycode, 0);
 -                              input_sync(dev);
 -                      }
 +              if (value && test_bit(code, atkbd->force_release_mask)) {
 +                      input_report_key(dev, keycode, 0);
 +                      input_sync(dev);
 +              }
        }
  
        if (atkbd->scroll) {
                if (click != -1)
                        input_report_key(dev, BTN_MIDDLE, click);
 -              input_report_rel(dev, REL_WHEEL, scroll);
 +              input_report_rel(dev, REL_WHEEL,
 +                               atkbd->release ? -scroll : scroll);
                input_report_rel(dev, REL_HWHEEL, hscroll);
                input_sync(dev);
        }
  
 -      atkbd->release = 0;
 +      atkbd->release = false;
  out:
        return IRQ_HANDLED;
  }
@@@ -575,7 -579,7 +578,7 @@@ static void atkbd_event_work(struct wor
  {
        struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
  
-       mutex_lock(&atkbd->event_mutex);
+       mutex_lock(&atkbd->mutex);
  
        if (!atkbd->enabled) {
                /*
                        atkbd_set_repeat_rate(atkbd);
        }
  
-       mutex_unlock(&atkbd->event_mutex);
+       mutex_unlock(&atkbd->mutex);
  }
  
  /*
@@@ -610,7 -614,7 +613,7 @@@ static void atkbd_schedule_event_work(s
  
        atkbd->event_jiffies = jiffies;
        set_bit(event_bit, &atkbd->event_mask);
-       wmb();
+       mb();
        schedule_delayed_work(&atkbd->event_work, delay);
  }
  
@@@ -630,18 -634,17 +633,18 @@@ static int atkbd_event(struct input_de
  
        switch (type) {
  
 -              case EV_LED:
 -                      atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
 -                      return 0;
 +      case EV_LED:
 +              atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
 +              return 0;
  
 -              case EV_REP:
 -                      if (!atkbd->softrepeat)
 -                              atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
 -                      return 0;
 -      }
 +      case EV_REP:
 +              if (!atkbd->softrepeat)
 +                      atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
 +              return 0;
  
 -      return -1;
 +      default:
 +              return -1;
 +      }
  }
  
  /*
  static inline void atkbd_enable(struct atkbd *atkbd)
  {
        serio_pause_rx(atkbd->ps2dev.serio);
 -      atkbd->enabled = 1;
 +      atkbd->enabled = true;
        serio_continue_rx(atkbd->ps2dev.serio);
  }
  
  static inline void atkbd_disable(struct atkbd *atkbd)
  {
        serio_pause_rx(atkbd->ps2dev.serio);
 -      atkbd->enabled = 0;
 +      atkbd->enabled = false;
        serio_continue_rx(atkbd->ps2dev.serio);
  }
  
@@@ -685,9 -688,7 +688,9 @@@ static int atkbd_probe(struct atkbd *at
  
        if (atkbd_reset)
                if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))
 -                      printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys);
 +                      dev_warn(&ps2dev->serio->dev,
 +                               "keyboard reset failed on %s\n",
 +                               ps2dev->serio->phys);
  
  /*
   * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
        atkbd->id = (param[0] << 8) | param[1];
  
        if (atkbd->id == 0xaca1 && atkbd->translated) {
 -              printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n");
 -              printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n");
 +              dev_err(&ps2dev->serio->dev,
 +                      "NCD terminal keyboards are only supported on non-translating controlelrs. "
 +                      "Use i8042.direct=1 to disable translation.\n");
                return -1;
        }
  
@@@ -737,7 -737,7 +740,7 @@@ static int atkbd_select_set(struct atkb
        struct ps2dev *ps2dev = &atkbd->ps2dev;
        unsigned char param[2];
  
 -      atkbd->extra = 0;
 +      atkbd->extra = false;
  /*
   * For known special keyboards we can go ahead and set the correct set.
   * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
        if (allow_extra) {
                param[0] = 0x71;
                if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {
 -                      atkbd->extra = 1;
 +                      atkbd->extra = true;
                        return 2;
                }
        }
@@@ -821,8 -821,7 +824,8 @@@ static int atkbd_activate(struct atkbd 
   */
  
        if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
 -              printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
 +              dev_err(&ps2dev->serio->dev,
 +                      "Failed to enable keyboard on %s\n",
                        ps2dev->serio->phys);
                return -1;
        }
@@@ -840,7 -839,7 +843,7 @@@ static void atkbd_cleanup(struct serio 
        struct atkbd *atkbd = serio_get_drvdata(serio);
  
        atkbd_disable(atkbd);
-       ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
+       ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
  }
  
  
@@@ -852,13 -851,20 +855,20 @@@ static void atkbd_disconnect(struct ser
  {
        struct atkbd *atkbd = serio_get_drvdata(serio);
  
+       sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
        atkbd_disable(atkbd);
  
-       /* make sure we don't have a command in flight */
+       input_unregister_device(atkbd->dev);
+       /*
+        * Make sure we don't have a command in flight.
+        * Note that since atkbd->enabled is false event work will keep
+        * rescheduling itself until it gets canceled and will not try
+        * accessing freed input device or serio port.
+        */
        cancel_delayed_work_sync(&atkbd->event_work);
  
-       sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
-       input_unregister_device(atkbd->dev);
        serio_close(serio);
        serio_set_drvdata(serio, NULL);
        kfree(atkbd);
@@@ -1090,18 -1096,16 +1100,18 @@@ static int atkbd_connect(struct serio *
        atkbd->dev = dev;
        ps2_init(&atkbd->ps2dev, serio);
        INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
-       mutex_init(&atkbd->event_mutex);
+       mutex_init(&atkbd->mutex);
  
        switch (serio->id.type) {
  
 -              case SERIO_8042_XL:
 -                      atkbd->translated = 1;
 -              case SERIO_8042:
 -                      if (serio->write)
 -                              atkbd->write = 1;
 -                      break;
 +      case SERIO_8042_XL:
 +              atkbd->translated = true;
 +              /* Fall through */
 +
 +      case SERIO_8042:
 +              if (serio->write)
 +                      atkbd->write = true;
 +              break;
        }
  
        atkbd->softraw = atkbd_softraw;
        atkbd->scroll = atkbd_scroll;
  
        if (atkbd->softrepeat)
 -              atkbd->softraw = 1;
 +              atkbd->softraw = true;
  
        serio_set_drvdata(serio, atkbd);
  
@@@ -1165,20 -1169,23 +1175,24 @@@ static int atkbd_reconnect(struct seri
  {
        struct atkbd *atkbd = serio_get_drvdata(serio);
        struct serio_driver *drv = serio->drv;
+       int retval = -1;
  
        if (!atkbd || !drv) {
 -              printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
 +              dev_dbg(&serio->dev,
 +                      "reconnect request, but serio is disconnected, ignoring...\n");
                return -1;
        }
  
+       mutex_lock(&atkbd->mutex);
        atkbd_disable(atkbd);
  
        if (atkbd->write) {
                if (atkbd_probe(atkbd))
-                       return -1;
+                       goto out;
                if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
-                       return -1;
+                       goto out;
  
                atkbd_activate(atkbd);
  
        }
  
        atkbd_enable(atkbd);
+       retval = 0;
  
-       return 0;
+  out:
+       mutex_unlock(&atkbd->mutex);
+       return retval;
  }
  
  static struct serio_device_id atkbd_serio_ids[] = {
@@@ -1241,47 -1251,28 +1258,28 @@@ static ssize_t atkbd_attr_show_helper(s
                                ssize_t (*handler)(struct atkbd *, char *))
  {
        struct serio *serio = to_serio_port(dev);
-       int retval;
-       retval = serio_pin_driver(serio);
-       if (retval)
-               return retval;
-       if (serio->drv != &atkbd_drv) {
-               retval = -ENODEV;
-               goto out;
-       }
-       retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
+       struct atkbd *atkbd = serio_get_drvdata(serio);
  
- out:
-       serio_unpin_driver(serio);
-       return retval;
+       return handler(atkbd, buf);
  }
  
  static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
                                ssize_t (*handler)(struct atkbd *, const char *, size_t))
  {
        struct serio *serio = to_serio_port(dev);
-       struct atkbd *atkbd;
+       struct atkbd *atkbd = serio_get_drvdata(serio);
        int retval;
  
-       retval = serio_pin_driver(serio);
+       retval = mutex_lock_interruptible(&atkbd->mutex);
        if (retval)
                return retval;
  
-       if (serio->drv != &atkbd_drv) {
-               retval = -ENODEV;
-               goto out;
-       }
-       atkbd = serio_get_drvdata(serio);
        atkbd_disable(atkbd);
        retval = handler(atkbd, buf, count);
        atkbd_enable(atkbd);
  
- out:
-       serio_unpin_driver(serio);
+       mutex_unlock(&atkbd->mutex);
        return retval;
  }
  
@@@ -1295,8 -1286,7 +1293,8 @@@ static ssize_t atkbd_set_extra(struct a
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
        int err;
 -      unsigned char old_extra, old_set;
 +      bool old_extra;
 +      unsigned char old_set;
  
        if (!atkbd->write)
                return -EIO;
@@@ -1379,7 -1369,7 +1377,7 @@@ static ssize_t atkbd_set_scroll(struct 
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
        int err;
 -      unsigned char old_scroll;
 +      bool old_scroll;
  
        if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
@@@ -1423,8 -1413,7 +1421,8 @@@ static ssize_t atkbd_set_set(struct atk
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
        int err;
 -      unsigned char old_set, old_extra;
 +      unsigned char old_set;
 +      bool old_extra;
  
        if (!atkbd->write)
                return -EIO;
@@@ -1474,7 -1463,7 +1472,7 @@@ static ssize_t atkbd_set_softrepeat(str
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
        int err;
 -      unsigned char old_softrepeat, old_softraw;
 +      bool old_softrepeat, old_softraw;
  
        if (!atkbd->write)
                return -EIO;
                atkbd->dev = new_dev;
                atkbd->softrepeat = value;
                if (atkbd->softrepeat)
 -                      atkbd->softraw = 1;
 +                      atkbd->softraw = true;
                atkbd_set_device_attrs(atkbd);
  
                err = input_register_device(atkbd->dev);
@@@ -1524,7 -1513,7 +1522,7 @@@ static ssize_t atkbd_set_softraw(struc
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
        int err;
 -      unsigned char old_softraw;
 +      bool old_softraw;
  
        if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
index 25706f8022587c7461bccd8cc421050970a0f79e,8e9380bfed4097fcdc283cfc7c3532ed0e911318..efcc3a3b9b53a3e2d53964fe219a628aad915898
@@@ -36,8 -36,6 +36,8 @@@ static const struct 
        [SH_KEYSC_MODE_1] = { 0, 6, 5 },
        [SH_KEYSC_MODE_2] = { 1, 5, 6 },
        [SH_KEYSC_MODE_3] = { 2, 4, 7 },
 +      [SH_KEYSC_MODE_4] = { 3, 6, 6 },
 +      [SH_KEYSC_MODE_5] = { 4, 6, 7 },
  };
  
  struct sh_keysc_priv {
@@@ -124,6 -122,8 +124,6 @@@ static irqreturn_t sh_keysc_isr(int irq
        return IRQ_HANDLED;
  }
  
 -#define res_size(res) ((res)->end - (res)->start + 1)
 -
  static int __devinit sh_keysc_probe(struct platform_device *pdev)
  {
        struct sh_keysc_priv *priv;
        memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
        pdata = &priv->pdata;
  
 -      priv->iomem_base = ioremap_nocache(res->start, res_size(res));
 +      priv->iomem_base = ioremap_nocache(res->start, resource_size(res));
        if (priv->iomem_base == NULL) {
                dev_err(&pdev->dev, "failed to remap I/O memory\n");
                error = -ENXIO;
@@@ -295,7 -295,7 +295,7 @@@ static int sh_keysc_resume(struct devic
        return 0;
  }
  
- static struct dev_pm_ops sh_keysc_dev_pm_ops = {
+ static const struct dev_pm_ops sh_keysc_dev_pm_ops = {
        .suspend = sh_keysc_suspend,
        .resume = sh_keysc_resume,
  };
index 29dc6aade766fdeeea3240a570432fc646478002,90be30e9355606cbc0e50971fc4381c5b429952e..9169d1591c1fea50c854c82a129bff8663d2fe12
@@@ -68,6 -68,10 +68,6 @@@ module_param(post_interrupt_delay, int
  MODULE_PARM_DESC(post_interrupt_delay,
        "delay (ms) before recal after recal interrupt detected");
  
 -static int autorecal = 1;
 -module_param(autorecal, int, 0644);
 -MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
 -
  /*
   * When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
   * above the pad and still have it send packets.  This causes a jump cursor
@@@ -423,7 -427,6 +423,6 @@@ static void hgpk_recalib_work(struct wo
  
  static int hgpk_register(struct psmouse *psmouse)
  {
-       struct input_dev *dev = psmouse->dev;
        int err;
  
        /* register handlers */
index ee69ec399e089ac55feafe8e2f9090001a986c1a,e0f30186d513d4633649beeb9a7f73e361c7d972..c3b626e9eae7c075cd7597779ddbef4becb731f6
@@@ -26,8 -26,6 +26,8 @@@
   * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
   */
  
 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 +
  #include <linux/stddef.h>
  #include <linux/module.h>
  #include <linux/serio.h>
@@@ -121,10 -119,11 +121,10 @@@ static int serio_bind_driver(struct ser
  
                error = device_bind_driver(&serio->dev);
                if (error) {
 -                      printk(KERN_WARNING
 -                              "serio: device_bind_driver() failed "
 -                              "for %s (%s) and %s, error: %d\n",
 -                              serio->phys, serio->name,
 -                              drv->description, error);
 +                      dev_warn(&serio->dev,
 +                               "device_bind_driver() failed for %s (%s) and %s, error: %d\n",
 +                               serio->phys, serio->name,
 +                               drv->description, error);
                        serio_disconnect_driver(serio);
                        serio->dev.driver = NULL;
                        return error;
@@@ -139,9 -138,9 +139,9 @@@ static void serio_find_driver(struct se
  
        error = device_attach(&serio->dev);
        if (error < 0)
 -              printk(KERN_WARNING
 -                      "serio: device_attach() failed for %s (%s), error: %d\n",
 -                      serio->phys, serio->name, error);
 +              dev_warn(&serio->dev,
 +                       "device_attach() failed for %s (%s), error: %d\n",
 +                       serio->phys, serio->name, error);
  }
  
  
@@@ -195,14 -194,17 +195,14 @@@ static int serio_queue_event(void *obje
  
        event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
        if (!event) {
 -              printk(KERN_ERR
 -                      "serio: Not enough memory to queue event %d\n",
 -                      event_type);
 +              pr_err("Not enough memory to queue event %d\n", event_type);
                retval = -ENOMEM;
                goto out;
        }
  
        if (!try_module_get(owner)) {
 -              printk(KERN_WARNING
 -                      "serio: Can't get module reference, dropping event %d\n",
 -                      event_type);
 +              pr_warning("Can't get module reference, dropping event %d\n",
 +                         event_type);
                kfree(event);
                retval = -EINVAL;
                goto out;
@@@ -228,12 -230,14 +228,12 @@@ static void serio_free_event(struct ser
  
  static void serio_remove_duplicate_events(struct serio_event *event)
  {
 -      struct list_head *node, *next;
 -      struct serio_event *e;
 +      struct serio_event *e, *next;
        unsigned long flags;
  
        spin_lock_irqsave(&serio_event_lock, flags);
  
 -      list_for_each_safe(node, next, &serio_event_list) {
 -              e = list_entry(node, struct serio_event, node);
 +      list_for_each_entry_safe(e, next, &serio_event_list, node) {
                if (event->object == e->object) {
                        /*
                         * If this event is of different type we should not
                        if (event->type != e->type)
                                break;
  
 -                      list_del_init(node);
 +                      list_del_init(&e->node);
                        serio_free_event(e);
                }
        }
  
  static struct serio_event *serio_get_event(void)
  {
 -      struct serio_event *event;
 -      struct list_head *node;
 +      struct serio_event *event = NULL;
        unsigned long flags;
  
        spin_lock_irqsave(&serio_event_lock, flags);
  
 -      if (list_empty(&serio_event_list)) {
 -              spin_unlock_irqrestore(&serio_event_lock, flags);
 -              return NULL;
 +      if (!list_empty(&serio_event_list)) {
 +              event = list_first_entry(&serio_event_list,
 +                                       struct serio_event, node);
 +              list_del_init(&event->node);
        }
  
 -      node = serio_event_list.next;
 -      event = list_entry(node, struct serio_event, node);
 -      list_del_init(node);
 -
        spin_unlock_irqrestore(&serio_event_lock, flags);
 -
        return event;
  }
  
@@@ -275,36 -284,32 +275,30 @@@ static void serio_handle_event(void
  
        mutex_lock(&serio_mutex);
  
-       /*
-        * Note that we handle only one event here to give swsusp
-        * a chance to freeze kseriod thread. Serio events should
-        * be pretty rare so we are not concerned about taking
-        * performance hit.
-        */
-       if ((event = serio_get_event())) {
+       while ((event = serio_get_event())) {
  
                switch (event->type) {
 -                      case SERIO_REGISTER_PORT:
 -                              serio_add_port(event->object);
 -                              break;
  
 -                      case SERIO_RECONNECT_PORT:
 -                              serio_reconnect_port(event->object);
 -                              break;
 +              case SERIO_REGISTER_PORT:
 +                      serio_add_port(event->object);
 +                      break;
  
 -                      case SERIO_RESCAN_PORT:
 -                              serio_disconnect_port(event->object);
 -                              serio_find_driver(event->object);
 -                              break;
 +              case SERIO_RECONNECT_PORT:
 +                      serio_reconnect_port(event->object);
 +                      break;
  
 -                      case SERIO_RECONNECT_CHAIN:
 -                              serio_reconnect_chain(event->object);
 -                              break;
 +              case SERIO_RESCAN_PORT:
 +                      serio_disconnect_port(event->object);
 +                      serio_find_driver(event->object);
 +                      break;
  
 -                      case SERIO_ATTACH_DRIVER:
 -                              serio_attach_driver(event->object);
 -                              break;
 +              case SERIO_RECONNECT_CHAIN:
 +                      serio_reconnect_chain(event->object);
 +                      break;
  
 -                      default:
 -                              break;
 +              case SERIO_ATTACH_DRIVER:
 +                      serio_attach_driver(event->object);
 +                      break;
                }
  
                serio_remove_duplicate_events(event);
   */
  static void serio_remove_pending_events(void *object)
  {
 -      struct list_head *node, *next;
 -      struct serio_event *event;
 +      struct serio_event *event, *next;
        unsigned long flags;
  
        spin_lock_irqsave(&serio_event_lock, flags);
  
 -      list_for_each_safe(node, next, &serio_event_list) {
 -              event = list_entry(node, struct serio_event, node);
 +      list_for_each_entry_safe(event, next, &serio_event_list, node) {
                if (event->object == object) {
 -                      list_del_init(node);
 +                      list_del_init(&event->node);
                        serio_free_event(event);
                }
        }
@@@ -367,13 -374,13 +361,12 @@@ static struct serio *serio_get_pending_
  
  static int serio_thread(void *nothing)
  {
-       set_freezable();
        do {
                serio_handle_event();
-               wait_event_freezable(serio_wait,
+               wait_event_interruptible(serio_wait,
                        kthread_should_stop() || !list_empty(&serio_event_list));
        } while (!kthread_should_stop());
  
 -      printk(KERN_DEBUG "serio: kseriod exiting\n");
        return 0;
  }
  
@@@ -438,11 -445,6 +431,11 @@@ static struct attribute_group serio_id_
        .attrs  = serio_device_id_attrs,
  };
  
 +static const struct attribute_group *serio_device_attr_groups[] = {
 +      &serio_id_attr_group,
 +      NULL
 +};
 +
  static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct serio *serio = to_serio_port(dev);
@@@ -530,7 -532,6 +523,7 @@@ static void serio_init_port(struct seri
                        (long)atomic_inc_return(&serio_no) - 1);
        serio->dev.bus = &serio_bus;
        serio->dev.release = serio_release_port;
 +      serio->dev.groups = serio_device_attr_groups;
        if (serio->parent) {
                serio->dev.parent = &serio->parent->dev;
                serio->depth = serio->parent->depth + 1;
@@@ -554,15 -555,21 +547,15 @@@ static void serio_add_port(struct seri
        }
  
        list_add_tail(&serio->node, &serio_list);
 +
        if (serio->start)
                serio->start(serio);
 +
        error = device_add(&serio->dev);
        if (error)
 -              printk(KERN_ERR
 -                      "serio: device_add() failed for %s (%s), error: %d\n",
 +              dev_err(&serio->dev,
 +                      "device_add() failed for %s (%s), error: %d\n",
                        serio->phys, serio->name, error);
 -      else {
 -              serio->registered = true;
 -              error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
 -              if (error)
 -                      printk(KERN_ERR
 -                              "serio: sysfs_create_group() failed for %s (%s), error: %d\n",
 -                              serio->phys, serio->name, error);
 -      }
  }
  
  /*
@@@ -589,8 -596,11 +582,8 @@@ static void serio_destroy_port(struct s
                serio->parent = NULL;
        }
  
 -      if (serio->registered) {
 -              sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
 +      if (device_is_registered(&serio->dev))
                device_del(&serio->dev);
 -              serio->registered = false;
 -      }
  
        list_del_init(&serio->node);
        serio_remove_pending_events(serio);
@@@ -788,8 -798,9 +781,8 @@@ static void serio_attach_driver(struct 
  
        error = driver_attach(&drv->driver);
        if (error)
 -              printk(KERN_WARNING
 -                      "serio: driver_attach() failed for %s with error %d\n",
 -                      drv->driver.name, error);
 +              pr_warning("driver_attach() failed for %s with error %d\n",
 +                         drv->driver.name, error);
  }
  
  int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name)
  
        error = driver_register(&drv->driver);
        if (error) {
 -              printk(KERN_ERR
 -                      "serio: driver_register() failed for %s, error: %d\n",
 +              pr_err("driver_register() failed for %s, error: %d\n",
                        drv->driver.name, error);
                return error;
        }
@@@ -975,7 -987,7 +968,7 @@@ irqreturn_t serio_interrupt(struct seri
  
          if (likely(serio->drv)) {
                  ret = serio->drv->interrupt(serio, data, dfl);
 -      } else if (!dfl && serio->registered) {
 +      } else if (!dfl && device_is_registered(&serio->dev)) {
                serio_rescan(serio);
                ret = IRQ_HANDLED;
        }
@@@ -1006,7 -1018,7 +999,7 @@@ static int __init serio_init(void
  
        error = bus_register(&serio_bus);
        if (error) {
 -              printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
 +              pr_err("Failed to register serio bus, error: %d\n", error);
                return error;
        }
  
        if (IS_ERR(serio_task)) {
                bus_unregister(&serio_bus);
                error = PTR_ERR(serio_task);
 -              printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error);
 +              pr_err("Failed to start kseriod, error: %d\n", error);
                return error;
        }
  
diff --combined include/linux/serio.h
index d0fb702059cd905947546945e39ef0bd69a05ac4,813d26c247ece48b709a14a427f655a2c04442fc..64b473066b9aa49760d67c2d45eb695cbf0d812e
@@@ -30,6 -30,7 +30,6 @@@ struct serio 
        char phys[32];
  
        bool manual_bind;
 -      bool registered;        /* port has been fully registered with driver core */
  
        struct serio_device_id id;
  
@@@ -135,25 -136,6 +135,6 @@@ static inline void serio_continue_rx(st
        spin_unlock_irq(&serio->lock);
  }
  
- /*
-  * Use the following functions to pin serio's driver in process context
-  */
- static inline int serio_pin_driver(struct serio *serio)
- {
-       return mutex_lock_interruptible(&serio->drv_mutex);
- }
- static inline void serio_pin_driver_uninterruptible(struct serio *serio)
- {
-       mutex_lock(&serio->drv_mutex);
- }
- static inline void serio_unpin_driver(struct serio *serio)
- {
-       mutex_unlock(&serio->drv_mutex);
- }
  #endif
  
  /*