Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 15ce0f2..320af25 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -253,6 +253,7 @@
 !Edrivers/usb/core/urb.c
 !Edrivers/usb/core/message.c
 !Edrivers/usb/core/file.c
+!Edrivers/usb/core/driver.c
 !Edrivers/usb/core/usb.c
 !Edrivers/usb/core/hub.c
     </chapter>
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 933fae7..f4b8dc4 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -27,6 +27,7 @@
 2.2  Powersave
 2.3  Userspace
 2.4  Ondemand
+2.5  Conservative
 
 3.   The Governor Interface in the CPUfreq Core
 
@@ -110,9 +111,64 @@
 
 The CPUfreq govenor "ondemand" sets the CPU depending on the
 current usage. To do this the CPU must have the capability to
-switch the frequency very fast.
+switch the frequency very quickly.  There are a number of sysfs file
+accessible parameters:
+
+sampling_rate: measured in uS (10^-6 seconds), this is how often you
+want the kernel to look at the CPU usage and to make decisions on
+what to do about the frequency.  Typically this is set to values of
+around '10000' or more.
+
+show_sampling_rate_(min|max): the minimum and maximum sampling rates
+available that you may set 'sampling_rate' to.
+
+up_threshold: defines what the average CPU usaged between the samplings
+of 'sampling_rate' needs to be for the kernel to make a decision on
+whether it should increase the frequency.  For example when it is set
+to its default value of '80' it means that between the checking
+intervals the CPU needs to be on average more than 80% in use to then
+decide that the CPU frequency needs to be increased.  
+
+sampling_down_factor: this parameter controls the rate that the CPU
+makes a decision on when to decrease the frequency.  When set to its
+default value of '5' it means that at 1/5 the sampling_rate the kernel
+makes a decision to lower the frequency.  Five "lower rate" decisions
+have to be made in a row before the CPU frequency is actually lower.
+If set to '1' then the frequency decreases as quickly as it increases,
+if set to '2' it decreases at half the rate of the increase.
+
+ignore_nice_load: this parameter takes a value of '0' or '1', when set
+to '0' (its default) then all processes are counted towards towards the
+'cpu utilisation' value.   When set to '1' then processes that are
+run with a 'nice' value will not count (and thus be ignored) in the
+overal usage calculation.  This is useful if you are running a CPU
+intensive calculation on your laptop that you do not care how long it
+takes to complete as you can 'nice' it and prevent it from taking part
+in the deciding process of whether to increase your CPU frequency.
 
 
+2.5 Conservative
+----------------
+
+The CPUfreq governor "conservative", much like the "ondemand"
+governor, sets the CPU depending on the current usage.  It differs in
+behaviour in that it gracefully increases and decreases the CPU speed
+rather than jumping to max speed the moment there is any load on the
+CPU.  This behaviour more suitable in a battery powered environment.
+The governor is tweaked in the same manner as the "ondemand" governor
+through sysfs with the addition of:
+
+freq_step: this describes what percentage steps the cpu freq should be
+increased and decreased smoothly by.  By default the cpu frequency will
+increase in 5% chunks of your maximum cpu frequency.  You can change this
+value to anywhere between 0 and 100 where '0' will effectively lock your
+CPU at a speed regardless of its load whilst '100' will, in theory, make
+it behave identically to the "ondemand" governor.
+
+down_threshold: same as the 'up_threshold' found for the "ondemand"
+governor but for the opposite direction.  For example when set to its
+default value of '20' it means that if the CPU usage needs to be below
+20% between samples to have the frequency decreased.
 
 3. The Governor Interface in the CPUfreq Core
 =============================================
diff --git a/MAINTAINERS b/MAINTAINERS
index 6af6830..3fd7687 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2640,6 +2640,12 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB ISP116X DRIVER
+P:	Olav Kongas
+M:	ok@artecdesign.ee
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Maintained
+
 USB KAWASAKI LSI DRIVER
 P:	Oliver Neukum
 M:	oliver@neukum.name
@@ -2651,7 +2657,7 @@
 P:	Matthew Dharm
 M:	mdharm-usb@one-eyed-alien.net
 L:	linux-usb-users@lists.sourceforge.net
-L:	linux-usb-devel@lists.sourceforge.net
+L:	usb-storage@lists.one-eyed-alien.net
 S:	Maintained
 W:	http://www.one-eyed-alien.net/~mdharm/linux-usb/
 
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 07892f4..277498a 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -43,6 +43,7 @@
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/irda.h>
+#include <asm/arch/ohci.h>
 
 #include "generic.h"
 
@@ -393,6 +394,25 @@
 	&mst_flash_device[1],
 };
 
+static int mainstone_ohci_init(struct device *dev)
+{
+	/* setup Port1 GPIO pin. */
+	pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN);	/* USBHPWR1 */
+	pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT);	/* USBHPEN1 */
+
+	/* Set the Power Control Polarity Low and Power Sense
+	   Polarity Low to active low. */
+	UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+		~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+	return 0;
+}
+
+static struct pxaohci_platform_data mainstone_ohci_platform_data = {
+	.port_mode	= PMM_PERPORT_MODE,
+	.init		= mainstone_ohci_init,
+};
+
 static void __init mainstone_init(void)
 {
 	int SW7 = 0;  /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
@@ -424,6 +444,7 @@
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);
 	pxa_set_ficp_info(&mainstone_ficp_platform_data);
+	pxa_set_ohci_info(&mainstone_ohci_platform_data);
 }
 
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index c722a9a..b41b1ef 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -21,6 +21,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/ohci.h>
 
 #include "generic.h"
 
@@ -194,6 +195,11 @@
 	.resource       = pxa27x_ohci_resources,
 };
 
+void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
+{
+	ohci_device.dev.platform_data = info;
+}
+
 static struct platform_device *devices[] __initdata = {
 	&ohci_device,
 };
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 04a4053..2b62dee 100644
--- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -177,9 +177,10 @@
  */
 static int nforce2_set_fsb(unsigned int fsb)
 {
-	u32 pll, temp = 0;
+	u32 temp = 0;
 	unsigned int tfsb;
 	int diff;
+	int pll = 0;
 
 	if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
 		printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 68a1fc8..0fbbd4c 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -45,7 +45,7 @@
 
 #define PFX "powernow-k8: "
 #define BFX PFX "BIOS error: "
-#define VERSION "version 1.50.4"
+#define VERSION "version 1.60.0"
 #include "powernow-k8.h"
 
 /* serialize freq changes  */
@@ -216,10 +216,10 @@
 
 	do {
 		wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
-                if (i++ > 100) {
-                        printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
-                        return 1;
-                }
+		if (i++ > 100) {
+			printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
+			return 1;
+		}
 	} while (query_current_values_with_pending_wait(data));
 
 	if (savefid != data->currfid) {
@@ -336,7 +336,7 @@
 /* Phase 2 - core frequency transition */
 static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
 {
-	u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid;
+	u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid;
 
 	if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
 		printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n",
@@ -359,9 +359,11 @@
 	    : vcoreqfid - vcocurrfid;
 
 	while (vcofiddiff > 2) {
+		(data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
+
 		if (reqfid > data->currfid) {
 			if (data->currfid > LO_FID_TABLE_TOP) {
-				if (write_new_fid(data, data->currfid + 2)) {
+				if (write_new_fid(data, data->currfid + fid_interval)) {
 					return 1;
 				}
 			} else {
@@ -371,7 +373,7 @@
 				}
 			}
 		} else {
-			if (write_new_fid(data, data->currfid - 2))
+			if (write_new_fid(data, data->currfid - fid_interval))
 				return 1;
 		}
 
@@ -464,7 +466,7 @@
 	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 
 	if (smp_processor_id() != cpu) {
-		printk(KERN_ERR "limiting to cpu %u failed\n", cpu);
+		printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
 		goto out;
 	}
 
@@ -474,7 +476,7 @@
 	eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
 	if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
 	    ((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
-	    ((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) {
+	    ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
 		printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
 		goto out;
 	}
@@ -517,22 +519,24 @@
 			printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j);
 			return -ENODEV;
 		}
-		if ((pst[j].fid > MAX_FID)
-		    || (pst[j].fid & 1)
-		    || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
+		if (pst[j].fid > MAX_FID) {
+			printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j);
+			return -ENODEV;
+		}
+		if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) {
 			/* Only first fid is allowed to be in "low" range */
-			printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
+			printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
 			return -EINVAL;
 		}
 		if (pst[j].fid < lastfid)
 			lastfid = pst[j].fid;
 	}
 	if (lastfid & 1) {
-		printk(KERN_ERR PFX "lastfid invalid\n");
+		printk(KERN_ERR BFX "lastfid invalid\n");
 		return -EINVAL;
 	}
 	if (lastfid > LO_FID_TABLE_TOP)
-		printk(KERN_INFO PFX  "first fid not from lo freq table\n");
+		printk(KERN_INFO BFX  "first fid not from lo freq table\n");
 
 	return 0;
 }
@@ -631,7 +635,7 @@
 
 		dprintk("table vers: 0x%x\n", psb->tableversion);
 		if (psb->tableversion != PSB_VERSION_1_4) {
-			printk(KERN_INFO BFX "PSB table is not v1.4\n");
+			printk(KERN_ERR BFX "PSB table is not v1.4\n");
 			return -ENODEV;
 		}
 
@@ -689,7 +693,7 @@
 	 * BIOS and Kernel Developer's Guide, which is available on
 	 * www.amd.com
 	 */
-	printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
+	printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n");
 	return -ENODEV;
 }
 
@@ -912,7 +916,7 @@
 	set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
 
 	if (smp_processor_id() != pol->cpu) {
-		printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
+		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
 		goto err_out;
 	}
 
@@ -982,6 +986,9 @@
 	cpumask_t oldmask = CPU_MASK_ALL;
 	int rc, i;
 
+	if (!cpu_online(pol->cpu))
+		return -ENODEV;
+
 	if (!check_supported_cpu(pol->cpu))
 		return -ENODEV;
 
@@ -1021,7 +1028,7 @@
 	set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
 
 	if (smp_processor_id() != pol->cpu) {
-		printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
+		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
 		goto err_out;
 	}
 
@@ -1162,10 +1169,9 @@
 	cpufreq_unregister_driver(&cpufreq_amd64_driver);
 }
 
-MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
+MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>");
 MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
 MODULE_LICENSE("GPL");
 
 late_initcall(powernowk8_init);
 module_exit(powernowk8_exit);
-
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index b1e85bb..d0de37d 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -42,7 +42,7 @@
 #define CPUID_XFAM			0x0ff00000	/* extended family */
 #define CPUID_XFAM_K8			0
 #define CPUID_XMOD			0x000f0000	/* extended model */
-#define CPUID_XMOD_REV_F		0x00040000
+#define CPUID_XMOD_REV_G		0x00060000
 #define CPUID_USE_XFAM_XMOD		0x00000f00
 #define CPUID_GET_MAX_CAPABILITIES	0x80000000
 #define CPUID_FREQ_VOLT_CAPABILITIES	0x80000007
@@ -86,13 +86,14 @@
  *   low fid table
  * - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry
  *   in the low fid table
- * - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid
+ * - the parts can only step at <= 200 MHz intervals, odd fid values are
+ *   supported in revision G and later revisions.
  * - lowest frequency must be >= interprocessor hypertransport link speed
  *   (only applies to MP systems obviously)
  */
 
 /* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
-#define LO_FID_TABLE_TOP     6	/* fid values marking the boundary    */
+#define LO_FID_TABLE_TOP     7	/* fid values marking the boundary    */
 #define HI_FID_TABLE_BOTTOM  8	/* between the low and high tables    */
 
 #define LO_VCOFREQ_TABLE_TOP    1400	/* corresponding vco frequency values */
@@ -106,7 +107,7 @@
 #define MIN_FREQ 800	/* Min and max freqs, per spec */
 #define MAX_FREQ 5000
 
-#define INVALID_FID_MASK 0xffffffc1  /* not a valid fid if these bits are set */
+#define INVALID_FID_MASK 0xffffffc0  /* not a valid fid if these bits are set */
 #define INVALID_VID_MASK 0xffffffc0  /* not a valid vid if these bits are set */
 
 #define VID_OFF 0x3f
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
index 5b7d18a..b425cd3d1 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
@@ -40,6 +40,7 @@
  */
 static unsigned int speedstep_processor = 0;
 
+static u32 pmbase;
 
 /*
  *   There are only two frequency states for each processor. Values
@@ -56,6 +57,33 @@
 
 
 /**
+ * speedstep_find_register - read the PMBASE address
+ *
+ * Returns: -ENODEV if no register could be found
+ */
+static int speedstep_find_register (void)
+{
+	if (!speedstep_chipset_dev)
+		return -ENODEV;
+
+	/* get PMBASE */
+	pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
+	if (!(pmbase & 0x01)) {
+		printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
+		return -ENODEV;
+	}
+
+	pmbase &= 0xFFFFFFFE;
+	if (!pmbase) {
+		printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
+		return -ENODEV;
+	}
+
+	dprintk("pmbase is 0x%x\n", pmbase);
+	return 0;
+}
+
+/**
  * speedstep_set_state - set the SpeedStep state
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
@@ -63,27 +91,13 @@
  */
 static void speedstep_set_state (unsigned int state)
 {
-	u32 pmbase;
 	u8 pm2_blk;
 	u8 value;
 	unsigned long flags;
 
-	if (!speedstep_chipset_dev || (state > 0x1))
+	if (state > 0x1)
 		return;
 
-	/* get PMBASE */
-	pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
-	if (!(pmbase & 0x01)) {
-		printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
-		return;
-	}
-
-	pmbase &= 0xFFFFFFFE;
-	if (!pmbase) {
-		printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
-		return;
-	}
-
 	/* Disable IRQs */
 	local_irq_save(flags);
 
@@ -315,10 +329,11 @@
 	cpus_allowed = current->cpus_allowed;
 	set_cpus_allowed(current, policy->cpus);
 
-	/* detect low and high frequency */
+	/* detect low and high frequency and transition latency */
 	result = speedstep_get_freqs(speedstep_processor,
 				     &speedstep_freqs[SPEEDSTEP_LOW].frequency,
 				     &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+				     &policy->cpuinfo.transition_latency,
 				     &speedstep_set_state);
 	set_cpus_allowed(current, cpus_allowed);
 	if (result)
@@ -335,7 +350,6 @@
 
 	/* cpuinfo and default policy values */
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	policy->cur = speed;
 
 	result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
@@ -400,6 +414,9 @@
 		return -EINVAL;
 	}
 
+	if (speedstep_find_register())
+		return -ENODEV;
+
 	return cpufreq_register_driver(&speedstep_driver);
 }
 
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index d368b3f..7c47005 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -320,11 +320,13 @@
 unsigned int speedstep_get_freqs(unsigned int processor,
 				  unsigned int *low_speed,
 				  unsigned int *high_speed,
+				  unsigned int *transition_latency,
 				  void (*set_state) (unsigned int state))
 {
 	unsigned int prev_speed;
 	unsigned int ret = 0;
 	unsigned long flags;
+	struct timeval tv1, tv2;
 
 	if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
 		return -EINVAL;
@@ -337,7 +339,7 @@
 		return -EIO;
 
 	dprintk("previous speed is %u\n", prev_speed);
-	
+
 	local_irq_save(flags);
 
 	/* switch to low state */
@@ -350,8 +352,17 @@
 
 	dprintk("low speed is %u\n", *low_speed);
 
+	/* start latency measurement */
+	if (transition_latency)
+		do_gettimeofday(&tv1);
+
 	/* switch to high state */
 	set_state(SPEEDSTEP_HIGH);
+
+	/* end latency measurement */
+	if (transition_latency)
+		do_gettimeofday(&tv2);
+
 	*high_speed = speedstep_get_processor_frequency(processor);
 	if (!*high_speed) {
 		ret = -EIO;
@@ -369,6 +380,25 @@
 	if (*high_speed != prev_speed)
 		set_state(SPEEDSTEP_LOW);
 
+	if (transition_latency) {
+		*transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC +
+			tv2.tv_usec - tv1.tv_usec;
+		dprintk("transition latency is %u uSec\n", *transition_latency);
+
+		/* convert uSec to nSec and add 20% for safety reasons */
+		*transition_latency *= 1200;
+
+		/* check if the latency measurement is too high or too low
+		 * and set it to a safe value (500uSec) in that case
+		 */
+		if (*transition_latency > 10000000 || *transition_latency < 50000) {
+			printk (KERN_WARNING "speedstep: frequency transition measured seems out of "
+					"range (%u nSec), falling back to a safe one of %u nSec.\n",
+					*transition_latency, 500000);
+			*transition_latency = 500000;
+		}
+	}
+
  out:
 	local_irq_restore(flags);
 	return (ret);
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
index 261a2c9..6a727fd 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
@@ -44,4 +44,5 @@
 extern unsigned int speedstep_get_freqs(unsigned int processor,
 	  unsigned int *low_speed,
 	  unsigned int *high_speed,
+	  unsigned int *transition_latency,
 	  void (*set_state) (unsigned int state));
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index 2718fb6..28cc5d5 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -269,6 +269,7 @@
 		result = speedstep_get_freqs(speedstep_processor,
 				&speedstep_freqs[SPEEDSTEP_LOW].frequency,
 				&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+				NULL,
 				&speedstep_set_state);
 
 		if (result) {
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index e792131..6d91b27 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -3,6 +3,7 @@
 #include <linux/string.h>
 #include <asm/semaphore.h>
 #include <linux/seq_file.h>
+#include <linux/cpufreq.h>
 
 /*
  *	Get CPU information for use by the procfs.
@@ -86,8 +87,11 @@
 		seq_printf(m, "stepping\t: unknown\n");
 
 	if ( cpu_has(c, X86_FEATURE_TSC) ) {
+		unsigned int freq = cpufreq_quick_get(n);
+		if (!freq)
+			freq = cpu_khz;
 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
-			cpu_khz / 1000, (cpu_khz % 1000));
+			freq / 1000, (freq % 1000));
 	}
 
 	/* Cache size */
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 5add0bc..088e5dd 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -43,6 +43,7 @@
 #include <linux/initrd.h>
 #include <linux/platform.h>
 #include <linux/pm.h>
+#include <linux/cpufreq.h>
 
 #include <asm/ia32.h>
 #include <asm/machvec.h>
@@ -517,6 +518,7 @@
 	char family[32], features[128], *cp, sep;
 	struct cpuinfo_ia64 *c = v;
 	unsigned long mask;
+	unsigned int proc_freq;
 	int i;
 
 	mask = c->features;
@@ -549,6 +551,10 @@
 		sprintf(cp, " 0x%lx", mask);
 	}
 
+	proc_freq = cpufreq_quick_get(cpunum);
+	if (!proc_freq)
+		proc_freq = c->proc_freq / 1000;
+
 	seq_printf(m,
 		   "processor  : %d\n"
 		   "vendor     : %s\n"
@@ -565,7 +571,7 @@
 		   "BogoMIPS   : %lu.%02lu\n",
 		   cpunum, c->vendor, family, c->model, c->revision, c->archrev,
 		   features, c->ppn, c->number,
-		   c->proc_freq / 1000000, c->proc_freq % 1000000,
+		   proc_freq / 1000, proc_freq % 1000,
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
 		   lpj*HZ/500000, (lpj*HZ/5000) % 100);
 #ifdef CONFIG_SMP
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 330cf84..60353f5 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -420,7 +420,7 @@
 		goto out;
 	pos = merge_64(a4, a5);
 	ret = rw_verify_area(READ, file, &pos, count);
-	if (ret)
+	if (ret < 0)
 		goto out;
 	ret = -EINVAL;
 	if (!file->f_op || !(read = file->f_op->read))
@@ -455,7 +455,7 @@
 		goto out;
 	pos = merge_64(a4, a5);
 	ret = rw_verify_area(WRITE, file, &pos, count);
-	if (ret)
+	if (ret < 0)
 		goto out;
 	ret = -EINVAL;
 	if (!file->f_op || !(write = file->f_op->write))
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 750e01d..64c4534 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -42,6 +42,7 @@
 #include <linux/edd.h>
 #include <linux/mmzone.h>
 #include <linux/kexec.h>
+#include <linux/cpufreq.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -1256,8 +1257,11 @@
 		seq_printf(m, "stepping\t: unknown\n");
 	
 	if (cpu_has(c,X86_FEATURE_TSC)) {
+		unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
+		if (!freq)
+			freq = cpu_khz;
 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
-			     cpu_khz / 1000, (cpu_khz % 1000));
+			     freq / 1000, (freq % 1000));
 	}
 
 	/* Cache size */
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 7b1cd93..c4b9d2a 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -358,7 +358,8 @@
 	  This driver supports certain USB attached storage devices
 	  such as flash keys.
 
-	  Warning: Enabling this cripples the usb-storage driver.
+	  If you enable this driver, it is recommended to avoid conflicts
+	  with usb-storage by enabling USB_LIBUSUAL.
 
 	  If unsure, say N.
 
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index bfb23d5..10740a0 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -9,7 +9,6 @@
  *
  * TODO (sorted by decreasing priority)
  *  -- Kill first_open (Al Viro fixed the block layer now)
- *  -- Do resets with usb_device_reset (needs a thread context, use khubd)
  *  -- set readonly flag for CDs, set removable flag for CF readers
  *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
  *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
@@ -29,6 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/usb_usual.h>
 #include <linux/blkdev.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/timer.h>
@@ -107,16 +107,6 @@
  */
 
 /*
- * Definitions which have to be scattered once we understand the layout better.
- */
-
-/* Transport (despite PR in the name) */
-#define US_PR_BULK	0x50		/* bulk only */
-
-/* Protocol */
-#define US_SC_SCSI	0x06		/* Transparent */
-
-/*
  * This many LUNs per USB device.
  * Every one of them takes a host, see UB_MAX_HOSTS.
  */
@@ -125,7 +115,7 @@
 /*
  */
 
-#define UB_MINORS_PER_MAJOR	8
+#define UB_PARTS_PER_LUN      8
 
 #define UB_MAX_CDB_SIZE      16		/* Corresponds to Bulk */
 
@@ -245,6 +235,13 @@
 	void *back;
 };
 
+struct ub_request {
+	struct request *rq;
+	unsigned int current_try;
+	unsigned int nsg;		/* sgv[nsg] */
+	struct scatterlist sgv[UB_MAX_REQ_SG];
+};
+
 /*
  */
 struct ub_capacity {
@@ -340,6 +337,8 @@
 	int readonly;
 	int first_open;			/* Kludge. See ub_bd_open. */
 
+	struct ub_request urq;
+
 	/* Use Ingo's mempool if or when we have more than one command. */
 	/*
 	 * Currently we never need more than one command for the whole device.
@@ -360,6 +359,7 @@
 	atomic_t poison;		/* The USB device is disconnected */
 	int openc;			/* protected by ub_lock! */
 					/* kref is too implicit for our taste */
+	int reset;			/* Reset is running */
 	unsigned int tagcnt;
 	char name[12];
 	struct usb_device *dev;
@@ -387,6 +387,9 @@
 	struct bulk_cs_wrap work_bcs;
 	struct usb_ctrlrequest work_cr;
 
+	struct work_struct reset_work;
+	wait_queue_head_t reset_wait;
+
 	int sg_stat[6];
 	struct ub_scsi_trace tr;
 };
@@ -395,12 +398,14 @@
  */
 static void ub_cleanup(struct ub_dev *sc);
 static int ub_request_fn_1(struct ub_lun *lun, struct request *rq);
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq);
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq);
+static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq);
+static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static void ub_end_rq(struct request *rq, int uptodate);
+static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_request *urq, struct ub_scsi_cmd *cmd);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
 static void ub_scsi_action(unsigned long _dev);
@@ -415,6 +420,8 @@
 static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     int stalled_pipe);
 static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
+static void ub_reset_enter(struct ub_dev *sc);
+static void ub_reset_task(void *arg);
 static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
 static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_capacity *ret);
@@ -422,13 +429,18 @@
 
 /*
  */
+#ifdef CONFIG_USB_LIBUSUAL
+
+#define ub_usb_ids  storage_usb_ids
+#else
+
 static struct usb_device_id ub_usb_ids[] = {
-	// { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) },	/* SDDR-31 */
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
 	{ }
 };
 
 MODULE_DEVICE_TABLE(usb, ub_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */
 
 /*
  * Find me a way to identify "next free minor" for add_disk(),
@@ -522,6 +534,9 @@
 	spin_lock_irqsave(&sc->lock, flags);
 
 	cnt += sprintf(page + cnt,
+	    "poison %d reset %d\n",
+	    atomic_read(&sc->poison), sc->reset);
+	cnt += sprintf(page + cnt,
 	    "qlen %d qmax %d\n",
 	    sc->cmd_queue.qlen, sc->cmd_queue.qmax);
 	cnt += sprintf(page + cnt,
@@ -770,7 +785,8 @@
 {
 	struct ub_dev *sc = lun->udev;
 	struct ub_scsi_cmd *cmd;
-	int rc;
+	struct ub_request *urq;
+	int n_elem;
 
 	if (atomic_read(&sc->poison) || lun->changed) {
 		blkdev_dequeue_request(rq);
@@ -778,66 +794,71 @@
 		return 0;
 	}
 
+	if (lun->urq.rq != NULL)
+		return -1;
 	if ((cmd = ub_get_cmd(lun)) == NULL)
 		return -1;
 	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
 
 	blkdev_dequeue_request(rq);
-	if (blk_pc_request(rq)) {
-		rc = ub_cmd_build_packet(sc, lun, cmd, rq);
-	} else {
-		rc = ub_cmd_build_block(sc, lun, cmd, rq);
-	}
-	if (rc != 0) {
-		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
-		return 0;
-	}
-	cmd->state = UB_CMDST_INIT;
-	cmd->lun = lun;
-	cmd->done = ub_rw_cmd_done;
-	cmd->back = rq;
 
-	cmd->tag = sc->tagcnt++;
-	if (ub_submit_scsi(sc, cmd) != 0) {
-		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
-		return 0;
-	}
-
-	return 0;
-}
-
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq)
-{
-	int ub_dir;
-	int n_elem;
-	unsigned int block, nblks;
-
-	if (rq_data_dir(rq) == WRITE)
-		ub_dir = UB_DIR_WRITE;
-	else
-		ub_dir = UB_DIR_READ;
-	cmd->dir = ub_dir;
+	urq = &lun->urq;
+	memset(urq, 0, sizeof(struct ub_request));
+	urq->rq = rq;
 
 	/*
 	 * get scatterlist from block layer
 	 */
-	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
-	if (n_elem <= 0) {
+	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
+	if (n_elem < 0) {
 		printk(KERN_INFO "%s: failed request map (%d)\n",
-		    sc->name, n_elem); /* P3 */
-		return -1;		/* request with no s/g entries? */
+		    lun->name, n_elem); /* P3 */
+		goto drop;
 	}
 	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
 		printk(KERN_WARNING "%s: request with %d segments\n",
-		    sc->name, n_elem);
-		return -1;
+		    lun->name, n_elem);
+		goto drop;
 	}
-	cmd->nsg = n_elem;
+	urq->nsg = n_elem;
 	sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
 
+	if (blk_pc_request(rq)) {
+		ub_cmd_build_packet(sc, lun, cmd, urq);
+	} else {
+		ub_cmd_build_block(sc, lun, cmd, urq);
+	}
+	cmd->state = UB_CMDST_INIT;
+	cmd->lun = lun;
+	cmd->done = ub_rw_cmd_done;
+	cmd->back = urq;
+
+	cmd->tag = sc->tagcnt++;
+	if (ub_submit_scsi(sc, cmd) != 0)
+		goto drop;
+
+	return 0;
+
+drop:
+	ub_put_cmd(lun, cmd);
+	ub_end_rq(rq, 0);
+	return 0;
+}
+
+static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq)
+{
+	struct request *rq = urq->rq;
+	unsigned int block, nblks;
+
+	if (rq_data_dir(rq) == WRITE)
+		cmd->dir = UB_DIR_WRITE;
+	else
+		cmd->dir = UB_DIR_READ;
+
+	cmd->nsg = urq->nsg;
+	memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
+
 	/*
 	 * build the command
 	 *
@@ -847,7 +868,7 @@
 	block = rq->sector >> lun->capacity.bshift;
 	nblks = rq->nr_sectors >> lun->capacity.bshift;
 
-	cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
+	cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10;
 	/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
 	cmd->cdb[2] = block >> 24;
 	cmd->cdb[3] = block >> 16;
@@ -858,14 +879,12 @@
 	cmd->cdb_len = 10;
 
 	cmd->len = rq->nr_sectors * 512;
-
-	return 0;
 }
 
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq)
+static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq)
 {
-	int n_elem;
+	struct request *rq = urq->rq;
 
 	if (rq->data_len == 0) {
 		cmd->dir = UB_DIR_NONE;
@@ -874,40 +893,26 @@
 			cmd->dir = UB_DIR_WRITE;
 		else
 			cmd->dir = UB_DIR_READ;
-
 	}
 
-	/*
-	 * get scatterlist from block layer
-	 */
-	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
-	if (n_elem < 0) {
-		printk(KERN_INFO "%s: failed request map (%d)\n",
-		    sc->name, n_elem); /* P3 */
-		return -1;
-	}
-	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
-		printk(KERN_WARNING "%s: request with %d segments\n",
-		    sc->name, n_elem);
-		return -1;
-	}
-	cmd->nsg = n_elem;
-	sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+	cmd->nsg = urq->nsg;
+	memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
 
 	memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
 	cmd->cdb_len = rq->cmd_len;
 
 	cmd->len = rq->data_len;
-
-	return 0;
 }
 
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
-	struct request *rq = cmd->back;
 	struct ub_lun *lun = cmd->lun;
+	struct ub_request *urq = cmd->back;
+	struct request *rq;
 	int uptodate;
 
+	rq = urq->rq;
+
 	if (cmd->error == 0) {
 		uptodate = 1;
 
@@ -928,9 +933,16 @@
 				rq->errors = SAM_STAT_CHECK_CONDITION;
 			else
 				rq->errors = DID_ERROR << 16;
+		} else {
+			if (cmd->error == -EIO) {
+				if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
+					return;
+			}
 		}
 	}
 
+	urq->rq = NULL;
+
 	ub_put_cmd(lun, cmd);
 	ub_end_rq(rq, uptodate);
 	blk_start_queue(lun->disk->queue);
@@ -938,13 +950,45 @@
 
 static void ub_end_rq(struct request *rq, int uptodate)
 {
-	int rc;
-
-	rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
-	// assert(rc == 0);
+	end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
 	end_that_request_last(rq);
 }
 
+static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_request *urq, struct ub_scsi_cmd *cmd)
+{
+
+	if (atomic_read(&sc->poison))
+		return -ENXIO;
+
+	ub_reset_enter(sc);
+
+	if (urq->current_try >= 3)
+		return -EIO;
+	urq->current_try++;
+	/* P3 */ printk("%s: dir %c len/act %d/%d "
+	    "[sense %x %02x %02x] retry %d\n",
+	    sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len,
+	    cmd->key, cmd->asc, cmd->ascq, urq->current_try);
+
+	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+	ub_cmd_build_block(sc, lun, cmd, urq);
+
+	cmd->state = UB_CMDST_INIT;
+	cmd->lun = lun;
+	cmd->done = ub_rw_cmd_done;
+	cmd->back = urq;
+
+	cmd->tag = sc->tagcnt++;
+
+#if 0 /* Wasteful */
+	return ub_submit_scsi(sc, cmd);
+#else
+	ub_cmdq_add(sc, cmd);
+	return 0;
+#endif
+}
+
 /*
  * Submit a regular SCSI operation (not an auto-sense).
  *
@@ -1075,7 +1119,7 @@
 	struct ub_scsi_cmd *cmd;
 	int rc;
 
-	while ((cmd = ub_cmdq_peek(sc)) != NULL) {
+	while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) {
 		if (cmd->state == UB_CMDST_DONE) {
 			ub_cmdq_pop(sc);
 			(*cmd->done)(sc, cmd);
@@ -1098,11 +1142,12 @@
 {
 	struct urb *urb = &sc->work_urb;
 	struct bulk_cs_wrap *bcs;
+	int len;
 	int rc;
 
 	if (atomic_read(&sc->poison)) {
-		/* A little too simplistic, I feel... */
-		goto Bad_End;
+		ub_state_done(sc, cmd, -ENODEV);
+		return;
 	}
 
 	if (cmd->state == UB_CMDST_CLEAR) {
@@ -1110,7 +1155,6 @@
 			/*
 			 * STALL while clearning STALL.
 			 * The control pipe clears itself - nothing to do.
-			 * XXX Might try to reset the device here and retry.
 			 */
 			printk(KERN_NOTICE "%s: stall on control pipe\n",
 			    sc->name);
@@ -1129,11 +1173,6 @@
 
 	} else if (cmd->state == UB_CMDST_CLR2STS) {
 		if (urb->status == -EPIPE) {
-			/*
-			 * STALL while clearning STALL.
-			 * The control pipe clears itself - nothing to do.
-			 * XXX Might try to reset the device here and retry.
-			 */
 			printk(KERN_NOTICE "%s: stall on control pipe\n",
 			    sc->name);
 			goto Bad_End;
@@ -1151,11 +1190,6 @@
 
 	} else if (cmd->state == UB_CMDST_CLRRS) {
 		if (urb->status == -EPIPE) {
-			/*
-			 * STALL while clearning STALL.
-			 * The control pipe clears itself - nothing to do.
-			 * XXX Might try to reset the device here and retry.
-			 */
 			printk(KERN_NOTICE "%s: stall on control pipe\n",
 			    sc->name);
 			goto Bad_End;
@@ -1172,7 +1206,12 @@
 		ub_state_stat_counted(sc, cmd);
 
 	} else if (cmd->state == UB_CMDST_CMD) {
-		if (urb->status == -EPIPE) {
+		switch (urb->status) {
+		case 0:
+			break;
+		case -EOVERFLOW:
+			goto Bad_End;
+		case -EPIPE:
 			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
 			if (rc != 0) {
 				printk(KERN_NOTICE "%s: "
@@ -1182,17 +1221,20 @@
 				 * This is typically ENOMEM or some other such shit.
 				 * Retrying is pointless. Just do Bad End on it...
 				 */
-				goto Bad_End;
+				ub_state_done(sc, cmd, rc);
+				return;
 			}
 			cmd->state = UB_CMDST_CLEAR;
 			ub_cmdtr_state(sc, cmd);
 			return;
-		}
-		if (urb->status != 0) {
+		case -ESHUTDOWN:	/* unplug */
+		case -EILSEQ:		/* unplug timeout on uhci */
+			ub_state_done(sc, cmd, -ENODEV);
+			return;
+		default:
 			goto Bad_End;
 		}
 		if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
-			/* XXX Must do reset here to unconfuse the device */
 			goto Bad_End;
 		}
 
@@ -1211,11 +1253,8 @@
 				printk(KERN_NOTICE "%s: "
 				    "unable to submit clear (%d)\n",
 				    sc->name, rc);
-				/*
-				 * This is typically ENOMEM or some other such shit.
-				 * Retrying is pointless. Just do Bad End on it...
-				 */
-				goto Bad_End;
+				ub_state_done(sc, cmd, rc);
+				return;
 			}
 			cmd->state = UB_CMDST_CLR2STS;
 			ub_cmdtr_state(sc, cmd);
@@ -1224,14 +1263,50 @@
 		if (urb->status == -EOVERFLOW) {
 			/*
 			 * A babble? Failure, but we must transfer CSW now.
-			 * XXX This is going to end in perpetual babble. Reset.
 			 */
 			cmd->error = -EOVERFLOW;	/* A cheap trick... */
 			ub_state_stat(sc, cmd);
 			return;
 		}
-		if (urb->status != 0)
-			goto Bad_End;
+
+		if (cmd->dir == UB_DIR_WRITE) {
+			/*
+			 * Do not continue writes in case of a failure.
+			 * Doing so would cause sectors to be mixed up,
+			 * which is worse than sectors lost.
+			 *
+			 * We must try to read the CSW, or many devices
+			 * get confused.
+			 */
+			len = urb->actual_length;
+			if (urb->status != 0 ||
+			    len != cmd->sgv[cmd->current_sg].length) {
+				cmd->act_len += len;
+				ub_cmdtr_act_len(sc, cmd);
+
+				cmd->error = -EIO;
+				ub_state_stat(sc, cmd);
+				return;
+			}
+
+		} else {
+			/*
+			 * If an error occurs on read, we record it, and
+			 * continue to fetch data in order to avoid bubble.
+			 *
+			 * As a small shortcut, we stop if we detect that
+			 * a CSW mixed into data.
+			 */
+			if (urb->status != 0)
+				cmd->error = -EIO;
+
+			len = urb->actual_length;
+			if (urb->status != 0 ||
+			    len != cmd->sgv[cmd->current_sg].length) {
+				if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN)
+					goto Bad_End;
+			}
+		}
 
 		cmd->act_len += urb->actual_length;
 		ub_cmdtr_act_len(sc, cmd);
@@ -1249,11 +1324,8 @@
 				printk(KERN_NOTICE "%s: "
 				    "unable to submit clear (%d)\n",
 				    sc->name, rc);
-				/*
-				 * This is typically ENOMEM or some other such shit.
-				 * Retrying is pointless. Just do Bad End on it...
-				 */
-				goto Bad_End;
+				ub_state_done(sc, cmd, rc);
+				return;
 			}
 
 			/*
@@ -1266,14 +1338,8 @@
 			ub_cmdtr_state(sc, cmd);
 			return;
 		}
-		if (urb->status == -EOVERFLOW) {
-			/*
-			 * XXX We are screwed here. Retrying is pointless,
-			 * because the pipelined data will not get in until
-			 * we read with a big enough buffer. We must reset XXX.
-			 */
-			goto Bad_End;
-		}
+
+		/* Catch everything, including -EOVERFLOW and other nasties. */
 		if (urb->status != 0)
 			goto Bad_End;
 
@@ -1319,15 +1385,15 @@
 			return;
 		}
 
-		rc = le32_to_cpu(bcs->Residue);
-		if (rc != cmd->len - cmd->act_len) {
+		len = le32_to_cpu(bcs->Residue);
+		if (len != cmd->len - cmd->act_len) {
 			/*
 			 * It is all right to transfer less, the caller has
 			 * to check. But it's not all right if the device
 			 * counts disagree with our counts.
 			 */
 			/* P3 */ printk("%s: resid %d len %d act %d\n",
-			    sc->name, rc, cmd->len, cmd->act_len);
+			    sc->name, len, cmd->len, cmd->act_len);
 			goto Bad_End;
 		}
 
@@ -1338,13 +1404,13 @@
 			ub_state_sense(sc, cmd);
 			return;
 		case US_BULK_STAT_PHASE:
-			/* XXX We must reset the transport here */
 			/* P3 */ printk("%s: status PHASE\n", sc->name);
 			goto Bad_End;
 		default:
 			printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
 			    sc->name, bcs->Status);
-			goto Bad_End;
+			ub_state_done(sc, cmd, -EINVAL);
+			return;
 		}
 
 		/* Not zeroing error to preserve a babble indicator */
@@ -1364,7 +1430,8 @@
 		printk(KERN_WARNING "%s: "
 		    "wrong command state %d\n",
 		    sc->name, cmd->state);
-		goto Bad_End;
+		ub_state_done(sc, cmd, -EINVAL);
+		return;
 	}
 	return;
 
@@ -1612,6 +1679,93 @@
 }
 
 /*
+ * Reset management
+ */
+
+static void ub_reset_enter(struct ub_dev *sc)
+{
+
+	if (sc->reset) {
+		/* This happens often on multi-LUN devices. */
+		return;
+	}
+	sc->reset = 1;
+
+#if 0 /* Not needed because the disconnect waits for us. */
+	unsigned long flags;
+	spin_lock_irqsave(&ub_lock, flags);
+	sc->openc++;
+	spin_unlock_irqrestore(&ub_lock, flags);
+#endif
+
+#if 0 /* We let them stop themselves. */
+	struct list_head *p;
+	struct ub_lun *lun;
+	list_for_each(p, &sc->luns) {
+		lun = list_entry(p, struct ub_lun, link);
+		blk_stop_queue(lun->disk->queue);
+	}
+#endif
+
+	schedule_work(&sc->reset_work);
+}
+
+static void ub_reset_task(void *arg)
+{
+	struct ub_dev *sc = arg;
+	unsigned long flags;
+	struct list_head *p;
+	struct ub_lun *lun;
+	int lkr, rc;
+
+	if (!sc->reset) {
+		printk(KERN_WARNING "%s: Running reset unrequested\n",
+		    sc->name);
+		return;
+	}
+
+	if (atomic_read(&sc->poison)) {
+		printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
+		    sc->name); /* P3 This floods. Remove soon. XXX */
+	} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
+		printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
+		    sc->name); /* P3 This floods. Remove soon. XXX */
+	} else {
+		if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
+			printk(KERN_NOTICE
+			    "%s: usb_lock_device_for_reset failed (%d)\n",
+			    sc->name, lkr);
+		} else {
+			rc = usb_reset_device(sc->dev);
+			if (rc < 0) {
+				printk(KERN_NOTICE "%s: "
+				    "usb_lock_device_for_reset failed (%d)\n",
+				    sc->name, rc);
+			}
+
+			if (lkr)
+				usb_unlock_device(sc->dev);
+		}
+	}
+
+	/*
+	 * In theory, no commands can be running while reset is active,
+	 * so nobody can ask for another reset, and so we do not need any
+	 * queues of resets or anything. We do need a spinlock though,
+	 * to interact with block layer.
+	 */
+	spin_lock_irqsave(&sc->lock, flags);
+	sc->reset = 0;
+	tasklet_schedule(&sc->tasklet);
+	list_for_each(p, &sc->luns) {
+		lun = list_entry(p, struct ub_lun, link);
+		blk_start_queue(lun->disk->queue);
+	}
+	wake_up(&sc->reset_wait);
+	spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+/*
  * This is called from a process context.
  */
 static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
@@ -2146,7 +2300,7 @@
 	if (ep_in == NULL || ep_out == NULL) {
 		printk(KERN_NOTICE "%s: failed endpoint check\n",
 		    sc->name);
-		return -EIO;
+		return -ENODEV;
 	}
 
 	/* Calculate and store the pipe values */
@@ -2172,6 +2326,9 @@
 	int rc;
 	int i;
 
+	if (usb_usual_check_type(dev_id, USB_US_TYPE_UB))
+		return -ENXIO;
+
 	rc = -ENOMEM;
 	if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
 		goto err_core;
@@ -2181,6 +2338,8 @@
 	usb_init_urb(&sc->work_urb);
 	tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
 	atomic_set(&sc->poison, 0);
+	INIT_WORK(&sc->reset_work, ub_reset_task, sc);
+	init_waitqueue_head(&sc->reset_wait);
 
 	init_timer(&sc->work_timer);
 	sc->work_timer.data = (unsigned long) sc;
@@ -2201,7 +2360,8 @@
 
 	/* XXX Verify that we can handle the device (from descriptors) */
 
-	ub_get_pipes(sc, sc->dev, intf);
+	if (ub_get_pipes(sc, sc->dev, intf) != 0)
+		goto err_dev_desc;
 
 	if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
 		goto err_diag;
@@ -2272,6 +2432,7 @@
 
 	/* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
 err_diag:
+err_dev_desc:
 	usb_set_intfdata(intf, NULL);
 	// usb_put_intf(sc->intf);
 	usb_put_dev(sc->dev);
@@ -2309,14 +2470,14 @@
 	ub_revalidate(sc, lun);
 
 	rc = -ENOMEM;
-	if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
+	if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL)
 		goto err_diskalloc;
 
 	lun->disk = disk;
 	sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
 	sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
 	disk->major = UB_MAJOR;
-	disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
+	disk->first_minor = lun->id * UB_PARTS_PER_LUN;
 	disk->fops = &ub_bd_fops;
 	disk->private_data = lun;
 	disk->driverfs_dev = &sc->intf->dev;
@@ -2380,6 +2541,11 @@
 	atomic_set(&sc->poison, 1);
 
 	/*
+	 * Wait for reset to end, if any.
+	 */
+	wait_event(sc->reset_wait, !sc->reset);
+
+	/*
 	 * Blow away queued commands.
 	 *
 	 * Actually, this never works, because before we get here
@@ -2392,7 +2558,7 @@
 	{
 		struct ub_scsi_cmd *cmd;
 		int cnt = 0;
-		while ((cmd = ub_cmdq_pop(sc)) != NULL) {
+		while ((cmd = ub_cmdq_peek(sc)) != NULL) {
 			cmd->error = -ENOTCONN;
 			cmd->state = UB_CMDST_DONE;
 			ub_cmdtr_state(sc, cmd);
@@ -2461,7 +2627,6 @@
 }
 
 static struct usb_driver ub_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ub",
 	.probe =	ub_probe,
 	.disconnect =	ub_disconnect,
@@ -2479,6 +2644,7 @@
 	if ((rc = usb_register(&ub_driver)) != 0)
 		goto err_register;
 
+	usb_usual_set_present(USB_US_TYPE_UB);
 	return 0;
 
 err_register:
@@ -2494,6 +2660,7 @@
 
 	devfs_remove(DEVFS_NAME);
 	unregister_blkdev(UB_MAJOR, DRV_NAME);
+	usb_usual_clear_present(USB_US_TYPE_UB);
 }
 
 module_init(ub_init);
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 8e7fb35..3e7a067 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -275,7 +275,6 @@
 }
 
 static struct usb_driver bcm203x_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "bcm203x",
 	.probe		= bcm203x_probe,
 	.disconnect	= bcm203x_disconnect,
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 067e278..8947c88 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -768,7 +768,6 @@
 }
 
 static struct usb_driver bfusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "bfusb",
 	.probe		= bfusb_probe,
 	.disconnect	= bfusb_disconnect,
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 3947963..9446960 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -619,7 +619,6 @@
 }
 
 static struct usb_driver bpa10x_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "bpa10x",
 	.probe		= bpa10x_probe,
 	.disconnect	= bpa10x_disconnect,
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 057cb2b..92382e8 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -1044,7 +1044,6 @@
 }
 
 static struct usb_driver hci_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "hci_usb",
 	.probe		= hci_usb_probe,
 	.disconnect	= hci_usb_disconnect,
diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h
index e9b87a7..00342a6 100644
--- a/drivers/char/ip2/i2pack.h
+++ b/drivers/char/ip2/i2pack.h
@@ -358,7 +358,7 @@
 #define MB_OUT_STRIPPED    0x40  // Board has read all output from fifo 
 #define MB_FATAL_ERROR     0x20  // Board has encountered a fatal error
 
-#pragma pack(4)                  // Reset padding to command-line default
+#pragma pack()                  // Reset padding to command-line default
 
 #endif      // I2PACK_H
 
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 092e9b1..1533f56 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -151,7 +151,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver usb_pcwd_driver = {
-	.owner =	THIS_MODULE,
 	.name =		DRIVER_NAME,
 	.probe =	usb_pcwd_probe,
 	.disconnect =	usb_pcwd_disconnect,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 815902c..a9163d0 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -823,6 +823,30 @@
 
 
 /** 
+ * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur
+ * @cpu: CPU number
+ *
+ * This is the last known freq, without actually getting it from the driver.
+ * Return value will be same as what is shown in scaling_cur_freq in sysfs.
+ */
+unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	unsigned int ret = 0;
+
+	if (policy) {
+		down(&policy->lock);
+		ret = policy->cur;
+		up(&policy->lock);
+		cpufreq_cpu_put(policy);
+	}
+
+	return (ret);
+}
+EXPORT_SYMBOL(cpufreq_quick_get);
+
+
+/** 
  * cpufreq_get - get the current CPU frequency (in kHz)
  * @cpu: CPU number
  *
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 2ed5c43..39543a2 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -93,7 +93,7 @@
 {
 	return	kstat_cpu(cpu).cpustat.idle +
 		kstat_cpu(cpu).cpustat.iowait +
-		( !dbs_tuners_ins.ignore_nice ? 
+		( dbs_tuners_ins.ignore_nice ?
 		  kstat_cpu(cpu).cpustat.nice :
 		  0);
 }
@@ -127,7 +127,7 @@
 show_one(sampling_down_factor, sampling_down_factor);
 show_one(up_threshold, up_threshold);
 show_one(down_threshold, down_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(ignore_nice_load, ignore_nice);
 show_one(freq_step, freq_step);
 
 static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, 
@@ -207,7 +207,7 @@
 	return count;
 }
 
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
 		const char *buf, size_t count)
 {
 	unsigned int input;
@@ -272,7 +272,7 @@
 define_one_rw(sampling_down_factor);
 define_one_rw(up_threshold);
 define_one_rw(down_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(ignore_nice_load);
 define_one_rw(freq_step);
 
 static struct attribute * dbs_attributes[] = {
@@ -282,7 +282,7 @@
 	&sampling_down_factor.attr,
 	&up_threshold.attr,
 	&down_threshold.attr,
-	&ignore_nice.attr,
+	&ignore_nice_load.attr,
 	&freq_step.attr,
 	NULL
 };
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 1774111..e69fd8d 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -89,7 +89,7 @@
 {
 	return	kstat_cpu(cpu).cpustat.idle +
 		kstat_cpu(cpu).cpustat.iowait +
-		( !dbs_tuners_ins.ignore_nice ? 
+		( dbs_tuners_ins.ignore_nice ?
 		  kstat_cpu(cpu).cpustat.nice :
 		  0);
 }
@@ -122,7 +122,7 @@
 show_one(sampling_rate, sampling_rate);
 show_one(sampling_down_factor, sampling_down_factor);
 show_one(up_threshold, up_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(ignore_nice_load, ignore_nice);
 
 static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, 
 		const char *buf, size_t count)
@@ -182,7 +182,7 @@
 	return count;
 }
 
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
 		const char *buf, size_t count)
 {
 	unsigned int input;
@@ -223,7 +223,7 @@
 define_one_rw(sampling_rate);
 define_one_rw(sampling_down_factor);
 define_one_rw(up_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(ignore_nice_load);
 
 static struct attribute * dbs_attributes[] = {
 	&sampling_rate_max.attr,
@@ -231,7 +231,7 @@
 	&sampling_rate.attr,
 	&sampling_down_factor.attr,
 	&up_threshold.attr,
-	&ignore_nice.attr,
+	&ignore_nice_load.attr,
 	NULL
 };
 
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 64b4a30..bc2fce6 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -235,7 +235,6 @@
 MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
 
 struct usb_driver iforce_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"iforce",
 	.probe =	iforce_usb_probe,
 	.disconnect =	iforce_usb_disconnect,
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index f8457ef..ca5b4a3 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1715,7 +1715,6 @@
 /* our driver information structure */
 /************************************/
 static struct usb_driver hfc_drv = {
-	.owner = THIS_MODULE,
 	.name  = "hfc_usb",
 	.id_table = hfcusb_idtab,
 	.probe = hfc_usb_probe,
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 8e192a3..99cb0f3 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -180,7 +180,6 @@
 MODULE_DEVICE_TABLE (usb, st5481_ids);
 
 static struct usb_driver st5481_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"st5481_usb",
 	.probe =	probe_st5481,
 	.disconnect =	disconnect_st5481,
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 0a78ba3..a6c91db 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -544,7 +544,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver flexcop_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "b2c2_flexcop_usb",
 	.probe		= flexcop_usb_probe,
 	.disconnect = flexcop_usb_disconnect,
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 336fc28..b996fb5 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -986,7 +986,6 @@
 MODULE_DEVICE_TABLE(usb, cinergyt2_table);
 
 static struct usb_driver cinergyt2_driver = {
-	.owner	= THIS_MODULE,
 	.name	= "cinergyT2",
 	.probe	= cinergyt2_probe,
 	.disconnect	= cinergyt2_disconnect,
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index 8c7beff..ce44aa6 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -144,7 +144,6 @@
 };
 
 static struct usb_driver a800_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_a800",
 	.probe		= a800_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 3fe383f..d05fab0 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -241,7 +241,6 @@
 };
 
 static struct usb_driver cxusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_cxusb",
 	.probe		= cxusb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index aa271a2..52ac3e5 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -373,7 +373,6 @@
 };
 
 static struct usb_driver dibusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_dibusb_mb",
 	.probe		= dibusb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index 6a0912e..55802fb 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -82,7 +82,6 @@
 };
 
 static struct usb_driver dibusb_mc_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_dibusb_mc",
 	.probe		= dibusb_mc_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index f98e306..450417a 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -233,7 +233,6 @@
 };
 
 static struct usb_driver digitv_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_digitv",
 	.probe		= digitv_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index b595476..6e2bac8 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -198,7 +198,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver dtt200u_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_dtt200u",
 	.probe		= dtt200u_usb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 1841a66..fac48fc 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -202,7 +202,6 @@
 };
 
 static struct usb_driver nova_t_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_nova_t_usb2",
 	.probe		= nova_t_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 6fd6765..14f1911 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -128,7 +128,6 @@
 };
 
 static struct usb_driver umt_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_umt_010",
 	.probe		= umt_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index de13c04..afa00fd 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -256,7 +256,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp702x_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb-usb-vp702x",
 	.probe 		= vp702x_usb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 75765e3..3835235 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -253,7 +253,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp7045_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_vp7045",
 	.probe		= vp7045_usb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 9774e94..1439cb7 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -582,7 +582,6 @@
 
 
 static struct usb_driver cpia_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "cpia",
 	.probe		= cpia_probe,
 	.disconnect	= cpia_disconnect,
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 06d7687..3a56120 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1884,7 +1884,6 @@
 }
 
 static struct usb_driver em28xx_usb_driver = {
-	.owner = THIS_MODULE,
 	.name = "em28xx",
 	.probe = em28xx_usb_probe,
 	.disconnect = em28xx_usb_disconnect,
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index c22c051..fa176ff 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1539,7 +1539,6 @@
  * USB device callbacks
  */
 static struct usb_driver irda_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "irda-usb",
 	.probe		= irda_usb_probe,
 	.disconnect	= irda_usb_disconnect,
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 3961a75..31867e4 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -1152,7 +1152,6 @@
  * USB device callbacks
  */
 static struct usb_driver irda_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "stir4200",
 	.probe		= stir_probe,
 	.disconnect	= stir_disconnect,
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index a50c2bc..3639c3f 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_USB_PRINTER)	+= class/
 
 obj-$(CONFIG_USB_STORAGE)	+= storage/
+obj-$(CONFIG_USB)		+= storage/
 
 obj-$(CONFIG_USB_AIPTEK)	+= input/
 obj-$(CONFIG_USB_ATI_REMOTE)	+= input/
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index f429862..550ddfa7 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -44,6 +44,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cxacru.
 
+config USB_UEAGLEATM
+	tristate "ADI 930 and eagle USB DSL modem"
+	depends on USB_ATM
+	select FW_LOADER
+	help
+	  Say Y here if you have an ADSL USB modem based on the ADI 930
+	  or eagle chipset. In order to use your modem you will need to
+	  install firmwares and CMV (Command Management Variables); see
+	  <https://gna.org/projects/ueagleatm/> for details.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ueagle-atm.
+
 config USB_XUSBATM
 	tristate "Other USB DSL modem support"
 	depends on USB_ATM
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile
index 8509971..4c4a776 100644
--- a/drivers/usb/atm/Makefile
+++ b/drivers/usb/atm/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_USB_CXACRU)	+= cxacru.o
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= speedtch.o
+obj-$(CONFIG_USB_UEAGLEATM)	+= ueagle-atm.o
 obj-$(CONFIG_USB_ATM)		+= usbatm.o
 obj-$(CONFIG_USB_XUSBATM)	+= xusbatm.o
 
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 9d59dc6..af0a41e 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -853,7 +853,6 @@
 }
 
 static struct usb_driver cxacru_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= cxacru_driver_name,
 	.probe		= cxacru_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index d0cbbb7..b283361 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -659,7 +659,6 @@
 static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *);
 
 static struct usb_driver speedtch_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= speedtch_driver_name,
 	.probe		= speedtch_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
new file mode 100644
index 0000000..7d2a679
--- /dev/null
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -0,0 +1,1820 @@
+/*-
+ * Copyright (c) 2003, 2004
+ *	Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
+ *
+ * Copyright (c) 2005 Matthieu Castet <castet.matthieu@free.fr>
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * GPL license :
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *
+ * HISTORY : some part of the code was base on ueagle 1.3 BSD driver,
+ * Damien Bergamini agree to put his code under a DUAL GPL/BSD license.
+ *
+ * The rest of the code was was rewritten from scratch.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+#include <linux/kthread.h>
+#include <linux/version.h>
+#include <asm/unaligned.h>
+
+#include "usbatm.h"
+
+#define EAGLEUSBVERSION "ueagle 1.1"
+
+
+/*
+ * Debug macros
+ */
+#define uea_dbg(usb_dev, format, args...)	\
+	do { \
+		if (debug >= 1) \
+			dev_dbg(&(usb_dev)->dev, \
+				"[ueagle-atm dbg] %s: " format, \
+					__FUNCTION__, ##args); \
+       } while (0)
+
+#define uea_vdbg(usb_dev, format, args...)	\
+	do { \
+		if (debug >= 2) \
+			dev_dbg(&(usb_dev)->dev, \
+				"[ueagle-atm vdbg]  " format, ##args); \
+       } while (0)
+
+#define uea_enters(usb_dev) \
+	uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
+
+#define uea_leaves(usb_dev) \
+	uea_vdbg(usb_dev, "leaving  %s\n", __FUNCTION__)
+
+#define uea_err(usb_dev, format,args...) \
+	dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
+
+#define uea_warn(usb_dev, format,args...) \
+	dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args)
+
+#define uea_info(usb_dev, format,args...) \
+	dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args)
+
+struct uea_cmvs {
+	u32 address;
+	u16 offset;
+	u32 data;
+} __attribute__ ((packed));
+
+struct uea_softc {
+	struct usb_device *usb_dev;
+	struct usbatm_data *usbatm;
+
+	int modem_index;
+	unsigned int driver_info;
+
+	int booting;
+	int reset;
+
+	wait_queue_head_t sync_q;
+
+	struct task_struct *kthread;
+	u32 data;
+	wait_queue_head_t cmv_ack_wait;
+	int cmv_ack;
+
+	struct work_struct task;
+	u16 pageno;
+	u16 ovl;
+
+	const struct firmware *dsp_firm;
+	struct urb *urb_int;
+
+	u8 cmv_function;
+	u16 cmv_idx;
+	u32 cmv_address;
+	u16 cmv_offset;
+
+	/* keep in sync with eaglectl */
+	struct uea_stats {
+		struct {
+			u32 state;
+			u32 flags;
+			u32 mflags;
+			u32 vidcpe;
+			u32 vidco;
+			u32 dsrate;
+			u32 usrate;
+			u32 dsunc;
+			u32 usunc;
+			u32 dscorr;
+			u32 uscorr;
+			u32 txflow;
+			u32 rxflow;
+			u32 usattenuation;
+			u32 dsattenuation;
+			u32 dsmargin;
+			u32 usmargin;
+			u32 firmid;
+		} phy;
+	} stats;
+};
+
+/*
+ * Elsa IDs
+ */
+#define ELSA_VID		0x05CC
+#define ELSA_PID_PSTFIRM	0x3350
+#define ELSA_PID_PREFIRM	0x3351
+
+/*
+ * Sagem USB IDs
+ */
+#define EAGLE_VID		0x1110
+#define EAGLE_I_PID_PREFIRM	0x9010	/* Eagle I */
+#define EAGLE_I_PID_PSTFIRM	0x900F	/* Eagle I */
+
+#define EAGLE_IIC_PID_PREFIRM	0x9024	/* Eagle IIC */
+#define EAGLE_IIC_PID_PSTFIRM	0x9023	/* Eagle IIC */
+
+#define EAGLE_II_PID_PREFIRM	0x9022	/* Eagle II */
+#define EAGLE_II_PID_PSTFIRM	0x9021	/* Eagle II */
+
+/*
+ *  Eagle III Pid
+ */
+#define EAGLE_III_PID_PREFIRM	0x9032	/* Eagle III */
+#define EAGLE_III_PID_PSTFIRM	0x9031	/* Eagle III */
+
+/*
+ * USR USB IDs
+ */
+#define USR_VID			0x0BAF
+#define MILLER_A_PID_PREFIRM	0x00F2
+#define MILLER_A_PID_PSTFIRM	0x00F1
+#define MILLER_B_PID_PREFIRM	0x00FA
+#define MILLER_B_PID_PSTFIRM	0x00F9
+#define HEINEKEN_A_PID_PREFIRM	0x00F6
+#define HEINEKEN_A_PID_PSTFIRM	0x00F5
+#define HEINEKEN_B_PID_PREFIRM	0x00F8
+#define HEINEKEN_B_PID_PSTFIRM	0x00F7
+
+#define PREFIRM 0
+#define PSTFIRM (1<<7)
+enum {
+	ADI930 = 0,
+	EAGLE_I,
+	EAGLE_II,
+	EAGLE_III
+};
+
+/* macros for both struct usb_device_id and struct uea_softc */
+#define UEA_IS_PREFIRM(x) \
+	(!((x)->driver_info & PSTFIRM))
+#define UEA_CHIP_VERSION(x) \
+	((x)->driver_info & 0xf)
+
+#define IS_ISDN(sc) \
+	(le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)
+
+#define INS_TO_USBDEV(ins) ins->usb_dev
+
+#define GET_STATUS(data) \
+	((data >> 8) & 0xf)
+#define IS_OPERATIONAL(sc) \
+	(GET_STATUS(sc->stats.phy.state) == 2)
+
+/*
+ * Set of macros to handle unaligned data in the firmware blob.
+ * The FW_GET_BYTE() macro is provided only for consistency.
+ */
+
+#define FW_GET_BYTE(p)	*((__u8 *) (p))
+#define FW_GET_WORD(p)	le16_to_cpu(get_unaligned((__le16 *) (p)))
+#define FW_GET_LONG(p)	le32_to_cpu(get_unaligned((__le32 *) (p)))
+
+#define FW_DIR "ueagle-atm/"
+#define NB_MODEM 4
+
+#define BULK_TIMEOUT 300
+#define CTRL_TIMEOUT 1000
+
+#define ACK_TIMEOUT msecs_to_jiffies(1500)
+
+#define UEA_INTR_IFACE_NO 	0
+#define UEA_US_IFACE_NO		1
+#define UEA_DS_IFACE_NO		2
+
+#define FASTEST_ISO_INTF	8
+
+#define UEA_BULK_DATA_PIPE	0x02
+#define UEA_IDMA_PIPE		0x04
+#define UEA_INTR_PIPE		0x04
+#define UEA_ISO_DATA_PIPE	0x08
+
+#define UEA_SET_BLOCK    	0x0001
+#define UEA_SET_MODE     	0x0003
+#define UEA_SET_2183_DATA	0x0004
+#define UEA_SET_TIMEOUT		0x0011
+
+#define UEA_LOOPBACK_OFF	0x0002
+#define UEA_LOOPBACK_ON		0x0003
+#define UEA_BOOT_IDMA		0x0006
+#define UEA_START_RESET		0x0007
+#define UEA_END_RESET		0x0008
+
+#define UEA_SWAP_MAILBOX	(0x3fcd | 0x4000)
+#define UEA_MPTX_START		(0x3fce | 0x4000)
+#define UEA_MPTX_MAILBOX	(0x3fd6 | 0x4000)
+#define UEA_MPRX_MAILBOX	(0x3fdf | 0x4000)
+
+/* structure describing a block within a DSP page */
+struct block_info {
+	__le16 wHdr;
+#define UEA_BIHDR 0xabcd
+	__le16 wAddress;
+	__le16 wSize;
+	__le16 wOvlOffset;
+	__le16 wOvl;		/* overlay */
+	__le16 wLast;
+} __attribute__ ((packed));
+#define BLOCK_INFO_SIZE 12
+
+/* structure representing a CMV (Configuration and Management Variable) */
+struct cmv {
+	__le16 wPreamble;
+#define PREAMBLE 0x535c
+	__u8 bDirection;
+#define MODEMTOHOST 0x01
+#define HOSTTOMODEM 0x10
+	__u8 bFunction;
+#define FUNCTION_TYPE(f)    ((f) >> 4)
+#define MEMACCESS	0x1
+#define ADSLDIRECTIVE	0x7
+
+#define FUNCTION_SUBTYPE(f) ((f) & 0x0f)
+/* for MEMACCESS */
+#define REQUESTREAD	0x0
+#define REQUESTWRITE	0x1
+#define REPLYREAD	0x2
+#define REPLYWRITE	0x3
+/* for ADSLDIRECTIVE */
+#define KERNELREADY	0x0
+#define MODEMREADY	0x1
+
+#define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf))
+	__le16 wIndex;
+	__le32 dwSymbolicAddress;
+#define MAKESA(a, b, c, d)						\
+	(((c) & 0xff) << 24 |						\
+	 ((d) & 0xff) << 16 |						\
+	 ((a) & 0xff) << 8  |						\
+	 ((b) & 0xff))
+
+#define SA_CNTL MAKESA('C', 'N', 'T', 'L')
+#define SA_DIAG MAKESA('D', 'I', 'A', 'G')
+#define SA_INFO MAKESA('I', 'N', 'F', 'O')
+#define SA_OPTN MAKESA('O', 'P', 'T', 'N')
+#define SA_RATE MAKESA('R', 'A', 'T', 'E')
+#define SA_STAT MAKESA('S', 'T', 'A', 'T')
+	__le16 wOffsetAddress;
+	__le32 dwData;
+} __attribute__ ((packed));
+#define CMV_SIZE 16
+
+/* structure representing swap information */
+struct swap_info {
+	__u8 bSwapPageNo;
+	__u8 bOvl;		/* overlay */
+} __attribute__ ((packed));
+
+/* structure representing interrupt data */
+struct intr_pkt {
+	__u8 bType;
+	__u8 bNotification;
+	__le16 wValue;
+	__le16 wIndex;
+	__le16 wLength;
+	__le16 wInterrupt;
+#define INT_LOADSWAPPAGE 0x0001
+#define INT_INCOMINGCMV  0x0002
+	union {
+		struct {
+			struct swap_info swapinfo;
+			__le16 wDataSize;
+		} __attribute__ ((packed)) s1;
+
+		struct {
+			struct cmv cmv;
+			__le16 wDataSize;
+		} __attribute__ ((packed)) s2;
+	} __attribute__ ((packed)) u;
+#define bSwapPageNo	u.s1.swapinfo.bSwapPageNo
+#define bOvl		u.s1.swapinfo.bOvl
+} __attribute__ ((packed));
+#define INTR_PKT_SIZE 28
+
+static struct usb_driver uea_driver;
+static DECLARE_MUTEX(uea_semaphore);
+static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
+
+static int modem_index;
+static unsigned int debug;
+static int sync_wait[NB_MODEM];
+static char *cmv_file[NB_MODEM];
+
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
+module_param_array(sync_wait, bool, NULL, 0644);
+MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
+module_param_array(cmv_file, charp, NULL, 0644);
+MODULE_PARM_DESC(cmv_file,
+		"file name with configuration and management variables");
+
+#define UPDATE_ATM_STAT(type, val) \
+	do { \
+		if (sc->usbatm->atm_dev) \
+			sc->usbatm->atm_dev->type = val; \
+	} while (0)
+
+/* Firmware loading */
+#define LOAD_INTERNAL     0xA0
+#define F8051_USBCS       0x7f92
+
+/**
+ * uea_send_modem_cmd - Send a command for pre-firmware devices.
+ */
+static int uea_send_modem_cmd(struct usb_device *usb,
+		u16 addr, u16 size, u8 * buff)
+{
+	int ret = -ENOMEM;
+	u8 *xfer_buff;
+
+	xfer_buff = kmalloc(size, GFP_KERNEL);
+	if (xfer_buff) {
+		memcpy(xfer_buff, buff, size);
+		ret = usb_control_msg(usb,
+				      usb_sndctrlpipe(usb, 0),
+				      LOAD_INTERNAL,
+				      USB_DIR_OUT | USB_TYPE_VENDOR |
+				      USB_RECIP_DEVICE, addr, 0, xfer_buff,
+				      size, CTRL_TIMEOUT);
+		kfree(xfer_buff);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return (ret == size) ? 0 : -EIO;
+}
+
+static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context)
+{
+	struct usb_device *usb = context;
+	u8 *pfw, value;
+	u32 crc = 0;
+	int ret, size;
+
+	uea_enters(usb);
+	if (!fw_entry) {
+		uea_err(usb, "firmware is not available\n");
+		goto err;
+	}
+
+	pfw = fw_entry->data;
+	size = fw_entry->size;
+	if (size < 4)
+		goto err_fw_corrupted;
+
+	crc = FW_GET_LONG(pfw);
+	pfw += 4;
+	size -= 4;
+	if (crc32_be(0, pfw, size) != crc)
+		goto err_fw_corrupted;
+
+	/*
+	 * Start to upload formware : send reset
+	 */
+	value = 1;
+	ret = uea_send_modem_cmd(usb, F8051_USBCS, sizeof(value), &value);
+
+	if (ret < 0) {
+		uea_err(usb, "modem reset failed with error %d\n", ret);
+		goto err;
+	}
+
+	while (size > 3) {
+		u8 len = FW_GET_BYTE(pfw);
+		u16 add = FW_GET_WORD(pfw + 1);
+
+		size -= len + 3;
+		if (size < 0)
+			goto err_fw_corrupted;
+
+		ret = uea_send_modem_cmd(usb, add, len, pfw + 3);
+		if (ret < 0) {
+			uea_err(usb, "uploading firmware data failed "
+					"with error %d\n", ret);
+			goto err;
+		}
+		pfw += len + 3;
+	}
+
+	if (size != 0)
+		goto err_fw_corrupted;
+
+	/*
+	 * Tell the modem we finish : de-assert reset
+	 */
+	value = 0;
+	ret = uea_send_modem_cmd(usb, F8051_USBCS, 1, &value);
+	if (ret < 0)
+		uea_err(usb, "modem de-assert failed with error %d\n", ret);
+	else
+		uea_info(usb, "firmware uploaded\n");
+
+	uea_leaves(usb);
+	return;
+
+err_fw_corrupted:
+	uea_err(usb, "firmware is corrupted\n");
+err:
+	uea_leaves(usb);
+}
+
+/**
+ * uea_load_firmware - Load usb firmware for pre-firmware devices.
+ */
+static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
+{
+	int ret;
+	char *fw_name = FW_DIR "eagle.fw";
+
+	uea_enters(usb);
+	uea_info(usb, "pre-firmware device, uploading firmware\n");
+
+	switch (ver) {
+	case ADI930:
+		fw_name = FW_DIR "adi930.fw";
+		break;
+	case EAGLE_I:
+		fw_name = FW_DIR "eagleI.fw";
+		break;
+	case EAGLE_II:
+		fw_name = FW_DIR "eagleII.fw";
+		break;
+	case EAGLE_III:
+		fw_name = FW_DIR "eagleIII.fw";
+		break;
+	}
+
+	ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);
+	if (ret)
+		uea_err(usb, "firmware %s is not available\n", fw_name);
+	else
+		uea_info(usb, "loading firmware %s\n", fw_name);
+
+	uea_leaves(usb);
+	return ret;
+}
+
+/* modem management : dsp firmware, send/read CMV, monitoring statistic
+ */
+
+/*
+ * Make sure that the DSP code provided is safe to use.
+ */
+static int check_dsp(u8 *dsp, unsigned int len)
+{
+	u8 pagecount, blockcount;
+	u16 blocksize;
+	u32 pageoffset;
+	unsigned int i, j, p, pp;
+
+	pagecount = FW_GET_BYTE(dsp);
+	p = 1;
+
+	/* enough space for page offsets? */
+	if (p + 4 * pagecount > len)
+		return 1;
+
+	for (i = 0; i < pagecount; i++) {
+
+		pageoffset = FW_GET_LONG(dsp + p);
+		p += 4;
+
+		if (pageoffset == 0)
+			continue;
+
+		/* enough space for blockcount? */
+		if (pageoffset >= len)
+			return 1;
+
+		pp = pageoffset;
+		blockcount = FW_GET_BYTE(dsp + pp);
+		pp += 1;
+
+		for (j = 0; j < blockcount; j++) {
+
+			/* enough space for block header? */
+			if (pp + 4 > len)
+				return 1;
+
+			pp += 2;	/* skip blockaddr */
+			blocksize = FW_GET_WORD(dsp + pp);
+			pp += 2;
+
+			/* enough space for block data? */
+			if (pp + blocksize > len)
+				return 1;
+
+			pp += blocksize;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * send data to the idma pipe
+ * */
+static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
+{
+	int ret = -ENOMEM;
+	u8 *xfer_buff;
+	int bytes_read;
+
+	xfer_buff = kmalloc(size, GFP_KERNEL);
+	if (!xfer_buff) {
+		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
+		return ret;
+	}
+
+	memcpy(xfer_buff, data, size);
+
+	ret = usb_bulk_msg(sc->usb_dev,
+			 usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
+			 xfer_buff, size, &bytes_read, BULK_TIMEOUT);
+
+	kfree(xfer_buff);
+	if (ret < 0)
+		return ret;
+	if (size != bytes_read) {
+		uea_err(INS_TO_USBDEV(sc), "size != bytes_read %d %d\n", size,
+		       bytes_read);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int request_dsp(struct uea_softc *sc)
+{
+	int ret;
+	char *dsp_name;
+
+	if (UEA_CHIP_VERSION(sc) == ADI930) {
+		if (IS_ISDN(sc))
+			dsp_name = FW_DIR "DSP9i.bin";
+		else
+			dsp_name = FW_DIR "DSP9p.bin";
+	} else {
+		if (IS_ISDN(sc))
+			dsp_name = FW_DIR "DSPei.bin";
+		else
+			dsp_name = FW_DIR "DSPep.bin";
+	}
+
+	ret = request_firmware(&sc->dsp_firm,
+				dsp_name, &sc->usb_dev->dev);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "requesting firmware %s failed with error %d\n",
+		       dsp_name, ret);
+		return ret;
+	}
+
+	if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+		       dsp_name);
+		release_firmware(sc->dsp_firm);
+		sc->dsp_firm = NULL;
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+/*
+ * The uea_load_page() function must be called within a process context
+ */
+static void uea_load_page(void *xsc)
+{
+	struct uea_softc *sc = xsc;
+	u16 pageno = sc->pageno;
+	u16 ovl = sc->ovl;
+	struct block_info bi;
+
+	u8 *p;
+	u8 pagecount, blockcount;
+	u16 blockaddr, blocksize;
+	u32 pageoffset;
+	int i;
+
+	/* reload firmware when reboot start and it's loaded already */
+	if (ovl == 0 && pageno == 0 && sc->dsp_firm) {
+		release_firmware(sc->dsp_firm);
+		sc->dsp_firm = NULL;
+	}
+
+	if (sc->dsp_firm == NULL && request_dsp(sc) < 0)
+		return;
+
+	p = sc->dsp_firm->data;
+	pagecount = FW_GET_BYTE(p);
+	p += 1;
+
+	if (pageno >= pagecount)
+		goto bad1;
+
+	p += 4 * pageno;
+	pageoffset = FW_GET_LONG(p);
+
+	if (pageoffset == 0)
+		goto bad1;
+
+	p = sc->dsp_firm->data + pageoffset;
+	blockcount = FW_GET_BYTE(p);
+	p += 1;
+
+	uea_dbg(INS_TO_USBDEV(sc),
+	       "sending %u blocks for DSP page %u\n", blockcount, pageno);
+
+	bi.wHdr = cpu_to_le16(UEA_BIHDR);
+	bi.wOvl = cpu_to_le16(ovl);
+	bi.wOvlOffset = cpu_to_le16(ovl | 0x8000);
+
+	for (i = 0; i < blockcount; i++) {
+		blockaddr = FW_GET_WORD(p);
+		p += 2;
+
+		blocksize = FW_GET_WORD(p);
+		p += 2;
+
+		bi.wSize = cpu_to_le16(blocksize);
+		bi.wAddress = cpu_to_le16(blockaddr);
+		bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0);
+
+		/* send block info through the IDMA pipe */
+		if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE))
+			goto bad2;
+
+		/* send block data through the IDMA pipe */
+		if (uea_idma_write(sc, p, blocksize))
+			goto bad2;
+
+		p += blocksize;
+	}
+
+	return;
+
+bad2:
+	uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
+	return;
+bad1:
+	uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+}
+
+static inline void wake_up_cmv_ack(struct uea_softc *sc)
+{
+	sc->cmv_ack = 1;
+	wake_up(&sc->cmv_ack_wait);
+}
+
+static inline int wait_cmv_ack(struct uea_softc *sc)
+{
+	int ret = wait_event_timeout(sc->cmv_ack_wait,
+						   sc->cmv_ack, ACK_TIMEOUT);
+	sc->cmv_ack = 0;
+
+	if (ret < 0)
+		return ret;
+
+	return (ret == 0) ? -ETIMEDOUT : 0;
+
+}
+
+#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
+
+static int uea_request(struct uea_softc *sc,
+		u16 value, u16 index, u16 size, void *data)
+{
+	u8 *xfer_buff;
+	int ret = -ENOMEM;
+
+	xfer_buff = kmalloc(size, GFP_KERNEL);
+	if (!xfer_buff) {
+		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
+		return ret;
+	}
+	memcpy(xfer_buff, data, size);
+
+	ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
+			      UCDC_SEND_ENCAPSULATED_COMMAND,
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      value, index, xfer_buff, size, CTRL_TIMEOUT);
+
+	kfree(xfer_buff);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc), "usb_control_msg error %d\n", ret);
+		return ret;
+	}
+
+	if (ret != size) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "usb_control_msg send only %d bytes (instead of %d)\n",
+		       ret, size);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int uea_cmv(struct uea_softc *sc,
+		u8 function, u32 address, u16 offset, u32 data)
+{
+	struct cmv cmv;
+	int ret;
+
+	/* we send a request, but we expect a reply */
+	sc->cmv_function = function | 0x2;
+	sc->cmv_idx++;
+	sc->cmv_address = address;
+	sc->cmv_offset = offset;
+
+	cmv.wPreamble = cpu_to_le16(PREAMBLE);
+	cmv.bDirection = HOSTTOMODEM;
+	cmv.bFunction = function;
+	cmv.wIndex = cpu_to_le16(sc->cmv_idx);
+	put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress);
+	cmv.wOffsetAddress = cpu_to_le16(offset);
+	put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData);
+
+	ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
+	if (ret < 0)
+		return ret;
+	return wait_cmv_ack(sc);
+}
+
+static inline int uea_read_cmv(struct uea_softc *sc,
+		u32 address, u16 offset, u32 *data)
+{
+	int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD),
+			  address, offset, 0);
+	if (ret < 0)
+		uea_err(INS_TO_USBDEV(sc),
+			"reading cmv failed with error %d\n", ret);
+	else
+	 	*data = sc->data;
+
+	return ret;
+}
+
+static inline int uea_write_cmv(struct uea_softc *sc,
+		u32 address, u16 offset, u32 data)
+{
+	int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE),
+			  address, offset, data);
+	if (ret < 0)
+		uea_err(INS_TO_USBDEV(sc),
+			"writing cmv failed with error %d\n", ret);
+
+	return ret;
+}
+
+/*
+ * Monitor the modem and update the stat
+ * return 0 if everything is ok
+ * return < 0 if an error occurs (-EAGAIN reboot needed)
+ */
+static int uea_stat(struct uea_softc *sc)
+{
+	u32 data;
+	int ret;
+
+	uea_enters(INS_TO_USBDEV(sc));
+	data = sc->stats.phy.state;
+
+	ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state);
+	if (ret < 0)
+		return ret;
+
+	switch (GET_STATUS(sc->stats.phy.state)) {
+	case 0:		/* not yet synchronized */
+		uea_dbg(INS_TO_USBDEV(sc),
+		       "modem not yet synchronized\n");
+		return 0;
+
+	case 1:		/* initialization */
+		uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
+		return 0;
+
+	case 2:		/* operational */
+		uea_vdbg(INS_TO_USBDEV(sc), "modem operational\n");
+		break;
+
+	case 3:		/* fail ... */
+		uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n");
+		return -EAGAIN;
+
+	case 4 ... 6:	/* test state */
+		uea_warn(INS_TO_USBDEV(sc),
+				"modem in test mode - not supported\n");
+		return -EAGAIN;
+
+	case 7:		/* fast-retain ... */
+		uea_info(INS_TO_USBDEV(sc), "modem in fast-retain mode\n");
+		return 0;
+	default:
+		uea_err(INS_TO_USBDEV(sc), "modem invalid SW mode %d\n",
+			GET_STATUS(sc->stats.phy.state));
+		return -EAGAIN;
+	}
+
+	if (GET_STATUS(data) != 2) {
+		uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL);
+		uea_info(INS_TO_USBDEV(sc), "modem operational\n");
+
+		/* release the dsp firmware as it is not needed until
+		 * the next failure
+		 */
+		if (sc->dsp_firm) {
+			release_firmware(sc->dsp_firm);
+			sc->dsp_firm = NULL;
+		}
+
+		ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
+		if (ret < 0)
+			return ret;
+		uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
+				sc->stats.phy.firmid);
+	}
+
+	/* always update it as atm layer could not be init when we switch to
+	 * operational state
+	 */
+	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND);
+
+	/* wake up processes waiting for synchronization */
+	wake_up(&sc->sync_q);
+
+	ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags);
+	if (ret < 0)
+		return ret;
+	sc->stats.phy.mflags |= sc->stats.phy.flags;
+
+	/* in case of a flags ( for example delineation LOSS (& 0x10)),
+	 * we check the status again in order to detect the failure earlier
+	 */
+	if (sc->stats.phy.flags) {
+		uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+		       sc->stats.phy.flags);
+		return 0;
+	}
+
+	ret = uea_read_cmv(sc, SA_RATE, 0, &data);
+	if (ret < 0)
+		return ret;
+
+	/* in bulk mode the modem have problem with high rate
+	 * changing internal timing could improve things, but the
+	 * value is misterious.
+	 * ADI930 don't support it (-EPIPE error).
+	 */
+	if (UEA_CHIP_VERSION(sc) != ADI930
+		    && sc->stats.phy.dsrate != (data >> 16) * 32) {
+		/* Original timming from ADI(used in windows driver)
+		 * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
+		 */
+		u16 timeout = (data <= 0x20ffff) ? 0 : 1;
+		ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL);
+		uea_info(INS_TO_USBDEV(sc),
+				"setting new timeout %d%s\n", timeout,
+				ret < 0?" failed":"");
+	}
+	sc->stats.phy.dsrate = (data >> 16) * 32;
+	sc->stats.phy.usrate = (data & 0xffff) * 32;
+	UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424);
+
+	ret = uea_read_cmv(sc, SA_DIAG, 23, &data);
+	if (ret < 0)
+		return ret;
+	sc->stats.phy.dsattenuation = (data & 0xff) / 2;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 47, &data);
+	if (ret < 0)
+		return ret;
+	sc->stats.phy.usattenuation = (data & 0xff) / 2;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 25, &sc->stats.phy.dsmargin);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 49, &sc->stats.phy.usmargin);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 51, &sc->stats.phy.rxflow);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 52, &sc->stats.phy.txflow);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 54, &sc->stats.phy.dsunc);
+	if (ret < 0)
+		return ret;
+
+	/* only for atu-c */
+	ret = uea_read_cmv(sc, SA_DIAG, 58, &sc->stats.phy.usunc);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 53, &sc->stats.phy.dscorr);
+	if (ret < 0)
+		return ret;
+
+	/* only for atu-c */
+	ret = uea_read_cmv(sc, SA_DIAG, 57, &sc->stats.phy.uscorr);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_INFO, 8, &sc->stats.phy.vidco);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_INFO, 13, &sc->stats.phy.vidcpe);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int request_cmvs(struct uea_softc *sc,
+		 struct uea_cmvs **cmvs, const struct firmware **fw)
+{
+	int ret, size;
+	u8 *data;
+	char *file;
+	static char cmv_name[256] = FW_DIR;
+
+	if (cmv_file[sc->modem_index] == NULL) {
+		if (UEA_CHIP_VERSION(sc) == ADI930)
+			file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin";
+		else
+			file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin";
+	} else
+		file = cmv_file[sc->modem_index];
+
+	strcpy(cmv_name, FW_DIR);
+	strlcat(cmv_name, file, sizeof(cmv_name));
+
+	ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "requesting firmware %s failed with error %d\n",
+		       cmv_name, ret);
+		return ret;
+	}
+
+	data = (u8 *) (*fw)->data;
+	size = *data * sizeof(struct uea_cmvs) + 1;
+	if (size != (*fw)->size) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+		       cmv_name);
+		release_firmware(*fw);
+		return -EILSEQ;
+	}
+
+	*cmvs = (struct uea_cmvs *)(data + 1);
+	return *data;
+}
+
+/* Start boot post firmware modem:
+ * - send reset commands through usb control pipe
+ * - start workqueue for DSP loading
+ * - send CMV options to modem
+ */
+
+static int uea_start_reset(struct uea_softc *sc)
+{
+	u16 zero = 0;	/* ;-) */
+	int i, len, ret;
+	struct uea_cmvs *cmvs;
+	const struct firmware *cmvs_fw;
+
+	uea_enters(INS_TO_USBDEV(sc));
+	uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
+
+	sc->booting = 1;
+	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
+
+	/* reset statistics */
+	memset(&sc->stats, 0, sizeof(struct uea_stats));
+
+	/* tell the modem that we want to boot in IDMA mode */
+	uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+	uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL);
+
+ 	/* enter reset mode */
+	uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL);
+
+	/* original driver use 200ms, but windows driver use 100ms */
+	msleep(100);
+
+	/* leave reset mode */
+	uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL);
+
+ 	/* clear tx and rx mailboxes */
+	uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero);
+	uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero);
+	uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero);
+
+	msleep(1000);
+	sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+	sc->booting = 0;
+
+	/* start loading DSP */
+	sc->pageno = 0;
+	sc->ovl = 0;
+	schedule_work(&sc->task);
+
+	/* wait for modem ready CMV */
+	ret = wait_cmv_ack(sc);
+	if (ret < 0)
+		return ret;
+
+	/* Enter in R-IDLE (cmv) until instructed otherwise */
+	ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
+	if (ret < 0)
+		return ret;
+
+	/* get options */
+ 	ret = len = request_cmvs(sc, &cmvs, &cmvs_fw);
+	if (ret < 0)
+		return ret;
+
+	/* send options */
+	for (i = 0; i < len; i++) {
+		ret = uea_write_cmv(sc, FW_GET_LONG(&cmvs[i].address),
+					FW_GET_WORD(&cmvs[i].offset),
+					FW_GET_LONG(&cmvs[i].data));
+		if (ret < 0)
+			goto out;
+	}
+	/* Enter in R-ACT-REQ */
+	ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+out:
+	release_firmware(cmvs_fw);
+	sc->reset = 0;
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
+}
+
+/*
+ * In case of an error wait 1s before rebooting the modem
+ * if the modem don't request reboot (-EAGAIN).
+ * Monitor the modem every 1s.
+ */
+
+static int uea_kthread(void *data)
+{
+	struct uea_softc *sc = data;
+	int ret = -EAGAIN;
+
+	uea_enters(INS_TO_USBDEV(sc));
+	while (!kthread_should_stop()) {
+		if (ret < 0 || sc->reset)
+			ret = uea_start_reset(sc);
+		if (!ret)
+			ret = uea_stat(sc);
+		if (ret != -EAGAIN)
+			msleep(1000);
+	}
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
+}
+
+/* Load second usb firmware for ADI930 chip */
+static int load_XILINX_firmware(struct uea_softc *sc)
+{
+	const struct firmware *fw_entry;
+	int ret, size, u, ln;
+	u8 *pfw, value;
+	char *fw_name = FW_DIR "930-fpga.bin";
+
+	uea_enters(INS_TO_USBDEV(sc));
+
+	ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev);
+	if (ret) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n",
+		       fw_name);
+		goto err0;
+	}
+
+	pfw = fw_entry->data;
+	size = fw_entry->size;
+	if (size != 0x577B) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+		       fw_name);
+		ret = -EILSEQ;
+		goto err1;
+	}
+	for (u = 0; u < size; u += ln) {
+		ln = min(size - u, 64);
+		ret = uea_request(sc, 0xe, 0, ln, pfw + u);
+		if (ret < 0) {
+			uea_err(INS_TO_USBDEV(sc),
+			       "elsa download data failed (%d)\n", ret);
+			goto err1;
+		}
+	}
+
+	/* finish to send the fpga
+	 */
+	ret = uea_request(sc, 0xe, 1, 0, NULL);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+				"elsa download data failed (%d)\n", ret);
+		goto err1;
+	}
+
+	/*
+	 * Tell the modem we finish : de-assert reset
+	 */
+	value = 0;
+	ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
+	if (ret < 0)
+		uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret);
+
+
+err1:
+	release_firmware(fw_entry);
+err0:
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
+}
+
+static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
+{
+	uea_enters(INS_TO_USBDEV(sc));
+	if (le16_to_cpu(cmv->wPreamble) != PREAMBLE)
+		goto bad1;
+
+	if (cmv->bDirection != MODEMTOHOST)
+		goto bad1;
+
+	/* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to
+	 * the first MEMACESS cmv. Ignore it...
+	 */
+	if (cmv->bFunction != sc->cmv_function) {
+		if (UEA_CHIP_VERSION(sc) == ADI930
+				&& cmv->bFunction ==  MAKEFUNCTION(2, 2)) {
+			cmv->wIndex = cpu_to_le16(sc->cmv_idx);
+			put_unaligned(cpu_to_le32(sc->cmv_address), &cmv->dwSymbolicAddress);
+			cmv->wOffsetAddress = cpu_to_le16(sc->cmv_offset);
+		}
+		else
+			goto bad2;
+	}
+
+	if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
+		wake_up_cmv_ack(sc);
+		return;
+	}
+
+	/* in case of MEMACCESS */
+	if (le16_to_cpu(cmv->wIndex) != sc->cmv_idx ||
+	    le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) !=
+	    sc->cmv_address
+	    || le16_to_cpu(cmv->wOffsetAddress) != sc->cmv_offset)
+		goto bad2;
+
+	sc->data = le32_to_cpu(get_unaligned(&cmv->dwData));
+	sc->data = sc->data << 16 | sc->data >> 16;
+
+	wake_up_cmv_ack(sc);
+	return;
+
+bad2:
+	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+			"Function : %d, Subfunction : %d\n",
+			FUNCTION_TYPE(cmv->bFunction),
+			FUNCTION_SUBTYPE(cmv->bFunction));
+	return;
+
+bad1:
+	uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
+			"wPreamble %d, bDirection %d\n",
+			le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+}
+
+/*
+ * interrupt handler
+ */
+static void uea_intr(struct urb *urb, struct pt_regs *regs)
+{
+	struct uea_softc *sc = (struct uea_softc *)urb->context;
+	struct intr_pkt *intr;
+	uea_enters(INS_TO_USBDEV(sc));
+
+	if (urb->status < 0) {
+		uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
+		       urb->status);
+		return;
+	}
+
+	intr = (struct intr_pkt *) urb->transfer_buffer;
+
+	/* device-to-host interrupt */
+	if (intr->bType != 0x08 || sc->booting) {
+		uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
+		// rebooting ?
+		// sc->reset = 1;
+		goto resubmit;
+	}
+
+	switch (le16_to_cpu(intr->wInterrupt)) {
+	case INT_LOADSWAPPAGE:
+		sc->pageno = intr->bSwapPageNo;
+		sc->ovl = intr->bOvl >> 4 | intr->bOvl << 4;
+		schedule_work(&sc->task);
+		break;
+
+	case INT_INCOMINGCMV:
+		uea_dispatch_cmv(sc, &intr->u.s2.cmv);
+		break;
+
+	default:
+		uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
+		       le16_to_cpu(intr->wInterrupt));
+	}
+
+resubmit:
+	usb_submit_urb(sc->urb_int, GFP_ATOMIC);
+}
+
+/*
+ * Start the modem : init the data and start kernel thread
+ */
+static int uea_boot(struct uea_softc *sc)
+{
+	int ret;
+	struct intr_pkt *intr;
+
+	uea_enters(INS_TO_USBDEV(sc));
+
+	INIT_WORK(&sc->task, uea_load_page, sc);
+	init_waitqueue_head(&sc->sync_q);
+	init_waitqueue_head(&sc->cmv_ack_wait);
+
+	if (UEA_CHIP_VERSION(sc) == ADI930)
+		load_XILINX_firmware(sc);
+
+	intr = kmalloc(INTR_PKT_SIZE, GFP_KERNEL);
+	if (!intr) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "cannot allocate interrupt package\n");
+		uea_leaves(INS_TO_USBDEV(sc));
+		return -ENOMEM;
+	}
+
+	sc->urb_int = usb_alloc_urb(0, GFP_KERNEL);
+	if (!sc->urb_int) {
+		uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n");
+		goto err;
+	}
+
+	usb_fill_int_urb(sc->urb_int, sc->usb_dev,
+			 usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
+			 intr, INTR_PKT_SIZE, uea_intr, sc,
+			 sc->usb_dev->actconfig->interface[0]->altsetting[0].
+			 endpoint[0].desc.bInterval);
+
+	ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "urb submition failed with error %d\n", ret);
+		goto err1;
+	}
+
+	sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
+	if (sc->kthread == ERR_PTR(-ENOMEM)) {
+		uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+		goto err2;
+	}
+
+	uea_leaves(INS_TO_USBDEV(sc));
+	return 0;
+
+err2:
+	usb_kill_urb(sc->urb_int);
+err1:
+	kfree(intr);
+err:
+	usb_free_urb(sc->urb_int);
+	uea_leaves(INS_TO_USBDEV(sc));
+	return -ENOMEM;
+}
+
+/*
+ * Stop the modem : kill kernel thread and free data
+ */
+static void uea_stop(struct uea_softc *sc)
+{
+	int ret;
+	uea_enters(INS_TO_USBDEV(sc));
+	ret = kthread_stop(sc->kthread);
+	uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+
+	/* stop any pending boot process */
+	flush_scheduled_work();
+
+	uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+
+	usb_kill_urb(sc->urb_int);
+	kfree(sc->urb_int->transfer_buffer);
+	usb_free_urb(sc->urb_int);
+
+	if (sc->dsp_firm)
+		release_firmware(sc->dsp_firm);
+	uea_leaves(INS_TO_USBDEV(sc));
+}
+
+/* syfs interface */
+static struct uea_softc *dev_to_uea(struct device *dev)
+{
+	struct usb_interface *intf;
+	struct usbatm_data *usbatm;
+
+	intf = to_usb_interface(dev);
+	if (!intf)
+		return NULL;
+
+	usbatm = usb_get_intfdata(intf);
+	if (!usbatm)
+		return NULL;
+
+	return usbatm->driver_data;
+}
+
+static ssize_t read_status(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static ssize_t reboot(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+	sc->reset = 1;
+	ret = count;
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
+
+static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+
+	switch (GET_STATUS(sc->stats.phy.state)) {
+	case 0:
+		ret = sprintf(buf, "Modem is booting\n");
+		break;
+	case 1:
+		ret = sprintf(buf, "Modem is initializing\n");
+		break;
+	case 2:
+		ret = sprintf(buf, "Modem is operational\n");
+		break;
+	default:
+		ret = sprintf(buf, "Modem synchronization failed\n");
+		break;
+	}
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
+
+static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+
+	if (sc->stats.phy.flags & 0x0C00)
+		ret = sprintf(buf, "ERROR\n");
+	else if (sc->stats.phy.flags & 0x0030)
+		ret = sprintf(buf, "LOSS\n");
+	else
+		ret = sprintf(buf, "GOOD\n");
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
+
+#define UEA_ATTR(name, reset) 					\
+								\
+static ssize_t read_##name(struct device *dev, 			\
+		struct device_attribute *attr, char *buf)	\
+{ 								\
+	int ret = -ENODEV; 					\
+	struct uea_softc *sc; 					\
+ 								\
+	down(&uea_semaphore); 					\
+	sc = dev_to_uea(dev);					\
+	if (!sc) 						\
+		goto out; 					\
+	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name);	\
+	if (reset)						\
+		sc->stats.phy.name = 0;				\
+out: 								\
+	up(&uea_semaphore); 					\
+	return ret; 						\
+} 								\
+								\
+static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)
+
+UEA_ATTR(mflags, 1);
+UEA_ATTR(vidcpe, 0);
+UEA_ATTR(usrate, 0);
+UEA_ATTR(dsrate, 0);
+UEA_ATTR(usattenuation, 0);
+UEA_ATTR(dsattenuation, 0);
+UEA_ATTR(usmargin, 0);
+UEA_ATTR(dsmargin, 0);
+UEA_ATTR(txflow, 0);
+UEA_ATTR(rxflow, 0);
+UEA_ATTR(uscorr, 0);
+UEA_ATTR(dscorr, 0);
+UEA_ATTR(usunc, 0);
+UEA_ATTR(dsunc, 0);
+
+/* Retrieve the device End System Identifier (MAC) */
+
+#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10)
+static int uea_getesi(struct uea_softc *sc, u_char * esi)
+{
+	unsigned char mac_str[2 * ETH_ALEN + 1];
+	int i;
+	if (usb_string
+	    (sc->usb_dev, sc->usb_dev->descriptor.iSerialNumber, mac_str,
+	     sizeof(mac_str)) != 2 * ETH_ALEN)
+		return 1;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]);
+
+	return 0;
+}
+
+/* ATM stuff */
+static int uea_atm_open(struct usbatm_data *usbatm, struct atm_dev *atm_dev)
+{
+	struct uea_softc *sc = usbatm->driver_data;
+
+	return uea_getesi(sc, atm_dev->esi);
+}
+
+static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf)
+{
+	struct uea_softc *sc = usbatm->driver_data;
+
+	wait_event(sc->sync_q, IS_OPERATIONAL(sc));
+
+	return 0;
+
+}
+
+static int claim_interface(struct usb_device *usb_dev,
+			   struct usbatm_data *usbatm, int ifnum)
+{
+	int ret;
+	struct usb_interface *intf = usb_ifnum_to_if(usb_dev, ifnum);
+
+	if (!intf) {
+		uea_err(usb_dev, "interface %d not found\n", ifnum);
+		return -ENODEV;
+	}
+
+	ret = usb_driver_claim_interface(&uea_driver, intf, usbatm);
+	if (ret != 0)
+		uea_err(usb_dev, "can't claim interface %d, error %d\n", ifnum,
+		       ret);
+	return ret;
+}
+
+static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+{
+	/* sysfs interface */
+	device_create_file(&intf->dev, &dev_attr_stat_status);
+	device_create_file(&intf->dev, &dev_attr_stat_mflags);
+	device_create_file(&intf->dev, &dev_attr_stat_human_status);
+	device_create_file(&intf->dev, &dev_attr_stat_delin);
+	device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
+	device_create_file(&intf->dev, &dev_attr_stat_usrate);
+	device_create_file(&intf->dev, &dev_attr_stat_dsrate);
+	device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
+	device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
+	device_create_file(&intf->dev, &dev_attr_stat_usmargin);
+	device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
+	device_create_file(&intf->dev, &dev_attr_stat_txflow);
+	device_create_file(&intf->dev, &dev_attr_stat_rxflow);
+	device_create_file(&intf->dev, &dev_attr_stat_uscorr);
+	device_create_file(&intf->dev, &dev_attr_stat_dscorr);
+	device_create_file(&intf->dev, &dev_attr_stat_usunc);
+	device_create_file(&intf->dev, &dev_attr_stat_dsunc);
+}
+
+static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
+		   const struct usb_device_id *id, int *heavy)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct uea_softc *sc;
+	int ret, ifnum = intf->altsetting->desc.bInterfaceNumber;
+
+	uea_enters(usb);
+
+	/* interface 0 is for firmware/monitoring */
+	if (ifnum != UEA_INTR_IFACE_NO)
+		return -ENODEV;
+
+	*heavy = sync_wait[modem_index];
+
+	/* interface 1 is for outbound traffic */
+	ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
+	if (ret < 0)
+		return ret;
+
+	/* ADI930 has only 2 interfaces and inbound traffic
+	 * is on interface 1
+	 */
+	if (UEA_CHIP_VERSION(id) != ADI930) {
+		/* interface 2 is for inbound traffic */
+		ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
+		if (ret < 0)
+			return ret;
+	}
+
+	sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
+	if (!sc) {
+		uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+		return -ENOMEM;
+	}
+
+	sc->usb_dev = usb;
+	usbatm->driver_data = sc;
+	sc->usbatm = usbatm;
+	sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
+	sc->driver_info = id->driver_info;
+
+	ret = uea_boot(sc);
+	if (ret < 0) {
+		kfree(sc);
+		return ret;
+	}
+
+	create_fs_entries(sc, intf);
+	return 0;
+}
+
+static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+{
+	/* sysfs interface */
+	device_remove_file(&intf->dev, &dev_attr_stat_status);
+	device_remove_file(&intf->dev, &dev_attr_stat_mflags);
+	device_remove_file(&intf->dev, &dev_attr_stat_human_status);
+	device_remove_file(&intf->dev, &dev_attr_stat_delin);
+	device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
+	device_remove_file(&intf->dev, &dev_attr_stat_usrate);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
+	device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
+	device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
+	device_remove_file(&intf->dev, &dev_attr_stat_txflow);
+	device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
+	device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
+	device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
+	device_remove_file(&intf->dev, &dev_attr_stat_usunc);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+}
+
+static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
+{
+	struct uea_softc *sc = usbatm->driver_data;
+
+	destroy_fs_entries(sc, intf);
+	uea_stop(sc);
+	kfree(sc);
+}
+
+static struct usbatm_driver uea_usbatm_driver = {
+	.driver_name = "ueagle-atm",
+	.owner = THIS_MODULE,
+	.bind = uea_bind,
+	.atm_start = uea_atm_open,
+	.unbind = uea_unbind,
+	.heavy_init = uea_heavy,
+	.in = UEA_BULK_DATA_PIPE,
+	.out = UEA_BULK_DATA_PIPE,
+};
+
+static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+
+	uea_enters(usb);
+	uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n",
+	       le16_to_cpu(usb->descriptor.idVendor),
+	       le16_to_cpu(usb->descriptor.idProduct),
+	       chip_name[UEA_CHIP_VERSION(id)]);
+
+	usb_reset_device(usb);
+
+	if (UEA_IS_PREFIRM(id))
+		return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
+
+	return usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+}
+
+static void uea_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	int ifnum = intf->altsetting->desc.bInterfaceNumber;
+	uea_enters(usb);
+
+	/* ADI930 has 2 interfaces and eagle 3 interfaces.
+	 * Pre-firmware device has one interface
+	 */
+	if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
+		down(&uea_semaphore);
+		usbatm_usb_disconnect(intf);
+		up(&uea_semaphore);
+		uea_info(usb, "ADSL device removed\n");
+	}
+
+	uea_leaves(usb);
+}
+
+/*
+ * List of supported VID/PID
+ */
+static const struct usb_device_id uea_ids[] = {
+	{USB_DEVICE(ELSA_VID,	ELSA_PID_PREFIRM),	.driver_info = ADI930 | PREFIRM},
+	{USB_DEVICE(ELSA_VID,	ELSA_PID_PSTFIRM),	.driver_info = ADI930 | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_I_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_I_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_II_PID_PREFIRM),	.driver_info = EAGLE_II | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_II_PID_PSTFIRM),	.driver_info = EAGLE_II | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_IIC_PID_PREFIRM),	.driver_info = EAGLE_II | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_IIC_PID_PSTFIRM),	.driver_info = EAGLE_II | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_III_PID_PREFIRM),	.driver_info = EAGLE_III | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_III_PID_PSTFIRM),	.driver_info = EAGLE_III | PSTFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_A_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_A_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_B_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_B_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},
+	{}
+};
+
+/*
+ * USB driver descriptor
+ */
+static struct usb_driver uea_driver = {
+	.name = "ueagle-atm",
+	.id_table = uea_ids,
+	.probe = uea_probe,
+	.disconnect = uea_disconnect,
+};
+
+MODULE_DEVICE_TABLE(usb, uea_ids);
+
+/**
+ * uea_init - Initialize the module.
+ *      Register to USB subsystem
+ */
+static int __init uea_init(void)
+{
+	printk(KERN_INFO "[ueagle-atm] driver " EAGLEUSBVERSION " loaded\n");
+
+	usb_register(&uea_driver);
+
+	return 0;
+}
+
+module_init(uea_init);
+
+/**
+ * uea_exit  -  Destroy module
+ *    Deregister with USB subsystem
+ */
+static void __exit uea_exit(void)
+{
+	/*
+	 * This calls automatically the uea_disconnect method if necessary:
+	 */
+	usb_deregister(&uea_driver);
+
+	printk(KERN_INFO "[ueagle-atm] driver unloaded\n");
+}
+
+module_exit(uea_exit);
+
+MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka");
+MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 2e6593e..9baa629 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -646,14 +646,14 @@
 	kfree(instance);
 }
 
-void usbatm_get_instance(struct usbatm_data *instance)
+static void usbatm_get_instance(struct usbatm_data *instance)
 {
 	dbg("%s", __func__);
 
 	kref_get(&instance->refcount);
 }
 
-void usbatm_put_instance(struct usbatm_data *instance)
+static void usbatm_put_instance(struct usbatm_data *instance)
 {
 	dbg("%s", __func__);
 
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 7fe7fb4..5c76e3a 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -140,7 +140,6 @@
 }
 
 static struct usb_driver xusbatm_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= xusbatm_driver_name,
 	.probe		= xusbatm_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 5085827..3ad9ee8 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -2732,7 +2732,6 @@
 MODULE_DEVICE_TABLE (usb, usb_audio_ids);
 
 static struct usb_driver usb_audio_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"audio",
 	.probe =	usb_audio_probe,
 	.disconnect =	usb_audio_disconnect,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 1b47514..248279e 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -6,6 +6,7 @@
  * Copyright (c) 1999 Johannes Erdfelt	<johannes@erdfelt.com>
  * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  * Copyright (c) 2004 Oliver Neukum	<oliver@neukum.name>
+ * Copyright (c) 2005 David Kubicek	<dave@awk.cz>
  *
  * USB Abstract Control Model driver for USB modems and ISDN adapters
  *
@@ -29,6 +30,7 @@
  *		config we want, sysadmin changes bConfigurationValue in sysfs.
  *	v0.23 - use softirq for rx processing, as needed by tty layer
  *	v0.24 - change probe method to evaluate CDC union descriptor
+ *	v0.25 - downstream tasks paralelized to maximize throughput
  */
 
 /*
@@ -63,14 +65,15 @@
 #include <linux/usb_cdc.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
+#include <linux/list.h>
 
 #include "cdc-acm.h"
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.23"
-#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
+#define DRIVER_VERSION "v0.25"
+#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
 
 static struct usb_driver acm_driver;
@@ -284,7 +287,9 @@
 /* data interface returns incoming bytes, or we got unthrottled */
 static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
 {
-	struct acm *acm = urb->context;
+	struct acm_rb *buf;
+	struct acm_ru *rcv = urb->context;
+	struct acm *acm = rcv->instance;
 	dbg("Entering acm_read_bulk with status %d\n", urb->status);
 
 	if (!ACM_READY(acm))
@@ -293,49 +298,109 @@
 	if (urb->status)
 		dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
 
-	/* calling tty_flip_buffer_push() in_irq() isn't allowed */
-	tasklet_schedule(&acm->bh);
+	buf = rcv->buffer;
+	buf->size = urb->actual_length;
+
+	spin_lock(&acm->read_lock);
+	list_add_tail(&rcv->list, &acm->spare_read_urbs);
+	list_add_tail(&buf->list, &acm->filled_read_bufs);
+	spin_unlock(&acm->read_lock);
+
+	tasklet_schedule(&acm->urb_task);
 }
 
 static void acm_rx_tasklet(unsigned long _acm)
 {
 	struct acm *acm = (void *)_acm;
-	struct urb *urb = acm->readurb;
+	struct acm_rb *buf;
 	struct tty_struct *tty = acm->tty;
-	unsigned char *data = urb->transfer_buffer;
+	struct acm_ru *rcv;
+	//unsigned long flags;
 	int i = 0;
 	dbg("Entering acm_rx_tasklet");
 
-	if (urb->actual_length > 0 && !acm->throttle)  {
-		for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters,
-			 * we drop them. */
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			tty_insert_flip_char(tty, data[i], 0);
-		}
-		dbg("Handed %d bytes to tty layer", i+1);
-		tty_flip_buffer_push(tty);
+	if (!ACM_READY(acm) || acm->throttle)
+		return;
+
+next_buffer:
+	spin_lock(&acm->read_lock);
+	if (list_empty(&acm->filled_read_bufs)) {
+		spin_unlock(&acm->read_lock);
+		goto urbs;
 	}
+	buf = list_entry(acm->filled_read_bufs.next,
+			 struct acm_rb, list);
+	list_del(&buf->list);
+	spin_unlock(&acm->read_lock);
+
+	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
+
+	for (i = 0; i < buf->size && !acm->throttle; i++) {
+		/* if we insert more than TTY_FLIPBUF_SIZE characters,
+		   we drop them. */
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			tty_flip_buffer_push(tty);
+ 		}
+		tty_insert_flip_char(tty, buf->base[i], 0);
+ 	}
+	tty_flip_buffer_push(tty);
 
 	spin_lock(&acm->throttle_lock);
 	if (acm->throttle) {
 		dbg("Throtteling noticed");
-		memmove(data, data + i, urb->actual_length - i);
-		urb->actual_length -= i;
-		acm->resubmit_to_unthrottle = 1;
+		memmove(buf->base, buf->base + i, buf->size - i);
+		buf->size -= i;
 		spin_unlock(&acm->throttle_lock);
+		spin_lock(&acm->read_lock);
+		list_add(&buf->list, &acm->filled_read_bufs);
+		spin_unlock(&acm->read_lock);
 		return;
 	}
 	spin_unlock(&acm->throttle_lock);
 
-	urb->actual_length = 0;
-	urb->dev = acm->dev;
+	spin_lock(&acm->read_lock);
+	list_add(&buf->list, &acm->spare_read_bufs);
+	spin_unlock(&acm->read_lock);
+	goto next_buffer;
 
-	i = usb_submit_urb(urb, GFP_ATOMIC);
-	if (i)
-		dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
+urbs:
+	while (!list_empty(&acm->spare_read_bufs)) {
+		spin_lock(&acm->read_lock);
+		if (list_empty(&acm->spare_read_urbs)) {
+			spin_unlock(&acm->read_lock);
+			return;
+		}
+		rcv = list_entry(acm->spare_read_urbs.next,
+				 struct acm_ru, list);
+		list_del(&rcv->list);
+		spin_unlock(&acm->read_lock);
+
+		buf = list_entry(acm->spare_read_bufs.next,
+				 struct acm_rb, list);
+		list_del(&buf->list);
+
+		rcv->buffer = buf;
+
+		usb_fill_bulk_urb(rcv->urb, acm->dev,
+				  acm->rx_endpoint,
+				  buf->base,
+				  acm->readsize,
+				  acm_read_bulk, rcv);
+		rcv->urb->transfer_dma = buf->dma;
+		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
+
+		/* This shouldn't kill the driver as unsuccessful URBs are returned to the
+		   free-urbs-pool and resubmited ASAP */
+		if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+			list_add(&buf->list, &acm->spare_read_bufs);
+			spin_lock(&acm->read_lock);
+			list_add(&rcv->list, &acm->spare_read_urbs);
+			spin_unlock(&acm->read_lock);
+			return;
+		}
+	}
 }
 
 /* data interface wrote those outgoing bytes */
@@ -369,6 +434,7 @@
 {
 	struct acm *acm;
 	int rv = -EINVAL;
+	int i;
 	dbg("Entering acm_tty_open.\n");
 	
 	down(&open_sem);
@@ -382,7 +448,9 @@
 	tty->driver_data = acm;
 	acm->tty = tty;
 
-
+	/* force low_latency on so that our tty_push actually forces the data through,
+	   otherwise it is scheduled, and with high data rates data can get lost. */
+	tty->low_latency = 1;
 
 	if (acm->used++) {
 		goto done;
@@ -394,18 +462,20 @@
 		goto bail_out;
 	}
 
-	acm->readurb->dev = acm->dev;
-	if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
-		dbg("usb_submit_urb(read bulk) failed");
-		goto bail_out_and_unlink;
-	}
-
 	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
 		goto full_bailout;
 
-	/* force low_latency on so that our tty_push actually forces the data through, 
-	   otherwise it is scheduled, and with high data rates data can get lost. */
-	tty->low_latency = 1;
+	INIT_LIST_HEAD(&acm->spare_read_urbs);
+	INIT_LIST_HEAD(&acm->spare_read_bufs);
+	INIT_LIST_HEAD(&acm->filled_read_bufs);
+	for (i = 0; i < ACM_NRU; i++) {
+		list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
+	}
+	for (i = 0; i < ACM_NRB; i++) {
+		list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
+	}
+
+	tasklet_schedule(&acm->urb_task);
 
 done:
 err_out:
@@ -413,8 +483,6 @@
 	return rv;
 
 full_bailout:
-	usb_kill_urb(acm->readurb);
-bail_out_and_unlink:
 	usb_kill_urb(acm->ctrlurb);
 bail_out:
 	acm->used--;
@@ -424,18 +492,22 @@
 
 static void acm_tty_unregister(struct acm *acm)
 {
+	int i;
+
 	tty_unregister_device(acm_tty_driver, acm->minor);
 	usb_put_intf(acm->control);
 	acm_table[acm->minor] = NULL;
 	usb_free_urb(acm->ctrlurb);
-	usb_free_urb(acm->readurb);
 	usb_free_urb(acm->writeurb);
+	for (i = 0; i < ACM_NRU; i++)
+		usb_free_urb(acm->ru[i].urb);
 	kfree(acm);
 }
 
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct acm *acm = tty->driver_data;
+	int i;
 
 	if (!acm || !acm->used)
 		return;
@@ -446,7 +518,8 @@
 			acm_set_control(acm, acm->ctrlout = 0);
 			usb_kill_urb(acm->ctrlurb);
 			usb_kill_urb(acm->writeurb);
-			usb_kill_urb(acm->readurb);
+			for (i = 0; i < ACM_NRU; i++)
+				usb_kill_urb(acm->ru[i].urb);
 		} else
 			acm_tty_unregister(acm);
 	}
@@ -528,10 +601,7 @@
 	spin_lock_bh(&acm->throttle_lock);
 	acm->throttle = 0;
 	spin_unlock_bh(&acm->throttle_lock);
-	if (acm->resubmit_to_unthrottle) {
-		acm->resubmit_to_unthrottle = 0;
-		acm_read_bulk(acm->readurb, NULL);
-	}
+	tasklet_schedule(&acm->urb_task);
 }
 
 static void acm_tty_break_ctl(struct tty_struct *tty, int state)
@@ -588,7 +658,7 @@
 	return -ENOIOCTLCMD;
 }
 
-static __u32 acm_tty_speed[] = {
+static const __u32 acm_tty_speed[] = {
 	0, 50, 75, 110, 134, 150, 200, 300, 600,
 	1200, 1800, 2400, 4800, 9600, 19200, 38400,
 	57600, 115200, 230400, 460800, 500000, 576000,
@@ -596,7 +666,7 @@
 	2500000, 3000000, 3500000, 4000000
 };
 
-static __u8 acm_tty_size[] = {
+static const __u8 acm_tty_size[] = {
 	5, 6, 7, 8
 };
 
@@ -694,6 +764,7 @@
 	int call_interface_num = -1;
 	int data_interface_num;
 	unsigned long quirks;
+	int i;
 
 	/* handle quirks deadly to normal probing*/
 	quirks = (unsigned long)id->driver_info;
@@ -833,7 +904,7 @@
 	}
 
 	ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
-	readsize = le16_to_cpu(epread->wMaxPacketSize);
+	readsize = le16_to_cpu(epread->wMaxPacketSize)*2;
 	acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
 	acm->control = control_interface;
 	acm->data = data_interface;
@@ -842,12 +913,14 @@
 	acm->ctrl_caps = ac_management_function;
 	acm->ctrlsize = ctrlsize;
 	acm->readsize = readsize;
-	acm->bh.func = acm_rx_tasklet;
-	acm->bh.data = (unsigned long) acm;
+	acm->urb_task.func = acm_rx_tasklet;
+	acm->urb_task.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint, acm);
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
+	spin_lock_init(&acm->read_lock);
 	acm->write_ready = 1;
+	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 
 	buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
 	if (!buf) {
@@ -856,13 +929,6 @@
 	}
 	acm->ctrl_buffer = buf;
 
-	buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
-	if (!buf) {
-		dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
-		goto alloc_fail3;
-	}
-	acm->read_buffer = buf;
-
 	if (acm_write_buffers_alloc(acm) < 0) {
 		dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
 		goto alloc_fail4;
@@ -873,10 +939,25 @@
 		dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
 		goto alloc_fail5;
 	}
-	acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!acm->readurb) {
-		dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
-		goto alloc_fail6;
+	for (i = 0; i < ACM_NRU; i++) {
+		struct acm_ru *rcv = &(acm->ru[i]);
+
+		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+			dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
+			goto alloc_fail7;
+		}
+
+		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		rcv->instance = acm;
+	}
+	for (i = 0; i < ACM_NRB; i++) {
+		struct acm_rb *buf = &(acm->rb[i]);
+
+		// Using usb_buffer_alloc instead of kmalloc as Oliver suggested
+		if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
+			dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
+			goto alloc_fail7;
+		}
 	}
 	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!acm->writeurb) {
@@ -889,15 +970,9 @@
 	acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	acm->ctrlurb->transfer_dma = acm->ctrl_dma;
 
-	usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
-			  acm->read_buffer, readsize, acm_read_bulk, acm);
-	acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
-	acm->readurb->transfer_dma = acm->read_dma;
-
 	usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
 			  NULL, acm->writesize, acm_write_bulk, acm);
 	acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
-	/* acm->writeurb->transfer_dma = 0; */
 
 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
 
@@ -917,14 +992,14 @@
 	return 0;
 
 alloc_fail7:
-	usb_free_urb(acm->readurb);
-alloc_fail6:
+	for (i = 0; i < ACM_NRB; i++)
+		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+	for (i = 0; i < ACM_NRU; i++)
+		usb_free_urb(acm->ru[i].urb);
 	usb_free_urb(acm->ctrlurb);
 alloc_fail5:
 	acm_write_buffers_free(acm);
 alloc_fail4:
-	usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
-alloc_fail3:
 	usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
 alloc_fail2:
 	kfree(acm);
@@ -936,6 +1011,7 @@
 {
 	struct acm *acm = usb_get_intfdata (intf);
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	int i;
 
 	if (!acm || !acm->dev) {
 		dbg("disconnect on nonexisting interface");
@@ -946,15 +1022,24 @@
 	acm->dev = NULL;
 	usb_set_intfdata (intf, NULL);
 
+	tasklet_disable(&acm->urb_task);
+
 	usb_kill_urb(acm->ctrlurb);
-	usb_kill_urb(acm->readurb);
 	usb_kill_urb(acm->writeurb);
+	for (i = 0; i < ACM_NRU; i++)
+		usb_kill_urb(acm->ru[i].urb);
+
+	INIT_LIST_HEAD(&acm->filled_read_bufs);
+	INIT_LIST_HEAD(&acm->spare_read_bufs);
+
+	tasklet_enable(&acm->urb_task);
 
 	flush_scheduled_work(); /* wait for acm_softint */
 
 	acm_write_buffers_free(acm);
-	usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
+	for (i = 0; i < ACM_NRB; i++)
+		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
 
 	usb_driver_release_interface(&acm_driver, acm->data);
 
@@ -1003,7 +1088,6 @@
 MODULE_DEVICE_TABLE (usb, acm_ids);
 
 static struct usb_driver acm_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cdc_acm",
 	.probe =	acm_probe,
 	.disconnect =	acm_disconnect,
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 963a5df..fd2aaccd 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -59,6 +59,9 @@
  * when processing onlcr, so we only need 2 buffers.
  */
 #define ACM_NWB  2
+#define ACM_NRU  16
+#define ACM_NRB  16
+
 struct acm_wb {
 	unsigned char *buf;
 	dma_addr_t dmah;
@@ -66,22 +69,43 @@
 	int use;
 };
 
+struct acm_rb {
+	struct list_head	list;
+	int			size;
+	unsigned char		*base;
+	dma_addr_t		dma;
+};
+
+struct acm_ru {
+	struct list_head	list;
+	struct acm_rb		*buffer;
+	struct urb		*urb;
+	struct acm		*instance;
+};
+
 struct acm {
 	struct usb_device *dev;				/* the corresponding usb device */
 	struct usb_interface *control;			/* control interface */
 	struct usb_interface *data;			/* data interface */
 	struct tty_struct *tty;				/* the corresponding tty */
-	struct urb *ctrlurb, *readurb, *writeurb;	/* urbs */
-	u8 *ctrl_buffer, *read_buffer;			/* buffers of urbs */
-	dma_addr_t ctrl_dma, read_dma;			/* dma handles of buffers */
+	struct urb *ctrlurb, *writeurb;			/* urbs */
+	u8 *ctrl_buffer;				/* buffers of urbs */
+	dma_addr_t ctrl_dma;				/* dma handles of buffers */
 	struct acm_wb wb[ACM_NWB];
+	struct acm_ru ru[ACM_NRU];
+	struct acm_rb rb[ACM_NRB];
+	int rx_endpoint;
+	spinlock_t read_lock;
+	struct list_head spare_read_urbs;
+	struct list_head spare_read_bufs;
+	struct list_head filled_read_bufs;
 	int write_current;				/* current write buffer */
 	int write_used;					/* number of non-empty write buffers */
 	int write_ready;				/* write urb is not running */
 	spinlock_t write_lock;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
-	struct tasklet_struct bh;			/* rx processing */
+	struct tasklet_struct urb_task;                 /* rx processing */
 	spinlock_t throttle_lock;			/* synchronize throtteling and read callback */
 	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
 	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
@@ -91,7 +115,6 @@
 	unsigned int minor;				/* acm minor number */
 	unsigned char throttle;				/* throttled by tty layer */
 	unsigned char clocal;				/* termios CLOCAL */
-	unsigned char resubmit_to_unthrottle;		/* throtteling has disabled the read urb */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
 };
 
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 5f8af35..f13f004 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -2027,7 +2027,6 @@
 };
 
 static struct usb_driver usb_midi_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"midi",
 	.probe =	usb_midi_probe,
 	.disconnect =	usb_midi_disconnect,
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 357e753..27e9404 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -199,7 +199,7 @@
 #define USBLP_QUIRK_BIDIR	0x1	/* reports bidir but requires unidirectional mode (no INs/reads) */
 #define USBLP_QUIRK_USB_INIT	0x2	/* needs vendor USB init string */
 
-static struct quirk_printer_struct quirk_printers[] = {
+static const struct quirk_printer_struct quirk_printers[] = {
 	{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
 	{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
 	{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
@@ -301,7 +301,7 @@
  * Get and print printer errors.
  */
 
-static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
+static const char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
 
 static int usblp_check_status(struct usblp *usblp, int err)
 {
@@ -438,7 +438,7 @@
  			       | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
 }
 
-static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct usblp *usblp = file->private_data;
 	int length, err, i;
@@ -838,7 +838,8 @@
 	.read =		usblp_read,
 	.write =	usblp_write,
 	.poll =		usblp_poll,
-	.ioctl =	usblp_ioctl,
+	.unlocked_ioctl =	usblp_ioctl,
+	.compat_ioctl =		usblp_ioctl,
 	.open =		usblp_open,
 	.release =	usblp_release,
 };
@@ -849,6 +850,20 @@
 	.minor_base =	USBLP_MINOR_BASE,
 };
 
+static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usblp *usblp = usb_get_intfdata (intf);
+
+	if (usblp->device_id_string[0] == 0 &&
+	    usblp->device_id_string[1] == 0)
+		return 0;
+
+	return sprintf(buf, "%s", usblp->device_id_string+2);
+}
+
+static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL);
+
 static int usblp_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
@@ -933,20 +948,12 @@
 
 	/* Retrieve and store the device ID string. */
 	usblp_cache_device_id_string(usblp);
+	device_create_file(&intf->dev, &dev_attr_ieee1284_id);
 
 #ifdef DEBUG
 	usblp_check_status(usblp, 0);
 #endif
 
-	info("usblp%d: USB %sdirectional printer dev %d "
-		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
-		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
-		usblp->ifnum,
-		usblp->protocol[usblp->current_protocol].alt_setting,
-		usblp->current_protocol,
-		le16_to_cpu(usblp->dev->descriptor.idVendor),
-		le16_to_cpu(usblp->dev->descriptor.idProduct));
-
 	usb_set_intfdata (intf, usblp);
 
 	usblp->present = 1;
@@ -957,11 +964,20 @@
 		goto abort_intfdata;
 	}
 	usblp->minor = intf->minor;
+	info("usblp%d: USB %sdirectional printer dev %d "
+		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
+		usblp->ifnum,
+		usblp->protocol[usblp->current_protocol].alt_setting,
+		usblp->current_protocol,
+		le16_to_cpu(usblp->dev->descriptor.idVendor),
+		le16_to_cpu(usblp->dev->descriptor.idProduct));
 
 	return 0;
 
 abort_intfdata:
 	usb_set_intfdata (intf, NULL);
+	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 abort:
 	if (usblp) {
 		if (usblp->writebuf)
@@ -1156,6 +1172,8 @@
 		BUG ();
 	}
 
+	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
+
 	down (&usblp_sem);
 	down (&usblp->sem);
 	usblp->present = 0;
@@ -1186,7 +1204,6 @@
 MODULE_DEVICE_TABLE (usb, usblp_ids);
 
 static struct usb_driver usblp_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usblp",
 	.probe =	usblp_probe,
 	.disconnect =	usblp_disconnect,
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 86d5c38..28329dd 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -2,7 +2,7 @@
 # Makefile for USB Core files and filesystem
 #
 
-usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o \
+usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
 			config.o file.o buffer.o sysfs.o devio.o notify.o
 
 ifeq ($(CONFIG_PCI),y)
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 419c994..ad742ce 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -55,6 +55,9 @@
 	char		name [16];
 	int 		i, size;
 
+	if (!hcd->self.controller->dma_mask)
+		return 0;
+
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
 		if (!(size = pool_max [i]))
 			continue;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 83e815d..2684e15 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -67,45 +67,45 @@
 /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
 #define ALLOW_SERIAL_NUMBER
 
-static char *format_topo =
+static const char *format_topo =
 /* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
 "\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
 
-static char *format_string_manufacturer =
+static const char *format_string_manufacturer =
 /* S:  Manufacturer=xxxx */
   "S:  Manufacturer=%.100s\n";
 
-static char *format_string_product =
+static const char *format_string_product =
 /* S:  Product=xxxx */
   "S:  Product=%.100s\n";
 
 #ifdef ALLOW_SERIAL_NUMBER
-static char *format_string_serialnumber =
+static const char *format_string_serialnumber =
 /* S:  SerialNumber=xxxx */
   "S:  SerialNumber=%.100s\n";
 #endif
 
-static char *format_bandwidth =
+static const char *format_bandwidth =
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
   "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
   
-static char *format_device1 =
+static const char *format_device1 =
 /* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
   "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
 
-static char *format_device2 =
+static const char *format_device2 =
 /* P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx */
   "P:  Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
 
-static char *format_config =
+static const char *format_config =
 /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
   
-static char *format_iface =
+static const char *format_iface =
 /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
   "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
 
-static char *format_endpt =
+static const char *format_endpt =
 /* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
   "E:  Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
 
@@ -545,10 +545,10 @@
 		struct usb_device *childdev = usbdev->children[chix];
 
 		if (childdev) {
-			down(&childdev->serialize);
+			usb_lock_device(childdev);
 			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
 					bus, level + 1, chix, ++cnt);
-			up(&childdev->serialize);
+			usb_unlock_device(childdev);
 			if (ret == -EFAULT)
 				return total_written;
 			total_written += ret;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index b1d6e9a..2b68998 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -402,7 +402,6 @@
 }
 
 struct usb_driver usbfs_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbfs",
 	.probe =	driver_probe,
 	.disconnect =	driver_disconnect,
@@ -1350,9 +1349,7 @@
 	/* let kernel drivers try to (re)bind to the interface */
 	case USBDEVFS_CONNECT:
 		usb_unlock_device(ps->dev);
-		usb_lock_all_devices();
 		bus_rescan_devices(intf->dev.bus);
-		usb_unlock_all_devices();
 		usb_lock_device(ps->dev);
 		break;
 
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
new file mode 100644
index 0000000..076462c
--- /dev/null
+++ b/drivers/usb/core/driver.c
@@ -0,0 +1,472 @@
+/*
+ * drivers/usb/driver.c - most of the driver model stuff for usb
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * based on drivers/usb/usb.c which had the following copyrights:
+ *	(C) Copyright Linus Torvalds 1999
+ *	(C) Copyright Johannes Erdfelt 1999-2001
+ *	(C) Copyright Andreas Gal 1999
+ *	(C) Copyright Gregory P. Smith 1999
+ *	(C) Copyright Deti Fliegl 1999 (new USB architecture)
+ *	(C) Copyright Randy Dunlap 2000
+ *	(C) Copyright David Brownell 2000-2004
+ *	(C) Copyright Yggdrasil Computing, Inc. 2000
+ *		(usb_device_id matching changes by Adam J. Richter)
+ *	(C) Copyright Greg Kroah-Hartman 2002-2003
+ *
+ * NOTE! This is not actually a driver at all, rather this is
+ * just a collection of helper routines that implement the
+ * generic USB things that the real drivers can use..
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+#include "hcd.h"
+#include "usb.h"
+
+static int usb_match_one_id(struct usb_interface *interface,
+			    const struct usb_device_id *id);
+
+struct usb_dynid {
+	struct list_head node;
+	struct usb_device_id id;
+};
+
+
+static int generic_probe(struct device *dev)
+{
+	return 0;
+}
+static int generic_remove(struct device *dev)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	/* if this is only an unbind, not a physical disconnect, then
+	 * unconfigure the device */
+	if (udev->state == USB_STATE_CONFIGURED)
+		usb_set_configuration(udev, 0);
+
+	/* in case the call failed or the device was suspended */
+	if (udev->state >= USB_STATE_CONFIGURED)
+		usb_disable_device(udev, 0);
+	return 0;
+}
+
+struct device_driver usb_generic_driver = {
+	.owner = THIS_MODULE,
+	.name =	"usb",
+	.bus = &usb_bus_type,
+	.probe = generic_probe,
+	.remove = generic_remove,
+};
+
+/* Fun hack to determine if the struct device is a
+ * usb device or a usb interface. */
+int usb_generic_driver_data;
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Adds a new dynamic USBdevice ID to this driver,
+ * and cause the driver to probe for all devices again.
+ */
+static ssize_t store_new_id(struct device_driver *driver,
+			    const char *buf, size_t count)
+{
+	struct usb_driver *usb_drv = to_usb_driver(driver);
+	struct usb_dynid *dynid;
+	u32 idVendor = 0;
+	u32 idProduct = 0;
+	int fields = 0;
+
+	fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
+	if (fields < 2)
+		return -EINVAL;
+
+	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+	if (!dynid)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dynid->node);
+	dynid->id.idVendor = idVendor;
+	dynid->id.idProduct = idProduct;
+	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+
+	spin_lock(&usb_drv->dynids.lock);
+	list_add_tail(&usb_drv->dynids.list, &dynid->node);
+	spin_unlock(&usb_drv->dynids.lock);
+
+	if (get_driver(driver)) {
+		driver_attach(driver);
+		put_driver(driver);
+	}
+
+	return count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+static int usb_create_newid_file(struct usb_driver *usb_drv)
+{
+	int error = 0;
+
+	if (usb_drv->no_dynamic_id)
+		goto exit;
+
+	if (usb_drv->probe != NULL)
+		error = sysfs_create_file(&usb_drv->driver.kobj,
+					  &driver_attr_new_id.attr);
+exit:
+	return error;
+}
+
+static void usb_remove_newid_file(struct usb_driver *usb_drv)
+{
+	if (usb_drv->no_dynamic_id)
+		return;
+
+	if (usb_drv->probe != NULL)
+		sysfs_remove_file(&usb_drv->driver.kobj,
+				  &driver_attr_new_id.attr);
+}
+
+static void usb_free_dynids(struct usb_driver *usb_drv)
+{
+	struct usb_dynid *dynid, *n;
+
+	spin_lock(&usb_drv->dynids.lock);
+	list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
+		list_del(&dynid->node);
+		kfree(dynid);
+	}
+	spin_unlock(&usb_drv->dynids.lock);
+}
+#else
+static inline int usb_create_newid_file(struct usb_driver *usb_drv)
+{
+	return 0;
+}
+
+static void usb_remove_newid_file(struct usb_driver *usb_drv)
+{
+}
+
+static inline void usb_free_dynids(struct usb_driver *usb_drv)
+{
+}
+#endif
+
+static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
+							struct usb_driver *drv)
+{
+	struct usb_dynid *dynid;
+
+	spin_lock(&drv->dynids.lock);
+	list_for_each_entry(dynid, &drv->dynids.list, node) {
+		if (usb_match_one_id(intf, &dynid->id)) {
+			spin_unlock(&drv->dynids.lock);
+			return &dynid->id;
+		}
+	}
+	spin_unlock(&drv->dynids.lock);
+	return NULL;
+}
+
+
+/* called from driver core with usb_bus_type.subsys writelock */
+static int usb_probe_interface(struct device *dev)
+{
+	struct usb_interface * intf = to_usb_interface(dev);
+	struct usb_driver * driver = to_usb_driver(dev->driver);
+	const struct usb_device_id *id;
+	int error = -ENODEV;
+
+	dev_dbg(dev, "%s\n", __FUNCTION__);
+
+	if (!driver->probe)
+		return error;
+	/* FIXME we'd much prefer to just resume it ... */
+	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
+	id = usb_match_id(intf, driver->id_table);
+	if (!id)
+		id = usb_match_dynamic_id(intf, driver);
+	if (id) {
+		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
+
+		/* Interface "power state" doesn't correspond to any hardware
+		 * state whatsoever.  We use it to record when it's bound to
+		 * a driver that may start I/0:  it's not frozen/quiesced.
+		 */
+		mark_active(intf);
+		intf->condition = USB_INTERFACE_BINDING;
+		error = driver->probe(intf, id);
+		if (error) {
+			mark_quiesced(intf);
+			intf->condition = USB_INTERFACE_UNBOUND;
+		} else
+			intf->condition = USB_INTERFACE_BOUND;
+	}
+
+	return error;
+}
+
+/* called from driver core with usb_bus_type.subsys writelock */
+static int usb_unbind_interface(struct device *dev)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+
+	intf->condition = USB_INTERFACE_UNBINDING;
+
+	/* release all urbs for this interface */
+	usb_disable_interface(interface_to_usbdev(intf), intf);
+
+	if (driver && driver->disconnect)
+		driver->disconnect(intf);
+
+	/* reset other interface state */
+	usb_set_interface(interface_to_usbdev(intf),
+			intf->altsetting[0].desc.bInterfaceNumber,
+			0);
+	usb_set_intfdata(intf, NULL);
+	intf->condition = USB_INTERFACE_UNBOUND;
+	mark_quiesced(intf);
+
+	return 0;
+}
+
+/* returns 0 if no match, 1 if match */
+static int usb_match_one_id(struct usb_interface *interface,
+			    const struct usb_device_id *id)
+{
+	struct usb_host_interface *intf;
+	struct usb_device *dev;
+
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return 0;
+
+	intf = interface->cur_altsetting;
+	dev = interface_to_usbdev(interface);
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+	    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+	    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
+		return 0;
+
+	/* No need to test id->bcdDevice_lo != 0, since 0 is never
+	   greater than any unsigned number. */
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+	    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+	    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+	    (id->bDeviceClass != dev->descriptor.bDeviceClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+	    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
+	    (id->bInterfaceClass != intf->desc.bInterfaceClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
+	    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
+	    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
+		return 0;
+
+	return 1;
+}
+/**
+ * usb_match_id - find first usb_device_id matching device or interface
+ * @interface: the interface of interest
+ * @id: array of usb_device_id structures, terminated by zero entry
+ *
+ * usb_match_id searches an array of usb_device_id's and returns
+ * the first one matching the device or interface, or null.
+ * This is used when binding (or rebinding) a driver to an interface.
+ * Most USB device drivers will use this indirectly, through the usb core,
+ * but some layered driver frameworks use it directly.
+ * These device tables are exported with MODULE_DEVICE_TABLE, through
+ * modutils, to support the driver loading functionality of USB hotplugging.
+ *
+ * What Matches:
+ *
+ * The "match_flags" element in a usb_device_id controls which
+ * members are used.  If the corresponding bit is set, the
+ * value in the device_id must match its corresponding member
+ * in the device or interface descriptor, or else the device_id
+ * does not match.
+ *
+ * "driver_info" is normally used only by device drivers,
+ * but you can create a wildcard "matches anything" usb_device_id
+ * as a driver's "modules.usbmap" entry if you provide an id with
+ * only a nonzero "driver_info" field.  If you do this, the USB device
+ * driver's probe() routine should use additional intelligence to
+ * decide whether to bind to the specified interface.
+ *
+ * What Makes Good usb_device_id Tables:
+ *
+ * The match algorithm is very simple, so that intelligence in
+ * driver selection must come from smart driver id records.
+ * Unless you have good reasons to use another selection policy,
+ * provide match elements only in related groups, and order match
+ * specifiers from specific to general.  Use the macros provided
+ * for that purpose if you can.
+ *
+ * The most specific match specifiers use device descriptor
+ * data.  These are commonly used with product-specific matches;
+ * the USB_DEVICE macro lets you provide vendor and product IDs,
+ * and you can also match against ranges of product revisions.
+ * These are widely used for devices with application or vendor
+ * specific bDeviceClass values.
+ *
+ * Matches based on device class/subclass/protocol specifications
+ * are slightly more general; use the USB_DEVICE_INFO macro, or
+ * its siblings.  These are used with single-function devices
+ * where bDeviceClass doesn't specify that each interface has
+ * its own class.
+ *
+ * Matches based on interface class/subclass/protocol are the
+ * most general; they let drivers bind to any interface on a
+ * multiple-function device.  Use the USB_INTERFACE_INFO
+ * macro, or its siblings, to match class-per-interface style
+ * devices (as recorded in bDeviceClass).
+ *
+ * Within those groups, remember that not all combinations are
+ * meaningful.  For example, don't give a product version range
+ * without vendor and product IDs; or specify a protocol without
+ * its associated class and subclass.
+ */
+const struct usb_device_id *usb_match_id(struct usb_interface *interface,
+					 const struct usb_device_id *id)
+{
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return NULL;
+
+	/* It is important to check that id->driver_info is nonzero,
+	   since an entry that is all zeroes except for a nonzero
+	   id->driver_info is the way to create an entry that
+	   indicates that the driver want to examine every
+	   device and interface. */
+	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+	       id->driver_info; id++) {
+		if (usb_match_one_id(interface, id))
+			return id;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(usb_match_id);
+
+int usb_device_match(struct device *dev, struct device_driver *drv)
+{
+	struct usb_interface *intf;
+	struct usb_driver *usb_drv;
+	const struct usb_device_id *id;
+
+	/* check for generic driver, which we don't match any device with */
+	if (drv == &usb_generic_driver)
+		return 0;
+
+	intf = to_usb_interface(dev);
+	usb_drv = to_usb_driver(drv);
+
+	id = usb_match_id(intf, usb_drv->id_table);
+	if (id)
+		return 1;
+
+	id = usb_match_dynamic_id(intf, usb_drv);
+	if (id)
+		return 1;
+	return 0;
+}
+
+/**
+ * usb_register_driver - register a USB driver
+ * @new_driver: USB operations for the driver
+ * @owner: module owner of this driver.
+ *
+ * Registers a USB driver with the USB core.  The list of unattached
+ * interfaces will be rescanned whenever a new driver is added, allowing
+ * the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ *
+ * NOTE: if you want your driver to use the USB major number, you must call
+ * usb_register_dev() to enable that functionality.  This function no longer
+ * takes care of that.
+ */
+int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+{
+	int retval = 0;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	new_driver->driver.name = (char *)new_driver->name;
+	new_driver->driver.bus = &usb_bus_type;
+	new_driver->driver.probe = usb_probe_interface;
+	new_driver->driver.remove = usb_unbind_interface;
+	new_driver->driver.owner = owner;
+	spin_lock_init(&new_driver->dynids.lock);
+	INIT_LIST_HEAD(&new_driver->dynids.list);
+
+	retval = driver_register(&new_driver->driver);
+
+	if (!retval) {
+		pr_info("%s: registered new driver %s\n",
+			usbcore_name, new_driver->name);
+		usbfs_update_special();
+		usb_create_newid_file(new_driver);
+	} else {
+		printk(KERN_ERR "%s: error %d registering driver %s\n",
+			usbcore_name, retval, new_driver->name);
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(usb_register_driver);
+
+/**
+ * usb_deregister - unregister a USB driver
+ * @driver: USB operations of the driver to unregister
+ * Context: must be able to sleep
+ *
+ * Unlinks the specified driver from the internal USB driver list.
+ *
+ * NOTE: If you called usb_register_dev(), you still need to call
+ * usb_deregister_dev() to clean up your driver's allocated minor numbers,
+ * this * call will no longer do it for you.
+ */
+void usb_deregister(struct usb_driver *driver)
+{
+	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+
+	usb_remove_newid_file(driver);
+	usb_free_dynids(driver);
+	driver_unregister(&driver->driver);
+
+	usbfs_update_special();
+}
+EXPORT_SYMBOL_GPL(usb_deregister);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index da24c31..0018bbc 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -857,9 +857,7 @@
 		return (retval < 0) ? retval : -EMSGSIZE;
 	}
 
-	usb_lock_device (usb_dev);
 	retval = usb_new_device (usb_dev);
-	usb_unlock_device (usb_dev);
 	if (retval) {
 		usb_dev->bus->root_hub = NULL;
 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
@@ -1827,8 +1825,6 @@
 		retval = -ENOMEM;
 		goto err_allocate_root_hub;
 	}
-	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
-			USB_SPEED_FULL;
 
 	/* Although in principle hcd->driver->start() might need to use rhdev,
 	 * none of the current drivers do.
@@ -1846,6 +1842,9 @@
 		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 	hcd->remote_wakeup = hcd->can_wakeup;
 
+	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
+			USB_SPEED_FULL;
+	rhdev->bus_mA = min(500u, hcd->power_budget);
 	if ((retval = register_root_hub(rhdev, hcd)) != 0)
 		goto err_register_root_hub;
 
@@ -1891,7 +1890,10 @@
 	spin_lock_irq (&hcd_root_hub_lock);
 	hcd->rh_registered = 0;
 	spin_unlock_irq (&hcd_root_hub_lock);
+
+	down(&usb_bus_list_lock);
 	usb_disconnect(&hcd->self.root_hub);
+	up(&usb_bus_list_lock);
 
 	hcd->poll_rh = 0;
 	del_timer_sync(&hcd->rh_timer);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index c8a1b35..591b5aa 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -380,6 +380,7 @@
 #ifdef CONFIG_PM
 extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+extern void usb_root_hub_lost_power (struct usb_device *rhdev);
 extern int hcd_bus_suspend (struct usb_bus *bus);
 extern int hcd_bus_resume (struct usb_bus *bus);
 #else
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f78bd12..650d5ee 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -32,7 +32,7 @@
 #include "hub.h"
 
 /* Protect struct usb_device->state and ->children members
- * Note: Both are also protected by ->serialize, except that ->state can
+ * Note: Both are also protected by ->dev.sem, except that ->state can
  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
 static DEFINE_SPINLOCK(device_state_lock);
 
@@ -515,6 +515,31 @@
 	return ret;
 }
 
+
+/* caller has locked the hub device */
+static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
+{
+	struct usb_device *hdev = hub->hdev;
+	int port1;
+
+	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+		if (hdev->children[port1 - 1]) {
+			usb_disconnect(&hdev->children[port1 - 1]);
+			if (disable_ports)
+				hub_port_disable(hub, port1, 0);
+		}
+	}
+	hub_quiesce(hub);
+}
+
+/* caller has locked the hub device */
+static void hub_post_reset(struct usb_hub *hub)
+{
+	hub_activate(hub);
+	hub_power_on(hub);
+}
+
+
 static int hub_configure(struct usb_hub *hub,
 	struct usb_endpoint_descriptor *endpoint)
 {
@@ -677,26 +702,40 @@
 	 * and battery-powered root hubs (may provide just 8 mA).
 	 */
 	ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
-	if (ret < 0) {
+	if (ret < 2) {
 		message = "can't get hub status";
 		goto fail;
 	}
 	le16_to_cpus(&hubstatus);
 	if (hdev == hdev->bus->root_hub) {
-		struct usb_hcd *hcd =
-				container_of(hdev->bus, struct usb_hcd, self);
-
-		hub->power_budget = min(500u, hcd->power_budget) / 2;
+		if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
+			hub->mA_per_port = 500;
+		else {
+			hub->mA_per_port = hdev->bus_mA;
+			hub->limited_power = 1;
+		}
 	} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
 		dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
 			hub->descriptor->bHubContrCurrent);
-		hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
-					/ 2;
-	}
-	if (hub->power_budget)
-		dev_dbg(hub_dev, "%dmA bus power budget for children\n",
-			hub->power_budget * 2);
+		hub->limited_power = 1;
+		if (hdev->maxchild > 0) {
+			int remaining = hdev->bus_mA -
+					hub->descriptor->bHubContrCurrent;
 
+			if (remaining < hdev->maxchild * 100)
+				dev_warn(hub_dev,
+					"insufficient power available "
+					"to use all downstream ports\n");
+			hub->mA_per_port = 100;		/* 7.2.1.1 */
+		}
+	} else {	/* Self-powered external hub */
+		/* FIXME: What about battery-powered external hubs that
+		 * provide less current per port? */
+		hub->mA_per_port = 500;
+	}
+	if (hub->mA_per_port < 500)
+		dev_dbg(hub_dev, "%umA bus power budget for each child\n",
+				hub->mA_per_port);
 
 	ret = hub_hub_status(hub, &hubstatus, &hubchange);
 	if (ret < 0) {
@@ -750,29 +789,10 @@
 
 static unsigned highspeed_hubs;
 
-/* Called after the hub driver is unbound from a hub with children */
-static void hub_remove_children_work(void *__hub)
-{
-	struct usb_hub		*hub = __hub;
-	struct usb_device	*hdev = hub->hdev;
-	int			i;
-
-	kfree(hub);
-
-	usb_lock_device(hdev);
-	for (i = 0; i < hdev->maxchild; ++i) {
-		if (hdev->children[i])
-			usb_disconnect(&hdev->children[i]);
-	}
-	usb_unlock_device(hdev);
-	usb_put_dev(hdev);
-}
-
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
 	struct usb_device *hdev;
-	int n, port1;
 
 	usb_set_intfdata (intf, NULL);
 	hdev = hub->hdev;
@@ -780,7 +800,9 @@
 	if (hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs--;
 
-	hub_quiesce(hub);
+	/* Disconnect all children and quiesce the hub */
+	hub_pre_reset(hub, 1);
+
 	usb_free_urb(hub->urb);
 	hub->urb = NULL;
 
@@ -800,27 +822,7 @@
 		hub->buffer = NULL;
 	}
 
-	/* If there are any children then this is an unbind only, not a
-	 * physical disconnection.  The active ports must be disabled
-	 * and later on we must call usb_disconnect().  We can't call
-	 * it now because we may not hold the hub's device lock.
-	 */
-	n = 0;
-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
-		if (hdev->children[port1 - 1]) {
-			++n;
-			hub_port_disable(hub, port1, 1);
-		}
-	}
-
-	if (n == 0)
-		kfree(hub);
-	else {
-		/* Reuse the hub->leds work_struct for our own purposes */
-		INIT_WORK(&hub->leds, hub_remove_children_work, hub);
-		schedule_work(&hub->leds);
-		usb_get_dev(hdev);
-	}
+	kfree(hub);
 }
 
 static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -917,26 +919,6 @@
 	}
 }
 
-/* caller has locked the hub device */
-static void hub_pre_reset(struct usb_hub *hub)
-{
-	struct usb_device *hdev = hub->hdev;
-	int i;
-
-	for (i = 0; i < hdev->maxchild; ++i) {
-		if (hdev->children[i])
-			usb_disconnect(&hdev->children[i]);
-	}
-	hub_quiesce(hub);
-}
-
-/* caller has locked the hub device */
-static void hub_post_reset(struct usb_hub *hub)
-{
-	hub_activate(hub);
-	hub_power_on(hub);
-}
-
 
 /* grab device/port lock, returning index of that port (zero based).
  * protects the upstream link used by this device from concurrent
@@ -964,24 +946,21 @@
 	t = locktree(hdev);
 	if (t < 0)
 		return t;
-	for (t = 0; t < hdev->maxchild; t++) {
-		if (hdev->children[t] == udev) {
-			/* everything is fail-fast once disconnect
-			 * processing starts
-			 */
-			if (udev->state == USB_STATE_NOTATTACHED)
-				break;
 
-			/* when everyone grabs locks top->bottom,
-			 * non-overlapping work may be concurrent
-			 */
-			down(&udev->serialize);
-			up(&hdev->serialize);
-			return t + 1;
-		}
+	/* everything is fail-fast once disconnect
+	 * processing starts
+	 */
+	if (udev->state == USB_STATE_NOTATTACHED) {
+		usb_unlock_device(hdev);
+		return -ENODEV;
 	}
+
+	/* when everyone grabs locks top->bottom,
+	 * non-overlapping work may be concurrent
+	 */
+	usb_lock_device(udev);
 	usb_unlock_device(hdev);
-	return -ENODEV;
+	return udev->portnum;
 }
 
 static void recursively_mark_NOTATTACHED(struct usb_device *udev)
@@ -1039,6 +1018,39 @@
 EXPORT_SYMBOL(usb_set_device_state);
 
 
+#ifdef CONFIG_PM
+
+/**
+ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+ * @rhdev: struct usb_device for the root hub
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+ * has been reset.  The routine marks all the children of the root hub
+ * as NOTATTACHED and marks logical connect-change events on their ports.
+ */
+void usb_root_hub_lost_power(struct usb_device *rhdev)
+{
+	struct usb_hub *hub;
+	int port1;
+	unsigned long flags;
+
+	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+	spin_lock_irqsave(&device_state_lock, flags);
+	hub = hdev_to_hub(rhdev);
+	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
+		if (rhdev->children[port1 - 1]) {
+			recursively_mark_NOTATTACHED(
+					rhdev->children[port1 - 1]);
+			set_bit(port1, hub->change_bits);
+		}
+	}
+	spin_unlock_irqrestore(&device_state_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+
+#endif
+
 static void choose_address(struct usb_device *udev)
 {
 	int		devnum;
@@ -1099,16 +1111,10 @@
 	 * this quiesces everyting except pending urbs.
 	 */
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
-
-	/* lock the bus list on behalf of HCDs unregistering their root hubs */
-	if (!udev->parent) {
-		down(&usb_bus_list_lock);
-		usb_lock_device(udev);
-	} else
-		down(&udev->serialize);
-
 	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
 
+	usb_lock_device(udev);
+
 	/* Free up all the children before we remove this device */
 	for (i = 0; i < USB_MAXCHILDREN; i++) {
 		if (udev->children[i])
@@ -1136,54 +1142,112 @@
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
 
-	if (!udev->parent) {
-		usb_unlock_device(udev);
-		up(&usb_bus_list_lock);
-	} else
-		up(&udev->serialize);
+	usb_unlock_device(udev);
 
 	device_unregister(&udev->dev);
 }
 
+static inline const char *plural(int n)
+{
+	return (n == 1 ? "" : "s");
+}
+
 static int choose_configuration(struct usb_device *udev)
 {
-	int c, i;
+	int i;
+	u16 devstatus;
+	int bus_powered;
+	int num_configs;
+	struct usb_host_config *c, *best;
 
-	/* NOTE: this should interact with hub power budgeting */
+	/* If this fails, assume the device is bus-powered */
+	devstatus = 0;
+	usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+	le16_to_cpus(&devstatus);
+	bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
+	dev_dbg(&udev->dev, "device is %s-powered\n",
+			bus_powered ? "bus" : "self");
 
-	c = udev->config[0].desc.bConfigurationValue;
-	if (udev->descriptor.bNumConfigurations != 1) {
-		for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
-			struct usb_interface_descriptor	*desc;
+	best = NULL;
+	c = udev->config;
+	num_configs = udev->descriptor.bNumConfigurations;
+	for (i = 0; i < num_configs; (i++, c++)) {
+		struct usb_interface_descriptor	*desc =
+				&c->intf_cache[0]->altsetting->desc;
 
-			/* heuristic:  Linux is more likely to have class
-			 * drivers, so avoid vendor-specific interfaces.
-			 */
-			desc = &udev->config[i].intf_cache[0]
-					->altsetting->desc;
-			if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
-				continue;
-			/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS.
-			 * MSFT needs this to be the first config; never use
-			 * it as the default unless Linux has host-side RNDIS.
-			 * A second config would ideally be CDC-Ethernet, but
-			 * may instead be the "vendor specific" CDC subset
-			 * long used by ARM Linux for sa1100 or pxa255.
-			 */
-			if (desc->bInterfaceClass == USB_CLASS_COMM
-					&& desc->bInterfaceSubClass == 2
-					&& desc->bInterfaceProtocol == 0xff) {
-				c = udev->config[1].desc.bConfigurationValue;
-				continue;
-			}
-			c = udev->config[i].desc.bConfigurationValue;
+		/*
+		 * HP's USB bus-powered keyboard has only one configuration
+		 * and it claims to be self-powered; other devices may have
+		 * similar errors in their descriptors.  If the next test
+		 * were allowed to execute, such configurations would always
+		 * be rejected and the devices would not work as expected.
+		 */
+#if 0
+		/* Rule out self-powered configs for a bus-powered device */
+		if (bus_powered && (c->desc.bmAttributes &
+					USB_CONFIG_ATT_SELFPOWER))
+			continue;
+#endif
+
+		/*
+		 * The next test may not be as effective as it should be.
+		 * Some hubs have errors in their descriptor, claiming
+		 * to be self-powered when they are really bus-powered.
+		 * We will overestimate the amount of current such hubs
+		 * make available for each port.
+		 *
+		 * This is a fairly benign sort of failure.  It won't
+		 * cause us to reject configurations that we should have
+		 * accepted.
+		 */
+
+		/* Rule out configs that draw too much bus current */
+		if (c->desc.bMaxPower * 2 > udev->bus_mA)
+			continue;
+
+		/* If the first config's first interface is COMM/2/0xff
+		 * (MSFT RNDIS), rule it out unless Linux has host-side
+		 * RNDIS support. */
+		if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM
+				&& desc->bInterfaceSubClass == 2
+				&& desc->bInterfaceProtocol == 0xff) {
+#ifndef CONFIG_USB_NET_RNDIS
+			continue;
+#else
+			best = c;
+#endif
+		}
+
+		/* From the remaining configs, choose the first one whose
+		 * first interface is for a non-vendor-specific class.
+		 * Reason: Linux is more likely to have a class driver
+		 * than a vendor-specific driver. */
+		else if (udev->descriptor.bDeviceClass !=
+						USB_CLASS_VENDOR_SPEC &&
+				desc->bInterfaceClass !=
+						USB_CLASS_VENDOR_SPEC) {
+			best = c;
 			break;
 		}
-		dev_info(&udev->dev,
-			"configuration #%d chosen from %d choices\n",
-			c, udev->descriptor.bNumConfigurations);
+
+		/* If all the remaining configs are vendor-specific,
+		 * choose the first one. */
+		else if (!best)
+			best = c;
 	}
-	return c;
+
+	if (best) {
+		i = best->desc.bConfigurationValue;
+		dev_info(&udev->dev,
+			"configuration #%d chosen from %d choice%s\n",
+			i, num_configs, plural(num_configs));
+	} else {
+		i = -1;
+		dev_warn(&udev->dev,
+			"no configuration chosen from %d choice%s\n",
+			num_configs, plural(num_configs));
+	}
+	return i;
 }
 
 #ifdef DEBUG
@@ -1210,8 +1274,8 @@
  *
  * This is called with devices which have been enumerated, but not yet
  * configured.  The device descriptor is available, but not descriptors
- * for any device configuration.  The caller must have locked udev and
- * either the parent hub (if udev is a normal device) or else the
+ * for any device configuration.  The caller must have locked either
+ * the parent hub (if udev is a normal device) or else the
  * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
  * udev has already been installed, but udev is not yet visible through
  * sysfs or other filesystem code.
@@ -1221,8 +1285,7 @@
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Only the hub driver should ever call this; root hub registration
- * uses it indirectly.
+ * Only the hub driver or root-hub registrar should ever call this.
  */
 int usb_new_device(struct usb_device *udev)
 {
@@ -1269,15 +1332,9 @@
 					le16_to_cpu(udev->config[0].desc.wTotalLength),
 					USB_DT_OTG, (void **) &desc) == 0) {
 			if (desc->bmAttributes & USB_OTG_HNP) {
-				unsigned		port1;
+				unsigned		port1 = udev->portnum;
 				struct usb_device	*root = udev->parent;
 				
-				for (port1 = 1; port1 <= root->maxchild;
-						port1++) {
-					if (root->children[port1-1] == udev)
-						break;
-				}
-
 				dev_info(&udev->dev,
 					"Dual-Role OTG device on %sHNP port\n",
 					(port1 == bus->otg_port)
@@ -1331,27 +1388,27 @@
 	}
 	usb_create_sysfs_dev_files (udev);
 
+	usb_lock_device(udev);
+
 	/* choose and set the configuration. that registers the interfaces
 	 * with the driver core, and lets usb device drivers bind to them.
 	 */
 	c = choose_configuration(udev);
-	if (c < 0)
-		dev_warn(&udev->dev,
-				"can't choose an initial configuration\n");
-	else {
+	if (c >= 0) {
 		err = usb_set_configuration(udev, c);
 		if (err) {
 			dev_err(&udev->dev, "can't set config #%d, error %d\n",
 					c, err);
-			usb_remove_sysfs_dev_files(udev);
-			device_del(&udev->dev);
-			goto fail;
+			/* This need not be fatal.  The user can try to
+			 * set other configurations. */
 		}
 	}
 
 	/* USB device state == configured ... usable */
 	usb_notify_add_device(udev);
 
+	usb_unlock_device(udev);
+
 	return 0;
 
 fail:
@@ -1654,15 +1711,9 @@
 int usb_suspend_device(struct usb_device *udev)
 {
 #ifdef	CONFIG_USB_SUSPEND
-	int	port1, status;
-
-	port1 = locktree(udev);
-	if (port1 < 0)
-		return port1;
-
-	status = __usb_suspend_device(udev, port1);
-	usb_unlock_device(udev);
-	return status;
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
+	return __usb_suspend_device(udev, udev->portnum);
 #else
 	/* NOTE:  udev->state unchanged, it's not lying ... */
 	udev->dev.power.power_state = PMSG_SUSPEND;
@@ -1694,13 +1745,14 @@
 	usb_set_device_state(udev, udev->actconfig
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
+	udev->dev.power.power_state = PMSG_ON;
 
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
 	 * and device drivers will know about any resume quirks.
 	 */
 	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-	if (status < 0)
+	if (status < 2)
 		dev_dbg(&udev->dev,
 			"gone after usb resume? status %d\n",
 			status);
@@ -1709,7 +1761,7 @@
 		int		(*resume)(struct device *);
 
 		le16_to_cpus(&devstatus);
-		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
+		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
 				&& udev->parent) {
 			status = usb_control_msg(udev,
 					usb_sndctrlpipe(udev, 0),
@@ -1729,8 +1781,14 @@
 		 * may have a child resume event to deal with soon
 		 */
 		resume = udev->dev.bus->resume;
-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
-			(void) resume(&udev->actconfig->interface[i]->dev);
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct device *dev =
+					&udev->actconfig->interface[i]->dev;
+
+			down(&dev->sem);
+			(void) resume(dev);
+			up(&dev->sem);
+		}
 		status = 0;
 
 	} else if (udev->devnum <= 0) {
@@ -1813,11 +1871,10 @@
  */
 int usb_resume_device(struct usb_device *udev)
 {
-	int	port1, status;
+	int	status;
 
-	port1 = locktree(udev);
-	if (port1 < 0)
-		return port1;
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
 
 #ifdef	CONFIG_USB_SUSPEND
 	/* selective resume of one downstream hub-to-device port */
@@ -1826,7 +1883,7 @@
 			// NOTE swsusp may bork us, device state being wrong...
 			// NOTE this fails if parent is also suspended...
 			status = hub_port_resume(hdev_to_hub(udev->parent),
-					port1, udev);
+					udev->portnum, udev);
 		} else
 			status = 0;
 	} else
@@ -1836,13 +1893,11 @@
 		dev_dbg(&udev->dev, "can't resume, status %d\n",
 			status);
 
-	usb_unlock_device(udev);
-
 	/* rebind drivers that had no suspend() */
 	if (status == 0) {
-		usb_lock_all_devices();
+		usb_unlock_device(udev);
 		bus_rescan_devices(&usb_bus_type);
-		usb_unlock_all_devices();
+		usb_lock_device(udev);
 	}
 	return status;
 }
@@ -1856,14 +1911,14 @@
 	/* don't repeat RESUME sequence if this device
 	 * was already woken up by some other task
 	 */
-	down(&udev->serialize);
+	usb_lock_device(udev);
 	if (udev->state == USB_STATE_SUSPENDED) {
 		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
 		/* TRSMRCY = 10 msec */
 		msleep(10);
 		status = finish_device_resume(udev);
 	}
-	up(&udev->serialize);
+	usb_unlock_device(udev);
 #endif
 	return status;
 }
@@ -1964,7 +2019,7 @@
 
 		if (!udev || status < 0)
 			continue;
-		down (&udev->serialize);
+		usb_lock_device(udev);
 		if (portstat & USB_PORT_STAT_SUSPEND)
 			status = hub_port_resume(hub, port1, udev);
 		else {
@@ -1975,7 +2030,7 @@
 				hub_port_logical_disconnect(hub, port1);
 			}
 		}
-		up(&udev->serialize);
+		usb_unlock_device(udev);
 	}
 	}
 #endif
@@ -2359,39 +2414,36 @@
 {
 	struct usb_device *hdev = hub->hdev;
 	int remaining;
-	unsigned i;
+	int port1;
 
-	remaining = hub->power_budget;
-	if (!remaining)		/* self-powered */
+	if (!hub->limited_power)
 		return 0;
 
-	for (i = 0; i < hdev->maxchild; i++) {
-		struct usb_device	*udev = hdev->children[i];
-		int			delta, ceiling;
+	remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
+	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+		struct usb_device	*udev = hdev->children[port1 - 1];
+		int			delta;
 
 		if (!udev)
 			continue;
 
-		/* 100mA per-port ceiling, or 8mA for OTG ports */
-		if (i != (udev->bus->otg_port - 1) || hdev->parent)
-			ceiling = 50;
-		else
-			ceiling = 4;
-
+		/* Unconfigured devices may not use more than 100mA,
+		 * or 8mA for OTG ports */
 		if (udev->actconfig)
-			delta = udev->actconfig->desc.bMaxPower;
+			delta = udev->actconfig->desc.bMaxPower * 2;
+		else if (port1 != udev->bus->otg_port || hdev->parent)
+			delta = 100;
 		else
-			delta = ceiling;
-		// dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta);
-		if (delta > ceiling)
-			dev_warn(&udev->dev, "%dmA over %dmA budget!\n",
-				2 * (delta - ceiling), 2 * ceiling);
+			delta = 8;
+		if (delta > hub->mA_per_port)
+			dev_warn(&udev->dev, "%dmA is over %umA budget "
+					"for port %d!\n",
+					delta, hub->mA_per_port, port1);
 		remaining -= delta;
 	}
 	if (remaining < 0) {
-		dev_warn(hub->intfdev,
-			"%dmA over power budget!\n",
-			-2 * remaining);
+		dev_warn(hub->intfdev, "%dmA over power budget!\n",
+			- remaining);
 		remaining = 0;
 	}
 	return remaining;
@@ -2486,7 +2538,8 @@
 
 		usb_set_device_state(udev, USB_STATE_POWERED);
 		udev->speed = USB_SPEED_UNKNOWN;
- 
+ 		udev->bus_mA = hub->mA_per_port;
+
 		/* set the address */
 		choose_address(udev);
 		if (udev->devnum <= 0) {
@@ -2506,16 +2559,16 @@
 		 * on the parent.
 		 */
 		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
-				&& hub->power_budget) {
+				&& udev->bus_mA <= 100) {
 			u16	devstat;
 
 			status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
 					&devstat);
-			if (status < 0) {
+			if (status < 2) {
 				dev_dbg(&udev->dev, "get status %d ?\n", status);
 				goto loop_disable;
 			}
-			cpu_to_le16s(&devstat);
+			le16_to_cpus(&devstat);
 			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
 				dev_err(&udev->dev,
 					"can't connect bus-powered hub "
@@ -2540,7 +2593,6 @@
 		 * udev becomes globally accessible, although presumably
 		 * no one will look at it until hdev is unlocked.
 		 */
-		down (&udev->serialize);
 		status = 0;
 
 		/* We mustn't add new devices if the parent hub has
@@ -2564,15 +2616,12 @@
 			}
 		}
 
-		up (&udev->serialize);
 		if (status)
 			goto loop_disable;
 
 		status = hub_power_remaining(hub);
 		if (status)
-			dev_dbg(hub_dev,
-				"%dmA power budget left\n",
-				2 * status);
+			dev_dbg(hub_dev, "%dmA power budget left\n", status);
 
 		return;
 
@@ -2648,6 +2697,8 @@
 		if (i) {
 			dpm_runtime_resume(&hdev->dev);
 			dpm_runtime_resume(&intf->dev);
+			usb_put_intf(intf);
+			continue;
 		}
 
 		/* Lock the device, then check to see if we were
@@ -2661,7 +2712,7 @@
 
 		/* If the hub has died, clean up after it */
 		if (hdev->state == USB_STATE_NOTATTACHED) {
-			hub_pre_reset(hub);
+			hub_pre_reset(hub, 0);
 			goto loop;
 		}
 
@@ -2784,6 +2835,11 @@
 			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
 				dev_dbg (hub_dev, "power change\n");
 				clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
+				if (hubstatus & HUB_STATUS_LOCAL_POWER)
+					/* FIXME: Is this always true? */
+					hub->limited_power = 0;
+				else
+					hub->limited_power = 1;
 			}
 			if (hubchange & HUB_CHANGE_OVERCURRENT) {
 				dev_dbg (hub_dev, "overcurrent change\n");
@@ -2832,7 +2888,6 @@
 MODULE_DEVICE_TABLE (usb, hub_id_table);
 
 static struct usb_driver hub_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"hub",
 	.probe =	hub_probe,
 	.disconnect =	hub_disconnect,
@@ -2944,7 +2999,8 @@
 	struct usb_hub			*parent_hub;
 	struct usb_device_descriptor	descriptor = udev->descriptor;
 	struct usb_hub			*hub = NULL;
-	int 				i, ret = 0, port1 = -1;
+	int 				i, ret = 0;
+	int				port1 = udev->portnum;
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
 			udev->state == USB_STATE_SUSPENDED) {
@@ -2958,18 +3014,6 @@
 		dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
 		return -EISDIR;
 	}
-
-	for (i = 0; i < parent_hdev->maxchild; i++)
-		if (parent_hdev->children[i] == udev) {
-			port1 = i + 1;
-			break;
-		}
-
-	if (port1 < 0) {
-		/* If this ever happens, it's very bad */
-		dev_err(&udev->dev, "Can't locate device's port!\n");
-		return -ENOENT;
-	}
 	parent_hub = hdev_to_hub(parent_hdev);
 
 	/* If we're resetting an active hub, take some special actions */
@@ -2977,7 +3021,7 @@
 			udev->actconfig->interface[0]->dev.driver ==
 				&hub_driver.driver &&
 			(hub = hdev_to_hub(udev)) != NULL) {
-		hub_pre_reset(hub);
+		hub_pre_reset(hub, 0);
 	}
 
 	set_bit(port1, parent_hub->busy_bits);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index bf23f89..29d5f45 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -220,8 +220,9 @@
 	struct usb_hub_descriptor *descriptor;	/* class descriptor */
 	struct usb_tt		tt;		/* Transaction Translator */
 
-	u8			power_budget;	/* in 2mA units; or zero */
+	unsigned		mA_per_port;	/* current for each child */
 
+	unsigned		limited_power:1;
 	unsigned		quiescing:1;
 	unsigned		activating:1;
 	unsigned		resume_root_hub:1;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fe74f99..319de03 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1387,6 +1387,12 @@
 	if (dev->state != USB_STATE_ADDRESS)
 		usb_disable_device (dev, 1);	// Skip ep0
 
+	i = dev->bus_mA - cp->desc.bMaxPower * 2;
+	if (i < 0)
+		dev_warn(&dev->dev, "new config #%d exceeds power "
+				"limit by %dmA\n",
+				configuration, -i);
+
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
 			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e80ef94..56a3520 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -32,7 +32,6 @@
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
-#include <linux/rwsem.h>
 #include <linux/usb.h>
 
 #include <asm/io.h>
@@ -47,165 +46,7 @@
 const char *usbcore_name = "usbcore";
 
 static int nousb;	/* Disable USB when built into kernel image */
-			/* Not honored on modular build */
 
-static DECLARE_RWSEM(usb_all_devices_rwsem);
-
-
-static int generic_probe (struct device *dev)
-{
-	return 0;
-}
-static int generic_remove (struct device *dev)
-{
-	struct usb_device *udev = to_usb_device(dev);
-
-	/* if this is only an unbind, not a physical disconnect, then
-	 * unconfigure the device */
-	if (udev->state == USB_STATE_CONFIGURED)
-		usb_set_configuration(udev, 0);
-
-	/* in case the call failed or the device was suspended */
-	if (udev->state >= USB_STATE_CONFIGURED)
-		usb_disable_device(udev, 0);
-	return 0;
-}
-
-static struct device_driver usb_generic_driver = {
-	.owner = THIS_MODULE,
-	.name =	"usb",
-	.bus = &usb_bus_type,
-	.probe = generic_probe,
-	.remove = generic_remove,
-};
-
-static int usb_generic_driver_data;
-
-/* called from driver core with usb_bus_type.subsys writelock */
-static int usb_probe_interface(struct device *dev)
-{
-	struct usb_interface * intf = to_usb_interface(dev);
-	struct usb_driver * driver = to_usb_driver(dev->driver);
-	const struct usb_device_id *id;
-	int error = -ENODEV;
-
-	dev_dbg(dev, "%s\n", __FUNCTION__);
-
-	if (!driver->probe)
-		return error;
-	/* FIXME we'd much prefer to just resume it ... */
-	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
-		return -EHOSTUNREACH;
-
-	id = usb_match_id (intf, driver->id_table);
-	if (id) {
-		dev_dbg (dev, "%s - got id\n", __FUNCTION__);
-
-		/* Interface "power state" doesn't correspond to any hardware
-		 * state whatsoever.  We use it to record when it's bound to
-		 * a driver that may start I/0:  it's not frozen/quiesced.
-		 */
-		mark_active(intf);
-		intf->condition = USB_INTERFACE_BINDING;
-		error = driver->probe (intf, id);
-		if (error) {
-			mark_quiesced(intf);
-			intf->condition = USB_INTERFACE_UNBOUND;
-		} else
-			intf->condition = USB_INTERFACE_BOUND;
-	}
-
-	return error;
-}
-
-/* called from driver core with usb_bus_type.subsys writelock */
-static int usb_unbind_interface(struct device *dev)
-{
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
-
-	intf->condition = USB_INTERFACE_UNBINDING;
-
-	/* release all urbs for this interface */
-	usb_disable_interface(interface_to_usbdev(intf), intf);
-
-	if (driver && driver->disconnect)
-		driver->disconnect(intf);
-
-	/* reset other interface state */
-	usb_set_interface(interface_to_usbdev(intf),
-			intf->altsetting[0].desc.bInterfaceNumber,
-			0);
-	usb_set_intfdata(intf, NULL);
-	intf->condition = USB_INTERFACE_UNBOUND;
-	mark_quiesced(intf);
-
-	return 0;
-}
-
-/**
- * usb_register - register a USB driver
- * @new_driver: USB operations for the driver
- *
- * Registers a USB driver with the USB core.  The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
- * Returns a negative error code on failure and 0 on success.
- * 
- * NOTE: if you want your driver to use the USB major number, you must call
- * usb_register_dev() to enable that functionality.  This function no longer
- * takes care of that.
- */
-int usb_register(struct usb_driver *new_driver)
-{
-	int retval = 0;
-
-	if (nousb)
-		return -ENODEV;
-
-	new_driver->driver.name = (char *)new_driver->name;
-	new_driver->driver.bus = &usb_bus_type;
-	new_driver->driver.probe = usb_probe_interface;
-	new_driver->driver.remove = usb_unbind_interface;
-	new_driver->driver.owner = new_driver->owner;
-
-	usb_lock_all_devices();
-	retval = driver_register(&new_driver->driver);
-	usb_unlock_all_devices();
-
-	if (!retval) {
-		pr_info("%s: registered new driver %s\n",
-			usbcore_name, new_driver->name);
-		usbfs_update_special();
-	} else {
-		printk(KERN_ERR "%s: error %d registering driver %s\n",
-			usbcore_name, retval, new_driver->name);
-	}
-
-	return retval;
-}
-
-/**
- * usb_deregister - unregister a USB driver
- * @driver: USB operations of the driver to unregister
- * Context: must be able to sleep
- *
- * Unlinks the specified driver from the internal USB driver list.
- * 
- * NOTE: If you called usb_register_dev(), you still need to call
- * usb_deregister_dev() to clean up your driver's allocated minor numbers,
- * this * call will no longer do it for you.
- */
-void usb_deregister(struct usb_driver *driver)
-{
-	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
-
-	usb_lock_all_devices();
-	driver_unregister (&driver->driver);
-	usb_unlock_all_devices();
-
-	usbfs_update_special();
-}
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -351,152 +192,23 @@
 	iface->condition = USB_INTERFACE_UNBOUND;
 	mark_quiesced(iface);
 }
-
-/**
- * usb_match_id - find first usb_device_id matching device or interface
- * @interface: the interface of interest
- * @id: array of usb_device_id structures, terminated by zero entry
- *
- * usb_match_id searches an array of usb_device_id's and returns
- * the first one matching the device or interface, or null.
- * This is used when binding (or rebinding) a driver to an interface.
- * Most USB device drivers will use this indirectly, through the usb core,
- * but some layered driver frameworks use it directly.
- * These device tables are exported with MODULE_DEVICE_TABLE, through
- * modutils and "modules.usbmap", to support the driver loading
- * functionality of USB hotplugging.
- *
- * What Matches:
- *
- * The "match_flags" element in a usb_device_id controls which
- * members are used.  If the corresponding bit is set, the
- * value in the device_id must match its corresponding member
- * in the device or interface descriptor, or else the device_id
- * does not match.
- *
- * "driver_info" is normally used only by device drivers,
- * but you can create a wildcard "matches anything" usb_device_id
- * as a driver's "modules.usbmap" entry if you provide an id with
- * only a nonzero "driver_info" field.  If you do this, the USB device
- * driver's probe() routine should use additional intelligence to
- * decide whether to bind to the specified interface.
- * 
- * What Makes Good usb_device_id Tables:
- *
- * The match algorithm is very simple, so that intelligence in
- * driver selection must come from smart driver id records.
- * Unless you have good reasons to use another selection policy,
- * provide match elements only in related groups, and order match
- * specifiers from specific to general.  Use the macros provided
- * for that purpose if you can.
- *
- * The most specific match specifiers use device descriptor
- * data.  These are commonly used with product-specific matches;
- * the USB_DEVICE macro lets you provide vendor and product IDs,
- * and you can also match against ranges of product revisions.
- * These are widely used for devices with application or vendor
- * specific bDeviceClass values.
- *
- * Matches based on device class/subclass/protocol specifications
- * are slightly more general; use the USB_DEVICE_INFO macro, or
- * its siblings.  These are used with single-function devices
- * where bDeviceClass doesn't specify that each interface has
- * its own class. 
- *
- * Matches based on interface class/subclass/protocol are the
- * most general; they let drivers bind to any interface on a
- * multiple-function device.  Use the USB_INTERFACE_INFO
- * macro, or its siblings, to match class-per-interface style 
- * devices (as recorded in bDeviceClass).
- *  
- * Within those groups, remember that not all combinations are
- * meaningful.  For example, don't give a product version range
- * without vendor and product IDs; or specify a protocol without
- * its associated class and subclass.
- */   
-const struct usb_device_id *
-usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
-{
-	struct usb_host_interface *intf;
-	struct usb_device *dev;
-
-	/* proc_connectinfo in devio.c may call us with id == NULL. */
-	if (id == NULL)
-		return NULL;
-
-	intf = interface->cur_altsetting;
-	dev = interface_to_usbdev(interface);
-
-	/* It is important to check that id->driver_info is nonzero,
-	   since an entry that is all zeroes except for a nonzero
-	   id->driver_info is the way to create an entry that
-	   indicates that the driver want to examine every
-	   device and interface. */
-	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
-	       id->driver_info; id++) {
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
-		    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
-		    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
-			continue;
-
-		/* No need to test id->bcdDevice_lo != 0, since 0 is never
-		   greater than any unsigned number. */
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
-		    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
-		    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
-		    (id->bDeviceClass != dev->descriptor.bDeviceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
-		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
-		    (id->bInterfaceClass != intf->desc.bInterfaceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
-		    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
-		    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
-			continue;
-
-		return id;
-	}
-
-	return NULL;
-}
-
+struct find_interface_arg {
+	int minor;
+	struct usb_interface *interface;
+};
 
 static int __find_interface(struct device * dev, void * data)
 {
-	struct usb_interface ** ret = (struct usb_interface **)data;
-	struct usb_interface * intf = *ret;
-	int *minor = (int *)data;
+	struct find_interface_arg *arg = data;
+	struct usb_interface *intf;
 
 	/* can't look at usb devices, only interfaces */
 	if (dev->driver == &usb_generic_driver)
 		return 0;
 
 	intf = to_usb_interface(dev);
-	if (intf->minor != -1 && intf->minor == *minor) {
-		*ret = intf;
+	if (intf->minor != -1 && intf->minor == arg->minor) {
+		arg->interface = intf;
 		return 1;
 	}
 	return 0;
@@ -513,35 +225,14 @@
  */
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
-	struct usb_interface *intf = (struct usb_interface *)(long)minor;
-	int ret;
+	struct find_interface_arg argb;
 
-	ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
-
-	return ret ? intf : NULL;
+	argb.minor = minor;
+	argb.interface = NULL;
+	driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
+	return argb.interface;
 }
 
-static int usb_device_match (struct device *dev, struct device_driver *drv)
-{
-	struct usb_interface *intf;
-	struct usb_driver *usb_drv;
-	const struct usb_device_id *id;
-
-	/* check for generic driver, which we don't match any device with */
-	if (drv == &usb_generic_driver)
-		return 0;
-
-	intf = to_usb_interface(dev);
-	usb_drv = to_usb_driver(drv);
-	
-	id = usb_match_id (intf, usb_drv->id_table);
-	if (id)
-		return 1;
-
-	return 0;
-}
-
-
 #ifdef	CONFIG_HOTPLUG
 
 /*
@@ -750,12 +441,11 @@
 		/* hub driver sets up TT records */
 	}
 
+	dev->portnum = port1;
 	dev->bus = bus;
 	dev->parent = parent;
 	INIT_LIST_HEAD(&dev->filelist);
 
-	init_MUTEX(&dev->serialize);
-
 	return dev;
 }
 
@@ -828,76 +518,21 @@
 
 /*			USB device locking
  *
- * Although locking USB devices should be straightforward, it is
- * complicated by the way the driver-model core works.  When a new USB
- * driver is registered or unregistered, the core will automatically
- * probe or disconnect all matching interfaces on all USB devices while
- * holding the USB subsystem writelock.  There's no good way for us to
- * tell which devices will be used or to lock them beforehand; our only
- * option is to effectively lock all the USB devices.
- *
- * We do that by using a private rw-semaphore, usb_all_devices_rwsem.
- * When locking an individual device you must first acquire the rwsem's
- * readlock.  When a driver is registered or unregistered the writelock
- * must be held.  These actions are encapsulated in the subroutines
- * below, so all a driver needs to do is call usb_lock_device() and
- * usb_unlock_device().
+ * USB devices and interfaces are locked using the semaphore in their
+ * embedded struct device.  The hub driver guarantees that whenever a
+ * device is connected or disconnected, drivers are called with the
+ * USB device locked as well as their particular interface.
  *
  * Complications arise when several devices are to be locked at the same
  * time.  Only hub-aware drivers that are part of usbcore ever have to
- * do this; nobody else needs to worry about it.  The problem is that
- * usb_lock_device() must not be called to lock a second device since it
- * would acquire the rwsem's readlock reentrantly, leading to deadlock if
- * another thread was waiting for the writelock.  The solution is simple:
- *
- *	When locking more than one device, call usb_lock_device()
- *	to lock the first one.  Lock the others by calling
- *	down(&udev->serialize) directly.
- *
- *	When unlocking multiple devices, use up(&udev->serialize)
- *	to unlock all but the last one.  Unlock the last one by
- *	calling usb_unlock_device().
+ * do this; nobody else needs to worry about it.  The rule for locking
+ * is simple:
  *
  *	When locking both a device and its parent, always lock the
  *	the parent first.
  */
 
 /**
- * usb_lock_device - acquire the lock for a usb device structure
- * @udev: device that's being locked
- *
- * Use this routine when you don't hold any other device locks;
- * to acquire nested inner locks call down(&udev->serialize) directly.
- * This is necessary for proper interaction with usb_lock_all_devices().
- */
-void usb_lock_device(struct usb_device *udev)
-{
-	down_read(&usb_all_devices_rwsem);
-	down(&udev->serialize);
-}
-
-/**
- * usb_trylock_device - attempt to acquire the lock for a usb device structure
- * @udev: device that's being locked
- *
- * Don't use this routine if you already hold a device lock;
- * use down_trylock(&udev->serialize) instead.
- * This is necessary for proper interaction with usb_lock_all_devices().
- *
- * Returns 1 if successful, 0 if contention.
- */
-int usb_trylock_device(struct usb_device *udev)
-{
-	if (!down_read_trylock(&usb_all_devices_rwsem))
-		return 0;
-	if (down_trylock(&udev->serialize)) {
-		up_read(&usb_all_devices_rwsem);
-		return 0;
-	}
-	return 1;
-}
-
-/**
  * usb_lock_device_for_reset - cautiously acquire the lock for a
  *	usb device structure
  * @udev: device that's being locked
@@ -935,7 +570,7 @@
 		}
 	}
 
-	while (!usb_trylock_device(udev)) {
+	while (usb_trylock_device(udev) != 0) {
 
 		/* If we can't acquire the lock after waiting one second,
 		 * we're probably deadlocked */
@@ -953,39 +588,6 @@
 	return 1;
 }
 
-/**
- * usb_unlock_device - release the lock for a usb device structure
- * @udev: device that's being unlocked
- *
- * Use this routine when releasing the only device lock you hold;
- * to release inner nested locks call up(&udev->serialize) directly.
- * This is necessary for proper interaction with usb_lock_all_devices().
- */
-void usb_unlock_device(struct usb_device *udev)
-{
-	up(&udev->serialize);
-	up_read(&usb_all_devices_rwsem);
-}
-
-/**
- * usb_lock_all_devices - acquire the lock for all usb device structures
- *
- * This is necessary when registering a new driver or probing a bus,
- * since the driver-model core may try to use any usb_device.
- */
-void usb_lock_all_devices(void)
-{
-	down_write(&usb_all_devices_rwsem);
-}
-
-/**
- * usb_unlock_all_devices - release the lock for all usb device structures
- */
-void usb_unlock_all_devices(void)
-{
-	up_write(&usb_all_devices_rwsem);
-}
-
 
 static struct usb_device *match_device(struct usb_device *dev,
 				       u16 vendor_id, u16 product_id)
@@ -1008,10 +610,10 @@
 	/* look through all of the children of this device */
 	for (child = 0; child < dev->maxchild; ++child) {
 		if (dev->children[child]) {
-			down(&dev->children[child]->serialize);
+			usb_lock_device(dev->children[child]);
 			ret_dev = match_device(dev->children[child],
 					       vendor_id, product_id);
-			up(&dev->children[child]->serialize);
+			usb_unlock_device(dev->children[child]);
 			if (ret_dev)
 				goto exit;
 		}
@@ -1496,18 +1098,8 @@
 	.resume =	usb_generic_resume,
 };
 
-#ifndef MODULE
-
-static int __init usb_setup_disable(char *str)
-{
-	nousb = 1;
-	return 1;
-}
-
 /* format to disable USB on kernel command line is: nousb */
-__setup("nousb", usb_setup_disable);
-
-#endif
+__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
 
 /*
  * for external read access to <nousb>
@@ -1598,8 +1190,6 @@
  * driver modules to use.
  */
 
-EXPORT_SYMBOL(usb_register);
-EXPORT_SYMBOL(usb_deregister);
 EXPORT_SYMBOL(usb_disabled);
 
 EXPORT_SYMBOL_GPL(usb_get_intf);
@@ -1610,14 +1200,10 @@
 EXPORT_SYMBOL(usb_get_dev);
 EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
 
-EXPORT_SYMBOL(usb_lock_device);
-EXPORT_SYMBOL(usb_trylock_device);
 EXPORT_SYMBOL(usb_lock_device_for_reset);
-EXPORT_SYMBOL(usb_unlock_device);
 
 EXPORT_SYMBOL(usb_driver_claim_interface);
 EXPORT_SYMBOL(usb_driver_release_interface);
-EXPORT_SYMBOL(usb_match_id);
 EXPORT_SYMBOL(usb_find_interface);
 EXPORT_SYMBOL(usb_ifnum_to_if);
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c4a684..4647e1e 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -16,9 +16,6 @@
 extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
-extern void usb_lock_all_devices(void);
-extern void usb_unlock_all_devices(void);
-
 extern void usb_kick_khubd(struct usb_device *dev);
 extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
@@ -33,6 +30,9 @@
 extern int usb_suspend_device(struct usb_device *dev);
 extern int usb_resume_device(struct usb_device *dev);
 
+extern struct device_driver usb_generic_driver;
+extern int usb_generic_driver_data;
+extern int usb_device_match(struct device *dev, struct device_driver *drv);
 
 /* Interfaces and their "power state" are owned by usbcore */
 
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index c655d46..9734cb7 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -138,7 +138,7 @@
 	/* or like sa1100: two fixed function endpoints */
 	"ep1out-bulk", "ep2in-bulk",
 };
-#define DUMMY_ENDPOINTS	(sizeof(ep_name)/sizeof(char *))
+#define DUMMY_ENDPOINTS	ARRAY_SIZE(ep_name)
 
 /*-------------------------------------------------------------------------*/
 
@@ -896,7 +896,7 @@
 #endif
 }
 
-static int dummy_udc_probe (struct platform_device *dev)
+static int dummy_udc_probe (struct platform_device *pdev)
 {
 	struct dummy	*dum = the_controller;
 	int		rc;
@@ -909,7 +909,7 @@
 	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
 
 	strcpy (dum->gadget.dev.bus_id, "gadget");
-	dum->gadget.dev.parent = &dev->dev;
+	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
 	rc = device_register (&dum->gadget.dev);
 	if (rc < 0)
@@ -919,47 +919,47 @@
 	usb_bus_get (&dummy_to_hcd (dum)->self);
 #endif
 
-	platform_set_drvdata (dev, dum);
+	platform_set_drvdata (pdev, dum);
 	device_create_file (&dum->gadget.dev, &dev_attr_function);
 	return rc;
 }
 
-static int dummy_udc_remove (struct platform_device *dev)
+static int dummy_udc_remove (struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata (dev);
+	struct dummy	*dum = platform_get_drvdata (pdev);
 
-	platform_set_drvdata (dev, NULL);
+	platform_set_drvdata (pdev, NULL);
 	device_remove_file (&dum->gadget.dev, &dev_attr_function);
 	device_unregister (&dum->gadget.dev);
 	return 0;
 }
 
-static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state)
+static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
 {
-	struct dummy	*dum = platform_get_drvdata(dev);
+	struct dummy	*dum = platform_get_drvdata(pdev);
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 	spin_lock_irq (&dum->lock);
 	dum->udc_suspended = 1;
 	set_link_state (dum);
 	spin_unlock_irq (&dum->lock);
 
-	dev->dev.power.power_state = state;
+	pdev->dev.power.power_state = state;
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
 
-static int dummy_udc_resume (struct platform_device *dev)
+static int dummy_udc_resume (struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata(dev);
+	struct dummy	*dum = platform_get_drvdata(pdev);
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 	spin_lock_irq (&dum->lock);
 	dum->udc_suspended = 0;
 	set_link_state (dum);
 	spin_unlock_irq (&dum->lock);
 
-	dev->dev.power.power_state = PMSG_ON;
+	pdev->dev.power.power_state = PMSG_ON;
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
@@ -1576,7 +1576,7 @@
 	dum = hcd_to_dummy (hcd);
 
 	spin_lock_irqsave (&dum->lock, flags);
-	if (hcd->state != HC_STATE_RUNNING)
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		goto done;
 
 	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
@@ -1623,7 +1623,7 @@
 	int		retval = 0;
 	unsigned long	flags;
 
-	if (hcd->state != HC_STATE_RUNNING)
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		return -ETIMEDOUT;
 
 	dum = hcd_to_dummy (hcd);
@@ -1756,9 +1756,12 @@
 {
 	struct dummy *dum = hcd_to_dummy (hcd);
 
+	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+
 	spin_lock_irq (&dum->lock);
 	dum->rh_state = DUMMY_RH_SUSPENDED;
 	set_link_state (dum);
+	hcd->state = HC_STATE_SUSPENDED;
 	spin_unlock_irq (&dum->lock);
 	return 0;
 }
@@ -1766,14 +1769,23 @@
 static int dummy_bus_resume (struct usb_hcd *hcd)
 {
 	struct dummy *dum = hcd_to_dummy (hcd);
+	int rc = 0;
+
+	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
 
 	spin_lock_irq (&dum->lock);
-	dum->rh_state = DUMMY_RH_RUNNING;
-	set_link_state (dum);
-	if (!list_empty(&dum->urbp_list))
-		mod_timer (&dum->timer, jiffies);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+		dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
+		rc = -ENODEV;
+	} else {
+		dum->rh_state = DUMMY_RH_RUNNING;
+		set_link_state (dum);
+		if (!list_empty(&dum->urbp_list))
+			mod_timer (&dum->timer, jiffies);
+		hcd->state = HC_STATE_RUNNING;
+	}
 	spin_unlock_irq (&dum->lock);
-	return 0;
+	return rc;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1899,14 +1911,14 @@
 	.bus_resume =		dummy_bus_resume,
 };
 
-static int dummy_hcd_probe (struct platform_device *dev)
+static int dummy_hcd_probe(struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 	int			retval;
 
-	dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
 
-	hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id);
+	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
 	if (!hcd)
 		return -ENOMEM;
 	the_controller = hcd_to_dummy (hcd);
@@ -1919,36 +1931,43 @@
 	return retval;
 }
 
-static int dummy_hcd_remove (struct platform_device *dev)
+static int dummy_hcd_remove (struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 
-	hcd = platform_get_drvdata (dev);
+	hcd = platform_get_drvdata (pdev);
 	usb_remove_hcd (hcd);
 	usb_put_hcd (hcd);
 	the_controller = NULL;
 	return 0;
 }
 
-static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state)
+static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd		*hcd;
+	struct dummy		*dum;
+	int			rc = 0;
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
-	hcd = platform_get_drvdata (dev);
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 
-	hcd->state = HC_STATE_SUSPENDED;
-	return 0;
+	hcd = platform_get_drvdata (pdev);
+	dum = hcd_to_dummy (hcd);
+	if (dum->rh_state == DUMMY_RH_RUNNING) {
+		dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
+		rc = -EBUSY;
+	} else
+		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	return rc;
 }
 
-static int dummy_hcd_resume (struct platform_device *dev)
+static int dummy_hcd_resume (struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
-	hcd = platform_get_drvdata (dev);
-	hcd->state = HC_STATE_RUNNING;
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 
+	hcd = platform_get_drvdata (pdev);
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	usb_hcd_poll_rh_status (hcd);
 	return 0;
 }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ea09aaa..0cea978 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kref.h>
 #include <linux/kthread.h>
 #include <linux/limits.h>
 #include <linux/list.h>
@@ -238,7 +239,6 @@
 #include <linux/string.h>
 #include <linux/suspend.h>
 #include <linux/utsname.h>
-#include <linux/wait.h>
 
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
@@ -250,7 +250,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"20 October 2004"
+#define DRIVER_VERSION		"28 November 2005"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -335,8 +335,8 @@
 #define MAX_LUNS	8
 
 	/* Arggh!  There should be a module_param_array_named macro! */
-static char		*file[MAX_LUNS] = {NULL, };
-static int		ro[MAX_LUNS] = {0, };
+static char		*file[MAX_LUNS];
+static int		ro[MAX_LUNS];
 
 static struct {
 	int		num_filenames;
@@ -587,7 +587,7 @@
 struct fsg_buffhd {
 	void				*buf;
 	dma_addr_t			dma;
-	volatile enum fsg_buffer_state	state;
+	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 
 	/* The NetChip 2280 is faster, and handles some protocol faults
@@ -596,9 +596,9 @@
 	unsigned int			bulk_out_intended_length;
 
 	struct usb_request		*inreq;
-	volatile int			inreq_busy;
+	int				inreq_busy;
 	struct usb_request		*outreq;
-	volatile int			outreq_busy;
+	int				outreq_busy;
 };
 
 enum fsg_state {
@@ -631,13 +631,16 @@
 	/* filesem protects: backing files in use */
 	struct rw_semaphore	filesem;
 
+	/* reference counting: wait until all LUNs are released */
+	struct kref		ref;
+
 	struct usb_ep		*ep0;		// Handy copy of gadget->ep0
 	struct usb_request	*ep0req;	// For control responses
-	volatile unsigned int	ep0_req_tag;
+	unsigned int		ep0_req_tag;
 	const char		*ep0req_name;
 
 	struct usb_request	*intreq;	// For interrupt responses
-	volatile int		intreq_busy;
+	int			intreq_busy;
 	struct fsg_buffhd	*intr_buffhd;
 
  	unsigned int		bulk_out_maxpacket;
@@ -667,7 +670,6 @@
 	struct fsg_buffhd	*next_buffhd_to_drain;
 	struct fsg_buffhd	buffhds[NUM_BUFFERS];
 
-	wait_queue_head_t	thread_wqh;
 	int			thread_wakeup_needed;
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
@@ -694,7 +696,6 @@
 	unsigned int		nluns;
 	struct lun		*luns;
 	struct lun		*curlun;
-	struct completion	lun_released;
 };
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -1073,11 +1074,13 @@
 
 /* These routines may be called in process context or in_irq */
 
+/* Caller must hold fsg->lock */
 static void wakeup_thread(struct fsg_dev *fsg)
 {
 	/* Tell the main thread that something has happened */
 	fsg->thread_wakeup_needed = 1;
-	wake_up_all(&fsg->thread_wqh);
+	if (fsg->thread_task)
+		wake_up_process(fsg->thread_task);
 }
 
 
@@ -1164,11 +1167,12 @@
 		usb_ep_fifo_flush(ep);
 
 	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
 	spin_lock(&fsg->lock);
 	bh->inreq_busy = 0;
 	bh->state = BUF_STATE_EMPTY;
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
@@ -1185,11 +1189,12 @@
 		usb_ep_fifo_flush(ep);
 
 	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
 	spin_lock(&fsg->lock);
 	bh->outreq_busy = 0;
 	bh->state = BUF_STATE_FULL;
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 
@@ -1206,11 +1211,12 @@
 		usb_ep_fifo_flush(ep);
 
 	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
 	spin_lock(&fsg->lock);
 	fsg->intreq_busy = 0;
 	bh->state = BUF_STATE_EMPTY;
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 #else
@@ -1261,8 +1267,8 @@
 	fsg->cbbuf_cmnd_size = req->actual;
 	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
 
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 #else
@@ -1514,8 +1520,8 @@
 
 /* Use this for bulk or interrupt transfers, not ep0 */
 static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request *req, volatile int *pbusy,
-		volatile enum fsg_buffer_state *state)
+		struct usb_request *req, int *pbusy,
+		enum fsg_buffer_state *state)
 {
 	int	rc;
 
@@ -1523,8 +1529,11 @@
 		dump_msg(fsg, "bulk-in", req->buf, req->length);
 	else if (ep == fsg->intr_in)
 		dump_msg(fsg, "intr-in", req->buf, req->length);
+
+	spin_lock_irq(&fsg->lock);
 	*pbusy = 1;
 	*state = BUF_STATE_BUSY;
+	spin_unlock_irq(&fsg->lock);
 	rc = usb_ep_queue(ep, req, GFP_KERNEL);
 	if (rc != 0) {
 		*pbusy = 0;
@@ -1544,14 +1553,23 @@
 
 static int sleep_thread(struct fsg_dev *fsg)
 {
-	int	rc;
+	int	rc = 0;
 
 	/* Wait until a signal arrives or we are woken up */
-	rc = wait_event_interruptible(fsg->thread_wqh,
-			fsg->thread_wakeup_needed);
+	for (;;) {
+		try_to_freeze();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (signal_pending(current)) {
+			rc = -EINTR;
+			break;
+		}
+		if (fsg->thread_wakeup_needed)
+			break;
+		schedule();
+	}
+	__set_current_state(TASK_RUNNING);
 	fsg->thread_wakeup_needed = 0;
-	try_to_freeze();
-	return (rc ? -EINTR : 0);
+	return rc;
 }
 
 
@@ -1788,6 +1806,7 @@
 		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
 			break;			// We stopped early
 		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
 			fsg->next_buffhd_to_drain = bh->next;
 			bh->state = BUF_STATE_EMPTY;
 
@@ -2356,6 +2375,7 @@
 
 		/* Throw away the data in a filled buffer */
 		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
 			bh->state = BUF_STATE_EMPTY;
 			fsg->next_buffhd_to_drain = bh->next;
 
@@ -3021,6 +3041,7 @@
 			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
 			}
+		smp_rmb();
 		rc = received_cbw(fsg, bh);
 		bh->state = BUF_STATE_EMPTY;
 
@@ -3642,11 +3663,19 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void fsg_release(struct kref *ref)
+{
+	struct fsg_dev	*fsg = container_of(ref, struct fsg_dev, ref);
+
+	kfree(fsg->luns);
+	kfree(fsg);
+}
+
 static void lun_release(struct device *dev)
 {
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
 
-	complete(&fsg->lun_released);
+	kref_put(&fsg->ref, fsg_release);
 }
 
 static void fsg_unbind(struct usb_gadget *gadget)
@@ -3660,14 +3689,12 @@
 	clear_bit(REGISTERED, &fsg->atomic_bitflags);
 
 	/* Unregister the sysfs attribute files and the LUNs */
-	init_completion(&fsg->lun_released);
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
 		if (curlun->registered) {
 			device_remove_file(&curlun->dev, &dev_attr_ro);
 			device_remove_file(&curlun->dev, &dev_attr_file);
 			device_unregister(&curlun->dev);
-			wait_for_completion(&fsg->lun_released);
 			curlun->registered = 0;
 		}
 	}
@@ -3846,6 +3873,7 @@
 			curlun->dev.release = lun_release;
 			device_create_file(&curlun->dev, &dev_attr_ro);
 			device_create_file(&curlun->dev, &dev_attr_file);
+			kref_get(&fsg->ref);
 		}
 
 		if (file[i] && *file[i]) {
@@ -4061,7 +4089,7 @@
 		return -ENOMEM;
 	spin_lock_init(&fsg->lock);
 	init_rwsem(&fsg->filesem);
-	init_waitqueue_head(&fsg->thread_wqh);
+	kref_init(&fsg->ref);
 	init_completion(&fsg->thread_notifier);
 
 	the_fsg = fsg;
@@ -4069,13 +4097,6 @@
 }
 
 
-static void fsg_free(struct fsg_dev *fsg)
-{
-	kfree(fsg->luns);
-	kfree(fsg);
-}
-
-
 static int __init fsg_init(void)
 {
 	int		rc;
@@ -4085,7 +4106,7 @@
 		return rc;
 	fsg = the_fsg;
 	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
-		fsg_free(fsg);
+		kref_put(&fsg->ref, fsg_release);
 	return rc;
 }
 module_init(fsg_init);
@@ -4103,6 +4124,6 @@
 	wait_for_completion(&fsg->thread_notifier);
 
 	close_all_backing_files(fsg);
-	fsg_free(fsg);
+	kref_put(&fsg->ref, fsg_release);
 }
 module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b35ac6d..65e084a 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -890,10 +890,12 @@
 	/* wait for write buffer to drain, or */
 	/* at most GS_CLOSE_TIMEOUT seconds */
 	if (gs_buf_data_avail(port->port_write_buf) > 0) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
 		wait_cond_interruptible_timeout(port->port_write_wait,
 		port->port_dev == NULL
 		|| gs_buf_data_avail(port->port_write_buf) == 0,
 		&port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);
+		spin_lock_irqsave(&port->port_lock, flags);
 	}
 
 	/* free disconnected port on final close */
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 58321d3..e3020f4b 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -2,6 +2,10 @@
 # Makefile for USB Host Controller Drivers
 #
 
+ifeq ($(CONFIG_USB_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
 obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 29f52a4..9dd3d14 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -17,13 +17,6 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/dmapool.h>
@@ -624,7 +617,7 @@
 	}
 
 	/* remote wakeup [4.3.1] */
-	if ((status & STS_PCD) && hcd->remote_wakeup) {
+	if (status & STS_PCD) {
 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
 
 		/* resume root hub? */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 82caf33..69b0b9b 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -59,7 +59,7 @@
 
 		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
 			t2 |= PORT_SUSPEND;
-		if (hcd->remote_wakeup)
+		if (device_may_wakeup(&hcd->self.root_hub->dev))
 			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
 		else
 			t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
@@ -517,7 +517,7 @@
 			if ((temp & PORT_PE) == 0
 					|| (temp & PORT_RESET) != 0)
 				goto error;
-			if (hcd->remote_wakeup)
+			if (device_may_wakeup(&hcd->self.root_hub->dev))
 				temp |= PORT_WAKE_BITS;
 			writel (temp | PORT_SUSPEND,
 				&ehci->regs->port_status [wIndex]);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 13f73a8..08ca0f8 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -210,7 +210,16 @@
 	/* Serial Bus Release Number is at PCI 0x60 offset */
 	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
 
-	/* REVISIT:  per-port wake capability (PCI 0x62) currently unused */
+	/* Workaround current PCI init glitch:  wakeup bits aren't
+	 * being set from PCI PM capability.
+	 */
+	if (!device_can_wakeup(&pdev->dev)) {
+		u16	port_wake;
+
+		pci_read_config_word(pdev, 0x62, &port_wake);
+		if (port_wake & 0x0001)
+			device_init_wakeup(&pdev->dev, 1);
+	}
 
 	retval = ehci_pci_reinit(ehci, pdev);
 done:
@@ -269,7 +278,6 @@
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	unsigned		port;
-	struct usb_device	*root = hcd->self.root_hub;
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval = -EINVAL;
 
@@ -303,13 +311,7 @@
 
 restart:
 	ehci_dbg(ehci, "lost power, restarting\n");
-	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
-		port--;
-		if (!root->children [port])
-			continue;
-		usb_set_device_state(root->children[port],
-					USB_STATE_NOTATTACHED);
-	}
+	usb_root_hub_lost_power(hcd->self.root_hub);
 
 	/* Else reset, to cope with power loss or flush-to-storage
 	 * style "resume" having let BIOS kick in during reboot.
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index bf03ec0..9b13bf2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -514,18 +514,18 @@
 		qtd->urb = urb;
 		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
 		list_add_tail (&qtd->qtd_list, head);
+
+		/* for zero length DATA stages, STATUS is always IN */
+		if (len == 0)
+			token |= (1 /* "in" */ << 8);
 	} 
 
 	/*
 	 * data transfer stage:  buffer setup
 	 */
-	if (likely (len > 0))
-		buf = urb->transfer_dma;
-	else
-		buf = 0;
+	buf = urb->transfer_dma;
 
-	/* for zero length DATA stages, STATUS is always IN */
-	if (!buf || is_input)
+	if (is_input)
 		token |= (1 /* "in" */ << 8);
 	/* else it's already initted to "out" pid (0 << 8) */
 
@@ -572,7 +572,7 @@
 	 * control requests may need a terminating data "status" ack;
 	 * bulk ones may need a terminating short packet (zero length).
 	 */
-	if (likely (buf != 0)) {
+	if (likely (urb->transfer_buffer_length != 0)) {
 		int	one_more = 0;
 
 		if (usb_pipecontrol (urb->pipe)) {
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 82f6498..584b8dc 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -55,19 +55,13 @@
 /* enqueuing/finishing log of urbs */
 //#define URB_TRACE
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/interrupt.h>
 #include <linux/usb.h>
 #include <linux/usb_isp116x.h>
 #include <linux/platform_device.h>
@@ -77,14 +71,10 @@
 #include <asm/system.h>
 #include <asm/byteorder.h>
 
-#ifndef DEBUG
-#	define	STUB_DEBUG_FILE
-#endif
-
 #include "../core/hcd.h"
 #include "isp116x.h"
 
-#define DRIVER_VERSION	"05 Aug 2005"
+#define DRIVER_VERSION	"03 Nov 2005"
 #define DRIVER_DESC	"ISP116x USB Host Controller Driver"
 
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -164,13 +154,11 @@
 	struct ptd *ptd;
 	int buflen = isp116x->atl_last_dir == PTD_DIR_IN
 	    ? isp116x->atl_bufshrt : isp116x->atl_buflen;
-	int ptd_count = 0;
 
 	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
 	isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
 	isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
 	for (ep = isp116x->atl_active; ep; ep = ep->active) {
-		++ptd_count;
 		ptd = &ep->ptd;
 		dump_ptd(ptd);
 		dump_ptd_out_data(ptd, ep->data);
@@ -305,9 +293,8 @@
 		udev = urb->dev;
 		ptd = &ep->ptd;
 		cc = PTD_GET_CC(ptd);
-
-		spin_lock(&urb->lock);
 		short_not_ok = 1;
+		spin_lock(&urb->lock);
 
 		/* Data underrun is special. For allowed underrun
 		   we clear the error and continue as normal. For
@@ -420,7 +407,7 @@
 			ep->nextpid = 0;
 			break;
 		default:
-			BUG_ON(1);
+			BUG();
 		}
 		spin_unlock(&urb->lock);
 	}
@@ -628,8 +615,12 @@
 		u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
 		isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
 		if (intstat & HCINT_UE) {
-			ERR("Unrecoverable error\n");
-			/* What should we do here? Reset?  */
+			ERR("Unrecoverable error, HC is dead!\n");
+			/* IRQ's are off, we do no DMA,
+			   perfectly ready to die ... */
+			hcd->state = HC_STATE_HALT;
+			ret = IRQ_HANDLED;
+			goto done;
 		}
 		if (intstat & HCINT_RHSC)
 			/* When root hub or any of its ports is going
@@ -640,7 +631,6 @@
 		if (intstat & HCINT_RD) {
 			DBG("---- remote wakeup\n");
 			usb_hcd_resume_root_hub(hcd);
-			ret = IRQ_HANDLED;
 		}
 		irqstat &= ~HCuPINT_OPR;
 		ret = IRQ_HANDLED;
@@ -651,6 +641,7 @@
 	}
 
 	isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+      done:
 	spin_unlock(&isp116x->lock);
 	return ret;
 }
@@ -724,6 +715,7 @@
 
 	spin_lock_irqsave(&isp116x->lock, flags);
 	if (!HC_IS_RUNNING(hcd->state)) {
+		kfree(ep);
 		ret = -ENODEV;
 		goto fail;
 	}
@@ -888,7 +880,7 @@
 				     struct usb_host_endpoint *hep)
 {
 	int i;
-	struct isp116x_ep *ep = hep->hcpriv;;
+	struct isp116x_ep *ep = hep->hcpriv;
 
 	if (!ep)
 		return;
@@ -916,8 +908,6 @@
 	return (int)fmnum;
 }
 
-/*----------------------------------------------------------------*/
-
 /*
   Adapted from ohci-hub.c. Currently we don't support autosuspend.
 */
@@ -968,11 +958,10 @@
 	desc->bHubContrCurrent = 0;
 	desc->bNbrPorts = (u8) (reg & 0x3);
 	/* Power switching, device type, overcurrent. */
-	desc->wHubCharacteristics =
-	    (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
+	desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
 	desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
 	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+	desc->bitmap[0] = 0;
 	desc->bitmap[1] = ~0;
 }
 
@@ -1159,135 +1148,9 @@
 	return ret;
 }
 
-#ifdef	CONFIG_PM
-
-static int isp116x_bus_suspend(struct usb_hcd *hcd)
-{
-	struct isp116x *isp116x = hcd_to_isp116x(hcd);
-	unsigned long flags;
-	u32 val;
-	int ret = 0;
-
-	spin_lock_irqsave(&isp116x->lock, flags);
-
-	val = isp116x_read_reg32(isp116x, HCCONTROL);
-	switch (val & HCCONTROL_HCFS) {
-	case HCCONTROL_USB_OPER:
-		hcd->state = HC_STATE_QUIESCING;
-		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
-		val |= HCCONTROL_USB_SUSPEND;
-		if (hcd->remote_wakeup)
-			val |= HCCONTROL_RWE;
-		/* Wait for usb transfers to finish */
-		mdelay(2);
-		isp116x_write_reg32(isp116x, HCCONTROL, val);
-		hcd->state = HC_STATE_SUSPENDED;
-		/* Wait for devices to suspend */
-		mdelay(5);
-	case HCCONTROL_USB_SUSPEND:
-		break;
-	case HCCONTROL_USB_RESUME:
-		isp116x_write_reg32(isp116x, HCCONTROL,
-				    (val & ~HCCONTROL_HCFS) |
-				    HCCONTROL_USB_RESET);
-	case HCCONTROL_USB_RESET:
-		ret = -EBUSY;
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&isp116x->lock, flags);
-	return ret;
-}
-
-static int isp116x_bus_resume(struct usb_hcd *hcd)
-{
-	struct isp116x *isp116x = hcd_to_isp116x(hcd);
-	u32 val;
-	int ret = -EINPROGRESS;
-
-	msleep(5);
-	spin_lock_irq(&isp116x->lock);
-
-	val = isp116x_read_reg32(isp116x, HCCONTROL);
-	switch (val & HCCONTROL_HCFS) {
-	case HCCONTROL_USB_SUSPEND:
-		val &= ~HCCONTROL_HCFS;
-		val |= HCCONTROL_USB_RESUME;
-		isp116x_write_reg32(isp116x, HCCONTROL, val);
-	case HCCONTROL_USB_RESUME:
-		break;
-	case HCCONTROL_USB_OPER:
-		/* Without setting power_state here the
-		   SUSPENDED state won't be removed from
-		   sysfs/usbN/power.state as a response to remote
-		   wakeup. Maybe in the future. */
-		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
-		ret = 0;
-		break;
-	default:
-		ret = -EBUSY;
-	}
-
-	if (ret != -EINPROGRESS) {
-		spin_unlock_irq(&isp116x->lock);
-		return ret;
-	}
-
-	val = isp116x->rhdesca & RH_A_NDP;
-	while (val--) {
-		u32 stat =
-		    isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
-		/* force global, not selective, resume */
-		if (!(stat & RH_PS_PSS))
-			continue;
-		DBG("%s: Resuming port %d\n", __func__, val);
-		isp116x_write_reg32(isp116x, RH_PS_POCI, val
-				    ? HCRHPORT2 : HCRHPORT1);
-	}
-	spin_unlock_irq(&isp116x->lock);
-
-	hcd->state = HC_STATE_RESUMING;
-	mdelay(20);
-
-	/* Go operational */
-	spin_lock_irq(&isp116x->lock);
-	val = isp116x_read_reg32(isp116x, HCCONTROL);
-	isp116x_write_reg32(isp116x, HCCONTROL,
-			    (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
-	spin_unlock_irq(&isp116x->lock);
-	/* see analogous comment above */
-	hcd->self.root_hub->dev.power.power_state = PMSG_ON;
-	hcd->state = HC_STATE_RUNNING;
-
-	return 0;
-}
-
-
-#else
-
-#define	isp116x_bus_suspend	NULL
-#define	isp116x_bus_resume	NULL
-
-#endif
-
 /*-----------------------------------------------------------------*/
 
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct isp116x *isp116x)
-{
-}
-
-static inline void remove_debug_file(struct isp116x *isp116x)
-{
-}
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#ifdef CONFIG_DEBUG_FS
 
 static void dump_irq(struct seq_file *s, char *label, u16 mask)
 {
@@ -1311,13 +1174,9 @@
 		   mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
 }
 
-static int proc_isp116x_show(struct seq_file *s, void *unused)
+static int isp116x_show_dbg(struct seq_file *s, void *unused)
 {
 	struct isp116x *isp116x = s->private;
-	struct isp116x_ep *ep;
-	struct urb *urb;
-	unsigned i;
-	char *str;
 
 	seq_printf(s, "%s\n%s version %s\n",
 		   isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@@ -1333,105 +1192,50 @@
 	}
 
 	spin_lock_irq(&isp116x->lock);
-
 	dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
 	dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
 	dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
 	dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
-
-	list_for_each_entry(ep, &isp116x->async, schedule) {
-
-		switch (ep->nextpid) {
-		case USB_PID_IN:
-			str = "in";
-			break;
-		case USB_PID_OUT:
-			str = "out";
-			break;
-		case USB_PID_SETUP:
-			str = "setup";
-			break;
-		case USB_PID_ACK:
-			str = "status";
-			break;
-		default:
-			str = "?";
-			break;
-		};
-		seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
-			   ep->epnum, str, ep->maxpacket);
-		list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
-			seq_printf(s, "  urb%p, %d/%d\n", urb,
-				   urb->actual_length,
-				   urb->transfer_buffer_length);
-		}
-	}
-	if (!list_empty(&isp116x->async))
-		seq_printf(s, "\n");
-
-	seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
-
-	for (i = 0; i < PERIODIC_SIZE; i++) {
-		ep = isp116x->periodic[i];
-		if (!ep)
-			continue;
-		seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
-
-		/* DUMB: prints shared entries multiple times */
-		do {
-			seq_printf(s, "   %d/%p (%sdev%d ep%d%s max %d)\n",
-				   ep->period, ep,
-				   (ep->udev->speed ==
-				    USB_SPEED_FULL) ? "" : "ls ",
-				   ep->udev->devnum, ep->epnum,
-				   (ep->epnum ==
-				    0) ? "" : ((ep->nextpid ==
-						USB_PID_IN) ? "in" : "out"),
-				   ep->maxpacket);
-			ep = ep->next;
-		} while (ep);
-	}
+	isp116x_show_regs_seq(isp116x, s);
 	spin_unlock_irq(&isp116x->lock);
 	seq_printf(s, "\n");
 
 	return 0;
 }
 
-static int proc_isp116x_open(struct inode *inode, struct file *file)
+static int isp116x_open_seq(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_isp116x_show, PDE(inode)->data);
+	return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
 }
 
-static struct file_operations proc_ops = {
-	.open = proc_isp116x_open,
+static struct file_operations isp116x_debug_fops = {
+	.open = isp116x_open_seq,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-/* expect just one isp116x per system */
-static const char proc_filename[] = "driver/isp116x";
-
-static void create_debug_file(struct isp116x *isp116x)
+static int create_debug_file(struct isp116x *isp116x)
 {
-	struct proc_dir_entry *pde;
-
-	pde = create_proc_entry(proc_filename, 0, NULL);
-	if (pde == NULL)
-		return;
-
-	pde->proc_fops = &proc_ops;
-	pde->data = isp116x;
-	isp116x->pde = pde;
+	isp116x->dentry = debugfs_create_file(hcd_name,
+					      S_IRUGO, NULL, isp116x,
+					      &isp116x_debug_fops);
+	if (!isp116x->dentry)
+		return -ENOMEM;
+	return 0;
 }
 
 static void remove_debug_file(struct isp116x *isp116x)
 {
-	if (isp116x->pde)
-		remove_proc_entry(proc_filename, NULL);
+	debugfs_remove(isp116x->dentry);
 }
 
-#endif
+#else
+
+#define	create_debug_file(d)	0
+#define	remove_debug_file(d)	do{}while(0)
+
+#endif				/* CONFIG_DEBUG_FS */
 
 /*-----------------------------------------------------------------*/
 
@@ -1466,7 +1270,7 @@
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	unsigned long t;
 	u16 clkrdy = 0;
-	int ret = 0, timeout = 15 /* ms */ ;
+	int ret, timeout = 15 /* ms */ ;
 
 	ret = isp116x_sw_reset(isp116x);
 	if (ret)
@@ -1482,7 +1286,7 @@
 			break;
 	}
 	if (!clkrdy) {
-		ERR("Clock not ready after 20ms\n");
+		ERR("Clock not ready after %dms\n", timeout);
 		/* After sw_reset the clock won't report to be ready, if
 		   H_WAKEUP pin is high. */
 		ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@@ -1572,7 +1376,8 @@
 
 	val = 0;
 	if (board->remote_wakeup_enable) {
-		hcd->can_wakeup = 1;
+		if (!device_can_wakeup(hcd->self.controller))
+			device_init_wakeup(hcd->self.controller, 1);
 		val |= RH_HS_DRWE;
 	}
 	isp116x_write_reg32(isp116x, HCRHSTATUS, val);
@@ -1600,12 +1405,126 @@
 	isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
 	isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
 
-	isp116x_show_regs(isp116x);
+	isp116x_show_regs_log(isp116x);
 	spin_unlock_irqrestore(&isp116x->lock, flags);
 	return 0;
 }
 
-/*-----------------------------------------------------------------*/
+#ifdef	CONFIG_PM
+
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
+{
+	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+	unsigned long flags;
+	u32 val;
+	int ret = 0;
+
+	spin_lock_irqsave(&isp116x->lock, flags);
+
+	val = isp116x_read_reg32(isp116x, HCCONTROL);
+	switch (val & HCCONTROL_HCFS) {
+	case HCCONTROL_USB_OPER:
+		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+		val |= HCCONTROL_USB_SUSPEND;
+		if (device_may_wakeup(&hcd->self.root_hub->dev))
+			val |= HCCONTROL_RWE;
+		/* Wait for usb transfers to finish */
+		mdelay(2);
+		isp116x_write_reg32(isp116x, HCCONTROL, val);
+		/* Wait for devices to suspend */
+		mdelay(5);
+	case HCCONTROL_USB_SUSPEND:
+		break;
+	case HCCONTROL_USB_RESUME:
+		isp116x_write_reg32(isp116x, HCCONTROL,
+				    (val & ~HCCONTROL_HCFS) |
+				    HCCONTROL_USB_RESET);
+	case HCCONTROL_USB_RESET:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&isp116x->lock, flags);
+	return ret;
+}
+
+static int isp116x_bus_resume(struct usb_hcd *hcd)
+{
+	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+	u32 val;
+
+	msleep(5);
+	spin_lock_irq(&isp116x->lock);
+
+	val = isp116x_read_reg32(isp116x, HCCONTROL);
+	switch (val & HCCONTROL_HCFS) {
+	case HCCONTROL_USB_SUSPEND:
+		val &= ~HCCONTROL_HCFS;
+		val |= HCCONTROL_USB_RESUME;
+		isp116x_write_reg32(isp116x, HCCONTROL, val);
+	case HCCONTROL_USB_RESUME:
+		break;
+	case HCCONTROL_USB_OPER:
+		spin_unlock_irq(&isp116x->lock);
+		/* Without setting power_state here the
+		   SUSPENDED state won't be removed from
+		   sysfs/usbN/power.state as a response to remote
+		   wakeup. Maybe in the future. */
+		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+		return 0;
+	default:
+		/* HCCONTROL_USB_RESET: this may happen, when during
+		   suspension the HC lost power. Reinitialize completely */
+		spin_unlock_irq(&isp116x->lock);
+		DBG("Chip has been reset while suspended. Reinit from scratch.\n");
+		isp116x_reset(hcd);
+		isp116x_start(hcd);
+		isp116x_hub_control(hcd, SetPortFeature,
+				    USB_PORT_FEAT_POWER, 1, NULL, 0);
+		if ((isp116x->rhdesca & RH_A_NDP) == 2)
+			isp116x_hub_control(hcd, SetPortFeature,
+					    USB_PORT_FEAT_POWER, 2, NULL, 0);
+		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+		return 0;
+	}
+
+	val = isp116x->rhdesca & RH_A_NDP;
+	while (val--) {
+		u32 stat =
+		    isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
+		/* force global, not selective, resume */
+		if (!(stat & RH_PS_PSS))
+			continue;
+		DBG("%s: Resuming port %d\n", __func__, val);
+		isp116x_write_reg32(isp116x, RH_PS_POCI, val
+				    ? HCRHPORT2 : HCRHPORT1);
+	}
+	spin_unlock_irq(&isp116x->lock);
+
+	hcd->state = HC_STATE_RESUMING;
+	msleep(20);
+
+	/* Go operational */
+	spin_lock_irq(&isp116x->lock);
+	val = isp116x_read_reg32(isp116x, HCCONTROL);
+	isp116x_write_reg32(isp116x, HCCONTROL,
+			    (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+	spin_unlock_irq(&isp116x->lock);
+	/* see analogous comment above */
+	hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+	hcd->state = HC_STATE_RUNNING;
+
+	return 0;
+}
+
+#else
+
+#define	isp116x_bus_suspend	NULL
+#define	isp116x_bus_resume	NULL
+
+#endif
 
 static struct hc_driver isp116x_hc_driver = {
 	.description = hcd_name,
@@ -1735,12 +1654,19 @@
 	}
 
 	ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
-	if (ret != 0)
+	if (ret)
 		goto err6;
 
-	create_debug_file(isp116x);
+	ret = create_debug_file(isp116x);
+	if (ret) {
+		ERR("Couldn't create debugfs entry\n");
+		goto err7;
+	}
+
 	return 0;
 
+      err7:
+	usb_remove_hcd(hcd);
       err6:
 	usb_put_hcd(hcd);
       err5:
@@ -1762,13 +1688,9 @@
 */
 static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
 {
-	int ret = 0;
-
-	VDBG("%s: state %x\n", __func__, state);
-
+	VDBG("%s: state %x\n", __func__, state.event);
 	dev->dev.power.power_state = state;
-
-	return ret;
+	return 0;
 }
 
 /*
@@ -1776,13 +1698,9 @@
 */
 static int isp116x_resume(struct platform_device *dev)
 {
-	int ret = 0;
-
-	VDBG("%s:  state %x\n", __func__, dev->dev.power.power_state);
-
+	VDBG("%s:  state %x\n", __func__, dev->power.power_state.event);
 	dev->dev.power.power_state = PMSG_ON;
-
-	return ret;
+	return 0;
 }
 
 #else
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index c6fec96..a1b7c38 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -259,7 +259,7 @@
 
 	struct isp116x_platform_data *board;
 
-	struct proc_dir_entry *pde;
+	struct dentry *dentry;
 	unsigned long stat1, stat2, stat4, stat8, stat16;
 
 	/* HC registers */
@@ -450,7 +450,7 @@
 	isp116x_write_data32(isp116x, (u32) val);
 }
 
-#define isp116x_show_reg(d,r) {					\
+#define isp116x_show_reg_log(d,r,s) {				\
 	if ((r) < 0x20) {			                \
 		DBG("%-12s[%02x]: %08x\n", #r,			\
 			r, isp116x_read_reg32(d, r));		\
@@ -459,35 +459,60 @@
 			r, isp116x_read_reg16(d, r));	    	\
 	}							\
 }
+#define isp116x_show_reg_seq(d,r,s) {				\
+	if ((r) < 0x20) {					\
+		seq_printf(s, "%-12s[%02x]: %08x\n", #r,	\
+			r, isp116x_read_reg32(d, r));		\
+	} else {						\
+		seq_printf(s, "%-12s[%02x]:     %04x\n", #r,	\
+			r, isp116x_read_reg16(d, r));		\
+	}							\
+}
 
-static inline void isp116x_show_regs(struct isp116x *isp116x)
+#define isp116x_show_regs(d,type,s) {			\
+	isp116x_show_reg_##type(d, HCREVISION, s);	\
+	isp116x_show_reg_##type(d, HCCONTROL, s);	\
+	isp116x_show_reg_##type(d, HCCMDSTAT, s);	\
+	isp116x_show_reg_##type(d, HCINTSTAT, s);	\
+	isp116x_show_reg_##type(d, HCINTENB, s);	\
+	isp116x_show_reg_##type(d, HCFMINTVL, s);	\
+	isp116x_show_reg_##type(d, HCFMREM, s);		\
+	isp116x_show_reg_##type(d, HCFMNUM, s);		\
+	isp116x_show_reg_##type(d, HCLSTHRESH, s);	\
+	isp116x_show_reg_##type(d, HCRHDESCA, s);	\
+	isp116x_show_reg_##type(d, HCRHDESCB, s);	\
+	isp116x_show_reg_##type(d, HCRHSTATUS, s);	\
+	isp116x_show_reg_##type(d, HCRHPORT1, s);	\
+	isp116x_show_reg_##type(d, HCRHPORT2, s);	\
+	isp116x_show_reg_##type(d, HCHWCFG, s);		\
+	isp116x_show_reg_##type(d, HCDMACFG, s);	\
+	isp116x_show_reg_##type(d, HCXFERCTR, s);	\
+	isp116x_show_reg_##type(d, HCuPINT, s);		\
+	isp116x_show_reg_##type(d, HCuPINTENB, s);	\
+	isp116x_show_reg_##type(d, HCCHIPID, s);	\
+	isp116x_show_reg_##type(d, HCSCRATCH, s);	\
+	isp116x_show_reg_##type(d, HCITLBUFLEN, s);	\
+	isp116x_show_reg_##type(d, HCATLBUFLEN, s);	\
+	isp116x_show_reg_##type(d, HCBUFSTAT, s);	\
+	isp116x_show_reg_##type(d, HCRDITL0LEN, s);	\
+	isp116x_show_reg_##type(d, HCRDITL1LEN, s);	\
+}
+
+/*
+   Dump registers for debugfs.
+*/
+static inline void isp116x_show_regs_seq(struct isp116x *isp116x,
+					  struct seq_file *s)
 {
-	isp116x_show_reg(isp116x, HCREVISION);
-	isp116x_show_reg(isp116x, HCCONTROL);
-	isp116x_show_reg(isp116x, HCCMDSTAT);
-	isp116x_show_reg(isp116x, HCINTSTAT);
-	isp116x_show_reg(isp116x, HCINTENB);
-	isp116x_show_reg(isp116x, HCFMINTVL);
-	isp116x_show_reg(isp116x, HCFMREM);
-	isp116x_show_reg(isp116x, HCFMNUM);
-	isp116x_show_reg(isp116x, HCLSTHRESH);
-	isp116x_show_reg(isp116x, HCRHDESCA);
-	isp116x_show_reg(isp116x, HCRHDESCB);
-	isp116x_show_reg(isp116x, HCRHSTATUS);
-	isp116x_show_reg(isp116x, HCRHPORT1);
-	isp116x_show_reg(isp116x, HCRHPORT2);
-	isp116x_show_reg(isp116x, HCHWCFG);
-	isp116x_show_reg(isp116x, HCDMACFG);
-	isp116x_show_reg(isp116x, HCXFERCTR);
-	isp116x_show_reg(isp116x, HCuPINT);
-	isp116x_show_reg(isp116x, HCuPINTENB);
-	isp116x_show_reg(isp116x, HCCHIPID);
-	isp116x_show_reg(isp116x, HCSCRATCH);
-	isp116x_show_reg(isp116x, HCITLBUFLEN);
-	isp116x_show_reg(isp116x, HCATLBUFLEN);
-	isp116x_show_reg(isp116x, HCBUFSTAT);
-	isp116x_show_reg(isp116x, HCRDITL0LEN);
-	isp116x_show_reg(isp116x, HCRDITL1LEN);
+	isp116x_show_regs(isp116x, seq, s);
+}
+
+/*
+   Dump registers to syslog.
+*/
+static inline void isp116x_show_regs_log(struct isp116x *isp116x)
+{
+	isp116x_show_regs(isp116x, log, NULL);
 }
 
 #if defined(URB_TRACE)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index bf1d9ab..a4b1240 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,13 +75,6 @@
  */
  
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-#	define DEBUG
-#else
-#	undef DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
@@ -802,7 +795,6 @@
 	int temp;
 	int i;
 	struct urb_priv *priv;
-	struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
 
 	/* mark any devices gone, so they do nothing till khubd disconnects.
 	 * recycle any "live" eds/tds (and urbs) right away.
@@ -811,11 +803,7 @@
 	 */ 
 	spin_lock_irq(&ohci->lock);
 	disable (ohci);
-	for (i = 0; i < root->maxchild; i++) {
-		if (root->children [i])
-			usb_set_device_state (root->children[i],
-				USB_STATE_NOTATTACHED);
-	}
+	usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
 	if (!list_empty (&ohci->pending))
 		ohci_dbg(ohci, "abort schedule...\n");
 	list_for_each_entry (priv, &ohci->pending, pending) {
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 72e3b12..4b2226d 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -372,7 +372,7 @@
 					& ohci->hc_control)
 				== OHCI_USB_OPER
 			&& time_after (jiffies, ohci->next_statechange)
-			&& usb_trylock_device (hcd->self.root_hub)
+			&& usb_trylock_device (hcd->self.root_hub) == 0
 			) {
 		ohci_vdbg (ohci, "autosuspend\n");
 		(void) ohci_bus_suspend (hcd);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 9d65ec3..acde886 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -26,18 +26,12 @@
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
-
-
-#define PMM_NPS_MODE           1
-#define PMM_GLOBAL_MODE        2
-#define PMM_PERPORT_MODE       3
+#include <asm/arch/ohci.h>
 
 #define PXA_UHC_MAX_PORTNUM    3
 
 #define UHCRHPS(x)              __REG2( 0x4C000050, (x)<<2 )
 
-static int pxa27x_ohci_pmm_state;
-
 /*
   PMM_NPS_MODE -- PMM Non-power switching mode
       Ports are powered continuously.
@@ -50,8 +44,6 @@
  */
 static int pxa27x_ohci_select_pmm( int mode )
 {
-	pxa27x_ohci_pmm_state = mode;
-
 	switch ( mode ) {
 	case PMM_NPS_MODE:
 		UHCRHDA |= RH_A_NPS;
@@ -71,7 +63,6 @@
 			"Invalid mode %d, set to non-power switch mode.\n", 
 			mode );
 
-		pxa27x_ohci_pmm_state = PMM_NPS_MODE;
 		UHCRHDA |= RH_A_NPS;
 	}
 
@@ -82,8 +73,13 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void pxa27x_start_hc(struct platform_device *dev)
+static int pxa27x_start_hc(struct device *dev)
 {
+	int retval = 0;
+	struct pxaohci_platform_data *inf;
+
+	inf = dev->platform_data;
+
 	pxa_set_cken(CKEN10_USBHOST, 1);
 
 	UHCHR |= UHCHR_FHR;
@@ -94,21 +90,11 @@
 	while (UHCHR & UHCHR_FSBIR)
 		cpu_relax();
 
-	/* This could be properly abstracted away through the
-	   device data the day more machines are supported and
-	   their differences can be figured out correctly. */
-	if (machine_is_mainstone()) {
-		/* setup Port1 GPIO pin. */
-		pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN);	/* USBHPWR1 */
-		pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT);	/* USBHPEN1 */
+	if (inf->init)
+		retval = inf->init(dev);
 
-		/* Set the Power Control Polarity Low and Power Sense
-		   Polarity Low to active low. Supply power to USB ports. */
-		UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
-			~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
-
-		pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
-	}
+	if (retval < 0)
+		return retval;
 
 	UHCHR &= ~UHCHR_SSE;
 
@@ -117,10 +103,19 @@
 	/* Clear any OTG Pin Hold */
 	if (PSSR & PSSR_OTGPH)
 		PSSR |= PSSR_OTGPH;
+
+	return 0;
 }
 
-static void pxa27x_stop_hc(struct platform_device *dev)
+static void pxa27x_stop_hc(struct device *dev)
 {
+	struct pxaohci_platform_data *inf;
+
+	inf = dev->platform_data;
+
+	if (inf->exit)
+		inf->exit(dev);
+
 	UHCHR |= UHCHR_FHR;
 	udelay(11);
 	UHCHR &= ~UHCHR_FHR;
@@ -147,22 +142,27 @@
  * through the hotplug entry's driver_data.
  *
  */
-int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
-			  struct platform_device *dev)
+int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
 {
 	int retval;
 	struct usb_hcd *hcd;
+	struct pxaohci_platform_data *inf;
 
-	if (dev->resource[1].flags != IORESOURCE_IRQ) {
+	inf = pdev->dev.platform_data;
+
+	if (!inf)
+		return -ENODEV;
+
+	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
 		pr_debug ("resource[1] is not IORESOURCE_IRQ");
 		return -ENOMEM;
 	}
 
-	hcd = usb_create_hcd (driver, &dev->dev, "pxa27x");
+	hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
 	if (!hcd)
 		return -ENOMEM;
-	hcd->rsrc_start = dev->resource[0].start;
-	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+	hcd->rsrc_start = pdev->resource[0].start;
+	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		pr_debug("request_mem_region failed");
@@ -177,18 +177,22 @@
 		goto err2;
 	}
 
-	pxa27x_start_hc(dev);
+	if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
+		pr_debug("pxa27x_start_hc failed");
+		goto err3;
+	}
 
 	/* Select Power Management Mode */
-	pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
+	pxa27x_ohci_select_pmm(inf->port_mode);
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+	retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
 	if (retval == 0)
 		return retval;
 
-	pxa27x_stop_hc(dev);
+	pxa27x_stop_hc(&pdev->dev);
+ err3:
 	iounmap(hcd->regs);
  err2:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -211,10 +215,10 @@
  * context, normally "rmmod", "apmd", or something similar.
  *
  */
-void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
+void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
-	pxa27x_stop_hc(dev);
+	pxa27x_stop_hc(&pdev->dev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
@@ -292,15 +296,12 @@
 
 static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
 {
-	int ret;
-
 	pr_debug ("In ohci_hcd_pxa27x_drv_probe");
 
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
-	return ret;
+	return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
 }
 
 static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
@@ -308,31 +309,55 @@
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
 	usb_hcd_pxa27x_remove(hcd, pdev);
+	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef	CONFIG_PM
+static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
 {
-//	struct usb_hcd *hcd = platform_get_drvdata(dev);
-	printk("%s: not implemented yet\n", __FUNCTION__);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	pxa27x_stop_hc(&pdev->dev);
+	hcd->state = HC_STATE_SUSPENDED;
+	pdev->dev.power.power_state = PMSG_SUSPEND;
 
 	return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev)
+static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
 {
-//	struct usb_hcd *hcd = platform_get_drvdata(dev);
-	printk("%s: not implemented yet\n", __FUNCTION__);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int status;
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+		return status;
+
+	pdev->dev.power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(hcd);
 
 	return 0;
 }
+#endif
 
 
 static struct platform_driver ohci_hcd_pxa27x_driver = {
 	.probe		= ohci_hcd_pxa27x_drv_probe,
 	.remove		= ohci_hcd_pxa27x_drv_remove,
+#ifdef CONFIG_PM
 	.suspend	= ohci_hcd_pxa27x_drv_suspend, 
 	.resume		= ohci_hcd_pxa27x_drv_resume,
+#endif
 	.driver		= {
 		.name	= "pxa27x-ohci",
 	},
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index e46528c..3ef2c0c 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -9,12 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a7722a6..517360b 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -32,13 +32,6 @@
 #undef	PACKET_TRACE
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-#	define DEBUG
-#else
-#	undef DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -1581,7 +1574,9 @@
 	hcd->state = HC_STATE_RUNNING;
 
 	if (sl811->board) {
-		hcd->can_wakeup = sl811->board->can_wakeup;
+		if (!device_can_wakeup(hcd->self.controller))
+			device_init_wakeup(hcd->self.controller,
+				sl811->board->can_wakeup);
 		hcd->power_budget = sl811->board->power * 2;
 	}
 
@@ -1805,9 +1800,10 @@
 	 * let's assume it'd only be powered to enable remote wakeup.
 	 */
 	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
-			|| !hcd->can_wakeup) {
+			|| !device_can_wakeup(&hcd->self.root_hub->dev)) {
 		sl811->port1 = 0;
 		port_power(sl811, 1);
+		usb_root_hub_lost_power(hcd->self.root_hub);
 		return 0;
 	}
 
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index e73faf8..5056b74 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -38,7 +38,7 @@
 /* MACROS                                                             */
 /*====================================================================*/
 
-#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
+#if defined(DEBUG) || defined(PCMCIA_DEBUG)
 
 static int pc_debug = 0;
 module_param(pc_debug, int, 0644);
@@ -129,7 +129,8 @@
 	resources[2].end   = base_addr + 1;
 
 	/* The driver core will probe for us.  We know sl811-hcd has been
-	 * initialized already because of the link order dependency.
+	 * initialized already because of the link order dependency created
+	 * by referencing "sl811h_driver".
 	 */
 	platform_dev.name = sl811h_driver.name;
 	return platform_device_register(&platform_dev);
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 151154d..5832953 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -2,8 +2,8 @@
  * UHCI-specific debugging code. Invaluable when something
  * goes wrong, but don't get in my face.
  *
- * Kernel visible pointers are surrounded in []'s and bus
- * visible pointers are surrounded in ()'s
+ * Kernel visible pointers are surrounded in []s and bus
+ * visible pointers are surrounded in ()s
  *
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999-2001 Johannes Erdfelt
@@ -19,7 +19,7 @@
 
 static struct dentry *uhci_debugfs_root = NULL;
 
-/* Handle REALLY large printk's so we don't overflow buffers */
+/* Handle REALLY large printks so we don't overflow buffers */
 static inline void lprintk(char *buf)
 {
 	char *p;
@@ -160,7 +160,7 @@
 			}
 
 			if (active && ni > i) {
-				out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
+				out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
 				tmp = ntmp;
 				td = ntd;
 				i = ni;
@@ -173,7 +173,7 @@
 	if (list_empty(&urbp->queue_list) || urbp->queued)
 		goto out;
 
-	out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
+	out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
 
 	head = &urbp->queue_list;
 	tmp = head->next;
@@ -197,7 +197,7 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-static const char *qh_names[] = {
+static const char * const qh_names[] = {
   "skel_int128_qh", "skel_int64_qh",
   "skel_int32_qh", "skel_int16_qh",
   "skel_int8_qh", "skel_int4_qh",
@@ -464,7 +464,7 @@
 		} while (tmp != head);
 	}
 
-	out += sprintf(out, "Skeleton QH's\n");
+	out += sprintf(out, "Skeleton QHs\n");
 
 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
 		int shown = 0;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 79efaf7..dfe121d 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -23,11 +23,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -67,10 +62,10 @@
 
 /*
  * debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
+ * debug = 1, dump failed URBs except for stalls
+ * debug = 2, dump all failed URBs (including stalls)
  *            show all queues in /debug/uhci/[pci_addr]
- * debug = 3, show all TD's in URB's when dumping
+ * debug = 3, show all TDs in URBs when dumping
  */
 #ifdef DEBUG
 static int debug = 1;
@@ -93,7 +88,7 @@
 #define FSBR_DELAY	msecs_to_jiffies(50)
 
 /* When we timeout an idle transfer for FSBR, we'll switch it over to */
-/* depth first traversal. We'll do it in groups of this number of TD's */
+/* depth first traversal. We'll do it in groups of this number of TDs */
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
@@ -478,8 +473,6 @@
 	struct dentry *dentry;
 
 	hcd->uses_new_polling = 1;
-	if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
-		hcd->can_wakeup = 1;		/* Assume it supports PME# */
 
 	dentry = debugfs_create_file(hcd->self.bus_name,
 			S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
@@ -573,7 +566,7 @@
 	uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
 
 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
-	uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
+	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
 		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
 	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
 
@@ -735,8 +728,9 @@
 
 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
-	/* We aren't in D3 state anymore, we do that even if dead as I
-	 * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
+	/* Since we aren't in D3 any more, it's safe to set this flag
+	 * even if the controller was dead.  It might not even be dead
+	 * any more, if the firmware or quirks code has reset it.
 	 */
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	mb();
@@ -755,8 +749,12 @@
 	check_and_reset_hc(uhci);
 	configure_hc(uhci);
 
-	if (uhci->rh_state == UHCI_RH_RESET)
+	if (uhci->rh_state == UHCI_RH_RESET) {
+
+		/* The controller had to be reset */
+		usb_root_hub_lost_power(hcd->self.root_hub);
 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+	}
 
 	spin_unlock_irq(&uhci->lock);
 
@@ -882,7 +880,7 @@
 
 init_failed:
 	if (kmem_cache_destroy(uhci_up_cachep))
-		warn("not all urb_priv's were freed!");
+		warn("not all urb_privs were freed!");
 
 up_failed:
 	debugfs_remove(uhci_debugfs_root);
@@ -900,7 +898,7 @@
 	pci_unregister_driver(&uhci_pci_driver);
 	
 	if (kmem_cache_destroy(uhci_up_cachep))
-		warn("not all urb_priv's were freed!");
+		warn("not all urb_privs were freed!");
 
 	debugfs_remove(uhci_debugfs_root);
 	kfree(errbuf);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index e576db5..8b4b887 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -71,8 +71,6 @@
 #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
 #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
 
-#define UHCI_NULL_DATA_SIZE	0x7FF	/* for UHCI controller TD */
-
 #define UHCI_PTR_BITS		cpu_to_le32(0x000F)
 #define UHCI_PTR_TERM		cpu_to_le32(0x0001)
 #define UHCI_PTR_QH		cpu_to_le32(0x0002)
@@ -168,9 +166,11 @@
 #define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
 #define TD_TOKEN_PID_MASK	0xFF
 
-#define uhci_explen(len)	((len) << TD_TOKEN_EXPLEN_SHIFT)
+#define uhci_explen(len)	((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
+					TD_TOKEN_EXPLEN_SHIFT)
 
-#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK)
+#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
+					1) & TD_TOKEN_EXPLEN_MASK)
 #define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
 #define uhci_endpoint(token)	(((token) >> 15) & 0xf)
 #define uhci_devaddr(token)	(((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
@@ -223,10 +223,10 @@
  */
 
 /*
- * The UHCI driver places Interrupt, Control and Bulk into QH's both
- * to group together TD's for one transfer, and also to faciliate queuing
- * of URB's. To make it easy to insert entries into the schedule, we have
- * a skeleton of QH's for each predefined Interrupt latency, low-speed
+ * The UHCI driver places Interrupt, Control and Bulk into QHs both
+ * to group together TDs for one transfer, and also to facilitate queuing
+ * of URBs. To make it easy to insert entries into the schedule, we have
+ * a skeleton of QHs for each predefined Interrupt latency, low-speed
  * control, full-speed control and terminating QH (see explanation for
  * the terminating QH below).
  *
@@ -257,8 +257,8 @@
  *   reclamation.
  *
  * Isochronous transfers are stored before the start of the skeleton
- * schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * schedule and don't use QHs. While the UHCI spec doesn't forbid the
+ * use of QHs for Isochronous, it doesn't use them either. And the spec
  * says that queues never advance on an error completion status, which
  * makes them totally unsuitable for Isochronous transfers.
  */
@@ -359,7 +359,7 @@
 	struct dma_pool *td_pool;
 
 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
-	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
+	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QHs */
 
 	spinlock_t lock;
 
@@ -389,22 +389,22 @@
 	unsigned long resuming_ports;
 	unsigned long ports_timeout;		/* Time to stop signalling */
 
-	/* Main list of URB's currently controlled by this HC */
+	/* Main list of URBs currently controlled by this HC */
 	struct list_head urb_list;
 
-	/* List of QH's that are done, but waiting to be unlinked (race) */
+	/* List of QHs that are done, but waiting to be unlinked (race) */
 	struct list_head qh_remove_list;
 	unsigned int qh_remove_age;		/* Age in frames */
 
-	/* List of TD's that are done, but waiting to be freed (race) */
+	/* List of TDs that are done, but waiting to be freed (race) */
 	struct list_head td_remove_list;
 	unsigned int td_remove_age;		/* Age in frames */
 
-	/* List of asynchronously unlinked URB's */
+	/* List of asynchronously unlinked URBs */
 	struct list_head urb_remove_list;
 	unsigned int urb_remove_age;		/* Age in frames */
 
-	/* List of URB's awaiting completion callback */
+	/* List of URBs awaiting completion callback */
 	struct list_head complete_list;
 
 	int rh_numports;			/* Number of root-hub ports */
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 7e46887..b607600 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -80,7 +80,7 @@
 }
 
 /*
- * We insert Isochronous URB's directly into the frame list at the beginning
+ * We insert Isochronous URBs directly into the frame list at the beginning
  */
 static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
 {
@@ -369,7 +369,7 @@
 				uhci_fixup_toggle(urb,
 					uhci_toggle(td_token(lltd)) ^ 1));
 
-	/* All qh's in the queue need to link to the next queue */
+	/* All qhs in the queue need to link to the next queue */
 	urbp->qh->link = eurbp->qh->link;
 
 	wmb();			/* Make sure we flush everything */
@@ -502,7 +502,7 @@
 	}
 
 	/* Check to see if the remove list is empty. Set the IOC bit */
-	/* to force an interrupt so we can remove the TD's*/
+	/* to force an interrupt so we can remove the TDs*/
 	if (list_empty(&uhci->td_remove_list))
 		uhci_set_next_interrupt(uhci);
 
@@ -596,7 +596,7 @@
 		return -ENOMEM;
 
 	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination | uhci_explen(7),
+	uhci_fill_td(td, status, destination | uhci_explen(8),
 		urb->setup_dma);
 
 	/*
@@ -612,7 +612,7 @@
 	}
 
 	/*
-	 * Build the DATA TD's
+	 * Build the DATA TDs
 	 */
 	while (len > 0) {
 		int pktsze = len;
@@ -628,7 +628,7 @@
 		destination ^= TD_TOKEN_TOGGLE;
 	
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
 			data);
 
 		data += pktsze;
@@ -658,7 +658,7 @@
 
 	uhci_add_td_to_urb(urb, td);
 	uhci_fill_td(td, status | TD_CTRL_IOC,
-		destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+		destination | uhci_explen(0), 0);
 
 	qh = uhci_alloc_qh(uhci);
 	if (!qh)
@@ -744,7 +744,7 @@
 
 	urb->actual_length = 0;
 
-	/* The rest of the TD's (but the last) are data */
+	/* The rest of the TDs (but the last) are data */
 	tmp = tmp->next;
 	while (tmp != head && tmp->next != head) {
 		unsigned int ctrlstat;
@@ -848,7 +848,7 @@
 		status |= TD_CTRL_SPD;
 
 	/*
-	 * Build the DATA TD's
+	 * Build the DATA TDs
 	 */
 	do {	/* Allow zero length packets */
 		int pktsze = maxsze;
@@ -864,7 +864,7 @@
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
 			data);
@@ -890,7 +890,7 @@
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+		uhci_fill_td(td, status, destination | uhci_explen(0) |
 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
 			data);
@@ -1025,7 +1025,7 @@
 	list_for_each_entry(up, &uhci->urb_list, urb_list) {
 		struct urb *u = up->urb;
 
-		/* look for pending URB's with identical pipe handle */
+		/* look for pending URBs with identical pipe handle */
 		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
 		    (u->status == -EINPROGRESS) && (u != urb)) {
 			if (!last_urb)
@@ -1092,7 +1092,7 @@
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
+		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
 			urb->transfer_dma + urb->iso_frame_desc[i].offset);
 
 		if (i + 1 >= urb->number_of_packets)
@@ -1355,7 +1355,7 @@
 
 	uhci_delete_queued_urb(uhci, urb);
 
-	/* The interrupt loop will reclaim the QH's */
+	/* The interrupt loop will reclaim the QHs */
 	uhci_remove_qh(uhci, urbp->qh);
 	urbp->qh = NULL;
 }
@@ -1413,7 +1413,7 @@
 	list_for_each_entry(td, head, list) {
 		/*
 		 * Make sure we don't do the last one (since it'll have the
-		 * TERM bit set) as well as we skip every so many TD's to
+		 * TERM bit set) as well as we skip every so many TDs to
 		 * make sure it doesn't hog the bandwidth
 		 */
 		if (td->list.next != head && (count % DEPTH_INTERVAL) ==
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 1d973bc..0498711 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -962,7 +962,6 @@
  */
 static struct usb_driver mdc800_usb_driver =
 {
-	.owner =	THIS_MODULE,
 	.name =		"mdc800",
 	.probe =	mdc800_usb_probe,
 	.disconnect =	mdc800_usb_disconnect,
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 950543a..458f2ac 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -160,7 +160,6 @@
 static struct usb_device_id mts_usb_ids [];
 
 static struct usb_driver mts_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"microtekX6",
 	.probe =	mts_usb_probe,
 	.disconnect =	mts_usb_disconnect,
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 1e53934..509dd0a 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -273,6 +273,20 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called ati_remote.
 
+config USB_ATI_REMOTE2
+	tristate "ATI / Philips USB RF remote control"
+	depends on USB && INPUT
+	---help---
+	  Say Y here if you want to use an ATI or Philips USB RF remote control.
+	  These are RF remotes with USB receivers.
+	  ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards
+	  and is also available as a separate product.
+	  This driver provides mouse pointer, left and right mouse buttons,
+	  and maps all the other remote buttons to keypress events.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ati_remote2.
+
 config USB_KEYSPAN_REMOTE
 	tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
 	depends on USB && INPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 07cb17d..d512d9f 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -28,6 +28,7 @@
 
 obj-$(CONFIG_USB_AIPTEK)	+= aiptek.o
 obj-$(CONFIG_USB_ATI_REMOTE)	+= ati_remote.o
+obj-$(CONFIG_USB_ATI_REMOTE2)	+= ati_remote2.o
 obj-$(CONFIG_USB_HID)		+= usbhid.o
 obj-$(CONFIG_USB_KBD)		+= usbkbd.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index a32558b..df29b80 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -261,7 +261,6 @@
 MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
 
 static struct usb_driver usb_acecad_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usb_acecad",
 	.probe =	usb_acecad_probe,
 	.disconnect =	usb_acecad_disconnect,
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 0e2505c..a6693b0 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -338,7 +338,7 @@
  * the bitmap which comes from the tablet. This hides the
  * issue that the F_keys are not sequentially numbered.
  */
-static int macroKeyEvents[] = {
+static const int macroKeyEvents[] = {
 	KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
 	KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11,
 	KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17,
@@ -2093,7 +2093,7 @@
 	/* Programming the tablet macro keys needs to be done with a for loop
 	 * as the keycodes are discontiguous.
 	 */
-	for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
+	for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
 		set_bit(macroKeyEvents[i], inputdev->keybit);
 
 	/*
@@ -2135,7 +2135,7 @@
 	 * not an error :-)
 	 */
 
-	for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
+	for (i = 0; i < ARRAY_SIZE(speeds); ++i) {
 		aiptek->curSetting.programmableDelay = speeds[i];
 		(void)aiptek_program_tablet(aiptek);
 		if (aiptek->inputdev->absmax[ABS_X] > 0) {
@@ -2190,7 +2190,6 @@
 static void aiptek_disconnect(struct usb_interface *intf);
 
 static struct usb_driver aiptek_driver = {
-	.owner = THIS_MODULE,
 	.name = "aiptek",
 	.probe = aiptek_probe,
 	.disconnect = aiptek_disconnect,
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 15840db..1949b54 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -452,7 +452,6 @@
 }
 
 static struct usb_driver atp_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "appletouch",
 	.probe		= atp_probe,
 	.disconnect	= atp_disconnect,
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 9a2a47d..f7bdc50 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -96,6 +96,7 @@
 #include <linux/usb.h>
 #include <linux/usb_input.h>
 #include <linux/wait.h>
+#include <linux/jiffies.h>
 
 /*
  * Module and Version Information, Module Parameters
@@ -146,7 +147,7 @@
 static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
 
 /* Acceleration curve for directional control pad */
-static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
 
 /* Duplicate event filtering time.
  * Sequential, identical KIND_FILTERED inputs with less than
@@ -197,7 +198,7 @@
 #define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
 
 /* Translation table from hardware messages to input events. */
-static struct {
+static const struct {
 	short kind;
 	unsigned char data1, data2;
 	int type;
@@ -295,7 +296,6 @@
 
 /* usb specific object to register with the usb subsystem */
 static struct usb_driver ati_remote_driver = {
-	.owner        = THIS_MODULE,
 	.name         = "ati_remote",
 	.probe        = ati_remote_probe,
 	.disconnect   = ati_remote_disconnect,
@@ -472,7 +472,7 @@
 		/* Filter duplicate events which happen "too close" together. */
 		if ((ati_remote->old_data[0] == data[1]) &&
 			(ati_remote->old_data[1] == data[2]) &&
-			((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
+			time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) {
 			ati_remote->repeat_count++;
 		} else {
 			ati_remote->repeat_count = 0;
@@ -507,16 +507,16 @@
 	 * pad down, so we increase acceleration, ramping up over two seconds to
 	 * a maximum speed.  The acceleration curve is #defined above.
 	 */
-	if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) {
+	if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) {
 		acc = 1;
 		ati_remote->acc_jiffies = jiffies;
 	}
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3))  acc = accel[0];
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2))  acc = accel[1];
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1))  acc = accel[2];
-	else if ((jiffies - ati_remote->acc_jiffies) < HZ )        acc = accel[3];
-	else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4];
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1))  acc = accel[5];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3)))  acc = accel[0];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2)))  acc = accel[1];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1)))  acc = accel[2];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + HZ))         acc = accel[3];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1)))  acc = accel[5];
 	else acc = accel[6];
 
 	input_regs(dev, regs);
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
new file mode 100644
index 0000000..ab1a1ae
--- /dev/null
+++ b/drivers/usb/input/ati_remote2.c
@@ -0,0 +1,477 @@
+/*
+ * ati_remote2 - ATI/Philips USB RF remote driver
+ *
+ * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/usb_input.h>
+
+#define DRIVER_DESC    "ATI/Philips USB RF remote driver"
+#define DRIVER_VERSION "0.1"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
+MODULE_LICENSE("GPL");
+
+static unsigned int mode_mask = 0x1F;
+module_param(mode_mask, uint, 0644);
+MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
+
+static struct usb_device_id ati_remote2_id_table[] = {
+	{ USB_DEVICE(0x0471, 0x0602) },	/* ATI Remote Wonder II */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, ati_remote2_id_table);
+
+static struct {
+	int hw_code;
+	int key_code;
+} ati_remote2_key_table[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x0c, KEY_POWER },
+	{ 0x0d, KEY_MUTE },
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x11, KEY_VOLUMEDOWN },
+	{ 0x20, KEY_CHANNELUP },
+	{ 0x21, KEY_CHANNELDOWN },
+	{ 0x28, KEY_FORWARD },
+	{ 0x29, KEY_REWIND },
+	{ 0x2c, KEY_PLAY },
+	{ 0x30, KEY_PAUSE },
+	{ 0x31, KEY_STOP },
+	{ 0x37, KEY_RECORD },
+	{ 0x38, KEY_DVD },
+	{ 0x39, KEY_TV },
+	{ 0x54, KEY_MENU },
+	{ 0x58, KEY_UP },
+	{ 0x59, KEY_DOWN },
+	{ 0x5a, KEY_LEFT },
+	{ 0x5b, KEY_RIGHT },
+	{ 0x5c, KEY_OK },
+	{ 0x78, KEY_A },
+	{ 0x79, KEY_B },
+	{ 0x7a, KEY_C },
+	{ 0x7b, KEY_D },
+	{ 0x7c, KEY_E },
+	{ 0x7d, KEY_F },
+	{ 0x82, KEY_ENTER },
+	{ 0x8e, KEY_VENDOR },
+	{ 0x96, KEY_COFFEE },
+	{ 0xa9, BTN_LEFT },
+	{ 0xaa, BTN_RIGHT },
+	{ 0xbe, KEY_QUESTION },
+	{ 0xd5, KEY_FRONT },
+	{ 0xd0, KEY_EDIT },
+	{ 0xf9, KEY_INFO },
+	{ (0x00 << 8) | 0x3f, KEY_PROG1 },
+	{ (0x01 << 8) | 0x3f, KEY_PROG2 },
+	{ (0x02 << 8) | 0x3f, KEY_PROG3 },
+	{ (0x03 << 8) | 0x3f, KEY_PROG4 },
+	{ (0x04 << 8) | 0x3f, KEY_PC },
+	{ 0, KEY_RESERVED }
+};
+
+struct ati_remote2 {
+	struct input_dev *idev;
+	struct usb_device *udev;
+
+	struct usb_interface *intf[2];
+	struct usb_endpoint_descriptor *ep[2];
+	struct urb *urb[2];
+	void *buf[2];
+	dma_addr_t buf_dma[2];
+
+	unsigned long jiffies;
+	int mode;
+
+	char name[64];
+	char phys[64];
+};
+
+static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id);
+static void ati_remote2_disconnect(struct usb_interface *interface);
+
+static struct usb_driver ati_remote2_driver = {
+	.name       = "ati_remote2",
+	.probe      = ati_remote2_probe,
+	.disconnect = ati_remote2_disconnect,
+	.id_table   = ati_remote2_id_table,
+};
+
+static int ati_remote2_open(struct input_dev *idev)
+{
+	struct ati_remote2 *ar2 = idev->private;
+	int r;
+
+	r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
+	if (r) {
+		dev_err(&ar2->intf[0]->dev,
+			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+		return r;
+	}
+	r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
+	if (r) {
+		usb_kill_urb(ar2->urb[0]);
+		dev_err(&ar2->intf[1]->dev,
+			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+		return r;
+	}
+
+	return 0;
+}
+
+static void ati_remote2_close(struct input_dev *idev)
+{
+	struct ati_remote2 *ar2 = idev->private;
+
+	usb_kill_urb(ar2->urb[0]);
+	usb_kill_urb(ar2->urb[1]);
+}
+
+static void ati_remote2_input_mouse(struct ati_remote2 *ar2, struct pt_regs *regs)
+{
+	struct input_dev *idev = ar2->idev;
+	u8 *data = ar2->buf[0];
+
+	if (data[0] > 4) {
+		dev_err(&ar2->intf[0]->dev,
+			"Unknown mode byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	if (!((1 << data[0]) & mode_mask))
+		return;
+
+	input_regs(idev, regs);
+	input_event(idev, EV_REL, REL_X, (s8) data[1]);
+	input_event(idev, EV_REL, REL_Y, (s8) data[2]);
+	input_sync(idev);
+}
+
+static int ati_remote2_lookup(unsigned int hw_code)
+{
+	int i;
+
+	for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+		if (ati_remote2_key_table[i].hw_code == hw_code)
+			return i;
+
+	return -1;
+}
+
+static void ati_remote2_input_key(struct ati_remote2 *ar2, struct pt_regs *regs)
+{
+	struct input_dev *idev = ar2->idev;
+	u8 *data = ar2->buf[1];
+	int hw_code, index;
+
+	if (data[0] > 4) {
+		dev_err(&ar2->intf[1]->dev,
+			"Unknown mode byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	hw_code = data[2];
+	/*
+	 * Mode keys (AUX1-AUX4, PC) all generate the same code byte.
+	 * Use the mode byte to figure out which one was pressed.
+	 */
+	if (hw_code == 0x3f) {
+		/*
+		 * For some incomprehensible reason the mouse pad generates
+		 * events which look identical to the events from the last
+		 * pressed mode key. Naturally we don't want to generate key
+		 * events for the mouse pad so we filter out any subsequent
+		 * events from the same mode key.
+		 */
+		if (ar2->mode == data[0])
+			return;
+
+		if (data[1] == 0)
+			ar2->mode = data[0];
+
+		hw_code |= data[0] << 8;
+	}
+
+	if (!((1 << data[0]) & mode_mask))
+		return;
+
+	index = ati_remote2_lookup(hw_code);
+	if (index < 0) {
+		dev_err(&ar2->intf[1]->dev,
+			"Unknown code byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	switch (data[1]) {
+	case 0:	/* release */
+		break;
+	case 1:	/* press */
+		ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]);
+		break;
+	case 2:	/* repeat */
+
+		/* No repeat for mouse buttons. */
+		if (ati_remote2_key_table[index].key_code == BTN_LEFT ||
+		    ati_remote2_key_table[index].key_code == BTN_RIGHT)
+			return;
+
+		if (!time_after_eq(jiffies, ar2->jiffies))
+			return;
+
+		ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]);
+		break;
+	default:
+		dev_err(&ar2->intf[1]->dev,
+			"Unknown state byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	input_regs(idev, regs);
+	input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
+	input_sync(idev);
+}
+
+static void ati_remote2_complete_mouse(struct urb *urb, struct pt_regs *regs)
+{
+	struct ati_remote2 *ar2 = urb->context;
+	int r;
+
+	switch (urb->status) {
+	case 0:
+		ati_remote2_input_mouse(ar2, regs);
+		break;
+	case -ENOENT:
+	case -EILSEQ:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev_dbg(&ar2->intf[0]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+		return;
+	default:
+		dev_err(&ar2->intf[0]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+	}
+
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		dev_err(&ar2->intf[0]->dev,
+			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+}
+
+static void ati_remote2_complete_key(struct urb *urb, struct pt_regs *regs)
+{
+	struct ati_remote2 *ar2 = urb->context;
+	int r;
+
+	switch (urb->status) {
+	case 0:
+		ati_remote2_input_key(ar2, regs);
+		break;
+	case -ENOENT:
+	case -EILSEQ:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev_dbg(&ar2->intf[1]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+		return;
+	default:
+		dev_err(&ar2->intf[1]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+	}
+
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		dev_err(&ar2->intf[1]->dev,
+			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+}
+
+static int ati_remote2_input_init(struct ati_remote2 *ar2)
+{
+	struct input_dev *idev;
+	int i;
+
+	idev = input_allocate_device();
+	if (!idev)
+		return -ENOMEM;
+
+	ar2->idev = idev;
+	idev->private = ar2;
+
+	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+	idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+	idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+		set_bit(ati_remote2_key_table[i].key_code, idev->keybit);
+
+	idev->rep[REP_DELAY]  = 250;
+	idev->rep[REP_PERIOD] = 33;
+
+	idev->open = ati_remote2_open;
+	idev->close = ati_remote2_close;
+
+	idev->name = ar2->name;
+	idev->phys = ar2->phys;
+
+	usb_to_input_id(ar2->udev, &idev->id);
+	idev->cdev.dev = &ar2->udev->dev;
+
+	i = input_register_device(idev);
+	if (i)
+		input_free_device(idev);
+
+	return i;
+}
+
+static int ati_remote2_urb_init(struct ati_remote2 *ar2)
+{
+	struct usb_device *udev = ar2->udev;
+	int i, pipe, maxp;
+
+	for (i = 0; i < 2; i++) {
+		ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
+		if (!ar2->buf[i])
+			return -ENOMEM;
+
+		ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+		if (!ar2->urb[i])
+			return -ENOMEM;
+
+		pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress);
+		maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+		maxp = maxp > 4 ? 4 : maxp;
+
+		usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp,
+				 i ? ati_remote2_complete_key : ati_remote2_complete_mouse,
+				 ar2, ar2->ep[i]->bInterval);
+		ar2->urb[i]->transfer_dma = ar2->buf_dma[i];
+		ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	}
+
+	return 0;
+}
+
+static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		if (ar2->urb[i])
+			usb_free_urb(ar2->urb[i]);
+
+		if (ar2->buf[i])
+			usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
+	}
+}
+
+static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *alt = interface->cur_altsetting;
+	struct ati_remote2 *ar2;
+	int r;
+
+	if (alt->desc.bInterfaceNumber)
+		return -ENODEV;
+
+	ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL);
+	if (!ar2)
+		return -ENOMEM;
+
+	ar2->udev = udev;
+
+	ar2->intf[0] = interface;
+	ar2->ep[0] = &alt->endpoint[0].desc;
+
+	ar2->intf[1] = usb_ifnum_to_if(udev, 1);
+	r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
+	if (r)
+		goto fail1;
+	alt = ar2->intf[1]->cur_altsetting;
+	ar2->ep[1] = &alt->endpoint[0].desc;
+
+	r = ati_remote2_urb_init(ar2);
+	if (r)
+		goto fail2;
+
+	usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
+	strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
+
+	strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
+
+	r = ati_remote2_input_init(ar2);
+	if (r)
+		goto fail2;
+
+	usb_set_intfdata(interface, ar2);
+
+	return 0;
+
+ fail2:
+	ati_remote2_urb_cleanup(ar2);
+
+	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+ fail1:
+	kfree(ar2);
+
+	return r;
+}
+
+static void ati_remote2_disconnect(struct usb_interface *interface)
+{
+	struct ati_remote2 *ar2;
+	struct usb_host_interface *alt = interface->cur_altsetting;
+
+	if (alt->desc.bInterfaceNumber)
+		return;
+
+	ar2 = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	input_unregister_device(ar2->idev);
+
+	ati_remote2_urb_cleanup(ar2);
+
+	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+
+	kfree(ar2);
+}
+
+static int __init ati_remote2_init(void)
+{
+	int r;
+
+	r = usb_register(&ati_remote2_driver);
+	if (r)
+		printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r);
+	else
+		printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n");
+
+	return r;
+}
+
+static void __exit ati_remote2_exit(void)
+{
+	usb_deregister(&ati_remote2_driver);
+}
+
+module_init(ati_remote2_init);
+module_exit(ati_remote2_exit);
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h
index 26ca5b8..b44d398 100644
--- a/drivers/usb/input/fixp-arith.h
+++ b/drivers/usb/input/fixp-arith.h
@@ -38,7 +38,7 @@
 #define FRAC_MASK ((1<<FRAC_N)-1)
 
 // Not to be used directly. Use fixp_{cos,sin}
-static fixp_t cos_table[45] = {
+static const fixp_t cos_table[45] = {
 	0x0100,	0x00FF,	0x00FF,	0x00FE,	0x00FD,	0x00FC,	0x00FA,	0x00F8,
 	0x00F6,	0x00F3,	0x00F0,	0x00ED,	0x00E9,	0x00E6,	0x00E2,	0x00DD,
 	0x00D9,	0x00D4,	0x00CF,	0x00C9,	0x00C4,	0x00BE,	0x00B8,	0x00B1,
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index a3e44ef..5f52979 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1454,7 +1454,7 @@
  * Alphabetically sorted blacklist by quirk type.
  */
 
-static struct hid_blacklist {
+static const struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
 	unsigned quirks;
@@ -1930,7 +1930,6 @@
 MODULE_DEVICE_TABLE (usb, hid_usb_ids);
 
 static struct usb_driver hid_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbhid",
 	.probe =	hid_probe,
 	.disconnect =	hid_disconnect,
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 1220a50..192a03b 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -39,7 +39,7 @@
 
 #define unk	KEY_UNKNOWN
 
-static unsigned char hid_keyboard[256] = {
+static const unsigned char hid_keyboard[256] = {
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
@@ -58,7 +58,7 @@
 	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
 };
 
-static struct {
+static const struct {
 	__s32 x;
 	__s32 y;
 }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 440377c..4dff847 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -826,7 +826,6 @@
 
 
 static /* const */ struct usb_driver hiddev_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"hiddev",
 	.probe =	hiddev_usbd_probe,
 };
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 4a50acb..7618ae5 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -250,7 +250,6 @@
 MODULE_DEVICE_TABLE(usb, itmtouch_ids);
 
 static struct usb_driver itmtouch_driver = {
-	.owner =        THIS_MODULE,
 	.name =         "itmtouch",
 	.probe =        itmtouch_probe,
 	.disconnect =   itmtouch_disconnect,
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index fd48e74e..f6d5cea 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -197,7 +197,6 @@
 }
 
 static struct usb_driver kbtab_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"kbtab",
 	.probe =	kbtab_probe,
 	.disconnect =	kbtab_disconnect,
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index a32cfe5..b4a051b 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -95,7 +95,7 @@
  * Currently there are 15 and 17 button models so RESERVED codes
  * are blank areas in the mapping.
  */
-static int keyspan_key_table[] = {
+static const int keyspan_key_table[] = {
 	KEY_RESERVED,		/* 0 is just a place holder. */
 	KEY_RESERVED,
 	KEY_STOP,
@@ -559,7 +559,6 @@
  */
 static struct usb_driver keyspan_driver =
 {
-	.owner =	THIS_MODULE,
 	.name =		"keyspan_remote",
 	.probe =	keyspan_probe,
 	.disconnect =	keyspan_disconnect,
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 52cc18c..f018953 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -310,7 +310,6 @@
 MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
 
 static struct usb_driver mtouchusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "mtouchusb",
 	.probe		= mtouchusb_probe,
 	.disconnect	= mtouchusb_disconnect,
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index b747623..fdf0f78 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -441,7 +441,6 @@
 MODULE_DEVICE_TABLE (usb, powermate_devices);
 
 static struct usb_driver powermate_driver = {
-	.owner =	THIS_MODULE,
         .name =         "powermate",
         .probe =        powermate_probe,
         .disconnect =   powermate_disconnect,
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 7420c6b..3b3c7b4 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -1,7 +1,7 @@
 /******************************************************************************
  * touchkitusb.c  --  Driver for eGalax TouchKit USB Touchscreens
  *
- * Copyright (C) 2004 by Daniel Ritz
+ * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
  *
  * This program is free software; you can redistribute it and/or
@@ -41,15 +41,13 @@
 #define TOUCHKIT_MAX_YC			0x07ff
 #define TOUCHKIT_YC_FUZZ		0x0
 #define TOUCHKIT_YC_FLAT		0x0
-#define TOUCHKIT_REPORT_DATA_SIZE	8
+#define TOUCHKIT_REPORT_DATA_SIZE	16
 
 #define TOUCHKIT_DOWN			0x01
-#define TOUCHKIT_POINT_TOUCH		0x81
-#define TOUCHKIT_POINT_NOTOUCH		0x80
 
-#define TOUCHKIT_GET_TOUCHED(dat)	((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0)
-#define TOUCHKIT_GET_X(dat)		(((dat)[3] << 7) | (dat)[4])
-#define TOUCHKIT_GET_Y(dat)		(((dat)[1] << 7) | (dat)[2])
+#define TOUCHKIT_PKT_TYPE_MASK		0xFE
+#define TOUCHKIT_PKT_TYPE_REPT		0x80
+#define TOUCHKIT_PKT_TYPE_DIAG		0x0A
 
 #define DRIVER_VERSION			"v0.1"
 #define DRIVER_AUTHOR			"Daniel Ritz <daniel.ritz@gmx.ch>"
@@ -62,6 +60,8 @@
 struct touchkit_usb {
 	unsigned char *data;
 	dma_addr_t data_dma;
+	char buffer[TOUCHKIT_REPORT_DATA_SIZE];
+	int buf_len;
 	struct urb *irq;
 	struct usb_device *udev;
 	struct input_dev *input;
@@ -77,11 +77,128 @@
 	{}
 };
 
+/* helpers to read the data */
+static inline int touchkit_get_touched(char *data)
+{
+	return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
+}
+
+static inline int touchkit_get_x(char *data)
+{
+	return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
+}
+
+static inline int touchkit_get_y(char *data)
+{
+	return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
+}
+
+
+/* processes one input packet. */
+static void touchkit_process_pkt(struct touchkit_usb *touchkit,
+                                 struct pt_regs *regs, char *pkt)
+{
+	int x, y;
+
+	/* only process report packets */
+	if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
+		return;
+
+	if (swap_xy) {
+		y = touchkit_get_x(pkt);
+		x = touchkit_get_y(pkt);
+	} else {
+		x = touchkit_get_x(pkt);
+		y = touchkit_get_y(pkt);
+	}
+
+	input_regs(touchkit->input, regs);
+	input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
+	input_report_abs(touchkit->input, ABS_X, x);
+	input_report_abs(touchkit->input, ABS_Y, y);
+	input_sync(touchkit->input);
+}
+
+
+static int touchkit_get_pkt_len(char *buf)
+{
+	switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
+	case TOUCHKIT_PKT_TYPE_REPT:
+		return 5;
+
+	case TOUCHKIT_PKT_TYPE_DIAG:
+		return buf[1] + 2;
+	}
+
+	return 0;
+}
+
+static void touchkit_process(struct touchkit_usb *touchkit, int len,
+                             struct pt_regs *regs)
+{
+	char *buffer;
+	int pkt_len, buf_len, pos;
+
+	/* if the buffer contains data, append */
+	if (unlikely(touchkit->buf_len)) {
+		int tmp;
+
+		/* if only 1 byte in buffer, add another one to get length */
+		if (touchkit->buf_len == 1)
+			touchkit->buffer[1] = touchkit->data[0];
+
+		pkt_len = touchkit_get_pkt_len(touchkit->buffer);
+
+		/* unknown packet: drop everything */
+		if (!pkt_len)
+			return;
+
+		/* append, process */
+		tmp = pkt_len - touchkit->buf_len;
+		memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
+		touchkit_process_pkt(touchkit, regs, touchkit->buffer);
+
+		buffer = touchkit->data + tmp;
+		buf_len = len - tmp;
+	} else {
+		buffer = touchkit->data;
+		buf_len = len;
+	}
+
+	/* only one byte left in buffer */
+	if (unlikely(buf_len == 1)) {
+		touchkit->buffer[0] = buffer[0];
+		touchkit->buf_len = 1;
+		return;
+	}
+
+	/* loop over the buffer */
+	pos = 0;
+	while (pos < buf_len) {
+		/* get packet len */
+		pkt_len = touchkit_get_pkt_len(buffer + pos);
+
+		/* unknown packet: drop everything */
+		if (unlikely(!pkt_len))
+			return;
+
+		/* full packet: process */
+		if (likely(pkt_len <= buf_len)) {
+			touchkit_process_pkt(touchkit, regs, buffer + pos);
+		} else {
+			/* incomplete packet: save in buffer */
+			memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
+			touchkit->buf_len = buf_len - pos;
+		}
+		pos += pkt_len;
+	}
+}
+
+
 static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct touchkit_usb *touchkit = urb->context;
 	int retval;
-	int x, y;
 
 	switch (urb->status) {
 	case 0:
@@ -105,20 +222,7 @@
 		goto exit;
 	}
 
-	if (swap_xy) {
-		y = TOUCHKIT_GET_X(touchkit->data);
-		x = TOUCHKIT_GET_Y(touchkit->data);
-	} else {
-		x = TOUCHKIT_GET_X(touchkit->data);
-		y = TOUCHKIT_GET_Y(touchkit->data);
-	}
-
-	input_regs(touchkit->input, regs);
-	input_report_key(touchkit->input, BTN_TOUCH,
-	                 TOUCHKIT_GET_TOUCHED(touchkit->data));
-	input_report_abs(touchkit->input, ABS_X, x);
-	input_report_abs(touchkit->input, ABS_Y, y);
-	input_sync(touchkit->input);
+	touchkit_process(touchkit, urb->actual_length, regs);
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -267,7 +371,6 @@
 MODULE_DEVICE_TABLE(usb, touchkit_devices);
 
 static struct usb_driver touchkit_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "touchkitusb",
 	.probe		= touchkit_probe,
 	.disconnect	= touchkit_disconnect,
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 226b6f9..2f3edc2 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -345,7 +345,6 @@
 MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
 
 static struct usb_driver usb_kbd_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbkbd",
 	.probe =	usb_kbd_probe,
 	.disconnect =	usb_kbd_disconnect,
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 230f6b1..af52613 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -226,7 +226,6 @@
 MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
 
 static struct usb_driver usb_mouse_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "usbmouse",
 	.probe		= usb_mouse_probe,
 	.disconnect	= usb_mouse_disconnect,
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index dc099bb..48df4cf 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -945,7 +945,6 @@
 }
 
 static struct usb_driver wacom_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"wacom",
 	.probe =	wacom_probe,
 	.disconnect =	wacom_disconnect,
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 43112f0..e278489 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -70,7 +70,7 @@
 
 #define XPAD_PKT_LEN 32
 
-static struct xpad_device {
+static const struct xpad_device {
 	u16 idVendor;
 	u16 idProduct;
 	char *name;
@@ -81,13 +81,13 @@
 	{ 0x0000, 0x0000, "X-Box pad" }
 };
 
-static signed short xpad_btn[] = {
+static const signed short xpad_btn[] = {
 	BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z,	/* "analog" buttons */
 	BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR,	/* start/back/sticks */
 	-1						/* terminating entry */
 };
 
-static signed short xpad_abs[] = {
+static const signed short xpad_abs[] = {
 	ABS_X, ABS_Y,		/* left stick */
 	ABS_RX, ABS_RY,		/* right stick */
 	ABS_Z, ABS_RZ,		/* triggers left/right */
@@ -316,7 +316,6 @@
 }
 
 static struct usb_driver xpad_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "xpad",
 	.probe		= xpad_probe,
 	.disconnect	= xpad_disconnect,
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index f526aeb..1bfc105 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -987,7 +987,6 @@
 }
 
 static struct usb_driver yealink_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "yealink",
 	.probe		= usb_probe,
 	.disconnect	= usb_disconnect,
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 27b23c5..18d8eaf 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -812,7 +812,6 @@
 MODULE_DEVICE_TABLE (usb, dabusb_ids);
 
 static struct usb_driver dabusb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"dabusb",
 	.probe =	dabusb_probe,
 	.disconnect =	dabusb_disconnect,
diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index 7503f5b..6a5700e 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/usb/media/dsbr100.c
@@ -150,7 +150,6 @@
 
 /* USB subsystem interface */
 static struct usb_driver usb_dsbr100_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"dsbr100",
 	.probe =	usb_dsbr100_probe,
 	.disconnect =	usb_dsbr100_disconnect,
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index ba41fc7..a42c222 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -3457,7 +3457,7 @@
 	if(init_model3_input) {
 		if (debug > 0)
 			info("Setting input to RCA.");
-		for (i=0; i < (sizeof(initData)/sizeof(initData[0])); i++) {
+		for (i=0; i < ARRAY_SIZE(initData); i++) {
 			ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
 		}
 	}
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 9fe2c27..e2ede58 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -77,14 +77,14 @@
 static int sharpness =	MAX_SHARPNESS/2;
 static int whitebal =	3*(MAX_WHITEBAL/4);
 
-static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
+static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
 
 /* These FPS speeds are from the windows config box. They are
  * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
  * real fps.
  */
 
-static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
+static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
 			       { 24, 40, 48, 60, 72, 80, 100 },
 			       { 18, 30, 36, 45, 54, 60, 75  },
 			       { 6,  10, 12, 15, 18, 21, 25  } };
@@ -95,7 +95,7 @@
 	u8	cmd;
 };
 
-static struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
+static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
 					  { 160, 136, 0xa },
 					  { 176, 144, 0x4 },
 					  { 320, 240, 0x5 } };
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 036c485..3a0e8ce 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -211,7 +211,7 @@
 
 /* Number of times to retry a failed I2C transaction. Increase this if you
  * are getting "Failed to read sensor ID..." */
-static int i2c_detect_tries = 5;
+static const int i2c_detect_tries = 5;
 
 /* MMX support is present in kernel and CPU. Checked upon decomp module load. */
 #if defined(__i386__) || defined(__x86_64__)
@@ -6008,7 +6008,6 @@
 }
 
 static struct usb_driver ov511_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ov511",
 	.id_table =	device_table,
 	.probe =	ov51x_probe,
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 5309919..359c4b2 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -109,7 +109,7 @@
 #define PT_RESET_CONTROL_FORMATTER		0x02
 #define PT_STATUS_FORMATTER			0x03
 
-static char *size2name[PSZ_MAX] =
+static const char *size2name[PSZ_MAX] =
 {
 	"subQCIF",
 	"QSIF",
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 5524fd7..09ca612 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -111,7 +111,6 @@
 static void usb_pwc_disconnect(struct usb_interface *intf);
 
 static struct usb_driver pwc_driver = {
-	.owner =		THIS_MODULE,
 	.name =			"Philips webcam",	/* name */
 	.id_table =		pwc_device_table,
 	.probe =		usb_pwc_probe,		/* probe() */
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index f69e443..b2ae29a 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1401,7 +1401,6 @@
 }
 
 static struct usb_driver se401_driver = {
-	.owner		= THIS_MODULE,
         .name		= "se401",
         .id_table	= device_table,
 	.probe		= se401_probe,
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index b2e66e3..8d1a1c3 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -1316,7 +1316,7 @@
 	struct v4l2_control ctrl;
 	struct v4l2_queryctrl *qctrl;
 	struct v4l2_rect* rect;
-	u8 i = 0, n = 0;
+	u8 i = 0;
 	int err = 0;
 
 	if (!(cam->state & DEV_INITIALIZED)) {
@@ -1352,7 +1352,7 @@
 		return err;
 
 	if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
-		DBG(3, "Compressed video format is active, quality %d", 
+		DBG(3, "Compressed video format is active, quality %d",
 		    cam->compression.quality)
 	else
 		DBG(3, "Uncompressed video format is active")
@@ -1364,9 +1364,8 @@
 		}
 
 	if (s->set_ctrl) {
-		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
-		for (i = 0; i < n; i++)
-			if (s->qctrl[i].id != 0 && 
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+			if (s->qctrl[i].id != 0 &&
 			    !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
 				ctrl.id = s->qctrl[i].id;
 				ctrl.value = qctrl[i].default_value;
@@ -1388,7 +1387,7 @@
 		init_waitqueue_head(&cam->wait_stream);
 		cam->nreadbuffers = 2;
 		memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
-		memcpy(&(s->_rect), &(s->cropcap.defrect), 
+		memcpy(&(s->_rect), &(s->cropcap.defrect),
 		       sizeof(struct v4l2_rect));
 		cam->state |= DEV_INITIALIZED;
 	}
@@ -1810,13 +1809,12 @@
 	{
 		struct sn9c102_sensor* s = cam->sensor;
 		struct v4l2_queryctrl qc;
-		u8 i, n;
+		u8 i;
 
 		if (copy_from_user(&qc, arg, sizeof(qc)))
 			return -EFAULT;
 
-		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
-		for (i = 0; i < n; i++)
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
 			if (qc.id && qc.id == s->qctrl[i].id) {
 				memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
 				if (copy_to_user(arg, &qc, sizeof(qc)))
@@ -1852,7 +1850,7 @@
 	{
 		struct sn9c102_sensor* s = cam->sensor;
 		struct v4l2_control ctrl;
-		u8 i, n;
+		u8 i;
 		int err = 0;
 
 		if (!s->set_ctrl)
@@ -1861,8 +1859,7 @@
 		if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 			return -EFAULT;
 
-		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
-		for (i = 0; i < n; i++)
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
 			if (ctrl.id == s->qctrl[i].id) {
 				if (ctrl.value < s->qctrl[i].minimum ||
 				    ctrl.value > s->qctrl[i].maximum)
@@ -2544,7 +2541,7 @@
 	unsigned int i, n;
 	int err = 0, r;
 
-	n = sizeof(sn9c102_id_table)/sizeof(sn9c102_id_table[0]);
+	n = ARRAY_SIZE(sn9c102_id_table);
 	for (i = 0; i < n-1; i++)
 		if (le16_to_cpu(udev->descriptor.idVendor) == 
 		    sn9c102_id_table[i].idVendor &&
@@ -2711,7 +2708,6 @@
 
 
 static struct usb_driver sn9c102_usb_driver = {
-	.owner =      THIS_MODULE,
 	.name =       "sn9c102",
 	.id_table =   sn9c102_id_table,
 	.probe =      sn9c102_usb_probe,
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 0fd0fa9..774038b 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -1477,7 +1477,6 @@
 }
 
 static struct usb_driver stv680_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"stv680",
 	.probe =	stv680_probe,
 	.disconnect =	stv680_disconnect,
diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h
index 4459406..b0551cd 100644
--- a/drivers/usb/media/stv680.h
+++ b/drivers/usb/media/stv680.h
@@ -151,7 +151,7 @@
 };
 
 
-static unsigned char red[256] = { 
+static const unsigned char red[256] = {
 	0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 
 	18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, 
 	44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, 
@@ -176,7 +176,7 @@
 	220, 220, 221, 221 
 }; 
 
-static unsigned char green[256] = {
+static const unsigned char green[256] = {
 	0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 
 	21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, 
 	50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, 
@@ -201,7 +201,7 @@
 	245, 245, 246, 246 
 }; 
 
-static unsigned char blue[256] = {
+static const unsigned char blue[256] = {
 	0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 
 	23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, 
 	55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, 
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index 24efb21..4bd1133 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -725,7 +725,7 @@
 		/* Allocate user_data separately because of kmalloc's limits */
 		if (num_extra > 0) {
 			up->user_size = num_cams * num_extra;
-			up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL);
+			up->user_data = kmalloc(up->user_size, GFP_KERNEL);
 			if (up->user_data == NULL) {
 				err("%s: Failed to allocate user_data (%d. bytes)",
 				    __FUNCTION__, up->user_size);
@@ -955,7 +955,7 @@
 	.ioctl =  usbvideo_v4l_ioctl,
 	.llseek = no_llseek,
 };
-static struct video_device usbvideo_template = {
+static const struct video_device usbvideo_template = {
 	.owner =      THIS_MODULE,
 	.type =       VID_TYPE_CAPTURE,
 	.hardware =   VID_HARDWARE_CPIA,
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 0bc0b12..1c73155 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1257,7 +1257,6 @@
 MODULE_DEVICE_TABLE(usb, vicam_table);
 
 static struct usb_driver vicam_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "vicam",
 	.probe		= vicam_probe,
 	.disconnect	= vicam_disconnect,
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index 67612c8..04d6933 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -2958,7 +2958,7 @@
 	};
 
 	#define V4L1_IOCTL(cmd) \
-	        ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \
+	        ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \
 	        v4l1_ioctls[_IOC_NR((cmd))] : "?")
 
 	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
@@ -3554,7 +3554,7 @@
 
 
 	/* Allocate 2 bytes of memory for camera control USB transfers */
-	if (!(cam->control_buffer = (u16*)kmalloc(2, GFP_KERNEL))) {
+	if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) {
 		DBG(1,"Couldn't allocate memory for camera control transfers")
 		err = -ENOMEM;
 		goto fail;
@@ -3562,7 +3562,7 @@
 	memset(cam->control_buffer, 0, 2);
 
 	/* Allocate 8 bytes of memory for USB data transfers to the FSB */
-	if (!(cam->data_buffer = (u16*)kmalloc(8, GFP_KERNEL))) {
+	if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) {
 		DBG(1, "Couldn't allocate memory for data "
 		       "transfers to the FSB")
 		err = -ENOMEM;
@@ -3668,7 +3668,6 @@
 
 
 static struct usb_driver w9968cf_usb_driver = {
-	.owner =      THIS_MODULE,
 	.name =       "w9968cf",
 	.id_table =   winbond_id_table,
 	.probe =      w9968cf_usb_probe,
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index b293db3..449b250 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -767,7 +767,7 @@
 	        memset (bep, 0, sizeof (auerbuf_t));
                 bep->list = bcp;
                 INIT_LIST_HEAD (&bep->buff_list);
-                bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL);
+                bep->bufp = kmalloc (bufsize, GFP_KERNEL);
                 if (!bep->bufp)
 			goto bl_fail;
                 bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
@@ -1123,7 +1123,7 @@
                 }
         }
         if (!cp->intbufp) {
-                cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL);
+                cp->intbufp = kmalloc (irqsize, GFP_KERNEL);
                 if (!cp->intbufp) {
                         ret = -ENOMEM;
                         goto intoend;
@@ -2103,7 +2103,6 @@
 
 /* Standard usb driver struct */
 static struct usb_driver auerswald_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"auerswald",
 	.probe =	auerswald_probe,
 	.disconnect =	auerswald_disconnect,
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index b33044d..6671317 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -50,7 +50,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver cytherm_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cytherm",
 	.probe =	cytherm_probe,
 	.disconnect =	cytherm_disconnect,
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index c815520..3824df3 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -227,7 +227,6 @@
 }
 
 static struct usb_driver emi26_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "emi26 - firmware loader",
 	.probe		= emi26_probe,
 	.disconnect	= emi26_disconnect,
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 189986a..52fea2e 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -266,7 +266,6 @@
 }
 
 static struct usb_driver emi62_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "emi62 - firmware loader",
 	.probe		= emi62_probe,
 	.disconnect	= emi62_disconnect,
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 1dc3e0f..d8cde10 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -114,7 +114,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver idmouse_driver = {
-	.owner = THIS_MODULE,
 	.name = DRIVER_SHORT,
 	.probe = idmouse_probe,
 	.disconnect = idmouse_disconnect,
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7e93ac9..981d8a5 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -763,7 +763,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver ld_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ldusb",
 	.probe =	ld_usb_probe,
 	.disconnect =	ld_usb_disconnect,
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 2703e20..1336745 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -282,7 +282,6 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver tower_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"legousbtower",
 	.probe =	tower_probe,
 	.disconnect =	tower_disconnect,
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 067a814..605a3c8 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -555,7 +555,6 @@
 }
 
 static struct usb_driver interfacekit_driver = {
-	.owner = THIS_MODULE,
 	.name = "phidgetkit",
 	.probe = interfacekit_probe,
 	.disconnect = interfacekit_disconnect,
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index a30d4a6..b3418d2 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -306,7 +306,6 @@
 }
 
 static struct usb_driver servo_driver = {
-	.owner = THIS_MODULE,
 	.name = "phidgetservo",
 	.probe = servo_probe,
 	.disconnect = servo_disconnect,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 9590dba..384fa37 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -465,14 +465,14 @@
 
 	rio->rio_dev = dev;
 
-	if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+	if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
 		err("probe_rio: Not enough memory for the output buffer");
 		usb_deregister_dev(intf, &usb_rio_class);
 		return -ENOMEM;
 	}
 	dbg("probe_rio: obuf address:%p", rio->obuf);
 
-	if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+	if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
 		err("probe_rio: Not enough memory for the input buffer");
 		usb_deregister_dev(intf, &usb_rio_class);
 		kfree(rio->obuf);
@@ -522,7 +522,6 @@
 MODULE_DEVICE_TABLE (usb, rio_table);
 
 static struct usb_driver rio_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"rio500",
 	.probe =	probe_rio,
 	.disconnect =	disconnect_rio,
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 41ef2b6..3260d59 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -863,9 +863,6 @@
 
 	    switch (length) {
 
-		case 0:
-			return ret;
-
 		case 1:
 			if (userbuffer) {
 				if (get_user(swap8, (u8 __user *)userbuffer))
@@ -1221,9 +1218,6 @@
 
 	    switch (length) {
 
-		case 0:
-			return ret;
-
 		case 1:
 
 			ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
@@ -2443,8 +2437,8 @@
 	u8 *tempbuf;
 	u16 *tempbufb;
 	size_t written;
-	static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
-	static char bootlogo[] = "(o_ //\\ V_/_";
+	static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+	static const char bootlogo[] = "(o_ //\\ V_/_";
 
 	/* sisusb->lock is down */
 
@@ -3489,7 +3483,6 @@
 MODULE_DEVICE_TABLE (usb, sisusb_table);
 
 static struct usb_driver sisusb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"sisusb",
 	.probe =	sisusb_probe,
 	.disconnect =	sisusb_disconnect,
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 85f3725..cc3dae3 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -371,7 +371,6 @@
 }
 
 static struct usb_driver lcd_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usblcd",
 	.probe =	lcd_probe,
 	.disconnect =	lcd_disconnect,
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 3c93921..877b081 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -148,7 +148,6 @@
 }
 
 static struct usb_driver led_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbled",
 	.probe =	led_probe,
 	.disconnect =	led_disconnect,
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 605a2af..84fa172 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2134,7 +2134,6 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver usbtest_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbtest",
 	.id_table =	id_table,
 	.probe =	usbtest_probe,
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 1cabe7e..4081990 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -780,7 +780,6 @@
 
 
 static struct usb_driver uss720_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"uss720",
 	.probe =	uss720_probe,
 	.disconnect =	uss720_disconnect,
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 17d0190..6116121 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -97,19 +97,12 @@
 	if (len >= DATA_MAX)
 		len = DATA_MAX;
 
-	/*
-	 * Bulk is easy to shortcut reliably. 
-	 * XXX Other pipe types need consideration. Currently, we overdo it
-	 * and collect garbage for them: better more than less.
-	 */
-	if (usb_pipebulk(pipe) || usb_pipecontrol(pipe)) {
-		if (usb_pipein(pipe)) {
-			if (ev_type == 'S')
-				return '<';
-		} else {
-			if (ev_type == 'C')
-				return '>';
-		}
+	if (usb_pipein(pipe)) {
+		if (ev_type == 'S')
+			return '<';
+	} else {
+		if (ev_type == 'C')
+			return '>';
 	}
 
 	/*
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 542120e..5411816 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -912,13 +912,16 @@
 	// ASIX AX88772 10/100
         USB_DEVICE (0x0b95, 0x7720),
         .driver_info = (unsigned long) &ax88772_info,
+}, {
+	// Linksys USB200M Rev 2
+	USB_DEVICE (0x13b1, 0x0018),
+	.driver_info = (unsigned long) &ax88772_info,
 },
 	{ },		// END
 };
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver asix_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"asix",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index 37ef365..be5f5e1 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -934,7 +934,6 @@
 MODULE_DEVICE_TABLE(usb, catc_id_table);
 
 static struct usb_driver catc_driver = {
-	.owner =	THIS_MODULE,
 	.name =		driver_name,
 	.probe =	catc_probe,
 	.disconnect =	catc_disconnect,
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index c008c98..63f1f3b 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -476,7 +476,6 @@
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver cdc_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cdc_ether",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
index f05cfb8..ec801e8 100644
--- a/drivers/usb/net/cdc_subset.c
+++ b/drivers/usb/net/cdc_subset.c
@@ -306,7 +306,6 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_driver cdc_subset_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cdc_subset",
 	.probe =	usbnet_probe,
 	.suspend =	usbnet_suspend,
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index 2455e9a..faf1e86 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -377,7 +377,6 @@
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver gl620a_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"gl620a",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index b577651..def3bb8 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -175,7 +175,6 @@
  *     kaweth_driver
  ****************************************************************/
 static struct usb_driver kaweth_driver = {
-	.owner =	THIS_MODULE,
 	.name =		driver_name,
 	.probe =	kaweth_probe,
 	.disconnect =	kaweth_disconnect,
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index b3799b1..78e6a43 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -593,7 +593,6 @@
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver net1080_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"net1080",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 683e3df..156a2f1 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -45,7 +45,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.6.12 (2005/01/13)"
+#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -57,12 +57,14 @@
 
 static int loopback = 0;
 static int mii_mode = 0;
+static char *devid=NULL;
 
 static struct usb_eth_dev usb_dev_id[] = {
 #define	PEGASUS_DEV(pn, vid, pid, flags)	\
 	{.name = pn, .vendor = vid, .device = pid, .private = flags},
 #include "pegasus.h"
 #undef	PEGASUS_DEV
+	{NULL, 0, 0, 0},
 	{NULL, 0, 0, 0}
 };
 
@@ -71,6 +73,7 @@
 	{.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
 #include "pegasus.h"
 #undef	PEGASUS_DEV
+	{},
 	{}
 };
 
@@ -79,8 +82,10 @@
 MODULE_LICENSE("GPL");
 module_param(loopback, bool, 0);
 module_param(mii_mode, bool, 0);
+module_param(devid, charp, 0);
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
 MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
+MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'");
 
 /* use ethtool to change the level for any given device */
 static int msg_level = -1;
@@ -113,7 +118,7 @@
 		break;
 	default:
 		if (netif_msg_drv(pegasus))
-			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+			dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
 				__FUNCTION__, urb->status);
 	}
 	pegasus->flags &= ~ETH_REGS_CHANGED;
@@ -308,9 +313,9 @@
 	__le16 regdi;
 	int ret;
 
-	ret = set_register(pegasus, PhyCtrl, 0);
-	ret = set_registers(pegasus, PhyAddr, sizeof (data), data);
-	ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+	set_register(pegasus, PhyCtrl, 0);
+	set_registers(pegasus, PhyAddr, sizeof (data), data);
+	set_register(pegasus, PhyCtrl, (indx | PHY_READ));
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, PhyCtrl, 1, data);
 		if (data[0] & PHY_DONE)
@@ -319,12 +324,12 @@
 	if (i < REG_TIMEOUT) {
 		ret = get_registers(pegasus, PhyData, 2, &regdi);
 		*regd = le16_to_cpu(regdi);
-		return 1;
+		return ret;
 	}
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 
-	return 0;
+	return ret;
 }
 
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
@@ -344,20 +349,20 @@
 
 	data[1] = (u8) regd;
 	data[2] = (u8) (regd >> 8);
-	ret = set_register(pegasus, PhyCtrl, 0);
-	ret = set_registers(pegasus, PhyAddr, sizeof(data), data);
-	ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
+	set_register(pegasus, PhyCtrl, 0);
+	set_registers(pegasus, PhyAddr, sizeof(data), data);
+	set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, PhyCtrl, 1, data);
 		if (data[0] & PHY_DONE)
 			break;
 	}
 	if (i < REG_TIMEOUT)
-		return 0;
+		return ret;
 
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
-	return 1;
+	return -ETIMEDOUT;
 }
 
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
@@ -374,9 +379,9 @@
 	__le16 retdatai;
 	int ret;
 
-	ret = set_register(pegasus, EpromCtrl, 0);
-	ret = set_register(pegasus, EpromOffset, index);
-	ret = set_register(pegasus, EpromCtrl, EPROM_READ);
+	set_register(pegasus, EpromCtrl, 0);
+	set_register(pegasus, EpromOffset, index);
+	set_register(pegasus, EpromCtrl, EPROM_READ);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -386,12 +391,12 @@
 	if (i < REG_TIMEOUT) {
 		ret = get_registers(pegasus, EpromData, 2, &retdatai);
 		*retdata = le16_to_cpu(retdatai);
-		return 0;
+		return ret;
 	}
 
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
-	return -1;
+	return -ETIMEDOUT;
 }
 
 #ifdef	PEGASUS_WRITE_EEPROM
@@ -400,8 +405,8 @@
 	__u8 tmp;
 	int ret;
 
-	ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
-	ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
+	get_registers(pegasus, EthCtrl2, 1, &tmp);
+	set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
 }
 
 static inline void disable_eprom_write(pegasus_t * pegasus)
@@ -409,9 +414,9 @@
 	__u8 tmp;
 	int ret;
 
-	ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
-	ret = set_register(pegasus, EpromCtrl, 0);
-	ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
+	get_registers(pegasus, EthCtrl2, 1, &tmp);
+	set_register(pegasus, EpromCtrl, 0);
+	set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
 }
 
 static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
@@ -420,11 +425,11 @@
 	__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
 	int ret;
 
-	ret = set_registers(pegasus, EpromOffset, 4, d);
+	set_registers(pegasus, EpromOffset, 4, d);
 	enable_eprom_write(pegasus);
-	ret = set_register(pegasus, EpromOffset, index);
-	ret = set_registers(pegasus, EpromData, 2, &data);
-	ret = set_register(pegasus, EpromCtrl, EPROM_WRITE);
+	set_register(pegasus, EpromOffset, index);
+	set_registers(pegasus, EpromData, 2, &data);
+	set_register(pegasus, EpromCtrl, EPROM_WRITE);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -433,10 +438,10 @@
 	}
 	disable_eprom_write(pegasus);
 	if (i < REG_TIMEOUT)
-		return 0;
+		return ret;
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
-	return -1;
+	return -ETIMEDOUT;
 }
 #endif				/* PEGASUS_WRITE_EEPROM */
 
@@ -454,10 +459,9 @@
 static void set_ethernet_addr(pegasus_t * pegasus)
 {
 	__u8 node_id[6];
-	int ret;
 
 	get_node_id(pegasus, node_id);
-	ret = set_registers(pegasus, EthID, sizeof (node_id), node_id);
+	set_registers(pegasus, EthID, sizeof (node_id), node_id);
 	memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
 }
 
@@ -465,30 +469,29 @@
 {
 	__u8 data = 0x8;
 	int i;
-	int ret;
 
-	ret = set_register(pegasus, EthCtrl1, data);
+	set_register(pegasus, EthCtrl1, data);
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		ret = get_registers(pegasus, EthCtrl1, 1, &data);
+		get_registers(pegasus, EthCtrl1, 1, &data);
 		if (~data & 0x08) {
 			if (loopback & 1)
 				break;
 			if (mii_mode && (pegasus->features & HAS_HOME_PNA))
-				ret = set_register(pegasus, Gpio1, 0x34);
+				set_register(pegasus, Gpio1, 0x34);
 			else
-				ret = set_register(pegasus, Gpio1, 0x26);
-			ret = set_register(pegasus, Gpio0, pegasus->features);
-			ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
+				set_register(pegasus, Gpio1, 0x26);
+			set_register(pegasus, Gpio0, pegasus->features);
+			set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
 			break;
 		}
 	}
 	if (i == REG_TIMEOUT)
-		return 1;
+		return -ETIMEDOUT;
 
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
 	    usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
-		ret = set_register(pegasus, Gpio0, 0x24);
-		ret = set_register(pegasus, Gpio0, 0x26);
+		set_register(pegasus, Gpio0, 0x24);
+		set_register(pegasus, Gpio0, 0x26);
 	}
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
 		__u16 auxmode;
@@ -527,7 +530,7 @@
 		write_mii_word(pegasus, 0, 0x1b, auxmode | 4);
 	}
 
-	return 0;
+	return ret;
 }
 
 static void fill_skb_pool(pegasus_t * pegasus)
@@ -881,9 +884,8 @@
 static inline void disable_net_traffic(pegasus_t * pegasus)
 {
 	int tmp = 0;
-	int ret;
 
-	ret = set_registers(pegasus, EthCtrl0, 2, &tmp);
+	set_registers(pegasus, EthCtrl0, 2, &tmp);
 }
 
 static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -1206,18 +1208,17 @@
 static inline void setup_pegasus_II(pegasus_t * pegasus)
 {
 	__u8 data = 0xa5;
-	int ret;
 	
-	ret = set_register(pegasus, Reg1d, 0);
-	ret = set_register(pegasus, Reg7b, 1);
+	set_register(pegasus, Reg1d, 0);
+	set_register(pegasus, Reg7b, 1);
 	mdelay(100);
 	if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
-		ret = set_register(pegasus, Reg7b, 0);
+		set_register(pegasus, Reg7b, 0);
 	else
-		ret = set_register(pegasus, Reg7b, 2);
+		set_register(pegasus, Reg7b, 2);
 
-	ret = set_register(pegasus, 0x83, data);
-	ret = get_registers(pegasus, 0x83, 1, &data);
+	set_register(pegasus, 0x83, data);
+	get_registers(pegasus, 0x83, 1, &data);
 
 	if (data == 0xa5) {
 		pegasus->chip = 0x8513;
@@ -1225,14 +1226,14 @@
 		pegasus->chip = 0;
 	}
 
-	ret = set_register(pegasus, 0x80, 0xc0);
-	ret = set_register(pegasus, 0x83, 0xff);
-	ret = set_register(pegasus, 0x84, 0x01);
+	set_register(pegasus, 0x80, 0xc0);
+	set_register(pegasus, 0x83, 0xff);
+	set_register(pegasus, 0x84, 0x01);
 	
 	if (pegasus->features & HAS_HOME_PNA && mii_mode)
-		ret = set_register(pegasus, Reg81, 6);
+		set_register(pegasus, Reg81, 6);
 	else
-		ret = set_register(pegasus, Reg81, 2);
+		set_register(pegasus, Reg81, 2);
 }
 
 
@@ -1414,9 +1415,42 @@
 	.resume = pegasus_resume,
 };
 
+static void parse_id(char *id)
+{
+	unsigned int vendor_id=0, device_id=0, flags=0, i=0;
+	char *token, *name=NULL;
+
+	if ((token = strsep(&id, ":")) != NULL)
+		name = token;
+	/* name now points to a null terminated string*/
+	if ((token = strsep(&id, ":")) != NULL)
+		vendor_id = simple_strtoul(token, NULL, 16);
+	if ((token = strsep(&id, ":")) != NULL)
+		device_id = simple_strtoul(token, NULL, 16);
+	flags = simple_strtoul(id, NULL, 16);
+	pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n",
+	        driver_name, name, vendor_id, device_id, flags);
+
+	if (vendor_id > 0x10000 || vendor_id == 0)
+		return;
+	if (device_id > 0x10000 || device_id == 0)
+		return;
+
+	for (i=0; usb_dev_id[i].name; i++);
+	usb_dev_id[i].name = name;
+	usb_dev_id[i].vendor = vendor_id;
+	usb_dev_id[i].device = device_id;
+	usb_dev_id[i].private = flags;
+	pegasus_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+	pegasus_ids[i].idVendor = vendor_id;
+	pegasus_ids[i].idProduct = device_id;
+}
+
 static int __init pegasus_init(void)
 {
 	pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
+	if (devid)
+		parse_id(devid);
 	pegasus_workqueue = create_singlethread_workqueue("pegasus");
 	if (!pegasus_workqueue)
 		return -ENOMEM;
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c
index 89856aa..4fe8633 100644
--- a/drivers/usb/net/plusb.c
+++ b/drivers/usb/net/plusb.c
@@ -127,7 +127,6 @@
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver plusb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"plusb",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index c0ecbab..49991ac 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -586,7 +586,6 @@
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver rndis_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"rndis_host",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 787dd35..8ca52be 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -177,7 +177,6 @@
 static const char driver_name [] = "rtl8150";
 
 static struct usb_driver rtl8150_driver = {
-	.owner =	THIS_MODULE,
 	.name =		driver_name,
 	.probe =	rtl8150_probe,
 	.disconnect =	rtl8150_disconnect,
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index 680d139..9c5ab25 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -357,7 +357,6 @@
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver zaurus_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"zaurus",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index 2f52261..f3a8e28 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -1722,7 +1722,7 @@
 	    IW_PRIV_TYPE_NONE, "sethostauth" },
 	{ ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
 	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
-	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 
+	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
 	    IW_PRIV_TYPE_NONE, "authstation" },
 	{ ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 	    IW_PRIV_TYPE_NONE, "setmaxassoc" },
@@ -1731,9 +1731,9 @@
 };
 
 static const struct iw_handler_def zd1201_iw_handlers = {
-	.num_standard 		= sizeof(zd1201_iw_handler)/sizeof(iw_handler),
-	.num_private 		= sizeof(zd1201_private_handler)/sizeof(iw_handler),
-	.num_private_args 	= sizeof(zd1201_private_args)/sizeof(struct iw_priv_args),
+	.num_standard 		= ARRAY_SIZE(zd1201_iw_handler),
+	.num_private 		= ARRAY_SIZE(zd1201_private_handler),
+	.num_private_args 	= ARRAY_SIZE(zd1201_private_args),
 	.standard 		= (iw_handler *)zd1201_iw_handler,
 	.private 		= (iw_handler *)zd1201_private_handler,
 	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
@@ -1829,6 +1829,8 @@
 	if (err)
 		goto err_net;
 
+	SET_NETDEV_DEV(zd->dev, &usb->dev);
+
 	err = register_netdev(zd->dev);
 	if (err)
 		goto err_net;
@@ -1923,7 +1925,6 @@
 #endif
 
 static struct usb_driver zd1201_usb = {
-	.owner = THIS_MODULE,
 	.name = "zd1201",
 	.probe = zd1201_probe,
 	.disconnect = zd1201_disconnect,
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 1f29d88..dbf1f063 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -23,11 +23,11 @@
 MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver airprime_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"airprime",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver airprime_device = {
diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c
index 18022a7..343f6f2 100644
--- a/drivers/usb/serial/anydata.c
+++ b/drivers/usb/serial/anydata.c
@@ -27,11 +27,11 @@
 static int debug;
 
 static struct usb_driver anydata_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"anydata",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static int anydata_open(struct usb_serial_port *port, struct file *filp)
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 84bc0ee..4144777 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -113,11 +113,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver belkin_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"belkin",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* All of the device info needed for the serial converters */
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index c978700..da46b35 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -67,11 +67,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver cp2101_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "cp2101",
 	.probe		= usb_serial_probe,
 	.disconnect	= usb_serial_disconnect,
 	.id_table	= id_table,
+	.no_dynamic_id	= 	1,
 };
 
 static struct usb_serial_driver cp2101_device = {
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index e581e4a..6d18d4e 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -76,11 +76,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver cyberjack_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cyberjack",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver cyberjack_device = {
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index af9290e..af18355 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -112,6 +112,7 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 struct cypress_private {
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index dc74644..8fc414b 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -493,11 +493,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver digi_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"digi_acceleport",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 0b0546d..79a766e 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -105,11 +105,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver empeg_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"empeg",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver empeg_device = {
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 06e04b4..eb863b3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -471,12 +471,15 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
 	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
+	{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -488,9 +491,10 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
-static char *ftdi_chip_name[] = {
+static const char *ftdi_chip_name[] = {
 	[SIO] = "SIO",	/* the serial part of FT8U100AX */
 	[FT8U232AM] = "FT8U232AM",
 	[FT232BM] = "FT232BM",
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 773ea3e..f380f9ea 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -343,6 +343,13 @@
 #define XSENS_CONVERTER_7_PID	0xD38F
 
 /*
+ * Teratronik product ids.
+ * Submitted by O. Wölfelschneider.
+ */
+#define FTDI_TERATRONIK_VCP_PID	 0xEC88	/* Teratronik device (preferring VCP driver on windows) */
+#define FTDI_TERATRONIK_D2XX_PID 0xEC89	/* Teratronik device (preferring D2XX driver on windows) */
+
+/*
  * Evolution Robotics products (http://www.evolution.com/).
  * Submitted by Shawn M. Lavelle.
  */
@@ -352,6 +359,12 @@
 /* Pyramid Computer GmbH */
 #define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
 
+/*
+ * Posiflex inc retail equipment (http://www.posiflex.com.tw)
+ */
+#define POSIFLEX_VID		0x0d3a  /* Vendor ID */
+#define POSIFLEX_PP7000_PID	0x0300  /* PP-7000II thermal printer */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 35820bd..452efce 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -222,11 +222,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver garmin_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"garmin_gps",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 53a47c3..4ddac62 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -68,11 +68,11 @@
 }
 
 static struct usb_driver generic_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbserial_generic",
 	.probe =	generic_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	generic_serial_ids,
+	.no_dynamic_id = 	1,
 };
 #endif
 
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 8eadfb7..e9719da 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -37,11 +37,11 @@
 MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver hp49gp_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"hp4X",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver hp49gp_device = {
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index dc4c498..faedbeb 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -184,7 +184,7 @@
 // These assume a 3.6864MHz crystal, the standard /16, and
 // MCR.7 = 0.
 //
-static struct divisor_table_entry divisor_table[] = {
+static const struct divisor_table_entry divisor_table[] = {
 	{   50,		4608},  
 	{   75,		3072},  
 	{   110,	2095},		/* 2094.545455 => 230450   => .0217 % over */
@@ -242,11 +242,11 @@
 #include "io_tables.h"	/* all of the devices that this driver supports */
 
 static struct usb_driver io_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"io_edgeport",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* function prototypes for all of our local functions */
@@ -2353,7 +2353,7 @@
 
 	dbg("%s - %d", __FUNCTION__, baudrate);
 
-	for (i = 0; i < NUM_ENTRIES(divisor_table); i++) {
+	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
 		if ( divisor_table[i].BaudRate == baudrate ) {
 			*divisor = divisor_table[i].Divisor;
 			return 0;
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index 5112d7a..123fa8a 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -31,9 +31,6 @@
 #ifndef HIGH8
 	#define HIGH8(a)	((unsigned char)((a & 0xff00) >> 8))
 #endif
-#ifndef NUM_ENTRIES
-	#define NUM_ENTRIES(x)	(sizeof(x)/sizeof((x)[0]))
-#endif
 
 #ifndef __KERNEL__
 #define __KERNEL__
diff --git a/drivers/usb/serial/io_fw_boot2.h b/drivers/usb/serial/io_fw_boot2.h
index c7c3a3c..e3463de 100644
--- a/drivers/usb/serial/io_fw_boot2.h
+++ b/drivers/usb/serial/io_fw_boot2.h
@@ -537,7 +537,7 @@
 
 };
 
-static struct edge_firmware_version_info IMAGE_VERSION_NAME = {
+static const struct edge_firmware_version_info IMAGE_VERSION_NAME = {
 	2, 0, 3 };		// Major, Minor, Build
 
 #undef IMAGE_VERSION_NAME
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 832b6d6..2edf9cab 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -216,11 +216,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver io_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"io_ti",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 
@@ -2843,7 +2843,7 @@
  * Free the buffer and all associated memory.
  */
 
-void edge_buf_free(struct edge_buf *eb)
+static void edge_buf_free(struct edge_buf *eb)
 {
 	if (eb) {
 		kfree(eb->buf_buf);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d5d0664..06d07ce 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -542,11 +542,11 @@
 MODULE_DEVICE_TABLE (usb, ipaq_id_table);
 
 static struct usb_driver ipaq_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ipaq",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	ipaq_id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 7744b81..2dd191f 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -152,11 +152,11 @@
 MODULE_DEVICE_TABLE(usb, usb_ipw_ids);
 
 static struct usb_driver usb_ipw_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ipwtty",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	usb_ipw_ids,
+	.no_dynamic_id = 	1,
 };
 
 static int debug;
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 19f329e..a590104 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -125,11 +125,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver ir_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ir-usb",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 5cfc13b..7472ed6 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -520,11 +520,11 @@
 MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
 
 static struct usb_driver keyspan_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"keyspan",                
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	keyspan_ids_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* usb_device_id table for the pre-firmware download keyspan devices */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index cd4f48b..b0441c3 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -150,11 +150,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver keyspan_pda_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"keyspan_pda",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_device_id id_table_std [] = {
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index a8951c0..4e2f7df 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -116,11 +116,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver kl5kusb105d_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"kl5kusb105d",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver kl5kusb105d_device = {
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 9456dd9..d9c21e2 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -97,11 +97,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver kobil_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"kobil",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index ca5dbad..b6d6cab 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -125,11 +125,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver mct_u232_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"mct_u232",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver mct_u232_device = {
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 3caf970..762d8ff 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -80,11 +80,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver omninet_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"omninet",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 7716000..3fd2405 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -95,11 +95,11 @@
 MODULE_DEVICE_TABLE(usb, option_ids);
 
 static struct usb_driver option_driver = {
-	.owner      = THIS_MODULE,
 	.name       = "option",
 	.probe      = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table   = option_ids,
+	.no_dynamic_id = 	1,
 };
 
 /* The card has three separate interfaces, wich the serial driver
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 41a45a5..f037210 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -82,11 +82,11 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver pl2303_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"pl2303",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 #define SET_LINE_REQUEST_TYPE		0x21
@@ -810,7 +810,7 @@
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 status_idx = UART_STATE;
-	u8 length = UART_STATE;
+	u8 length = UART_STATE + 1;
 
 	if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
 	    (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 ||
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index c22bdc0..f0215f8 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -160,14 +160,14 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver safe_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"safe_serial",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
-static __u16 crc10_table[256] = {
+static const __u16 crc10_table[256] = {
 	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
 	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
 	0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
@@ -425,7 +425,7 @@
 	if (vendor || product) {
 		info ("vendor: %x product: %x\n", vendor, product);
 
-		for (i = 0; i < (sizeof (id_table) / sizeof (struct usb_device_id)); i++) {
+		for (i = 0; i < ARRAY_SIZE(id_table); i++) {
 			if (!id_table[i].idVendor && !id_table[i].idProduct) {
 				id_table[i].idVendor = vendor;
 				id_table[i].idProduct = product;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 205dbf7..abb830c 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -248,11 +248,11 @@
 };
 
 static struct usb_driver ti_usb_driver = {
-	.owner			= THIS_MODULE,
 	.name			= "ti_usb_3410_5052",
 	.probe			= usb_serial_probe,
 	.disconnect		= usb_serial_disconnect,
 	.id_table		= ti_id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver ti_1port_device = {
@@ -351,17 +351,14 @@
 	int i,j;
 	int ret;
 
-
 	/* insert extra vendor and product ids */
-	j = sizeof(ti_id_table_3410)/sizeof(struct usb_device_id)
-		- TI_EXTRA_VID_PID_COUNT - 1;
+	j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
 	for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
 		ti_id_table_3410[j].idVendor = vendor_3410[i];
 		ti_id_table_3410[j].idProduct = product_3410[i];
 		ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
 	}
-	j = sizeof(ti_id_table_5052)/sizeof(struct usb_device_id)
-		- TI_EXTRA_VID_PID_COUNT - 1;
+	j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
 	for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
 		ti_id_table_5052[j].idVendor = vendor_5052[i];
 		ti_id_table_5052[j].idProduct = product_5052[i];
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0c4881d..8bc8337 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -30,6 +30,7 @@
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
+#include <asm/semaphore.h>
 #include <linux/usb.h>
 #include "usb-serial.h"
 #include "pl2303.h"
@@ -42,10 +43,10 @@
 
 /* Driver structure we register with the USB core */
 static struct usb_driver usb_serial_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbserial",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
+	.no_dynamic_id = 	1,
 };
 
 /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
@@ -188,6 +189,11 @@
 
 	portNumber = tty->index - serial->minor;
 	port = serial->port[portNumber];
+	if (!port)
+		return -ENODEV;
+
+	if (down_interruptible(&port->sem))
+		return -ERESTARTSYS;
 	 
 	++port->open_count;
 
@@ -213,6 +219,7 @@
 			goto bailout_module_put;
 	}
 
+	up(&port->sem);
 	return 0;
 
 bailout_module_put:
@@ -220,6 +227,7 @@
 bailout_kref_put:
 	kref_put(&serial->kref, destroy_serial);
 	port->open_count = 0;
+	up(&port->sem);
 	return retval;
 }
 
@@ -232,8 +240,10 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	down(&port->sem);
+
 	if (port->open_count == 0)
-		return;
+		goto out;
 
 	--port->open_count;
 	if (port->open_count == 0) {
@@ -251,6 +261,9 @@
 	}
 
 	kref_put(&port->serial->kref, destroy_serial);
+
+out:
+	up(&port->sem);
 }
 
 static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
@@ -258,6 +271,9 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
 
 	if (!port->open_count) {
@@ -277,6 +293,9 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -296,6 +315,9 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s = port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -314,6 +336,9 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -330,6 +355,9 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -347,6 +375,9 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -ENODEV;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
 	if (!port->open_count) {
@@ -368,6 +399,9 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -384,6 +418,9 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -445,6 +482,9 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -464,6 +504,9 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -742,6 +785,7 @@
 		port->number = i + serial->minor;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
+		sema_init(&port->sem, 1);
 		INIT_WORK(&port->work, usb_serial_port_softint, port);
 		serial->port[i] = port;
 	}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 238a5a8..d7d27c3 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -16,6 +16,7 @@
 
 #include <linux/config.h>
 #include <linux/kref.h>
+#include <asm/semaphore.h>
 
 #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
 #define SERIAL_TTY_MINORS	255	/* loads of devices :) */
@@ -30,6 +31,8 @@
  * @serial: pointer back to the struct usb_serial owner of this port.
  * @tty: pointer to the corresponding tty for this port.
  * @lock: spinlock to grab when updating portions of this structure.
+ * @sem: semaphore used to synchronize serial_open() and serial_close()
+ *	access for this port.
  * @number: the number of the port (the minor number).
  * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
  * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
@@ -60,6 +63,7 @@
 	struct usb_serial *	serial;
 	struct tty_struct *	tty;
 	spinlock_t		lock;
+	struct semaphore        sem;
 	unsigned char		number;
 
 	unsigned char *		interrupt_in_buffer;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index a473c1c..49b1fbe 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -173,11 +173,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver visor_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"visor",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 18c3183..a7c3c47 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -127,11 +127,11 @@
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver whiteheat_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"whiteheat",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index c41d64d..92be101 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -112,6 +112,15 @@
 	  Say Y here to include additional code to support the Lexar Jumpshot
 	  USB CompactFlash reader.
 
+config USB_STORAGE_ALAUDA
+	bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)"
+	depends on USB_STORAGE && EXPERIMENTAL
+	help
+	  Say Y here to include additional code to support the Olympus MAUSB-10
+	  and Fujifilm DPC-R1 USB Card reader/writer devices.
+
+	  These devices are based on the Alauda chip and support support both
+	  XD and SmartMedia cards.
 
 config USB_STORAGE_ONETOUCH
 	bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
@@ -124,3 +133,17 @@
 	  hard drive's as an input device. An action can be associated with
 	  this input in any keybinding software. (e.g. gnome's keyboard short-
 	  cuts)
+
+config USB_LIBUSUAL
+	bool "The shared table of common (or usual) storage devices"
+	depends on USB
+	help
+	  This module contains a table of common (or usual) devices
+	  for usb-storage and ub drivers, and allows to switch binding
+	  of these devices without rebuilding modules.
+
+	  Typical syntax of /etc/modprobe.conf is:
+
+		options libusual bias="ub"
+
+	  If unsure, say N.
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 44ab8f9..8cbba22 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -18,7 +18,12 @@
 usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
 
 usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
 			initializers.o $(usb-storage-obj-y)
+
+ifneq ($(CONFIG_USB_LIBUSUAL),)
+	obj-$(CONFIG_USB)	+= libusual.o
+endif
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
new file mode 100644
index 0000000..4d3cbb1
--- /dev/null
+++ b/drivers/usb/storage/alauda.c
@@ -0,0 +1,1119 @@
+/*
+ * Driver for Alauda-based card readers
+ *
+ * Current development and maintenance by:
+ *   (c) 2005 Daniel Drake <dsd@gentoo.org>
+ *
+ * The 'Alauda' is a chip manufacturered by RATOC for OEM use.
+ *
+ * Alauda implements a vendor-specific command set to access two media reader
+ * ports (XD, SmartMedia). This driver converts SCSI commands to the commands
+ * which are accepted by these devices.
+ *
+ * The driver was developed through reverse-engineering, with the help of the
+ * sddr09 driver which has many similarities, and with some help from the
+ * (very old) vendor-supplied GPL sma03 driver.
+ *
+ * For protocol info, see http://alauda.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+#include "alauda.h"
+
+#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
+#define LSB_of(s) ((s)&0xFF)
+#define MSB_of(s) ((s)>>8)
+
+#define MEDIA_PORT(us) us->srb->device->lun
+#define MEDIA_INFO(us) ((struct alauda_info *)us->extra)->port[MEDIA_PORT(us)]
+
+#define PBA_LO(pba) ((pba & 0xF) << 5)
+#define PBA_HI(pba) (pba >> 3)
+#define PBA_ZONE(pba) (pba >> 11)
+
+/*
+ * Media handling
+ */
+
+struct alauda_card_info {
+	unsigned char id;		/* id byte */
+	unsigned char chipshift;	/* 1<<cs bytes total capacity */
+	unsigned char pageshift;	/* 1<<ps bytes in a page */
+	unsigned char blockshift;	/* 1<<bs pages per block */
+	unsigned char zoneshift;	/* 1<<zs blocks per zone */
+};
+
+static struct alauda_card_info alauda_card_ids[] = {
+	/* NAND flash */
+	{ 0x6e, 20, 8, 4, 8},	/* 1 MB */
+	{ 0xe8, 20, 8, 4, 8},	/* 1 MB */
+	{ 0xec, 20, 8, 4, 8},	/* 1 MB */
+	{ 0x64, 21, 8, 4, 9}, 	/* 2 MB */
+	{ 0xea, 21, 8, 4, 9},	/* 2 MB */
+	{ 0x6b, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xe3, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xe5, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xe6, 23, 9, 4, 10},	/* 8 MB */
+	{ 0x73, 24, 9, 5, 10},	/* 16 MB */
+	{ 0x75, 25, 9, 5, 10},	/* 32 MB */
+	{ 0x76, 26, 9, 5, 10},	/* 64 MB */
+	{ 0x79, 27, 9, 5, 10},	/* 128 MB */
+	{ 0x71, 28, 9, 5, 10},	/* 256 MB */
+
+	/* MASK ROM */
+	{ 0x5d, 21, 9, 4, 8},	/* 2 MB */
+	{ 0xd5, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xd6, 23, 9, 4, 10},	/* 8 MB */
+	{ 0x57, 24, 9, 4, 11},	/* 16 MB */
+	{ 0x58, 25, 9, 4, 12},	/* 32 MB */
+	{ 0,}
+};
+
+static struct alauda_card_info *alauda_card_find_id(unsigned char id) {
+	int i;
+
+	for (i = 0; alauda_card_ids[i].id != 0; i++)
+		if (alauda_card_ids[i].id == id)
+			return &(alauda_card_ids[i]);
+	return NULL;
+}
+
+/*
+ * ECC computation.
+ */
+
+static unsigned char parity[256];
+static unsigned char ecc2[256];
+
+static void nand_init_ecc(void) {
+	int i, j, a;
+
+	parity[0] = 0;
+	for (i = 1; i < 256; i++)
+		parity[i] = (parity[i&(i-1)] ^ 1);
+
+	for (i = 0; i < 256; i++) {
+		a = 0;
+		for (j = 0; j < 8; j++) {
+			if (i & (1<<j)) {
+				if ((j & 1) == 0)
+					a ^= 0x04;
+				if ((j & 2) == 0)
+					a ^= 0x10;
+				if ((j & 4) == 0)
+					a ^= 0x40;
+			}
+		}
+		ecc2[i] = ~(a ^ (a<<1) ^ (parity[i] ? 0xa8 : 0));
+	}
+}
+
+/* compute 3-byte ecc on 256 bytes */
+static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
+	int i, j, a;
+	unsigned char par, bit, bits[8];
+
+	par = 0;
+	for (j = 0; j < 8; j++)
+		bits[j] = 0;
+
+	/* collect 16 checksum bits */
+	for (i = 0; i < 256; i++) {
+		par ^= data[i];
+		bit = parity[data[i]];
+		for (j = 0; j < 8; j++)
+			if ((i & (1<<j)) == 0)
+				bits[j] ^= bit;
+	}
+
+	/* put 4+4+4 = 12 bits in the ecc */
+	a = (bits[3] << 6) + (bits[2] << 4) + (bits[1] << 2) + bits[0];
+	ecc[0] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));
+
+	a = (bits[7] << 6) + (bits[6] << 4) + (bits[5] << 2) + bits[4];
+	ecc[1] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));
+
+	ecc[2] = ecc2[par];
+}
+
+static int nand_compare_ecc(unsigned char *data, unsigned char *ecc) {
+	return (data[0] == ecc[0] && data[1] == ecc[1] && data[2] == ecc[2]);
+}
+
+static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
+	memcpy(data, ecc, 3);
+}
+
+/*
+ * Alauda driver
+ */
+
+/*
+ * Forget our PBA <---> LBA mappings for a particular port
+ */
+static void alauda_free_maps (struct alauda_media_info *media_info)
+{
+	unsigned int shift = media_info->zoneshift
+		+ media_info->blockshift + media_info->pageshift;
+	unsigned int num_zones = media_info->capacity >> shift;
+	unsigned int i;
+
+	if (media_info->lba_to_pba != NULL)
+		for (i = 0; i < num_zones; i++) {
+			kfree(media_info->lba_to_pba[i]);
+			media_info->lba_to_pba[i] = NULL;
+		}
+
+	if (media_info->pba_to_lba != NULL)
+		for (i = 0; i < num_zones; i++) {
+			kfree(media_info->pba_to_lba[i]);
+			media_info->pba_to_lba[i] = NULL;
+		}
+}
+
+/*
+ * Returns 2 bytes of status data
+ * The first byte describes media status, and second byte describes door status
+ */
+static int alauda_get_media_status(struct us_data *us, unsigned char *data)
+{
+	int rc;
+	unsigned char command;
+
+	if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+		command = ALAUDA_GET_XD_MEDIA_STATUS;
+	else
+		command = ALAUDA_GET_SM_MEDIA_STATUS;
+
+	rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+		command, 0xc0, 0, 1, data, 2);
+
+	US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n",
+		data[0], data[1]);
+
+	return rc;
+}
+
+/*
+ * Clears the "media was changed" bit so that we know when it changes again
+ * in the future.
+ */
+static int alauda_ack_media(struct us_data *us)
+{
+	unsigned char command;
+
+	if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+		command = ALAUDA_ACK_XD_MEDIA_CHANGE;
+	else
+		command = ALAUDA_ACK_SM_MEDIA_CHANGE;
+
+	return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
+		command, 0x40, 0, 1, NULL, 0);
+}
+
+/*
+ * Retrieves a 4-byte media signature, which indicates manufacturer, capacity,
+ * and some other details.
+ */
+static int alauda_get_media_signature(struct us_data *us, unsigned char *data)
+{
+	unsigned char command;
+
+	if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+		command = ALAUDA_GET_XD_MEDIA_SIG;
+	else
+		command = ALAUDA_GET_SM_MEDIA_SIG;
+
+	return usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+		command, 0xc0, 0, 0, data, 4);
+}
+
+/*
+ * Resets the media status (but not the whole device?)
+ */
+static int alauda_reset_media(struct us_data *us)
+{
+	unsigned char *command = us->iobuf;
+
+	memset(command, 0, 9);
+	command[0] = ALAUDA_BULK_CMD;
+	command[1] = ALAUDA_BULK_RESET_MEDIA;
+	command[8] = MEDIA_PORT(us);
+
+	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+}
+
+/*
+ * Examines the media and deduces capacity, etc.
+ */
+static int alauda_init_media(struct us_data *us)
+{
+	unsigned char *data = us->iobuf;
+	int ready = 0;
+	struct alauda_card_info *media_info;
+	unsigned int num_zones;
+
+	while (ready == 0) {
+		msleep(20);
+
+		if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD)
+			return USB_STOR_TRANSPORT_ERROR;
+
+		if (data[0] & 0x10)
+			ready = 1;
+	}
+
+	US_DEBUGP("alauda_init_media: We are ready for action!\n");
+
+	if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	msleep(10);
+
+	if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	if (data[0] != 0x14) {
+		US_DEBUGP("alauda_init_media: Media not ready after ack\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n",
+		data[0], data[1], data[2], data[3]);
+	media_info = alauda_card_find_id(data[1]);
+	if (media_info == NULL) {
+		printk("alauda_init_media: Unrecognised media signature: "
+			"%02X %02X %02X %02X\n",
+			data[0], data[1], data[2], data[3]);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	MEDIA_INFO(us).capacity = 1 << media_info->chipshift;
+	US_DEBUGP("Found media with capacity: %ldMB\n",
+		MEDIA_INFO(us).capacity >> 20);
+
+	MEDIA_INFO(us).pageshift = media_info->pageshift;
+	MEDIA_INFO(us).blockshift = media_info->blockshift;
+	MEDIA_INFO(us).zoneshift = media_info->zoneshift;
+
+	MEDIA_INFO(us).pagesize = 1 << media_info->pageshift;
+	MEDIA_INFO(us).blocksize = 1 << media_info->blockshift;
+	MEDIA_INFO(us).zonesize = 1 << media_info->zoneshift;
+
+	MEDIA_INFO(us).uzonesize = ((1 << media_info->zoneshift) / 128) * 125;
+	MEDIA_INFO(us).blockmask = MEDIA_INFO(us).blocksize - 1;
+
+	num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift
+		+ MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift);
+	MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO);
+	MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO);
+
+	if (alauda_reset_media(us) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Examines the media status and does the right thing when the media has gone,
+ * appeared, or changed.
+ */
+static int alauda_check_media(struct us_data *us)
+{
+	struct alauda_info *info = (struct alauda_info *) us->extra;
+	unsigned char status[2];
+	int rc;
+
+	rc = alauda_get_media_status(us, status);
+
+	/* Check for no media or door open */
+	if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
+		|| ((status[1] & 0x01) == 0)) {
+		US_DEBUGP("alauda_check_media: No media, or door open\n");
+		alauda_free_maps(&MEDIA_INFO(us));
+		info->sense_key = 0x02;
+		info->sense_asc = 0x3A;
+		info->sense_ascq = 0x00;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
+
+	/* Check for media change */
+	if (status[0] & 0x08) {
+		US_DEBUGP("alauda_check_media: Media change detected\n");
+		alauda_free_maps(&MEDIA_INFO(us));
+		alauda_init_media(us);
+
+		info->sense_key = UNIT_ATTENTION;
+		info->sense_asc = 0x28;
+		info->sense_ascq = 0x00;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Checks the status from the 2nd status register
+ * Returns 3 bytes of status data, only the first is known
+ */
+static int alauda_check_status2(struct us_data *us)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_GET_STATUS2,
+		0, 0, 0, 0, 3, 0, MEDIA_PORT(us)
+	};
+	unsigned char data[3];
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		data, 3, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]);
+	if (data[0] & ALAUDA_STATUS_ERROR)
+		return USB_STOR_XFER_ERROR;
+
+	return USB_STOR_XFER_GOOD;
+}
+
+/*
+ * Gets the redundancy data for the first page of a PBA
+ * Returns 16 bytes.
+ */
+static int alauda_get_redu_data(struct us_data *us, u16 pba, unsigned char *data)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_GET_REDU_DATA,
+		PBA_HI(pba), PBA_ZONE(pba), 0, PBA_LO(pba), 0, 0, MEDIA_PORT(us)
+	};
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		data, 16, NULL);
+}
+
+/*
+ * Finds the first unused PBA in a zone
+ * Returns the absolute PBA of an unused PBA, or 0 if none found.
+ */
+static u16 alauda_find_unused_pba(struct alauda_media_info *info,
+	unsigned int zone)
+{
+	u16 *pba_to_lba = info->pba_to_lba[zone];
+	unsigned int i;
+
+	for (i = 0; i < info->zonesize; i++)
+		if (pba_to_lba[i] == UNDEF)
+			return (zone << info->zoneshift) + i;
+
+	return 0;
+}
+
+/*
+ * Reads the redundancy data for all PBA's in a zone
+ * Produces lba <--> pba mappings
+ */
+static int alauda_read_map(struct us_data *us, unsigned int zone)
+{
+	unsigned char *data = us->iobuf;
+	int result;
+	int i, j;
+	unsigned int zonesize = MEDIA_INFO(us).zonesize;
+	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+	unsigned int lba_offset, lba_real, blocknum;
+	unsigned int zone_base_lba = zone * uzonesize;
+	unsigned int zone_base_pba = zone * zonesize;
+	u16 *lba_to_pba = kcalloc(zonesize, sizeof(u16), GFP_NOIO);
+	u16 *pba_to_lba = kcalloc(zonesize, sizeof(u16), GFP_NOIO);
+	if (lba_to_pba == NULL || pba_to_lba == NULL) {
+		result = USB_STOR_TRANSPORT_ERROR;
+		goto error;
+	}
+
+	US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone);
+
+	/* 1024 PBA's per zone */
+	for (i = 0; i < zonesize; i++)
+		lba_to_pba[i] = pba_to_lba[i] = UNDEF;
+
+	for (i = 0; i < zonesize; i++) {
+		blocknum = zone_base_pba + i;
+
+		result = alauda_get_redu_data(us, blocknum, data);
+		if (result != USB_STOR_XFER_GOOD) {
+			result = USB_STOR_TRANSPORT_ERROR;
+			goto error;
+		}
+
+		/* special PBAs have control field 0^16 */
+		for (j = 0; j < 16; j++)
+			if (data[j] != 0)
+				goto nonz;
+		pba_to_lba[i] = UNUSABLE;
+		US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum);
+		continue;
+
+	nonz:
+		/* unwritten PBAs have control field FF^16 */
+		for (j = 0; j < 16; j++)
+			if (data[j] != 0xff)
+				goto nonff;
+		continue;
+
+	nonff:
+		/* normal PBAs start with six FFs */
+		if (j < 6) {
+			US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: "
+			       "reserved area = %02X%02X%02X%02X "
+			       "data status %02X block status %02X\n",
+			       blocknum, data[0], data[1], data[2], data[3],
+			       data[4], data[5]);
+			pba_to_lba[i] = UNUSABLE;
+			continue;
+		}
+
+		if ((data[6] >> 4) != 0x01) {
+			US_DEBUGP("alauda_read_map: PBA %d has invalid address "
+			       "field %02X%02X/%02X%02X\n",
+			       blocknum, data[6], data[7], data[11], data[12]);
+			pba_to_lba[i] = UNUSABLE;
+			continue;
+		}
+
+		/* check even parity */
+		if (parity[data[6] ^ data[7]]) {
+			printk("alauda_read_map: Bad parity in LBA for block %d"
+			       " (%02X %02X)\n", i, data[6], data[7]);
+			pba_to_lba[i] = UNUSABLE;
+			continue;
+		}
+
+		lba_offset = short_pack(data[7], data[6]);
+		lba_offset = (lba_offset & 0x07FF) >> 1;
+		lba_real = lba_offset + zone_base_lba;
+
+		/*
+		 * Every 1024 physical blocks ("zone"), the LBA numbers
+		 * go back to zero, but are within a higher block of LBA's.
+		 * Also, there is a maximum of 1000 LBA's per zone.
+		 * In other words, in PBA 1024-2047 you will find LBA 0-999
+		 * which are really LBA 1000-1999. This allows for 24 bad
+		 * or special physical blocks per zone.
+		 */
+
+		if (lba_offset >= uzonesize) {
+			printk("alauda_read_map: Bad low LBA %d for block %d\n",
+			       lba_real, blocknum);
+			continue;
+		}
+
+		if (lba_to_pba[lba_offset] != UNDEF) {
+			printk("alauda_read_map: LBA %d seen for PBA %d and %d\n",
+			       lba_real, lba_to_pba[lba_offset], blocknum);
+			continue;
+		}
+
+		pba_to_lba[i] = lba_real;
+		lba_to_pba[lba_offset] = blocknum;
+		continue;
+	}
+
+	MEDIA_INFO(us).lba_to_pba[zone] = lba_to_pba;
+	MEDIA_INFO(us).pba_to_lba[zone] = pba_to_lba;
+	result = 0;
+	goto out;
+
+error:
+	kfree(lba_to_pba);
+	kfree(pba_to_lba);
+out:
+	return result;
+}
+
+/*
+ * Checks to see whether we have already mapped a certain zone
+ * If we haven't, the map is generated
+ */
+static void alauda_ensure_map_for_zone(struct us_data *us, unsigned int zone)
+{
+	if (MEDIA_INFO(us).lba_to_pba[zone] == NULL
+		|| MEDIA_INFO(us).pba_to_lba[zone] == NULL)
+		alauda_read_map(us, zone);
+}
+
+/*
+ * Erases an entire block
+ */
+static int alauda_erase_block(struct us_data *us, u16 pba)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba),
+		PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, MEDIA_PORT(us)
+	};
+	unsigned char buf[2];
+
+	US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba);
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		buf, 2, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n",
+		buf[0], buf[1]);
+	return rc;
+}
+
+/*
+ * Reads data from a certain offset page inside a PBA, including interleaved
+ * redundancy data. Returns (pagesize+64)*pages bytes in data.
+ */
+static int alauda_read_block_raw(struct us_data *us, u16 pba,
+		unsigned int page, unsigned int pages, unsigned char *data)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_READ_BLOCK, PBA_HI(pba),
+		PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)
+	};
+
+	US_DEBUGP("alauda_read_block: pba %d page %d count %d\n",
+		pba, page, pages);
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		data, (MEDIA_INFO(us).pagesize + 64) * pages, NULL);
+}
+
+/*
+ * Reads data from a certain offset page inside a PBA, excluding redundancy
+ * data. Returns pagesize*pages bytes in data. Note that data must be big enough
+ * to hold (pagesize+64)*pages bytes of data, but you can ignore those 'extra'
+ * trailing bytes outside this function.
+ */
+static int alauda_read_block(struct us_data *us, u16 pba,
+		unsigned int page, unsigned int pages, unsigned char *data)
+{
+	int i, rc;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+
+	rc = alauda_read_block_raw(us, pba, page, pages, data);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	/* Cut out the redundancy data */
+	for (i = 0; i < pages; i++) {
+		int dest_offset = i * pagesize;
+		int src_offset = i * (pagesize + 64);
+		memmove(data + dest_offset, data + src_offset, pagesize);
+	}
+
+	return rc;
+}
+
+/*
+ * Writes an entire block of data and checks status after write.
+ * Redundancy data must be already included in data. Data should be
+ * (pagesize+64)*blocksize bytes in length.
+ */
+static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)
+{
+	int rc;
+	struct alauda_info *info = (struct alauda_info *) us->extra;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_BLOCK, PBA_HI(pba),
+		PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)
+	};
+
+	US_DEBUGP("alauda_write_block: pba %d\n", pba);
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	rc = usb_stor_bulk_transfer_buf(us, info->wr_ep, data,
+		(MEDIA_INFO(us).pagesize + 64) * MEDIA_INFO(us).blocksize,
+		NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	return alauda_check_status2(us);
+}
+
+/*
+ * Write some data to a specific LBA.
+ */
+static int alauda_write_lba(struct us_data *us, u16 lba,
+		 unsigned int page, unsigned int pages,
+		 unsigned char *ptr, unsigned char *blockbuffer)
+{
+	u16 pba, lbap, new_pba;
+	unsigned char *bptr, *cptr, *xptr;
+	unsigned char ecc[3];
+	int i, result;
+	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+	unsigned int zonesize = MEDIA_INFO(us).zonesize;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+	unsigned int blocksize = MEDIA_INFO(us).blocksize;
+	unsigned int lba_offset = lba % uzonesize;
+	unsigned int new_pba_offset;
+	unsigned int zone = lba / uzonesize;
+
+	alauda_ensure_map_for_zone(us, zone);
+
+	pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
+	if (pba == 1) {
+		/* Maybe it is impossible to write to PBA 1.
+		   Fake success, but don't do anything. */
+		printk("alauda_write_lba: avoid writing to pba 1\n");
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone);
+	if (!new_pba) {
+		printk("alauda_write_lba: Out of unused blocks\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* read old contents */
+	if (pba != UNDEF) {
+		result = alauda_read_block_raw(us, pba, 0,
+			blocksize, blockbuffer);
+		if (result != USB_STOR_XFER_GOOD)
+			return result;
+	} else {
+		memset(blockbuffer, 0, blocksize * (pagesize + 64));
+	}
+
+	lbap = (lba_offset << 1) | 0x1000;
+	if (parity[MSB_of(lbap) ^ LSB_of(lbap)])
+		lbap ^= 1;
+
+	/* check old contents and fill lba */
+	for (i = 0; i < blocksize; i++) {
+		bptr = blockbuffer + (i * (pagesize + 64));
+		cptr = bptr + pagesize;
+		nand_compute_ecc(bptr, ecc);
+		if (!nand_compare_ecc(cptr+13, ecc)) {
+			US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
+				  i, pba);
+			nand_store_ecc(cptr+13, ecc);
+		}
+		nand_compute_ecc(bptr + (pagesize / 2), ecc);
+		if (!nand_compare_ecc(cptr+8, ecc)) {
+			US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
+				  i, pba);
+			nand_store_ecc(cptr+8, ecc);
+		}
+		cptr[6] = cptr[11] = MSB_of(lbap);
+		cptr[7] = cptr[12] = LSB_of(lbap);
+	}
+
+	/* copy in new stuff and compute ECC */
+	xptr = ptr;
+	for (i = page; i < page+pages; i++) {
+		bptr = blockbuffer + (i * (pagesize + 64));
+		cptr = bptr + pagesize;
+		memcpy(bptr, xptr, pagesize);
+		xptr += pagesize;
+		nand_compute_ecc(bptr, ecc);
+		nand_store_ecc(cptr+13, ecc);
+		nand_compute_ecc(bptr + (pagesize / 2), ecc);
+		nand_store_ecc(cptr+8, ecc);
+	}
+
+	result = alauda_write_block(us, new_pba, blockbuffer);
+	if (result != USB_STOR_XFER_GOOD)
+		return result;
+
+	new_pba_offset = new_pba - (zone * zonesize);
+	MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;
+	MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba;
+	US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n",
+		lba, new_pba);
+
+	if (pba != UNDEF) {
+		unsigned int pba_offset = pba - (zone * zonesize);
+		result = alauda_erase_block(us, pba);
+		if (result != USB_STOR_XFER_GOOD)
+			return result;
+		MEDIA_INFO(us).pba_to_lba[zone][pba_offset] = UNDEF;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Read data from a specific sector address
+ */
+static int alauda_read_data(struct us_data *us, unsigned long address,
+		unsigned int sectors)
+{
+	unsigned char *buffer;
+	u16 lba, max_lba;
+	unsigned int page, len, index, offset;
+	unsigned int blockshift = MEDIA_INFO(us).blockshift;
+	unsigned int pageshift = MEDIA_INFO(us).pageshift;
+	unsigned int blocksize = MEDIA_INFO(us).blocksize;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+	int result;
+
+	/*
+	 * Since we only read in one block at a time, we have to create
+	 * a bounce buffer and move the data a piece at a time between the
+	 * bounce buffer and the actual transfer buffer.
+	 * We make this buffer big enough to hold temporary redundancy data,
+	 * which we use when reading the data blocks.
+	 */
+
+	len = min(sectors, blocksize) * (pagesize + 64);
+	buffer = kmalloc(len, GFP_NOIO);
+	if (buffer == NULL) {
+		printk("alauda_read_data: Out of memory\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* Figure out the initial LBA and page */
+	lba = address >> blockshift;
+	page = (address & MEDIA_INFO(us).blockmask);
+	max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift);
+
+	result = USB_STOR_TRANSPORT_GOOD;
+	index = offset = 0;
+
+	while (sectors > 0) {
+		unsigned int zone = lba / uzonesize; /* integer division */
+		unsigned int lba_offset = lba - (zone * uzonesize);
+		unsigned int pages;
+		u16 pba;
+		alauda_ensure_map_for_zone(us, zone);
+
+		/* Not overflowing capacity? */
+		if (lba >= max_lba) {
+			US_DEBUGP("Error: Requested lba %u exceeds "
+				  "maximum %u\n", lba, max_lba);
+			result = USB_STOR_TRANSPORT_ERROR;
+			break;
+		}
+
+		/* Find number of pages we can read in this block */
+		pages = min(sectors, blocksize - page);
+		len = pages << pageshift;
+
+		/* Find where this lba lives on disk */
+		pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
+
+		if (pba == UNDEF) {	/* this lba was never written */
+			US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
+				  pages, lba, page);
+
+			/* This is not really an error. It just means
+			   that the block has never been written.
+			   Instead of returning USB_STOR_TRANSPORT_ERROR
+			   it is better to return all zero data. */
+
+			memset(buffer, 0, len);
+		} else {
+			US_DEBUGP("Read %d pages, from PBA %d"
+				  " (LBA %d) page %d\n",
+				  pages, pba, lba, page);
+
+			result = alauda_read_block(us, pba, page, pages, buffer);
+			if (result != USB_STOR_TRANSPORT_GOOD)
+				break;
+		}
+
+		/* Store the data in the transfer buffer */
+		usb_stor_access_xfer_buf(buffer, len, us->srb,
+				&index, &offset, TO_XFER_BUF);
+
+		page = 0;
+		lba++;
+		sectors -= pages;
+	}
+
+	kfree(buffer);
+	return result;
+}
+
+/*
+ * Write data to a specific sector address
+ */
+static int alauda_write_data(struct us_data *us, unsigned long address,
+		unsigned int sectors)
+{
+	unsigned char *buffer, *blockbuffer;
+	unsigned int page, len, index, offset;
+	unsigned int blockshift = MEDIA_INFO(us).blockshift;
+	unsigned int pageshift = MEDIA_INFO(us).pageshift;
+	unsigned int blocksize = MEDIA_INFO(us).blocksize;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+	u16 lba, max_lba;
+	int result;
+
+	/*
+	 * Since we don't write the user data directly to the device,
+	 * we have to create a bounce buffer and move the data a piece
+	 * at a time between the bounce buffer and the actual transfer buffer.
+	 */
+
+	len = min(sectors, blocksize) * pagesize;
+	buffer = kmalloc(len, GFP_NOIO);
+	if (buffer == NULL) {
+		printk("alauda_write_data: Out of memory\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/*
+	 * We also need a temporary block buffer, where we read in the old data,
+	 * overwrite parts with the new data, and manipulate the redundancy data
+	 */
+	blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO);
+	if (blockbuffer == NULL) {
+		printk("alauda_write_data: Out of memory\n");
+		kfree(buffer);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* Figure out the initial LBA and page */
+	lba = address >> blockshift;
+	page = (address & MEDIA_INFO(us).blockmask);
+	max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift);
+
+	result = USB_STOR_TRANSPORT_GOOD;
+	index = offset = 0;
+
+	while (sectors > 0) {
+		/* Write as many sectors as possible in this block */
+		unsigned int pages = min(sectors, blocksize - page);
+		len = pages << pageshift;
+
+		/* Not overflowing capacity? */
+		if (lba >= max_lba) {
+			US_DEBUGP("alauda_write_data: Requested lba %u exceeds "
+				  "maximum %u\n", lba, max_lba);
+			result = USB_STOR_TRANSPORT_ERROR;
+			break;
+		}
+
+		/* Get the data from the transfer buffer */
+		usb_stor_access_xfer_buf(buffer, len, us->srb,
+				&index, &offset, FROM_XFER_BUF);
+
+		result = alauda_write_lba(us, lba, page, pages, buffer,
+			blockbuffer);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			break;
+
+		page = 0;
+		lba++;
+		sectors -= pages;
+	}
+
+	kfree(buffer);
+	kfree(blockbuffer);
+	return result;
+}
+
+/*
+ * Our interface with the rest of the world
+ */
+
+static void alauda_info_destructor(void *extra)
+{
+	struct alauda_info *info = (struct alauda_info *) extra;
+	int port;
+
+	if (!info)
+		return;
+
+	for (port = 0; port < 2; port++) {
+		struct alauda_media_info *media_info = &info->port[port];
+
+		alauda_free_maps(media_info);
+		kfree(media_info->lba_to_pba);
+		kfree(media_info->pba_to_lba);
+	}
+}
+
+/*
+ * Initialize alauda_info struct and find the data-write endpoint
+ */
+int init_alauda(struct us_data *us)
+{
+	struct alauda_info *info;
+	struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
+	nand_init_ecc();
+
+	us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
+	if (!us->extra) {
+		US_DEBUGP("init_alauda: Gah! Can't allocate storage for"
+			"alauda info struct!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+	info = (struct alauda_info *) us->extra;
+	us->extra_destructor = alauda_info_destructor;
+
+	info->wr_ep = usb_sndbulkpipe(us->pusb_dev,
+		altsetting->endpoint[0].desc.bEndpointAddress
+		& USB_ENDPOINT_NUMBER_MASK);
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	int rc;
+	struct alauda_info *info = (struct alauda_info *) us->extra;
+	unsigned char *ptr = us->iobuf;
+	static unsigned char inquiry_response[36] = {
+		0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
+	};
+
+	if (srb->cmnd[0] == INQUIRY) {
+		US_DEBUGP("alauda_transport: INQUIRY. "
+			"Returning bogus response.\n");
+		memcpy(ptr, inquiry_response, sizeof(inquiry_response));
+		fill_inquiry_response(us, ptr, 36);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == TEST_UNIT_READY) {
+		US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n");
+		return alauda_check_media(us);
+	}
+
+	if (srb->cmnd[0] == READ_CAPACITY) {
+		unsigned int num_zones;
+		unsigned long capacity;
+
+		rc = alauda_check_media(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift
+			+ MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift);
+
+		capacity = num_zones * MEDIA_INFO(us).uzonesize
+			* MEDIA_INFO(us).blocksize;
+
+		/* Report capacity and page size */
+		((__be32 *) ptr)[0] = cpu_to_be32(capacity - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(512);
+
+		usb_stor_set_xfer_buf(ptr, 8, srb);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == READ_10) {
+		unsigned int page, pages;
+
+		rc = alauda_check_media(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		page = short_pack(srb->cmnd[3], srb->cmnd[2]);
+		page <<= 16;
+		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
+		pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
+
+		US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n",
+			  page, pages);
+
+		return alauda_read_data(us, page, pages);
+	}
+
+	if (srb->cmnd[0] == WRITE_10) {
+		unsigned int page, pages;
+
+		rc = alauda_check_media(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		page = short_pack(srb->cmnd[3], srb->cmnd[2]);
+		page <<= 16;
+		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
+		pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
+
+		US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n",
+			  page, pages);
+
+		return alauda_write_data(us, page, pages);
+	}
+
+	if (srb->cmnd[0] == REQUEST_SENSE) {
+		US_DEBUGP("alauda_transport: REQUEST_SENSE.\n");
+
+		memset(ptr, 0, 18);
+		ptr[0] = 0xF0;
+		ptr[2] = info->sense_key;
+		ptr[7] = 11;
+		ptr[12] = info->sense_asc;
+		ptr[13] = info->sense_ascq;
+		usb_stor_set_xfer_buf(ptr, 18, srb);
+
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
+		/* sure.  whatever.  not like we can stop the user from popping
+		   the media out of the device (no locking doors, etc) */
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n",
+		srb->cmnd[0], srb->cmnd[0]);
+	info->sense_key = 0x05;
+	info->sense_asc = 0x20;
+	info->sense_ascq = 0x00;
+	return USB_STOR_TRANSPORT_FAILED;
+}
+
diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h
new file mode 100644
index 0000000..a700f87
--- /dev/null
+++ b/drivers/usb/storage/alauda.h
@@ -0,0 +1,100 @@
+/*
+ * Driver for Alauda-based card readers
+ *
+ * Current development and maintenance by:
+ *    (c) 2005 Daniel Drake <dsd@gentoo.org>
+ *
+ * See alauda.c for more explanation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _USB_ALAUDA_H
+#define _USB_ALAUDA_H
+
+/*
+ * Status bytes
+ */
+#define ALAUDA_STATUS_ERROR		0x01
+#define ALAUDA_STATUS_READY		0x40
+
+/*
+ * Control opcodes (for request field)
+ */
+#define ALAUDA_GET_XD_MEDIA_STATUS	0x08
+#define ALAUDA_GET_SM_MEDIA_STATUS	0x98
+#define ALAUDA_ACK_XD_MEDIA_CHANGE	0x0a
+#define ALAUDA_ACK_SM_MEDIA_CHANGE	0x9a
+#define ALAUDA_GET_XD_MEDIA_SIG		0x86
+#define ALAUDA_GET_SM_MEDIA_SIG		0x96
+
+/*
+ * Bulk command identity (byte 0)
+ */
+#define ALAUDA_BULK_CMD			0x40
+
+/*
+ * Bulk opcodes (byte 1)
+ */
+#define ALAUDA_BULK_GET_REDU_DATA	0x85
+#define ALAUDA_BULK_READ_BLOCK		0x94
+#define ALAUDA_BULK_ERASE_BLOCK		0xa3
+#define ALAUDA_BULK_WRITE_BLOCK		0xb4
+#define ALAUDA_BULK_GET_STATUS2		0xb7
+#define ALAUDA_BULK_RESET_MEDIA		0xe0
+
+/*
+ * Port to operate on (byte 8)
+ */
+#define ALAUDA_PORT_XD			0x00
+#define ALAUDA_PORT_SM			0x01
+
+/*
+ * LBA and PBA are unsigned ints. Special values.
+ */
+#define UNDEF    0xffff
+#define SPARE    0xfffe
+#define UNUSABLE 0xfffd
+
+int init_alauda(struct us_data *us);
+int alauda_transport(struct scsi_cmnd *srb, struct us_data *us);
+
+struct alauda_media_info {
+	unsigned long capacity;		/* total media size in bytes */
+	unsigned int pagesize;		/* page size in bytes */
+	unsigned int blocksize;		/* number of pages per block */
+	unsigned int uzonesize;		/* number of usable blocks per zone */
+	unsigned int zonesize;		/* number of blocks per zone */
+	unsigned int blockmask;		/* mask to get page from address */
+
+	unsigned char pageshift;
+	unsigned char blockshift;
+	unsigned char zoneshift;
+
+	u16 **lba_to_pba;		/* logical to physical block map */
+	u16 **pba_to_lba;		/* physical to logical block map */
+};
+
+struct alauda_info {
+	struct alauda_media_info port[2];
+	int wr_ep;			/* endpoint to write data out of */
+
+	unsigned char sense_key;
+	unsigned long sense_asc;	/* additional sense code */
+	unsigned long sense_ascq;	/* additional sense code qualifier */
+};
+
+#endif
+
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 5a93217..01e4306 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -132,6 +132,7 @@
 	case 0x5C: what = "READ BUFFER CAPACITY"; break;
 	case 0x5D: what = "SEND CUE SHEET"; break;
 	case GPCMD_BLANK: what = "BLANK"; break;
+	case REPORT_LUNS: what = "REPORT LUNS"; break;
 	case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
 	case READ_12: what = "READ_12"; break;
 	case WRITE_12: what = "WRITE_12"; break;
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 7372386..4c1b2bd 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -45,10 +45,6 @@
  * mode */
 int usb_stor_euscsi_init(struct us_data *us);
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-int sddr09_init(struct us_data *us);
-#endif
-
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
new file mode 100644
index 0000000..b28151d
--- /dev/null
+++ b/drivers/usb/storage/libusual.c
@@ -0,0 +1,266 @@
+/*
+ * libusual
+ *
+ * The libusual contains the table of devices common for ub and usb-storage.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_usual.h>
+#include <linux/vmalloc.h>
+
+/*
+ */
+#define USU_MOD_FL_THREAD   1	/* Thread is running */
+#define USU_MOD_FL_PRESENT  2	/* The module is loaded */
+
+struct mod_status {
+	unsigned long fls;
+};
+
+static struct mod_status stat[3];
+static DEFINE_SPINLOCK(usu_lock);
+
+/*
+ */
+#define USB_US_DEFAULT_BIAS	USB_US_TYPE_STOR
+static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
+
+#define BIAS_NAME_SIZE  (sizeof("usb-storage"))
+static const char *bias_names[3] = { "none", "usb-storage", "ub" };
+
+static DECLARE_MUTEX_LOCKED(usu_init_notify);
+static DECLARE_COMPLETION(usu_end_notify);
+static atomic_t total_threads = ATOMIC_INIT(0);
+
+static int usu_probe_thread(void *arg);
+
+/*
+ * The table.
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName,useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+  .driver_info = ((useType)<<24) }
+
+struct usb_device_id storage_usb_ids [] = {
+#	include "unusual_devs.h"
+	{ } /* Terminating entry */
+};
+
+#undef USUAL_DEV
+#undef UNUSUAL_DEV
+
+MODULE_DEVICE_TABLE(usb, storage_usb_ids);
+EXPORT_SYMBOL_GPL(storage_usb_ids);
+
+/*
+ * @type: the module type as an integer
+ */
+void usb_usual_set_present(int type)
+{
+	struct mod_status *st;
+	unsigned long flags;
+
+	if (type <= 0 || type >= 3)
+		return;
+	st = &stat[type];
+	spin_lock_irqsave(&usu_lock, flags);
+	st->fls |= USU_MOD_FL_PRESENT;
+	spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_usual_set_present);
+
+void usb_usual_clear_present(int type)
+{
+	struct mod_status *st;
+	unsigned long flags;
+
+	if (type <= 0 || type >= 3)
+		return;
+	st = &stat[type];
+	spin_lock_irqsave(&usu_lock, flags);
+	st->fls &= ~USU_MOD_FL_PRESENT;
+	spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_usual_clear_present);
+
+/*
+ * Match the calling driver type against the table.
+ * Returns: 0 if the device matches.
+ */
+int usb_usual_check_type(const struct usb_device_id *id, int caller_type)
+{
+	int id_type = USB_US_TYPE(id->driver_info);
+
+	if (caller_type <= 0 || caller_type >= 3)
+		return -EINVAL;
+
+	/* Drivers grab fixed assignment devices */
+	if (id_type == caller_type)
+		return 0;
+	/* Drivers grab devices biased to them */
+	if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias))
+		return 0;
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usb_usual_check_type);
+
+/*
+ */
+static int usu_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	int type;
+	int rc;
+	unsigned long flags;
+
+	type = USB_US_TYPE(id->driver_info);
+	if (type == 0)
+		type = atomic_read(&usu_bias);
+
+	spin_lock_irqsave(&usu_lock, flags);
+	if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
+		spin_unlock_irqrestore(&usu_lock, flags);
+		return -ENXIO;
+	}
+	stat[type].fls |= USU_MOD_FL_THREAD;
+	spin_unlock_irqrestore(&usu_lock, flags);
+
+	rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
+	if (rc < 0) {
+		printk(KERN_WARNING "libusual: "
+		    "Unable to start the thread for %s: %d\n",
+		    bias_names[type], rc);
+		spin_lock_irqsave(&usu_lock, flags);
+		stat[type].fls &= ~USU_MOD_FL_THREAD;
+		spin_unlock_irqrestore(&usu_lock, flags);
+		return rc;	/* Not being -ENXIO causes a message printed */
+	}
+	atomic_inc(&total_threads);
+
+	return -ENXIO;
+}
+
+static void usu_disconnect(struct usb_interface *intf)
+{
+	;	/* We should not be here. */
+}
+
+static struct usb_driver usu_driver = {
+	.name =		"libusual",
+	.probe =	usu_probe,
+	.disconnect =	usu_disconnect,
+	.id_table =	storage_usb_ids,
+};
+
+/*
+ * A whole new thread for a purpose of request_module seems quite stupid.
+ * The request_module forks once inside again. However, if we attempt
+ * to load a storage module from our own modprobe thread, that module
+ * references our symbols, which cannot be resolved until our module is
+ * initialized. I wish there was a way to wait for the end of initialization.
+ * The module notifier reports MODULE_STATE_COMING only.
+ * So, we wait until module->init ends as the next best thing.
+ */
+static int usu_probe_thread(void *arg)
+{
+	int type = (unsigned long) arg;
+	struct mod_status *st = &stat[type];
+	int rc;
+	unsigned long flags;
+
+	daemonize("libusual_%d", type);	/* "usb-storage" is kinda too long */
+
+	/* A completion does not work here because it's counted. */
+	down(&usu_init_notify);
+	up(&usu_init_notify);
+
+	rc = request_module(bias_names[type]);
+	spin_lock_irqsave(&usu_lock, flags);
+	if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
+		/*
+		 * This should not happen, but let us keep tabs on it.
+		 */
+		printk(KERN_NOTICE "libusual: "
+		    "modprobe for %s succeeded, but module is not present\n",
+		    bias_names[type]);
+	}
+	st->fls &= ~USU_MOD_FL_THREAD;
+	spin_unlock_irqrestore(&usu_lock, flags);
+
+	complete_and_exit(&usu_end_notify, 0);
+}
+
+/*
+ */
+static int __init usb_usual_init(void)
+{
+	int rc;
+
+	rc = usb_register(&usu_driver);
+	up(&usu_init_notify);
+	return rc;
+}
+
+static void __exit usb_usual_exit(void)
+{
+	/*
+	 * We do not check for any drivers present, because
+	 * they keep us pinned with symbol references.
+	 */
+
+	usb_deregister(&usu_driver);
+
+	while (atomic_read(&total_threads) > 0) {
+		wait_for_completion(&usu_end_notify);
+		atomic_dec(&total_threads);
+	}
+}
+
+/*
+ * Validate and accept the bias parameter.
+ */
+static int usu_set_bias(const char *bias_s, struct kernel_param *kp)
+{
+	int i;
+	int len;
+	int bias_n = 0;
+
+	len = strlen(bias_s);
+	if (len == 0)
+		return -EDOM;
+	if (bias_s[len-1] == '\n')
+		--len;
+
+	for (i = 1; i < 3; i++) {
+		if (strncmp(bias_s, bias_names[i], len) == 0) {
+			bias_n = i;
+			break;
+		}
+	}
+	if (bias_n == 0)
+		return -EINVAL;
+
+	atomic_set(&usu_bias, bias_n);
+	return 0;
+}
+
+static int usu_get_bias(char *buffer, struct kernel_param *kp)
+{
+	return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)]));
+}
+
+module_init(usb_usual_init);
+module_exit(usb_usual_exit);
+
+module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR);
+__MODULE_PARM_TYPE(bias, "string");
+MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 89401a5..55ee2d3 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -52,6 +52,7 @@
 	struct urb *irq;	/* urb for interrupt in report */
 	unsigned char *data;	/* input data */
 	dma_addr_t data_dma;
+	unsigned int is_open:1;
 };
 
 static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
@@ -89,6 +90,7 @@
 {
 	struct usb_onetouch *onetouch = dev->private;
 
+	onetouch->is_open = 1;
 	onetouch->irq->dev = onetouch->udev;
 	if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
 		err("usb_submit_urb failed");
@@ -103,8 +105,30 @@
 	struct usb_onetouch *onetouch = dev->private;
 
 	usb_kill_urb(onetouch->irq);
+	onetouch->is_open = 0;
 }
 
+#ifdef CONFIG_PM
+static void usb_onetouch_pm_hook(struct us_data *us, int action)
+{
+	struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra;
+
+	if (onetouch->is_open) {
+		switch (action) {
+		case US_SUSPEND:
+			usb_kill_urb(onetouch->irq);
+			break;
+		case US_RESUME:
+			if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
+				err("usb_submit_urb failed");
+			break;
+		default:
+			break;
+		}
+	}
+}
+#endif /* CONFIG_PM */
+
 int onetouch_connect_input(struct us_data *ss)
 {
 	struct usb_device *udev = ss->pusb_dev;
@@ -185,6 +209,9 @@
 
 	ss->extra_destructor = onetouch_release_input;
 	ss->extra = onetouch;
+#ifdef CONFIG_PM
+	ss->suspend_resume_hook = usb_onetouch_pm_hook;
+#endif
 
 	input_register_device(onetouch->dev);
 
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 02bff01..845bed4 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,20 +41,6 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-/* Sub Classes */
-
-#define US_SC_RBC	0x01		/* Typically, flash devices */
-#define US_SC_8020	0x02		/* CD-ROM */
-#define US_SC_QIC	0x03		/* QIC-157 Tapes */
-#define US_SC_UFI	0x04		/* Floppy */
-#define US_SC_8070	0x05		/* Removable media */
-#define US_SC_SCSI	0x06		/* Transparent */
-#define US_SC_ISD200    0x07		/* ISD200 ATA */
-#define US_SC_MIN	US_SC_RBC
-#define US_SC_MAX	US_SC_ISD200
-
-#define US_SC_DEVICE	0xff		/* Use device's value */
-
 /* Protocol handling routines */
 extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
 extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 0ea2f5a..fb8baca 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -133,13 +133,11 @@
 	{ 0,}
 };
 
-#define SIZE(a)	(sizeof(a)/sizeof((a)[0]))
-
 static struct nand_flash_dev *
 nand_find_id(unsigned char id) {
 	int i;
 
-	for (i = 0; i < SIZE(nand_flash_ids); i++)
+	for (i = 0; i < ARRAY_SIZE(nand_flash_ids); i++)
 		if (nand_flash_ids[i].model_id == id)
 			return &(nand_flash_ids[i]);
 	return NULL;
@@ -214,6 +212,20 @@
  * The actual driver starts here.
  */
 
+struct sddr09_card_info {
+	unsigned long	capacity;	/* Size of card in bytes */
+	int		pagesize;	/* Size of page in bytes */
+	int		pageshift;	/* log2 of pagesize */
+	int		blocksize;	/* Size of block in pages */
+	int		blockshift;	/* log2 of blocksize */
+	int		blockmask;	/* 2^blockshift - 1 */
+	int		*lba_to_pba;	/* logical to physical map */
+	int		*pba_to_lba;	/* physical to logical map */
+	int		lbact;		/* number of available pages */
+	int		flags;
+#define	SDDR09_WP	1		/* write protected */
+};
+
 /*
  * On my 16MB card, control blocks have size 64 (16 real control bytes,
  * and 48 junk bytes). In reality of course the card uses 16 control bytes,
@@ -237,7 +249,7 @@
 #define SPARE    0xfffffffe
 #define UNUSABLE 0xfffffffd
 
-static int erase_bad_lba_entries = 0;
+static const int erase_bad_lba_entries = 0;
 
 /* send vendor interface command (0x41) */
 /* called for requests 0, 1, 8 */
@@ -260,8 +272,11 @@
 
 	rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype,
 				   0, 0, xfer_data, xfer_len);
-	return (rc == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD :
-			USB_STOR_TRANSPORT_ERROR);
+	switch (rc) {
+		case USB_STOR_XFER_GOOD:	return 0;
+		case USB_STOR_XFER_STALLED:	return -EPIPE;
+		default:			return -EIO;
+	}
 }
 
 static int
@@ -308,20 +323,12 @@
 	command[4] = buflen;
 
 	result = sddr09_send_scsi_command(us, command, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
-		US_DEBUGP("request sense failed\n");
+	if (result)
 		return result;
-	}
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 			sensebuf, buflen, NULL);
-	if (result != USB_STOR_XFER_GOOD) {
-		US_DEBUGP("request sense bulk in failed\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	} else {
-		US_DEBUGP("request sense worked\n");
-		return USB_STOR_TRANSPORT_GOOD;
-	}
+	return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
 }
 
 /*
@@ -369,7 +376,7 @@
 
 	result = sddr09_send_scsi_command(us, command, 12);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
 			  x, result);
 		return result;
@@ -381,9 +388,9 @@
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
 			  x, result);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -EIO;
 	}
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 
 /*
@@ -497,7 +504,7 @@
 
 	result = sddr09_send_scsi_command(us, command, 12);
 
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		US_DEBUGP("Result for send_control in sddr09_erase %d\n",
 			  result);
 
@@ -555,7 +562,7 @@
 
 	result = sddr09_send_scsi_command(us, command, 12);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
 			  result);
 		return result;
@@ -567,9 +574,9 @@
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
 			  result);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -EIO;
 	}
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 
 /* erase address, write same address */
@@ -633,7 +640,7 @@
 
 	result = sddr09_send_scsi_command(us, command, 4*nsg+3);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",
 			  result);
 		return result;
@@ -641,7 +648,7 @@
 
 	buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
 	if (!buf)
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 				       buf, bulklen, NULL);
@@ -649,10 +656,10 @@
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
 			  result);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -EIO;
 	}
 
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 #endif
 
@@ -681,14 +688,13 @@
 	command[1] = LUNBITS;
 
 	result = sddr09_send_scsi_command(us, command, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		return result;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 				       data, 64, NULL);
 	*status = data[0];
-	return (result == USB_STOR_XFER_GOOD ?
-			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+	return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
 }
 
 static int
@@ -703,6 +709,13 @@
 	unsigned int len, index, offset;
 	int result;
 
+	// Figure out the initial LBA and page
+	lba = address >> info->blockshift;
+	page = (address & info->blockmask);
+	maxlba = info->capacity >> (info->pageshift + info->blockshift);
+	if (lba >= maxlba)
+		return -EIO;
+
 	// Since we only read in one block at a time, we have to create
 	// a bounce buffer and move the data a piece at a time between the
 	// bounce buffer and the actual transfer buffer.
@@ -711,18 +724,13 @@
 	buffer = kmalloc(len, GFP_NOIO);
 	if (buffer == NULL) {
 		printk("sddr09_read_data: Out of memory\n");
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 	}
 
-	// Figure out the initial LBA and page
-	lba = address >> info->blockshift;
-	page = (address & info->blockmask);
-	maxlba = info->capacity >> (info->pageshift + info->blockshift);
-
 	// This could be made much more efficient by checking for
 	// contiguous LBA's. Another exercise left to the student.
 
-	result = USB_STOR_TRANSPORT_GOOD;
+	result = 0;
 	index = offset = 0;
 
 	while (sectors > 0) {
@@ -735,7 +743,7 @@
 		if (lba >= maxlba) {
 			US_DEBUGP("Error: Requested lba %u exceeds "
 				  "maximum %u\n", lba, maxlba);
-			result = USB_STOR_TRANSPORT_ERROR;
+			result = -EIO;
 			break;
 		}
 
@@ -749,7 +757,7 @@
 
 			/* This is not really an error. It just means
 			   that the block has never been written.
-			   Instead of returning USB_STOR_TRANSPORT_ERROR
+			   Instead of returning an error
 			   it is better to return all zero data. */
 
 			memset(buffer, 0, len);
@@ -764,7 +772,7 @@
 
 			result = sddr09_read20(us, address>>1,
 					pages, info->pageshift, buffer, 0);
-			if (result != USB_STOR_TRANSPORT_GOOD)
+			if (result)
 				break;
 		}
 
@@ -830,7 +838,7 @@
 		pba = sddr09_find_unused_pba(info, lba);
 		if (!pba) {
 			printk("sddr09_write_lba: Out of unused blocks\n");
-			return USB_STOR_TRANSPORT_ERROR;
+			return -ENOSPC;
 		}
 		info->pba_to_lba[pba] = lba;
 		info->lba_to_pba[lba] = pba;
@@ -841,7 +849,7 @@
 		/* Maybe it is impossible to write to PBA 1.
 		   Fake success, but don't do anything. */
 		printk("sddr09: avoid writing to pba 1\n");
-		return USB_STOR_TRANSPORT_GOOD;
+		return 0;
 	}
 
 	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
@@ -850,7 +858,7 @@
 	address = (pba << (info->pageshift + info->blockshift));
 	result = sddr09_read22(us, address>>1, info->blocksize,
 			       info->pageshift, blockbuffer, 0);
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		return result;
 
 	/* check old contents and fill lba */
@@ -897,7 +905,7 @@
 	{
 		unsigned char status = 0;
 		int result2 = sddr09_read_status(us, &status);
-		if (result2 != USB_STOR_TRANSPORT_GOOD)
+		if (result2)
 			US_DEBUGP("sddr09_write_inplace: cannot read status\n");
 		else if (status != 0xc0)
 			US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",
@@ -920,13 +928,20 @@
 		  unsigned int sectors) {
 
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
-	unsigned int lba, page, pages;
+	unsigned int lba, maxlba, page, pages;
 	unsigned int pagelen, blocklen;
 	unsigned char *blockbuffer;
 	unsigned char *buffer;
 	unsigned int len, index, offset;
 	int result;
 
+	// Figure out the initial LBA and page
+	lba = address >> info->blockshift;
+	page = (address & info->blockmask);
+	maxlba = info->capacity >> (info->pageshift + info->blockshift);
+	if (lba >= maxlba)
+		return -EIO;
+
 	// blockbuffer is used for reading in the old data, overwriting
 	// with the new data, and performing ECC calculations
 
@@ -938,7 +953,7 @@
 	blockbuffer = kmalloc(blocklen, GFP_NOIO);
 	if (!blockbuffer) {
 		printk("sddr09_write_data: Out of memory\n");
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 	}
 
 	// Since we don't write the user data directly to the device,
@@ -950,14 +965,10 @@
 	if (buffer == NULL) {
 		printk("sddr09_write_data: Out of memory\n");
 		kfree(blockbuffer);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 	}
 
-	// Figure out the initial LBA and page
-	lba = address >> info->blockshift;
-	page = (address & info->blockmask);
-
-	result = USB_STOR_TRANSPORT_GOOD;
+	result = 0;
 	index = offset = 0;
 
 	while (sectors > 0) {
@@ -967,13 +978,21 @@
 		pages = min(sectors, info->blocksize - page);
 		len = (pages << info->pageshift);
 
+		/* Not overflowing capacity? */
+		if (lba >= maxlba) {
+			US_DEBUGP("Error: Requested lba %u exceeds "
+				  "maximum %u\n", lba, maxlba);
+			result = -EIO;
+			break;
+		}
+
 		// Get the data from the transfer buffer
 		usb_stor_access_xfer_buf(buffer, len, us->srb,
 				&index, &offset, FROM_XFER_BUF);
 
 		result = sddr09_write_lba(us, lba, page, pages,
 				buffer, blockbuffer);
-		if (result != USB_STOR_TRANSPORT_GOOD)
+		if (result)
 			break;
 
 		page = 0;
@@ -1022,7 +1041,7 @@
 	command[1] = LUNBITS;
 
 	result = sddr09_send_scsi_command(us, command, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		return result;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
@@ -1031,8 +1050,7 @@
 	for (i = 0; i < 4; i++)
 		deviceID[i] = content[i];
 
-	return (result == USB_STOR_XFER_GOOD ?
-			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+	return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
 }
 
 static int
@@ -1041,7 +1059,7 @@
 	unsigned char status;
 
 	result = sddr09_read_status(us, &status);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_get_wp: read_status fails\n");
 		return result;
 	}
@@ -1057,7 +1075,7 @@
 	if (status & 0x1)
 		US_DEBUGP(" Error");
 	US_DEBUGP("\n");
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 
 #if 0
@@ -1089,7 +1107,7 @@
 
 	result = sddr09_read_deviceID(us, deviceID);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result of read_deviceID is %d\n", result);
 		printk("sddr09: could not read card info\n");
 		return NULL;
@@ -1200,7 +1218,7 @@
 				us, address>>1,
 				min(alloc_blocks, numblocks - i),
 				buffer, 0);
-			if (result != USB_STOR_TRANSPORT_GOOD) {
+			if (result) {
 				result = -1;
 				goto done;
 			}
@@ -1342,29 +1360,53 @@
 	kfree(info->pba_to_lba);
 }
 
-static void
-sddr09_init_card_info(struct us_data *us) {
-	if (!us->extra) {
-		us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO);
-		if (us->extra) {
-			memset(us->extra, 0, sizeof(struct sddr09_card_info));
-			us->extra_destructor = sddr09_card_info_destructor;
-		}
+static int
+sddr09_common_init(struct us_data *us) {
+	int result;
+
+	/* set the configuration -- STALL is an acceptable response here */
+	if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
+		US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
+				->actconfig->desc.bConfigurationValue);
+		return -EINVAL;
 	}
+
+	result = usb_reset_configuration(us->pusb_dev);
+	US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
+	if (result == -EPIPE) {
+		US_DEBUGP("-- stall on control interface\n");
+	} else if (result != 0) {
+		/* it's not a stall, but another error -- time to bail */
+		US_DEBUGP("-- Unknown error.  Rejecting device\n");
+		return -EINVAL;
+	}
+
+	us->extra = kzalloc(sizeof(struct sddr09_card_info), GFP_NOIO);
+	if (!us->extra)
+		return -ENOMEM;
+	us->extra_destructor = sddr09_card_info_destructor;
+
+	nand_init_ecc();
+	return 0;
 }
 
+
 /*
  * This is needed at a very early stage. If this is not listed in the
  * unusual devices list but called from here then LUN 0 of the combo reader
  * is not recognized. But I do not know what precisely these calls do.
  */
 int
-sddr09_init(struct us_data *us) {
+usb_stor_sddr09_dpcm_init(struct us_data *us) {
 	int result;
 	unsigned char *data = us->iobuf;
 
+	result = sddr09_common_init(us);
+	if (result)
+		return result;
+
 	result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_init: send_command fails\n");
 		return result;
 	}
@@ -1373,7 +1415,7 @@
 	// get 07 02
 
 	result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_init: 2nd send_command fails\n");
 		return result;
 	}
@@ -1382,7 +1424,7 @@
 	// get 07 00
 
 	result = sddr09_request_sense(us, data, 18);
-	if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {
+	if (result == 0 && data[2] != 0) {
 		int j;
 		for (j=0; j<18; j++)
 			printk(" %02X", data[j]);
@@ -1398,7 +1440,7 @@
 
 	// test unit ready
 
-	return USB_STOR_TRANSPORT_GOOD;		/* not result */
+	return 0;		/* not result */
 }
 
 /*
@@ -1427,13 +1469,6 @@
 	};
 
 	info = (struct sddr09_card_info *)us->extra;
-	if (!info) {
-		nand_init_ecc();
-		sddr09_init_card_info(us);
-		info = (struct sddr09_card_info *)us->extra;
-		if (!info)
-			return USB_STOR_TRANSPORT_ERROR;
-	}
 
 	if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) {
 		/* for a faked command, we have to follow with a faked sense */
@@ -1536,7 +1571,9 @@
 		US_DEBUGP("READ_10: read page %d pagect %d\n",
 			  page, pages);
 
-		return sddr09_read_data(us, page, pages);
+		result = sddr09_read_data(us, page, pages);
+		return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
+				USB_STOR_TRANSPORT_ERROR);
 	}
 
 	if (srb->cmnd[0] == WRITE_10) {
@@ -1549,7 +1586,9 @@
 		US_DEBUGP("WRITE_10: write page %d pagect %d\n",
 			  page, pages);
 
-		return sddr09_write_data(us, page, pages);
+		result = sddr09_write_data(us, page, pages);
+		return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
+				USB_STOR_TRANSPORT_ERROR);
 	}
 
 	/* catch-all for all other commands, except
@@ -1575,10 +1614,10 @@
 	US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
 
 	result = sddr09_send_scsi_command(us, srb->cmnd, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "
 			  "returns %d\n", result);
-		return result;
+		return USB_STOR_TRANSPORT_ERROR;
 	}
 
 	if (srb->request_bufflen == 0)
@@ -1606,3 +1645,10 @@
 	return USB_STOR_TRANSPORT_GOOD;
 }
 
+/*
+ * Initialization routine for the sddr09 subdriver
+ */
+int
+usb_stor_sddr09_init(struct us_data *us) {
+	return sddr09_common_init(us);
+}
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index c9d78d6..c03089a 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -31,18 +31,7 @@
 
 extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
 
-struct sddr09_card_info {
-	unsigned long	capacity;	/* Size of card in bytes */
-	int		pagesize;	/* Size of page in bytes */
-	int		pageshift;	/* log2 of pagesize */
-	int		blocksize;	/* Size of block in pages */
-	int		blockshift;	/* log2 of blocksize */
-	int		blockmask;	/* 2^blockshift - 1 */
-	int		*lba_to_pba;	/* logical to physical map */
-	int		*pba_to_lba;	/* physical to logical map */
-	int		lbact;		/* number of available pages */
-	int		flags;
-#define	SDDR09_WP	1		/* write protected */
-};
+extern int usb_stor_sddr09_dpcm_init(struct us_data *us);
+extern int usb_stor_sddr09_init(struct us_data *us);
 
 #endif
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 0a362cc..633a7158 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -41,39 +41,8 @@
 #ifndef _TRANSPORT_H_
 #define _TRANSPORT_H_
 
-#include <linux/config.h>
 #include <linux/blkdev.h>
 
-/* Protocols */
-
-#define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
-#define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
-#define US_PR_BULK	0x50		/* bulk only */
-#ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-#define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
-#endif
-#define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#define US_PR_FREECOM   0xf1		/* Freecom */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
-#endif
-
-#define US_PR_DEVICE	0xff		/* Use device's value */
-
 /*
  * Bulk only data structures
  */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f5f47a3..dc301e5 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -79,13 +79,6 @@
 		US_SC_8070, US_PR_USBAT, init_usbat, 0),
 #endif
 
-/* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
-UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
-		"VIA Technologies Inc.",
-		"USB 2.0 Card Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_IGNORE_RESIDUE ),
-
 /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
  * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
  * for USB floppies that need the SINGLE_LUN enforcement.
@@ -96,6 +89,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
+/* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
+UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
+		"VIA Technologies Inc.",
+		"USB 2.0 Card Reader",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
  * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
  * always fails and confuses drive.
@@ -187,6 +187,14 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
+/* Patch for Nikon coolpix 2000
+ * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/
+UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
+		"NIKON",
+		"NIKON DSC E2000",
+		US_SC_DEVICE, US_PR_DEVICE,NULL,
+		US_FL_NOT_LOCKABLE ),
+
 /* BENQ DC5330
  * Reported by Manuel Fombuena <mfombuena@ya.com> and
  * Frank Copeland <fjc@thingy.apana.org.au> */
@@ -276,14 +284,14 @@
 UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999, 
 		"Sandisk",
 		"ImageMate SDDR09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN ),
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
 
 /* This entry is from Andries.Brouwer@cwi.nl */
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB SmartMedia / CompactFlash Adapter",
-		US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, 
+		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
 		0), 
 #endif
 
@@ -527,6 +535,13 @@
 		"Silicon Media R/W",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
+		"Fujifilm",
+		"DPC-R1 (Alauda)",
+ 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+#endif
+
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
@@ -673,8 +688,8 @@
 UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100, 
 		"Olympus",
 		"Camedia MAUSB-2",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN ),
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
 #endif
 
 /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
@@ -739,8 +754,8 @@
 UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999, 
 		"Sandisk",
 		"ImageMate SDDR-09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN ),
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
 #endif
 
 #ifdef CONFIG_USB_STORAGE_FREECOM
@@ -776,6 +791,13 @@
  		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
 #endif
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
+		"Olympus",
+		"MAUSB-10 (Alauda)",
+ 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+#endif
+
 #ifdef CONFIG_USB_STORAGE_DATAFAB
 UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
 		"Datafab",
@@ -1134,3 +1156,27 @@
 		US_SC_SCSI, US_PR_SDDR55, NULL,
 		US_FL_SINGLE_LUN),
 #endif
+
+/* Control/Bulk transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
+
+/* Control/Bulk/Interrupt transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
+
+/* Bulk-only transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 3847ebe..dbcf239 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -94,6 +94,9 @@
 #ifdef CONFIG_USB_STORAGE_ONETOUCH
 #include "onetouch.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+#include "alauda.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -112,49 +115,33 @@
 static DECLARE_COMPLETION(threads_gone);
 
 
-/* The entries in this table, except for final ones here
- * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
- * line for line with the entries of us_unsuaul_dev_list[].
+/*
+ * The entries in this table correspond, line for line,
+ * with the entries of us_unusual_dev_list[].
  */
+#ifndef CONFIG_USB_LIBUSUAL
 
 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
 		    vendorName, productName,useProtocol, useTransport, \
 		    initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+  .driver_info = (USB_US_TYPE_STOR<<24) }
 
 static struct usb_device_id storage_usb_ids [] = {
 
 #	include "unusual_devs.h"
 #undef UNUSUAL_DEV
-	/* Control/Bulk transport for all SubClass values */
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
-
-	/* Control/Bulk/Interrupt transport for all SubClass values */
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
-
-	/* Bulk-only transport for all SubClass values */
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-
+#undef USUAL_DEV
 	/* Terminating entry */
 	{ }
 };
 
 MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */
 
 /* This is the list of devices we recognize, along with their flag data */
 
@@ -167,7 +154,6 @@
  * are free to use as many characters as you like.
  */
 
-#undef UNUSUAL_DEV
 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
 		    vendor_name, product_name, use_protocol, use_transport, \
 		    init_function, Flags) \
@@ -177,53 +163,18 @@
 	.useProtocol = use_protocol,	\
 	.useTransport = use_transport,	\
 	.initFunction = init_function,	\
-	.flags = Flags, \
+}
+
+#define USUAL_DEV(use_protocol, use_transport, use_type) \
+{ \
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
 }
 
 static struct us_unusual_dev us_unusual_dev_list[] = {
 #	include "unusual_devs.h" 
 #	undef UNUSUAL_DEV
-	/* Control/Bulk transport for all SubClass values */
-	{ .useProtocol = US_SC_RBC,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_8020,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_QIC,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_UFI,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_8070,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_SCSI,
-	  .useTransport = US_PR_CB},
-
-	/* Control/Bulk/Interrupt transport for all SubClass values */
-	{ .useProtocol = US_SC_RBC,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_8020,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_QIC,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_UFI,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_8070,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_SCSI,
-	  .useTransport = US_PR_CBI},
-
-	/* Bulk-only transport for all SubClass values */
-	{ .useProtocol = US_SC_RBC,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_8020,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_QIC,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_UFI,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_8070,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_SCSI,
-	  .useTransport = US_PR_BULK},
+#	undef USUAL_DEV
 
 	/* Terminating entry */
 	{ NULL }
@@ -240,6 +191,8 @@
 	down(&us->dev_semaphore);
 
 	US_DEBUGP("%s\n", __FUNCTION__);
+	if (us->suspend_resume_hook)
+		(us->suspend_resume_hook)(us, US_SUSPEND);
 	iface->dev.power.power_state.event = message.event;
 
 	/* When runtime PM is working, we'll set a flag to indicate
@@ -256,6 +209,8 @@
 	down(&us->dev_semaphore);
 
 	US_DEBUGP("%s\n", __FUNCTION__);
+	if (us->suspend_resume_hook)
+		(us->suspend_resume_hook)(us, US_RESUME);
 	iface->dev.power.power_state.event = PM_EVENT_ON;
 
 	up(&us->dev_semaphore);
@@ -484,14 +439,20 @@
 	return 0;
 }
 
+/* Find an unusual_dev descriptor (always succeeds in the current code) */
+static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
+{
+	const int id_index = id - storage_usb_ids;
+	return &us_unusual_dev_list[id_index];
+}
+
 /* Get the unusual_devs entries and the string descriptors */
-static void get_device_info(struct us_data *us, int id_index)
+static void get_device_info(struct us_data *us, const struct usb_device_id *id)
 {
 	struct usb_device *dev = us->pusb_dev;
 	struct usb_interface_descriptor *idesc =
 		&us->pusb_intf->cur_altsetting->desc;
-	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
-	struct usb_device_id *id = &storage_usb_ids[id_index];
+	struct us_unusual_dev *unusual_dev = find_unusual(id);
 
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
@@ -501,7 +462,7 @@
 	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
 			idesc->bInterfaceProtocol :
 			unusual_dev->useTransport;
-	us->flags = unusual_dev->flags;
+	us->flags = USB_US_ORIG_FLAGS(id->driver_info);
 
 	/*
 	 * This flag is only needed when we're in high-speed, so let's
@@ -516,7 +477,7 @@
 	 * from the unusual_devs.h table.
 	 */
 	if (id->idVendor || id->idProduct) {
-		static char *msgs[3] = {
+		static const char *msgs[3] = {
 			"an unneeded SubClass entry",
 			"an unneeded Protocol entry",
 			"unneeded SubClass and Protocol entries"};
@@ -529,7 +490,7 @@
 		if (unusual_dev->useTransport != US_PR_DEVICE &&
 			us->protocol == idesc->bInterfaceProtocol)
 			msg += 2;
-		if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE))
+		if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
 			printk(KERN_NOTICE USB_STORAGE "This device "
 				"(%04x,%04x,%04x S %02x P %02x)"
 				" has %s in unusual_devs.h\n"
@@ -686,6 +647,15 @@
 		break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+	case US_PR_ALAUDA:
+		us->transport_name  = "Alauda Control/Bulk";
+		us->transport = alauda_transport;
+		us->transport_reset = usb_stor_Bulk_reset;
+		us->max_lun = 1;
+		break;
+#endif
+
 	default:
 		return -EIO;
 	}
@@ -921,10 +891,12 @@
 {
 	struct Scsi_Host *host;
 	struct us_data *us;
-	const int id_index = id - storage_usb_ids; 
 	int result;
 	struct task_struct *th;
 
+	if (usb_usual_check_type(id, USB_US_TYPE_STOR))
+		return -ENXIO;
+
 	US_DEBUGP("USB Mass Storage device detected\n");
 
 	/*
@@ -957,29 +929,7 @@
 	 * of the match from the usb_device_id table, so we can find the
 	 * corresponding entry in the private table.
 	 */
-	get_device_info(us, id_index);
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	if (us->protocol == US_PR_EUSB_SDDR09 ||
-			us->protocol == US_PR_DPCM_USB) {
-		/* set the configuration -- STALL is an acceptable response here */
-		if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
-			US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
-				->actconfig->desc.bConfigurationValue);
-			goto BadDevice;
-		}
-		result = usb_reset_configuration(us->pusb_dev);
-
-		US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
-		if (result == -EPIPE) {
-			US_DEBUGP("-- stall on control interface\n");
-		} else if (result != 0) {
-			/* it's not a stall, but another error -- time to bail */
-			US_DEBUGP("-- Unknown error.  Rejecting device\n");
-			goto BadDevice;
-		}
-	}
-#endif
+	get_device_info(us, id);
 
 	/* Get the transport, protocol, and pipe settings */
 	result = get_transport(us);
@@ -1044,7 +994,6 @@
  ***********************************************************************/
 
 static struct usb_driver usb_storage_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usb-storage",
 	.probe =	storage_probe,
 	.disconnect =	storage_disconnect,
@@ -1062,9 +1011,10 @@
 
 	/* register the driver, return usb_register return code if error */
 	retval = usb_register(&usb_storage_driver);
-	if (retval == 0)
+	if (retval == 0) {
 		printk(KERN_INFO "USB Mass Storage support registered.\n");
-
+		usb_usual_set_present(USB_US_TYPE_STOR);
+	}
 	return retval;
 }
 
@@ -1088,6 +1038,8 @@
 		wait_for_completion(&threads_gone);
 		atomic_dec(&total_threads);
 	}
+
+	usb_usual_clear_present(USB_US_TYPE_STOR);
 }
 
 module_init(usb_stor_init);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 98b0971..7259fd1 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -45,6 +45,7 @@
 #define _USB_H_
 
 #include <linux/usb.h>
+#include <linux/usb_usual.h>
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
@@ -63,38 +64,8 @@
 	__u8  useProtocol;
 	__u8  useTransport;
 	int (*initFunction)(struct us_data *);
-	unsigned int flags;
 };
 
-/*
- * Static flag definitions.  We use this roundabout technique so that the
- * proc_info() routine can automatically display a message for each flag.
- */
-#define US_DO_ALL_FLAGS						\
-	US_FLAG(SINGLE_LUN,	0x00000001)			\
-		/* allow access to only LUN 0 */		\
-	US_FLAG(NEED_OVERRIDE,	0x00000002)			\
-		/* unusual_devs entry is necessary */		\
-	US_FLAG(SCM_MULT_TARG,	0x00000004)			\
-		/* supports multiple targets */			\
-	US_FLAG(FIX_INQUIRY,	0x00000008)			\
-		/* INQUIRY response needs faking */		\
-	US_FLAG(FIX_CAPACITY,	0x00000010)			\
-		/* READ CAPACITY response too big */		\
-	US_FLAG(IGNORE_RESIDUE,	0x00000020)			\
-		/* reported residue is wrong */			\
-	US_FLAG(BULK32,		0x00000040)			\
-		/* Uses 32-byte CBW length */			\
-	US_FLAG(NOT_LOCKABLE,	0x00000080)			\
-		/* PREVENT/ALLOW not supported */		\
-	US_FLAG(GO_SLOW,	0x00000100)			\
-		/* Need delay after Command phase */		\
-	US_FLAG(NO_WP_DETECT,	0x00000200)			\
-		/* Don't check for write-protect */		\
-
-#define US_FLAG(name, value)	US_FL_##name = value ,
-enum { US_DO_ALL_FLAGS };
-#undef US_FLAG
 
 /* Dynamic flag definitions: used in set_bit() etc. */
 #define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */
@@ -122,7 +93,11 @@
 typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
 typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
-typedef void (*extra_data_destructor)(void *);	 /* extra data destructor   */
+typedef void (*extra_data_destructor)(void *);	/* extra data destructor */
+typedef void (*pm_hook)(struct us_data *, int);	/* power management hook */
+
+#define US_SUSPEND	0
+#define US_RESUME	1
 
 /* we allocate one of these for every device that we remember */
 struct us_data {
@@ -178,6 +153,9 @@
 	/* subdriver information */
 	void			*extra;		 /* Any extra data          */
 	extra_data_destructor	extra_destructor;/* extra data destructor   */
+#ifdef CONFIG_PM
+	pm_hook			suspend_resume_hook;
+#endif
 };
 
 /* Convert between us_data and the corresponding Scsi_Host */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 6c3a53f..5d02f16 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -39,10 +39,15 @@
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE	192
 
+/* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER		( PAGE_SIZE - 512 )
+#define WRITES_IN_FLIGHT	8
+
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
 	struct usb_device *	udev;			/* the usb device for this device */
 	struct usb_interface *	interface;		/* the interface for this device */
+	struct semaphore	limit_sem;		/* limiting the number of writes in progress */
 	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
@@ -152,6 +157,7 @@
 	/* free up our allocated buffer */
 	usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
 			urb->transfer_buffer, urb->transfer_dma);
+	up(&dev->limit_sem);
 }
 
 static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
@@ -160,6 +166,7 @@
 	int retval = 0;
 	struct urb *urb = NULL;
 	char *buf = NULL;
+	size_t writesize = min(count, (size_t)MAX_TRANSFER);
 
 	dev = (struct usb_skel *)file->private_data;
 
@@ -167,6 +174,12 @@
 	if (count == 0)
 		goto exit;
 
+	/* limit the number of URBs in flight to stop a user from using up all RAM */
+	if (down_interruptible(&dev->limit_sem)) {
+		retval = -ERESTARTSYS;
+		goto exit;
+	}
+
 	/* create a urb, and a buffer for it, and copy the data to the urb */
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
@@ -174,13 +187,13 @@
 		goto error;
 	}
 
-	buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+	buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
 	if (!buf) {
 		retval = -ENOMEM;
 		goto error;
 	}
 
-	if (copy_from_user(buf, user_buffer, count)) {
+	if (copy_from_user(buf, user_buffer, writesize)) {
 		retval = -EFAULT;
 		goto error;
 	}
@@ -188,7 +201,7 @@
 	/* initialize the urb properly */
 	usb_fill_bulk_urb(urb, dev->udev,
 			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
-			  buf, count, skel_write_bulk_callback, dev);
+			  buf, writesize, skel_write_bulk_callback, dev);
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* send the data out the bulk port */
@@ -202,11 +215,12 @@
 	usb_free_urb(urb);
 
 exit:
-	return count;
+	return writesize;
 
 error:
-	usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+	usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
 	usb_free_urb(urb);
+	up(&dev->limit_sem);
 	return retval;
 }
 
@@ -238,13 +252,13 @@
 	int retval = -ENOMEM;
 
 	/* allocate memory for our device state and initialize it */
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		err("Out of memory");
 		goto error;
 	}
-	memset(dev, 0x00, sizeof(*dev));
 	kref_init(&dev->kref);
+	sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
@@ -330,7 +344,6 @@
 }
 
 static struct usb_driver skel_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"skeleton",
 	.probe =	skel_probe,
 	.disconnect =	skel_disconnect,
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index 15fb250..b914630 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -52,7 +52,6 @@
 
 
 static struct usb_driver ds_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"DS9490R",
 	.probe =	ds_probe,
 	.disconnect =	ds_disconnect,
diff --git a/fs/compat.c b/fs/compat.c
index 8186341..55ac032 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1170,7 +1170,7 @@
 	}
 
 	ret = rw_verify_area(type, file, pos, tot_len);
-	if (ret)
+	if (ret < 0)
 		goto out;
 
 	fnv = NULL;
diff --git a/fs/read_write.c b/fs/read_write.c
index a091ee4..df3468a 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -14,6 +14,7 @@
 #include <linux/security.h>
 #include <linux/module.h>
 #include <linux/syscalls.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -182,22 +183,33 @@
 }
 #endif
 
+/*
+ * rw_verify_area doesn't like huge counts. We limit
+ * them to something that fits in "int" so that others
+ * won't have to do range checks all the time.
+ */
+#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
 
 int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count)
 {
 	struct inode *inode;
 	loff_t pos;
 
-	if (unlikely(count > INT_MAX))
+	if (unlikely((ssize_t) count < 0))
 		goto Einval;
 	pos = *ppos;
 	if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
 		goto Einval;
 
 	inode = file->f_dentry->d_inode;
-	if (inode->i_flock && MANDATORY_LOCK(inode))
-		return locks_mandatory_area(read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, inode, file, pos, count);
-	return 0;
+	if (inode->i_flock && MANDATORY_LOCK(inode)) {
+		int retval = locks_mandatory_area(
+			read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
+			inode, file, pos, count);
+		if (retval < 0)
+			return retval;
+	}
+	return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
 
 Einval:
 	return -EINVAL;
@@ -244,7 +256,8 @@
 		return -EFAULT;
 
 	ret = rw_verify_area(READ, file, pos, count);
-	if (!ret) {
+	if (ret >= 0) {
+		count = ret;
 		ret = security_file_permission (file, MAY_READ);
 		if (!ret) {
 			if (file->f_op->read)
@@ -295,7 +308,8 @@
 		return -EFAULT;
 
 	ret = rw_verify_area(WRITE, file, pos, count);
-	if (!ret) {
+	if (ret >= 0) {
+		count = ret;
 		ret = security_file_permission (file, MAY_WRITE);
 		if (!ret) {
 			if (file->f_op->write)
@@ -497,7 +511,7 @@
 	}
 
 	ret = rw_verify_area(type, file, pos, tot_len);
-	if (ret)
+	if (ret < 0)
 		goto out;
 	ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE);
 	if (ret)
@@ -653,8 +667,9 @@
 		if (!(in_file->f_mode & FMODE_PREAD))
 			goto fput_in;
 	retval = rw_verify_area(READ, in_file, ppos, count);
-	if (retval)
+	if (retval < 0)
 		goto fput_in;
+	count = retval;
 
 	retval = security_file_permission (in_file, MAY_READ);
 	if (retval)
@@ -674,8 +689,9 @@
 		goto fput_out;
 	out_inode = out_file->f_dentry->d_inode;
 	retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
-	if (retval)
+	if (retval < 0)
 		goto fput_out;
+	count = retval;
 
 	retval = security_file_permission (out_file, MAY_WRITE);
 	if (retval)
diff --git a/include/asm-arm/arch-pxa/ohci.h b/include/asm-arm/arch-pxa/ohci.h
new file mode 100644
index 0000000..7da8956
--- /dev/null
+++ b/include/asm-arm/arch-pxa/ohci.h
@@ -0,0 +1,18 @@
+#ifndef ASMARM_ARCH_OHCI_H
+#define ASMARM_ARCH_OHCI_H
+
+struct device;
+
+struct pxaohci_platform_data {
+	int (*init)(struct device *);
+	void (*exit)(struct device *);
+
+	int port_mode;
+#define PMM_NPS_MODE           1
+#define PMM_GLOBAL_MODE        2
+#define PMM_PERPORT_MODE       3
+};
+
+extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
+
+#endif
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index d068176..c31650d 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -256,6 +256,16 @@
 /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
 unsigned int cpufreq_get(unsigned int cpu);
 
+/* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
+#ifdef CONFIG_CPU_FREQ
+unsigned int cpufreq_quick_get(unsigned int cpu);
+#else
+static inline unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+	return 0;
+}
+#endif
+
 
 /*********************************************************************
  *                       CPUFREQ DEFAULT GOVERNOR                    *
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d81b050..e59d1bd 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -329,8 +329,6 @@
 	struct usb_tt	*tt; 		/* low/full speed dev, highspeed hub */
 	int		ttport;		/* device port on that tt hub */
 
-	struct semaphore serialize;
-
 	unsigned int toggle[2];		/* one bit for each endpoint
 					 * ([0] = IN, [1] = OUT) */
 
@@ -349,6 +347,9 @@
 
 	char **rawdescriptors;		/* Raw descriptors for each config */
 
+	unsigned short bus_mA;		/* Current available from the bus */
+	u8 portnum;			/* Parent port number (origin 1) */
+
 	int have_langid;		/* whether string_langid is valid */
 	int string_langid;		/* language ID for strings */
 
@@ -377,11 +378,12 @@
 extern struct usb_device *usb_get_dev(struct usb_device *dev);
 extern void usb_put_dev(struct usb_device *dev);
 
-extern void usb_lock_device(struct usb_device *udev);
-extern int usb_trylock_device(struct usb_device *udev);
+/* USB device locking */
+#define usb_lock_device(udev)		down(&(udev)->dev.sem)
+#define usb_unlock_device(udev)		up(&(udev)->dev.sem)
+#define usb_trylock_device(udev)	down_trylock(&(udev)->dev.sem)
 extern int usb_lock_device_for_reset(struct usb_device *udev,
 		struct usb_interface *iface);
-extern void usb_unlock_device(struct usb_device *udev);
 
 /* USB port reset for device reinitialization */
 extern int usb_reset_device(struct usb_device *dev);
@@ -529,10 +531,13 @@
 
 /* ----------------------------------------------------------------------- */
 
+struct usb_dynids {
+	spinlock_t lock;
+	struct list_head list;
+};
+
 /**
  * struct usb_driver - identifies USB driver to usbcore
- * @owner: Pointer to the module owner of this driver; initialize
- *	it using THIS_MODULE.
  * @name: The driver name should be unique among USB drivers,
  *	and should normally be the same as the module name.
  * @probe: Called to see if the driver is willing to manage a particular
@@ -553,7 +558,11 @@
  * @id_table: USB drivers use ID table to support hotplugging.
  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
  *	or your driver's probe function will never get called.
+ * @dynids: used internally to hold the list of dynamically added device
+ *	ids for this driver.
  * @driver: the driver model core driver structure.
+ * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
+ *	added to this driver by preventing the sysfs file from being created.
  *
  * USB drivers must provide a name, probe() and disconnect() methods,
  * and an id_table.  Other driver fields are optional.
@@ -571,8 +580,6 @@
  * them as necessary, and blocking until the unlinks complete).
  */
 struct usb_driver {
-	struct module *owner;
-
 	const char *name;
 
 	int (*probe) (struct usb_interface *intf,
@@ -588,7 +595,9 @@
 
 	const struct usb_device_id *id_table;
 
+	struct usb_dynids dynids;
 	struct device_driver driver;
+	unsigned int no_dynamic_id:1;
 };
 #define	to_usb_driver(d) container_of(d, struct usb_driver, driver)
 
@@ -614,7 +623,11 @@
  * use these in module_init()/module_exit()
  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
  */
-extern int usb_register(struct usb_driver *);
+int usb_register_driver(struct usb_driver *, struct module *);
+static inline int usb_register(struct usb_driver *driver)
+{
+	return usb_register_driver(driver, THIS_MODULE);
+}
 extern void usb_deregister(struct usb_driver *);
 
 extern int usb_register_dev(struct usb_interface *intf,
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
new file mode 100644
index 0000000..b2d0898
--- /dev/null
+++ b/include/linux/usb_usual.h
@@ -0,0 +1,126 @@
+/*
+ * Interface to the libusual.
+ *
+ * Copyright (c) 2005 Pete Zaitcev <zaitcev@redhat.com>
+ * Copyright (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * Copyright (c) 1999 Michael Gee (michael@linuxspecific.com)
+ */
+
+#ifndef __LINUX_USB_USUAL_H
+#define __LINUX_USB_USUAL_H
+
+#include <linux/config.h>
+
+/* We should do this for cleanliness... But other usb_foo.h do not do this. */
+/* #include <linux/usb.h> */
+
+/*
+ * The flags field, which we store in usb_device_id.driver_info.
+ * It is compatible with the old usb-storage flags in lower 24 bits.
+ */
+
+/*
+ * Static flag definitions.  We use this roundabout technique so that the
+ * proc_info() routine can automatically display a message for each flag.
+ */
+#define US_DO_ALL_FLAGS						\
+	US_FLAG(SINGLE_LUN,	0x00000001)			\
+		/* allow access to only LUN 0 */		\
+	US_FLAG(NEED_OVERRIDE,	0x00000002)			\
+		/* unusual_devs entry is necessary */		\
+	US_FLAG(SCM_MULT_TARG,	0x00000004)			\
+		/* supports multiple targets */			\
+	US_FLAG(FIX_INQUIRY,	0x00000008)			\
+		/* INQUIRY response needs faking */		\
+	US_FLAG(FIX_CAPACITY,	0x00000010)			\
+		/* READ CAPACITY response too big */		\
+	US_FLAG(IGNORE_RESIDUE,	0x00000020)			\
+		/* reported residue is wrong */			\
+	US_FLAG(BULK32,		0x00000040)			\
+		/* Uses 32-byte CBW length */			\
+	US_FLAG(NOT_LOCKABLE,	0x00000080)			\
+		/* PREVENT/ALLOW not supported */		\
+	US_FLAG(GO_SLOW,	0x00000100)			\
+		/* Need delay after Command phase */		\
+	US_FLAG(NO_WP_DETECT,	0x00000200)			\
+		/* Don't check for write-protect */		\
+
+#define US_FLAG(name, value)	US_FL_##name = value ,
+enum { US_DO_ALL_FLAGS };
+#undef US_FLAG
+
+/*
+ * The bias field for libusual and friends.
+ */
+#define USB_US_TYPE_NONE   0
+#define USB_US_TYPE_STOR   1		/* usb-storage */
+#define USB_US_TYPE_UB     2		/* ub */
+
+#define USB_US_TYPE(flags) 		(((flags) >> 24) & 0xFF)
+#define USB_US_ORIG_FLAGS(flags)	((flags) & 0x00FFFFFF)
+
+/*
+ * This is probably not the best place to keep these constants, conceptually.
+ * But it's the only header included into all places which need them.
+ */
+
+/* Sub Classes */
+
+#define US_SC_RBC	0x01		/* Typically, flash devices */
+#define US_SC_8020	0x02		/* CD-ROM */
+#define US_SC_QIC	0x03		/* QIC-157 Tapes */
+#define US_SC_UFI	0x04		/* Floppy */
+#define US_SC_8070	0x05		/* Removable media */
+#define US_SC_SCSI	0x06		/* Transparent */
+#define US_SC_ISD200    0x07		/* ISD200 ATA */
+#define US_SC_MIN	US_SC_RBC
+#define US_SC_MAX	US_SC_ISD200
+
+#define US_SC_DEVICE	0xff		/* Use device's value */
+
+/* Protocols */
+
+#define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
+#define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
+#define US_PR_BULK	0x50		/* bulk only */
+#ifdef CONFIG_USB_STORAGE_USBAT
+#define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR09
+#define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR55
+#define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
+#endif
+#define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
+#ifdef CONFIG_USB_STORAGE_FREECOM
+#define US_PR_FREECOM   0xf1		/* Freecom */
+#endif
+#ifdef CONFIG_USB_STORAGE_DATAFAB
+#define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
+#endif
+#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+#define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
+#endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+#define US_PR_ALAUDA    0xf4		/* Alauda chipsets */
+#endif
+
+#define US_PR_DEVICE	0xff		/* Use device's value */
+
+/*
+ */
+#ifdef CONFIG_USB_LIBUSUAL
+
+extern struct usb_device_id storage_usb_ids[];
+extern void usb_usual_set_present(int type);
+extern void usb_usual_clear_present(int type);
+extern int usb_usual_check_type(const struct usb_device_id *, int type);
+#else
+
+#define usb_usual_set_present(t)	do { } while(0)
+#define usb_usual_clear_present(t)	do { } while(0)
+#define usb_usual_check_type(id, t)	(0)
+#endif /* CONFIG_USB_LIBUSUAL */
+
+#endif /* __LINUX_USB_USUAL_H */
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 99dae02..22f8bb6 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1996,7 +1996,6 @@
 MODULE_DEVICE_TABLE (usb, usb_audio_ids);
 
 static struct usb_driver usb_audio_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"snd-usb-audio",
 	.probe =	usb_audio_probe,
 	.disconnect =	usb_audio_disconnect,
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cf77313..a3967f7 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -409,7 +409,6 @@
 
 MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
 static struct usb_driver snd_usX2Y_usb_driver = {
- 	.owner =	THIS_MODULE,
 	.name =		"snd-usb-usx2y",
 	.probe =	snd_usX2Y_probe,
 	.disconnect =	snd_usX2Y_disconnect,