Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dtor/input.git manually
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 27 Jun 2005 21:47:31 +0000 (14:47 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 27 Jun 2005 21:47:31 +0000 (14:47 -0700)
Some manual fixups required due to clashes with the PF_FREEZE cleanups.

16 files changed:
1  2 
Documentation/kernel-parameters.txt
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/keyboard/atkbd.c
drivers/input/mouse/alps.c
drivers/input/mouse/psmouse.h
drivers/input/mousedev.c
drivers/usb/input/aiptek.c
drivers/usb/input/hid-core.c
include/linux/input.h
sound/oss/Kconfig
sound/oss/es1370.c
sound/oss/es1371.c
sound/oss/esssolo1.c
sound/pci/cs4281.c

@@@ -358,10 -358,6 +358,10 @@@ running once the system is up
        cpia_pp=        [HW,PPT]
                        Format: { parport<nr> | auto | none }
  
 +      crashkernel=nn[KMG]@ss[KMG]
 +                      [KNL] Reserve a chunk of physical memory to
 +                      hold a kernel to switch to with kexec on panic.
 +
        cs4232=         [HW,OSS]
                        Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
  
                        Format: {"as"|"cfq"|"deadline"|"noop"}
                        See Documentation/block/as-iosched.txt
                        and Documentation/block/deadline-iosched.txt for details.
 +      elfcorehdr=     [IA-32]
 +                      Specifies physical address of start of kernel core image
 +                      elf header.
 +                      See Documentation/kdump.txt for details.
  
        enforcing       [SELINUX] Set initial enforcing status.
                        Format: {"0" | "1"}
  
        i810=           [HW,DRM]
  
 +      i8k.ignore_dmi  [HW] Continue probing hardware even if DMI data
 +                      indicates that the driver is running on unsupported
 +                      hardware.
        i8k.force       [HW] Activate i8k driver even if SMM BIOS signature
                        does not match list of supported models.
        i8k.power_status
                        See Documentation/ramdisk.txt.
  
        psmouse.proto=  [HW,MOUSE] Highest PS2 mouse protocol extension to
-                       probe for (bare|imps|exps).
+                       probe for (bare|imps|exps|lifebook|any).
        psmouse.rate=   [HW,MOUSE] Set desired mouse report rate, in reports
                        per second.
        psmouse.resetafter=
diff --combined drivers/input/evdev.c
@@@ -21,6 -21,7 +21,7 @@@
  #include <linux/smp_lock.h>
  #include <linux/device.h>
  #include <linux/devfs_fs_kernel.h>
+ #include <linux/compat.h>
  
  struct evdev {
        int exist;
@@@ -145,6 -146,41 +146,41 @@@ static int evdev_open(struct inode * in
        return 0;
  }
  
+ #ifdef CONFIG_COMPAT
+ struct input_event_compat {
+       struct compat_timeval time;
+       __u16 type;
+       __u16 code;
+       __s32 value;
+ };
+ #ifdef CONFIG_X86_64
+ #  define COMPAT_TEST test_thread_flag(TIF_IA32)
+ #elif defined(CONFIG_IA64)
+ #  define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
+ #elif defined(CONFIG_ARCH_S390)
+ #  define COMPAT_TEST test_thread_flag(TIF_31BIT)
+ #else
+ #  define COMPAT_TEST test_thread_flag(TIF_32BIT)
+ #endif
+ static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+ {
+       struct evdev_list *list = file->private_data;
+       struct input_event_compat event;
+       int retval = 0;
+       while (retval < count) {
+               if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
+                       return -EFAULT;
+               input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+               retval += sizeof(struct input_event_compat);
+       }
+       return retval;
+ }
+ #endif
  static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
  {
        struct evdev_list *list = file->private_data;
  
        if (!list->evdev->exist) return -ENODEV;
  
+ #ifdef CONFIG_COMPAT
+       if (COMPAT_TEST)
+               return evdev_write_compat(file, buffer, count, ppos);
+ #endif
        while (retval < count) {
  
                if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
        return retval;
  }
  
+ #ifdef CONFIG_COMPAT
+ static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+ {
+       struct evdev_list *list = file->private_data;
+       int retval;
+       if (count < sizeof(struct input_event_compat))
+               return -EINVAL;
+       if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
+               return -EAGAIN;
+       retval = wait_event_interruptible(list->evdev->wait,
+               list->head != list->tail || (!list->evdev->exist));
+       if (retval)
+               return retval;
+       if (!list->evdev->exist)
+               return -ENODEV;
+       while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
+               struct input_event *event = (struct input_event *) list->buffer + list->tail;
+               struct input_event_compat event_compat;
+               event_compat.time.tv_sec = event->time.tv_sec;
+               event_compat.time.tv_usec = event->time.tv_usec;
+               event_compat.type = event->type;
+               event_compat.code = event->code;
+               event_compat.value = event->value;
+               if (copy_to_user(buffer + retval, &event_compat,
+                       sizeof(struct input_event_compat))) return -EFAULT;
+               list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
+               retval += sizeof(struct input_event_compat);
+       }
+       return retval;
+ }
+ #endif
  static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
  {
        struct evdev_list *list = file->private_data;
        int retval;
  
+ #ifdef CONFIG_COMPAT
+       if (COMPAT_TEST)
+               return evdev_read_compat(file, buffer, count, ppos);
+ #endif
        if (count < sizeof(struct input_event))
                return -EINVAL;
  
  
        while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
                if (copy_to_user(buffer + retval, list->buffer + list->tail,
-                        sizeof(struct input_event))) return -EFAULT;
+                       sizeof(struct input_event))) return -EFAULT;
                list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
                retval += sizeof(struct input_event);
        }
@@@ -203,7 -289,7 +289,7 @@@ static unsigned int evdev_poll(struct f
                (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
  }
  
- static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
        struct evdev_list *list = file->private_data;
        struct evdev *evdev = list->evdev;
  
                default:
  
-                       if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
+                       if (_IOC_TYPE(cmd) != 'E')
                                return -EINVAL;
  
-                       if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
-                               long *bits;
-                               int len;
-                               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;
-                                       default: return -EINVAL;
+                       if (_IOC_DIR(cmd) == _IOC_READ) {
+                               if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
+                                       long *bits;
+                                       int len;
+                                       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;
+                                               default: return -EINVAL;
+                                       }
+                                       len = NBITS(len) * sizeof(long);
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, bits, len) ? -EFAULT : len;
                                }
-                               len = NBITS(len) * sizeof(long);
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, bits, len) ? -EFAULT : len;
-                       }
  
-                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
-                               int len;
-                               len = NBITS(KEY_MAX) * sizeof(long);
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, dev->key, len) ? -EFAULT : len;
-                       }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
+                                       int len;
+                                       len = NBITS(KEY_MAX) * sizeof(long);
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->key, len) ? -EFAULT : len;
+                               }
  
-                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
-                               int len;
-                               len = NBITS(LED_MAX) * sizeof(long);
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, dev->led, len) ? -EFAULT : len;
-                       }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
+                                       int len;
+                                       len = NBITS(LED_MAX) * sizeof(long);
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->led, len) ? -EFAULT : len;
+                               }
  
-                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
-                               int len;
-                               len = NBITS(SND_MAX) * sizeof(long);
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
-                       }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
+                                       int len;
+                                       len = NBITS(SND_MAX) * sizeof(long);
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
+                               }
  
-                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
-                               int len;
-                               if (!dev->name) return -ENOENT;
-                               len = strlen(dev->name) + 1;
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, dev->name, len) ? -EFAULT : len;
-                       }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
+                                       int len;
+                                       if (!dev->name) return -ENOENT;
+                                       len = strlen(dev->name) + 1;
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->name, len) ? -EFAULT : len;
+                               }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
+                                       int len;
+                                       if (!dev->phys) return -ENOENT;
+                                       len = strlen(dev->phys) + 1;
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
+                               }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
+                                       int len;
+                                       if (!dev->uniq) return -ENOENT;
+                                       len = strlen(dev->uniq) + 1;
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
+                               }
+                               if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       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_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
-                               int len;
-                               if (!dev->phys) return -ENOENT;
-                               len = strlen(dev->phys) + 1;
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
                        }
  
-                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
-                               int len;
-                               if (!dev->uniq) return -ENOENT;
-                               len = strlen(dev->uniq) + 1;
-                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-                               return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
+                       if (_IOC_DIR(cmd) == _IOC_WRITE) {
+                               if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
+                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
+                                               return -EFAULT;
+                                       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;
+                                       return 0;
+                               }
                        }
+       }
+       return -EINVAL;
+ }
  
-                       if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+ #ifdef CONFIG_COMPAT
+ #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
+ #define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
+ #define OFF_COMPAT(x)  ((x)%BITS_PER_LONG_COMPAT)
+ #define BIT_COMPAT(x)  (1UL<<OFF_COMPAT(x))
+ #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT)
+ #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1)
+ #ifdef __BIG_ENDIAN
+ #define bit_to_user(bit, max) \
+ do { \
+       int i; \
+       int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
+       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
+       for (i = 0; i < len / sizeof(compat_long_t); i++) \
+               if (copy_to_user((compat_long_t*) p + i, \
+                                (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
+                                sizeof(compat_long_t))) \
+                       return -EFAULT; \
+       return len; \
+ } while (0)
+ #else
+ #define bit_to_user(bit, max) \
+ do { \
+       int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
+       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
+       return copy_to_user(p, (bit), len) ? -EFAULT : len; \
+ } while (0)
+ #endif
+ static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+       struct evdev_list *list = file->private_data;
+       struct evdev *evdev = list->evdev;
+       struct input_dev *dev = evdev->handle.dev;
+       struct input_absinfo abs;
+       void __user *p = compat_ptr(arg);
  
-                               int t = _IOC_NR(cmd) & ABS_MAX;
+       if (!evdev->exist) return -ENODEV;
  
-                               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];
+       switch (cmd) {
  
-                               if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
-                                       return -EFAULT;
+               case EVIOCGVERSION:
+               case EVIOCGID:
+               case EVIOCGKEYCODE:
+               case EVIOCSKEYCODE:
+               case EVIOCSFF:
+               case EVIOCRMFF:
+               case EVIOCGEFFECTS:
+               case EVIOCGRAB:
+                       return evdev_ioctl(file, cmd, (unsigned long) p);
  
-                               return 0;
+               default:
+                       if (_IOC_TYPE(cmd) != 'E')
+                               return -EINVAL;
+                       if (_IOC_DIR(cmd) == _IOC_READ) {
+                               if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
+                                       long *bits;
+                                       int max;
+                                       switch (_IOC_NR(cmd) & EV_MAX) {
+                                               case      0: bits = dev->evbit;  max = EV_MAX;  break;
+                                               case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
+                                               case EV_REL: bits = dev->relbit; max = REL_MAX; break;
+                                               case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
+                                               case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
+                                               case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
+                                               case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
+                                               case EV_FF:  bits = dev->ffbit;  max = FF_MAX;  break;
+                                               default: return -EINVAL;
+                                       }
+                                       bit_to_user(bits, max);
+                               }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
+                                       bit_to_user(dev->key, KEY_MAX);
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
+                                       bit_to_user(dev->led, LED_MAX);
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+                                       bit_to_user(dev->snd, SND_MAX);
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
+                                       int len;
+                                       if (!dev->name) return -ENOENT;
+                                       len = strlen(dev->name) + 1;
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->name, len) ? -EFAULT : len;
+                               }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
+                                       int len;
+                                       if (!dev->phys) return -ENOENT;
+                                       len = strlen(dev->phys) + 1;
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
+                               }
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
+                                       int len;
+                                       if (!dev->uniq) return -ENOENT;
+                                       len = strlen(dev->uniq) + 1;
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
+                               }
+                               if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+                                       int t = _IOC_NR(cmd) & ABS_MAX;
+                                       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_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
+                       if (_IOC_DIR(cmd) == _IOC_WRITE) {
  
-                               int 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;
+                                       int 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;
+                                       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;
+                                       return 0;
+                               }
                        }
        }
        return -EINVAL;
  }
+ #endif
  
  static struct file_operations evdev_fops = {
        .owner =        THIS_MODULE,
        .poll =         evdev_poll,
        .open =         evdev_open,
        .release =      evdev_release,
-       .ioctl =        evdev_ioctl,
+       .unlocked_ioctl = evdev_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl = evdev_ioctl_compat,
+ #endif
        .fasync =       evdev_fasync,
        .flush =        evdev_flush
  };
@@@ -431,9 -678,9 +678,9 @@@ static struct input_handle *evdev_conne
  
        devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
                        S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
 -      class_simple_device_add(input_class,
 -                              MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 -                              dev->dev, "event%d", minor);
 +      class_device_create(input_class,
 +                      MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 +                      dev->dev, "event%d", minor);
  
        return &evdev->handle;
  }
@@@ -443,8 -690,7 +690,8 @@@ static void evdev_disconnect(struct inp
        struct evdev *evdev = handle->private;
        struct evdev_list *list;
  
 -      class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 +      class_device_destroy(input_class,
 +                      MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
        devfs_remove("input/event%d", evdev->minor);
        evdev->exist = 0;
  
diff --combined drivers/input/input.c
@@@ -219,10 -219,24 +219,24 @@@ void input_release_device(struct input_
  
  int input_open_device(struct input_handle *handle)
  {
+       struct input_dev *dev = handle->dev;
+       int err;
+       err = down_interruptible(&dev->sem);
+       if (err)
+               return err;
        handle->open++;
-       if (handle->dev->open)
-               return handle->dev->open(handle->dev);
-       return 0;
+       if (!dev->users++ && dev->open)
+               err = dev->open(dev);
+       if (err)
+               handle->open--;
+       up(&dev->sem);
+       return err;
  }
  
  int input_flush_device(struct input_handle* handle, struct file* file)
  
  void input_close_device(struct input_handle *handle)
  {
+       struct input_dev *dev = handle->dev;
        input_release_device(handle);
-       if (handle->dev->close)
-               handle->dev->close(handle->dev);
+       down(&dev->sem);
+       if (!--dev->users && dev->close)
+               dev->close(dev);
        handle->open--;
+       up(&dev->sem);
  }
  
  static void input_link_handle(struct input_handle *handle)
@@@ -415,6 -436,8 +436,8 @@@ void input_register_device(struct input
  
        set_bit(EV_SYN, dev->evbit);
  
+       init_MUTEX(&dev->sem);
        /*
         * 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.
@@@ -674,6 -697,8 +697,8 @@@ static int input_handlers_read(char *bu
        return (count > cnt) ? cnt : count;
  }
  
+ static struct file_operations input_fileops;
  static int __init input_proc_init(void)
  {
        struct proc_dir_entry *entry;
                return -ENOMEM;
        }
        entry->owner = THIS_MODULE;
+       input_fileops = *entry->proc_fops;
+       entry->proc_fops = &input_fileops;
        entry->proc_fops->poll = input_devices_poll;
        entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
        if (entry == NULL) {
  static inline int input_proc_init(void) { return 0; }
  #endif
  
 -struct class_simple *input_class;
 +struct class *input_class;
  
  static int __init input_init(void)
  {
        int retval = -ENOMEM;
  
 -      input_class = class_simple_create(THIS_MODULE, "input");
 +      input_class = class_create(THIS_MODULE, "input");
        if (IS_ERR(input_class))
                return PTR_ERR(input_class);
        input_proc_init();
                remove_proc_entry("devices", proc_bus_input_dir);
                remove_proc_entry("handlers", proc_bus_input_dir);
                remove_proc_entry("input", proc_bus);
 -              class_simple_destroy(input_class);
 +              class_destroy(input_class);
                return retval;
        }
  
                remove_proc_entry("handlers", proc_bus_input_dir);
                remove_proc_entry("input", proc_bus);
                unregister_chrdev(INPUT_MAJOR, "input");
 -              class_simple_destroy(input_class);
 +              class_destroy(input_class);
        }
        return retval;
  }
@@@ -741,7 -768,7 +768,7 @@@ static void __exit input_exit(void
  
        devfs_remove("input");
        unregister_chrdev(INPUT_MAJOR, "input");
 -      class_simple_destroy(input_class);
 +      class_destroy(input_class);
  }
  
  subsys_initcall(input_init);
diff --combined drivers/input/joydev.c
@@@ -285,48 -285,33 +285,33 @@@ static unsigned int joydev_poll(struct 
                (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
  }
  
- static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
  {
-       struct joydev_list *list = file->private_data;
-       struct joydev *joydev = list->joydev;
        struct input_dev *dev = joydev->handle.dev;
-       void __user *argp = (void __user *)arg;
        int i, j;
  
-       if (!joydev->exist) return -ENODEV;
        switch (cmd) {
  
                case JS_SET_CAL:
                        return copy_from_user(&joydev->glue.JS_CORR, argp,
-                               sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
+                               sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
                case JS_GET_CAL:
                        return copy_to_user(argp, &joydev->glue.JS_CORR,
-                               sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
+                               sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
                case JS_SET_TIMEOUT:
-                       return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
+                       return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
                case JS_GET_TIMEOUT:
-                       return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
-               case JS_SET_TIMELIMIT:
-                       return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
-               case JS_GET_TIMELIMIT:
-                       return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
-               case JS_SET_ALL:
-                       return copy_from_user(&joydev->glue, argp,
-                                               sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
-               case JS_GET_ALL:
-                       return copy_to_user(argp, &joydev->glue,
-                                               sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
+                       return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
  
                case JSIOCGVERSION:
-                       return put_user(JS_VERSION, (__u32 __user *) arg);
+                       return put_user(JS_VERSION, (__u32 __user *) argp);
                case JSIOCGAXES:
-                       return put_user(joydev->nabs, (__u8 __user *) arg);
+                       return put_user(joydev->nabs, (__u8 __user *) argp);
                case JSIOCGBUTTONS:
-                       return put_user(joydev->nkey, (__u8 __user *) arg);
+                       return put_user(joydev->nkey, (__u8 __user *) argp);
                case JSIOCSCORR:
                        if (copy_from_user(joydev->corr, argp,
-                                     sizeof(struct js_corr) * joydev->nabs))
+                                     sizeof(joydev->corr[0]) * joydev->nabs))
                            return -EFAULT;
                        for (i = 0; i < joydev->nabs; i++) {
                                j = joydev->abspam[i];
                        return 0;
                case JSIOCGCORR:
                        return copy_to_user(argp, joydev->corr,
-                                               sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
+                                               sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
                case JSIOCSAXMAP:
                        if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
                                return -EFAULT;
        return -EINVAL;
  }
  
+ #ifdef CONFIG_COMPAT
+ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+       struct joydev_list *list = file->private_data;
+       struct joydev *joydev = list->joydev;
+       void __user *argp = (void __user *)arg;
+       s32 tmp32;
+       struct JS_DATA_SAVE_TYPE_32 ds32;
+       int err;
+       if (!joydev->exist) return -ENODEV;
+       switch(cmd) {
+       case JS_SET_TIMELIMIT:
+               err = get_user(tmp32, (s32 __user *) arg);
+               if (err == 0)
+                       joydev->glue.JS_TIMELIMIT = tmp32;
+               break;
+       case JS_GET_TIMELIMIT:
+               tmp32 = joydev->glue.JS_TIMELIMIT;
+               err = put_user(tmp32, (s32 __user *) arg);
+               break;
+       case JS_SET_ALL:
+               err = copy_from_user(&ds32, argp,
+                                    sizeof(ds32)) ? -EFAULT : 0;
+               if (err == 0) {
+                       joydev->glue.JS_TIMEOUT    = ds32.JS_TIMEOUT;
+                       joydev->glue.BUSY          = ds32.BUSY;
+                       joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME;
+                       joydev->glue.JS_TIMELIMIT  = ds32.JS_TIMELIMIT;
+                       joydev->glue.JS_SAVE       = ds32.JS_SAVE;
+                       joydev->glue.JS_CORR       = ds32.JS_CORR;
+               }
+               break;
+       case JS_GET_ALL:
+               ds32.JS_TIMEOUT    = joydev->glue.JS_TIMEOUT;
+               ds32.BUSY          = joydev->glue.BUSY;
+               ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME;
+               ds32.JS_TIMELIMIT  = joydev->glue.JS_TIMELIMIT;
+               ds32.JS_SAVE       = joydev->glue.JS_SAVE;
+               ds32.JS_CORR       = joydev->glue.JS_CORR;
+               err = copy_to_user(argp, &ds32,
+                                         sizeof(ds32)) ? -EFAULT : 0;
+               break;
+       default:
+               err = joydev_ioctl_common(joydev, cmd, argp);
+       }
+       return err;
+ }
+ #endif /* CONFIG_COMPAT */
+ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ {
+       struct joydev_list *list = file->private_data;
+       struct joydev *joydev = list->joydev;
+       void __user *argp = (void __user *)arg;
+       if (!joydev->exist) return -ENODEV;
+       switch(cmd) {
+               case JS_SET_TIMELIMIT:
+                       return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
+               case JS_GET_TIMELIMIT:
+                       return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
+               case JS_SET_ALL:
+                       return copy_from_user(&joydev->glue, argp,
+                                               sizeof(joydev->glue)) ? -EFAULT : 0;
+               case JS_GET_ALL:
+                       return copy_to_user(argp, &joydev->glue,
+                                               sizeof(joydev->glue)) ? -EFAULT : 0;
+               default:
+                       return joydev_ioctl_common(joydev, cmd, argp);
+       }
+ }
  static struct file_operations joydev_fops = {
        .owner =        THIS_MODULE,
        .read =         joydev_read,
        .open =         joydev_open,
        .release =      joydev_release,
        .ioctl =        joydev_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl = joydev_compat_ioctl,
+ #endif
        .fasync =       joydev_fasync,
  };
  
@@@ -452,9 -518,9 +518,9 @@@ static struct input_handle *joydev_conn
  
        devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
                        S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
 -      class_simple_device_add(input_class,
 -                              MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
 -                              dev->dev, "js%d", minor);
 +      class_device_create(input_class,
 +                      MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
 +                      dev->dev, "js%d", minor);
  
        return &joydev->handle;
  }
@@@ -464,7 -530,7 +530,7 @@@ static void joydev_disconnect(struct in
        struct joydev *joydev = handle->private;
        struct joydev_list *list;
  
 -      class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 +      class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
        devfs_remove("input/js%d", joydev->minor);
        joydev->exist = 0;
  
@@@ -54,7 -54,7 +54,7 @@@ static int atkbd_softraw = 1
  module_param_named(softraw, atkbd_softraw, bool, 0);
  MODULE_PARM_DESC(softraw, "Use software generated rawmode");
  
 -static int atkbd_scroll = 1;
 +static int atkbd_scroll = 0;
  module_param_named(scroll, atkbd_scroll, bool, 0);
  MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
  
@@@ -219,15 -219,15 +219,15 @@@ static ssize_t atkbd_attr_set_helper(st
  #define ATKBD_DEFINE_ATTR(_name)                                              \
  static ssize_t atkbd_show_##_name(struct atkbd *, char *);                    \
  static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t);               \
 -static ssize_t atkbd_do_show_##_name(struct device *d, char *b)                       \
 +static ssize_t atkbd_do_show_##_name(struct device *d, struct device_attribute *attr, char *b)                        \
  {                                                                             \
        return atkbd_attr_show_helper(d, b, atkbd_show_##_name);                \
  }                                                                             \
 -static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s)        \
 +static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s) \
  {                                                                             \
        return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name);               \
  }                                                                             \
- static struct device_attribute atkbd_attr_##_name =                           \
+ static struct device_attribute atkbd_attr_##_name =                           \
        __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
  
  ATKBD_DEFINE_ATTR(extra);
@@@ -388,7 -388,7 +388,7 @@@ static irqreturn_t atkbd_interrupt(stru
                        value = atkbd->release ? 0 :
                                (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
  
-                       switch (value) {        /* Workaround Toshiba laptop multiple keypress */
+                       switch (value) {        /* Workaround Toshiba laptop multiple keypress */
                                case 0:
                                        atkbd->last = 0;
                                        break;
@@@ -894,7 -894,7 +894,7 @@@ static int atkbd_reconnect(struct seri
        if (atkbd->write) {
                param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
                         | (test_bit(LED_NUML,    atkbd->dev.led) ? 2 : 0)
-                        | (test_bit(LED_CAPSL,   atkbd->dev.led) ? 4 : 0);
+                        | (test_bit(LED_CAPSL,   atkbd->dev.led) ? 4 : 0);
  
                if (atkbd_probe(atkbd))
                        return -1;
  
  #define ALPS_DUALPOINT        0x01
  #define ALPS_WHEEL    0x02
- #define ALPS_FW_BK    0x04
+ #define ALPS_FW_BK_1  0x04
  #define ALPS_4BTN     0x08
  #define ALPS_OLDPROTO 0x10
  #define ALPS_PASS     0x20
+ #define ALPS_FW_BK_2  0x40
  
  static struct alps_model_info alps_model_data[] = {
        { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO },            /* UMAX-530T */
        { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
        { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
        { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL },               /* Toshiba Satellite S2400-103 */
-       { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK },               /* NEC Versa L320 */
+       { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 },             /* NEC Versa L320 */
        { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
        { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS },                /* Dell Latitude D800 */
        { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
-       { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
+       { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 },             /* Ahtec Laptop */
        { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
        { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
        { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
  
  /*
   * ALPS abolute Mode - new format
-  * 
-  * byte 0:  1    ?    ?    ?    1    ?    ?    ? 
+  *
+  * byte 0:  1    ?    ?    ?    1    ?    ?    ?
   * byte 1:  0   x6   x5   x4   x3   x2   x1   x0
   * byte 2:  0   x10  x9   x8   x7    ?  fin  ges
-  * byte 3:  0   y9   y8   y7    1    M    R    L 
+  * byte 3:  0   y9   y8   y7    1    M    R    L
   * byte 4:  0   y6   y5   y4   y3   y2   y1   y0
   * byte 5:  0   z6   z5   z4   z3   z2   z1   z0
   *
@@@ -81,11 -82,12 +82,12 @@@ static void alps_process_packet(struct 
        struct input_dev *dev = &psmouse->dev;
        struct input_dev *dev2 = &priv->dev2;
        int x, y, z, ges, fin, left, right, middle;
+       int back = 0, forward = 0;
  
        input_regs(dev, regs);
  
        if ((packet[0] & 0xc8) == 0x08) {   /* 3-byte PS/2 packet */
-               input_report_key(dev2, BTN_LEFT,   packet[0] & 1);    
+               input_report_key(dev2, BTN_LEFT,   packet[0] & 1);
                input_report_key(dev2, BTN_RIGHT,  packet[0] & 2);
                input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
                input_report_rel(dev2, REL_X,
                z = packet[5];
        }
  
+       if (priv->i->flags & ALPS_FW_BK_1) {
+               back = packet[2] & 4;
+               forward = packet[0] & 0x10;
+       }
+       if (priv->i->flags & ALPS_FW_BK_2) {
+               back = packet[3] & 4;
+               forward = packet[2] & 4;
+               if ((middle = forward && back))
+                       forward = back = 0;
+       }
        ges = packet[2] & 1;
        fin = packet[2] & 2;
  
        input_report_abs(dev, ABS_PRESSURE, z);
        input_report_key(dev, BTN_TOOL_FINGER, z > 0);
  
        if (priv->i->flags & ALPS_WHEEL)
                input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
  
-       if (priv->i->flags & ALPS_FW_BK) {
-               input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
-               input_report_key(dev, BTN_BACK, packet[2] & 0x04);
+       if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
+               input_report_key(dev, BTN_FORWARD, forward);
+               input_report_key(dev, BTN_BACK, back);
        }
  
        input_sync(dev);
@@@ -257,7 -270,6 +270,6 @@@ static struct alps_model_info *alps_get
  static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
  {
        struct ps2dev *ps2dev = &psmouse->ps2dev;
-       unsigned char param[3];
        int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
  
        if (ps2_command(ps2dev, NULL, cmd) ||
                return -1;
  
        /* we may get 3 more bytes, just ignore them */
-       ps2_command(ps2dev, param, 0x0300);
+       ps2_drain(ps2dev, 3, 100);
  
        return 0;
  }
@@@ -352,7 -364,7 +364,7 @@@ static int alps_reconnect(struct psmous
        if (alps_get_status(psmouse, param))
                return -1;
  
 -      if (param[0] & 0x04)
 +      if (!(param[0] & 0x04))
                alps_tap_mode(psmouse, 1);
  
        if (alps_absolute_mode(psmouse)) {
@@@ -425,7 -437,7 +437,7 @@@ int alps_init(struct psmouse *psmouse
                psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
        }
  
-       if (priv->i->flags & ALPS_FW_BK) {
+       if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
                psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
                psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
        }
        priv->dev2.id.bustype = BUS_I8042;
        priv->dev2.id.vendor = 0x0002;
        priv->dev2.id.product = PSMOUSE_ALPS;
-       priv->dev2.id.version = 0x0000; 
-       
+       priv->dev2.id.version = 0x0000;
        priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
        priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
        priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
@@@ -461,17 -473,15 +473,15 @@@ init_fail
  int alps_detect(struct psmouse *psmouse, int set_properties)
  {
        int version;
-       struct alps_model_info *model; 
+       struct alps_model_info *model;
  
        if (!(model = alps_get_model(psmouse, &version)))
                return -1;
  
        if (set_properties) {
                psmouse->vendor = "ALPS";
-               if (model->flags & ALPS_DUALPOINT) 
-                       psmouse->name = "DualPoint TouchPad";
-               else
-                       psmouse->name = "GlidePoint";
+               psmouse->name = model->flags & ALPS_DUALPOINT ?
+                               "DualPoint TouchPad" : "GlidePoint";
                psmouse->model = version;
        }
        return 0;
@@@ -77,6 -77,8 +77,8 @@@ enum psmouse_type 
        PSMOUSE_IMEX,
        PSMOUSE_SYNAPTICS,
        PSMOUSE_ALPS,
+       PSMOUSE_LIFEBOOK,
+       PSMOUSE_AUTO            /* This one should always be last */
  };
  
  int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
@@@ -91,15 -93,15 +93,15 @@@ ssize_t psmouse_attr_set_helper(struct 
  #define PSMOUSE_DEFINE_ATTR(_name)                                            \
  static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *);           \
  static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
 -static ssize_t psmouse_do_show_##_name(struct device *d, char *b)             \
 +static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b)              \
  {                                                                             \
        return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name);       \
  }                                                                             \
 -static ssize_t psmouse_do_set_##_name(struct device *d, const char *b, size_t s)\
 +static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\
  {                                                                             \
        return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name);      \
  }                                                                             \
- static struct device_attribute psmouse_attr_##_name =                                 \
+ static struct device_attribute psmouse_attr_##_name =                         \
        __ATTR(_name, S_IWUSR | S_IRUGO,                                        \
                psmouse_do_show_##_name, psmouse_do_set_##_name);
  
diff --combined drivers/input/mousedev.c
@@@ -220,6 -220,7 +220,7 @@@ static void mousedev_notify_readers(str
        struct mousedev_list *list;
        struct mousedev_motion *p;
        unsigned long flags;
+       int wake_readers = 0;
  
        list_for_each_entry(list, &mousedev->list, node) {
                spin_lock_irqsave(&list->packet_lock, flags);
  
                spin_unlock_irqrestore(&list->packet_lock, flags);
  
-               if (list->ready)
+               if (list->ready) {
                        kill_fasync(&list->fasync, SIGIO, POLL_IN);
+                       wake_readers = 1;
+               }
        }
  
-       wake_up_interruptible(&mousedev->wait);
+       if (wake_readers)
+               wake_up_interruptible(&mousedev->wait);
  }
  
  static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
@@@ -647,9 -651,9 +651,9 @@@ static struct input_handle *mousedev_co
  
        devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
                        S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
 -      class_simple_device_add(input_class,
 -                              MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
 -                              dev->dev, "mouse%d", minor);
 +      class_device_create(input_class,
 +                      MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
 +                      dev->dev, "mouse%d", minor);
  
        return &mousedev->handle;
  }
@@@ -659,8 -663,7 +663,8 @@@ static void mousedev_disconnect(struct 
        struct mousedev *mousedev = handle->private;
        struct mousedev_list *list;
  
 -      class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 +      class_device_destroy(input_class,
 +                      MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
        devfs_remove("input/mouse%d", mousedev->minor);
        mousedev->exist = 0;
  
@@@ -736,8 -739,8 +740,8 @@@ static int __init mousedev_init(void
  
        devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
                        S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
 -      class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
 -                              NULL, "mice");
 +      class_device_create(input_class,
 +                      MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
  
  #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
        if (!(psaux_registered = !misc_register(&psaux_mouse)))
@@@ -756,8 -759,7 +760,8 @@@ static void __exit mousedev_exit(void
                misc_deregister(&psaux_mouse);
  #endif
        devfs_remove("input/mice");
 -      class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 +      class_device_destroy(input_class,
 +                      MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
        input_unregister_handler(&mousedev_handler);
  }
  
@@@ -1,7 -1,7 +1,7 @@@
  /*
   *  Native support for the Aiptek HyperPen USB Tablets
   *  (4000U/5000U/6000U/8000U/12000U)
-  *  
+  *
   *  Copyright (c) 2001      Chris Atenasio   <chris@crud.net>
   *  Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net>
   *
@@@ -31,7 -31,7 +31,7 @@@
   *           - Added support for the sysfs interface, deprecating the
   *             procfs interface for 2.5.x kernel. Also added support for
   *             Wheel command. Bryan W. Headley July-15-2003.
-  *      v1.2 - Reworked jitter timer as a kernel thread. 
+  *      v1.2 - Reworked jitter timer as a kernel thread.
   *             Bryan W. Headley November-28-2003/Jan-10-2004.
   *      v1.3 - Repaired issue of kernel thread going nuts on single-processor
   *             machines, introduced programmableDelay as a command line
   * NOTE:
   *      This kernel driver is augmented by the "Aiptek" XFree86 input
   *      driver for your X server, as well as the Gaiptek GUI Front-end
-  *      "Tablet Manager". 
-  *      These three products are highly interactive with one another, 
+  *      "Tablet Manager".
+  *      These three products are highly interactive with one another,
   *      so therefore it's easier to document them all as one subsystem.
-  *      Please visit the project's "home page", located at, 
+  *      Please visit the project's "home page", located at,
   *      http://aiptektablet.sourceforge.net.
   *
   * This program is free software; you can redistribute it and/or modify
   * Command/Data    Description     Return Bytes    Return Value
   * 0x10/0x00       SwitchToMouse       0
   * 0x10/0x01       SwitchToTablet      0
-  * 0x18/0x04       SetResolution       0 
+  * 0x18/0x04       SetResolution       0
   * 0x12/0xFF       AutoGainOn          0
   * 0x17/0x00       FilterOn            0
   * 0x01/0x00       GetXExtension       2           MaxX
  #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE        2
  #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED             3
  
-       /* Time to wait (in ms) to help mask hand jittering 
+       /* Time to wait (in ms) to help mask hand jittering
         * when pressing the stylus buttons.
         */
  #define AIPTEK_JITTER_DELAY_DEFAULT                   50
@@@ -324,7 -324,6 +324,6 @@@ struct aiptek 
        struct aiptek_settings curSetting;      /* tablet's current programmable */
        struct aiptek_settings newSetting;      /* ... and new param settings    */
        unsigned int ifnum;                     /* interface number for IO       */
-       int openCount;                          /* module use counter            */
        int diagnostic;                         /* tablet diagnostic codes       */
        unsigned long eventCount;               /* event count                   */
        int inDelay;                            /* jitter: in jitter delay?      */
@@@ -791,7 -790,7 +790,7 @@@ exit
   * specific Aiptek model numbers, because there has been overlaps,
   * use, and reuse of id's in existing models. Certain models have
   * been known to use more than one ID, indicative perhaps of
-  * manufacturing revisions. In any event, we consider these 
+  * manufacturing revisions. In any event, we consider these
   * IDs to not be model-specific nor unique.
   */
  static const struct usb_device_id aiptek_ids[] = {
@@@ -814,15 -813,9 +813,9 @@@ static int aiptek_open(struct input_de
  {
        struct aiptek *aiptek = inputdev->private;
  
-       if (aiptek->openCount++ > 0) {
-               return 0;
-       }
        aiptek->urb->dev = aiptek->usbdev;
-       if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) {
-               aiptek->openCount--;
+       if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0)
                return -EIO;
-       }
  
        return 0;
  }
@@@ -834,13 -827,11 +827,11 @@@ static void aiptek_close(struct input_d
  {
        struct aiptek *aiptek = inputdev->private;
  
-       if (--aiptek->openCount == 0) {
-               usb_kill_urb(aiptek->urb);
-       }
+       usb_kill_urb(aiptek->urb);
  }
  
  /***********************************************************************
-  * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, 
+  * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x,
   * where they were known as usb_set_report and usb_get_report.
   */
  static int
@@@ -1025,7 -1016,7 +1016,7 @@@ static int aiptek_program_tablet(struc
  /***********************************************************************
   * support the 'size' file -- display support
   */
 -static ssize_t show_tabletSize(struct device *dev, char *buf)
 +static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1048,7 -1039,7 +1039,7 @@@ static DEVICE_ATTR(size, S_IRUGO, show_
  /***********************************************************************
   * support routines for the 'product_id' file
   */
 -static ssize_t show_tabletProductId(struct device *dev, char *buf)
 +static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1064,7 -1055,7 +1055,7 @@@ static DEVICE_ATTR(product_id, S_IRUGO
  /***********************************************************************
   * support routines for the 'vendor_id' file
   */
 -static ssize_t show_tabletVendorId(struct device *dev, char *buf)
 +static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1079,7 -1070,7 +1070,7 @@@ static DEVICE_ATTR(vendor_id, S_IRUGO, 
  /***********************************************************************
   * support routines for the 'vendor' file
   */
 -static ssize_t show_tabletManufacturer(struct device *dev, char *buf)
 +static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        int retval;
@@@ -1096,7 -1087,7 +1087,7 @@@ static DEVICE_ATTR(vendor, S_IRUGO, sho
  /***********************************************************************
   * support routines for the 'product' file
   */
 -static ssize_t show_tabletProduct(struct device *dev, char *buf)
 +static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        int retval;
@@@ -1114,7 -1105,7 +1105,7 @@@ static DEVICE_ATTR(product, S_IRUGO, sh
   * support routines for the 'pointer_mode' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletPointerMode(struct device *dev, char *buf)
 +static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletPointerMode(struct device *dev, const char *buf, size_t count)
 +store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        if (aiptek == NULL)
@@@ -1168,7 -1159,7 +1159,7 @@@ static DEVICE_ATTR(pointer_mode
   * support routines for the 'coordinate_mode' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletCoordinateMode(struct device *dev, char *buf)
 +static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletCoordinateMode(struct device *dev, const char *buf, size_t count)
 +store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        if (aiptek == NULL)
@@@ -1217,7 -1208,7 +1208,7 @@@ static DEVICE_ATTR(coordinate_mode
   * support routines for the 'tool_mode' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletToolMode(struct device *dev, char *buf)
 +static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletToolMode(struct device *dev, const char *buf, size_t count)
 +store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        if (aiptek == NULL)
@@@ -1295,7 -1286,7 +1286,7 @@@ static DEVICE_ATTR(tool_mode
   * support routines for the 'xtilt' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletXtilt(struct device *dev, char *buf)
 +static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
  }
  
  static ssize_t
 -store_tabletXtilt(struct device *dev, const char *buf, size_t count)
 +store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        int x;
@@@ -1337,7 -1328,7 +1328,7 @@@ static DEVICE_ATTR(xtilt
   * support routines for the 'ytilt' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletYtilt(struct device *dev, char *buf)
 +static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
  }
  
  static ssize_t
 -store_tabletYtilt(struct device *dev, const char *buf, size_t count)
 +store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        int y;
@@@ -1379,7 -1370,7 +1370,7 @@@ static DEVICE_ATTR(ytilt
   * support routines for the 'jitter' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletJitterDelay(struct device *dev, char *buf)
 +static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
  }
  
  static ssize_t
 -store_tabletJitterDelay(struct device *dev, const char *buf, size_t count)
 +store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1409,7 -1400,7 +1400,7 @@@ static DEVICE_ATTR(jitter
   * support routines for the 'delay' file. Note that this file
   * both displays current setting and allows reprogramming.
   */
 -static ssize_t show_tabletProgrammableDelay(struct device *dev, char *buf)
 +static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
  }
  
  static ssize_t
 -store_tabletProgrammableDelay(struct device *dev, const char *buf, size_t count)
 +store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1440,7 -1431,7 +1431,7 @@@ static DEVICE_ATTR(delay
   * support routines for the 'input_path' file. Note that this file
   * only displays current setting.
   */
 -static ssize_t show_tabletInputDevice(struct device *dev, char *buf)
 +static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1457,7 -1448,7 +1448,7 @@@ static DEVICE_ATTR(input_path, S_IRUGO
   * support routines for the 'event_count' file. Note that this file
   * only displays current setting.
   */
 -static ssize_t show_tabletEventsReceived(struct device *dev, char *buf)
 +static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1473,7 -1464,7 +1464,7 @@@ static DEVICE_ATTR(event_count, S_IRUGO
   * support routines for the 'diagnostic' file. Note that this file
   * only displays current setting.
   */
 -static ssize_t show_tabletDiagnosticMessage(struct device *dev, char *buf)
 +static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *retMsg;
@@@ -1515,7 -1506,7 +1506,7 @@@ static DEVICE_ATTR(diagnostic, S_IRUGO
   * support routines for the 'stylus_upper' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletStylusUpper(struct device *dev, char *buf)
 +static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletStylusUpper(struct device *dev, const char *buf, size_t count)
 +store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1565,7 -1556,7 +1556,7 @@@ static DEVICE_ATTR(stylus_upper
   * support routines for the 'stylus_lower' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletStylusLower(struct device *dev, char *buf)
 +static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletStylusLower(struct device *dev, const char *buf, size_t count)
 +store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1615,7 -1606,7 +1606,7 @@@ static DEVICE_ATTR(stylus_lower
   * support routines for the 'mouse_left' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletMouseLeft(struct device *dev, char *buf)
 +static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletMouseLeft(struct device *dev, const char *buf, size_t count)
 +store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1669,7 -1660,7 +1660,7 @@@ static DEVICE_ATTR(mouse_left
   * support routines for the 'mouse_middle' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletMouseMiddle(struct device *dev, char *buf)
 +static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletMouseMiddle(struct device *dev, const char *buf, size_t count)
 +store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1725,7 -1716,7 +1716,7 @@@ static DEVICE_ATTR(mouse_middle
   * support routines for the 'mouse_right' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletMouseRight(struct device *dev, char *buf)
 +static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
        char *s;
  }
  
  static ssize_t
 -store_tabletMouseRight(struct device *dev, const char *buf, size_t count)
 +store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1780,7 -1771,7 +1771,7 @@@ static DEVICE_ATTR(mouse_right
   * support routines for the 'wheel' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletWheel(struct device *dev, char *buf)
 +static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
  }
  
  static ssize_t
 -store_tabletWheel(struct device *dev, const char *buf, size_t count)
 +store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1814,7 -1805,7 +1805,7 @@@ static DEVICE_ATTR(wheel
   * support routines for the 'execute' file. Note that this file
   * both displays current setting and allows for setting changing.
   */
 -static ssize_t show_tabletExecute(struct device *dev, char *buf)
 +static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
  }
  
  static ssize_t
 -store_tabletExecute(struct device *dev, const char *buf, size_t count)
 +store_tabletExecute(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1855,7 -1846,7 +1846,7 @@@ static DEVICE_ATTR(execute
   * support routines for the 'odm_code' file. Note that this file
   * only displays current setting.
   */
 -static ssize_t show_tabletODMCode(struct device *dev, char *buf)
 +static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1871,7 -1862,7 +1862,7 @@@ static DEVICE_ATTR(odm_code, S_IRUGO, s
   * support routines for the 'model_code' file. Note that this file
   * only displays current setting.
   */
 -static ssize_t show_tabletModelCode(struct device *dev, char *buf)
 +static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -1887,7 -1878,7 +1878,7 @@@ static DEVICE_ATTR(model_code, S_IRUGO
   * support routines for the 'firmware_code' file. Note that this file
   * only displays current setting.
   */
 -static ssize_t show_firmwareCode(struct device *dev, char *buf)
 +static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct aiptek *aiptek = dev_get_drvdata(dev);
  
@@@ -2252,7 -2243,6 +2243,6 @@@ static void aiptek_disconnect(struct us
                                AIPTEK_PACKET_LENGTH,
                                aiptek->data, aiptek->data_dma);
                kfree(aiptek);
-               aiptek = NULL;
        }
  }
  
@@@ -232,7 -232,7 +232,7 @@@ static int hid_add_field(struct hid_par
        report->size += parser->global.report_size * parser->global.report_count;
  
        if (!parser->local.usage_index) /* Ignore padding fields */
-               return 0; 
+               return 0;
  
        usages = max_t(int, parser->local.usage_index, parser->global.report_count);
  
@@@ -765,7 -765,7 +765,7 @@@ static __inline__ __u32 s32ton(__s32 va
  static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
  {
        report += (offset >> 5) << 2; offset &= 31;
-       return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1);
+       return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1);
  }
  
  static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
@@@ -1233,6 -1233,13 +1233,13 @@@ int hid_wait_io(struct hid_device *hid
        return 0;
  }
  
+ static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
+ {
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report,
+               ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ }
  static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
                unsigned char type, void *buf, int size)
  {
@@@ -1301,10 -1308,6 +1308,6 @@@ void hid_init_reports(struct hid_devic
  
        if (err)
                warn("timeout initializing reports\n");
-       usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-               HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
-               hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
  }
  
  #define USB_VENDOR_ID_WACOM           0x056a
  #define USB_DEVICE_ID_WACOM_INTUOS3   0x00B0
  #define USB_DEVICE_ID_WACOM_CINTIQ    0x003F
  
+ #define USB_VENDOR_ID_ACECAD          0x0460
+ #define USB_DEVICE_ID_ACECAD_FLAIR    0x0004
+ #define USB_DEVICE_ID_ACECAD_302      0x0008
  #define USB_VENDOR_ID_KBGEAR          0x084e
  #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO        0x1001
  
@@@ -1502,6 -1509,9 +1509,9 @@@ static struct hid_blacklist 
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
  
+       { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
@@@ -1590,6 -1600,8 +1600,8 @@@ static struct hid_device *usb_hid_confi
                return NULL;
        }
  
+       hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
        if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
                dbg("reading report descriptor failed");
                kfree(rdesc);
                /* Change the polling interval of mice. */
                if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
                        interval = hid_mousepoll_interval;
-               
                if (endpoint->bEndpointAddress & USB_DIR_IN) {
                        if (hid->urbin)
                                continue;
@@@ -1762,7 -1774,7 +1774,7 @@@ static int hid_probe(struct usb_interfa
                        intf->altsetting->desc.bInterfaceNumber);
  
        if (!(hid = usb_hid_configure(intf)))
 -              return -EIO;
 +              return -ENODEV;
  
        hid_init_reports(hid);
        hid_dump_device(hid);
        if (!hid->claimed) {
                printk ("HID device not claimed by input or hiddev\n");
                hid_disconnect(intf);
 -              return -EIO;
 +              return -ENODEV;
        }
  
        printk(KERN_INFO);
diff --combined include/linux/input.h
@@@ -859,6 -859,10 +859,10 @@@ struct input_dev 
        int (*erase_effect)(struct input_dev *dev, int effect_id);
  
        struct input_handle *grab;
+       struct semaphore sem;   /* serializes open and close operations */
+       unsigned int users;
        struct device *dev;
  
        struct list_head        h_list;
@@@ -1015,7 -1019,7 +1019,7 @@@ static inline void input_set_abs_params
        dev->absbit[LONG(axis)] |= BIT(axis);
  }
  
 -extern struct class_simple *input_class;
 +extern struct class *input_class;
  
  #endif
  #endif
diff --combined sound/oss/Kconfig
@@@ -6,7 -6,7 +6,7 @@@
  # Prompt user for primary drivers.
  config SOUND_BT878
        tristate "BT878 audio dma"
 -      depends on SOUND_PRIME!=n && SOUND
 +      depends on SOUND_PRIME
        ---help---
          Audio DMA support for bt878 based grabber boards.  As you might have
          already noticed, bt878 is listed with two functions in /proc/pci.
@@@ -22,7 -22,7 +22,7 @@@
  
  config SOUND_CMPCI
        tristate "C-Media PCI (CMI8338/8738)"
 -      depends on SOUND_PRIME!=n && SOUND && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card using the CMI8338
          or the CMI8738 chipset.  Data on these chips are available at
@@@ -52,7 -52,7 +52,7 @@@ config SOUND_CMPCI_MID
  
  config SOUND_CMPCI_JOYSTICK
        bool "Enable joystick"
-       depends on SOUND_CMPCI && X86
+       depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
        help
          Say Y here in order to enable the joystick port on a sound card using
          the CMI8338 or the CMI8738 chipset.  You need to config the
@@@ -61,7 -61,7 +61,7 @@@
  
  config SOUND_EMU10K1
        tristate "Creative SBLive! (EMU10K1)"
 -      depends on SOUND_PRIME!=n && SOUND && PCI
 +      depends on SOUND_PRIME && PCI
        ---help---
          Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
          such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@@ -87,7 -87,7 +87,7 @@@ config MIDI_EMU10K
  
  config SOUND_FUSION
        tristate "Crystal SoundFusion (CS4280/461x)"
 -      depends on SOUND_PRIME!=n && SOUND
 +      depends on SOUND_PRIME
        help
          This module drives the Crystal SoundFusion devices (CS4280/46xx
          series) when wired as native sound drivers with AC97 codecs.  If
  
  config SOUND_CS4281
        tristate "Crystal Sound CS4281"
 -      depends on SOUND_PRIME!=n && SOUND
 +      depends on SOUND_PRIME
        help
          Picture and feature list at
          <http://www.pcbroker.com/crystal4281.html>.
  
  config SOUND_BCM_CS4297A
        tristate "Crystal Sound CS4297a (for Swarm)"
 -      depends on SOUND_PRIME!=n && SIBYTE_SWARM && SOUND
 +      depends on SOUND_PRIME && SIBYTE_SWARM
        help
          The BCM91250A has a Crystal CS4297a on synchronous serial
          port B (in addition to the DB-9 serial port).  Say Y or M
  
  config SOUND_ES1370
        tristate "Ensoniq AudioPCI (ES1370)"
 -      depends on SOUND_PRIME!=n && SOUND && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the Ensoniq
          ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
  
  config SOUND_ES1371
        tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
 -      depends on SOUND_PRIME!=n && SOUND && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the Ensoniq
          ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
  
  config SOUND_ESSSOLO1
        tristate "ESS Technology Solo1" 
 -      depends on SOUND_PRIME!=n && SOUND && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the ESS Technology
          Solo1 chip. To find out if your sound card uses a
  
  config SOUND_MAESTRO
        tristate "ESS Maestro, Maestro2, Maestro2E driver"
 -      depends on SOUND_PRIME!=n && SOUND && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a sound system driven by ESS's Maestro line
          of PCI sound chips.  These include the Maestro 1, Maestro 2, and
  
  config SOUND_MAESTRO3
        tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
 -      depends on SOUND_PRIME!=n && SOUND && PCI && EXPERIMENTAL
 +      depends on SOUND_PRIME && PCI && EXPERIMENTAL
        help
          Say Y or M if you have a sound system driven by ESS's Maestro 3
          PCI sound chip.
  
  config SOUND_ICH
        tristate "Intel ICH (i8xx) audio support"
 -      depends on SOUND_PRIME!=n && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Support for integral audio in Intel's I/O Controller Hub (ICH)
          chipset, as used on the 810/820/840 motherboards.
  
  config SOUND_HARMONY
        tristate "PA Harmony audio driver"
 -      depends on GSC_LASI && SOUND_PRIME!=n
 +      depends on GSC_LASI && SOUND_PRIME
        help
          Say 'Y' or 'M' to include support for Harmony soundchip
          on HP 712, 715/new and many other GSC based machines.
  
  config SOUND_SONICVIBES
        tristate "S3 SonicVibes"
 -      depends on SOUND_PRIME!=n && SOUND
 +      depends on SOUND_PRIME
        help
          Say Y or M if you have a PCI sound card utilizing the S3
          SonicVibes chipset. To find out if your sound card uses a
  
  config SOUND_VWSND
        tristate "SGI Visual Workstation Sound"
 -      depends on SOUND_PRIME!=n && X86_VISWS && SOUND
 +      depends on SOUND_PRIME && X86_VISWS
        help
          Say Y or M if you have an SGI Visual Workstation and you want to be
          able to use its on-board audio.  Read
  
  config SOUND_HAL2
        tristate "SGI HAL2 sound (EXPERIMENTAL)"
 -      depends on SOUND_PRIME!=n && SOUND && SGI_IP22 && EXPERIMENTAL
 +      depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
        help
          Say Y or M if you have an SGI Indy system and want to be able to
          use it's on-board A2 audio system.
  
  config SOUND_IT8172
        tristate "IT8172G Sound"
 -      depends on SOUND_PRIME!=n && (MIPS_ITE8172 || MIPS_IVR) && SOUND
 +      depends on SOUND_PRIME && (MIPS_ITE8172 || MIPS_IVR)
  
  config SOUND_VRC5477
        tristate "NEC Vrc5477 AC97 sound"
 -      depends on SOUND_PRIME!=n && DDB5477 && SOUND
 +      depends on SOUND_PRIME && DDB5477
        help
          Say Y here to enable sound support for the NEC Vrc5477 chip, an
          integrated, multi-function controller chip for MIPS CPUs.  Works
  
  config SOUND_AU1000
        tristate "Au1000 Sound"
 -      depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND
 +      depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500)
  
  config SOUND_AU1550_AC97
        tristate "Au1550 AC97 Sound"
 -      depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND
 +      depends on SOUND_PRIME && SOC_AU1550
  
  config SOUND_TRIDENT
        tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
 -      depends on SOUND_PRIME!=n && SOUND
 +      depends on SOUND_PRIME
        ---help---
          Say Y or M if you have a PCI sound card utilizing the Trident
          4DWave-DX/NX chipset or your mother board chipset has SiS 7018
  
  config SOUND_MSNDCLAS
        tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
 -      depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE)
 +      depends on SOUND_PRIME && (m || !STANDALONE)
        help
          Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
          Monterey (not for the Pinnacle or Fiji).
@@@ -331,7 -331,7 +331,7 @@@ config MSNDCLAS_I
  
  config SOUND_MSNDPIN
        tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji"
 -      depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE)
 +      depends on SOUND_PRIME && (m || !STANDALONE)
        help
          Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
          See <file:Documentation/sound/oss/MultiSound> for important information
@@@ -492,7 -492,7 +492,7 @@@ config MSND_FIFOSIZ
  
  config SOUND_VIA82CXXX
        tristate "VIA 82C686 Audio Codec"
 -      depends on SOUND_PRIME!=n && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y here to include support for the audio codec found on VIA
          82Cxxx-based chips. Typically these are built into a motherboard.
@@@ -512,7 -512,7 +512,7 @@@ config MIDI_VIA82CXX
  
  config SOUND_OSS
        tristate "OSS sound modules"
 -      depends on SOUND_PRIME!=n && SOUND
 +      depends on SOUND_PRIME
        help
          OSS is the Open Sound System suite of sound card drivers.  They make
          sound programming easier since they provide a common API.  Say Y or
@@@ -1077,7 -1077,7 +1077,7 @@@ config SOUND_WAVEARTIS
  
  config SOUND_TVMIXER
        tristate "TV card (bt848) mixer support"
 -      depends on SOUND_PRIME!=n && SOUND && I2C
 +      depends on SOUND_PRIME && I2C
        help
          Support for audio mixer facilities on the BT848 TV frame-grabber
          card.
@@@ -1088,11 -1088,11 +1088,11 @@@ config SOUND_KAHLU
  
  config SOUND_ALI5455
        tristate "ALi5455 audio support"
 -      depends on SOUND_PRIME!=n && PCI
 +      depends on SOUND_PRIME && PCI
  
  config SOUND_FORTE
        tristate "ForteMedia FM801 driver"
 -      depends on SOUND_PRIME!=n && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you want driver support for the ForteMedia FM801 PCI
          audio controller (Abit AU10, Genius Sound Maker, HP Workstation
  
  config SOUND_RME96XX
        tristate "RME Hammerfall (RME96XX) support"
 -      depends on SOUND_PRIME!=n && PCI
 +      depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a Hammerfall or Hammerfall light
          multichannel card from RME. If you want to access advanced
  
  config SOUND_AD1980
        tristate "AD1980 front/back switch plugin"
 -      depends on SOUND_PRIME!=n
 +      depends on SOUND_PRIME
  
  config SOUND_SH_DAC_AUDIO
        tristate "SuperH DAC audio support"
 -      depends on SOUND_PRIME!=n && SOUND && CPU_SH3
 +      depends on SOUND_PRIME && CPU_SH3
  
  config SOUND_SH_DAC_AUDIO_CHANNEL
        int "    DAC channel"
diff --combined sound/oss/es1370.c
  #include <linux/spinlock.h>
  #include <linux/gameport.h>
  #include <linux/wait.h>
 +#include <linux/dma-mapping.h>
  
  #include <asm/io.h>
  #include <asm/page.h>
  #include <asm/uaccess.h>
  
+ #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+ #define SUPPORT_JOYSTICK
+ #endif
  /* --------------------------------------------------------------------- */
  
  #undef OSS_DOCUMENTED_MIXER_SEMANTICS
@@@ -385,7 -388,10 +389,10 @@@ struct es1370_state 
                unsigned char obuf[MIDIOUTBUF];
        } midi;
  
+ #ifdef SUPPORT_JOYSTICK
        struct gameport *gameport;
+ #endif
        struct semaphore sem;
  };
  
@@@ -2554,10 -2560,55 +2561,55 @@@ static struct initvol 
        { SOUND_MIXER_WRITE_OGAIN, 0x4040 }
  };
  
+ #ifdef SUPPORT_JOYSTICK
+ static int __devinit es1370_register_gameport(struct es1370_state *s)
+ {
+       struct gameport *gp;
+       if (!request_region(0x200, JOY_EXTENT, "es1370")) {
+               printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
+               return -EBUSY;
+       }
+       s->gameport = gp = gameport_allocate_port();
+       if (!gp) {
+               printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
+               release_region(0x200, JOY_EXTENT);
+               return -ENOMEM;
+       }
+       gameport_set_name(gp, "ESS1370");
+       gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+       gp->dev.parent = &s->dev->dev;
+       gp->io = 0x200;
+       s->ctrl |= CTRL_JYSTK_EN;
+       outl(s->ctrl, s->io + ES1370_REG_CONTROL);
+       gameport_register_port(gp);
+       return 0;
+ }
+ static inline void es1370_unregister_gameport(struct es1370_state *s)
+ {
+       if (s->gameport) {
+               int gpio = s->gameport->io;
+               gameport_unregister_port(s->gameport);
+               release_region(gpio, JOY_EXTENT);
+       }
+ }
+ #else
+ static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; }
+ static inline void es1370_unregister_gameport(struct es1370_state *s) { }
+ #endif /* SUPPORT_JOYSTICK */
  static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
  {
        struct es1370_state *s;
-       struct gameport *gp = NULL;
        mm_segment_t fs;
        int i, val, ret;
  
                return -ENODEV;
        if (pcidev->irq == 0) 
                return -ENODEV;
 -      i = pci_set_dma_mask(pcidev, 0xffffffff);
 +      i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
        if (i) {
                printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n");
                return i;
        /* note: setting CTRL_SERR_DIS is reported to break
         * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
        s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
-       if (!request_region(0x200, JOY_EXTENT, "es1370")) {
-               printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
-       } else if (!(s->gameport = gp = gameport_allocate_port())) {
-               printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
-               release_region(0x200, JOY_EXTENT);
-       } else {
-               gameport_set_name(gp, "ESS1370");
-               gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
-               gp->dev.parent = &s->dev->dev;
-               gp->io = 0x200;
-               s->ctrl |= CTRL_JYSTK_EN;
-       }
        if (lineout[devindex])
                s->ctrl |= CTRL_XCTL0;
        if (micbias[devindex])
                s->ctrl |= CTRL_XCTL1;
        s->sctrl = 0;
-       printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
-              KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
-              s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
-              (s->ctrl & CTRL_XCTL0) ? "out" : "in",
-                      (s->ctrl & CTRL_XCTL1) ? "1" : "0");
+       printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n",
+              s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in",
+              (s->ctrl & CTRL_XCTL1) ? "1" : "0");
        /* register devices */
        if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) {
                ret = s->dev_audio;
        }
        set_fs(fs);
  
-       /* register gameport */
-       if (gp)
-               gameport_register_port(gp);
+       es1370_register_gameport(s);
  
        /* store it in the driver field */
        pci_set_drvdata(pcidev, s);
   err_dev1:
        printk(KERN_ERR "es1370: cannot register misc device\n");
        free_irq(s->irq, s);
-       if (s->gameport) {
-               release_region(s->gameport->io, JOY_EXTENT);
-               gameport_free_port(s->gameport);
-       }
   err_irq:
        release_region(s->io, ES1370_EXTENT);
   err_region:
@@@ -2719,11 -2750,7 +2751,7 @@@ static void __devexit es1370_remove(str
        outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
        synchronize_irq(s->irq);
        free_irq(s->irq, s);
-       if (s->gameport) {
-               int gpio = s->gameport->io;
-               gameport_unregister_port(s->gameport);
-               release_region(gpio, JOY_EXTENT);
-       }
+       es1370_unregister_gameport(s);
        release_region(s->io, ES1370_EXTENT);
        unregister_sound_dsp(s->dev_audio);
        unregister_sound_mixer(s->dev_mixer);
diff --combined sound/oss/es1371.c
  #include <linux/ac97_codec.h>
  #include <linux/gameport.h>
  #include <linux/wait.h>
 +#include <linux/dma-mapping.h>
  
  #include <asm/io.h>
  #include <asm/page.h>
  #include <asm/uaccess.h>
  
+ #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+ #define SUPPORT_JOYSTICK
+ #endif
  /* --------------------------------------------------------------------- */
  
  #undef OSS_DOCUMENTED_MIXER_SEMANTICS
@@@ -454,7 -457,10 +458,10 @@@ struct es1371_state 
                unsigned char obuf[MIDIOUTBUF];
        } midi;
  
+ #ifdef SUPPORT_JOYSTICK
        struct gameport *gameport;
+ #endif
        struct semaphore sem;
  };
  
@@@ -2787,12 -2793,63 +2794,63 @@@ static struc
        { PCI_ANY_ID, PCI_ANY_ID }
  };
  
+ #ifdef SUPPORT_JOYSTICK
+ static int __devinit es1371_register_gameport(struct es1371_state *s)
+ {
+       struct gameport *gp;
+       int gpio;
+       for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
+               if (request_region(gpio, JOY_EXTENT, "es1371"))
+                       break;
+       if (gpio < 0x200) {
+               printk(KERN_ERR PFX "no free joystick address found\n");
+               return -EBUSY;
+       }
+       s->gameport = gp = gameport_allocate_port();
+       if (!gp) {
+               printk(KERN_ERR PFX "can not allocate memory for gameport\n");
+               release_region(gpio, JOY_EXTENT);
+               return -ENOMEM;
+       }
+       gameport_set_name(gp, "ESS1371 Gameport");
+       gameport_set_phys(gp, "isa%04x/gameport0", gpio);
+       gp->dev.parent = &s->dev->dev;
+       gp->io = gpio;
+       s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+       outl(s->ctrl, s->io + ES1371_REG_CONTROL);
+       gameport_register_port(gp);
+       return 0;
+ }
+ static inline void es1371_unregister_gameport(struct es1371_state *s)
+ {
+       if (s->gameport) {
+               int gpio = s->gameport->io;
+               gameport_unregister_port(s->gameport);
+               release_region(gpio, JOY_EXTENT);
+       }
+ }
+ #else
+ static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; }
+ static inline void es1371_unregister_gameport(struct es1371_state *s) { }
+ #endif /* SUPPORT_JOYSTICK */
  static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
  {
        struct es1371_state *s;
-       struct gameport *gp;
        mm_segment_t fs;
-       int i, gpio, val, res = -1;
+       int i, val, res = -1;
        int idx;
        unsigned long tmo;
        signed long tmo2;
                return -ENODEV;
        if (pcidev->irq == 0) 
                return -ENODEV;
 -      i = pci_set_dma_mask(pcidev, 0xffffffff);
 +      i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
        if (i) {
                printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
                return i;
                }
        }
  
-       for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
-               if (request_region(gpio, JOY_EXTENT, "es1371"))
-                       break;
-       if (gpio < 0x200) {
-               printk(KERN_ERR PFX "no free joystick address found\n");
-       } else if (!(s->gameport = gp = gameport_allocate_port())) {
-               printk(KERN_ERR PFX "can not allocate memory for gameport\n");
-               release_region(gpio, JOY_EXTENT);
-       } else {
-               gameport_set_name(gp, "ESS1371 Gameport");
-               gameport_set_phys(gp, "isa%04x/gameport0", gpio);
-               gp->dev.parent = &s->dev->dev;
-               gp->io = gpio;
-               s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-       }
        s->sctrl = 0;
        cssr = 0;
        s->spdif_volume = -1;
        /* turn on S/PDIF output driver if requested */
        outl(cssr, s->io+ES1371_REG_STATUS);
  
-       /* register gameport */
-       if (s->gameport)
-               gameport_register_port(s->gameport);
+       es1371_register_gameport(s);
  
        /* store it in the driver field */
        pci_set_drvdata(pcidev, s);
        /* increment devindex */
        if (devindex < NR_DEVICE-1)
                devindex++;
-               return 0;
+       return 0;
  
   err_gp:
-       if (s->gameport) {
-               release_region(s->gameport->io, JOY_EXTENT);
-               gameport_free_port(s->gameport);
-       }
  #ifdef ES1371_DEBUG
        if (s->ps)
                remove_proc_entry("es1371", NULL);
@@@ -3025,11 -3059,7 +3060,7 @@@ static void __devexit es1371_remove(str
        outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
        synchronize_irq(s->irq);
        free_irq(s->irq, s);
-       if (s->gameport) {
-               int gpio = s->gameport->io;
-               gameport_unregister_port(s->gameport);
-               release_region(gpio, JOY_EXTENT);
-       }
+       es1371_unregister_gameport(s);
        release_region(s->io, ES1371_EXTENT);
        unregister_sound_dsp(s->dev_audio);
        unregister_sound_mixer(s->codec->dev_mixer);
diff --combined sound/oss/esssolo1.c
  #include <linux/smp_lock.h>
  #include <linux/gameport.h>
  #include <linux/wait.h>
 +#include <linux/dma-mapping.h>
  
  #include <asm/io.h>
  #include <asm/page.h>
  
  #define FMODE_DMFM 0x10
  
+ #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+ #define SUPPORT_JOYSTICK 1
+ #endif
  static struct pci_driver solo1_driver;
  
  /* --------------------------------------------------------------------- */
@@@ -227,7 -230,9 +231,9 @@@ struct solo1_state 
                unsigned char obuf[MIDIOUTBUF];
        } midi;
  
+ #if SUPPORT_JOYSTICK
        struct gameport *gameport;
+ #endif
  };
  
  /* --------------------------------------------------------------------- */
@@@ -2281,6 -2286,7 +2287,7 @@@ solo1_resume(struct pci_dev *pci_dev) 
        return 0;
  }
  
+ #ifdef SUPPORT_JOYSTICK
  static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port)
  {
        struct gameport *gp;
        return 0;
  }
  
+ static inline void solo1_unregister_gameport(struct solo1_state *s)
+ {
+       if (s->gameport) {
+               int gpio = s->gameport->io;
+               gameport_unregister_port(s->gameport);
+               release_region(gpio, GAMEPORT_EXTENT);
+       }
+ }
+ #else
+ static inline int solo1_register_gameport(struct solo1_state *s, int io_port) { return -ENOSYS; }
+ static inline void solo1_unregister_gameport(struct solo1_state *s) { }
+ #endif /* SUPPORT_JOYSTICK */
  static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
  {
        struct solo1_state *s;
         * to 24 bits first, then 32 bits (playback only) if that fails.
         */
        if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
 -          pci_set_dma_mask(pcidev, 0xffffffff)) {
 +          pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
                printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
                return -ENODEV;
        }
@@@ -2438,11 -2457,7 +2458,7 @@@ static void __devexit solo1_remove(stru
        synchronize_irq(s->irq);
        pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */
        free_irq(s->irq, s);
-       if (s->gameport) {
-               int gpio = s->gameport->io;
-               gameport_unregister_port(s->gameport);
-               release_region(gpio, GAMEPORT_EXTENT);
-       }
+       solo1_unregister_gameport(s);
        release_region(s->iobase, IOBASE_EXTENT);
        release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
        release_region(s->ddmabase, DDMABASE_EXTENT);
diff --combined sound/pci/cs4281.c
@@@ -206,10 -206,7 +206,10 @@@ MODULE_PARM_DESC(dual_codec, "Secondar
  
  #define BA0_PMCS              0x0344  /* Power Management Control/Status */
  #define BA0_CWPR              0x03e0  /* Configuration Write Protect */
 +
  #define BA0_EPPMC             0x03e4  /* Extended PCI Power Management Control */
 +#define BA0_EPPMC_FPDN                (1<<14) /* Full Power DowN */
 +
  #define BA0_GPIOR             0x03e8  /* GPIO Pin Interface Register */
  
  #define BA0_SPMC              0x03ec  /* Serial Port Power Management Control (& ASDIN2 enable) */
@@@ -1338,11 -1335,6 +1338,6 @@@ static inline int snd_cs4281_create_gam
  static inline void snd_cs4281_free_gameport(cs4281_t *chip) { }
  #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
  
- /*
-  */
  static int snd_cs4281_free(cs4281_t *chip)
  {
        snd_cs4281_free_gameport(chip);
@@@ -1464,11 -1456,6 +1459,11 @@@ static int snd_cs4281_chip_init(cs4281_
        int timeout;
        int retry_count = 2;
  
 +      /* Having EPPMC.FPDN=1 prevent proper chip initialisation */
 +      tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC);
 +      if (tmp & BA0_EPPMC_FPDN)
 +              snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN);
 +
        __retry:
        tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
        if (tmp != BA0_CFLR_DEFAULT) {
@@@ -2132,7 -2119,7 +2127,7 @@@ static struct pci_driver driver = 
        
  static int __init alsa_card_cs4281_init(void)
  {
 -      return pci_module_init(&driver);
 +      return pci_register_driver(&driver);
  }
  
  static void __exit alsa_card_cs4281_exit(void)