--- /dev/null
+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>
+
+---
+ drivers/clocksource/sh_cmt.c | 32 +++++++++++++++++++-------------
+ drivers/clocksource/sh_mtu2.c | 6 +++---
+ drivers/clocksource/sh_tmu.c | 6 +++---
+ 3 files changed, 25 insertions(+), 19 deletions(-)
+
+--- a/drivers/clocksource/sh_cmt.c
++++ b/drivers/clocksource/sh_cmt.c
+@@ -603,18 +603,13 @@ static int sh_cmt_setup(struct sh_cmt_pr
+ 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_pr
+ 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;
+ }
+
+--- a/drivers/clocksource/sh_mtu2.c
++++ b/drivers/clocksource/sh_mtu2.c
+@@ -221,15 +221,15 @@ static void sh_mtu2_register_clockevent(
+ 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,
+--- a/drivers/clocksource/sh_tmu.c
++++ b/drivers/clocksource/sh_tmu.c
+@@ -323,15 +323,15 @@ static void sh_tmu_register_clockevent(s
+ 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,
--- /dev/null
+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;
+ }
+
--- /dev/null
+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);
--- /dev/null
+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);
--- /dev/null
+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
--- /dev/null
+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 */
--- /dev/null
+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,
--- /dev/null
+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;
+ }
+
--- /dev/null
+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;
--- /dev/null
+From abd50713944c8ea9e0af5b7bffa0aacae21cc91a Mon Sep 17 00:00:00 2001
+From: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Date: Tue, 26 Jan 2010 18:50:16 +0100
+Subject: perf: Reimplement frequency driven sampling
+
+From: Peter Zijlstra <a.p.zijlstra@chello.nl>
+
+commit abd50713944c8ea9e0af5b7bffa0aacae21cc91a upstream.
+
+There was a bug in the old period code that caused intel_pmu_enable_all()
+or native_write_msr_safe() to show up quite high in the profiles.
+
+In staring at that code it made my head hurt, so I rewrote it in a
+hopefully simpler fashion. Its now fully symetric between tick and
+overflow driven adjustments and uses less data to boot.
+
+The only complication is that it basically wants to do a u128 division.
+The code approximates that in a rather simple truncate until it fits
+fashion, taking care to balance the terms while truncating.
+
+This version does not generate that sampling artefact.
+
+Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/perf_event.h | 5 -
+ kernel/perf_event.c | 132 +++++++++++++++++++++++++++++++--------------
+ 2 files changed, 94 insertions(+), 43 deletions(-)
+
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -496,9 +496,8 @@ struct hw_perf_event {
+ atomic64_t period_left;
+ u64 interrupts;
+
+- u64 freq_count;
+- u64 freq_interrupts;
+- u64 freq_stamp;
++ u64 freq_time_stamp;
++ u64 freq_count_stamp;
+ #endif
+ };
+
+--- a/kernel/perf_event.c
++++ b/kernel/perf_event.c
+@@ -1350,14 +1350,83 @@ static void perf_event_cpu_sched_in(stru
+
+ static void perf_log_throttle(struct perf_event *event, int enable);
+
+-static void perf_adjust_period(struct perf_event *event, u64 events)
++static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
++{
++ u64 frequency = event->attr.sample_freq;
++ u64 sec = NSEC_PER_SEC;
++ u64 divisor, dividend;
++
++ int count_fls, nsec_fls, frequency_fls, sec_fls;
++
++ count_fls = fls64(count);
++ nsec_fls = fls64(nsec);
++ frequency_fls = fls64(frequency);
++ sec_fls = 30;
++
++ /*
++ * We got @count in @nsec, with a target of sample_freq HZ
++ * the target period becomes:
++ *
++ * @count * 10^9
++ * period = -------------------
++ * @nsec * sample_freq
++ *
++ */
++
++ /*
++ * Reduce accuracy by one bit such that @a and @b converge
++ * to a similar magnitude.
++ */
++#define REDUCE_FLS(a, b) \
++do { \
++ if (a##_fls > b##_fls) { \
++ a >>= 1; \
++ a##_fls--; \
++ } else { \
++ b >>= 1; \
++ b##_fls--; \
++ } \
++} while (0)
++
++ /*
++ * Reduce accuracy until either term fits in a u64, then proceed with
++ * the other, so that finally we can do a u64/u64 division.
++ */
++ while (count_fls + sec_fls > 64 && nsec_fls + frequency_fls > 64) {
++ REDUCE_FLS(nsec, frequency);
++ REDUCE_FLS(sec, count);
++ }
++
++ if (count_fls + sec_fls > 64) {
++ divisor = nsec * frequency;
++
++ while (count_fls + sec_fls > 64) {
++ REDUCE_FLS(count, sec);
++ divisor >>= 1;
++ }
++
++ dividend = count * sec;
++ } else {
++ dividend = count * sec;
++
++ while (nsec_fls + frequency_fls > 64) {
++ REDUCE_FLS(nsec, frequency);
++ dividend >>= 1;
++ }
++
++ divisor = nsec * frequency;
++ }
++
++ return div64_u64(dividend, divisor);
++}
++
++static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
+ {
+ struct hw_perf_event *hwc = &event->hw;
+ u64 period, sample_period;
+ s64 delta;
+
+- events *= hwc->sample_period;
+- period = div64_u64(events, event->attr.sample_freq);
++ period = perf_calculate_period(event, nsec, count);
+
+ delta = (s64)(period - hwc->sample_period);
+ delta = (delta + 7) / 8; /* low pass filter */
+@@ -1368,13 +1437,22 @@ static void perf_adjust_period(struct pe
+ sample_period = 1;
+
+ hwc->sample_period = sample_period;
++
++ if (atomic64_read(&hwc->period_left) > 8*sample_period) {
++ perf_disable();
++ event->pmu->disable(event);
++ atomic64_set(&hwc->period_left, 0);
++ event->pmu->enable(event);
++ perf_enable();
++ }
+ }
+
+ static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
+ {
+ struct perf_event *event;
+ struct hw_perf_event *hwc;
+- u64 interrupts, freq;
++ u64 interrupts, now;
++ s64 delta;
+
+ raw_spin_lock(&ctx->lock);
+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
+@@ -1395,44 +1473,18 @@ static void perf_ctx_adjust_freq(struct
+ if (interrupts == MAX_INTERRUPTS) {
+ perf_log_throttle(event, 1);
+ event->pmu->unthrottle(event);
+- interrupts = 2*sysctl_perf_event_sample_rate/HZ;
+ }
+
+ if (!event->attr.freq || !event->attr.sample_freq)
+ continue;
+
+- /*
+- * if the specified freq < HZ then we need to skip ticks
+- */
+- if (event->attr.sample_freq < HZ) {
+- freq = event->attr.sample_freq;
+-
+- hwc->freq_count += freq;
+- hwc->freq_interrupts += interrupts;
+-
+- if (hwc->freq_count < HZ)
+- continue;
+-
+- interrupts = hwc->freq_interrupts;
+- hwc->freq_interrupts = 0;
+- hwc->freq_count -= HZ;
+- } else
+- freq = HZ;
++ event->pmu->read(event);
++ now = atomic64_read(&event->count);
++ delta = now - hwc->freq_count_stamp;
++ hwc->freq_count_stamp = now;
+
+- perf_adjust_period(event, freq * interrupts);
+-
+- /*
+- * In order to avoid being stalled by an (accidental) huge
+- * sample period, force reset the sample period if we didn't
+- * get any events in this freq period.
+- */
+- if (!interrupts) {
+- perf_disable();
+- event->pmu->disable(event);
+- atomic64_set(&hwc->period_left, 0);
+- event->pmu->enable(event);
+- perf_enable();
+- }
++ if (delta > 0)
++ perf_adjust_period(event, TICK_NSEC, delta);
+ }
+ raw_spin_unlock(&ctx->lock);
+ }
+@@ -3688,12 +3740,12 @@ static int __perf_event_overflow(struct
+
+ if (event->attr.freq) {
+ u64 now = perf_clock();
+- s64 delta = now - hwc->freq_stamp;
++ s64 delta = now - hwc->freq_time_stamp;
+
+- hwc->freq_stamp = now;
++ hwc->freq_time_stamp = now;
+
+- if (delta > 0 && delta < TICK_NSEC)
+- perf_adjust_period(event, NSEC_PER_SEC / (int)delta);
++ if (delta > 0 && delta < 2*TICK_NSEC)
++ perf_adjust_period(event, delta, hwc->last_period);
+ }
+
+ /*
--- /dev/null
+From 37fe5fcb7a5b5235c8b71bf5469ce4c7246e3fab Mon Sep 17 00:00:00 2001
+From: Zhang, Yanmin <yanmin_zhang@linux.intel.com>
+Date: Thu, 25 Feb 2010 11:00:51 +0800
+Subject: perf symbols: Check the right return variable
+
+From: Zhang, Yanmin <yanmin_zhang@linux.intel.com>
+
+commit 37fe5fcb7a5b5235c8b71bf5469ce4c7246e3fab upstream.
+
+In function dso__split_kallsyms(), curr_map saves the return value
+of map__new2. So check it instead of var map after the call returns.
+
+Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
+Cc: Frederic Weisbecker <fweisbec@gmail.com>
+LKML-Reference: <1267066851.1726.9.camel@localhost>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ tools/perf/util/symbol.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/perf/util/symbol.c
++++ b/tools/perf/util/symbol.c
+@@ -503,7 +503,7 @@ static int dso__split_kallsyms(struct ds
+ return -1;
+
+ curr_map = map__new2(pos->start, dso, map->type);
+- if (map == NULL) {
++ if (curr_map == NULL) {
+ dso__delete(dso);
+ return -1;
+ }
--- /dev/null
+From 24691ea964cc0123e386b661e03a86a481c6ee79 Mon Sep 17 00:00:00 2001
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Fri, 26 Feb 2010 16:36:23 +0100
+Subject: perf_event: Fix preempt warning in perf_clock()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+commit 24691ea964cc0123e386b661e03a86a481c6ee79 upstream.
+
+A recent commit introduced a preemption warning for
+perf_clock(), use raw_smp_processor_id() to avoid this, it
+really doesn't matter which cpu we use here.
+
+Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+LKML-Reference: <1267198583.22519.684.camel@laptop>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/perf_event.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/perf_event.c
++++ b/kernel/perf_event.c
+@@ -248,7 +248,7 @@ static void perf_unpin_context(struct pe
+
+ static inline u64 perf_clock(void)
+ {
+- return cpu_clock(smp_processor_id());
++ return cpu_clock(raw_smp_processor_id());
+ }
+
+ /*
--- /dev/null
+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(©_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(©_bm);
+ struct page *page = pfn_to_page(pfn);
+
--- /dev/null
+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);
drm-i915-give-up-on-8xx-lid-status.patch
ath9k-fix-keycache-leak-in-split-tkip-case.patch
rtc-core-fix-memory-leak.patch
+x86-pci-prevent-mmconfig-memory-corruption.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-fixed-pohmelfs-regression-because-of-per-bdi-writeback.patch
+staging-wlan-ng-add-select-wext_priv-to-kconfig-to-prevent-build-failure.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-v4l-soc_camera-fix-bound-checking-of-mbus_fmt-index.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
+perf-symbols-check-the-right-return-variable.patch
+perf_event-fix-preempt-warning-in-perf_clock.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
+perf-reimplement-frequency-driven-sampling.patch
+tracing-fix-ftrace_event_call-alignment-for-use-with-gcc-4.5.patch
--- /dev/null
+From 182374a0bddeef46769d2f8ab56fcccc433b96f3 Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Wed, 3 Feb 2010 01:04:30 +0300
+Subject: Staging: Fixed pohmelfs regression because of per-bdi writeback.
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit 182374a0bddeef46769d2f8ab56fcccc433b96f3 upstream.
+
+Since pohmelfs isn't tied to a single block device, it needs to setup a
+backing dev like nfs/btrfs/etc do.
+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/pohmelfs/inode.c | 20 ++++++++++++++++++--
+ drivers/staging/pohmelfs/netfs.h | 3 +++
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/pohmelfs/inode.c
++++ b/drivers/staging/pohmelfs/inode.c
+@@ -36,6 +36,7 @@
+ #define POHMELFS_MAGIC_NUM 0x504f482e
+
+ static struct kmem_cache *pohmelfs_inode_cache;
++static atomic_t psb_bdi_num = ATOMIC_INIT(0);
+
+ /*
+ * Removes inode from all trees, drops local name cache and removes all queued
+@@ -1331,6 +1332,8 @@ static void pohmelfs_put_super(struct su
+ pohmelfs_crypto_exit(psb);
+ pohmelfs_state_exit(psb);
+
++ bdi_destroy(&psb->bdi);
++
+ kfree(psb);
+ sb->s_fs_info = NULL;
+ }
+@@ -1815,11 +1818,22 @@ static int pohmelfs_fill_super(struct su
+ if (!psb)
+ goto err_out_exit;
+
++ err = bdi_init(&psb->bdi);
++ if (err)
++ goto err_out_free_sb;
++
++ err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
++ if (err) {
++ bdi_destroy(&psb->bdi);
++ goto err_out_free_sb;
++ }
++
+ sb->s_fs_info = psb;
+ sb->s_op = &pohmelfs_sb_ops;
+ sb->s_magic = POHMELFS_MAGIC_NUM;
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_blocksize = PAGE_SIZE;
++ sb->s_bdi = &psb->bdi;
+
+ psb->sb = sb;
+
+@@ -1863,11 +1877,11 @@ static int pohmelfs_fill_super(struct su
+
+ err = pohmelfs_parse_options((char *) data, psb, 0);
+ if (err)
+- goto err_out_free_sb;
++ goto err_out_free_bdi;
+
+ err = pohmelfs_copy_crypto(psb);
+ if (err)
+- goto err_out_free_sb;
++ goto err_out_free_bdi;
+
+ err = pohmelfs_state_init(psb);
+ if (err)
+@@ -1916,6 +1930,8 @@ err_out_state_exit:
+ err_out_free_strings:
+ kfree(psb->cipher_string);
+ kfree(psb->hash_string);
++err_out_free_bdi:
++ bdi_destroy(&psb->bdi);
+ err_out_free_sb:
+ kfree(psb);
+ err_out_exit:
+--- a/drivers/staging/pohmelfs/netfs.h
++++ b/drivers/staging/pohmelfs/netfs.h
+@@ -18,6 +18,7 @@
+
+ #include <linux/types.h>
+ #include <linux/connector.h>
++#include <linux/backing-dev.h>
+
+ #define POHMELFS_CN_IDX 5
+ #define POHMELFS_CN_VAL 0
+@@ -624,6 +625,8 @@ struct pohmelfs_sb {
+
+ struct super_block *sb;
+
++ struct backing_dev_info bdi;
++
+ /*
+ * Algorithm strings.
+ */
--- /dev/null
+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);
--- /dev/null
+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 */
--- /dev/null
+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/rtl8192u/Kconfig
+
+ source "drivers/staging/rtl8192e/Kconfig"
+
+-source "drivers/staging/mimio/Kconfig"
+-
+ source "drivers/staging/frontier/Kconfig"
+
+ source "drivers/staging/dream/Kconfig"
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -23,7 +23,6 @@ obj-$(CONFIG_R8187SE) += rtl8187se/
+ obj-$(CONFIG_RTL8192SU) += rtl8192su/
+ obj-$(CONFIG_RTL8192U) += rtl8192u/
+ obj-$(CONFIG_RTL8192E) += rtl8192e/
+-obj-$(CONFIG_INPUT_MIMIO) += mimio/
+ obj-$(CONFIG_TRANZPORT) += frontier/
+ obj-$(CONFIG_DREAM) += dream/
+ obj-$(CONFIG_POHMELFS) += pohmelfs/
+--- 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");
--- /dev/null
+From 8a8e29752dfdba014b866d3c587d3409e57263dd Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peterhuewe@gmx.de>
+Date: Thu, 7 Jan 2010 21:21:35 +0100
+Subject: Staging: wlan-ng: Add select WEXT_PRIV to Kconfig to prevent build failure
+
+From: Peter Huewe <peterhuewe@gmx.de>
+
+commit 8a8e29752dfdba014b866d3c587d3409e57263dd upstream.
+
+Without WEXT_PRIV set the p80211wext.c fails to build due to unknown fields in
+the iw_handler_def struct.
+Those fields are enclosed in WEXT_PRIV conditionals in the prototype
+of iw_handler_def in include/net/iw_handler.h
+
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Acked-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/wlan-ng/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/wlan-ng/Kconfig
++++ b/drivers/staging/wlan-ng/Kconfig
+@@ -1,6 +1,7 @@
+ config PRISM2_USB
+ tristate "Prism2.5/3 USB driver"
+ depends on WLAN && USB && WIRELESS_EXT
++ select WEXT_PRIV
+ default n
+ ---help---
+ This is the wlan-ng prism 2.5/3 USB driver for a wide range of
--- /dev/null
+From 86c38a31aa7f2dd6e74a262710bf8ebf7455acc5 Mon Sep 17 00:00:00 2001
+From: Jeff Mahoney <jeffm@suse.com>
+Date: Wed, 24 Feb 2010 13:59:23 -0500
+Subject: tracing: Fix ftrace_event_call alignment for use with gcc 4.5
+
+From: Jeff Mahoney <jeffm@suse.com>
+
+commit 86c38a31aa7f2dd6e74a262710bf8ebf7455acc5 upstream.
+
+GCC 4.5 introduces behavior that forces the alignment of structures to
+ use the largest possible value. The default value is 32 bytes, so if
+ some structures are defined with a 4-byte alignment and others aren't
+ declared with an alignment constraint at all - it will align at 32-bytes.
+
+ For things like the ftrace events, this results in a non-standard array.
+ When initializing the ftrace subsystem, we traverse the _ftrace_events
+ section and call the initialization callback for each event. When the
+ structures are misaligned, we could be treating another part of the
+ structure (or the zeroed out space between them) as a function pointer.
+
+ This patch forces the alignment for all the ftrace_event_call structures
+ to 4 bytes.
+
+ Without this patch, the kernel fails to boot very early when built with
+ gcc 4.5.
+
+ It's trivial to check the alignment of the members of the array, so it
+ might be worthwhile to add something to the build system to do that
+ automatically. Unfortunately, that only covers this case. I've asked one
+ of the gcc developers about adding a warning when this condition is seen.
+
+Signed-off-by: Jeff Mahoney <jeffm@suse.com>
+LKML-Reference: <4B85770B.6010901@suse.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/syscalls.h | 6 ++++--
+ include/trace/ftrace.h | 3 ++-
+ kernel/trace/trace.h | 3 ++-
+ 3 files changed, 8 insertions(+), 4 deletions(-)
+
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -132,7 +132,8 @@ struct perf_event_attr;
+
+ #define SYSCALL_TRACE_ENTER_EVENT(sname) \
+ static const struct syscall_metadata __syscall_meta_##sname; \
+- static struct ftrace_event_call event_enter_##sname; \
++ static struct ftrace_event_call \
++ __attribute__((__aligned__(4))) event_enter_##sname; \
+ static struct trace_event enter_syscall_print_##sname = { \
+ .trace = print_syscall_enter, \
+ }; \
+@@ -154,7 +155,8 @@ struct perf_event_attr;
+
+ #define SYSCALL_TRACE_EXIT_EVENT(sname) \
+ static const struct syscall_metadata __syscall_meta_##sname; \
+- static struct ftrace_event_call event_exit_##sname; \
++ static struct ftrace_event_call \
++ __attribute__((__aligned__(4))) event_exit_##sname; \
+ static struct trace_event exit_syscall_print_##sname = { \
+ .trace = print_syscall_exit, \
+ }; \
+--- a/include/trace/ftrace.h
++++ b/include/trace/ftrace.h
+@@ -65,7 +65,8 @@
+ };
+ #undef DEFINE_EVENT
+ #define DEFINE_EVENT(template, name, proto, args) \
+- static struct ftrace_event_call event_##name
++ static struct ftrace_event_call \
++ __attribute__((__aligned__(4))) event_##name
+
+ #undef DEFINE_EVENT_PRINT
+ #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
+--- a/kernel/trace/trace.h
++++ b/kernel/trace/trace.h
+@@ -791,7 +791,8 @@ extern const char *__stop___trace_bprint
+
+ #undef FTRACE_ENTRY
+ #define FTRACE_ENTRY(call, struct_name, id, tstruct, print) \
+- extern struct ftrace_event_call event_##call;
++ extern struct ftrace_event_call \
++ __attribute__((__aligned__(4))) event_##call;
+ #undef FTRACE_ENTRY_DUP
+ #define FTRACE_ENTRY_DUP(call, struct_name, id, tstruct, print) \
+ FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
--- /dev/null
+From 84f3751d6a6f766780dee509433bf7b3dfcdf465 Mon Sep 17 00:00:00 2001
+From: Baruch Siach <baruch@tkos.co.il>
+Date: Fri, 19 Feb 2010 14:09:25 -0300
+Subject: V4L/DVB: v4l: soc_camera: fix bound checking of mbus_fmt[] index
+
+From: Baruch Siach <baruch@tkos.co.il>
+
+commit 84f3751d6a6f766780dee509433bf7b3dfcdf465 upstream.
+
+When code <= V4L2_MBUS_FMT_FIXED soc_mbus_get_fmtdesc returns a pointer to
+mbus_fmt[x], where x < 0. Fix this.
+
+Signed-off-by: Baruch Siach <baruch@tkos.co.il>
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/video/soc_mediabus.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/video/soc_mediabus.c
++++ b/drivers/media/video/soc_mediabus.c
+@@ -134,7 +134,8 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line);
+ const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
+ enum v4l2_mbus_pixelcode code)
+ {
+- if ((unsigned int)(code - V4L2_MBUS_FMT_FIXED) > ARRAY_SIZE(mbus_fmt))
++ if (code - V4L2_MBUS_FMT_FIXED > ARRAY_SIZE(mbus_fmt) ||
++ code <= V4L2_MBUS_FMT_FIXED)
+ return NULL;
+ return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1;
+ }
--- /dev/null
+From bb8d41330ce27edb91adb6922d3f8e1a8923f727 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 25 Feb 2010 16:42:11 +0100
+Subject: x86/PCI: Prevent mmconfig memory corruption
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit bb8d41330ce27edb91adb6922d3f8e1a8923f727 upstream.
+
+commit ff097ddd4 (x86/PCI: MMCONFIG: manage pci_mmcfg_region as a
+list, not a table) introduced a nasty memory corruption when
+pci_mmcfg_list is empty.
+
+pci_mmcfg_check_end_bus_number() dereferences pci_mmcfg_list.prev even
+when the list is empty. The following write hits some variable near to
+pci_mmcfg_list.
+
+Further down a similar problem exists, where cfg->list.next is
+dereferenced unconditionally and a comparison with some variable near
+to pci_mmcfg_list happens.
+
+Add a check for the last element into the for_each_entry() loop and
+remove all the other crappy logic which is just a leftover of the old
+array based code which was replaced by the list conversion.
+
+Reported-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
+Cc: Yinghai Lu <yinghai@kernel.org>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/pci/mmconfig-shared.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+--- a/arch/x86/pci/mmconfig-shared.c
++++ b/arch/x86/pci/mmconfig-shared.c
+@@ -303,22 +303,17 @@ static void __init pci_mmcfg_check_end_b
+ {
+ struct pci_mmcfg_region *cfg, *cfgx;
+
+- /* last one*/
+- cfg = list_entry(pci_mmcfg_list.prev, typeof(*cfg), list);
+- if (cfg)
+- if (cfg->end_bus < cfg->start_bus)
+- cfg->end_bus = 255;
+-
+- if (list_is_singular(&pci_mmcfg_list))
+- return;
+-
+- /* don't overlap please */
++ /* Fixup overlaps */
+ list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+ if (cfg->end_bus < cfg->start_bus)
+ cfg->end_bus = 255;
+
++ /* Don't access the list head ! */
++ if (cfg->list.next == &pci_mmcfg_list)
++ break;
++
+ cfgx = list_entry(cfg->list.next, typeof(*cfg), list);
+- if (cfg != cfgx && cfg->end_bus >= cfgx->start_bus)
++ if (cfg->end_bus >= cfgx->start_bus)
+ cfg->end_bus = cfgx->start_bus - 1;
+ }
+ }