]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more .32 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 9 Mar 2010 23:06:49 +0000 (15:06 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 9 Mar 2010 23:06:49 +0000 (15:06 -0800)
16 files changed:
queue-2.6.32/clocksource-fix-up-a-registration-irq-race-in-the-sh-drivers.patch [new file with mode: 0644]
queue-2.6.32/dvb-core-fix-dos-bug-in-ule-decapsulation-code-that-can-be-triggered-by-an-invalid-payload-pointer.patch [new file with mode: 0644]
queue-2.6.32/macintosh-hwmon-ams-fix-device-removal-sequence.patch [new file with mode: 0644]
queue-2.6.32/macintosh-therm_adt746x-fix-sysfs-attributes-lifetime.patch [new file with mode: 0644]
queue-2.6.32/oprofile-remove-tracing-build-dependency.patch [new file with mode: 0644]
queue-2.6.32/oprofile-x86-fix-msr-access-to-reserved-counters.patch [new file with mode: 0644]
queue-2.6.32/oprofile-x86-fix-perfctr-nmi-reservation-for-mulitplexing.patch [new file with mode: 0644]
queue-2.6.32/oprofile-x86-remove-node-check-in-amd-ibs-initialization.patch [new file with mode: 0644]
queue-2.6.32/oprofile-x86-use-kzalloc-instead-of-kmalloc.patch [new file with mode: 0644]
queue-2.6.32/pm-hibernate-fix-preallocating-of-memory.patch [new file with mode: 0644]
queue-2.6.32/qla1280-drop-host_lock-while-requesting-firmware.patch [new file with mode: 0644]
queue-2.6.32/series
queue-2.6.32/staging-hv-add-a-pci-device-table.patch [new file with mode: 0644]
queue-2.6.32/staging-hv-match-on-dmi-values-to-know-if-we-should-run.patch [new file with mode: 0644]
queue-2.6.32/staging-mimio-remove-the-mimio-driver.patch [new file with mode: 0644]
queue-2.6.32/v4l-dvb-13148-uvcvideo-handle-v4l2_ctrl_type_button-control-type-in-vidioc_queryctrl.patch [new file with mode: 0644]

diff --git a/queue-2.6.32/clocksource-fix-up-a-registration-irq-race-in-the-sh-drivers.patch b/queue-2.6.32/clocksource-fix-up-a-registration-irq-race-in-the-sh-drivers.patch
new file mode 100644 (file)
index 0000000..863cc86
--- /dev/null
@@ -0,0 +1,126 @@
+From da64c2a8dee66ca03f4f3e15d84be7bedf73db3d Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Thu, 25 Feb 2010 16:37:46 +0900
+Subject: clocksource: Fix up a registration/IRQ race in the sh drivers.
+
+From: Paul Mundt <lethal@linux-sh.org>
+
+commit da64c2a8dee66ca03f4f3e15d84be7bedf73db3d upstream.
+
+All of the SH clocksource drivers follow the scheme that the IRQ is setup
+prior to registering the clockevent. The interrupt handler in the
+clockevent cases looks to the event handler function pointer being filled
+in by the registration code, permitting us to get in to situations where
+asserted IRQs step in to the handler before registration has had a chance
+to complete and hitting a NULL pointer deref.
+
+In practice this is not an issue for most platforms, but some of them
+with fairly special loaders (or that are chain-loading from another
+kernel) may enter in to this situation. This fixes up the oops reported
+by Rafael on hp6xx.
+
+Reported-and-tested-by: Rafael Ignacio Zurita <rafaelignacio.zurita@gmail.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+--- a/drivers/clocksource/sh_cmt.c
++++ b/drivers/clocksource/sh_cmt.c
+@@ -603,18 +603,13 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
+       p->irqaction.handler = sh_cmt_interrupt;
+       p->irqaction.dev_id = p;
+       p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+-      ret = setup_irq(irq, &p->irqaction);
+-      if (ret) {
+-              pr_err("sh_cmt: failed to request irq %d\n", irq);
+-              goto err1;
+-      }
+       /* get hold of clock */
+       p->clk = clk_get(&p->pdev->dev, cfg->clk);
+       if (IS_ERR(p->clk)) {
+               pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
+               ret = PTR_ERR(p->clk);
+-              goto err2;
++              goto err1;
+       }
+       if (resource_size(res) == 6) {
+@@ -627,14 +622,25 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
+               p->clear_bits = ~0xc000;
+       }
+-      return sh_cmt_register(p, cfg->name,
+-                             cfg->clockevent_rating,
+-                             cfg->clocksource_rating);
+- err2:
+-      remove_irq(irq, &p->irqaction);
+- err1:
++      ret = sh_cmt_register(p, cfg->name,
++                            cfg->clockevent_rating,
++                            cfg->clocksource_rating);
++      if (ret) {
++              pr_err("sh_cmt: registration failed\n");
++              goto err1;
++      }
++
++      ret = setup_irq(irq, &p->irqaction);
++      if (ret) {
++              pr_err("sh_cmt: failed to request irq %d\n", irq);
++              goto err1;
++      }
++
++      return 0;
++
++err1:
+       iounmap(p->mapbase);
+- err0:
++err0:
+       return ret;
+ }
+diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
+index 973e714..4c8a759 100644
+--- a/drivers/clocksource/sh_mtu2.c
++++ b/drivers/clocksource/sh_mtu2.c
+@@ -221,15 +221,15 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
+       ced->cpumask = cpumask_of(0);
+       ced->set_mode = sh_mtu2_clock_event_mode;
++      pr_info("sh_mtu2: %s used for clock events\n", ced->name);
++      clockevents_register_device(ced);
++
+       ret = setup_irq(p->irqaction.irq, &p->irqaction);
+       if (ret) {
+               pr_err("sh_mtu2: failed to request irq %d\n",
+                      p->irqaction.irq);
+               return;
+       }
+-
+-      pr_info("sh_mtu2: %s used for clock events\n", ced->name);
+-      clockevents_register_device(ced);
+ }
+ static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name,
+diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
+index 93c2322..961f5b5 100644
+--- a/drivers/clocksource/sh_tmu.c
++++ b/drivers/clocksource/sh_tmu.c
+@@ -323,15 +323,15 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
+       ced->set_next_event = sh_tmu_clock_event_next;
+       ced->set_mode = sh_tmu_clock_event_mode;
++      pr_info("sh_tmu: %s used for clock events\n", ced->name);
++      clockevents_register_device(ced);
++
+       ret = setup_irq(p->irqaction.irq, &p->irqaction);
+       if (ret) {
+               pr_err("sh_tmu: failed to request irq %d\n",
+                      p->irqaction.irq);
+               return;
+       }
+-
+-      pr_info("sh_tmu: %s used for clock events\n", ced->name);
+-      clockevents_register_device(ced);
+ }
+ static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
diff --git a/queue-2.6.32/dvb-core-fix-dos-bug-in-ule-decapsulation-code-that-can-be-triggered-by-an-invalid-payload-pointer.patch b/queue-2.6.32/dvb-core-fix-dos-bug-in-ule-decapsulation-code-that-can-be-triggered-by-an-invalid-payload-pointer.patch
new file mode 100644 (file)
index 0000000..7bba6b2
--- /dev/null
@@ -0,0 +1,45 @@
+From 29e1fa3565a7951cc415c634eb2b78dbdbee151d Mon Sep 17 00:00:00 2001
+From: Ang Way Chuang <wcang79@gmail.com>
+Date: Thu, 25 Feb 2010 09:45:03 +0800
+Subject: dvb-core: Fix DoS bug in ULE decapsulation code that can be triggered by an invalid Payload Pointer
+
+From: Ang Way Chuang <wcang79@gmail.com>
+
+commit 29e1fa3565a7951cc415c634eb2b78dbdbee151d upstream.
+
+ULE (Unidirectional Lightweight Encapsulation RFC 4326) decapsulation
+has a bug that causes endless loop when Payload Pointer of MPEG2-TS
+frame is 182 or 183.  Anyone who sends malicious MPEG2-TS frame will
+cause the receiver of ULE SNDU to go into endless loop.
+
+This patch was generated and tested against linux-2.6.32.9 and should
+apply cleanly to linux-2.6.33 as well because there was only one typo
+fix to dvb_net.c since v2.6.32.
+
+This bug was brought to you by modern day Santa Claus who decided to
+shower the satellite dish at Keio University with heavy snow causing
+huge burst of errors.  We, receiver end, received Santa Claus's gift in
+the form of kernel bug.
+
+Care has been taken not to introduce more bug by fixing this bug, but
+please scrutinize the code for I always produces buggy code.
+
+Signed-off-by: Ang Way Chuang <wcang79@gmail.com>
+Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/dvb/dvb-core/dvb_net.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/dvb/dvb-core/dvb_net.c
++++ b/drivers/media/dvb/dvb-core/dvb_net.c
+@@ -504,6 +504,7 @@ static void dvb_net_ule( struct net_devi
+                                      "bytes left in TS.  Resyncing.\n", ts_remain);
+                               priv->ule_sndu_len = 0;
+                               priv->need_pusi = 1;
++                              ts += TS_SZ;
+                               continue;
+                       }
diff --git a/queue-2.6.32/macintosh-hwmon-ams-fix-device-removal-sequence.patch b/queue-2.6.32/macintosh-hwmon-ams-fix-device-removal-sequence.patch
new file mode 100644 (file)
index 0000000..8b7ea4d
--- /dev/null
@@ -0,0 +1,98 @@
+From 98ceb75c7c14eada76b0aa9f03a635a735cee3cb Mon Sep 17 00:00:00 2001
+From: Jean Delvare <khali@linux-fr.org>
+Date: Sun, 31 Jan 2010 04:03:23 +0000
+Subject: macintosh/hwmon/ams: Fix device removal sequence
+
+From: Jean Delvare <khali@linux-fr.org>
+
+commit 98ceb75c7c14eada76b0aa9f03a635a735cee3cb upstream.
+
+Some code that is in ams_exit() (the module exit code) should instead
+be called when the device (not module) is removed. It probably doesn't
+make much of a difference in the PMU case, but in the I2C case it does
+matter.
+
+I make no guarantee that my fix isn't racy, I'm not familiar enough
+with the ams driver code to tell for sure.
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Tested-by: Christian Kujau <lists@nerdbynature.de>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Stelian Pop <stelian@popies.net>
+Cc: Michael Hanselmann <linux-kernel@hansmi.ch>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/hwmon/ams/ams-core.c |   11 +++++++----
+ drivers/hwmon/ams/ams-i2c.c  |    2 ++
+ drivers/hwmon/ams/ams-pmu.c  |    2 ++
+ drivers/hwmon/ams/ams.h      |    1 +
+ 4 files changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/hwmon/ams/ams-core.c
++++ b/drivers/hwmon/ams/ams-core.c
+@@ -213,7 +213,7 @@ int __init ams_init(void)
+       return -ENODEV;
+ }
+-void ams_exit(void)
++void ams_sensor_detach(void)
+ {
+       /* Remove input device */
+       ams_input_exit();
+@@ -221,9 +221,6 @@ void ams_exit(void)
+       /* Remove attributes */
+       device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+-      /* Shut down implementation */
+-      ams_info.exit();
+-
+       /* Flush interrupt worker
+        *
+        * We do this after ams_info.exit(), because an interrupt might
+@@ -239,6 +236,12 @@ void ams_exit(void)
+       pmf_unregister_irq_client(&ams_freefall_client);
+ }
++static void __exit ams_exit(void)
++{
++      /* Shut down implementation */
++      ams_info.exit();
++}
++
+ MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
+ MODULE_DESCRIPTION("Apple Motion Sensor driver");
+ MODULE_LICENSE("GPL");
+--- a/drivers/hwmon/ams/ams-i2c.c
++++ b/drivers/hwmon/ams/ams-i2c.c
+@@ -238,6 +238,8 @@ static int ams_i2c_probe(struct i2c_clie
+ static int ams_i2c_remove(struct i2c_client *client)
+ {
+       if (ams_info.has_device) {
++              ams_sensor_detach();
++
+               /* Disable interrupts */
+               ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+--- a/drivers/hwmon/ams/ams-pmu.c
++++ b/drivers/hwmon/ams/ams-pmu.c
+@@ -133,6 +133,8 @@ static void ams_pmu_get_xyz(s8 *x, s8 *y
+ static void ams_pmu_exit(void)
+ {
++      ams_sensor_detach();
++
+       /* Disable interrupts */
+       ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+--- a/drivers/hwmon/ams/ams.h
++++ b/drivers/hwmon/ams/ams.h
+@@ -61,6 +61,7 @@ extern struct ams ams_info;
+ extern void ams_sensors(s8 *x, s8 *y, s8 *z);
+ extern int ams_sensor_attach(void);
++extern void ams_sensor_detach(void);
+ extern int ams_pmu_init(struct device_node *np);
+ extern int ams_i2c_init(struct device_node *np);
diff --git a/queue-2.6.32/macintosh-therm_adt746x-fix-sysfs-attributes-lifetime.patch b/queue-2.6.32/macintosh-therm_adt746x-fix-sysfs-attributes-lifetime.patch
new file mode 100644 (file)
index 0000000..dbf31d7
--- /dev/null
@@ -0,0 +1,120 @@
+From 33a470f6d5e1879c26f16f6b34dc09f82d44f6e9 Mon Sep 17 00:00:00 2001
+From: Jean Delvare <khali@linux-fr.org>
+Date: Sun, 31 Jan 2010 04:00:30 +0000
+Subject: macintosh/therm_adt746x: Fix sysfs attributes lifetime
+
+From: Jean Delvare <khali@linux-fr.org>
+
+commit 33a470f6d5e1879c26f16f6b34dc09f82d44f6e9 upstream.
+
+Looking at drivers/macintosh/therm_adt746x.c, the sysfs files are
+created in thermostat_init() and removed in thermostat_exit(), which
+are the driver's init and exit functions. These files are backed-up by
+a per-device structure, so it looks like the wrong thing to do: the
+sysfs files have a lifetime longer than the data structure that is
+backing it up.
+
+I think that sysfs files creation should be moved to the end of
+probe_thermostat() and sysfs files removal should be moved to the
+beginning of remove_thermostat().
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Tested-by: Christian Kujau <lists@nerdbynature.de>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Colin Leroy <colin@colino.net>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/macintosh/therm_adt746x.c |   34 ++++++++++++++++++++++++----------
+ 1 file changed, 24 insertions(+), 10 deletions(-)
+
+--- a/drivers/macintosh/therm_adt746x.c
++++ b/drivers/macintosh/therm_adt746x.c
+@@ -90,6 +90,8 @@ static struct task_struct *thread_therm
+ static void write_both_fan_speed(struct thermostat *th, int speed);
+ static void write_fan_speed(struct thermostat *th, int speed, int fan);
++static void thermostat_create_files(void);
++static void thermostat_remove_files(void);
+ static int
+ write_reg(struct thermostat* th, int reg, u8 data)
+@@ -161,6 +163,8 @@ remove_thermostat(struct i2c_client *cli
+       struct thermostat *th = i2c_get_clientdata(client);
+       int i;
+       
++      thermostat_remove_files();
++
+       if (thread_therm != NULL) {
+               kthread_stop(thread_therm);
+       }
+@@ -449,6 +453,8 @@ static int probe_thermostat(struct i2c_c
+               return -ENOMEM;
+       }
++      thermostat_create_files();
++
+       return 0;
+ }
+@@ -566,7 +572,6 @@ thermostat_init(void)
+       struct device_node* np;
+       const u32 *prop;
+       int i = 0, offset = 0;
+-      int err;
+       np = of_find_node_by_name(NULL, "fan");
+       if (!np)
+@@ -633,6 +638,17 @@ thermostat_init(void)
+               return -ENODEV;
+       }
++#ifndef CONFIG_I2C_POWERMAC
++      request_module("i2c-powermac");
++#endif
++
++      return i2c_add_driver(&thermostat_driver);
++}
++
++static void thermostat_create_files(void)
++{
++      int err;
++
+       err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature);
+       err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature);
+       err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit);
+@@ -647,16 +663,9 @@ thermostat_init(void)
+       if (err)
+               printk(KERN_WARNING
+                       "Failed to create tempertaure attribute file(s).\n");
+-
+-#ifndef CONFIG_I2C_POWERMAC
+-      request_module("i2c-powermac");
+-#endif
+-
+-      return i2c_add_driver(&thermostat_driver);
+ }
+-static void __exit
+-thermostat_exit(void)
++static void thermostat_remove_files(void)
+ {
+       if (of_dev) {
+               device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature);
+@@ -673,9 +682,14 @@ thermostat_exit(void)
+                       device_remove_file(&of_dev->dev,
+                                          &dev_attr_sensor2_fan_speed);
+-              of_device_unregister(of_dev);
+       }
++}
++
++static void __exit
++thermostat_exit(void)
++{
+       i2c_del_driver(&thermostat_driver);
++      of_device_unregister(of_dev);
+ }
+ module_init(thermostat_init);
diff --git a/queue-2.6.32/oprofile-remove-tracing-build-dependency.patch b/queue-2.6.32/oprofile-remove-tracing-build-dependency.patch
new file mode 100644 (file)
index 0000000..fe0ae3b
--- /dev/null
@@ -0,0 +1,39 @@
+From 18b4a4d59e97e7ff13ee84b5bec79f3fc70a9f0a Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Wed, 10 Feb 2010 10:03:34 +0100
+Subject: oprofile: remove tracing build dependency
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit 18b4a4d59e97e7ff13ee84b5bec79f3fc70a9f0a upstream.
+
+The commit
+
+ 1155de4 ring-buffer: Make it generally available
+
+already made ring-buffer available without the TRACING option
+enabled. This patch removes the TRACING dependency from oprofile.
+
+Fixes also oprofile configuration on ia64.
+
+The patch also applies to the 2.6.32-stable kernel.
+
+Reported-by: Tony Jones <tonyj@suse.de>
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/Kconfig |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -6,8 +6,6 @@ config OPROFILE
+       tristate "OProfile system profiling (EXPERIMENTAL)"
+       depends on PROFILING
+       depends on HAVE_OPROFILE
+-      depends on TRACING_SUPPORT
+-      select TRACING
+       select RING_BUFFER
+       select RING_BUFFER_ALLOW_SWAP
+       help
diff --git a/queue-2.6.32/oprofile-x86-fix-msr-access-to-reserved-counters.patch b/queue-2.6.32/oprofile-x86-fix-msr-access-to-reserved-counters.patch
new file mode 100644 (file)
index 0000000..4886eb4
--- /dev/null
@@ -0,0 +1,52 @@
+From cfc9c0b450176a077205ef39092f0dc1a04e020a Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Fri, 26 Feb 2010 13:45:24 +0100
+Subject: oprofile/x86: fix msr access to reserved counters
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit cfc9c0b450176a077205ef39092f0dc1a04e020a upstream.
+
+During switching virtual counters there is access to perfctr msrs. If
+the counter is not available this fails due to an invalid
+address. This patch fixes this.
+
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/oprofile/op_model_amd.c |    9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/oprofile/op_model_amd.c
++++ b/arch/x86/oprofile/op_model_amd.c
+@@ -85,7 +85,7 @@ static void op_mux_switch_ctrl(struct op
+       /* enable active counters */
+       for (i = 0; i < NUM_COUNTERS; ++i) {
+               int virt = op_x86_phys_to_virt(i);
+-              if (!counter_config[virt].enabled)
++              if (!reset_value[virt])
+                       continue;
+               rdmsrl(msrs->controls[i].addr, val);
+               val &= model->reserved;
+@@ -121,7 +121,8 @@ static void op_amd_setup_ctrs(struct op_
+       /* setup reset_value */
+       for (i = 0; i < NUM_VIRT_COUNTERS; ++i) {
+-              if (counter_config[i].enabled)
++              if (counter_config[i].enabled
++                  && msrs->counters[op_x86_virt_to_phys(i)].addr)
+                       reset_value[i] = counter_config[i].count;
+               else
+                       reset_value[i] = 0;
+@@ -146,9 +147,7 @@ static void op_amd_setup_ctrs(struct op_
+       /* enable active counters */
+       for (i = 0; i < NUM_COUNTERS; ++i) {
+               int virt = op_x86_phys_to_virt(i);
+-              if (!counter_config[virt].enabled)
+-                      continue;
+-              if (!msrs->counters[i].addr)
++              if (!reset_value[virt])
+                       continue;
+               /* setup counter registers */
diff --git a/queue-2.6.32/oprofile-x86-fix-perfctr-nmi-reservation-for-mulitplexing.patch b/queue-2.6.32/oprofile-x86-fix-perfctr-nmi-reservation-for-mulitplexing.patch
new file mode 100644 (file)
index 0000000..5e192bc
--- /dev/null
@@ -0,0 +1,106 @@
+From 68dc819ce829f7e7977a56524e710473bdb55115 Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Thu, 25 Feb 2010 19:16:46 +0100
+Subject: oprofile/x86: fix perfctr nmi reservation for mulitplexing
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit 68dc819ce829f7e7977a56524e710473bdb55115 upstream.
+
+Multiple virtual counters share one physical counter. The reservation
+of virtual counters fails due to duplicate allocation of the same
+counter. The counters are already reserved. Thus, virtual counter
+reservation may removed at all. This also makes the code easier.
+
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/oprofile/nmi_int.c      |   11 ++++++-----
+ arch/x86/oprofile/op_model_amd.c |   19 -------------------
+ 2 files changed, 6 insertions(+), 24 deletions(-)
+
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -179,7 +179,6 @@ static void nmi_cpu_setup_mux(int cpu, s
+               if (counter_config[i].enabled) {
+                       multiplex[i].saved = -(u64)counter_config[i].count;
+               } else {
+-                      multiplex[i].addr  = 0;
+                       multiplex[i].saved = 0;
+               }
+       }
+@@ -189,25 +188,27 @@ static void nmi_cpu_setup_mux(int cpu, s
+ static void nmi_cpu_save_mpx_registers(struct op_msrs *msrs)
+ {
++      struct op_msr *counters = msrs->counters;
+       struct op_msr *multiplex = msrs->multiplex;
+       int i;
+       for (i = 0; i < model->num_counters; ++i) {
+               int virt = op_x86_phys_to_virt(i);
+-              if (multiplex[virt].addr)
+-                      rdmsrl(multiplex[virt].addr, multiplex[virt].saved);
++              if (counters[i].addr)
++                      rdmsrl(counters[i].addr, multiplex[virt].saved);
+       }
+ }
+ static void nmi_cpu_restore_mpx_registers(struct op_msrs *msrs)
+ {
++      struct op_msr *counters = msrs->counters;
+       struct op_msr *multiplex = msrs->multiplex;
+       int i;
+       for (i = 0; i < model->num_counters; ++i) {
+               int virt = op_x86_phys_to_virt(i);
+-              if (multiplex[virt].addr)
+-                      wrmsrl(multiplex[virt].addr, multiplex[virt].saved);
++              if (counters[i].addr)
++                      wrmsrl(counters[i].addr, multiplex[virt].saved);
+       }
+ }
+--- a/arch/x86/oprofile/op_model_amd.c
++++ b/arch/x86/oprofile/op_model_amd.c
+@@ -76,19 +76,6 @@ static struct op_ibs_config ibs_config;
+ #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
+-static void op_mux_fill_in_addresses(struct op_msrs * const msrs)
+-{
+-      int i;
+-
+-      for (i = 0; i < NUM_VIRT_COUNTERS; i++) {
+-              int hw_counter = op_x86_virt_to_phys(i);
+-              if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+-                      msrs->multiplex[i].addr = MSR_K7_PERFCTR0 + hw_counter;
+-              else
+-                      msrs->multiplex[i].addr = 0;
+-      }
+-}
+-
+ static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
+                              struct op_msrs const * const msrs)
+ {
+@@ -107,10 +94,6 @@ static void op_mux_switch_ctrl(struct op
+       }
+ }
+-#else
+-
+-static inline void op_mux_fill_in_addresses(struct op_msrs * const msrs) { }
+-
+ #endif
+ /* functions for op_amd_spec */
+@@ -132,8 +115,6 @@ static void op_amd_fill_in_addresses(str
+               else
+                       msrs->controls[i].addr = 0;
+       }
+-
+-      op_mux_fill_in_addresses(msrs);
+ }
+ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
diff --git a/queue-2.6.32/oprofile-x86-remove-node-check-in-amd-ibs-initialization.patch b/queue-2.6.32/oprofile-x86-remove-node-check-in-amd-ibs-initialization.patch
new file mode 100644 (file)
index 0000000..cf97a1d
--- /dev/null
@@ -0,0 +1,42 @@
+From 89baaaa98a10cad5cc8516c7208b02d9fc711890 Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Thu, 28 Jan 2010 16:50:45 +0100
+Subject: oprofile/x86: remove node check in AMD IBS initialization
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit 89baaaa98a10cad5cc8516c7208b02d9fc711890 upstream.
+
+Standard AMD systems have the same number of nodes as there are
+northbridge devices. However, there may kernel configurations
+(especially for 32 bit) or system setups exist, where the node number
+is different or it can not be detected properly. Thus the check is not
+reliable and may fail though IBS setup was fine. For this reason it is
+better to remove the check.
+
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/oprofile/op_model_amd.c |   10 ----------
+ 1 file changed, 10 deletions(-)
+
+--- a/arch/x86/oprofile/op_model_amd.c
++++ b/arch/x86/oprofile/op_model_amd.c
+@@ -386,16 +386,6 @@ static int init_ibs_nmi(void)
+               return 1;
+       }
+-#ifdef CONFIG_NUMA
+-      /* Sanity check */
+-      /* Works only for 64bit with proper numa implementation. */
+-      if (nodes != num_possible_nodes()) {
+-              printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, "
+-                      "found: %d, expected %d",
+-                      nodes, num_possible_nodes());
+-              return 1;
+-      }
+-#endif
+       return 0;
+ }
diff --git a/queue-2.6.32/oprofile-x86-use-kzalloc-instead-of-kmalloc.patch b/queue-2.6.32/oprofile-x86-use-kzalloc-instead-of-kmalloc.patch
new file mode 100644 (file)
index 0000000..caaffe1
--- /dev/null
@@ -0,0 +1,104 @@
+From c17c8fbf349482e89b57d1b800e83e9f4cf40c47 Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Thu, 25 Feb 2010 20:20:25 +0100
+Subject: oprofile/x86: use kzalloc() instead of kmalloc()
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit c17c8fbf349482e89b57d1b800e83e9f4cf40c47 upstream.
+
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/oprofile/nmi_int.c       |    6 +++---
+ arch/x86/oprofile/op_model_amd.c  |    4 ----
+ arch/x86/oprofile/op_model_p4.c   |    6 ------
+ arch/x86/oprofile/op_model_ppro.c |    6 +-----
+ 4 files changed, 4 insertions(+), 18 deletions(-)
+
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -159,7 +159,7 @@ static int nmi_setup_mux(void)
+       for_each_possible_cpu(i) {
+               per_cpu(cpu_msrs, i).multiplex =
+-                      kmalloc(multiplex_size, GFP_KERNEL);
++                      kzalloc(multiplex_size, GFP_KERNEL);
+               if (!per_cpu(cpu_msrs, i).multiplex)
+                       return 0;
+       }
+@@ -304,11 +304,11 @@ static int allocate_msrs(void)
+       int i;
+       for_each_possible_cpu(i) {
+-              per_cpu(cpu_msrs, i).counters = kmalloc(counters_size,
++              per_cpu(cpu_msrs, i).counters = kzalloc(counters_size,
+                                                       GFP_KERNEL);
+               if (!per_cpu(cpu_msrs, i).counters)
+                       return 0;
+-              per_cpu(cpu_msrs, i).controls = kmalloc(controls_size,
++              per_cpu(cpu_msrs, i).controls = kzalloc(controls_size,
+                                                       GFP_KERNEL);
+               if (!per_cpu(cpu_msrs, i).controls)
+                       return 0;
+--- a/arch/x86/oprofile/op_model_amd.c
++++ b/arch/x86/oprofile/op_model_amd.c
+@@ -105,15 +105,11 @@ static void op_amd_fill_in_addresses(str
+       for (i = 0; i < NUM_COUNTERS; i++) {
+               if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+                       msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+-              else
+-                      msrs->counters[i].addr = 0;
+       }
+       for (i = 0; i < NUM_CONTROLS; i++) {
+               if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
+                       msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+-              else
+-                      msrs->controls[i].addr = 0;
+       }
+ }
+--- a/arch/x86/oprofile/op_model_p4.c
++++ b/arch/x86/oprofile/op_model_p4.c
+@@ -394,12 +394,6 @@ static void p4_fill_in_addresses(struct
+       setup_num_counters();
+       stag = get_stagger();
+-      /* initialize some registers */
+-      for (i = 0; i < num_counters; ++i)
+-              msrs->counters[i].addr = 0;
+-      for (i = 0; i < num_controls; ++i)
+-              msrs->controls[i].addr = 0;
+-
+       /* the counter & cccr registers we pay attention to */
+       for (i = 0; i < num_counters; ++i) {
+               addr = p4_counters[VIRT_CTR(stag, i)].counter_address;
+--- a/arch/x86/oprofile/op_model_ppro.c
++++ b/arch/x86/oprofile/op_model_ppro.c
+@@ -37,15 +37,11 @@ static void ppro_fill_in_addresses(struc
+       for (i = 0; i < num_counters; i++) {
+               if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+                       msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+-              else
+-                      msrs->counters[i].addr = 0;
+       }
+       for (i = 0; i < num_counters; i++) {
+               if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
+                       msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+-              else
+-                      msrs->controls[i].addr = 0;
+       }
+ }
+@@ -57,7 +53,7 @@ static void ppro_setup_ctrs(struct op_x8
+       int i;
+       if (!reset_value) {
+-              reset_value = kmalloc(sizeof(reset_value[0]) * num_counters,
++              reset_value = kzalloc(sizeof(reset_value[0]) * num_counters,
+                                       GFP_ATOMIC);
+               if (!reset_value)
+                       return;
diff --git a/queue-2.6.32/pm-hibernate-fix-preallocating-of-memory.patch b/queue-2.6.32/pm-hibernate-fix-preallocating-of-memory.patch
new file mode 100644 (file)
index 0000000..55728e4
--- /dev/null
@@ -0,0 +1,42 @@
+From a9c9b4429df437982d2fbfab1f4b46b01329e9ed Mon Sep 17 00:00:00 2001
+From: Rafael J. Wysocki <rjw@sisk.pl>
+Date: Thu, 25 Feb 2010 22:32:37 +0100
+Subject: PM / Hibernate: Fix preallocating of memory
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit a9c9b4429df437982d2fbfab1f4b46b01329e9ed upstream.
+
+The hibernate memory preallocation code allocates memory to push some
+user space data out of physical RAM, so that the hibernation image is
+not too large.  It allocates more memory than necessary for creating
+the image, so it has to release some pages to make room for
+allocations made while suspending devices and disabling nonboot CPUs,
+or the system will hang due to the lack of free pages to allocate
+from.  Unfortunately, the function used for freeing these pages,
+free_unnecessary_pages(), contains a bug that prevents it from doing
+the job on all systems without highmem.
+
+Fix this problem, which is a regression from the 2.6.30 kernel, by
+using the right condition for the termination of the loop in
+free_unnecessary_pages().
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Reported-and-tested-by: Alan Jenkins <sourcejedi.lkml@googlemail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/power/snapshot.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -1181,7 +1181,7 @@ static void free_unnecessary_pages(void)
+       memory_bm_position_reset(&copy_bm);
+-      while (to_free_normal > 0 && to_free_highmem > 0) {
++      while (to_free_normal > 0 || to_free_highmem > 0) {
+               unsigned long pfn = memory_bm_next_pfn(&copy_bm);
+               struct page *page = pfn_to_page(pfn);
diff --git a/queue-2.6.32/qla1280-drop-host_lock-while-requesting-firmware.patch b/queue-2.6.32/qla1280-drop-host_lock-while-requesting-firmware.patch
new file mode 100644 (file)
index 0000000..c64c847
--- /dev/null
@@ -0,0 +1,44 @@
+From 2cec802980727f1daa46d8c31b411e083d49d7a2 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 23 Jan 2010 18:40:29 +0000
+Subject: SCSI: qla1280: Drop host_lock while requesting firmware
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit 2cec802980727f1daa46d8c31b411e083d49d7a2 upstream.
+
+request_firmware() may sleep and it appears to be safe to release the
+spinlock here.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/qla1280.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/scsi/qla1280.c
++++ b/drivers/scsi/qla1280.c
+@@ -1640,8 +1640,10 @@ qla1280_load_firmware_pio(struct scsi_ql
+       uint16_t mb[MAILBOX_REGISTER_COUNT], i;
+       int err;
++      spin_unlock_irq(ha->host->host_lock);
+       err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
+                              &ha->pdev->dev);
++      spin_lock_irq(ha->host->host_lock);
+       if (err) {
+               printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+                      ql1280_board_tbl[ha->devnum].fwname, err);
+@@ -1699,8 +1701,10 @@ qla1280_load_firmware_dma(struct scsi_ql
+               return -ENOMEM;
+ #endif
++      spin_unlock_irq(ha->host->host_lock);
+       err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
+                              &ha->pdev->dev);
++      spin_lock_irq(ha->host->host_lock);
+       if (err) {
+               printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+                      ql1280_board_tbl[ha->devnum].fwname, err);
index c5762bd96ae07b0070500b4f77d602d9c69e861f..118f7f3637d45709064db7594263ddedfc5029af 100644 (file)
@@ -56,3 +56,18 @@ rndis_wlan-handle-nl80211_authtype_automatic.patch
 rndis_wlan-fix-buffer-overflow-in-rndis_query_oid.patch
 rndis_wlan-disable-stall-workaround.patch
 net-via-rhine-fix-scheduling-while-atomic-bugs.patch
+clocksource-fix-up-a-registration-irq-race-in-the-sh-drivers.patch
+qla1280-drop-host_lock-while-requesting-firmware.patch
+staging-hv-add-a-pci-device-table.patch
+staging-hv-match-on-dmi-values-to-know-if-we-should-run.patch
+staging-mimio-remove-the-mimio-driver.patch
+dvb-core-fix-dos-bug-in-ule-decapsulation-code-that-can-be-triggered-by-an-invalid-payload-pointer.patch
+v4l-dvb-13148-uvcvideo-handle-v4l2_ctrl_type_button-control-type-in-vidioc_queryctrl.patch
+pm-hibernate-fix-preallocating-of-memory.patch
+macintosh-therm_adt746x-fix-sysfs-attributes-lifetime.patch
+macintosh-hwmon-ams-fix-device-removal-sequence.patch
+oprofile-x86-fix-perfctr-nmi-reservation-for-mulitplexing.patch
+oprofile-remove-tracing-build-dependency.patch
+oprofile-x86-remove-node-check-in-amd-ibs-initialization.patch
+oprofile-x86-use-kzalloc-instead-of-kmalloc.patch
+oprofile-x86-fix-msr-access-to-reserved-counters.patch
diff --git a/queue-2.6.32/staging-hv-add-a-pci-device-table.patch b/queue-2.6.32/staging-hv-add-a-pci-device-table.patch
new file mode 100644 (file)
index 0000000..a4389c1
--- /dev/null
@@ -0,0 +1,55 @@
+From 9a775dbd4e8c87b7d35549183145321c7205404e Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Thu, 25 Feb 2010 16:42:10 -0800
+Subject: Staging: hv: add a pci device table
+
+From: Greg Kroah-Hartman <gregkh@suse.de>
+
+commit 9a775dbd4e8c87b7d35549183145321c7205404e upstream.
+
+This allows the HV core to be properly found and autoloaded
+by the system tools.
+
+It uses the Microsoft virtual VGA device to trigger this.
+
+Cc: Haiyang Zhang <haiyangz@microsoft.com>
+Cc: Hank Janssen <hjanssen@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/hv/vmbus_drv.c |   17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -24,6 +24,7 @@
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+ #include <linux/sysctl.h>
++#include <linux/pci.h>
+ #include "osd.h"
+ #include "logging.h"
+ #include "vmbus.h"
+@@ -973,6 +974,22 @@ static void __exit vmbus_exit(void)
+       return;
+ }
++/*
++ * We use a PCI table to determine if we should autoload this driver  This is
++ * needed by distro tools to determine if the hyperv drivers should be
++ * installed and/or configured.  We don't do anything else with the table, but
++ * it needs to be present.
++ *
++ * We might consider triggering off of DMI table info as well, as that does
++ * decribe the virtual machine being run on, but not all configuration tools
++ * seem to be able to handle DMI device ids properly.
++ */
++const static struct pci_device_id microsoft_hv_pci_table[] = {
++      { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
++      { 0 }
++};
++MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
++
+ MODULE_LICENSE("GPL");
+ module_param(vmbus_irq, int, S_IRUGO);
+ module_param(vmbus_loglevel, int, S_IRUGO);
diff --git a/queue-2.6.32/staging-hv-match-on-dmi-values-to-know-if-we-should-run.patch b/queue-2.6.32/staging-hv-match-on-dmi-values-to-know-if-we-should-run.patch
new file mode 100644 (file)
index 0000000..0deaf5d
--- /dev/null
@@ -0,0 +1,74 @@
+From c22090facd354749cfe99a46e903449c7ac07788 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Thu, 25 Feb 2010 16:43:15 -0800
+Subject: Staging: hv: match on DMI values to know if we should run.
+
+From: Greg Kroah-Hartman <gregkh@suse.de>
+
+commit c22090facd354749cfe99a46e903449c7ac07788 upstream.
+
+The HV core mucks around with specific irqs and other low-level stuff
+and takes forever to determine that it really shouldn't be running on a
+machine.  So instead, trigger off of the DMI system information and
+error out much sooner.  This also allows the module loading tools to
+recognize that this code should be loaded on this type of system.
+
+Cc: Haiyang Zhang <haiyangz@microsoft.com>
+Cc: Hank Janssen <hjanssen@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/hv/vmbus_drv.c |   21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -25,6 +25,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/sysctl.h>
+ #include <linux/pci.h>
++#include <linux/dmi.h>
+ #include "osd.h"
+ #include "logging.h"
+ #include "vmbus.h"
+@@ -947,6 +948,19 @@ static irqreturn_t vmbus_isr(int irq, vo
+       }
+ }
++static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
++      {
++              .ident = "Hyper-V",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
++                      DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
++              },
++      },
++      { },
++};
++MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);
++
+ static int __init vmbus_init(void)
+ {
+       int ret = 0;
+@@ -958,6 +972,9 @@ static int __init vmbus_init(void)
+               vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
+       /* Todo: it is used for loglevel, to be ported to new kernel. */
++      if (!dmi_check_system(microsoft_hv_dmi_table))
++              return -ENODEV;
++
+       ret = vmbus_bus_init(VmbusInitialize);
+       DPRINT_EXIT(VMBUS_DRV);
+@@ -979,10 +996,6 @@ static void __exit vmbus_exit(void)
+  * needed by distro tools to determine if the hyperv drivers should be
+  * installed and/or configured.  We don't do anything else with the table, but
+  * it needs to be present.
+- *
+- * We might consider triggering off of DMI table info as well, as that does
+- * decribe the virtual machine being run on, but not all configuration tools
+- * seem to be able to handle DMI device ids properly.
+  */
+ const static struct pci_device_id microsoft_hv_pci_table[] = {
+       { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
diff --git a/queue-2.6.32/staging-mimio-remove-the-mimio-driver.patch b/queue-2.6.32/staging-mimio-remove-the-mimio-driver.patch
new file mode 100644 (file)
index 0000000..8af20df
--- /dev/null
@@ -0,0 +1,987 @@
+From e37bcc0de040127281de13a84a608570355c20eb Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Thu, 11 Feb 2010 17:15:14 -0800
+Subject: Staging: mimio: remove the mimio driver
+
+From: Greg Kroah-Hartman <gregkh@suse.de>
+
+commit e37bcc0de040127281de13a84a608570355c20eb upstream.
+
+It turns out that Mimio has a userspace solution for this product using
+libusb, and the in-kernel driver is just getting in the way now and
+causing problems.  So they have asked that the in-kernel driver be
+removed.  As the staging driver wasn't quite working anyway, and Mimio
+supports their libusb solution for all distros, I am removing the
+in-kernel driver.
+
+The libusb solution can be downloaded from:
+       http://www.mimio.com/downloads/mimio_studio_software/linux.asp
+
+Cc: <mwilder@cs.nmsu.edu>
+Cc: Phil Hannent <phil@hannent.co.uk>
+Cc: Marc Rousseau <Marc.Rousseau@mimio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/Kconfig        |    2 
+ drivers/staging/Makefile       |    1 
+ drivers/staging/mimio/Kconfig  |   10 
+ drivers/staging/mimio/Makefile |    1 
+ drivers/staging/mimio/mimio.c  |  914 -----------------------------------------
+ 5 files changed, 928 deletions(-)
+
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -81,8 +81,6 @@ source "drivers/staging/rtl8192su/Kconfi
+ source "drivers/staging/rtl8192e/Kconfig"
+-source "drivers/staging/mimio/Kconfig"
+-
+ source "drivers/staging/frontier/Kconfig"
+ source "drivers/staging/android/Kconfig"
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -23,7 +23,6 @@ obj-$(CONFIG_ALTERA_PCIE_CHDMA)      += altpc
+ obj-$(CONFIG_RTL8187SE)               += rtl8187se/
+ obj-$(CONFIG_RTL8192SU)               += rtl8192su/
+ obj-$(CONFIG_RTL8192E)                += rtl8192e/
+-obj-$(CONFIG_INPUT_MIMIO)     += mimio/
+ obj-$(CONFIG_TRANZPORT)               += frontier/
+ obj-$(CONFIG_ANDROID)         += android/
+ obj-$(CONFIG_ANDROID)         += dream/
+--- a/drivers/staging/mimio/Kconfig
++++ /dev/null
+@@ -1,10 +0,0 @@
+-config INPUT_MIMIO
+-      tristate "Mimio Xi interactive whiteboard support"
+-      depends on USB && INPUT
+-      default N
+-      help
+-        Say Y here if you want to use a Mimio Xi interactive
+-        whiteboard device.
+-
+-        To compile this driver as a module, choose M here: the
+-        module will be called mimio.
+--- a/drivers/staging/mimio/Makefile
++++ /dev/null
+@@ -1 +0,0 @@
+-obj-$(CONFIG_INPUT_MIMIO)     += mimio.o
+--- a/drivers/staging/mimio/mimio.c
++++ /dev/null
+@@ -1,914 +0,0 @@
+-/*
+- * Hardware event => input event mapping:
+- *
+- *
+- *
+- input.h:#define BTN_TOOL_PEN            0x140 black
+- input.h:#define BTN_TOOL_RUBBER         0x141 blue
+- input.h:#define BTN_TOOL_BRUSH          0x142 green
+- input.h:#define BTN_TOOL_PENCIL         0x143 red
+- input.h:#define BTN_TOOL_AIRBRUSH       0x144 eraser
+- input.h:#define BTN_TOOL_FINGER         0x145 small eraser
+- input.h:#define BTN_TOOL_MOUSE          0x146 mimio interactive
+- input.h:#define BTN_TOOL_LENS           0x147 mimio interactive but1
+- input.h:#define LOCALBTN_TOOL_EXTRA1    0x14a mimio interactive but2 == BTN_TOUCH
+- input.h:#define LOCALBTN_TOOL_EXTRA2    0x14b mimio extra pens (orange, brown, yellow, purple) == BTN_STYLUS
+- input.h:#define LOCALBTN_TOOL_EXTRA3    0x14c unused == BTN_STYLUS2
+- input.h:#define BTN_TOOL_DOUBLETAP      0x14d unused
+- input.h:#define BTN_TOOL_TRIPLETAP      0x14e unused
+- *
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_K)     => EV_KEY BIT(BTN_TOOL_PEN)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_B)     => EV_KEY BIT(BTN_TOOL_RUBBER)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_G)     => EV_KEY BIT(BTN_TOOL_BRUSH)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_R)     => EV_KEY BIT(BTN_TOOL_PENCIL)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_E)     => EV_KEY BIT(BTN_TOOL_AIRBRUSH)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_ES)    => EV_KEY BIT(BTN_TOOL_FINGER)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_I)     => EV_KEY BIT(BTN_TOOL_MOUSE)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_IL)    => EV_KEY BIT(BTN_TOOL_LENS)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_IR)    => EV_KEY BIT(BTN_TOOL_DOUBLETAP)
+- * MIMIO_EV_PENDOWN(MIMIO_PEN_EX)    => EV_KEY BIT(BTN_TOOL_TRIPLETAP)
+- * MIMIO_EV_PENDATA                 => EV_ABS BIT(ABS_X), BIT(ABS_Y)
+- * MIMIO_EV_MEMRESET              => EV_KEY BIT(BTN_0)
+- * MIMIO_EV_ACC(ACC_NEWPAGE)       => EV_KEY BIT(BTN_1)
+- * MIMIO_EV_ACC(ACC_TAGPAGE)      => EV_KEY BIT(BTN_2)
+- * MIMIO_EV_ACC(ACC_PRINTPAGE)      => EV_KEY BIT(BTN_3)
+- * MIMIO_EV_ACC(ACC_MAXIMIZE)      => EV_KEY BIT(BTN_4)
+- * MIMIO_EV_ACC(ACC_FINDCTLPNL)      => EV_KEY BIT(BTN_5)
+- *
+- *
+- * open issues:
+- *      - cold-load of data captured when mimio in standalone mode not yet
+- *         supported; need to snoop Win32 box to see datastream for this.
+- *       - mimio mouse not yet supported; need to snoop Win32 box to see the
+- *         datastream for this.
+- */
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/spinlock.h>
+-#include <linux/input.h>
+-#include <linux/usb.h>
+-
+-#define DRIVER_VERSION                "v0.031"
+-#define DRIVER_AUTHOR         "mwilder@cs.nmsu.edu"
+-#define DRIVER_DESC           "USB mimio-xi driver"
+-
+-enum {UPVALUE, DOWNVALUE, MOVEVALUE};
+-
+-#define MIMIO_XRANGE_MAX      9600
+-#define MIMIO_YRANGE_MAX      4800
+-
+-#define LOCALBTN_TOOL_EXTRA1  BTN_TOUCH
+-#define LOCALBTN_TOOL_EXTRA2  BTN_STYLUS
+-#define LOCALBTN_TOOL_EXTRA3  BTN_STYLUS2
+-
+-#define MIMIO_VENDOR_ID               0x08d3
+-#define MIMIO_PRODUCT_ID      0x0001
+-#define MIMIO_MAXPAYLOAD      (8)
+-#define MIMIO_MAXNAMELEN      (64)
+-#define MIMIO_TXWAIT          (1)
+-#define MIMIO_TXDONE          (2)
+-
+-#define MIMIO_EV_PENDOWN      (0x22)
+-#define MIMIO_EV_PENDATA      (0x24)
+-#define MIMIO_EV_PENUP                (0x51)
+-#define MIMIO_EV_MEMRESET     (0x45)
+-#define MIMIO_EV_ACC          (0xb2)
+-
+-#define MIMIO_PEN_K           (1)     /* black pen */
+-#define MIMIO_PEN_B           (2)     /* blue pen */
+-#define MIMIO_PEN_G           (3)     /* green pen */
+-#define MIMIO_PEN_R           (4)     /* red pen */
+-/* 5, 6, 7, 8 are extra pens */
+-#define MIMIO_PEN_E           (9)     /* big eraser */
+-#define MIMIO_PEN_ES          (10)    /* lil eraser */
+-#define MIMIO_PENJUMP_START   (10)
+-#define MIMIO_PENJUMP         (6)
+-#define MIMIO_PEN_I           (17)    /* mimio interactive */
+-#define MIMIO_PEN_IL          (18)    /* mimio interactive button 1 */
+-#define MIMIO_PEN_IR          (19)    /* mimio interactive button 2 */
+-
+-#define MIMIO_PEN_MAX         (MIMIO_PEN_IR)
+-
+-#define ACC_DONE              (0)
+-#define ACC_NEWPAGE           (1)
+-#define ACC_TAGPAGE           (2)
+-#define ACC_PRINTPAGE         (4)
+-#define ACC_MAXIMIZE          (8)
+-#define ACC_FINDCTLPNL                (16)
+-
+-#define isvalidtxsize(n)      ((n) > 0 && (n) <= MIMIO_MAXPAYLOAD)
+-
+-
+-struct pktbuf {
+-      unsigned char instr;
+-      unsigned char buf[16];
+-      unsigned char *p;
+-      unsigned char *q;
+-};
+-
+-struct usbintendpt {
+-      dma_addr_t dma;
+-      struct urb *urb;
+-      unsigned char *buf;
+-      struct usb_endpoint_descriptor *desc;
+-};
+-
+-struct mimio {
+-      struct input_dev *idev;
+-      struct usb_device *udev;
+-      struct usb_interface *uifc;
+-      int open;
+-      int present;
+-      int greeted;
+-      int txflags;
+-      char phys[MIMIO_MAXNAMELEN];
+-      struct usbintendpt in;
+-      struct usbintendpt out;
+-      struct pktbuf pktbuf;
+-      unsigned char minor;
+-      wait_queue_head_t waitq;
+-      spinlock_t txlock;
+-      void (*rxhandler)(struct mimio *, unsigned char *, unsigned int);
+-      int last_pen_down;
+-};
+-
+-static void mimio_close(struct input_dev *);
+-static void mimio_dealloc(struct mimio *);
+-static void mimio_disconnect(struct usb_interface *);
+-static int mimio_greet(struct mimio *);
+-static void mimio_irq_in(struct urb *);
+-static void mimio_irq_out(struct urb *);
+-static int mimio_open(struct input_dev *);
+-static int mimio_probe(struct usb_interface *, const struct usb_device_id *);
+-static void mimio_rx_handler(struct mimio *, unsigned char *, unsigned int);
+-static int mimio_tx(struct mimio *, const char *, int);
+-
+-static char mimio_name[] = "VirtualInk mimio-Xi";
+-static struct usb_device_id mimio_table [] = {
+-      { USB_DEVICE(MIMIO_VENDOR_ID, MIMIO_PRODUCT_ID) },
+-      { USB_DEVICE(0x0525, 0xa4a0) }, /* gadget zero firmware */
+-      { }
+-};
+-
+-MODULE_DEVICE_TABLE(usb, mimio_table);
+-
+-static struct usb_driver mimio_driver = {
+-      .name = "mimio",
+-      .probe = mimio_probe,
+-      .disconnect = mimio_disconnect,
+-      .id_table = mimio_table,
+-};
+-
+-static DECLARE_MUTEX(disconnect_sem);
+-
+-static void mimio_close(struct input_dev *idev)
+-{
+-      struct mimio *mimio;
+-
+-      mimio = input_get_drvdata(idev);
+-      if (!mimio) {
+-              dev_err(&idev->dev, "null mimio attached to input device\n");
+-              return;
+-      }
+-
+-      if (mimio->open <= 0)
+-              dev_err(&idev->dev, "mimio not open.\n");
+-      else
+-              mimio->open--;
+-
+-      if (mimio->present == 0 && mimio->open == 0)
+-              mimio_dealloc(mimio);
+-}
+-
+-static void mimio_dealloc(struct mimio *mimio)
+-{
+-      if (mimio == NULL)
+-              return;
+-
+-      usb_kill_urb(mimio->in.urb);
+-
+-      usb_kill_urb(mimio->out.urb);
+-
+-      if (mimio->idev) {
+-              input_unregister_device(mimio->idev);
+-              if (mimio->idev->grab)
+-                      input_close_device(mimio->idev->grab);
+-              else
+-                      dev_dbg(&mimio->idev->dev, "mimio->idev->grab == NULL"
+-                              " -- didn't call input_close_device\n");
+-      }
+-
+-      usb_free_urb(mimio->in.urb);
+-
+-      usb_free_urb(mimio->out.urb);
+-
+-      if (mimio->in.buf) {
+-              usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->in.buf,
+-                              mimio->in.dma);
+-      }
+-
+-      if (mimio->out.buf)
+-              usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->out.buf,
+-                              mimio->out.dma);
+-
+-      if (mimio->idev)
+-              input_free_device(mimio->idev);
+-
+-      kfree(mimio);
+-}
+-
+-static void mimio_disconnect(struct usb_interface *ifc)
+-{
+-      struct mimio *mimio;
+-
+-      down(&disconnect_sem);
+-
+-      mimio = usb_get_intfdata(ifc);
+-      usb_set_intfdata(ifc, NULL);
+-      dev_dbg(&mimio->idev->dev, "disconnect\n");
+-
+-      if (mimio) {
+-              mimio->present = 0;
+-
+-              if (mimio->open <= 0)
+-                      mimio_dealloc(mimio);
+-      }
+-
+-      up(&disconnect_sem);
+-}
+-
+-static int mimio_greet(struct mimio *mimio)
+-{
+-      const struct grtpkt {
+-              int nbytes;
+-              unsigned delay;
+-              char data[8];
+-      } grtpkts[] = {
+-              { 3, 0, { 0x11, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x53, 0x55, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x43, 0x55, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x33, 0x55, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x13, 0x00, 0x5e, 0x02, 0x4f, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x13, 0x00, 0x04, 0x03, 0x14, 0x00, 0x00, 0x00 } },
+-              { 5, 2, { 0x13, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x13, 0x00, 0x0d, 0x08, 0x16, 0x00, 0x00, 0x00 } },
+-              { 5, 0, { 0x13, 0x00, 0x4d, 0x01, 0x5f, 0x00, 0x00, 0x00 } },
+-              { 3, 0, { 0xf1, 0x55, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+-              { 7, 2, { 0x52, 0x55, 0x00, 0x07, 0x31, 0x55, 0x64, 0x00 } },
+-              { 0, 0, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+-      };
+-      int rslt;
+-      const struct grtpkt *pkt;
+-
+-      for (pkt = grtpkts; pkt->nbytes; pkt++) {
+-              rslt = mimio_tx(mimio, pkt->data, pkt->nbytes);
+-              if (rslt)
+-                      return rslt;
+-              if (pkt->delay)
+-                      msleep(pkt->delay);
+-      }
+-
+-      return 0;
+-}
+-
+-static void mimio_irq_in(struct urb *urb)
+-{
+-      int rslt;
+-      char *data;
+-      const char *reason = "going down";
+-      struct mimio *mimio;
+-
+-      mimio = urb->context;
+-
+-      if (mimio == NULL)
+-              /* paranoia */
+-              return;
+-
+-      switch (urb->status) {
+-      case 0:
+-              /* success */
+-              break;
+-      case -ETIMEDOUT:
+-              reason = "timeout -- unplugged?";
+-      case -ECONNRESET:
+-      case -ENOENT:
+-      case -ESHUTDOWN:
+-              dev_dbg(&mimio->idev->dev, "%s.\n", reason);
+-              return;
+-      default:
+-              dev_dbg(&mimio->idev->dev, "unknown urb-status: %d.\n",
+-                      urb->status);
+-              goto exit;
+-      }
+-      data = mimio->in.buf;
+-
+-      if (mimio->rxhandler)
+-              mimio->rxhandler(mimio, data, urb->actual_length);
+-exit:
+-      /*
+-       * Keep listening to device on same urb.
+-       */
+-      rslt = usb_submit_urb(urb, GFP_ATOMIC);
+-      if (rslt)
+-              dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
+-                      rslt);
+-}
+-
+-static void mimio_irq_out(struct urb *urb)
+-{
+-      unsigned long flags;
+-      struct mimio *mimio;
+-
+-      mimio = urb->context;
+-
+-      if (urb->status)
+-              dev_dbg(&mimio->idev->dev, "urb-status: %d.\n", urb->status);
+-
+-      spin_lock_irqsave(&mimio->txlock, flags);
+-      mimio->txflags |= MIMIO_TXDONE;
+-      spin_unlock_irqrestore(&mimio->txlock, flags);
+-      wmb();
+-      wake_up(&mimio->waitq);
+-}
+-
+-static int mimio_open(struct input_dev *idev)
+-{
+-      int rslt;
+-      struct mimio *mimio;
+-
+-      rslt = 0;
+-      down(&disconnect_sem);
+-      mimio = input_get_drvdata(idev);
+-      dev_dbg(&idev->dev, "mimio_open\n");
+-
+-      if (mimio == NULL) {
+-              dev_err(&idev->dev, "null mimio.\n");
+-              rslt = -ENODEV;
+-              goto exit;
+-      }
+-
+-      if (mimio->open++)
+-              goto exit;
+-
+-      if (mimio->present && !mimio->greeted) {
+-              struct urb *urb = mimio->in.urb;
+-              mimio->in.urb->dev = mimio->udev;
+-              rslt = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
+-              if (rslt) {
+-                      dev_err(&idev->dev, "usb_submit_urb failure "
+-                              "(res = %d: %s). Not greeting.\n",
+-                              rslt,
+-                              (!urb ? "urb is NULL" :
+-                               (urb->hcpriv ? "urb->hcpriv is non-NULL" :
+-                                (!urb->complete ? "urb is not complete" :
+-                                 (urb->number_of_packets <= 0 ? "urb has no packets" :
+-                                  (urb->interval <= 0 ? "urb interval too small" :
+-                                   "urb interval too large or some other error"))))));
+-                      rslt = -EIO;
+-                      goto exit;
+-              }
+-              rslt = mimio_greet(mimio);
+-              if (rslt == 0) {
+-                      dev_dbg(&idev->dev, "Mimio greeted OK.\n");
+-                      mimio->greeted = 1;
+-              } else {
+-                      dev_dbg(&idev->dev, "Mimio greet Failure (%d)\n",
+-                              rslt);
+-              }
+-      }
+-
+-exit:
+-      up(&disconnect_sem);
+-      return rslt;
+-}
+-
+-static int mimio_probe(struct usb_interface *ifc,
+-                     const struct usb_device_id *id)
+-{
+-      char path[64];
+-      int pipe, maxp;
+-      struct mimio *mimio;
+-      struct usb_device *udev;
+-      struct usb_host_interface *hostifc;
+-      struct input_dev *input_dev;
+-      int res = 0;
+-      int i;
+-
+-      udev = interface_to_usbdev(ifc);
+-
+-      mimio = kzalloc(sizeof(struct mimio), GFP_KERNEL);
+-      if (!mimio)
+-              return -ENOMEM;
+-
+-      input_dev = input_allocate_device();
+-      if (!input_dev) {
+-              mimio_dealloc(mimio);
+-              return -ENOMEM;
+-      }
+-
+-      mimio->uifc = ifc;
+-      mimio->udev = udev;
+-      mimio->pktbuf.p = mimio->pktbuf.buf;
+-      mimio->pktbuf.q = mimio->pktbuf.buf;
+-      /* init_input_dev(mimio->idev); */
+-      mimio->idev = input_dev;
+-      init_waitqueue_head(&mimio->waitq);
+-      spin_lock_init(&mimio->txlock);
+-      hostifc = ifc->cur_altsetting;
+-
+-      if (hostifc->desc.bNumEndpoints != 2) {
+-              dev_err(&udev->dev, "Unexpected endpoint count: %d.\n",
+-                      hostifc->desc.bNumEndpoints);
+-              mimio_dealloc(mimio);
+-              return -ENODEV;
+-      }
+-
+-      mimio->in.desc = &(hostifc->endpoint[0].desc);
+-      mimio->out.desc = &(hostifc->endpoint[1].desc);
+-
+-      mimio->in.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
+-                                       &mimio->in.dma);
+-      mimio->out.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
+-                                        &mimio->out.dma);
+-
+-      if (mimio->in.buf == NULL || mimio->out.buf == NULL) {
+-              dev_err(&udev->dev, "usb_buffer_alloc failure.\n");
+-              mimio_dealloc(mimio);
+-              return -ENOMEM;
+-      }
+-
+-      mimio->in.urb = usb_alloc_urb(0, GFP_KERNEL);
+-      mimio->out.urb = usb_alloc_urb(0, GFP_KERNEL);
+-
+-      if (mimio->in.urb == NULL || mimio->out.urb == NULL) {
+-              dev_err(&udev->dev, "usb_alloc_urb failure.\n");
+-              mimio_dealloc(mimio);
+-              return -ENOMEM;
+-      }
+-
+-      /*
+-       * Build the input urb.
+-       */
+-      pipe = usb_rcvintpipe(udev, mimio->in.desc->bEndpointAddress);
+-      maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+-      if (maxp > MIMIO_MAXPAYLOAD)
+-              maxp = MIMIO_MAXPAYLOAD;
+-      usb_fill_int_urb(mimio->in.urb, udev, pipe, mimio->in.buf, maxp,
+-                       mimio_irq_in, mimio, mimio->in.desc->bInterval);
+-      mimio->in.urb->transfer_dma = mimio->in.dma;
+-      mimio->in.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+-
+-      /*
+-       * Build the output urb.
+-       */
+-      pipe = usb_sndintpipe(udev, mimio->out.desc->bEndpointAddress);
+-      maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+-      if (maxp > MIMIO_MAXPAYLOAD)
+-              maxp = MIMIO_MAXPAYLOAD;
+-      usb_fill_int_urb(mimio->out.urb, udev, pipe, mimio->out.buf, maxp,
+-                       mimio_irq_out, mimio, mimio->out.desc->bInterval);
+-      mimio->out.urb->transfer_dma = mimio->out.dma;
+-      mimio->out.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+-
+-      /*
+-       * Build input device info
+-       */
+-      usb_make_path(udev, path, 64);
+-      snprintf(mimio->phys, MIMIO_MAXNAMELEN, "%s/input0", path);
+-      input_set_drvdata(input_dev, mimio);
+-      /* input_dev->dev = &ifc->dev; */
+-      input_dev->open = mimio_open;
+-      input_dev->close = mimio_close;
+-      input_dev->name = mimio_name;
+-      input_dev->phys = mimio->phys;
+-      input_dev->dev.parent = &ifc->dev;
+-
+-      input_dev->id.bustype = BUS_USB;
+-      input_dev->id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+-      input_dev->id.product = le16_to_cpu(udev->descriptor.idProduct);
+-      input_dev->id.version = le16_to_cpu(udev->descriptor.bcdDevice);
+-
+-      input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+-      for (i = BTN_TOOL_PEN; i <= LOCALBTN_TOOL_EXTRA2; ++i)
+-              set_bit(i, input_dev->keybit);
+-
+-      input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
+-                                               BIT_MASK(BTN_1) |
+-                                               BIT_MASK(BTN_2) |
+-                                               BIT_MASK(BTN_3) |
+-                                               BIT_MASK(BTN_4) |
+-                                               BIT_MASK(BTN_5);
+-      /*   input_dev->keybit[BTN_MOUSE] |= BIT(BTN_LEFT); */
+-      input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
+-      input_set_abs_params(input_dev, ABS_X, 0, MIMIO_XRANGE_MAX, 0, 0);
+-      input_set_abs_params(input_dev, ABS_Y, 0, MIMIO_YRANGE_MAX, 0, 0);
+-      input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
+-
+-#if 0
+-      input_dev->absmin[ABS_X] = 0;
+-      input_dev->absmin[ABS_Y] = 0;
+-      input_dev->absmax[ABS_X] = 9600;
+-      input_dev->absmax[ABS_Y] = 4800;
+-      input_dev->absfuzz[ABS_X] = 0;
+-      input_dev->absfuzz[ABS_Y] = 0;
+-      input_dev->absflat[ABS_X] = 0;
+-      input_dev->absflat[ABS_Y] = 0;
+-#endif
+-
+-#if 0
+-      /* this will just reduce the precision */
+-      input_dev->absfuzz[ABS_X] = 8; /* experimental; may need to change */
+-      input_dev->absfuzz[ABS_Y] = 8; /* experimental; may need to change */
+-#endif
+-
+-      /*
+-       * Register the input device.
+-       */
+-      res = input_register_device(mimio->idev);
+-      if (res) {
+-              dev_err(&udev->dev, "input_register_device failure (%d)\n",
+-                      res);
+-              mimio_dealloc(mimio);
+-              return -EIO;
+-      }
+-      dev_dbg(&mimio->idev->dev, "input: %s on %s (res = %d).\n",
+-              input_dev->name, input_dev->phys, res);
+-
+-      usb_set_intfdata(ifc, mimio);
+-      mimio->present = 1;
+-
+-      /*
+-       * Submit the input urb to the usb subsystem.
+-       */
+-      mimio->in.urb->dev = mimio->udev;
+-      res = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
+-      if (res) {
+-              dev_err(&mimio->idev->dev, "usb_submit_urb failure (%d)\n",
+-                      res);
+-              mimio_dealloc(mimio);
+-              return -EIO;
+-      }
+-
+-      /*
+-       * Attempt to greet the mimio after giving
+-       * it some post-init settling time.
+-       *
+-       * note: sometimes this sleep interval isn't
+-       * long enough to permit the device to re-init
+-       * after a hot-swap; maybe need to bump it up.
+-       *
+-       * As it is, this probably breaks module unloading support!
+-       */
+-      msleep(1024);
+-
+-      res = mimio_greet(mimio);
+-      if (res == 0) {
+-              dev_dbg(&mimio->idev->dev, "Mimio greeted OK.\n");
+-              mimio->greeted = 1;
+-              mimio->rxhandler = mimio_rx_handler;
+-      } else {
+-              dev_dbg(&mimio->idev->dev, "Mimio greet Failure (%d)\n", res);
+-      }
+-
+-      return 0;
+-}
+-
+-static int handle_mimio_rx_penupdown(struct mimio *mimio,
+-                                   int down,
+-                                   const char *const instr[],
+-                                   const int instr_ofst[])
+-{
+-      int penid, x;
+-      if (mimio->pktbuf.q - mimio->pktbuf.p < (down ? 4 : 3))
+-              return 1;               /* partial pkt */
+-
+-      if (down) {
+-              x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
+-                      *(mimio->pktbuf.p + 2);
+-              if (x != *(mimio->pktbuf.p + 3)) {
+-                      dev_dbg(&mimio->idev->dev, "EV_PEN%s: bad xsum.\n",
+-                              down ? "DOWN":"UP");
+-                      /* skip this event data */
+-                      mimio->pktbuf.p += 4;
+-                      /* decode any remaining events */
+-                      return 0;
+-              }
+-              penid = mimio->pktbuf.instr = *(mimio->pktbuf.p + 2);
+-              if (penid > MIMIO_PEN_MAX) {
+-                      dev_dbg(&mimio->idev->dev,
+-                              "Unmapped penID (not in [0, %d]): %d\n",
+-                              MIMIO_PEN_MAX, (int)mimio->pktbuf.instr);
+-                      penid = mimio->pktbuf.instr = 0;
+-              }
+-              mimio->last_pen_down = penid;
+-      } else {
+-              penid = mimio->last_pen_down;
+-      }
+-      dev_dbg(&mimio->idev->dev, "%s (id %d, code %d) %s.\n", instr[penid],
+-              instr_ofst[penid], penid, down ? "down" : "up");
+-
+-      if (instr_ofst[penid] >= 0) {
+-              int code = BTN_TOOL_PEN + instr_ofst[penid];
+-              int value = down ? DOWNVALUE : UPVALUE;
+-              if (code > KEY_MAX)
+-                      dev_dbg(&mimio->idev->dev, "input_event will ignore "
+-                              "-- code (%d) > KEY_MAX\n", code);
+-              if (!test_bit(code, mimio->idev->keybit))
+-                      dev_dbg(&mimio->idev->dev, "input_event will ignore "
+-                              "-- bit for code (%d) not enabled\n", code);
+-              if (!!test_bit(code, mimio->idev->key) == value)
+-                      dev_dbg(&mimio->idev->dev, "input_event will ignore "
+-                              "-- bit for code (%d) already set to %d\n",
+-                              code, value);
+-              if (value != DOWNVALUE) {
+-                      /* input_regs(mimio->idev, regs); */
+-                      input_report_key(mimio->idev, code, value);
+-                      input_sync(mimio->idev);
+-              } else {
+-                      /* wait until we get some coordinates */
+-              }
+-      } else {
+-              dev_dbg(&mimio->idev->dev, "penID offset[%d] == %d is < 0 "
+-                      "- not sending\n", penid, instr_ofst[penid]);
+-      }
+-      mimio->pktbuf.p += down ? 4 : 3; /* 3 for up, 4 for down */
+-      return 0;
+-}
+-
+-/*
+- * Stay tuned for partial-packet excitement.
+- *
+- * This routine buffers data packets received from the mimio device
+- * in the mimio's data space.  This buffering is necessary because
+- * the mimio's in endpoint can serve us partial packets of data, and
+- * we want the driver to support the servicing of multiple mimios.
+- * Empirical evidence gathered so far suggests that the method of
+- * buffering packet data in the mimio's data space works.  Previous
+- * versions of this driver did not buffer packet data in each mimio's
+- * data-space, and were therefore not able to service multiple mimios.
+- * Note that since the caller of this routine is running in interrupt
+- * context, care needs to be taken to ensure that this routine does not
+- * become bloated, and it may be that another spinlock is needed in each
+- * mimio to guard the buffered packet data properly.
+- */
+-static void mimio_rx_handler(struct mimio *mimio,
+-                           unsigned char *data,
+-                           unsigned int nbytes)
+-{
+-      struct device *dev = &mimio->idev->dev;
+-      unsigned int x;
+-      unsigned int y;
+-      static const char * const instr[] = {
+-              "?0",
+-              "black pen", "blue pen", "green pen", "red pen",
+-              "brown pen", "orange pen", "purple pen", "yellow pen",
+-              "big eraser", "lil eraser",
+-              "?11", "?12", "?13", "?14", "?15", "?16",
+-              "mimio interactive", "interactive button1",
+-              "interactive button2"
+-      };
+-
+-      /* Mimio Interactive gives:
+-       * down: [0x22 0x01 0x11 0x32 0x24]
+-       * b1  : [0x22 0x01 0x12 0x31 0x24]
+-       * b2  : [0x22 0x01 0x13 0x30 0x24]
+-       */
+-      static const int instr_ofst[] = {
+-              -1,
+-              0, 1, 2, 3,
+-              9, 9, 9, 9,
+-              4, 5,
+-              -1, -1, -1, -1, -1, -1,
+-              6, 7, 8,
+-      };
+-
+-      memcpy(mimio->pktbuf.q, data, nbytes);
+-      mimio->pktbuf.q += nbytes;
+-
+-      while (mimio->pktbuf.p < mimio->pktbuf.q) {
+-              int t = *mimio->pktbuf.p;
+-              switch (t) {
+-              case MIMIO_EV_PENUP:
+-              case MIMIO_EV_PENDOWN:
+-                      if (handle_mimio_rx_penupdown(mimio,
+-                                                    t == MIMIO_EV_PENDOWN,
+-                                                    instr, instr_ofst))
+-                              return; /* partial packet */
+-                      break;
+-
+-              case MIMIO_EV_PENDATA:
+-                      if (mimio->pktbuf.q - mimio->pktbuf.p < 6)
+-                              /* partial pkt */
+-                              return;
+-                      x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
+-                              *(mimio->pktbuf.p + 2) ^
+-                              *(mimio->pktbuf.p + 3) ^
+-                              *(mimio->pktbuf.p + 4);
+-                      if (x != *(mimio->pktbuf.p + 5)) {
+-                              dev_dbg(dev, "EV_PENDATA: bad xsum.\n");
+-                              mimio->pktbuf.p += 6; /* skip this event data */
+-                              break; /* decode any remaining events */
+-                      }
+-                      x = *(mimio->pktbuf.p + 1);
+-                      x <<= 8;
+-                      x |= *(mimio->pktbuf.p + 2);
+-                      y = *(mimio->pktbuf.p + 3);
+-                      y <<= 8;
+-                      y |= *(mimio->pktbuf.p + 4);
+-                      dev_dbg(dev, "coord: (%d, %d)\n", x, y);
+-                      if (instr_ofst[mimio->pktbuf.instr] >= 0) {
+-                              int code = BTN_TOOL_PEN +
+-                                         instr_ofst[mimio->last_pen_down];
+-#if 0
+-                              /* Utter hack to ensure we get forwarded _AND_
+-                               * so we can identify when a complete signal is
+-                               * received */
+-                              mimio->idev->abs[ABS_Y] = -1;
+-                              mimio->idev->abs[ABS_X] = -1;
+-#endif
+-                              /* input_regs(mimio->idev, regs); */
+-                              input_report_abs(mimio->idev, ABS_X, x);
+-                              input_report_abs(mimio->idev, ABS_Y, y);
+-                              /* fake a penup */
+-                              change_bit(code, mimio->idev->key);
+-                              input_report_key(mimio->idev,
+-                                               code,
+-                                               DOWNVALUE);
+-                              /* always sync here */
+-                              mimio->idev->sync = 0;
+-                              input_sync(mimio->idev);
+-                      }
+-                      mimio->pktbuf.p += 6;
+-                      break;
+-              case MIMIO_EV_MEMRESET:
+-                      if (mimio->pktbuf.q - mimio->pktbuf.p < 7)
+-                              /* partial pkt */
+-                              return;
+-                      dev_dbg(dev, "mem-reset.\n");
+-                      /* input_regs(mimio->idev, regs); */
+-                      input_event(mimio->idev, EV_KEY, BTN_0, 1);
+-                      input_event(mimio->idev, EV_KEY, BTN_0, 0);
+-                      input_sync(mimio->idev);
+-                      mimio->pktbuf.p += 7;
+-                      break;
+-              case MIMIO_EV_ACC:
+-                      if (mimio->pktbuf.q - mimio->pktbuf.p < 4)
+-                              /* partial pkt */
+-                              return;
+-                      x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
+-                              *(mimio->pktbuf.p + 2);
+-                      if (x != *(mimio->pktbuf.p + 3)) {
+-                              dev_dbg(dev, "EV_ACC: bad xsum.\n");
+-                              mimio->pktbuf.p += 4; /* skip this event data */
+-                              break; /* decode any remaining events */
+-                      }
+-                      switch (*(mimio->pktbuf.p + 2)) {
+-                      case ACC_NEWPAGE:
+-                              dev_dbg(&mimio->idev->dev, "new-page.\n");
+-                              /* input_regs(mimio->idev, regs); */
+-                              input_event(mimio->idev, EV_KEY, BTN_1, 1);
+-                              input_event(mimio->idev, EV_KEY, BTN_1, 0);
+-                              input_sync(mimio->idev);
+-                              break;
+-                      case ACC_TAGPAGE:
+-                              dev_dbg(&mimio->idev->dev, "tag-page.\n");
+-                              /* input_regs(mimio->idev, regs); */
+-                              input_event(mimio->idev, EV_KEY, BTN_2, 1);
+-                              input_event(mimio->idev, EV_KEY, BTN_2, 0);
+-                              input_sync(mimio->idev);
+-                              break;
+-                      case ACC_PRINTPAGE:
+-                              dev_dbg(&mimio->idev->dev, "print-page.\n");
+-                              /* input_regs(mimio->idev, regs);*/
+-                              input_event(mimio->idev, EV_KEY, BTN_3, 1);
+-                              input_event(mimio->idev, EV_KEY, BTN_3, 0);
+-                              input_sync(mimio->idev);
+-                              break;
+-                      case ACC_MAXIMIZE:
+-                              dev_dbg(&mimio->idev->dev,
+-                                      "maximize-window.\n");
+-                              /* input_regs(mimio->idev, regs); */
+-                              input_event(mimio->idev, EV_KEY, BTN_4, 1);
+-                              input_event(mimio->idev, EV_KEY, BTN_4, 0);
+-                              input_sync(mimio->idev);
+-                              break;
+-                      case ACC_FINDCTLPNL:
+-                              dev_dbg(&mimio->idev->dev, "find-ctl-panel.\n");
+-                              /* input_regs(mimio->idev, regs); */
+-                              input_event(mimio->idev, EV_KEY, BTN_5, 1);
+-                              input_event(mimio->idev, EV_KEY, BTN_5, 0);
+-                              input_sync(mimio->idev);
+-                              break;
+-                      case ACC_DONE:
+-                              dev_dbg(&mimio->idev->dev, "acc-done.\n");
+-                              /* no event is dispatched to the input
+-                               * subsystem for this device event.
+-                               */
+-                              break;
+-                      default:
+-                              dev_dbg(dev, "unknown acc event.\n");
+-                              break;
+-                      }
+-                      mimio->pktbuf.p += 4;
+-                      break;
+-              default:
+-                      mimio->pktbuf.p++;
+-                      break;
+-              }
+-      }
+-
+-      /*
+-       * No partial event was received, so reset mimio's pktbuf ptrs.
+-       */
+-      mimio->pktbuf.p = mimio->pktbuf.q = mimio->pktbuf.buf;
+-}
+-
+-static int mimio_tx(struct mimio *mimio, const char *buf, int nbytes)
+-{
+-      int rslt;
+-      int timeout;
+-      unsigned long flags;
+-      DECLARE_WAITQUEUE(wait, current);
+-
+-      if (!(isvalidtxsize(nbytes))) {
+-              dev_err(&mimio->idev->dev, "invalid arg: nbytes: %d.\n",
+-                      nbytes);
+-              return -EINVAL;
+-      }
+-
+-      /*
+-       * Init the out urb and copy the data to send.
+-       */
+-      mimio->out.urb->dev = mimio->udev;
+-      mimio->out.urb->transfer_buffer_length = nbytes;
+-      memcpy(mimio->out.urb->transfer_buffer, buf, nbytes);
+-
+-      /*
+-       * Send the data.
+-       */
+-      spin_lock_irqsave(&mimio->txlock, flags);
+-      mimio->txflags = MIMIO_TXWAIT;
+-      rslt = usb_submit_urb(mimio->out.urb, GFP_ATOMIC);
+-      spin_unlock_irqrestore(&mimio->txlock, flags);
+-      dev_dbg(&mimio->idev->dev, "rslt: %d.\n", rslt);
+-
+-      if (rslt) {
+-              dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
+-                      rslt);
+-              return rslt;
+-      }
+-
+-      /*
+-       * Wait for completion to be signalled (the mimio_irq_out
+-       * completion routine will or MIMIO_TXDONE in with txflags).
+-       */
+-      timeout = HZ;
+-      set_current_state(TASK_INTERRUPTIBLE);
+-      add_wait_queue(&mimio->waitq, &wait);
+-
+-      while (timeout && ((mimio->txflags & MIMIO_TXDONE) == 0)) {
+-              timeout = schedule_timeout(timeout);
+-              rmb();
+-      }
+-
+-      if ((mimio->txflags & MIMIO_TXDONE) == 0)
+-              dev_dbg(&mimio->idev->dev, "tx timed out.\n");
+-
+-      /*
+-       * Now that completion has been signalled,
+-       * unlink the urb so that it can be recycled.
+-       */
+-      set_current_state(TASK_RUNNING);
+-      remove_wait_queue(&mimio->waitq, &wait);
+-      usb_unlink_urb(mimio->out.urb);
+-
+-      return rslt;
+-}
+-
+-static int __init mimio_init(void)
+-{
+-      int rslt;
+-
+-      rslt = usb_register(&mimio_driver);
+-      if (rslt != 0) {
+-              err("%s: usb_register failure: %d", __func__, rslt);
+-              return rslt;
+-      }
+-
+-      printk(KERN_INFO KBUILD_MODNAME ":"
+-             DRIVER_DESC " " DRIVER_VERSION "\n");
+-      return rslt;
+-}
+-
+-static void __exit mimio_exit(void)
+-{
+-      usb_deregister(&mimio_driver);
+-}
+-
+-module_init(mimio_init);
+-module_exit(mimio_exit);
+-
+-MODULE_AUTHOR(DRIVER_AUTHOR);
+-MODULE_DESCRIPTION(DRIVER_DESC);
+-MODULE_LICENSE("GPL");
diff --git a/queue-2.6.32/v4l-dvb-13148-uvcvideo-handle-v4l2_ctrl_type_button-control-type-in-vidioc_queryctrl.patch b/queue-2.6.32/v4l-dvb-13148-uvcvideo-handle-v4l2_ctrl_type_button-control-type-in-vidioc_queryctrl.patch
new file mode 100644 (file)
index 0000000..b212bc3
--- /dev/null
@@ -0,0 +1,36 @@
+From f4eabafeb3ea41801260fba624cbf2da971d19f8 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 6 Aug 2009 06:05:40 -0300
+Subject: V4L/DVB (13148): uvcvideo: Handle V4L2_CTRL_TYPE_BUTTON control type in VIDIOC_QUERYCTRL
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+commit f4eabafeb3ea41801260fba624cbf2da971d19f8 upstream.
+
+Return minimum, maximum and step set to 0 without querying the hardware.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/video/uvc/uvc_ctrl.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/media/video/uvc/uvc_ctrl.c
++++ b/drivers/media/video/uvc/uvc_ctrl.c
+@@ -826,6 +826,13 @@ int uvc_query_v4l2_ctrl(struct uvc_video
+               ret = 0;
+               goto out;
++      case V4L2_CTRL_TYPE_BUTTON:
++              v4l2_ctrl->minimum = 0;
++              v4l2_ctrl->maximum = 0;
++              v4l2_ctrl->step = 0;
++              ret = 0;
++              goto out;
++
+       default:
+               break;
+       }