Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4ec75c0..753db6d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -758,6 +758,9 @@
 	maxcpus=	[SMP] Maximum number of processors that	an SMP kernel
 			should make use of
 
+	max_addr=[KMG]	[KNL,BOOT,ia64] All physical memory greater than or
+			equal to this physical address is ignored.
+
 	max_luns=	[SCSI] Maximum number of LUNs to probe
 			Should be between 1 and 2^32-1.
 
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
index cf9a118..3f8a119 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/usb/sn9c102.txt
@@ -297,6 +297,7 @@
 0x0c45     0x602a
 0x0c45     0x602b
 0x0c45     0x602c
+0x0c45     0x602d
 0x0c45     0x6030
 0x0c45     0x6080
 0x0c45     0x6082
@@ -333,6 +334,7 @@
 -----       ------------
 HV7131D     Hynix Semiconductor, Inc.
 MI-0343     Micron Technology, Inc.
+OV7630      OmniVision Technologies, Inc.
 PAS106B     PixArt Imaging, Inc.
 PAS202BCB   PixArt Imaging, Inc.
 TAS5110C1B  Taiwan Advanced Sensor Corporation
@@ -470,9 +472,11 @@
 - Luca Capello for the donation of a webcam;
 - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
   donation of a webcam;
+- Jon Hollstrom for the donation of a webcam;
 - Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
   image sensor;
 - Stefano Mozzi, who donated 45 EU;
+- Andrew Pearce for the donation of a webcam;
 - Bertrik Sikken, who reverse-engineered and documented the Huffman compression
   algorithm used in the SN9C10x controllers and implemented the first decoder;
 - Mizuno Takafumi for the donation of a webcam;
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 2f8431f..f1896ee 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -101,6 +101,13 @@
   or 3 and 2 positions, correspondingly.
 - URB Status. This field makes no sense for submissions, but is present
   to help scripts with parsing. In error case, it contains the error code.
+  In case of a setup packet, it contains a Setup Tag. If scripts read a number
+  in this field, the proceed to read Data Length. Otherwise, they read
+  the setup packet before reading the Data Length.
+- Setup packet, if present, consists of 5 words: one of each for bmRequestType,
+  bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
+  These words are safe to decode if Setup Tag was 's'. Otherwise, the setup
+  packet was present, but not captured, and the fields contain filler.
 - Data Length. This is the actual length in the URB.
 - Data tag. The usbmon may not always capture data, even if length is nonzero.
   Only if tag is '=', the data words are present.
@@ -125,25 +132,31 @@
 			String data_str = st.nextToken();
 			int len = data_str.length() / 2;
 			int i;
+			int b;	// byte is signed, apparently?! XXX
 			for (i = 0; i < len; i++) {
-				data[data_len] = Byte.parseByte(
-				    data_str.substring(i*2, i*2 + 2),
-				    16);
+				// data[data_len] = Byte.parseByte(
+				//     data_str.substring(i*2, i*2 + 2),
+				//     16);
+				b = Integer.parseInt(
+				     data_str.substring(i*2, i*2 + 2),
+				     16);
+				if (b >= 128)
+					b *= -1;
+				data[data_len] = (byte) b;
 				data_len++;
 			}
 		}
 	}
 }
 
-This format is obviously deficient. For example, the setup packet for control
-transfers is not delivered. This will change in the future.
+This format may be changed in the future.
 
 Examples:
 
-An input control transfer to get a port status:
+An input control transfer to get a port status.
 
-d74ff9a0 2640288196 S Ci:001:00 -115 4 <
-d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100
+d5ea89a0 3575914555 S Ci:001:00 s a3 00 0000 0003 0004 4 <
+d5ea89a0 3575914560 C Ci:001:00 0 4 = 01050000
 
 An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
 to a storage device at address 5:
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index c5739d6..083c5df 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -596,6 +596,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0fb8a04c..7bc4a58 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -700,6 +700,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 menu "Device Drivers"
 
 source "drivers/base/Kconfig"
@@ -732,7 +734,7 @@
 
 source "drivers/message/i2o/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "drivers/isdn/Kconfig"
 
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index dc0c193..1f03732 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -183,6 +183,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/base/Kconfig"
 
 source "drivers/parport/Kconfig"
@@ -193,7 +195,7 @@
 
 source "drivers/md/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "drivers/ide/Kconfig"
 
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index f848e37..e5979d6 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -122,6 +122,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 # bring in ETRAX built-in drivers
 menu "Drivers for built-in interfaces"
 source arch/cris/arch-v10/drivers/Kconfig
@@ -149,7 +151,7 @@
 
 source "drivers/message/i2o/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "drivers/isdn/Kconfig"
 
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index c93f9514..ec85c0d 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -346,6 +346,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 9172860..26698a4 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -55,6 +55,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/base/Kconfig"
 
 source "drivers/mtd/Kconfig"
@@ -65,7 +67,7 @@
 
 source "arch/h8300/Kconfig.ide"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 #
 # input - input/joystick depends on it. As does USB.
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 6c02336..a801d9d 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1285,6 +1285,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 01b78e7..2e08942 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -423,6 +423,8 @@
 
 endif
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index ae84a101..0639ec0 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -191,7 +191,7 @@
 	unsigned char mac_addr[ETH_ALEN];
 	struct simeth_local *local;
 	struct net_device *dev;
-	int fd, i, err;
+	int fd, i, err, rc;
 
 	/*
 	 * XXX Fix me
@@ -228,7 +228,9 @@
 		return err;
 	}
 
-	dev->irq = assign_irq_vector(AUTO_ASSIGN);
+	if ((rc = assign_irq_vector(AUTO_ASSIGN)) < 0)
+		panic("%s: out of interrupt vectors!\n", __FUNCTION__);
+	dev->irq = rc;
 
 	/*
 	 * attach the interrupt in the simulator, this does enable interrupts
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 7a8ae0f..7dcb858 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -982,7 +982,7 @@
 static int __init
 simrs_init (void)
 {
-	int			i;
+	int			i, rc;
 	struct serial_state	*state;
 
 	if (!ia64_platform_is("hpsim"))
@@ -1017,7 +1017,10 @@
 		if (state->type == PORT_UNKNOWN) continue;
 
 		if (!state->irq) {
-			state->irq = assign_irq_vector(AUTO_ASSIGN);
+			if ((rc = assign_irq_vector(AUTO_ASSIGN)) < 0)
+				panic("%s: out of interrupt vectors!\n",
+				      __FUNCTION__);
+			state->irq = rc;
 			ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
 		}
 
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 69f88d56..bb9a506 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1249,7 +1249,7 @@
  	stf.spill [r17]=f11
 	adds out0=16,sp				// out0 = &sigscratch
 	br.call.sptk.many rp=ia64_rt_sigreturn
-.ret19:	.restore sp 0
+.ret19:	.restore sp,0
 	adds sp=16,sp
 	;;
 	ld8 r9=[sp]				// load new ar.unat
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index c170be0..7936b62 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -489,8 +489,6 @@
 			}
 		}
 	}
-	if (vector < 0)
-		panic("%s: out of interrupt vectors!\n", __FUNCTION__);
 
 	return vector;
 }
@@ -506,6 +504,8 @@
 
 	if (!list_empty(&iosapic_intr_info[vector].rtes)) {
 		new_vector = assign_irq_vector(AUTO_ASSIGN);
+		if (new_vector < 0)
+			panic("%s: out of interrupt vectors!\n", __FUNCTION__);
 		printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
 		memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
 		       sizeof(struct iosapic_intr_info));
@@ -734,9 +734,12 @@
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 
 	/* If vector is running out, we try to find a sharable vector */
-	vector = assign_irq_vector_nopanic(AUTO_ASSIGN);
-	if (vector < 0)
+	vector = assign_irq_vector(AUTO_ASSIGN);
+	if (vector < 0) {
 		vector = iosapic_find_sharable_vector(trigger, polarity);
+		if (vector < 0)
+			panic("%s: out of interrupt vectors!\n", __FUNCTION__);
+	}
 
 	spin_lock_irqsave(&irq_descp(vector)->lock, flags);
 	spin_lock(&iosapic_lock);
@@ -884,6 +887,8 @@
 		break;
 	      case ACPI_INTERRUPT_INIT:
 		vector = assign_irq_vector(AUTO_ASSIGN);
+		if (vector < 0)
+			panic("%s: out of interrupt vectors!\n", __FUNCTION__);
 		delivery = IOSAPIC_INIT;
 		break;
 	      case ACPI_INTERRUPT_CPEI:
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 4fe60c7..6c4d59f 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -63,30 +63,19 @@
 static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
 
 int
-assign_irq_vector_nopanic (int irq)
+assign_irq_vector (int irq)
 {
 	int pos, vector;
  again:
 	pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS);
 	vector = IA64_FIRST_DEVICE_VECTOR + pos;
 	if (vector > IA64_LAST_DEVICE_VECTOR)
-		return -1;
+		return -ENOSPC;
 	if (test_and_set_bit(pos, ia64_vector_mask))
 		goto again;
 	return vector;
 }
 
-int
-assign_irq_vector (int irq)
-{
-	int vector = assign_irq_vector_nopanic(irq);
-
-	if (vector < 0)
-		panic("assign_irq_vector: out of interrupt vectors!");
-
-	return vector;
-}
-
 void
 free_irq_vector (int vector)
 {
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 6407bff..b8ebb8e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -37,7 +37,6 @@
 #include <linux/vfs.h>
 #include <linux/pagemap.h>
 #include <linux/mount.h>
-#include <linux/version.h>
 #include <linux/bitops.h>
 
 #include <asm/errno.h>
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index c1cbcd1..254fe15 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -8,7 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/proc_fs.h>
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 177ddb7..d580adc 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -53,6 +53,7 @@
 #include <linux/cache.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/uaccess.h>
@@ -308,8 +309,7 @@
 			"partition %d\n", XPC_PARTID(part));
 
 		/* wait a 1/4 of a second or so */
-		set_current_state(TASK_INTERRUPTIBLE);
-		(void) schedule_timeout(0.25 * HZ);
+		msleep_interruptible(250);
 
 		if (part->act_state == XPC_P_DEACTIVATING) {
 			return part->reason;
@@ -841,9 +841,7 @@
 	down(&xpc_discovery_exited);
 
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(0.3 * HZ);
-	set_current_state(TASK_RUNNING);
+	msleep_interruptible(300);
 
 
 	/* wait for all partitions to become inactive */
@@ -860,12 +858,8 @@
 			}
 		}
 
-		if (active_part_count) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(0.3 * HZ);
-			set_current_state(TASK_RUNNING);
-		}
-
+		if (active_part_count)
+			msleep_interruptible(300);
 	} while (active_part_count > 0);
 
 
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 42ca8a3..7772951 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -359,6 +359,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 691a246..178c4a3 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -450,6 +450,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 menu "Character devices"
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index dbfcdc8..117f183 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -575,6 +575,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index bd9de7b..b578239 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1640,6 +1640,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index ce327c7..1c2d874 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -190,6 +190,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 23b0d2f..b833cbc 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -1355,6 +1355,8 @@
 	depends on ADVANCED_OPTIONS && 8xx
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index f804f25..fdd8afb 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -429,6 +429,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 6600ee8..477ac27 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -465,6 +465,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 config PCMCIA
 	bool
 	default n
@@ -475,7 +477,7 @@
 
 source "drivers/s390/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "fs/Kconfig"
 
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index a7c8bfc..adc8109f 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -784,6 +784,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 708e5973..4c3e533 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -268,6 +268,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 7a117ef..aca028a 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -268,6 +268,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 if !SUN4
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 5e8591c4..9afd28e 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -525,6 +525,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/base/Kconfig"
 
 source "drivers/video/Kconfig"
@@ -551,7 +553,7 @@
 
 source "drivers/ieee1394/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "drivers/isdn/Kconfig"
 
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 441fc2e..7e8e291 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -45,8 +45,8 @@
 /* Please don't make this stuff initdata!!!  --DaveM */
 static unsigned char boot_cpu_id;
 
-cpumask_t cpu_online_map = CPU_MASK_NONE __read_mostly;
-cpumask_t phys_cpu_present_map = CPU_MASK_NONE __read_mostly;
+cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
+cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
 static cpumask_t smp_commenced_mask;
 static cpumask_t cpu_callout_map;
 
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 6682c78..f945444 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -275,6 +275,8 @@
 
 source "init/Kconfig"
 
+source "net/Kconfig"
+
 source "drivers/base/Kconfig"
 
 source "arch/um/Kconfig_char"
@@ -287,7 +289,7 @@
 
 source "arch/um/Kconfig_net"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "fs/Kconfig"
 
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 27febd6..89c053b 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -250,6 +250,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 #############################################################################
 
 source "drivers/base/Kconfig"
@@ -283,7 +285,7 @@
 
 source "drivers/message/i2o/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "drivers/isdn/Kconfig"
 
diff --git a/arch/v850/lib/checksum.c b/arch/v850/lib/checksum.c
index d308b72..fa58726 100644
--- a/arch/v850/lib/checksum.c
+++ b/arch/v850/lib/checksum.c
@@ -138,7 +138,8 @@
  * Copy from userspace and compute checksum.  If we catch an exception
  * then zero the rest of the buffer.
  */
-unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
+unsigned int csum_partial_copy_from_user (const unsigned char *src,
+					  unsigned char *dst,
                                           int len, unsigned int sum,
                                           int *err_ptr)
 {
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index d09437b..4b83261 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -515,6 +515,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source drivers/Kconfig
 
 source "drivers/firmware/Kconfig"
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index c9b5d29..2b6257b 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -228,6 +228,8 @@
 
 endmenu
 
+source "net/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/drivers/Kconfig b/drivers/Kconfig
index cf087de3..cecab0a 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -28,7 +28,7 @@
 
 source "drivers/macintosh/Kconfig"
 
-source "net/Kconfig"
+source "drivers/net/Kconfig"
 
 source "drivers/isdn/Kconfig"
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2b55687..9a07ff7 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,6 +3,8 @@
 # Network device configuration
 #
 
+menu "Network device support"
+
 config NETDEVICES
 	depends on NET
 	bool "Network device support"
@@ -2547,3 +2549,4 @@
 	If you want to log kernel messages over the network, enable this.
 	See <file:Documentation/networking/netconsole.txt> for details.
 
+endmenu
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index 69c488d..b14e890 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -1,6 +1,33 @@
 #
 # Appletalk driver configuration
 #
+config ATALK
+	tristate "Appletalk protocol support"
+	select LLC
+	---help---
+	  AppleTalk is the protocol that Apple computers can use to communicate
+	  on a network.  If your Linux box is connected to such a network and you
+	  wish to connect to it, say Y.  You will need to use the netatalk package
+	  so that your Linux box can act as a print and file server for Macs as
+	  well as access AppleTalk printers.  Check out
+	  <http://www.zettabyte.net/netatalk/> on the WWW for details.
+	  EtherTalk is the name used for AppleTalk over Ethernet and the
+	  cheaper and slower LocalTalk is AppleTalk over a proprietary Apple
+	  network using serial links.  EtherTalk and LocalTalk are fully
+	  supported by Linux.
+
+	  General information about how to connect Linux, Windows machines and
+	  Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.  The
+	  NET-3-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>, contains valuable
+	  information as well.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called appletalk. You almost certainly want to compile it as a
+	  module so you can restart your AppleTalk stack without rebooting
+	  your machine. I hear that the GNU boycott of Apple is over, so
+	  even politically correct people are allowed to say Y here.
+
 config DEV_APPLETALK
 	bool "Appletalk interfaces support"
 	depends on ATALK
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index aad5494..f0996ce 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -369,7 +369,7 @@
  * assume 802.3 if the type field is short enough to be a length.
  * This is normal practice and works for any 'now in use' protocol.
  */
-static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *dev)
+static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index f4b6240..21537ee 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -540,7 +540,7 @@
  *	in far too many old systems not all even running Linux.
  */
  
-static unsigned short plip_type_trans(struct sk_buff *skb, struct net_device *dev)
+static __be16 plip_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 7217d44..2c83cca 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -861,8 +861,7 @@
 /*
  * Mark it for our own raw sockets interface
  */
-static unsigned short farsync_type_trans(struct sk_buff *skb,
-					 struct net_device *dev)
+static __be16 farsync_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	skb->dev = dev;
 	skb->mac.raw = skb->data;
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 8749684..48c03c1 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -91,8 +91,7 @@
 
 
 
-static unsigned short cisco_type_trans(struct sk_buff *skb,
-				       struct net_device *dev)
+static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	hdlc_header *data = (hdlc_header*)skb->data;
 
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 7cd6195..b81263e 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -66,8 +66,7 @@
 
 
 
-static unsigned short ppp_type_trans(struct sk_buff *skb,
-				     struct net_device *dev)
+static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	return __constant_htons(ETH_P_WAN_PPP);
 }
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c
index c41fb70..9456d31 100644
--- a/drivers/net/wan/hdlc_raw.c
+++ b/drivers/net/wan/hdlc_raw.c
@@ -24,8 +24,7 @@
 #include <linux/hdlc.h>
 
 
-static unsigned short raw_type_trans(struct sk_buff *skb,
-				     struct net_device *dev)
+static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	return __constant_htons(ETH_P_IP);
 }
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 3cb88c7..8f4d299 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -2210,7 +2210,7 @@
 	return NULL;
 }
 
-static inline unsigned short
+static inline __be16
 qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct qeth_card *card;
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index d79cd21..df014c2 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -65,12 +65,14 @@
 obj-$(CONFIG_USB_EMI62)		+= misc/
 obj-$(CONFIG_USB_IDMOUSE)	+= misc/
 obj-$(CONFIG_USB_LCD)		+= misc/
+obj-$(CONFIG_USB_LD)		+= misc/
 obj-$(CONFIG_USB_LED)		+= misc/
 obj-$(CONFIG_USB_LEGOTOWER)	+= misc/
 obj-$(CONFIG_USB_RIO500)	+= misc/
 obj-$(CONFIG_USB_TEST)		+= misc/
 obj-$(CONFIG_USB_USS720)	+= misc/
 obj-$(CONFIG_USB_PHIDGETSERVO)	+= misc/
+obj-$(CONFIG_USB_SISUSBVGA)	+= misc/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index cbd4a7d2..8e184e2 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -427,7 +427,7 @@
 		atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
 		atm_dev->signal = ATM_PHY_SIG_FOUND;
 
-		dev_info(dev, "ADSL line: up (%d Kib/s down | %d Kib/s up)\n",
+		dev_info(dev, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
 		     buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);
 		break;
 
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 6a6eaa2..d0cbbb7 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -100,6 +100,8 @@
 
 	struct work_struct status_checker;
 
+	unsigned char last_status;
+
 	int poll_delay; /* milliseconds */
 
 	struct timer_list resubmit_timer;
@@ -423,52 +425,48 @@
 	struct usbatm_data *usbatm = instance->usbatm;
 	struct atm_dev *atm_dev = usbatm->atm_dev;
 	unsigned char *buf = instance->scratch_buffer;
-	int ret;
+	int down_speed, up_speed, ret;
+	unsigned char status;
 
 	atm_dbg(usbatm, "%s entered\n", __func__);
 
 	ret = speedtch_read_status(instance);
 	if (ret < 0) {
 		atm_warn(usbatm, "error %d fetching device status\n", ret);
-		if (instance->poll_delay < MAX_POLL_DELAY)
-			instance->poll_delay *= 2;
+		instance->poll_delay = min(2 * instance->poll_delay, MAX_POLL_DELAY);
 		return;
 	}
 
-	if (instance->poll_delay > MIN_POLL_DELAY)
-		instance->poll_delay /= 2;
+	instance->poll_delay = max(instance->poll_delay / 2, MIN_POLL_DELAY);
 
-	atm_dbg(usbatm, "%s: line state %02x\n", __func__, buf[OFFSET_7]);
+	status = buf[OFFSET_7];
 
-	switch (buf[OFFSET_7]) {
-	case 0:
-		if (atm_dev->signal != ATM_PHY_SIG_LOST) {
+	atm_dbg(usbatm, "%s: line state %02x\n", __func__, status);
+
+	if ((status != instance->last_status) || !status) {
+		switch (status) {
+		case 0:
 			atm_dev->signal = ATM_PHY_SIG_LOST;
-			atm_info(usbatm, "ADSL line is down\n");
-			/* It'll never resync again unless we ask it to... */
+			if (instance->last_status)
+				atm_info(usbatm, "ADSL line is down\n");
+			/* It may never resync again unless we ask it to... */
 			ret = speedtch_start_synchro(instance);
-		}
-		break;
+			break;
 
-	case 0x08:
-		if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) {
+		case 0x08:
 			atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
 			atm_info(usbatm, "ADSL line is blocked?\n");
-		}
-		break;
+			break;
 
-	case 0x10:
-		if (atm_dev->signal != ATM_PHY_SIG_LOST) {
+		case 0x10:
 			atm_dev->signal = ATM_PHY_SIG_LOST;
 			atm_info(usbatm, "ADSL line is synchronising\n");
-		}
-		break;
+			break;
 
-	case 0x20:
-		if (atm_dev->signal != ATM_PHY_SIG_FOUND) {
-			int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8)
+		case 0x20:
+			down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8)
 				| (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24);
-			int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8)
+			up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8)
 				| (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24);
 
 			if (!(down_speed & 0x0000ffff) && !(up_speed & 0x0000ffff)) {
@@ -480,17 +478,17 @@
 			atm_dev->signal = ATM_PHY_SIG_FOUND;
 
 			atm_info(usbatm,
-				 "ADSL line is up (%d Kib/s down | %d Kib/s up)\n",
+				 "ADSL line is up (%d kb/s down | %d kb/s up)\n",
 				 down_speed, up_speed);
-		}
-		break;
+			break;
 
-	default:
-		if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) {
+		default:
 			atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
-			atm_info(usbatm, "Unknown line state %02x\n", buf[OFFSET_7]);
+			atm_info(usbatm, "Unknown line state %02x\n", status);
+			break;
 		}
-		break;
+
+		instance->last_status = status;
 	}
 }
 
@@ -730,6 +728,7 @@
 
 	instance->status_checker.timer.function = speedtch_status_poll;
 	instance->status_checker.timer.data = (unsigned long)instance;
+	instance->last_status = 0xff;
 	instance->poll_delay = MIN_POLL_DELAY;
 
 	init_timer(&instance->resubmit_timer);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 69e859e..adff5a7 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -422,6 +422,17 @@
 	return -EIO;
 }
 
+static void acm_tty_unregister(struct acm *acm)
+{
+	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);
+	kfree(acm);
+}
+
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct acm *acm = tty->driver_data;
@@ -436,14 +447,8 @@
 			usb_kill_urb(acm->ctrlurb);
 			usb_kill_urb(acm->writeurb);
 			usb_kill_urb(acm->readurb);
-		} else {
-			tty_unregister_device(acm_tty_driver, acm->minor);
-			acm_table[acm->minor] = NULL;
-			usb_free_urb(acm->ctrlurb);
-			usb_free_urb(acm->readurb);
-			usb_free_urb(acm->writeurb);
-			kfree(acm);
-		}
+		} else
+			acm_tty_unregister(acm);
 	}
 	up(&open_sem);
 }
@@ -905,7 +910,8 @@
 
 	usb_driver_claim_interface(&acm_driver, data_interface, acm);
 
-	tty_register_device(acm_tty_driver, minor, &intf->dev);
+	usb_get_intf(control_interface);
+	tty_register_device(acm_tty_driver, minor, &control_interface->dev);
 
 	acm_table[minor] = acm;
 	usb_set_intfdata (intf, acm);
@@ -954,12 +960,7 @@
 	usb_driver_release_interface(&acm_driver, acm->data);
 
 	if (!acm->used) {
-		tty_unregister_device(acm_tty_driver, acm->minor);
-		acm_table[acm->minor] = NULL;
-		usb_free_urb(acm->ctrlurb);
-		usb_free_urb(acm->readurb);
-		usb_free_urb(acm->writeurb);
-		kfree(acm);
+		acm_tty_unregister(acm);
 		up(&open_sem);
 		return;
 	}
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index b7827df..fc15b4a 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -106,7 +106,7 @@
 void *hcd_buffer_alloc (
 	struct usb_bus 		*bus,
 	size_t			size,
-	int			mem_flags,
+	unsigned		mem_flags,
 	dma_addr_t		*dma
 )
 {
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 83e732a..8616356 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1112,7 +1112,7 @@
  * expects usb_submit_urb() to have sanity checked and conditioned all
  * inputs in the urb
  */
-static int hcd_submit_urb (struct urb *urb, int mem_flags)
+static int hcd_submit_urb (struct urb *urb, unsigned mem_flags)
 {
 	int			status;
 	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 8dc13cd..67db4a9 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -142,12 +142,12 @@
 
 struct usb_operations {
 	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb *urb, int mem_flags);
+	int (*submit_urb) (struct urb *urb, unsigned mem_flags);
 	int (*unlink_urb) (struct urb *urb, int status);
 
 	/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
 	void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
-			int mem_flags,
+			unsigned mem_flags,
 			dma_addr_t *dma);
 	void (*buffer_free)(struct usb_bus *bus, size_t size,
 			void *addr, dma_addr_t dma);
@@ -200,7 +200,7 @@
 	int	(*urb_enqueue) (struct usb_hcd *hcd,
 					struct usb_host_endpoint *ep,
 					struct urb *urb,
-					int mem_flags);
+					unsigned mem_flags);
 	int	(*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
 
 	/* hw synch, freeing endpoint resources that urb_dequeue can't */
@@ -247,7 +247,7 @@
 void hcd_buffer_destroy (struct usb_hcd *hcd);
 
 void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
-	int mem_flags, dma_addr_t *dma);
+	unsigned mem_flags, dma_addr_t *dma);
 void hcd_buffer_free (struct usb_bus *bus, size_t size,
 	void *addr, dma_addr_t dma);
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 32ff3218..c3e46d2 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -26,6 +26,7 @@
 #include <linux/ioctl.h>
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
+#include <linux/kthread.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -47,8 +48,7 @@
 /* Wakes up khubd */
 static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
 
-static pid_t khubd_pid = 0;			/* PID of khubd */
-static DECLARE_COMPLETION(khubd_exited);
+static struct task_struct *khubd_task;
 
 /* cycle leds on hubs that aren't blinking for attention */
 static int blinkenlights = 0;
@@ -2807,23 +2807,16 @@
 
 static int hub_thread(void *__unused)
 {
-	/*
-	 * This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-
-	daemonize("khubd");
-	allow_signal(SIGKILL);
-
-	/* Send me a signal to get me die (for debugging) */
 	do {
 		hub_events();
-		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); 
+		wait_event_interruptible(khubd_wait,
+				!list_empty(&hub_event_list) ||
+				kthread_should_stop());
 		try_to_freeze();
-	} while (!signal_pending(current));
+	} while (!kthread_should_stop() || !list_empty(&hub_event_list));
 
-	pr_debug ("%s: khubd exiting\n", usbcore_name);
-	complete_and_exit(&khubd_exited, 0);
+	pr_debug("%s: khubd exiting\n", usbcore_name);
+	return 0;
 }
 
 static struct usb_device_id hub_id_table [] = {
@@ -2849,20 +2842,15 @@
 
 int usb_hub_init(void)
 {
-	pid_t pid;
-
 	if (usb_register(&hub_driver) < 0) {
 		printk(KERN_ERR "%s: can't register hub driver\n",
 			usbcore_name);
 		return -1;
 	}
 
-	pid = kernel_thread(hub_thread, NULL, CLONE_KERNEL);
-	if (pid >= 0) {
-		khubd_pid = pid;
-
+	khubd_task = kthread_run(hub_thread, NULL, "khubd");
+	if (!IS_ERR(khubd_task))
 		return 0;
-	}
 
 	/* Fall through if kernel_thread failed */
 	usb_deregister(&hub_driver);
@@ -2873,12 +2861,7 @@
 
 void usb_hub_cleanup(void)
 {
-	int ret;
-
-	/* Kill the thread */
-	ret = kill_proc(khubd_pid, SIGKILL, 1);
-
-	wait_for_completion(&khubd_exited);
+	kthread_stop(khubd_task);
 
 	/*
 	 * Hub resources are freed for us by usb_deregister. It calls
@@ -2890,7 +2873,6 @@
 	usb_deregister(&hub_driver);
 } /* usb_hub_cleanup() */
 
-
 static int config_descriptors_changed(struct usb_device *udev)
 {
 	unsigned			index;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f50aaf2..a428ef4 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -320,7 +320,7 @@
 	struct scatterlist	*sg,
 	int			nents,
 	size_t			length,
-	int			mem_flags
+	unsigned		mem_flags
 )
 {
 	int			i;
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 740cb4c..00297f1 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -196,6 +196,7 @@
 usb_descriptor_attr (bDeviceSubClass, "%02x\n")
 usb_descriptor_attr (bDeviceProtocol, "%02x\n")
 usb_descriptor_attr (bNumConfigurations, "%d\n")
+usb_descriptor_attr (bMaxPacketSize0, "%d\n")
 
 static struct attribute *dev_attrs[] = {
 	/* current configuration's attributes */
@@ -211,6 +212,7 @@
 	&dev_attr_bDeviceSubClass.attr,
 	&dev_attr_bDeviceProtocol.attr,
 	&dev_attr_bNumConfigurations.attr,
+	&dev_attr_bMaxPacketSize0.attr,
 	&dev_attr_speed.attr,
 	&dev_attr_devnum.attr,
 	&dev_attr_version.attr,
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 0faf18d..c0feee2 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -60,7 +60,7 @@
  *
  * The driver must call usb_free_urb() when it is finished with the urb.
  */
-struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
+struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags)
 {
 	struct urb *urb;
 
@@ -224,7 +224,7 @@
  *      GFP_NOIO, unless b) or c) apply
  *
  */
-int usb_submit_urb(struct urb *urb, int mem_flags)
+int usb_submit_urb(struct urb *urb, unsigned mem_flags)
 {
 	int			pipe, temp, max;
 	struct usb_device	*dev;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index a3c4220..99c85d2 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1129,7 +1129,7 @@
 void *usb_buffer_alloc (
 	struct usb_device *dev,
 	size_t size,
-	int mem_flags,
+	unsigned mem_flags,
 	dma_addr_t *dma
 )
 {
@@ -1532,6 +1532,9 @@
 EXPORT_SYMBOL(usb_deregister);
 EXPORT_SYMBOL(usb_disabled);
 
+EXPORT_SYMBOL_GPL(usb_get_intf);
+EXPORT_SYMBOL_GPL(usb_put_intf);
+
 EXPORT_SYMBOL(usb_alloc_dev);
 EXPORT_SYMBOL(usb_put_dev);
 EXPORT_SYMBOL(usb_get_dev);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4d69267..583db7c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -470,7 +470,7 @@
 }
 
 static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, int mem_flags)
+dummy_alloc_request (struct usb_ep *_ep, unsigned mem_flags)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
@@ -507,7 +507,7 @@
 	struct usb_ep *_ep,
 	unsigned bytes,
 	dma_addr_t *dma,
-	int mem_flags
+	unsigned mem_flags
 ) {
 	char			*retval;
 	struct dummy_ep		*ep;
@@ -540,7 +540,8 @@
 }
 
 static int
-dummy_queue (struct usb_ep *_ep, struct usb_request *_req, int mem_flags)
+dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
+		unsigned mem_flags)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
@@ -998,7 +999,7 @@
 	struct usb_hcd			*hcd,
 	struct usb_host_endpoint	*ep,
 	struct urb			*urb,
-	int				mem_flags
+	unsigned			mem_flags
 ) {
 	struct dummy	*dum;
 	struct urbp	*urbp;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 5bb53ae..8509e95 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -945,15 +945,16 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void eth_start (struct eth_dev *dev, int gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags);
+static void eth_start (struct eth_dev *dev, unsigned gfp_flags);
+static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags);
 
 static int
-set_ether_config (struct eth_dev *dev, int gfp_flags)
+set_ether_config (struct eth_dev *dev, unsigned gfp_flags)
 {
 	int					result = 0;
 	struct usb_gadget			*gadget = dev->gadget;
 
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 	/* status endpoint used for RNDIS and (optionally) CDC */
 	if (!subset_active(dev) && dev->status_ep) {
 		dev->status = ep_desc (gadget, &hs_status_desc,
@@ -967,6 +968,7 @@
 			goto done;
 		}
 	}
+#endif
 
 	dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
 	dev->in_ep->driver_data = dev;
@@ -1079,7 +1081,7 @@
  * that returns config descriptors, and altsetting code.
  */
 static int
-eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
+eth_set_config (struct eth_dev *dev, unsigned number, unsigned gfp_flags)
 {
 	int			result = 0;
 	struct usb_gadget	*gadget = dev->gadget;
@@ -1596,7 +1598,7 @@
 static void rx_complete (struct usb_ep *ep, struct usb_request *req);
 
 static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
+rx_submit (struct eth_dev *dev, struct usb_request *req, unsigned gfp_flags)
 {
 	struct sk_buff		*skb;
 	int			retval = -ENOMEM;
@@ -1722,7 +1724,7 @@
 }
 
 static int prealloc (struct list_head *list, struct usb_ep *ep,
-			unsigned n, int gfp_flags)
+			unsigned n, unsigned gfp_flags)
 {
 	unsigned		i;
 	struct usb_request	*req;
@@ -1761,7 +1763,7 @@
 	return 0;
 }
 
-static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags)
+static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags)
 {
 	int status;
 
@@ -1777,7 +1779,7 @@
 	return status;
 }
 
-static void rx_fill (struct eth_dev *dev, int gfp_flags)
+static void rx_fill (struct eth_dev *dev, unsigned gfp_flags)
 {
 	struct usb_request	*req;
 	unsigned long		flags;
@@ -2022,7 +2024,7 @@
 
 #endif	/* RNDIS */
 
-static void eth_start (struct eth_dev *dev, int gfp_flags)
+static void eth_start (struct eth_dev *dev, unsigned gfp_flags)
 {
 	DEBUG (dev, "%s\n", __FUNCTION__);
 
@@ -2428,7 +2430,7 @@
 	dev->req->complete = eth_setup_complete;
 
 	/* ... and maybe likewise for status transfer */
-#ifdef DEV_CONFIG_CDC
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 	if (dev->status_ep) {
 		dev->stat_req = eth_req_alloc (dev->status_ep,
 					STATUS_BYTECOUNT, GFP_KERNEL);
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index ed773a9..eaab26f 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -269,7 +269,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, int gfp_flags)
+goku_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
 {
 	struct goku_request	*req;
 
@@ -327,7 +327,7 @@
  */
 static void *
 goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-			dma_addr_t *dma, int  gfp_flags)
+			dma_addr_t *dma, unsigned gfp_flags)
 {
 	void		*retval;
 	struct goku_ep	*ep;
@@ -789,7 +789,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+goku_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
 {
 	struct goku_request	*req;
 	struct goku_ep		*ep;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index df75ab6..4842577 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -1106,7 +1106,7 @@
 }
 
 static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
-						 int gfp_flags)
+						 unsigned gfp_flags)
 {
 	struct lh7a40x_request *req;
 
@@ -1134,7 +1134,7 @@
 }
 
 static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
-				  dma_addr_t * dma, int gfp_flags)
+				  dma_addr_t * dma, unsigned gfp_flags)
 {
 	char *retval;
 
@@ -1158,7 +1158,7 @@
  *  NOTE: Sets INDEX register
  */
 static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
-			 int gfp_flags)
+			 unsigned gfp_flags)
 {
 	struct lh7a40x_request *req;
 	struct lh7a40x_ep *ep;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 13a3dbc9..477fab2 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -376,7 +376,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, int gfp_flags)
+net2280_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
 {
 	struct net2280_ep	*ep;
 	struct net2280_request	*req;
@@ -463,7 +463,7 @@
 	struct usb_ep		*_ep,
 	unsigned		bytes,
 	dma_addr_t		*dma,
-	int			gfp_flags
+	unsigned		gfp_flags
 )
 {
 	void			*retval;
@@ -897,7 +897,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+net2280_queue (struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
 {
 	struct net2280_request	*req;
 	struct net2280_ep	*ep;
@@ -1490,7 +1490,7 @@
 	unsigned long		flags;
 	int			i;
 	u32			t1, t2;
-	char			*s;
+	const char		*s;
 
 	dev = dev_get_drvdata (_dev);
 	next = buf;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index a2b812a..ff5533e 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -269,7 +269,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-omap_alloc_request(struct usb_ep *ep, int gfp_flags)
+omap_alloc_request(struct usb_ep *ep, unsigned gfp_flags)
 {
 	struct omap_req	*req;
 
@@ -298,7 +298,7 @@
 	struct usb_ep	*_ep,
 	unsigned	bytes,
 	dma_addr_t	*dma,
-	int		gfp_flags
+	unsigned	gfp_flags
 )
 {
 	void		*retval;
@@ -937,7 +937,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
 {
 	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
 	struct omap_req	*req = container_of(_req, struct omap_req, req);
@@ -2908,6 +2908,7 @@
  * make host resumes and VBUS detection trigger OMAP wakeup events; that
  * may involve talking to an external transceiver (e.g. isp1301).
  */
+
 static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level)
 {
 	u32	devstat;
@@ -2936,8 +2937,6 @@
 		return 0;
 
 	DBG("resume + wakeup/SRP\n");
-	udc->gadget.dev.parent->power.power_state = PMSG_ON;
-	udc->gadget.dev.power.power_state = PMSG_ON;
 	omap_pullup(&udc->gadget, 1);
 
 	/* maybe the host would enumerate us if we nudged it */
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 6a0b957..1507738 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -332,7 +332,7 @@
  * 	pxa2xx_ep_alloc_request - allocate a request data structure
  */
 static struct usb_request *
-pxa2xx_ep_alloc_request (struct usb_ep *_ep, int gfp_flags)
+pxa2xx_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
 {
 	struct pxa2xx_request *req;
 
@@ -367,7 +367,7 @@
  */
 static void *
 pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-	dma_addr_t *dma, int gfp_flags)
+	dma_addr_t *dma, unsigned gfp_flags)
 {
 	char			*retval;
 
@@ -874,7 +874,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
 {
 	struct pxa2xx_request	*req;
 	struct pxa2xx_ep	*ep;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index a6e035e..bb9b2d9 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -612,7 +612,7 @@
 }
 
 static struct usb_request *
-source_sink_start_ep (struct usb_ep *ep, int gfp_flags)
+source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
 {
 	struct usb_request	*req;
 	int			status;
@@ -640,7 +640,7 @@
 }
 
 static int
-set_source_sink_config (struct zero_dev *dev, int gfp_flags)
+set_source_sink_config (struct zero_dev *dev, unsigned gfp_flags)
 {
 	int			result = 0;
 	struct usb_ep		*ep;
@@ -744,7 +744,7 @@
 }
 
 static int
-set_loopback_config (struct zero_dev *dev, int gfp_flags)
+set_loopback_config (struct zero_dev *dev, unsigned gfp_flags)
 {
 	int			result = 0;
 	struct usb_ep		*ep;
@@ -845,7 +845,7 @@
  * by limiting configuration choices (like the pxa2xx).
  */
 static int
-zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
+zero_set_config (struct zero_dev *dev, unsigned number, unsigned gfp_flags)
 {
 	int			result = 0;
 	struct usb_gadget	*gadget = dev->gadget;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 35248a3..149b13f 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -960,7 +960,7 @@
 	struct usb_hcd	*hcd,
 	struct usb_host_endpoint *ep,
 	struct urb	*urb,
-	int		mem_flags
+	unsigned	mem_flags
 ) {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	struct list_head	qtd_list;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 45d89a7..d74b2d6 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -898,7 +898,7 @@
 	struct usb_host_endpoint *ep,
 	struct urb		*urb,
 	struct list_head	*qtd_list,
-	int			mem_flags
+	unsigned		mem_flags
 ) {
 	struct ehci_qtd		*qtd;
 	int			epnum;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index c2104ca..9af4f64 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -588,7 +588,7 @@
 	struct usb_host_endpoint *ep,
 	struct urb		*urb,
 	struct list_head	*qtd_list,
-	int			mem_flags
+	unsigned		mem_flags
 ) {
 	unsigned		epnum;
 	unsigned long		flags;
@@ -633,7 +633,7 @@
 /* ehci_iso_stream ops work with both ITD and SITD */
 
 static struct ehci_iso_stream *
-iso_stream_alloc (int mem_flags)
+iso_stream_alloc (unsigned mem_flags)
 {
 	struct ehci_iso_stream *stream;
 
@@ -846,7 +846,7 @@
 /* ehci_iso_sched ops can be ITD-only or SITD-only */
 
 static struct ehci_iso_sched *
-iso_sched_alloc (unsigned packets, int mem_flags)
+iso_sched_alloc (unsigned packets, unsigned mem_flags)
 {
 	struct ehci_iso_sched	*iso_sched;
 	int			size = sizeof *iso_sched;
@@ -919,7 +919,7 @@
 	struct ehci_iso_stream	*stream,
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
-	int			mem_flags
+	unsigned		mem_flags
 )
 {
 	struct ehci_itd		*itd;
@@ -1412,7 +1412,8 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+	unsigned mem_flags)
 {
 	int			status = -EINVAL;
 	unsigned long		flags;
@@ -1523,7 +1524,7 @@
 	struct ehci_iso_stream	*stream,
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
-	int			mem_flags
+	unsigned		mem_flags
 )
 {
 	struct ehci_sitd	*sitd;
@@ -1772,7 +1773,8 @@
 }
 
 
-static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+	unsigned mem_flags)
 {
 	int			status = -EINVAL;
 	unsigned long		flags;
@@ -1822,7 +1824,8 @@
 #else
 
 static inline int
-sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+	unsigned mem_flags)
 {
 	ehci_dbg (ehci, "split iso support is disabled\n");
 	return -ENOSYS;
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index d9883d7..81f8f6b 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -463,7 +463,8 @@
 
 static int etrax_remove_from_sb_list(struct urb *urb);
 
-static void* etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size, int mem_flags, dma_addr_t *dma);
+static void* etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size,
+	unsigned mem_flags, dma_addr_t *dma);
 static void etrax_usb_buffer_free(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma);
 
 static void etrax_usb_add_to_bulk_sb_list(struct urb *urb, int epid);
@@ -476,7 +477,7 @@
 static int etrax_usb_submit_intr_urb(struct urb *urb);
 static int etrax_usb_submit_isoc_urb(struct urb *urb);
 
-static int etrax_usb_submit_urb(struct urb *urb, int mem_flags);
+static int etrax_usb_submit_urb(struct urb *urb, unsigned mem_flags);
 static int etrax_usb_unlink_urb(struct urb *urb, int status);
 static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
 
@@ -1262,7 +1263,7 @@
 	return -1;
 }
 
-static int etrax_usb_submit_urb(struct urb *urb, int mem_flags)
+static int etrax_usb_submit_urb(struct urb *urb, unsigned mem_flags)
 {
 	etrax_hc_t *hc;
 	int ret = -EINVAL;
@@ -4277,7 +4278,8 @@
 }
 
 static void*
-etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size, int mem_flags, dma_addr_t *dma)
+etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size,
+	unsigned mem_flags, dma_addr_t *dma)
 {
   return kmalloc(size, mem_flags);
 }
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index ff0a168..50b1970 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -17,7 +17,7 @@
  * The driver basically works. A number of people have used it with a range
  * of devices.
  *
- *The driver passes all usbtests 1-14.
+ * The driver passes all usbtests 1-14.
  *
  * Suspending/resuming of root hub via sysfs works. Remote wakeup works too.
  * And suspending/resuming of platform device works too. Suspend/resume
@@ -229,7 +229,7 @@
 	struct isp116x_ep *ep;
 	struct urb *urb;
 	struct ptd *ptd;
-	u16 toggle, dir, len;
+	u16 toggle = 0, dir = PTD_DIR_SETUP, len;
 
 	for (ep = isp116x->atl_active; ep; ep = ep->active) {
 		BUG_ON(list_empty(&ep->hep->urb_list));
@@ -251,8 +251,6 @@
 			dir = PTD_DIR_OUT;
 			break;
 		case USB_PID_SETUP:
-			toggle = 0;
-			dir = PTD_DIR_SETUP;
 			len = sizeof(struct usb_ctrlrequest);
 			ep->data = urb->setup_packet;
 			break;
@@ -264,11 +262,9 @@
 			    ? PTD_DIR_OUT : PTD_DIR_IN;
 			break;
 		default:
-			/* To please gcc */
-			toggle = dir = 0;
 			ERR("%s %d: ep->nextpid %d\n", __func__, __LINE__,
 			    ep->nextpid);
-			BUG_ON(1);
+			BUG();
 		}
 
 		ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle);
@@ -697,7 +693,7 @@
 
 static int isp116x_urb_enqueue(struct usb_hcd *hcd,
 			       struct usb_host_endpoint *hep, struct urb *urb,
-			       int mem_flags)
+			       unsigned mem_flags)
 {
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	struct usb_device *udev = urb->dev;
@@ -719,7 +715,7 @@
 	}
 	/* avoid all allocations within spinlocks: request or endpoint */
 	if (!hep->hcpriv) {
-		ep = kcalloc(1, sizeof *ep, (__force unsigned)mem_flags);
+		ep = kcalloc(1, sizeof *ep, mem_flags);
 		if (!ep)
 			return -ENOMEM;
 	}
@@ -1054,7 +1050,7 @@
 		break;
 	case GetHubStatus:
 		DBG("GetHubStatus\n");
-		*(__le32 *) buf = cpu_to_le32(0);
+		*(__le32 *) buf = 0;
 		break;
 	case GetPortStatus:
 		DBG("GetPortStatus\n");
@@ -1810,9 +1806,9 @@
 	ret = usb_suspend_device(hcd->self.root_hub, state);
 	if (!ret) {
 		dev->power.power_state = state;
-		INFO("%s suspended\n", (char *)hcd_name);
+		INFO("%s suspended\n", hcd_name);
 	} else
-		ERR("%s suspend failed\n", (char *)hcd_name);
+		ERR("%s suspend failed\n", hcd_name);
 
 	return ret;
 }
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 13cd217..68decab 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -180,7 +180,7 @@
 	struct usb_hcd	*hcd,
 	struct usb_host_endpoint *ep,
 	struct urb	*urb,
-	int		mem_flags
+	unsigned	mem_flags
 ) {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	struct ed	*ed;
@@ -673,8 +673,10 @@
 
 	ohci_dump (ohci, 1);
 
-	if (ohci_to_hcd(ohci)->self.root_hub == NULL)
+	if (ohci_to_hcd(ohci)->self.root_hub == NULL) {
+		register_reboot_notifier (&ohci->reboot_notifier);
 		create_debug_files (ohci);
+	}
 
 	return 0;
 }
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index e2fc412..83ca454 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -419,10 +419,11 @@
 
 	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
 	rh = roothub_b (ohci);
+	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
 	desc->bitmap [0] = rh & RH_B_DR;
 	if (ports > 7) {
 		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
-		desc->bitmap [2] = desc->bitmap [3] = 0xff;
+		desc->bitmap [2] = 0xff;
 	} else
 		desc->bitmap [1] = 0xff;
 }
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 23735a3..fd3c4d3 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -84,7 +84,7 @@
 
 /* TDs ... */
 static struct td *
-td_alloc (struct ohci_hcd *hc, int mem_flags)
+td_alloc (struct ohci_hcd *hc, unsigned mem_flags)
 {
 	dma_addr_t	dma;
 	struct td	*td;
@@ -118,7 +118,7 @@
 
 /* EDs ... */
 static struct ed *
-ed_alloc (struct ohci_hcd *hc, int mem_flags)
+ed_alloc (struct ohci_hcd *hc, unsigned mem_flags)
 {
 	dma_addr_t	dma;
 	struct ed	*ed;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index b62d699..5cde76f 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -456,34 +456,22 @@
 
 #ifdef	CONFIG_PM
 
-/* states match PCI usage, always suspending the root hub except that
- * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
- *
- * FIXME: above comment is not right, and code is wrong, too :-(.
- */
-
-static int ohci_omap_suspend(struct device *dev, pm_message_t state, u32 level)
+static int ohci_omap_suspend(struct device *dev, pm_message_t message, u32 level)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
 	int		status = -EINVAL;
 
 	if (level != SUSPEND_POWER_DOWN)
 		return 0;
-	if (state <= dev->power.power_state)
-		return 0;
 
-	dev_dbg(dev, "suspend to %d\n", state);
 	down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
 	status = ohci_hub_suspend(ohci_to_hcd(ohci));
 	if (status == 0) {
-		if (state >= 4) {
-			omap_ohci_clock_power(0);
-			ohci_to_hcd(ohci)->self.root_hub->state =
-					USB_STATE_SUSPENDED;
-			state = 4;
-		}
+		omap_ohci_clock_power(0);
+		ohci_to_hcd(ohci)->self.root_hub->state =
+			USB_STATE_SUSPENDED;
 		ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-		dev->power.power_state = state;
+		dev->power.power_state = PMSG_SUSPEND;
 	}
 	up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
 	return status;
@@ -497,29 +485,20 @@
 	if (level != RESUME_POWER_ON)
 		return 0;
 
-	switch (dev->power.power_state) {
-	case 0:
-		break;
-	case 4:
-		if (time_before(jiffies, ohci->next_statechange))
-			msleep(5);
-		ohci->next_statechange = jiffies;
-		omap_ohci_clock_power(1);
-		/* FALLTHROUGH */
-	default:
-		dev_dbg(dev, "resume from %d\n", dev->power.power_state);
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+	omap_ohci_clock_power(1);
 #ifdef	CONFIG_USB_SUSPEND
-		/* get extra cleanup even if remote wakeup isn't in use */
-		status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
+	/* get extra cleanup even if remote wakeup isn't in use */
+	status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
 #else
-		down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-		status = ohci_hub_resume(ohci_to_hcd(ohci));
-		up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+	down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+	status = ohci_hub_resume(ohci_to_hcd(ohci));
+	up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
 #endif
-		if (status == 0)
-			dev->power.power_state = 0;
-		break;
-	}
+	if (status == 0)
+		dev->power.power_state = PMSG_ON;
 	return status;
 }
 
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 6c3f910b..7a890a6 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -815,7 +815,7 @@
 	struct usb_hcd		*hcd,
 	struct usb_host_endpoint *hep,
 	struct urb		*urb,
-	int			mem_flags
+	unsigned		mem_flags
 ) {
 	struct sl811		*sl811 = hcd_to_sl811(hcd);
 	struct usb_device	*udev = urb->dev;
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 5f18084..bbb36cd 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1164,7 +1164,7 @@
 
 static int uhci_urb_enqueue(struct usb_hcd *hcd,
 		struct usb_host_endpoint *ep,
-		struct urb *urb, int mem_flags)
+		struct urb *urb, unsigned mem_flags)
 {
 	int ret;
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index fd59f6b..298e4a2 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -259,3 +259,16 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called ati_remote.
 
+config USB_KEYSPAN_REMOTE
+	tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
+	depends on USB && INPUT && EXPERIMENTAL
+	---help---
+	  Say Y here if you want to use a Keyspan DMR USB remote control.
+	  Currently only the UIA-11 type of receiver has been tested.  The tag
+	  on the receiver that connects to the USB port should have a P/N that
+	  will tell you what type of DMR you have.  The UIA-10 type is not
+	  supported at this time.  This driver maps all buttons to keypress
+	  events.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called keyspan_remote.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 831b2b0..f1547be 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -31,6 +31,7 @@
 obj-$(CONFIG_USB_HID)		+= usbhid.o
 obj-$(CONFIG_USB_KBD)		+= usbkbd.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
+obj-$(CONFIG_USB_KEYSPAN_REMOTE)	+= keyspan_remote.o
 obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o
 obj-$(CONFIG_USB_MTOUCH)	+= mtouchusb.o
 obj-$(CONFIG_USB_ITMTOUCH)	+= itmtouch.o
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 100b49bd..2350e7a 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1428,6 +1428,19 @@
 #define USB_DEVICE_ID_VERNIER_SKIP	0x0003
 #define USB_DEVICE_ID_VERNIER_CYCLOPS	0x0004
 
+#define USB_VENDOR_ID_LD		0x0f11
+#define USB_DEVICE_ID_CASSY        	0x1000
+#define USB_DEVICE_ID_POCKETCASSY	0x1010
+#define USB_DEVICE_ID_MOBILECASSY	0x1020
+#define USB_DEVICE_ID_JWM		0x1080
+#define USB_DEVICE_ID_DMMP		0x1081
+#define USB_DEVICE_ID_UMIP		0x1090
+#define USB_DEVICE_ID_VIDEOCOM		0x1200
+#define USB_DEVICE_ID_COM3LAB		0x2000
+#define USB_DEVICE_ID_TELEPORT		0x2010
+#define USB_DEVICE_ID_NETWORKANALYSER	0x2020
+#define USB_DEVICE_ID_POWERCONTROL	0x2030
+
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -1463,6 +1476,17 @@
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
new file mode 100644
index 0000000..67dc936
--- /dev/null
+++ b/drivers/usb/input/keyspan_remote.c
@@ -0,0 +1,633 @@
+/*
+ * keyspan_remote: USB driver for the Keyspan DMR
+ *
+ * Copyright (C) 2005 Zymeta Corporation - Michael Downey (downey@zymeta.com)
+ *
+ *	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, version 2.
+ *
+ * This driver has been put together with the support of Innosys, Inc.
+ * and Keyspan, Inc the manufacturers of the Keyspan USB DMR product.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#define DRIVER_VERSION	"v0.1"
+#define DRIVER_AUTHOR	"Michael Downey <downey@zymeta.com>"
+#define DRIVER_DESC	"Driver for the USB Keyspan remote control."
+#define DRIVER_LICENSE	"GPL"
+
+/* Parameters that can be passed to the driver. */
+static int debug;
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
+
+/* Vendor and product ids */
+#define USB_KEYSPAN_VENDOR_ID		0x06CD
+#define USB_KEYSPAN_PRODUCT_UIA11	0x0202
+
+/* Defines for converting the data from the remote. */
+#define ZERO		0x18
+#define ZERO_MASK	0x1F	/* 5 bits for a 0 */
+#define ONE		0x3C
+#define ONE_MASK	0x3F	/* 6 bits for a 1 */
+#define SYNC		0x3F80
+#define SYNC_MASK	0x3FFF	/* 14 bits for a SYNC sequence */
+#define STOP		0x00
+#define STOP_MASK	0x1F	/* 5 bits for the STOP sequence */
+#define GAP		0xFF
+
+#define RECV_SIZE	8	/* The UIA-11 type have a 8 byte limit. */
+
+/* table of devices that work with this driver */
+static struct usb_device_id keyspan_table[] = {
+	{ USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) },
+	{ }					/* Terminating entry */
+};
+
+/* Structure to store all the real stuff that a remote sends to us. */
+struct keyspan_message {
+	u16	system;
+	u8	button;
+	u8	toggle;
+};
+
+/* Structure used for all the bit testing magic needed to be done. */
+struct bit_tester {
+	u32	tester;
+	int	len;
+	int	pos;
+	int	bits_left;
+	u8	buffer[32];
+};
+
+/* Structure to hold all of our driver specific stuff */
+struct usb_keyspan {
+	char				name[128];
+	char				phys[64];
+	struct usb_device*		udev;
+	struct input_dev		input;
+	struct usb_interface*		interface;
+	struct usb_endpoint_descriptor* in_endpoint;
+	struct urb*			irq_urb;
+	int				open;
+	dma_addr_t			in_dma;
+	unsigned char*			in_buffer;
+
+	/* variables used to parse messages from remote. */
+	struct bit_tester		data;
+	int				stage;
+	int				toggle;
+};
+
+/*
+ * Table that maps the 31 possible keycodes to input keys.
+ * Currently there are 15 and 17 button models so RESERVED codes
+ * are blank areas in the mapping.
+ */
+static int keyspan_key_table[] = {
+	KEY_RESERVED,		/* 0 is just a place holder. */
+	KEY_RESERVED,
+	KEY_STOP,
+	KEY_PLAYCD,
+	KEY_RESERVED,
+	KEY_PREVIOUSSONG,
+	KEY_REWIND,
+	KEY_FORWARD,
+	KEY_NEXTSONG,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_PAUSE,
+	KEY_VOLUMEUP,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_VOLUMEDOWN,
+	KEY_RESERVED,
+	KEY_UP,
+	KEY_RESERVED,
+	KEY_MUTE,
+	KEY_LEFT,
+	KEY_ENTER,
+	KEY_RIGHT,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_DOWN,
+	KEY_RESERVED,
+	KEY_KPASTERISK,
+	KEY_RESERVED,
+	KEY_MENU
+};
+
+static struct usb_driver keyspan_driver;
+
+/*
+ * Debug routine that prints out what we've received from the remote.
+ */
+static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/
+{
+	char codes[4*RECV_SIZE];
+	int i;
+
+	for (i = 0; i < RECV_SIZE; i++) {
+		snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]);
+	}
+
+	dev_info(&dev->udev->dev, "%s\n", codes);
+}
+
+/*
+ * Routine that manages the bit_tester structure.  It makes sure that there are
+ * at least bits_needed bits loaded into the tester.
+ */
+static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
+{
+	if (dev->data.bits_left >= bits_needed)
+		return(0);
+
+	/*
+	 * Somehow we've missed the last message. The message will be repeated
+	 * though so it's not too big a deal
+	 */
+	if (dev->data.pos >= dev->data.len) {
+		dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n",
+			__FUNCTION__, dev->data.pos, dev->data.len);
+		return(-1);
+	}
+
+	/* Load as much as we can into the tester. */
+	while ((dev->data.bits_left + 7 < (sizeof(dev->data.tester) * 8)) &&
+	       (dev->data.pos < dev->data.len)) {
+		dev->data.tester += (dev->data.buffer[dev->data.pos++] << dev->data.bits_left);
+		dev->data.bits_left += 8;
+	}
+
+	return(0);
+}
+
+/*
+ * Routine that handles all the logic needed to parse out the message from the remote.
+ */
+static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs)
+{
+	int i;
+	int found = 0;
+	struct keyspan_message message;
+
+	switch(remote->stage) {
+	case 0:
+		/*
+		 * In stage 0 we want to find the start of a message.  The remote sends a 0xFF as filler.
+		 * So the first byte that isn't a FF should be the start of a new message.
+		 */
+		for (i = 0; i < RECV_SIZE && remote->in_buffer[i] == GAP; ++i);
+
+		if (i < RECV_SIZE) {
+			memcpy(remote->data.buffer, remote->in_buffer, RECV_SIZE);
+			remote->data.len = RECV_SIZE;
+			remote->data.pos = 0;
+			remote->data.tester = 0;
+			remote->data.bits_left = 0;
+			remote->stage = 1;
+		}
+		break;
+
+	case 1:
+		/*
+		 * Stage 1 we should have 16 bytes and should be able to detect a
+		 * SYNC.  The SYNC is 14 bits, 7 0's and then 7 1's.
+		 */
+		memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE);
+		remote->data.len += RECV_SIZE;
+
+		found = 0;
+		while ((remote->data.bits_left >= 14 || remote->data.pos < remote->data.len) && !found) {
+			for (i = 0; i < 8; ++i) {
+				if (keyspan_load_tester(remote, 14) != 0) {
+					remote->stage = 0;
+					return;
+				}
+
+				if ((remote->data.tester & SYNC_MASK) == SYNC) {
+					remote->data.tester = remote->data.tester >> 14;
+					remote->data.bits_left -= 14;
+					found = 1;
+					break;
+				} else {
+					remote->data.tester = remote->data.tester >> 1;
+					--remote->data.bits_left;
+				}
+			}
+		}
+
+		if (!found) {
+			remote->stage = 0;
+			remote->data.len = 0;
+		} else {
+			remote->stage = 2;
+		}
+		break;
+
+	case 2:
+		/*
+		 * Stage 2 we should have 24 bytes which will be enough for a full
+		 * message.  We need to parse out the system code, button code,
+		 * toggle code, and stop.
+		 */
+		memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE);
+		remote->data.len += RECV_SIZE;
+
+		message.system = 0;
+		for (i = 0; i < 9; i++) {
+			keyspan_load_tester(remote, 6);
+
+			if ((remote->data.tester & ZERO_MASK) == ZERO) {
+				message.system = message.system << 1;
+				remote->data.tester = remote->data.tester >> 5;
+				remote->data.bits_left -= 5;
+			} else if ((remote->data.tester & ONE_MASK) == ONE) {
+				message.system = (message.system << 1) + 1;
+				remote->data.tester = remote->data.tester >> 6;
+				remote->data.bits_left -= 6;
+			} else {
+				err("%s - Unknown sequence found in system data.\n", __FUNCTION__);
+				remote->stage = 0;
+				return;
+			}
+		}
+
+		message.button = 0;
+		for (i = 0; i < 5; i++) {
+			keyspan_load_tester(remote, 6);
+
+			if ((remote->data.tester & ZERO_MASK) == ZERO) {
+				message.button = message.button << 1;
+				remote->data.tester = remote->data.tester >> 5;
+				remote->data.bits_left -= 5;
+			} else if ((remote->data.tester & ONE_MASK) == ONE) {
+				message.button = (message.button << 1) + 1;
+				remote->data.tester = remote->data.tester >> 6;
+				remote->data.bits_left -= 6;
+			} else {
+				err("%s - Unknown sequence found in button data.\n", __FUNCTION__);
+				remote->stage = 0;
+				return;
+			}
+		}
+
+		keyspan_load_tester(remote, 6);
+		if ((remote->data.tester & ZERO_MASK) == ZERO) {
+			message.toggle = 0;
+			remote->data.tester = remote->data.tester >> 5;
+			remote->data.bits_left -= 5;
+		} else if ((remote->data.tester & ONE_MASK) == ONE) {
+			message.toggle = 1;
+			remote->data.tester = remote->data.tester >> 6;
+			remote->data.bits_left -= 6;
+		} else {
+			err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+		}
+
+		keyspan_load_tester(remote, 5);
+		if ((remote->data.tester & STOP_MASK) == STOP) {
+			remote->data.tester = remote->data.tester >> 5;
+			remote->data.bits_left -= 5;
+		} else {
+			err("Bad message recieved, no stop bit found.\n");
+		}
+
+		dev_dbg(&remote->udev,
+			"%s found valid message: system: %d, button: %d, toggle: %d\n",
+			__FUNCTION__, message.system, message.button, message.toggle);
+
+		if (message.toggle != remote->toggle) {
+			input_regs(&remote->input, regs);
+			input_report_key(&remote->input, keyspan_key_table[message.button], 1);
+			input_report_key(&remote->input, keyspan_key_table[message.button], 0);
+			input_sync(&remote->input);
+			remote->toggle = message.toggle;
+		}
+
+		remote->stage = 0;
+		break;
+	}
+}
+
+/*
+ * Routine for sending all the initialization messages to the remote.
+ */
+static int keyspan_setup(struct usb_device* dev)
+{
+	int retval = 0;
+
+	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
+	if (retval) {
+		dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
+			__FUNCTION__, retval);
+		return(retval);
+	}
+
+	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				 0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
+	if (retval) {
+		dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
+			__FUNCTION__, retval);
+		return(retval);
+	}
+
+	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				 0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
+	if (retval) {
+		dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
+			__FUNCTION__, retval);
+		return(retval);
+	}
+
+	dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__);
+	return(retval);
+}
+
+/*
+ * Routine used to handle a new message that has come in.
+ */
+static void keyspan_irq_recv(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_keyspan *dev = urb->context;
+	int retval;
+
+	/* Check our status in case we need to bail out early. */
+	switch (urb->status) {
+	case 0:
+		break;
+
+	/* Device went away so don't keep trying to read from it. */
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+
+	default:
+		goto resubmit;
+		break;
+	}
+
+	if (debug)
+		keyspan_print(dev);
+
+	keyspan_check_data(dev, regs);
+
+resubmit:
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval);
+}
+
+static int keyspan_open(struct input_dev *dev)
+{
+	struct usb_keyspan *remote = dev->private;
+
+	if (remote->open++)
+		return 0;
+
+	remote->irq_urb->dev = remote->udev;
+	if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) {
+		remote->open--;
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void keyspan_close(struct input_dev *dev)
+{
+	struct usb_keyspan *remote = dev->private;
+
+	if (!--remote->open)
+		usb_kill_urb(remote->irq_urb);
+}
+
+/*
+ * Routine that sets up the driver to handle a specific USB device detected on the bus.
+ */
+static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	int i;
+	int retval = -ENOMEM;
+	char path[64];
+	char *buf;
+	struct usb_keyspan *remote = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
+
+	/* See if the offered device matches what we can accept */
+	if ((udev->descriptor.idVendor != USB_KEYSPAN_VENDOR_ID) ||
+	    (udev->descriptor.idProduct != USB_KEYSPAN_PRODUCT_UIA11) )
+		return -ENODEV;
+
+	/* allocate memory for our device state and initialize it */
+	remote = kmalloc(sizeof(*remote), GFP_KERNEL);
+	if (remote == NULL) {
+		err("Out of memory\n");
+		goto error;
+	}
+	memset(remote, 0x00, sizeof(*remote));
+
+	remote->udev = udev;
+	remote->interface = interface;
+	remote->toggle = -1;	/* Set to -1 so we will always not match the toggle from the first remote message. */
+
+	/* set up the endpoint information */
+	/* use only the first in interrupt endpoint */
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (!remote->in_endpoint &&
+		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+			/* we found our interrupt in endpoint */
+			remote->in_endpoint = endpoint;
+
+			remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
+			if (!remote->in_buffer) {
+				retval = -ENOMEM;
+				goto error;
+			}
+		}
+	}
+
+	if (!remote->in_endpoint) {
+		err("Could not find interrupt input endpoint.\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!remote->irq_urb) {
+		err("Failed to allocate urb.\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	retval = keyspan_setup(remote->udev);
+	if (retval) {
+		err("Failed to setup device.\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	/*
+	 * Setup the input system with the bits we are going to be reporting
+	 */
+	remote->input.evbit[0] = BIT(EV_KEY);		/* We will only report KEY events. */
+	for (i = 0; i < 32; ++i) {
+		if (keyspan_key_table[i] != KEY_RESERVED) {
+			set_bit(keyspan_key_table[i], remote->input.keybit);
+		}
+	}
+
+	remote->input.private = remote;
+	remote->input.open = keyspan_open;
+	remote->input.close = keyspan_close;
+
+	usb_make_path(remote->udev, path, 64);
+	sprintf(remote->phys, "%s/input0", path);
+
+	remote->input.name = remote->name;
+	remote->input.phys = remote->phys;
+	remote->input.id.bustype = BUS_USB;
+	remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor);
+	remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct);
+	remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice);
+
+	if (!(buf = kmalloc(63, GFP_KERNEL))) {
+		usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
+		kfree(remote);
+		return -ENOMEM;
+	}
+
+	if (remote->udev->descriptor.iManufacturer &&
+	    usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0)
+		strcat(remote->name, buf);
+
+	if (remote->udev->descriptor.iProduct &&
+	    usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0)
+		sprintf(remote->name, "%s %s", remote->name, buf);
+
+	if (!strlen(remote->name))
+		sprintf(remote->name, "USB Keyspan Remote %04x:%04x",
+			remote->input.id.vendor, remote->input.id.product);
+
+	kfree(buf);
+
+	/*
+	 * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open()
+	 */
+	usb_fill_int_urb(remote->irq_urb,
+			 remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress),
+			 remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote,
+			 remote->in_endpoint->bInterval);
+	remote->irq_urb->transfer_dma = remote->in_dma;
+	remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* we can register the device now, as it is ready */
+	input_register_device(&remote->input);
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, remote);
+
+	/* let the user know what node this device is now attached to */
+	info("connected: %s on %s", remote->name, path);
+	return 0;
+
+error:
+	/*
+	 * In case of error we need to clean up any allocated buffers
+	 */
+	if (remote->irq_urb)
+		usb_free_urb(remote->irq_urb);
+
+	if (remote->in_buffer)
+		usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
+
+	if (remote)
+		kfree(remote);
+
+	return retval;
+}
+
+/*
+ * Routine called when a device is disconnected from the USB.
+ */
+static void keyspan_disconnect(struct usb_interface *interface)
+{
+	struct usb_keyspan *remote;
+
+	/* prevent keyspan_open() from racing keyspan_disconnect() */
+	lock_kernel();
+
+	remote = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	if (remote) {	/* We have a valid driver structure so clean up everything we allocated. */
+		input_unregister_device(&remote->input);
+		usb_kill_urb(remote->irq_urb);
+		usb_free_urb(remote->irq_urb);
+		usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma);
+		kfree(remote);
+	}
+
+	unlock_kernel();
+
+	info("USB Keyspan now disconnected");
+}
+
+/*
+ * Standard driver set up sections
+ */
+static struct usb_driver keyspan_driver =
+{
+	.owner =	THIS_MODULE,
+	.name =		"keyspan_remote",
+	.probe =	keyspan_probe,
+	.disconnect =	keyspan_disconnect,
+	.id_table =	keyspan_table
+};
+
+static int __init usb_keyspan_init(void)
+{
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&keyspan_driver);
+	if (result)
+		err("usb_register failed. Error number %d\n", result);
+
+	return result;
+}
+
+static void __exit usb_keyspan_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&keyspan_driver);
+}
+
+module_init(usb_keyspan_init);
+module_exit(usb_keyspan_exit);
+
+MODULE_DEVICE_TABLE(usb, keyspan_table);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index 2b76df7..d83adff 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -2,7 +2,7 @@
 # Makefile for USB Media drivers
 #
 
-sn9c102-objs	:= sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
+sn9c102-objs	:= sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
 
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
 obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index 8b8a4c8..e5cea0e 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -56,7 +56,7 @@
 #define SN9C102_MODULE_AUTHOR   "(C) 2004-2005 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.24"
+#define SN9C102_MODULE_VERSION  "1:1.24a"
 #define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 24)
 
 enum sn9c102_bridge {
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index 31d5740..cf8cfba 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -429,7 +429,7 @@
 }
 
 
-static int 
+int
 sn9c102_i2c_try_write(struct sn9c102_device* cam,
                       struct sn9c102_sensor* sensor, u8 address, u8 value)
 {
diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c
new file mode 100644
index 0000000..d27c5ae
--- /dev/null
+++ b/drivers/usb/media/sn9c102_ov7630.c
@@ -0,0 +1,394 @@
+/***************************************************************************
+ * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera      *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2005 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor ov7630;
+
+
+static int ov7630_init(struct sn9c102_device* cam)
+{
+	int err = 0;
+
+	err += sn9c102_write_reg(cam, 0x00, 0x14);
+	err += sn9c102_write_reg(cam, 0x60, 0x17);
+	err += sn9c102_write_reg(cam, 0x0f, 0x18);
+	err += sn9c102_write_reg(cam, 0x50, 0x19);
+
+	err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+	err += sn9c102_i2c_write(cam, 0x11, 0x00);
+	err += sn9c102_i2c_write(cam, 0x15, 0x34);
+	err += sn9c102_i2c_write(cam, 0x16, 0x03);
+	err += sn9c102_i2c_write(cam, 0x17, 0x1c);
+	err += sn9c102_i2c_write(cam, 0x18, 0xbd);
+	err += sn9c102_i2c_write(cam, 0x19, 0x06);
+	err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+	err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+	err += sn9c102_i2c_write(cam, 0x20, 0x44);
+	err += sn9c102_i2c_write(cam, 0x23, 0xee);
+	err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+	err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+	err += sn9c102_i2c_write(cam, 0x28, 0x20);
+	err += sn9c102_i2c_write(cam, 0x29, 0x30);
+	err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+	err += sn9c102_i2c_write(cam, 0x30, 0x24);
+	err += sn9c102_i2c_write(cam, 0x32, 0x86);
+	err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+	err += sn9c102_i2c_write(cam, 0x61, 0x42);
+	err += sn9c102_i2c_write(cam, 0x65, 0x00);
+	err += sn9c102_i2c_write(cam, 0x69, 0x38);
+	err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+	err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+	err += sn9c102_i2c_write(cam, 0x71, 0x00);
+	err += sn9c102_i2c_write(cam, 0x74, 0x21);
+	err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+
+	return err;
+}
+
+
+static int ov7630_set_ctrl(struct sn9c102_device* cam,
+                           const struct v4l2_control* ctrl)
+{
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2);
+		err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		err += sn9c102_i2c_write(cam, 0x03, ctrl->value);
+		break;
+	case V4L2_CID_GAIN:
+		err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+		break;
+	case V4L2_CID_CONTRAST:
+		err += ctrl->value ? sn9c102_i2c_write(cam, 0x05,
+		                                       (ctrl->value-1) | 0x20)
+		                   : sn9c102_i2c_write(cam, 0x05, 0x00);
+		break;
+	case V4L2_CID_BRIGHTNESS:
+		err += sn9c102_i2c_write(cam, 0x06, ctrl->value);
+		break;
+	case V4L2_CID_SATURATION:
+		err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4);
+		break;
+	case V4L2_CID_HUE:
+		err += ctrl->value ? sn9c102_i2c_write(cam, 0x04,
+		                                       (ctrl->value-1) | 0x20)
+		                   : sn9c102_i2c_write(cam, 0x04, 0x00);
+		break;
+	case V4L2_CID_DO_WHITE_BALANCE:
+		err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
+		break;
+	case V4L2_CID_WHITENESS:
+		err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
+		break;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x09);
+		break;
+	case V4L2_CID_AUTOGAIN:
+		err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
+		break;
+	case V4L2_CID_VFLIP:
+		err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
+		break;
+	case V4L2_CID_BLACK_LEVEL:
+		err += sn9c102_i2c_write(cam, 0x25, ctrl->value);
+		break;
+	case SN9C102_V4L2_CID_BRIGHT_LEVEL:
+		err += sn9c102_i2c_write(cam, 0x24, ctrl->value);
+		break;
+	case SN9C102_V4L2_CID_GAMMA:
+		err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80);
+		break;
+	case SN9C102_V4L2_CID_BAND_FILTER:
+		err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err ? -EIO : 0;
+}
+
+
+static int ov7630_set_crop(struct sn9c102_device* cam,
+                           const struct v4l2_rect* rect)
+{
+	struct sn9c102_sensor* s = &ov7630;
+	int err = 0;
+	u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+	err += sn9c102_write_reg(cam, v_start, 0x13);
+
+	return err;
+}
+
+
+static int ov7630_set_pix_format(struct sn9c102_device* cam,
+                                 const struct v4l2_pix_format* pix)
+{
+	int err = 0;
+
+	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+		err += sn9c102_write_reg(cam, 0x20, 0x19);
+	else
+		err += sn9c102_write_reg(cam, 0x50, 0x19);
+
+	return err;
+}
+
+
+static struct sn9c102_sensor ov7630 = {
+	.name = "OV7630",
+	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.sysfs_ops = SN9C102_I2C_WRITE,
+	.frequency = SN9C102_I2C_100KHZ,
+	.interface = SN9C102_I2C_2WIRES,
+	.i2c_slave_id = 0x21,
+	.init = &ov7630_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0x3f,
+			.step = 0x01,
+			.default_value = 0x14,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_HUE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "hue",
+			.minimum = 0x00,
+			.maximum = 0x1f+1,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_SATURATION,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "saturation",
+			.minimum = 0x00,
+			.maximum = 0x0f,
+			.step = 0x01,
+			.default_value = 0x08,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_CONTRAST,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "contrast",
+			.minimum = 0x00,
+			.maximum = 0x1f+1,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_EXPOSURE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "exposure",
+			.minimum = 0x000,
+			.maximum = 0x3ff,
+			.step = 0x001,
+			.default_value = 0x83<<2,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_RED_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "red balance",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x3a,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BLUE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "blue balance",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x77,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BRIGHTNESS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "brightness",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0xa0,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_DO_WHITE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "white balance background: blue",
+			.minimum = 0x00,
+			.maximum = 0x3f,
+			.step = 0x01,
+			.default_value = 0x20,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_WHITENESS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "white balance background: red",
+			.minimum = 0x00,
+			.maximum = 0x3f,
+			.step = 0x01,
+			.default_value = 0x20,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_AUTO_WHITE_BALANCE,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "auto white balance",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x01,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_AUTOGAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "gain & exposure mode",
+			.minimum = 0x00,
+			.maximum = 0x03,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_VFLIP,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "vertical flip",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x01,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BLACK_LEVEL,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "black pixel ratio",
+			.minimum = 0x01,
+			.maximum = 0x9a,
+			.step = 0x01,
+			.default_value = 0x8a,
+			.flags = 0,
+		},
+		{
+			.id = SN9C102_V4L2_CID_BRIGHT_LEVEL,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "bright pixel ratio",
+			.minimum = 0x01,
+			.maximum = 0x9a,
+			.step = 0x01,
+			.default_value = 0x10,
+			.flags = 0,
+		},
+		{
+			.id = SN9C102_V4L2_CID_BAND_FILTER,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "band filter",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+		{
+			.id = SN9C102_V4L2_CID_GAMMA,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "rgb gamma",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+	},
+	.set_ctrl = &ov7630_set_ctrl,
+	.cropcap = {
+		.bounds = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+		.defrect = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+	},
+	.set_crop = &ov7630_set_crop,
+	.pix_format = {
+		.width = 640,
+		.height = 480,
+		.pixelformat = V4L2_PIX_FMT_SBGGR8,
+		.priv = 8,
+	},
+	.set_pix_format = &ov7630_set_pix_format
+};
+
+
+int sn9c102_probe_ov7630(struct sn9c102_device* cam)
+{
+	int err = 0;
+
+	sn9c102_attach_sensor(cam, &ov7630);
+
+	if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
+	    le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c)
+		return -ENODEV;
+
+	err += sn9c102_write_reg(cam, 0x01, 0x01);
+	err += sn9c102_write_reg(cam, 0x00, 0x01);
+	err += sn9c102_write_reg(cam, 0x28, 0x17);
+
+	if (err)
+		return -EIO;
+
+	err += sn9c102_i2c_write(cam, 0x0b, 0);
+	if (err)
+		return -ENODEV;
+
+	return 0;
+}
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index 6a7adeb..a45166c 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -64,6 +64,7 @@
 */
 extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
 extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
+extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
 extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
 extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
@@ -80,6 +81,7 @@
 	&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */    \
 	&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */  \
 	&sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */    \
+	&sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */    \
 	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */       \
 	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */       \
 	NULL,                                                                 \
@@ -103,7 +105,8 @@
 	{ USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */                        \
 	{ USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */                        \
 	{ USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */                        \
-	{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */                         \
+	{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */                         \
+	{ USB_DEVICE(0x0c45, 0x602d), },                                      \
 	{ USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */                          \
 	{ USB_DEVICE(0x0c45, 0x6080), },                                      \
 	{ USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */              \
@@ -145,6 +148,8 @@
 */
 
 /* The "try" I2C I/O versions are used when probing the sensor */
+extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
+                                 u8 address, u8 value);
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
                                 u8 address);
 
@@ -201,6 +206,8 @@
 	SN9C102_I2C_3WIRES,
 };
 
+#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+
 struct sn9c102_sensor {
 	char name[32], /* sensor name */
 	     maintainer[64]; /* name of the mantainer <email> */
@@ -243,7 +250,7 @@
 	   sensor according to the default configuration structures below.
 	*/
 
-	struct v4l2_queryctrl qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
+	struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
 	/*
 	   Optional list of default controls, defined as indicated in the 
 	   V4L2 API. Menu type controls are not handled by this interface.
@@ -356,7 +363,7 @@
 	   core module to store successfully updated values of the above
 	   settings, for rollbacks..etc..in case of errors during atomic I/O
 	*/
-	struct v4l2_queryctrl _qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
+	struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
 	struct v4l2_rect _rect;
 };
 
@@ -367,5 +374,8 @@
 #define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
 #define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2
 #define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3
+#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4
+#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5
+#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6
 
 #endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index 690d621..8775999 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -24,8 +24,6 @@
 
 static struct sn9c102_sensor tas5110c1b;
 
-static struct v4l2_control tas5110c1b_gain;
-
 
 static int tas5110c1b_init(struct sn9c102_device* cam)
 {
@@ -46,21 +44,6 @@
 }
 
 
-static int tas5110c1b_get_ctrl(struct sn9c102_device* cam, 
-                               struct v4l2_control* ctrl)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		ctrl->value = tas5110c1b_gain.value;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
 static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, 
                                const struct v4l2_control* ctrl)
 {
@@ -68,8 +51,7 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_GAIN:
-		if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value)))
-			tas5110c1b_gain.value = ctrl->value;
+		err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
 		break;
 	default:
 		return -EINVAL;
@@ -147,7 +129,6 @@
 			.height = 288,
 		},
 	},
-	.get_ctrl = &tas5110c1b_get_ctrl,
 	.set_crop = &tas5110c1b_set_crop,
 	.pix_format = {
 		.width = 352,
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index b378e94..927eafd 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -24,8 +24,6 @@
 
 static struct sn9c102_sensor tas5130d1b;
 
-static struct v4l2_control tas5130d1b_gain, tas5130d1b_exposure;
-
 
 static int tas5130d1b_init(struct sn9c102_device* cam)
 {
@@ -44,24 +42,6 @@
 }
 
 
-static int tas5130d1b_get_ctrl(struct sn9c102_device* cam, 
-                               struct v4l2_control* ctrl)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		ctrl->value = tas5130d1b_gain.value;
-		break;
-	case V4L2_CID_EXPOSURE:
-		ctrl->value = tas5130d1b_exposure.value;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
 static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, 
                                const struct v4l2_control* ctrl)
 {
@@ -69,12 +49,10 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_GAIN:
-		if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value)))
-			tas5130d1b_gain.value = ctrl->value;
+		err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
 		break;
 	case V4L2_CID_EXPOSURE:
-		if (!(err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value)))
-			tas5130d1b_exposure.value = ctrl->value;
+		err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
 		break;
 	default:
 		return -EINVAL;
@@ -147,7 +125,6 @@
 			.flags = 0,
 		},
 	},
-	.get_ctrl = &tas5130d1b_get_ctrl,
 	.set_ctrl = &tas5130d1b_set_ctrl,
 	.cropcap = {
 		.bounds = {
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 3a89695..6649531 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -139,6 +139,16 @@
 
 source "drivers/usb/misc/sisusbvga/Kconfig"
 
+config USB_LD
+	tristate "USB LD driver"
+	depends on USB && EXPERIMENTAL
+	help
+	  This driver is for generic USB devices that use interrupt transfers,
+	  like LD Didactic's USB devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ldusb.
+
 config USB_TEST
 	tristate "USB testing driver (DEVELOPMENT)"
 	depends on USB && USB_DEVICEFS && EXPERIMENTAL
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 4a3814c..862e40a 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_USB_EMI62)		+= emi62.o
 obj-$(CONFIG_USB_IDMOUSE)	+= idmouse.o
 obj-$(CONFIG_USB_LCD)		+= usblcd.o
+obj-$(CONFIG_USB_LD)		+= ldusb.o
 obj-$(CONFIG_USB_LED)		+= usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
 obj-$(CONFIG_USB_PHIDGETKIT)	+= phidgetkit.o
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
new file mode 100644
index 0000000..66ec883
--- /dev/null
+++ b/drivers/usb/misc/ldusb.c
@@ -0,0 +1,794 @@
+/**
+ * Generic USB driver for report based interrupt in/out devices
+ * like LD Didactic's USB devices. LD Didactic's USB devices are
+ * HID devices which do not use HID report definitons (they use
+ * raw interrupt in and our reports only for communication).
+ *
+ * This driver uses a ring buffer for time critical reading of
+ * interrupt in reports and provides read and write methods for
+ * raw interrupt reports (similar to the Windows HID driver).
+ * Devices based on the book USB COMPLETE by Jan Axelson may need
+ * such a compatibility to the Windows HID driver.
+ *
+ * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
+ *
+ *	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.
+ *
+ * Derived from Lego USB Tower driver
+ * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
+ *		 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
+ *
+ * V0.1  (mh) Initial version
+ * V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+
+/* Define these values to match your devices */
+#define USB_VENDOR_ID_LD		0x0f11	/* USB Vendor ID of LD Didactic GmbH */
+#define USB_DEVICE_ID_CASSY		0x1000	/* USB Product ID for all CASSY-S modules */
+#define USB_DEVICE_ID_POCKETCASSY	0x1010	/* USB Product ID for Pocket-CASSY */
+#define USB_DEVICE_ID_MOBILECASSY	0x1020	/* USB Product ID for Mobile-CASSY */
+#define USB_DEVICE_ID_JWM		0x1080	/* USB Product ID for Joule and Wattmeter */
+#define USB_DEVICE_ID_DMMP		0x1081	/* USB Product ID for Digital Multimeter P (reserved) */
+#define USB_DEVICE_ID_UMIP		0x1090	/* USB Product ID for UMI P */
+#define USB_DEVICE_ID_VIDEOCOM		0x1200	/* USB Product ID for VideoCom */
+#define USB_DEVICE_ID_COM3LAB		0x2000	/* USB Product ID for COM3LAB */
+#define USB_DEVICE_ID_TELEPORT		0x2010	/* USB Product ID for Terminal Adapter */
+#define USB_DEVICE_ID_NETWORKANALYSER	0x2020	/* USB Product ID for Network Analyser */
+#define USB_DEVICE_ID_POWERCONTROL	0x2030	/* USB Product ID for Controlling device for Power Electronics */
+
+#define USB_VENDOR_ID_VERNIER		0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP	0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP	0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS	0x0004
+
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define USB_LD_MINOR_BASE	0
+#else
+#define USB_LD_MINOR_BASE	176
+#endif
+
+/* table of devices that work with this driver */
+static struct usb_device_id ld_usb_table [] = {
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER) },
+	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL) },
+	{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
+	{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
+	{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
+	{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ld_usb_table);
+MODULE_VERSION("V0.11");
+MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
+MODULE_DESCRIPTION("LD USB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("LD USB Devices");
+
+#ifdef CONFIG_USB_DEBUG
+	static int debug = 1;
+#else
+	static int debug = 0;
+#endif
+
+/* Use our own dbg macro */
+#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
+
+/* Module parameters */
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* All interrupt in transfers are collected in a ring buffer to
+ * avoid racing conditions and get better performance of the driver.
+ */
+static int ring_buffer_size = 128;
+module_param(ring_buffer_size, int, 0);
+MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports");
+
+/* The write_buffer can contain more than one interrupt out transfer.
+ */
+static int write_buffer_size = 10;
+module_param(write_buffer_size, int, 0);
+MODULE_PARM_DESC(write_buffer_size, "Write buffer size in reports");
+
+/* As of kernel version 2.6.4 ehci-hcd uses an
+ * "only one interrupt transfer per frame" shortcut
+ * to simplify the scheduling of periodic transfers.
+ * This conflicts with our standard 1ms intervals for in and out URBs.
+ * We use default intervals of 2ms for in and 2ms for out transfers,
+ * which should be fast enough.
+ * Increase the interval to allow more devices that do interrupt transfers,
+ * or set to 1 to use the standard interval from the endpoint descriptors.
+ */
+static int min_interrupt_in_interval = 2;
+module_param(min_interrupt_in_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms");
+
+static int min_interrupt_out_interval = 2;
+module_param(min_interrupt_out_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms");
+
+/* Structure to hold all of our device specific stuff */
+struct ld_usb {
+	struct semaphore	sem;		/* locks this structure */
+	struct usb_interface*	intf;		/* save off the usb interface pointer */
+
+	int			open_count;	/* number of times this port has been opened */
+
+	char*			ring_buffer;
+	unsigned int		ring_head;
+	unsigned int		ring_tail;
+
+	wait_queue_head_t	read_wait;
+	wait_queue_head_t	write_wait;
+
+	char*			interrupt_in_buffer;
+	struct usb_endpoint_descriptor* interrupt_in_endpoint;
+	struct urb*		interrupt_in_urb;
+	int			interrupt_in_interval;
+	size_t			interrupt_in_endpoint_size;
+	int			interrupt_in_running;
+	int			interrupt_in_done;
+
+	char*			interrupt_out_buffer;
+	struct usb_endpoint_descriptor* interrupt_out_endpoint;
+	struct urb*		interrupt_out_urb;
+	int			interrupt_out_interval;
+	size_t			interrupt_out_endpoint_size;
+	int			interrupt_out_busy;
+};
+
+/* prevent races between open() and disconnect() */
+static DECLARE_MUTEX(disconnect_sem);
+
+static struct usb_driver ld_usb_driver;
+
+/**
+ *	ld_usb_abort_transfers
+ *      aborts transfers and frees associated data structures
+ */
+static void ld_usb_abort_transfers(struct ld_usb *dev)
+{
+	/* shutdown transfer */
+	if (dev->interrupt_in_running) {
+		dev->interrupt_in_running = 0;
+		if (dev->intf)
+			usb_kill_urb(dev->interrupt_in_urb);
+	}
+	if (dev->interrupt_out_busy)
+		if (dev->intf)
+			usb_kill_urb(dev->interrupt_out_urb);
+}
+
+/**
+ *	ld_usb_delete
+ */
+static void ld_usb_delete(struct ld_usb *dev)
+{
+	ld_usb_abort_transfers(dev);
+
+	/* free data structures */
+	usb_free_urb(dev->interrupt_in_urb);
+	usb_free_urb(dev->interrupt_out_urb);
+	kfree(dev->ring_buffer);
+	kfree(dev->interrupt_in_buffer);
+	kfree(dev->interrupt_out_buffer);
+	kfree(dev);
+}
+
+/**
+ *	ld_usb_interrupt_in_callback
+ */
+static void ld_usb_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct ld_usb *dev = urb->context;
+	size_t *actual_buffer;
+	unsigned int next_ring_head;
+	int retval;
+
+	if (urb->status) {
+		if (urb->status == -ENOENT ||
+		    urb->status == -ECONNRESET ||
+		    urb->status == -ESHUTDOWN) {
+			goto exit;
+		} else {
+			dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
+				 __FUNCTION__, urb->status);
+			goto resubmit; /* maybe we can recover */
+		}
+	}
+
+	if (urb->actual_length > 0) {
+		next_ring_head = (dev->ring_head+1) % ring_buffer_size;
+		if (next_ring_head != dev->ring_tail) {
+			actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_head*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
+			/* actual_buffer gets urb->actual_length + interrupt_in_buffer */
+			*actual_buffer = urb->actual_length;
+			memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
+			dev->ring_head = next_ring_head;
+			dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
+				 __FUNCTION__, urb->actual_length);
+		} else
+			dev_warn(&dev->intf->dev,
+				 "Ring buffer overflow, %d bytes dropped\n",
+				 urb->actual_length);
+	}
+
+resubmit:
+	/* resubmit if we're still running */
+	if (dev->interrupt_in_running && dev->intf) {
+		retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
+		if (retval)
+			dev_err(&dev->intf->dev,
+				"usb_submit_urb failed (%d)\n", retval);
+	}
+
+exit:
+	dev->interrupt_in_done = 1;
+	wake_up_interruptible(&dev->read_wait);
+}
+
+/**
+ *	ld_usb_interrupt_out_callback
+ */
+static void ld_usb_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct ld_usb *dev = urb->context;
+
+	/* sync/async unlink faults aren't errors */
+	if (urb->status && !(urb->status == -ENOENT ||
+			     urb->status == -ECONNRESET ||
+			     urb->status == -ESHUTDOWN))
+		dbg_info(&dev->intf->dev,
+			 "%s - nonzero write interrupt status received: %d\n",
+			 __FUNCTION__, urb->status);
+
+	dev->interrupt_out_busy = 0;
+	wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ *	ld_usb_open
+ */
+static int ld_usb_open(struct inode *inode, struct file *file)
+{
+	struct ld_usb *dev;
+	int subminor;
+	int retval = 0;
+	struct usb_interface *interface;
+
+	nonseekable_open(inode, file);
+	subminor = iminor(inode);
+
+	down(&disconnect_sem);
+
+	interface = usb_find_interface(&ld_usb_driver, subminor);
+
+	if (!interface) {
+		err("%s - error, can't find device for minor %d\n",
+		     __FUNCTION__, subminor);
+		retval = -ENODEV;
+		goto unlock_disconnect_exit;
+	}
+
+	dev = usb_get_intfdata(interface);
+
+	if (!dev) {
+		retval = -ENODEV;
+		goto unlock_disconnect_exit;
+	}
+
+	/* lock this device */
+	if (down_interruptible(&dev->sem)) {
+		retval = -ERESTARTSYS;
+		goto unlock_disconnect_exit;
+	}
+
+	/* allow opening only once */
+	if (dev->open_count) {
+		retval = -EBUSY;
+		goto unlock_exit;
+	}
+	dev->open_count = 1;
+
+	/* initialize in direction */
+	dev->ring_head = 0;
+	dev->ring_tail = 0;
+	usb_fill_int_urb(dev->interrupt_in_urb,
+			 interface_to_usbdev(interface),
+			 usb_rcvintpipe(interface_to_usbdev(interface),
+					dev->interrupt_in_endpoint->bEndpointAddress),
+			 dev->interrupt_in_buffer,
+			 dev->interrupt_in_endpoint_size,
+			 ld_usb_interrupt_in_callback,
+			 dev,
+			 dev->interrupt_in_interval);
+
+	dev->interrupt_in_running = 1;
+	dev->interrupt_in_done = 0;
+
+	retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+	if (retval) {
+		dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval);
+		dev->interrupt_in_running = 0;
+		dev->open_count = 0;
+		goto unlock_exit;
+	}
+
+	/* save device in the file's private structure */
+	file->private_data = dev;
+
+unlock_exit:
+	up(&dev->sem);
+
+unlock_disconnect_exit:
+	up(&disconnect_sem);
+
+	return retval;
+}
+
+/**
+ *	ld_usb_release
+ */
+static int ld_usb_release(struct inode *inode, struct file *file)
+{
+	struct ld_usb *dev;
+	int retval = 0;
+
+	dev = file->private_data;
+
+	if (dev == NULL) {
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	if (down_interruptible(&dev->sem)) {
+		retval = -ERESTARTSYS;
+		goto exit;
+	}
+
+	if (dev->open_count != 1) {
+		retval = -ENODEV;
+		goto unlock_exit;
+	}
+	if (dev->intf == NULL) {
+		/* the device was unplugged before the file was released */
+		up(&dev->sem);
+		/* unlock here as ld_usb_delete frees dev */
+		ld_usb_delete(dev);
+		goto exit;
+	}
+
+	/* wait until write transfer is finished */
+	if (dev->interrupt_out_busy)
+		wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
+	ld_usb_abort_transfers(dev);
+	dev->open_count = 0;
+
+unlock_exit:
+	up(&dev->sem);
+
+exit:
+	return retval;
+}
+
+/**
+ *	ld_usb_poll
+ */
+static unsigned int ld_usb_poll(struct file *file, poll_table *wait)
+{
+	struct ld_usb *dev;
+	unsigned int mask = 0;
+
+	dev = file->private_data;
+
+	poll_wait(file, &dev->read_wait, wait);
+	poll_wait(file, &dev->write_wait, wait);
+
+	if (dev->ring_head != dev->ring_tail)
+		mask |= POLLIN | POLLRDNORM;
+	if (!dev->interrupt_out_busy)
+		mask |= POLLOUT | POLLWRNORM;
+
+	return mask;
+}
+
+/**
+ *	ld_usb_read
+ */
+static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
+			   loff_t *ppos)
+{
+	struct ld_usb *dev;
+	size_t *actual_buffer;
+	size_t bytes_to_read;
+	int retval = 0;
+
+	dev = file->private_data;
+
+	/* verify that we actually have some data to read */
+	if (count == 0)
+		goto exit;
+
+	/* lock this object */
+	if (down_interruptible(&dev->sem)) {
+		retval = -ERESTARTSYS;
+		goto exit;
+	}
+
+	/* verify that the device wasn't unplugged */
+	if (dev->intf == NULL) {
+		retval = -ENODEV;
+		err("No device or device unplugged %d\n", retval);
+		goto unlock_exit;
+	}
+
+	/* wait for data */
+	if (dev->ring_head == dev->ring_tail) {
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto unlock_exit;
+		}
+		retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
+		if (retval < 0)
+			goto unlock_exit;
+	}
+
+	/* actual_buffer contains actual_length + interrupt_in_buffer */
+	actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
+	bytes_to_read = min(count, *actual_buffer);
+	if (bytes_to_read < *actual_buffer)
+		dev_warn(&dev->intf->dev, "Read buffer overflow, %d bytes dropped\n",
+			 *actual_buffer-bytes_to_read);
+
+	/* copy one interrupt_in_buffer from ring_buffer into userspace */
+	if (copy_to_user(buffer, actual_buffer+1, bytes_to_read)) {
+		retval = -EFAULT;
+		goto unlock_exit;
+	}
+	dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
+
+	retval = bytes_to_read;
+
+unlock_exit:
+	/* unlock the device */
+	up(&dev->sem);
+
+exit:
+	return retval;
+}
+
+/**
+ *	ld_usb_write
+ */
+static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
+			    size_t count, loff_t *ppos)
+{
+	struct ld_usb *dev;
+	size_t bytes_to_write;
+	int retval = 0;
+
+	dev = file->private_data;
+
+	/* verify that we actually have some data to write */
+	if (count == 0)
+		goto exit;
+
+	/* lock this object */
+	if (down_interruptible(&dev->sem)) {
+		retval = -ERESTARTSYS;
+		goto exit;
+	}
+
+	/* verify that the device wasn't unplugged */
+	if (dev->intf == NULL) {
+		retval = -ENODEV;
+		err("No device or device unplugged %d\n", retval);
+		goto unlock_exit;
+	}
+
+	/* wait until previous transfer is finished */
+	if (dev->interrupt_out_busy) {
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto unlock_exit;
+		}
+		retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy);
+		if (retval < 0) {
+			goto unlock_exit;
+		}
+	}
+
+	/* write the data into interrupt_out_buffer from userspace */
+	bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
+	if (bytes_to_write < count)
+		dev_warn(&dev->intf->dev, "Write buffer overflow, %d bytes dropped\n",count-bytes_to_write);
+	dbg_info(&dev->intf->dev, "%s: count = %d, bytes_to_write = %d\n", __FUNCTION__, count, bytes_to_write);
+
+	if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+		retval = -EFAULT;
+		goto unlock_exit;
+	}
+
+	if (dev->interrupt_out_endpoint == NULL) {
+		/* try HID_REQ_SET_REPORT=9 on control_endpoint instead of interrupt_out_endpoint */
+		retval = usb_control_msg(interface_to_usbdev(dev->intf),
+					 usb_sndctrlpipe(interface_to_usbdev(dev->intf), 0),
+					 9,
+					 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+					 1 << 8, 0,
+					 dev->interrupt_out_buffer,
+					 bytes_to_write,
+					 USB_CTRL_SET_TIMEOUT * HZ);
+		if (retval < 0)
+			err("Couldn't submit HID_REQ_SET_REPORT %d\n", retval);
+		goto unlock_exit;
+	}
+
+	/* send off the urb */
+	usb_fill_int_urb(dev->interrupt_out_urb,
+			 interface_to_usbdev(dev->intf),
+			 usb_sndintpipe(interface_to_usbdev(dev->intf),
+					dev->interrupt_out_endpoint->bEndpointAddress),
+			 dev->interrupt_out_buffer,
+			 bytes_to_write,
+			 ld_usb_interrupt_out_callback,
+			 dev,
+			 dev->interrupt_out_interval);
+
+	dev->interrupt_out_busy = 1;
+	wmb();
+
+	retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+	if (retval) {
+		dev->interrupt_out_busy = 0;
+		err("Couldn't submit interrupt_out_urb %d\n", retval);
+		goto unlock_exit;
+	}
+	retval = bytes_to_write;
+
+unlock_exit:
+	/* unlock the device */
+	up(&dev->sem);
+
+exit:
+	return retval;
+}
+
+/* file operations needed when we register this driver */
+static struct file_operations ld_usb_fops = {
+	.owner =	THIS_MODULE,
+	.read  =	ld_usb_read,
+	.write =	ld_usb_write,
+	.open =		ld_usb_open,
+	.release =	ld_usb_release,
+	.poll =		ld_usb_poll,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver ld_usb_class = {
+	.name =		"ldusb%d",
+	.fops =		&ld_usb_fops,
+	.minor_base =	USB_LD_MINOR_BASE,
+};
+
+/**
+ *	ld_usb_probe
+ *
+ *	Called by the usb core when a new device is connected that it thinks
+ *	this driver might be interested in.
+ */
+static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct ld_usb *dev = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	char *buffer;
+	int i;
+	int retval = -ENOMEM;
+
+	/* allocate memory for our device state and intialize it */
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&intf->dev, "Out of memory\n");
+		goto exit;
+	}
+	memset(dev, 0x00, sizeof(*dev));
+	init_MUTEX(&dev->sem);
+	dev->intf = intf;
+	init_waitqueue_head(&dev->read_wait);
+	init_waitqueue_head(&dev->write_wait);
+
+	/* workaround for early firmware versions on fast computers */
+	if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VENDOR_ID_LD) &&
+	    ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_CASSY) ||
+	     (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) &&
+	    (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) {
+		buffer = kmalloc(256, GFP_KERNEL);
+		/* usb_string makes SETUP+STALL to leave always ControlReadLoop */
+		usb_string(udev, 255, buffer, 256);
+		kfree(buffer);
+	}
+
+	iface_desc = intf->cur_altsetting;
+
+	/* set up the endpoint information */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+			dev->interrupt_in_endpoint = endpoint;
+		}
+
+		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+			dev->interrupt_out_endpoint = endpoint;
+		}
+	}
+	if (dev->interrupt_in_endpoint == NULL) {
+		dev_err(&intf->dev, "Interrupt in endpoint not found\n");
+		goto error;
+	}
+	if (dev->interrupt_out_endpoint == NULL)
+		dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
+
+	dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+	dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL);
+	if (!dev->ring_buffer) {
+		dev_err(&intf->dev, "Couldn't allocate ring_buffer\n");
+		goto error;
+	}
+	dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
+	if (!dev->interrupt_in_buffer) {
+		dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
+		goto error;
+	}
+	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->interrupt_in_urb) {
+		dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
+		goto error;
+	}
+	dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
+									 udev->descriptor.bMaxPacketSize0;
+	dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
+	if (!dev->interrupt_out_buffer) {
+		dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n");
+		goto error;
+	}
+	dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->interrupt_out_urb) {
+		dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
+		goto error;
+	}
+	dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
+	if (dev->interrupt_out_endpoint)
+		dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
+
+	/* we can register the device now, as it is ready */
+	usb_set_intfdata(intf, dev);
+
+	retval = usb_register_dev(intf, &ld_usb_class);
+	if (retval) {
+		/* something prevented us from registering this driver */
+		dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+		usb_set_intfdata(intf, NULL);
+		goto error;
+	}
+
+	/* let the user know what node this device is now attached to */
+	dev_info(&intf->dev, "LD USB Device #%d now attached to major %d minor %d\n",
+		(intf->minor - USB_LD_MINOR_BASE), USB_MAJOR, intf->minor);
+
+exit:
+	return retval;
+
+error:
+	ld_usb_delete(dev);
+
+	return retval;
+}
+
+/**
+ *	ld_usb_disconnect
+ *
+ *	Called by the usb core when the device is removed from the system.
+ */
+static void ld_usb_disconnect(struct usb_interface *intf)
+{
+	struct ld_usb *dev;
+	int minor;
+
+	down(&disconnect_sem);
+
+	dev = usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
+
+	down(&dev->sem);
+
+	minor = intf->minor;
+
+	/* give back our minor */
+	usb_deregister_dev(intf, &ld_usb_class);
+
+	/* if the device is not opened, then we clean up right now */
+	if (!dev->open_count) {
+		up(&dev->sem);
+		ld_usb_delete(dev);
+	} else {
+		dev->intf = NULL;
+		up(&dev->sem);
+	}
+
+	up(&disconnect_sem);
+
+	dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
+		 (minor - USB_LD_MINOR_BASE));
+}
+
+/* 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,
+	.id_table =	ld_usb_table,
+};
+
+/**
+ *	ld_usb_init
+ */
+static int __init ld_usb_init(void)
+{
+	int retval;
+
+	/* register this driver with the USB subsystem */
+	retval = usb_register(&ld_usb_driver);
+	if (retval)
+		err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval);
+
+	return retval;
+}
+
+/**
+ *	ld_usb_exit
+ */
+static void __exit ld_usb_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&ld_usb_driver);
+}
+
+module_init(ld_usb_init);
+module_exit(ld_usb_exit);
+
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 755a457..26266b30 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -19,11 +19,16 @@
 #define DATA_MAX  32
 
 /*
+ * Defined by USB 2.0 clause 9.3, table 9.2.
+ */
+#define SETUP_MAX  8
+
+/*
  * This limit exists to prevent OOMs when the user process stops reading.
  */
 #define EVENT_MAX  25
 
-#define PRINTF_DFL  120
+#define PRINTF_DFL  130
 
 struct mon_event_text {
 	struct list_head e_link;
@@ -33,7 +38,9 @@
 	unsigned int tstamp;
 	int length;		/* Depends on type: xfer length or act length */
 	int status;
+	char setup_flag;
 	char data_flag;
+	unsigned char setup[SETUP_MAX];
 	unsigned char data[DATA_MAX];
 };
 
@@ -64,6 +71,22 @@
  * This is called with the whole mon_bus locked, so no additional lock.
  */
 
+static inline char mon_text_get_setup(struct mon_event_text *ep,
+    struct urb *urb, char ev_type)
+{
+
+	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
+		return '-';
+
+	if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+		return 'D';
+	if (urb->setup_packet == NULL)
+		return 'Z';	/* '0' would be not as pretty. */
+
+	memcpy(ep->setup, urb->setup_packet, SETUP_MAX);
+	return 0;
+}
+
 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
     int len, char ev_type)
 {
@@ -90,7 +113,6 @@
 
 	/*
 	 * Bulk is easy to shortcut reliably. 
-	 * XXX Control needs setup packet taken.
 	 * XXX Other pipe types need consideration. Currently, we overdo it
 	 * and collect garbage for them: better more than less.
 	 */
@@ -144,6 +166,7 @@
 	/* Collecting status makes debugging sense for submits, too */
 	ep->status = urb->status;
 
+	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
 	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
 
 	rp->nevents++;
@@ -299,10 +322,25 @@
 	default: /* PIPE_BULK */  utype = 'B';
 	}
 	cnt += snprintf(pbuf + cnt, limit - cnt,
-	    "%lx %u %c %c%c:%03u:%02u %d %d",
+	    "%lx %u %c %c%c:%03u:%02u",
 	    ep->id, ep->tstamp, ep->type,
-	    utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe),
-	    ep->status, ep->length);
+	    utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+
+	if (ep->setup_flag == 0) {   /* Setup packet is present and captured */
+		cnt += snprintf(pbuf + cnt, limit - cnt,
+		    " s %02x %02x %04x %04x %04x",
+		    ep->setup[0],
+		    ep->setup[1],
+		    (ep->setup[3] << 8) | ep->setup[2],
+		    (ep->setup[5] << 8) | ep->setup[4],
+		    (ep->setup[7] << 8) | ep->setup[6]);
+	} else if (ep->setup_flag != '-') { /* Unable to capture setup packet */
+		cnt += snprintf(pbuf + cnt, limit - cnt,
+		    " %c __ __ ____ ____ ____", ep->setup_flag);
+	} else {                     /* No setup for this kind of URB */
+		cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status);
+	}
+	cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length);
 
 	if ((data_len = ep->length) > 0) {
 		if (ep->data_flag == 0) {
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index fd6ff4c..7ffa99b 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -477,7 +477,7 @@
 }
 
 static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
-static int kaweth_resubmit_rx_urb(struct kaweth_device *, int);
+static int kaweth_resubmit_rx_urb(struct kaweth_device *, unsigned);
 
 /****************************************************************
 	int_callback
@@ -550,7 +550,7 @@
  *     kaweth_resubmit_rx_urb
  ****************************************************************/
 static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
-						int mem_flags)
+						unsigned mem_flags)
 {
 	int result;
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index d882fa3..0b03dda 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -264,16 +264,26 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.4.2"
+#define DRIVER_VERSION "v1.4.3"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
 static int debug;
 
-static struct usb_device_id id_table_sio [] = {
-	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
-	{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
-	{ }						/* Terminating entry */
+/* struct ftdi_sio_quirk is used by devices requiring special attention. */
+struct ftdi_sio_quirk {
+	void (*setup)(struct usb_serial *); /* Special settings during startup. */
+};
+
+static void  ftdi_USB_UIRT_setup	(struct usb_serial *serial);
+static void  ftdi_HE_TIRA1_setup	(struct usb_serial *serial);
+
+static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
+	.setup = ftdi_USB_UIRT_setup,
+};
+
+static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
+	.setup = ftdi_HE_TIRA1_setup,
 };
 
 /*
@@ -288,237 +298,11 @@
  * the bcdDevice value is used to differentiate FT232BM and FT245BM from
  * the earlier FT8U232AM and FT8U232BM.  For now, include all known VID/PID
  * combinations in both tables.
- * FIXME: perhaps bcdDevice can also identify 12MHz devices, but I don't know
- * if those ever went into mass production. [Ian Abbott]
+ * FIXME: perhaps bcdDevice can also identify 12MHz FT8U232AM devices,
+ * but I don't know if those ever went into mass production. [Ian Abbott]
  */
 
 
-static struct usb_device_id id_table_8U232AM [] = {
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
-	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
-	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
-	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) },
-	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID, 0, 0x3ff) },
-	{ }						/* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_FT232BM [] = {
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_PIEGROUP_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
-	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
-	{ USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID, 0x400, 0xffff) },
-	{ }						/* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_USB_UIRT [] = {
-	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
-	{ }						/* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_HE_TIRA1 [] = {
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
-	{ }						/* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_FT2232C[] = {
-	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
-	{ }						/* Terminating entry */
-};
-
 
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
@@ -540,14 +324,14 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
 	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
@@ -597,35 +381,37 @@
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
 	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
-	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_USB_UIRT_quirk },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) },
- 	{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) },
+ 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
+ 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
+ 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
+ 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) },
+ 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
  	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
  	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
@@ -642,7 +428,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
 	{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID, 0x400, 0xffff) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
 	{ }						/* Terminating entry */
 };
 
@@ -705,12 +491,8 @@
  ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
 
 /* function prototypes for a FTDI serial converter */
-static int  ftdi_SIO_startup		(struct usb_serial *serial);
-static int  ftdi_8U232AM_startup	(struct usb_serial *serial);
-static int  ftdi_FT232BM_startup	(struct usb_serial *serial);
-static int  ftdi_FT2232C_startup	(struct usb_serial *serial);
-static int  ftdi_USB_UIRT_startup	(struct usb_serial *serial);
-static int  ftdi_HE_TIRA1_startup	(struct usb_serial *serial);
+static int  ftdi_sio_probe	(struct usb_serial *serial, const struct usb_device_id *id);
+static int  ftdi_sio_attach		(struct usb_serial *serial);
 static void ftdi_shutdown		(struct usb_serial *serial);
 static int  ftdi_open			(struct usb_serial_port *port, struct file *filp);
 static void ftdi_close			(struct usb_serial_port *port, struct file *filp);
@@ -733,14 +515,16 @@
 static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
 static __u32 ftdi_232bm_baud_to_divisor (int baud);
 
-static struct usb_serial_device_type ftdi_SIO_device = {
+static struct usb_serial_device_type ftdi_sio_device = {
 	.owner =		THIS_MODULE,
-	.name =			"FTDI SIO",
-	.id_table =		id_table_sio,
+	.name =			"FTDI USB Serial Device",
+	.short_name =		"ftdi_sio",
+	.id_table =		id_table_combined,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
 	.num_bulk_out =		1,
 	.num_ports =		1,
+	.probe =		ftdi_sio_probe,
 	.open =			ftdi_open,
 	.close =		ftdi_close,
 	.throttle =		ftdi_throttle,
@@ -755,143 +539,10 @@
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_SIO_startup,
+	.attach =		ftdi_sio_attach,
 	.shutdown =		ftdi_shutdown,
 };
 
-static struct usb_serial_device_type ftdi_8U232AM_device = {
-	.owner =		THIS_MODULE,
-	.name =			"FTDI 8U232AM Compatible",
-	.id_table =		id_table_8U232AM,
-	.num_interrupt_in =	0,
-	.num_bulk_in =		1,
-	.num_bulk_out =		1,
-	.num_ports =		1,
-	.open =			ftdi_open,
-	.close =		ftdi_close,
-	.throttle =		ftdi_throttle,
-	.unthrottle =		ftdi_unthrottle,
-	.write =		ftdi_write,
-	.write_room =		ftdi_write_room,
-	.chars_in_buffer =	ftdi_chars_in_buffer,
-	.read_bulk_callback =	ftdi_read_bulk_callback,
-	.write_bulk_callback =	ftdi_write_bulk_callback,
-	.tiocmget =             ftdi_tiocmget,
-	.tiocmset =             ftdi_tiocmset,
-	.ioctl =		ftdi_ioctl,
-	.set_termios =		ftdi_set_termios,
-	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_8U232AM_startup,
-	.shutdown =		ftdi_shutdown,
-};
-
-static struct usb_serial_device_type ftdi_FT232BM_device = {
-	.owner =		THIS_MODULE,
-	.name =			"FTDI FT232BM Compatible",
-	.id_table =		id_table_FT232BM,
-	.num_interrupt_in =	0,
-	.num_bulk_in =		1,
-	.num_bulk_out =		1,
-	.num_ports =		1,
-	.open =			ftdi_open,
-	.close =		ftdi_close,
-	.throttle =		ftdi_throttle,
-	.unthrottle =		ftdi_unthrottle,
-	.write =		ftdi_write,
-	.write_room =		ftdi_write_room,
-	.chars_in_buffer =	ftdi_chars_in_buffer,
-	.read_bulk_callback =	ftdi_read_bulk_callback,
-	.write_bulk_callback =	ftdi_write_bulk_callback,
-	.tiocmget =             ftdi_tiocmget,
-	.tiocmset =             ftdi_tiocmset,
-	.ioctl =		ftdi_ioctl,
-	.set_termios =		ftdi_set_termios,
-	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_FT232BM_startup,
-	.shutdown =		ftdi_shutdown,
-};
-
-static struct usb_serial_device_type ftdi_FT2232C_device = {
-	.owner =		THIS_MODULE,
-	.name =			"FTDI FT2232C Compatible",
-	.id_table =		id_table_FT2232C,
-	.num_interrupt_in =	0,
-	.num_bulk_in =		1,
-	.num_bulk_out =		1,
-	.num_ports =		1,
-	.open =			ftdi_open,
-	.close =		ftdi_close,
-	.throttle =		ftdi_throttle,
-	.unthrottle =		ftdi_unthrottle,
-	.write =		ftdi_write,
-	.write_room =		ftdi_write_room,
-	.chars_in_buffer =	ftdi_chars_in_buffer,
-	.read_bulk_callback =	ftdi_read_bulk_callback,
-	.write_bulk_callback =	ftdi_write_bulk_callback,
-	.tiocmget =             ftdi_tiocmget,
-	.tiocmset =             ftdi_tiocmset,
-	.ioctl =		ftdi_ioctl,
-	.set_termios =		ftdi_set_termios,
-	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_FT2232C_startup,
-	.shutdown =		ftdi_shutdown,
-};
-
-static struct usb_serial_device_type ftdi_USB_UIRT_device = {
-	.owner =		THIS_MODULE,
-	.name =			"USB-UIRT Infrared Tranceiver",
-	.id_table =		id_table_USB_UIRT,
-	.num_interrupt_in =	0,
-	.num_bulk_in =		1,
-	.num_bulk_out =		1,
-	.num_ports =		1,
-	.open =			ftdi_open,
-	.close =		ftdi_close,
-	.throttle =		ftdi_throttle,
-	.unthrottle =		ftdi_unthrottle,
-	.write =		ftdi_write,
-	.write_room =		ftdi_write_room,
-	.chars_in_buffer =	ftdi_chars_in_buffer,
-	.read_bulk_callback =	ftdi_read_bulk_callback,
-	.write_bulk_callback =	ftdi_write_bulk_callback,
-	.tiocmget =             ftdi_tiocmget,
-	.tiocmset =             ftdi_tiocmset,
-	.ioctl =		ftdi_ioctl,
-	.set_termios =		ftdi_set_termios,
-	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_USB_UIRT_startup,
-	.shutdown =		ftdi_shutdown,
-};
-
-/* The TIRA1 is based on a  FT232BM which requires a fixed baud rate of 100000
- * and which requires RTS-CTS to be enabled. */
-static struct usb_serial_device_type ftdi_HE_TIRA1_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Home-Electronics TIRA-1 IR Transceiver",
-	.id_table =		id_table_HE_TIRA1,
-	.num_interrupt_in =	0,
-	.num_bulk_in =		1,
-	.num_bulk_out =		1,
-	.num_ports =		1,
-	.open =			ftdi_open,
-	.close =		ftdi_close,
-	.throttle =		ftdi_throttle,
-	.unthrottle =		ftdi_unthrottle,
-	.write =		ftdi_write,
-	.write_room =		ftdi_write_room,
-	.chars_in_buffer =	ftdi_chars_in_buffer,
-	.read_bulk_callback =	ftdi_read_bulk_callback,
-	.write_bulk_callback =	ftdi_write_bulk_callback,
-	.tiocmget =             ftdi_tiocmget,
-	.tiocmset =             ftdi_tiocmset,
-	.ioctl =		ftdi_ioctl,
-	.set_termios =		ftdi_set_termios,
-	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_HE_TIRA1_startup,
-	.shutdown =		ftdi_shutdown,
-};
-
-
 
 #define WDR_TIMEOUT 5000 /* default urb timeout */
 
@@ -1212,6 +863,59 @@
 } /* set_serial_info */
 
 
+/* Determine type of FTDI chip based on USB config and descriptor. */
+static void ftdi_determine_type(struct usb_serial_port *port)
+{
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	struct usb_serial *serial = port->serial;
+	struct usb_device *udev = serial->dev;
+	unsigned version;
+	unsigned interfaces;
+
+	/* Assume it is not the original SIO device for now. */
+	priv->baud_base = 48000000 / 16;
+	priv->write_offset = 0;
+
+	version = le16_to_cpu(udev->descriptor.bcdDevice);
+	interfaces = udev->actconfig->desc.bNumInterfaces;
+	dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __FUNCTION__,
+			version, interfaces);
+	if (interfaces > 1) {
+		int inter;
+
+		/* Multiple interfaces.  Assume FT2232C. */
+		priv->chip_type = FT2232C;
+		/* Determine interface code. */
+		inter = serial->interface->altsetting->desc.bInterfaceNumber;
+		if (inter == 0) {
+			priv->interface = PIT_SIOA;
+		} else {
+			priv->interface = PIT_SIOB;
+		}
+		/* BM-type devices have a bug where bcdDevice gets set
+		 * to 0x200 when iSerialNumber is 0.  */
+		if (version < 0x500) {
+			dbg("%s: something fishy - bcdDevice too low for multi-interface device",
+					__FUNCTION__);
+		}
+	} else if (version < 0x200) {
+		/* Old device.  Assume its the original SIO. */
+		priv->chip_type = SIO;
+		priv->baud_base = 12000000 / 16;
+		priv->write_offset = 1;
+	} else if (version < 0x400) {
+		/* Assume its an FT8U232AM (or FT8U245AM) */
+		/* (It might be a BM because of the iSerialNumber bug,
+		 * but it will still work as an AM device.) */
+		priv->chip_type = FT8U232AM;
+	} else {
+		/* Assume its an FT232BM (or FT245BM) */
+		priv->chip_type = FT232BM;
+	}
+	info("Detected %s", ftdi_chip_name[priv->chip_type]);
+}
+
+
 /*
  * ***************************************************************************
  * Sysfs Attribute
@@ -1355,12 +1059,20 @@
  * ***************************************************************************
  */
 
-/* Common startup subroutine */
-/* Called from ftdi_SIO_startup, etc. */
-static int ftdi_common_startup (struct usb_serial *serial)
+/* Probe function to check for special devices */
+static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id)
+{
+	usb_set_serial_data(serial, (void *)id->driver_info);
+
+	return (0);
+}
+
+/* attach subroutine */
+static int ftdi_sio_attach (struct usb_serial *serial)
 {
 	struct usb_serial_port *port = serial->port[0];
 	struct ftdi_private *priv;
+	struct ftdi_sio_quirk *quirk;
 	
 	dbg("%s",__FUNCTION__);
 
@@ -1400,150 +1112,49 @@
 	port->bulk_out_buffer = NULL;
 
 	usb_set_serial_port_data(serial->port[0], priv);
+
+	ftdi_determine_type (serial->port[0]);
+	create_sysfs_attrs(serial);
+
+	/* Check for device requiring special set up. */
+	quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
+	if (quirk && quirk->setup) {
+		quirk->setup(serial);
+	}
 	
 	return (0);
-}
+} /* ftdi_sio_attach */
 
 
-/* Startup for the SIO chip */
+/* Setup for the USB-UIRT device, which requires hardwired
+ * baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
-static int ftdi_SIO_startup (struct usb_serial *serial)
+static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
 {
 	struct ftdi_private *priv;
-	int err;
 
 	dbg("%s",__FUNCTION__);
 
-	err = ftdi_common_startup(serial);
-	if (err){
-		return (err);
-	}
-
-	priv = usb_get_serial_port_data(serial->port[0]);
-	priv->chip_type = SIO;
-	priv->baud_base = 12000000 / 16;
-	priv->write_offset = 1;
-	
-	return (0);
-}
-
-/* Startup for the 8U232AM chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_8U232AM_startup (struct usb_serial *serial)
-{ /* ftdi_8U232AM_startup */
-	struct ftdi_private *priv;
-	int err;
-
-	dbg("%s",__FUNCTION__);
-	err = ftdi_common_startup(serial);
-	if (err){
-		return (err);
-	}
-
-	priv = usb_get_serial_port_data(serial->port[0]);
-	priv->chip_type = FT8U232AM;
-	priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */
-	
-	create_sysfs_attrs(serial);
-	
-	return (0);
-} /* ftdi_8U232AM_startup */
-
-/* Startup for the FT232BM chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_FT232BM_startup (struct usb_serial *serial)
-{ /* ftdi_FT232BM_startup */
-	struct ftdi_private *priv;
-	int err;
-
-	dbg("%s",__FUNCTION__);
-	err = ftdi_common_startup(serial);
-	if (err){
-		return (err);
-	}
-
-	priv = usb_get_serial_port_data(serial->port[0]);
-	priv->chip_type = FT232BM;
-	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */
-	
-	create_sysfs_attrs(serial);
-
-	return (0);
-} /* ftdi_FT232BM_startup */
-
-/* Startup for the FT2232C chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_FT2232C_startup (struct usb_serial *serial)
-{ /* ftdi_FT2232C_startup */
-	struct ftdi_private *priv;
-	int err;
-	int inter;
-
-	dbg("%s",__FUNCTION__);
-	err = ftdi_common_startup(serial);
-	if (err){
-		return (err);
-	}
-
-	priv = usb_get_serial_port_data(serial->port[0]);
-	priv->chip_type = FT2232C;
-	inter = serial->interface->altsetting->desc.bInterfaceNumber;
-
-	if (inter) {
-		priv->interface = PIT_SIOB;
-	}
-	else  {
-		priv->interface = PIT_SIOA;
-	}
-	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
-	
-	create_sysfs_attrs(serial);
-
-	return (0);
-} /* ftdi_FT2232C_startup */
-
-/* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */
-/* Called from usbserial:serial_probe */
-static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
-{ /* ftdi_USB_UIRT_startup */
-	struct ftdi_private *priv;
-	int err;
-
-	dbg("%s",__FUNCTION__);
-	err = ftdi_8U232AM_startup(serial);
-	if (err){
-		return (err);
-	}
-
 	priv = usb_get_serial_port_data(serial->port[0]);
 	priv->flags |= ASYNC_SPD_CUST;
 	priv->custom_divisor = 77;
 	priv->force_baud = B38400;
-	
-	return (0);
-} /* ftdi_USB_UIRT_startup */
+} /* ftdi_USB_UIRT_setup */
 
-/* Startup for the HE-TIRA1 device, which requires hardwired
- * baudrate (38400 gets mapped to 100000) */
-static int ftdi_HE_TIRA1_startup (struct usb_serial *serial)
-{ /* ftdi_HE_TIRA1_startup */
+/* Setup for the HE-TIRA1 device, which requires hardwired
+ * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
+static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
+{
 	struct ftdi_private *priv;
-	int err;
 
 	dbg("%s",__FUNCTION__);
-	err = ftdi_FT232BM_startup(serial);
-	if (err){
-		return (err);
-	}
 
 	priv = usb_get_serial_port_data(serial->port[0]);
 	priv->flags |= ASYNC_SPD_CUST;
 	priv->custom_divisor = 240;
 	priv->force_baud = B38400;
 	priv->force_rtscts = 1;
-	
-	return (0);
-} /* ftdi_HE_TIRA1_startup */
+} /* ftdi_HE_TIRA1_setup */
 
 
 /* ftdi_shutdown is called from usbserial:usb_serial_disconnect 
@@ -2367,60 +1978,11 @@
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-	int  ret, mask;
-	
 	dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
 
 	/* Based on code from acm.c and others */
 	switch (cmd) {
 
-	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
-		dbg("%s TIOCMBIS", __FUNCTION__);
- 	        if (get_user(mask, (unsigned long __user *) arg))
-			return -EFAULT;
-  	        if (mask & TIOCM_DTR){
-			if ((ret = set_dtr(port, HIGH)) < 0) {
-				err("Urb to set DTR failed");
-				return(ret);
-			}
-		}
-		if (mask & TIOCM_RTS) {
-			if ((ret = set_rts(port, HIGH)) < 0){
-				err("Urb to set RTS failed");
-				return(ret);
-			}
-		}
-		return(0);
-		break;
-
-	case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
-		dbg("%s TIOCMBIC", __FUNCTION__);
- 	        if (get_user(mask, (unsigned long __user *) arg))
-			return -EFAULT;
-  	        if (mask & TIOCM_DTR){
-			if ((ret = set_dtr(port, LOW)) < 0){
-				err("Urb to unset DTR failed");
-				return(ret);
-			}
-		}	
-		if (mask & TIOCM_RTS) {
-			if ((ret = set_rts(port, LOW)) < 0){
-				err("Urb to unset RTS failed");
-				return(ret);
-			}
-		}
-		return(0);
-		break;
-
-		/*
-		 * I had originally implemented TCSET{A,S}{,F,W} and
-		 * TCGET{A,S} here separately, however when testing I
-		 * found that the higher layers actually do the termios
-		 * conversions themselves and pass the call onto
-		 * ftdi_sio_set_termios. 
-		 *
-		 */
-
 	case TIOCGSERIAL: /* gets serial port data */
 		return get_serial_info(port, (struct serial_struct __user *) arg);
 
@@ -2516,24 +2078,9 @@
 	int retval;
 
 	dbg("%s", __FUNCTION__);
-	retval = usb_serial_register(&ftdi_SIO_device);
+	retval = usb_serial_register(&ftdi_sio_device);
 	if (retval)
-		goto failed_SIO_register;
-	retval = usb_serial_register(&ftdi_8U232AM_device);
-	if (retval)
-		goto failed_8U232AM_register;
-	retval = usb_serial_register(&ftdi_FT232BM_device);
-	if (retval)
-		goto failed_FT232BM_register;
-	retval = usb_serial_register(&ftdi_FT2232C_device);
-	if (retval)
-		goto failed_FT2232C_register;
-	retval = usb_serial_register(&ftdi_USB_UIRT_device);
-	if (retval)
-		goto failed_USB_UIRT_register;
-	retval = usb_serial_register(&ftdi_HE_TIRA1_device);
-	if (retval)
-		goto failed_HE_TIRA1_register;
+		goto failed_sio_register;
 	retval = usb_register(&ftdi_driver);
 	if (retval) 
 		goto failed_usb_register;
@@ -2541,18 +2088,8 @@
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 	return 0;
 failed_usb_register:
-	usb_serial_deregister(&ftdi_HE_TIRA1_device);
-failed_HE_TIRA1_register:
-	usb_serial_deregister(&ftdi_USB_UIRT_device);
-failed_USB_UIRT_register:
-	usb_serial_deregister(&ftdi_FT2232C_device);
-failed_FT2232C_register:
-	usb_serial_deregister(&ftdi_FT232BM_device);
-failed_FT232BM_register:
-	usb_serial_deregister(&ftdi_8U232AM_device);
-failed_8U232AM_register:
-	usb_serial_deregister(&ftdi_SIO_device);
-failed_SIO_register:
+	usb_serial_deregister(&ftdi_sio_device);
+failed_sio_register:
 	return retval;
 }
 
@@ -2563,12 +2100,7 @@
 	dbg("%s", __FUNCTION__);
 
 	usb_deregister (&ftdi_driver);
-	usb_serial_deregister (&ftdi_HE_TIRA1_device);
-	usb_serial_deregister (&ftdi_USB_UIRT_device);
-	usb_serial_deregister (&ftdi_FT2232C_device);
-	usb_serial_deregister (&ftdi_FT232BM_device);
-	usb_serial_deregister (&ftdi_8U232AM_device);
-	usb_serial_deregister (&ftdi_SIO_device);
+	usb_serial_deregister (&ftdi_sio_device);
 
 }
 
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 9fcc7bd..bd0ab30 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -697,7 +697,7 @@
 UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100, 
 		"Microtech",
 		"USB-SCSI-HD50",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
 #ifdef CONFIG_USB_STORAGE_DPCM
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index cd4e06b..041ab8c 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -81,7 +81,6 @@
 
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
-extern int assign_irq_vector_nopanic (int irq); /* allocate a free vector without panic */
 extern int assign_irq_vector (int irq);	/* allocate a free vector */
 extern void free_irq_vector (int vector);
 extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 9902185c..1df1c9f 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -16,7 +16,6 @@
 #define _ASM_IA64_SN_XP_H
 
 
-#include <linux/version.h>
 #include <linux/cache.h>
 #include <linux/hardirq.h>
 #include <asm/sn/types.h>
diff --git a/include/asm-sparc64/seccomp.h b/include/asm-sparc64/seccomp.h
new file mode 100644
index 0000000..7fcd996
--- /dev/null
+++ b/include/asm-sparc64/seccomp.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h> /* already defines TIF_32BIT */
+
+#ifndef TIF_32BIT
+#error "unexpected TIF_32BIT on sparc64"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-v850/checksum.h b/include/asm-v850/checksum.h
index d3aedb7b..4df5e710 100644
--- a/include/asm-v850/checksum.h
+++ b/include/asm-v850/checksum.h
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/checksum.h -- Checksum ops
  *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,2005  NEC Corporation
+ *  Copyright (C) 2001,2005  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -36,8 +36,8 @@
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-extern unsigned csum_partial_copy (const char *src, char *dst, int len,
-				   unsigned sum);
+extern unsigned csum_partial_copy (const unsigned char *src,
+				   unsigned char *dst, int len, unsigned sum);
 
 
 /*
@@ -46,7 +46,8 @@
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-extern unsigned csum_partial_copy_from_user (const char *src, char *dst,
+extern unsigned csum_partial_copy_from_user (const unsigned char *src,
+					     unsigned char *dst,
 					     int len, unsigned sum,
 					     int *csum_err);
 
diff --git a/include/asm-v850/mmu.h b/include/asm-v850/mmu.h
index e30a52b..267768c 100644
--- a/include/asm-v850/mmu.h
+++ b/include/asm-v850/mmu.h
@@ -1,22 +1,11 @@
-/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
+/* Copyright (C) 2002, 2005, David McCullough <davidm@snapgear.com> */
 
 #ifndef __V850_MMU_H__
 #define __V850_MMU_H__
 
-struct mm_rblock_struct {
-	int		size;
-	int		refcount;
-	void	*kblock;
-};
-
-struct mm_tblock_struct {
-	struct mm_rblock_struct	*rblock;
-	struct mm_tblock_struct	*next;
-};
-
 typedef struct {
-	struct mm_tblock_struct	tblock;
-	unsigned long			end_brk;
+	struct vm_list_struct	*vmlist;
+	unsigned long		end_brk;
 } mm_context_t;
 
 #endif /* __V850_MMU_H__ */
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index cf3847e..ce8518e 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -33,7 +33,7 @@
 				   unsigned short type, void *daddr,
 				   void *saddr, unsigned len);
 extern int		eth_rebuild_header(struct sk_buff *skb);
-extern unsigned short	eth_type_trans(struct sk_buff *skb, struct net_device *dev);
+extern __be16		eth_type_trans(struct sk_buff *skb, struct net_device *dev);
 extern void		eth_header_cache_update(struct hh_cache *hh, struct net_device *dev,
 						unsigned char * haddr);
 extern int		eth_header_cache(struct neighbour *neigh,
diff --git a/include/linux/fddidevice.h b/include/linux/fddidevice.h
index 002f636..e61e42d 100644
--- a/include/linux/fddidevice.h
+++ b/include/linux/fddidevice.h
@@ -25,7 +25,7 @@
 #include <linux/if_fddi.h>
 
 #ifdef __KERNEL__
-extern unsigned short	fddi_type_trans(struct sk_buff *skb,
+extern __be16	fddi_type_trans(struct sk_buff *skb,
 				struct net_device *dev);
 extern struct net_device *alloc_fddidev(int sizeof_priv);
 #endif
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index ed2927e..df695e9a 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -242,8 +242,8 @@
 }
 
 
-static __inline__ unsigned short hdlc_type_trans(struct sk_buff *skb,
-						 struct net_device *dev)
+static __inline__ __be16 hdlc_type_trans(struct sk_buff *skb,
+					 struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 27e4d16..2f0c085 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -16,6 +16,7 @@
 #define NETLINK_AUDIT		9	/* auditing */
 #define NETLINK_FIB_LOOKUP	10	
 #define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
+#define NETLINK_NETFILTER	12	/* netfilter subsystem */
 #define NETLINK_IP6_FW		13
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
 #define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index eb282b5..7246377 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -938,17 +938,17 @@
 }
 
 extern void usb_init_urb(struct urb *urb);
-extern struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
+extern struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags);
 extern void usb_free_urb(struct urb *urb);
 #define usb_put_urb usb_free_urb
 extern struct urb *usb_get_urb(struct urb *urb);
-extern int usb_submit_urb(struct urb *urb, int mem_flags);
+extern int usb_submit_urb(struct urb *urb, unsigned mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
 #define HAVE_USB_BUFFERS
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
-	int mem_flags, dma_addr_t *dma);
+	unsigned mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
 	void *addr, dma_addr_t dma);
 
@@ -1055,7 +1055,7 @@
 	struct scatterlist	*sg,
 	int			nents,
 	size_t			length,
-	int			mem_flags
+	unsigned		mem_flags
 );
 void usb_sg_cancel (struct usb_sg_request *io);
 void usb_sg_wait (struct usb_sg_request *io);
diff --git a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h
index f22d6be..ba617c3 100644
--- a/include/linux/usb_cdc.h
+++ b/include/linux/usb_cdc.h
@@ -34,6 +34,7 @@
 #define USB_CDC_ACM_TYPE		0x02		/* acm_descriptor */
 #define USB_CDC_UNION_TYPE		0x06		/* union_desc */
 #define USB_CDC_COUNTRY_TYPE		0x07
+#define USB_CDC_NETWORK_TERMINAL_TYPE	0x0a		/* network_terminal_desc */
 #define USB_CDC_ETHERNET_TYPE		0x0f		/* ether_desc */
 #define USB_CDC_WHCM_TYPE		0x11
 #define USB_CDC_MDLM_TYPE		0x12		/* mdlm_desc */
@@ -83,6 +84,18 @@
 	/* ... and there could be other slave interfaces */
 } __attribute__ ((packed));
 
+/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */
+struct usb_cdc_network_terminal_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__u8	bEntityId;
+	__u8	iName;
+	__u8	bChannelIndex;
+	__u8	bPhysicalInterface;
+} __attribute__ ((packed));
+
 /* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
 struct usb_cdc_ether_desc {
 	__u8	bLength;
diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
index b00f127..71e6086 100644
--- a/include/linux/usb_gadget.h
+++ b/include/linux/usb_gadget.h
@@ -107,18 +107,18 @@
 	int (*disable) (struct usb_ep *ep);
 
 	struct usb_request *(*alloc_request) (struct usb_ep *ep,
-		int gfp_flags);
+		unsigned gfp_flags);
 	void (*free_request) (struct usb_ep *ep, struct usb_request *req);
 
 	void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
-		dma_addr_t *dma, int gfp_flags);
+		dma_addr_t *dma, unsigned gfp_flags);
 	void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
 		unsigned bytes);
 	// NOTE:  on 2.6, drivers may also use dma_map() and
 	// dma_sync_single_*() to directly manage dma overhead. 
 
 	int (*queue) (struct usb_ep *ep, struct usb_request *req,
-		int gfp_flags);
+		unsigned gfp_flags);
 	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
 
 	int (*set_halt) (struct usb_ep *ep, int value);
@@ -214,7 +214,7 @@
  * Returns the request, or null if one could not be allocated.
  */
 static inline struct usb_request *
-usb_ep_alloc_request (struct usb_ep *ep, int gfp_flags)
+usb_ep_alloc_request (struct usb_ep *ep, unsigned gfp_flags)
 {
 	return ep->ops->alloc_request (ep, gfp_flags);
 }
@@ -254,7 +254,7 @@
  */
 static inline void *
 usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
-	int gfp_flags)
+	unsigned gfp_flags)
 {
 	return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
 }
@@ -330,7 +330,7 @@
  * reported when the usb peripheral is disconnected.
  */
 static inline int
-usb_ep_queue (struct usb_ep *ep, struct usb_request *req, int gfp_flags)
+usb_ep_queue (struct usb_ep *ep, struct usb_request *req, unsigned gfp_flags)
 {
 	return ep->ops->queue (ep, req, gfp_flags);
 }
diff --git a/include/linux/wanrouter.h b/include/linux/wanrouter.h
index 3e89f0f..1b6b76a 100644
--- a/include/linux/wanrouter.h
+++ b/include/linux/wanrouter.h
@@ -516,8 +516,7 @@
 /* Public functions available for device drivers */
 extern int register_wan_device(struct wan_device *wandev);
 extern int unregister_wan_device(char *name);
-unsigned short wanrouter_type_trans(struct sk_buff *skb,
-				    struct net_device *dev);
+__be16 wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev);
 int wanrouter_encapsulate(struct sk_buff *skb, struct net_device *dev,
 			  unsigned short type);
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ef27381..4a26adf 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -125,7 +125,8 @@
  */
 extern struct sock *sctp_get_ctl_sock(void);
 extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
-				     sctp_scope_t, int gfp, int flags);
+				     sctp_scope_t, unsigned int __nocast gfp,
+				     int flags);
 extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
 extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
 
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 88d9fe5..58462164 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -181,17 +181,17 @@
 int sctp_chunk_iif(const struct sctp_chunk *);
 struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *,
 					     struct sctp_chunk *,
-					     int gfp);
+					     unsigned int __nocast gfp);
 __u32 sctp_generate_verification_tag(void);
 void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
 
 /* Prototypes for chunk-building functions.  */
 struct sctp_chunk *sctp_make_init(const struct sctp_association *,
 			     const struct sctp_bind_addr *,
-			     int gfp, int vparam_len);
+			     unsigned int __nocast gfp, int vparam_len);
 struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *,
 				 const struct sctp_chunk *,
-				 const int gfp,
+				 const unsigned int __nocast gfp,
 				 const int unkparam_len);
 struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *,
 				    const struct sctp_chunk *);
@@ -265,7 +265,7 @@
                struct sctp_endpoint *,
                struct sctp_association *asoc,
                void *event_arg,
-               int gfp);
+	       unsigned int __nocast gfp);
 
 /* 2nd level prototypes */
 void sctp_generate_t3_rtx_event(unsigned long peer);
@@ -275,7 +275,8 @@
 
 struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
 				       const struct sctp_association *,
-				       struct sctp_chunk *, int gfp, int *err,
+				       struct sctp_chunk *,
+				       unsigned int __nocast gfp, int *err,
 				       struct sctp_chunk **err_chk_p);
 int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
 			   struct sockaddr_storage*, int);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7435528..994009b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -445,7 +445,8 @@
 	int malloced;
 };
 
-struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp);
+struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
+				    unsigned int __nocast gfp);
 void sctp_ssnmap_free(struct sctp_ssnmap *map);
 void sctp_ssnmap_clear(struct sctp_ssnmap *map);
 
@@ -945,7 +946,8 @@
 	} cacc;
 };
 
-struct sctp_transport *sctp_transport_new(const union sctp_addr *, int);
+struct sctp_transport *sctp_transport_new(const union sctp_addr *,
+					  unsigned int __nocast);
 void sctp_transport_set_owner(struct sctp_transport *,
 			      struct sctp_association *);
 void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
@@ -1093,9 +1095,10 @@
 void sctp_bind_addr_free(struct sctp_bind_addr *);
 int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
 			const struct sctp_bind_addr *src,
-			sctp_scope_t scope, int gfp,int flags);
+			sctp_scope_t scope, unsigned int __nocast gfp,
+			int flags);
 int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
-		       int gfp);
+		       unsigned int __nocast gfp);
 int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
 int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
 			 struct sctp_sock *);
@@ -1104,9 +1107,10 @@
 					int			addrcnt,
 					struct sctp_sock	*opt);
 union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
-					 int *addrs_len, int gfp);
+					 int *addrs_len,
+					 unsigned int __nocast gfp);
 int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
-			   __u16 port, int gfp);
+			   __u16 port, unsigned int __nocast gfp);
 
 sctp_scope_t sctp_scope(const union sctp_addr *);
 int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
@@ -1235,7 +1239,7 @@
 }
 
 /* These are function signatures for manipulating endpoints.  */
-struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
+struct sctp_endpoint *sctp_endpoint_new(struct sock *, unsigned int __nocast);
 void sctp_endpoint_free(struct sctp_endpoint *);
 void sctp_endpoint_put(struct sctp_endpoint *);
 void sctp_endpoint_hold(struct sctp_endpoint *);
@@ -1256,7 +1260,7 @@
 		     struct sctp_chunk **err_chunk);
 int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
 		      const union sctp_addr *peer,
-		      sctp_init_chunk_t *init, int gfp);
+		      sctp_init_chunk_t *init, unsigned int __nocast gfp);
 __u32 sctp_generate_tag(const struct sctp_endpoint *);
 __u32 sctp_generate_tsn(const struct sctp_endpoint *);
 
@@ -1719,7 +1723,7 @@
 
 struct sctp_association *
 sctp_association_new(const struct sctp_endpoint *, const struct sock *,
-		     sctp_scope_t scope, int gfp);
+		     sctp_scope_t scope, unsigned int __nocast gfp);
 void sctp_association_free(struct sctp_association *);
 void sctp_association_put(struct sctp_association *);
 void sctp_association_hold(struct sctp_association *);
@@ -1735,7 +1739,7 @@
 			    const union sctp_addr *laddr);
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
 				     const union sctp_addr *address,
-				     const int gfp,
+				     const unsigned int __nocast gfp,
 				     const int peer_state);
 void sctp_assoc_del_peer(struct sctp_association *asoc,
 			 const union sctp_addr *addr);
@@ -1759,9 +1763,11 @@
 void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned);
 void sctp_assoc_set_primary(struct sctp_association *,
 			    struct sctp_transport *);
-int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, int);
+int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *,
+				     unsigned int __nocast);
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
-					 struct sctp_cookie*, int gfp);
+					 struct sctp_cookie*,
+					 unsigned int __nocast gfp);
 
 int sctp_cmp_addr_exact(const union sctp_addr *ss1,
 			const union sctp_addr *ss2);
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 1019d83..90fe4bf 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -88,7 +88,7 @@
 	__u16 error,
 	__u16 outbound,
 	__u16 inbound,
-	int gfp);
+	unsigned int __nocast gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
 	const struct sctp_association *asoc,
@@ -96,35 +96,35 @@
 	int flags,
 	int state,
 	int error,
-	int gfp);
+	unsigned int __nocast gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
 	const struct sctp_association *asoc,
 	struct sctp_chunk *chunk,
 	__u16 flags,
-	int gfp);
+	unsigned int __nocast gfp);
 struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
 	const struct sctp_association *asoc,
 	struct sctp_chunk *chunk,
 	__u16 flags,
 	__u32 error,
-	int gfp);
+	unsigned int __nocast gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
 	const struct sctp_association *asoc,
 	__u16 flags,
-	int gfp);
+	unsigned int __nocast gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
 	const struct sctp_association *asoc,
-	__u32 indication, int gfp);
+	__u32 indication, unsigned int __nocast gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
-	const struct sctp_association *asoc, int gfp);
+	const struct sctp_association *asoc, unsigned int __nocast gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
 	struct sctp_chunk *chunk,
-	int gfp);
+	unsigned int __nocast gfp);
 
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 	struct msghdr *);
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index 961736d..1a60c6d 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -62,19 +62,22 @@
 void sctp_ulpq_free(struct sctp_ulpq *);
 
 /* Add a new DATA chunk for processing. */
-int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *, int);
+int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *,
+			unsigned int __nocast);
 
 /* Add a new event for propagation to the ULP. */
 int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
 
 /* Renege previously received chunks.  */
-void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, int);
+void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *,
+		      unsigned int __nocast);
 
 /* Perform partial delivery. */
-void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, int);
+void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *,
+				unsigned int __nocast);
 
 /* Abort the partial delivery. */
-void sctp_ulpq_abort_pd(struct sctp_ulpq *, int);
+void sctp_ulpq_abort_pd(struct sctp_ulpq *, unsigned int __nocast);
 
 /* Clear the partial data delivery condition on this socket. */
 int sctp_clear_pd(struct sock *sk);
diff --git a/include/net/x25device.h b/include/net/x25device.h
index cf36a20..d45ae88 100644
--- a/include/net/x25device.h
+++ b/include/net/x25device.h
@@ -5,8 +5,7 @@
 #include <linux/if_packet.h>
 #include <linux/skbuff.h>
 
-static inline unsigned short x25_type_trans(struct sk_buff *skb,
-					    struct net_device *dev)
+static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	skb->mac.raw = skb->data;
 	skb->input_dev = skb->dev = dev;
diff --git a/net/802/fddi.c b/net/802/fddi.c
index ebcf483..5ce24c4 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -122,10 +122,10 @@
  * the proper pointer to the start of packet data (skb->data).
  */
  
-unsigned short fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
+__be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fddihdr *fddi = (struct fddihdr *)skb->data;
-	unsigned short type;
+	__be16 type;
 	
 	/*
 	 * Set mac.raw field to point to FC byte, set data field to point
diff --git a/net/8021q/Kconfig b/net/8021q/Kconfig
new file mode 100644
index 0000000..c4a382e
--- /dev/null
+++ b/net/8021q/Kconfig
@@ -0,0 +1,19 @@
+#
+# Configuration for 802.1Q VLAN support
+#
+
+config VLAN_8021Q
+	tristate "802.1Q VLAN Support"
+	---help---
+	  Select this and you will be able to create 802.1Q VLAN interfaces
+	  on your ethernet interfaces.  802.1Q VLAN supports almost
+	  everything a regular ethernet interface does, including
+	  firewalling, bridging, and of course IP traffic.  You will need
+	  the 'vconfig' tool from the VLAN project in order to effectively
+	  use VLANs.  See the VLAN web page for more information:
+	  <http://www.candelatech.com/~greear/vlan.html>
+
+	  To compile this code as a module, choose M here: the module
+	  will be called 8021q.
+
+	  If unsure, say N.
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 1f6d316..91e412b 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -578,6 +578,14 @@
 			if (!vlandev)
 				continue;
 
+			if (netif_carrier_ok(dev)) {
+				if (!netif_carrier_ok(vlandev))
+					netif_carrier_on(vlandev);
+			} else {
+				if (netif_carrier_ok(vlandev))
+					netif_carrier_off(vlandev);
+			}
+
 			if ((vlandev->state & VLAN_LINK_STATE_MASK) != flgs) {
 				vlandev->state = (vlandev->state &~ VLAN_LINK_STATE_MASK) 
 					| flgs;
diff --git a/net/Kconfig b/net/Kconfig
index 9251b28..2684e80 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -2,7 +2,7 @@
 # Network configuration
 #
 
-menu "Networking support"
+menu "Networking"
 
 config NET
 	bool "Networking support"
@@ -10,7 +10,9 @@
 	  Unless you really know what you are doing, you should say Y here.
 	  The reason is that some programs need kernel networking support even
 	  when running on a stand-alone machine that isn't connected to any
-	  other computer. If you are upgrading from an older kernel, you
+	  other computer.
+	  
+	  If you are upgrading from an older kernel, you
 	  should consider updating your networking tools too because changes
 	  in the kernel and the tools often go hand in hand. The tools are
 	  contained in the package net-tools, the location and version number
@@ -20,57 +22,14 @@
 	  recommended to read the NET-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
+# Make sure that all config symbols are dependent on NET
+if NET
+
 menu "Networking options"
-	depends on NET
 
-config PACKET
-	tristate "Packet socket"
-	---help---
-	  The Packet protocol is used by applications which communicate
-	  directly with network devices without an intermediate network
-	  protocol implemented in the kernel, e.g. tcpdump.  If you want them
-	  to work, choose Y.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called af_packet.
-
-	  If unsure, say Y.
-
-config PACKET_MMAP
-	bool "Packet socket: mmapped IO"
-	depends on PACKET
-	help
-	  If you say Y here, the Packet protocol driver will use an IO
-	  mechanism that results in faster communication.
-
-	  If unsure, say N.
-
-config UNIX
-	tristate "Unix domain sockets"
-	---help---
-	  If you say Y here, you will include support for Unix domain sockets;
-	  sockets are the standard Unix mechanism for establishing and
-	  accessing network connections.  Many commonly used programs such as
-	  the X Window system and syslog use these sockets even if your
-	  machine is not connected to any network.  Unless you are working on
-	  an embedded system or something similar, you therefore definitely
-	  want to say Y here.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called unix.  Note that several important services won't work
-	  correctly if you say M here and then neglect to load the module.
-
-	  Say Y unless you know what you are doing.
-
-config NET_KEY
-	tristate "PF_KEY sockets"
-	select XFRM
-	---help---
-	  PF_KEYv2 socket family, compatible to KAME ones.
-	  They are required if you are going to use IPsec tools ported
-	  from KAME.
-
-	  Say Y unless you know what you are doing.
+source "net/packet/Kconfig"
+source "net/unix/Kconfig"
+source "net/xfrm/Kconfig"
 
 config INET
 	bool "TCP/IP networking"
@@ -94,30 +53,12 @@
 
 	  Short answer: say Y.
 
+if INET
 source "net/ipv4/Kconfig"
-
-#   IPv6 as module will cause a CRASH if you try to unload it
-config IPV6
-	tristate "The IPv6 protocol"
-	depends on INET
-	default m
-	select CRYPTO if IPV6_PRIVACY
-	select CRYPTO_MD5 if IPV6_PRIVACY
-	---help---
-	  This is complemental support for the IP version 6.
-	  You will still be able to do traditional IPv4 networking as well.
-
-	  For general information about IPv6, see
-	  <http://playground.sun.com/pub/ipng/html/ipng-main.html>.
-	  For Linux IPv6 development information, see <http://www.linux-ipv6.org>.
-	  For specific information about IPv6 under Linux, read the HOWTO at
-	  <http://www.bieringer.de/linux/IPv6/>.
-
-	  To compile this protocol support as a module, choose M here: the 
-	  module will be called ipv6.
-
 source "net/ipv6/Kconfig"
 
+endif # if INET
+
 menuconfig NETFILTER
 	bool "Network packet filtering (replaces ipchains)"
 	---help---
@@ -206,269 +147,16 @@
 
 endif
 
-config XFRM
-       bool
-       depends on NET
-
-source "net/xfrm/Kconfig"
-
 source "net/sctp/Kconfig"
-
-config ATM
-	tristate "Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  ATM is a high-speed networking technology for Local Area Networks
-	  and Wide Area Networks.  It uses a fixed packet size and is
-	  connection oriented, allowing for the negotiation of minimum
-	  bandwidth requirements.
-
-	  In order to participate in an ATM network, your Linux box needs an
-	  ATM networking card. If you have that, say Y here and to the driver
-	  of your ATM card below.
-
-	  Note that you need a set of user-space programs to actually make use
-	  of ATM.  See the file <file:Documentation/networking/atm.txt> for
-	  further details.
-
-config ATM_CLIP
-	tristate "Classical IP over ATM (EXPERIMENTAL)"
-	depends on ATM && INET
-	help
-	  Classical IP over ATM for PVCs and SVCs, supporting InARP and
-	  ATMARP. If you want to communication with other IP hosts on your ATM
-	  network, you will typically either say Y here or to "LAN Emulation
-	  (LANE)" below.
-
-config ATM_CLIP_NO_ICMP
-	bool "Do NOT send ICMP if no neighbour (EXPERIMENTAL)"
-	depends on ATM_CLIP
-	help
-	  Normally, an "ICMP host unreachable" message is sent if a neighbour
-	  cannot be reached because there is no VC to it in the kernel's
-	  ATMARP table. This may cause problems when ATMARP table entries are
-	  briefly removed during revalidation. If you say Y here, packets to
-	  such neighbours are silently discarded instead.
-
-config ATM_LANE
-	tristate "LAN Emulation (LANE) support (EXPERIMENTAL)"
-	depends on ATM
-	help
-	  LAN Emulation emulates services of existing LANs across an ATM
-	  network. Besides operating as a normal ATM end station client, Linux
-	  LANE client can also act as an proxy client bridging packets between
-	  ELAN and Ethernet segments. You need LANE if you want to try MPOA.
-
-config ATM_MPOA
-	tristate "Multi-Protocol Over ATM (MPOA) support (EXPERIMENTAL)"
-	depends on ATM && INET && ATM_LANE!=n
-	help
-	  Multi-Protocol Over ATM allows ATM edge devices such as routers,
-	  bridges and ATM attached hosts establish direct ATM VCs across
-	  subnetwork boundaries. These shortcut connections bypass routers
-	  enhancing overall network performance.
-
-config ATM_BR2684
-	tristate "RFC1483/2684 Bridged protocols"
-	depends on ATM && INET
-	help
-	  ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483)
-	  This device will act like an ethernet from the kernels point of view,
-	  with the traffic being carried by ATM PVCs (currently 1 PVC/device).
-	  This is sometimes used over DSL lines.  If in doubt, say N.
-
-config ATM_BR2684_IPFILTER
-	bool "Per-VC IP filter kludge"
-	depends on ATM_BR2684
-	help
-	  This is an experimental mechanism for users who need to terminating a
-	  large number of IP-only vcc's.  Do not enable this unless you are sure
-	  you know what you are doing.
-
-config BRIDGE
-	tristate "802.1d Ethernet Bridging"
-	---help---
-	  If you say Y here, then your Linux box will be able to act as an
-	  Ethernet bridge, which means that the different Ethernet segments it
-	  is connected to will appear as one Ethernet to the participants.
-	  Several such bridges can work together to create even larger
-	  networks of Ethernets using the IEEE 802.1 spanning tree algorithm.
-	  As this is a standard, Linux bridges will cooperate properly with
-	  other third party bridge products.
-
-	  In order to use the Ethernet bridge, you'll need the bridge
-	  configuration tools; see <file:Documentation/networking/bridge.txt>
-	  for location. Please read the Bridge mini-HOWTO for more
-	  information.
-
-	  If you enable iptables support along with the bridge support then you
-	  turn your bridge into a bridging IP firewall.
-	  iptables will then see the IP packets being bridged, so you need to
-	  take this into account when setting up your firewall rules.
-	  Enabling arptables support when bridging will let arptables see
-	  bridged ARP traffic in the arptables FORWARD chain.
-
-	  To compile this code as a module, choose M here: the module
-	  will be called bridge.
-
-	  If unsure, say N.
-
-config VLAN_8021Q
-	tristate "802.1Q VLAN Support"
-	---help---
-	  Select this and you will be able to create 802.1Q VLAN interfaces
-	  on your ethernet interfaces.  802.1Q VLAN supports almost
-	  everything a regular ethernet interface does, including
-	  firewalling, bridging, and of course IP traffic.  You will need
-	  the 'vconfig' tool from the VLAN project in order to effectively
-	  use VLANs.  See the VLAN web page for more information:
-	  <http://www.candelatech.com/~greear/vlan.html>
-
-	  To compile this code as a module, choose M here: the module
-	  will be called 8021q.
-
-	  If unsure, say N.
-
-config DECNET
-	tristate "DECnet Support"
-	---help---
-	  The DECnet networking protocol was used in many products made by
-	  Digital (now Compaq).  It provides reliable stream and sequenced
-	  packet communications over which run a variety of services similar
-	  to those which run over TCP/IP.
-
-	  To find some tools to use with the kernel layer support, please
-	  look at Patrick Caulfield's web site:
-	  <http://linux-decnet.sourceforge.net/>.
-
-	  More detailed documentation is available in
-	  <file:Documentation/networking/decnet.txt>.
-
-	  Be sure to say Y to "/proc file system support" and "Sysctl support"
-	  below when using DECnet, since you will need sysctl support to aid
-	  in configuration at run time.
-
-	  The DECnet code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module is called decnet.
-
+source "net/atm/Kconfig"
+source "net/bridge/Kconfig"
+source "net/8021q/Kconfig"
 source "net/decnet/Kconfig"
-
 source "net/llc/Kconfig"
-
-config IPX
-	tristate "The IPX protocol"
-	select LLC
-	---help---
-	  This is support for the Novell networking protocol, IPX, commonly
-	  used for local networks of Windows machines.  You need it if you
-	  want to access Novell NetWare file or print servers using the Linux
-	  Novell client ncpfs (available from
-	  <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
-	  within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
-	  available from <http://www.tldp.org/docs.html#howto>).  In order
-	  to do the former, you'll also have to say Y to "NCP file system
-	  support", below.
-
-	  IPX is similar in scope to IP, while SPX, which runs on top of IPX,
-	  is similar to TCP. There is also experimental support for SPX in
-	  Linux (see "SPX networking", below).
-
-	  To turn your Linux box into a fully featured NetWare file server and
-	  IPX router, say Y here and fetch either lwared from
-	  <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
-	  mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
-	  information, read the IPX-HOWTO available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  General information about how to connect Linux, Windows machines and
-	  Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
-
-	  The IPX driver would enlarge your kernel by about 16 KB. To compile
-	  this driver as a module, choose M here: the module will be called ipx.
-	  Unless you want to integrate your Linux box with a local Novell
-	  network, say N.
-
 source "net/ipx/Kconfig"
-
-config ATALK
-	tristate "Appletalk protocol support"
-	select LLC
-	---help---
-	  AppleTalk is the protocol that Apple computers can use to communicate
-	  on a network.  If your Linux box is connected to such a network and you
-	  wish to connect to it, say Y.  You will need to use the netatalk package
-	  so that your Linux box can act as a print and file server for Macs as
-	  well as access AppleTalk printers.  Check out
-	  <http://www.zettabyte.net/netatalk/> on the WWW for details.
-	  EtherTalk is the name used for AppleTalk over Ethernet and the
-	  cheaper and slower LocalTalk is AppleTalk over a proprietary Apple
-	  network using serial links.  EtherTalk and LocalTalk are fully
-	  supported by Linux.
-
-	  General information about how to connect Linux, Windows machines and
-	  Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.  The
-	  NET-3-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information as well.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called appletalk. You almost certainly want to compile it as a
-	  module so you can restart your AppleTalk stack without rebooting
-	  your machine. I hear that the GNU boycott of Apple is over, so
-	  even politically correct people are allowed to say Y here.
-
 source "drivers/net/appletalk/Kconfig"
-
-config X25
-	tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  X.25 is a set of standardized network protocols, similar in scope to
-	  frame relay; the one physical line from your box to the X.25 network
-	  entry point can carry several logical point-to-point connections
-	  (called "virtual circuits") to other computers connected to the X.25
-	  network. Governments, banks, and other organizations tend to use it
-	  to connect to each other or to form Wide Area Networks (WANs). Many
-	  countries have public X.25 networks. X.25 consists of two
-	  protocols: the higher level Packet Layer Protocol (PLP) (say Y here
-	  if you want that) and the lower level data link layer protocol LAPB
-	  (say Y to "LAPB Data Link Driver" below if you want that).
-
-	  You can read more about X.25 at <http://www.sangoma.com/x25.htm> and
-	  <http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/cbook/cx25.htm>.
-	  Information about X.25 for Linux is contained in the files
-	  <file:Documentation/networking/x25.txt> and
-	  <file:Documentation/networking/x25-iface.txt>.
-
-	  One connects to an X.25 network either with a dedicated network card
-	  using the X.21 protocol (not yet supported by Linux) or one can do
-	  X.25 over a standard telephone line using an ordinary modem (say Y
-	  to "X.25 async driver" below) or over Ethernet using an ordinary
-	  Ethernet card and the LAPB over Ethernet (say Y to "LAPB Data Link
-	  Driver" and "LAPB over Ethernet driver" below).
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called x25. If unsure, say N.
-
-config LAPB
-	tristate "LAPB Data Link Driver (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  Link Access Procedure, Balanced (LAPB) is the data link layer (i.e.
-	  the lower) part of the X.25 protocol. It offers a reliable
-	  connection service to exchange data frames with one other host, and
-	  it is used to transport higher level protocols (mostly X.25 Packet
-	  Layer, the higher part of X.25, but others are possible as well).
-	  Usually, LAPB is used with specialized X.21 network cards, but Linux
-	  currently supports LAPB only over Ethernet connections. If you want
-	  to use LAPB connections over Ethernet, say Y here and to "LAPB over
-	  Ethernet driver" below. Read
-	  <file:Documentation/networking/lapb-module.txt> for technical
-	  details.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called lapb.  If unsure, say N.
+source "net/x25/Kconfig"
+source "net/lapb/Kconfig"
 
 config NET_DIVERT
 	bool "Frame Diverter (EXPERIMENTAL)"
@@ -496,107 +184,10 @@
 
 	  If unsure, say N.
 
-config ECONET
-	tristate "Acorn Econet/AUN protocols (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && INET
-	---help---
-	  Econet is a fairly old and slow networking protocol mainly used by
-	  Acorn computers to access file and print servers. It uses native
-	  Econet network cards. AUN is an implementation of the higher level
-	  parts of Econet that runs over ordinary Ethernet connections, on
-	  top of the UDP packet protocol, which in turn runs on top of the
-	  Internet protocol IP.
-
-	  If you say Y here, you can choose with the next two options whether
-	  to send Econet/AUN traffic over a UDP Ethernet connection or over
-	  a native Econet network card.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called econet.
-
-config ECONET_AUNUDP
-	bool "AUN over UDP"
-	depends on ECONET
-	help
-	  Say Y here if you want to send Econet/AUN traffic over a UDP
-	  connection (UDP is a packet based protocol that runs on top of the
-	  Internet protocol IP) using an ordinary Ethernet network card.
-
-config ECONET_NATIVE
-	bool "Native Econet"
-	depends on ECONET
-	help
-	  Say Y here if you have a native Econet network card installed in
-	  your computer.
-
-config WAN_ROUTER
-	tristate "WAN router"
-	depends on EXPERIMENTAL
-	---help---
-	  Wide Area Networks (WANs), such as X.25, frame relay and leased
-	  lines, are used to interconnect Local Area Networks (LANs) over vast
-	  distances with data transfer rates significantly higher than those
-	  achievable with commonly used asynchronous modem connections.
-	  Usually, a quite expensive external device called a `WAN router' is
-	  needed to connect to a WAN.
-
-	  As an alternative, WAN routing can be built into the Linux kernel.
-	  With relatively inexpensive WAN interface cards available on the
-	  market, a perfectly usable router can be built for less than half
-	  the price of an external router.  If you have one of those cards and
-	  wish to use your Linux box as a WAN router, say Y here and also to
-	  the WAN driver for your card, below.  You will then need the
-	  wan-tools package which is available from <ftp://ftp.sangoma.com/>.
-	  Read <file:Documentation/networking/wan-router.txt> for more
-	  information.
-
-	  To compile WAN routing support as a module, choose M here: the
-	  module will be called wanrouter.
-
-	  If unsure, say N.
-
-menu "QoS and/or fair queueing"
-
-config NET_SCHED
-	bool "QoS and/or fair queueing"
-	---help---
-	  When the kernel has several packets to send out over a network
-	  device, it has to decide which ones to send first, which ones to
-	  delay, and which ones to drop. This is the job of the packet
-	  scheduler, and several different algorithms for how to do this
-	  "fairly" have been proposed.
-
-	  If you say N here, you will get the standard packet scheduler, which
-	  is a FIFO (first come, first served). If you say Y here, you will be
-	  able to choose from among several alternative algorithms which can
-	  then be attached to different network devices. This is useful for
-	  example if some of your network devices are real time devices that
-	  need a certain minimum data flow rate, or if you need to limit the
-	  maximum data flow rate for traffic which matches specified criteria.
-	  This code is considered to be experimental.
-
-	  To administer these schedulers, you'll need the user-level utilities
-	  from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>.
-	  That package also contains some documentation; for more, check out
-	  <http://snafu.freedom.org/linux2.2/iproute-notes.html>.
-
-	  This Quality of Service (QoS) support will enable you to use
-	  Differentiated Services (diffserv) and Resource Reservation Protocol
-	  (RSVP) on your Linux router if you also say Y to "QoS support",
-	  "Packet classifier API" and to some classifiers below. Documentation
-	  and software is at <http://diffserv.sourceforge.net/>.
-
-	  If you say Y here and to "/proc file system" below, you will be able
-	  to read status information about packet schedulers from the file
-	  /proc/net/psched.
-
-	  The available schedulers are listed in the following questions; you
-	  can say Y to as many as you like. If unsure, say N now.
-
+source "net/econet/Kconfig"
+source "net/wanrouter/Kconfig"
 source "net/sched/Kconfig"
 
-endmenu
-
 menu "Network testing"
 
 config NET_PKTGEN
@@ -635,12 +226,9 @@
 	def_bool NETPOLL
 
 source "net/ax25/Kconfig"
-
 source "net/irda/Kconfig"
-
 source "net/bluetooth/Kconfig"
 
-source "drivers/net/Kconfig"
-
-endmenu
+endif   # if NET
+endmenu # Networking
 
diff --git a/net/atm/Kconfig b/net/atm/Kconfig
new file mode 100644
index 0000000..bea2426
--- /dev/null
+++ b/net/atm/Kconfig
@@ -0,0 +1,74 @@
+#
+# Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)
+#
+
+config ATM
+	tristate "Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	---help---
+	  ATM is a high-speed networking technology for Local Area Networks
+	  and Wide Area Networks.  It uses a fixed packet size and is
+	  connection oriented, allowing for the negotiation of minimum
+	  bandwidth requirements.
+
+	  In order to participate in an ATM network, your Linux box needs an
+	  ATM networking card. If you have that, say Y here and to the driver
+	  of your ATM card below.
+
+	  Note that you need a set of user-space programs to actually make use
+	  of ATM.  See the file <file:Documentation/networking/atm.txt> for
+	  further details.
+
+config ATM_CLIP
+	tristate "Classical IP over ATM (EXPERIMENTAL)"
+	depends on ATM && INET
+	help
+	  Classical IP over ATM for PVCs and SVCs, supporting InARP and
+	  ATMARP. If you want to communication with other IP hosts on your ATM
+	  network, you will typically either say Y here or to "LAN Emulation
+	  (LANE)" below.
+
+config ATM_CLIP_NO_ICMP
+	bool "Do NOT send ICMP if no neighbour (EXPERIMENTAL)"
+	depends on ATM_CLIP
+	help
+	  Normally, an "ICMP host unreachable" message is sent if a neighbour
+	  cannot be reached because there is no VC to it in the kernel's
+	  ATMARP table. This may cause problems when ATMARP table entries are
+	  briefly removed during revalidation. If you say Y here, packets to
+	  such neighbours are silently discarded instead.
+
+config ATM_LANE
+	tristate "LAN Emulation (LANE) support (EXPERIMENTAL)"
+	depends on ATM
+	help
+	  LAN Emulation emulates services of existing LANs across an ATM
+	  network. Besides operating as a normal ATM end station client, Linux
+	  LANE client can also act as an proxy client bridging packets between
+	  ELAN and Ethernet segments. You need LANE if you want to try MPOA.
+
+config ATM_MPOA
+	tristate "Multi-Protocol Over ATM (MPOA) support (EXPERIMENTAL)"
+	depends on ATM && INET && ATM_LANE!=n
+	help
+	  Multi-Protocol Over ATM allows ATM edge devices such as routers,
+	  bridges and ATM attached hosts establish direct ATM VCs across
+	  subnetwork boundaries. These shortcut connections bypass routers
+	  enhancing overall network performance.
+
+config ATM_BR2684
+	tristate "RFC1483/2684 Bridged protocols"
+	depends on ATM && INET
+	help
+	  ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483)
+	  This device will act like an ethernet from the kernels point of view,
+	  with the traffic being carried by ATM PVCs (currently 1 PVC/device).
+	  This is sometimes used over DSL lines.  If in doubt, say N.
+
+config ATM_BR2684_IPFILTER
+	bool "Per-VC IP filter kludge"
+	depends on ATM_BR2684
+	help
+	  This is an experimental mechanism for users who need to terminating a
+	  large number of IP-only vcc's.  Do not enable this unless you are sure
+	  you know what you are doing.
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index e6954cf..289956c 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -289,8 +289,7 @@
  * This is similar to eth_type_trans, which cannot be used because of
  * our dev->hard_header_len
  */
-static inline unsigned short br_type_trans(struct sk_buff *skb,
-					       struct net_device *dev)
+static inline __be16 br_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig
new file mode 100644
index 0000000..db23d59
--- /dev/null
+++ b/net/bridge/Kconfig
@@ -0,0 +1,31 @@
+#
+# 802.1d Ethernet Bridging
+#
+
+config BRIDGE
+	tristate "802.1d Ethernet Bridging"
+	---help---
+	  If you say Y here, then your Linux box will be able to act as an
+	  Ethernet bridge, which means that the different Ethernet segments it
+	  is connected to will appear as one Ethernet to the participants.
+	  Several such bridges can work together to create even larger
+	  networks of Ethernets using the IEEE 802.1 spanning tree algorithm.
+	  As this is a standard, Linux bridges will cooperate properly with
+	  other third party bridge products.
+
+	  In order to use the Ethernet bridge, you'll need the bridge
+	  configuration tools; see <file:Documentation/networking/bridge.txt>
+	  for location. Please read the Bridge mini-HOWTO for more
+	  information.
+
+	  If you enable iptables support along with the bridge support then you
+	  turn your bridge into a bridging IP firewall.
+	  iptables will then see the IP packets being bridged, so you need to
+	  take this into account when setting up your firewall rules.
+	  Enabling arptables support when bridging will let arptables see
+	  bridged ARP traffic in the arptables FORWARD chain.
+
+	  To compile this code as a module, choose M here: the module
+	  will be called bridge.
+
+	  If unsure, say N.
diff --git a/net/decnet/Kconfig b/net/decnet/Kconfig
index 2101da5..92f2ec46 100644
--- a/net/decnet/Kconfig
+++ b/net/decnet/Kconfig
@@ -1,6 +1,29 @@
 #
 # DECnet configuration
 #
+config DECNET
+	tristate "DECnet Support"
+	---help---
+	  The DECnet networking protocol was used in many products made by
+	  Digital (now Compaq).  It provides reliable stream and sequenced
+	  packet communications over which run a variety of services similar
+	  to those which run over TCP/IP.
+
+	  To find some tools to use with the kernel layer support, please
+	  look at Patrick Caulfield's web site:
+	  <http://linux-decnet.sourceforge.net/>.
+
+	  More detailed documentation is available in
+	  <file:Documentation/networking/decnet.txt>.
+
+	  Be sure to say Y to "/proc file system support" and "Sysctl support"
+	  below when using DECnet, since you will need sysctl support to aid
+	  in configuration at run time.
+
+	  The DECnet code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module is called decnet.
+
 config DECNET_ROUTER
 	bool "DECnet: router support (EXPERIMENTAL)"
 	depends on DECNET && EXPERIMENTAL
diff --git a/net/econet/Kconfig b/net/econet/Kconfig
new file mode 100644
index 0000000..39a2d29
--- /dev/null
+++ b/net/econet/Kconfig
@@ -0,0 +1,36 @@
+#
+# Acorn Econet/AUN protocols 
+#
+
+config ECONET
+	tristate "Acorn Econet/AUN protocols (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && INET
+	---help---
+	  Econet is a fairly old and slow networking protocol mainly used by
+	  Acorn computers to access file and print servers. It uses native
+	  Econet network cards. AUN is an implementation of the higher level
+	  parts of Econet that runs over ordinary Ethernet connections, on
+	  top of the UDP packet protocol, which in turn runs on top of the
+	  Internet protocol IP.
+
+	  If you say Y here, you can choose with the next two options whether
+	  to send Econet/AUN traffic over a UDP Ethernet connection or over
+	  a native Econet network card.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called econet.
+
+config ECONET_AUNUDP
+	bool "AUN over UDP"
+	depends on ECONET
+	help
+	  Say Y here if you want to send Econet/AUN traffic over a UDP
+	  connection (UDP is a packet based protocol that runs on top of the
+	  Internet protocol IP) using an ordinary Ethernet network card.
+
+config ECONET_NATIVE
+	bool "Native Econet"
+	depends on ECONET
+	help
+	  Say Y here if you have a native Econet network card installed in
+	  your computer.
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index ab60ea6..f6dbfb9 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -155,7 +155,7 @@
  *	This is normal practice and works for any 'now in use' protocol.
  */
  
-unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 3e63123..df538688 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -3,7 +3,6 @@
 #
 config IP_MULTICAST
 	bool "IP: multicasting"
-	depends on INET
 	help
 	  This is code for addressing several networked computers at once,
 	  enlarging your kernel by about 2 KB. You need multicasting if you
@@ -17,7 +16,6 @@
 
 config IP_ADVANCED_ROUTER
 	bool "IP: advanced router"
-	depends on INET
 	---help---
 	  If you intend to run your Linux box mostly as a router, i.e. as a
 	  computer that forwards and redistributes network packets, say Y; you
@@ -183,7 +181,6 @@
 
 config IP_PNP
 	bool "IP: kernel level autoconfiguration"
-	depends on INET
 	help
 	  This enables automatic configuration of IP addresses of devices and
 	  of the routing table during kernel boot, based on either information
@@ -242,7 +239,6 @@
 #   bool '    IP: ARP support' CONFIG_IP_PNP_ARP		
 config NET_IPIP
 	tristate "IP: tunneling"
-	depends on INET
 	select INET_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
@@ -260,7 +256,6 @@
 
 config NET_IPGRE
 	tristate "IP: GRE tunnels over IP"
-	depends on INET
 	select XFRM
 	help
 	  Tunneling means encapsulating data of one protocol type within
@@ -319,7 +314,7 @@
 
 config ARPD
 	bool "IP: ARP daemon support (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	---help---
 	  Normally, the kernel maintains an internal cache which maps IP
 	  addresses to hardware addresses on the local network, so that
@@ -344,7 +339,6 @@
 
 config SYN_COOKIES
 	bool "IP: TCP syncookie support (disabled per default)"
-	depends on INET
 	---help---
 	  Normal TCP/IP networking is open to an attack known as "SYN
 	  flooding". This denial-of-service attack prevents legitimate remote
@@ -381,7 +375,6 @@
 
 config INET_AH
 	tristate "IP: AH transformation"
-	depends on INET
 	select XFRM
 	select CRYPTO
 	select CRYPTO_HMAC
@@ -394,7 +387,6 @@
 
 config INET_ESP
 	tristate "IP: ESP transformation"
-	depends on INET
 	select XFRM
 	select CRYPTO
 	select CRYPTO_HMAC
@@ -408,7 +400,6 @@
 
 config INET_IPCOMP
 	tristate "IP: IPComp transformation"
-	depends on INET
 	select XFRM
 	select INET_TUNNEL
 	select CRYPTO
@@ -421,7 +412,6 @@
 
 config INET_TUNNEL
 	tristate "IP: tunnel transformation"
-	depends on INET
 	select XFRM
 	---help---
 	  Support for generic IP tunnel transformation, which is required by
@@ -431,7 +421,6 @@
 
 config IP_TCPDIAG
 	tristate "IP: TCP socket monitoring interface"
-	depends on INET
 	default y
 	---help---
 	  Support for TCP socket monitoring interface used by native Linux
@@ -447,7 +436,6 @@
 
 config TCP_CONG_ADVANCED
 	bool "TCP: advanced congestion control"
-	depends on INET
 	---help---
 	  Support for selection of various TCP congestion control
 	  modules.
@@ -463,7 +451,6 @@
 
 config TCP_CONG_BIC
 	tristate "Binary Increase Congestion (BIC) control"
-	depends on INET
 	default y
 	---help---
 	BIC-TCP is a sender-side only change that ensures a linear RTT
@@ -478,7 +465,6 @@
 
 config TCP_CONG_WESTWOOD
 	tristate "TCP Westwood+"
-	depends on INET
 	default m
 	---help---
 	TCP Westwood+ is a sender-side only modification of the TCP Reno
@@ -493,7 +479,6 @@
 
 config TCP_CONG_HTCP
         tristate "H-TCP"
-	depends on INET
         default m
 	---help---
 	H-TCP is a send-side only modifications of the TCP Reno
@@ -505,7 +490,7 @@
 
 config TCP_CONG_HSTCP
 	tristate "High Speed TCP"
-	depends on INET && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	default n
 	---help---
 	Sally Floyd's High Speed TCP (RFC 3649) congestion control.
@@ -516,7 +501,7 @@
 
 config TCP_CONG_HYBLA
 	tristate "TCP-Hybla congestion control algorithm"
-	depends on INET && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	default n
 	---help---
 	TCP-Hybla is a sender-side only change that eliminates penalization of
@@ -526,7 +511,7 @@
 
 config TCP_CONG_VEGAS
 	tristate "TCP Vegas"
-	depends on INET && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	default n
 	---help---
 	TCP Vegas is a sender-side only change to TCP that anticipates
@@ -537,7 +522,7 @@
 
 config TCP_CONG_SCALABLE
 	tristate "Scalable TCP"
-	depends on INET && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	default n
 	---help---
 	Scalable TCP is a sender-side only change to TCP which uses a
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 9de83e6..80d1310 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -107,7 +107,6 @@
 	newskb->pkt_type = PACKET_LOOPBACK;
 	newskb->ip_summed = CHECKSUM_UNNECESSARY;
 	BUG_TRAP(newskb->dst);
-	nf_reset(newskb);
 	netif_rx(newskb);
 	return 0;
 }
@@ -188,14 +187,6 @@
 		skb = skb2;
 	}
 
-#ifdef CONFIG_BRIDGE_NETFILTER
-	/* bridge-netfilter defers calling some IP hooks to the bridge layer
-	 * and still needs the conntrack reference.
-	 */
-	if (skb->nf_bridge == NULL)
-#endif
-		nf_reset(skb);
-
 	if (hh) {
 		int hh_alen;
 
diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
index 63a82b4..c9820bf 100644
--- a/net/ipv4/ipvs/Kconfig
+++ b/net/ipv4/ipvs/Kconfig
@@ -2,11 +2,11 @@
 # IP Virtual Server configuration
 #
 menu	"IP: Virtual Server Configuration"
-	depends on INET && NETFILTER
+	depends on NETFILTER
 
 config	IP_VS
 	tristate "IP virtual server support (EXPERIMENTAL)"
-	depends on INET && NETFILTER
+	depends on NETFILTER
 	---help---
 	  IP Virtual Server support will let you build a high-performance
 	  virtual server based on cluster of two or more real servers. This
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 9f16ab3..d0145a8 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -758,7 +758,7 @@
 	return 1;
 }
 
-
+/* Called from keventd and must protect itself from softirqs */
 void ip_vs_random_dropentry(void)
 {
 	int idx;
@@ -773,7 +773,7 @@
 		/*
 		 *  Lock is actually needed in this loop.
 		 */
-		ct_write_lock(hash);
+		ct_write_lock_bh(hash);
 
 		list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
 			if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT))
@@ -806,7 +806,7 @@
 				ip_vs_conn_expire_now(cp->control);
 			}
 		}
-		ct_write_unlock(hash);
+		ct_write_unlock_bh(hash);
 	}
 }
 
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 12a82e9..7d99ede 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -90,7 +90,8 @@
 #endif
 
 /*
- *	update_defense_level is called from keventd and from sysctl.
+ *	update_defense_level is called from keventd and from sysctl,
+ *	so it needs to protect itself from softirqs
  */
 static void update_defense_level(void)
 {
@@ -110,6 +111,8 @@
 
 	nomem = (availmem < sysctl_ip_vs_amemthresh);
 
+	local_bh_disable();
+
 	/* drop_entry */
 	spin_lock(&__ip_vs_dropentry_lock);
 	switch (sysctl_ip_vs_drop_entry) {
@@ -206,6 +209,8 @@
 	if (to_change >= 0)
 		ip_vs_protocol_timeout_change(sysctl_ip_vs_secure_tcp>1);
 	write_unlock(&__ip_vs_securetcp_lock);
+
+	local_bh_enable();
 }
 
 
@@ -1360,9 +1365,7 @@
 			/* Restore the correct value */
 			*valp = val;
 		} else {
-			local_bh_disable();
 			update_defense_level();
-			local_bh_enable();
 		}
 	}
 	return rc;
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 42dc951..1dd824f 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -432,6 +432,13 @@
 				        const struct net_device *out,
 				        int (*okfn)(struct sk_buff *))
 {
+#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
+	/* Previously seen (loopback)?  Ignore.  Do this before
+           fragment check. */
+	if ((*pskb)->nfct)
+		return NF_ACCEPT;
+#endif
+
 	/* Gather fragments. */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
 		*pskb = ip_ct_gather_frags(*pskb,
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 726ea5e..d675ff8 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1685,7 +1685,7 @@
 		printk(KERN_WARNING "martian source %u.%u.%u.%u from "
 			"%u.%u.%u.%u, on dev %s\n",
 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
-		if (dev->hard_header_len) {
+		if (dev->hard_header_len && skb->mac.raw) {
 			int i;
 			unsigned char *p = skb->mac.raw;
 			printk(KERN_WARNING "ll header: ");
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index e66ca93..95163cd 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -1,6 +1,26 @@
 #
 # IPv6 configuration
-# 
+#
+
+#   IPv6 as module will cause a CRASH if you try to unload it
+config IPV6
+	tristate "The IPv6 protocol"
+	default m
+	select CRYPTO if IPV6_PRIVACY
+	select CRYPTO_MD5 if IPV6_PRIVACY
+	---help---
+	  This is complemental support for the IP version 6.
+	  You will still be able to do traditional IPv4 networking as well.
+
+	  For general information about IPv6, see
+	  <http://playground.sun.com/pub/ipng/html/ipng-main.html>.
+	  For Linux IPv6 development information, see <http://www.linux-ipv6.org>.
+	  For specific information about IPv6 under Linux, read the HOWTO at
+	  <http://www.bieringer.de/linux/IPv6/>.
+
+	  To compile this protocol support as a module, choose M here: the 
+	  module will be called ipv6.
+
 config IPV6_PRIVACY
 	bool "IPv6: Privacy Extensions (RFC 3041) support"
 	depends on IPV6
diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig
index a16237c..980a826 100644
--- a/net/ipx/Kconfig
+++ b/net/ipx/Kconfig
@@ -1,6 +1,39 @@
 #
 # IPX configuration
 #
+config IPX
+	tristate "The IPX protocol"
+	select LLC
+	---help---
+	  This is support for the Novell networking protocol, IPX, commonly
+	  used for local networks of Windows machines.  You need it if you
+	  want to access Novell NetWare file or print servers using the Linux
+	  Novell client ncpfs (available from
+	  <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
+	  within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
+	  available from <http://www.tldp.org/docs.html#howto>).  In order
+	  to do the former, you'll also have to say Y to "NCP file system
+	  support", below.
+
+	  IPX is similar in scope to IP, while SPX, which runs on top of IPX,
+	  is similar to TCP. There is also experimental support for SPX in
+	  Linux (see "SPX networking", below).
+
+	  To turn your Linux box into a fully featured NetWare file server and
+	  IPX router, say Y here and fetch either lwared from
+	  <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
+	  mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
+	  information, read the IPX-HOWTO available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  General information about how to connect Linux, Windows machines and
+	  Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
+
+	  The IPX driver would enlarge your kernel by about 16 KB. To compile
+	  this driver as a module, choose M here: the module will be called ipx.
+	  Unless you want to integrate your Linux box with a local Novell
+	  network, say N.
+
 config IPX_INTERN
 	bool "IPX: Full internal IPX network"
 	depends on IPX
diff --git a/net/lapb/Kconfig b/net/lapb/Kconfig
new file mode 100644
index 0000000..f0b5efb
--- /dev/null
+++ b/net/lapb/Kconfig
@@ -0,0 +1,22 @@
+#
+# LAPB Data Link Drive
+#
+
+config LAPB
+	tristate "LAPB Data Link Driver (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	---help---
+	  Link Access Procedure, Balanced (LAPB) is the data link layer (i.e.
+	  the lower) part of the X.25 protocol. It offers a reliable
+	  connection service to exchange data frames with one other host, and
+	  it is used to transport higher level protocols (mostly X.25 Packet
+	  Layer, the higher part of X.25, but others are possible as well).
+	  Usually, LAPB is used with specialized X.21 network cards, but Linux
+	  currently supports LAPB only over Ethernet connections. If you want
+	  to use LAPB connections over Ethernet, say Y here and to "LAPB over
+	  Ethernet driver" below. Read
+	  <file:Documentation/networking/lapb-module.txt> for technical
+	  details.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called lapb.  If unsure, say N.
diff --git a/net/packet/Kconfig b/net/packet/Kconfig
new file mode 100644
index 0000000..34ff93f
--- /dev/null
+++ b/net/packet/Kconfig
@@ -0,0 +1,26 @@
+#
+# Packet configuration
+#
+
+config PACKET
+	tristate "Packet socket"
+	---help---
+	  The Packet protocol is used by applications which communicate
+	  directly with network devices without an intermediate network
+	  protocol implemented in the kernel, e.g. tcpdump.  If you want them
+	  to work, choose Y.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called af_packet.
+
+	  If unsure, say Y.
+
+config PACKET_MMAP
+	bool "Packet socket: mmapped IO"
+	depends on PACKET
+	help
+	  If you say Y here, the Packet protocol driver will use an IO
+	  mechanism that results in faster communication.
+
+	  If unsure, say N.
+
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 0269616..c9d5980 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -274,6 +274,9 @@
 	dst_release(skb->dst);
 	skb->dst = NULL;
 
+	/* drop conntrack reference */
+	nf_reset(skb);
+
 	spkt = (struct sockaddr_pkt*)skb->cb;
 
 	skb_push(skb, skb->data-skb->mac.raw);
@@ -517,6 +520,9 @@
 	dst_release(skb->dst);
 	skb->dst = NULL;
 
+	/* drop conntrack reference */
+	nf_reset(skb);
+
 	spin_lock(&sk->sk_receive_queue.lock);
 	po->stats.tp_packets++;
 	__skb_queue_tail(&sk->sk_receive_queue, skb);
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 7bac249..59d3e71 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -1,6 +1,43 @@
 #
 # Traffic control configuration.
 # 
+
+menuconfig NET_SCHED
+	bool "QoS and/or fair queueing"
+	---help---
+	  When the kernel has several packets to send out over a network
+	  device, it has to decide which ones to send first, which ones to
+	  delay, and which ones to drop. This is the job of the packet
+	  scheduler, and several different algorithms for how to do this
+	  "fairly" have been proposed.
+
+	  If you say N here, you will get the standard packet scheduler, which
+	  is a FIFO (first come, first served). If you say Y here, you will be
+	  able to choose from among several alternative algorithms which can
+	  then be attached to different network devices. This is useful for
+	  example if some of your network devices are real time devices that
+	  need a certain minimum data flow rate, or if you need to limit the
+	  maximum data flow rate for traffic which matches specified criteria.
+	  This code is considered to be experimental.
+
+	  To administer these schedulers, you'll need the user-level utilities
+	  from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>.
+	  That package also contains some documentation; for more, check out
+	  <http://snafu.freedom.org/linux2.2/iproute-notes.html>.
+
+	  This Quality of Service (QoS) support will enable you to use
+	  Differentiated Services (diffserv) and Resource Reservation Protocol
+	  (RSVP) on your Linux router if you also say Y to "QoS support",
+	  "Packet classifier API" and to some classifiers below. Documentation
+	  and software is at <http://diffserv.sourceforge.net/>.
+
+	  If you say Y here and to "/proc file system" below, you will be able
+	  to read status information about packet schedulers from the file
+	  /proc/net/psched.
+
+	  The available schedulers are listed in the following questions; you
+	  can say Y to as many as you like. If unsure, say N now.
+
 choice
 	prompt "Packet scheduler clock source"
 	depends on NET_SCHED
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 4b47dd6..5b24ae0 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -71,7 +71,7 @@
 					  const struct sctp_endpoint *ep,
 					  const struct sock *sk,
 					  sctp_scope_t scope,
-					  int gfp)
+					  unsigned int __nocast gfp)
 {
 	struct sctp_sock *sp;
 	int i;
@@ -272,7 +272,8 @@
 /* Allocate and initialize a new association */
 struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
 					 const struct sock *sk,
-					 sctp_scope_t scope, int gfp)
+					 sctp_scope_t scope,
+					 unsigned int __nocast gfp)
 {
 	struct sctp_association *asoc;
 
@@ -478,7 +479,7 @@
 /* Add a transport address to an association.  */
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 					   const union sctp_addr *addr,
-					   const int gfp,
+					   const unsigned int __nocast gfp,
 					   const int peer_state)
 {
 	struct sctp_transport *peer;
@@ -1229,7 +1230,8 @@
 /* Build the bind address list for the association based on info from the
  * local endpoint and the remote peer.
  */
-int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, int gfp)
+int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
+				     unsigned int __nocast gfp)
 {
 	sctp_scope_t scope;
 	int flags;
@@ -1251,7 +1253,8 @@
 
 /* Build the association's bind address list from the cookie.  */
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
-					 struct sctp_cookie *cookie, int gfp)
+					 struct sctp_cookie *cookie,
+					 unsigned int __nocast gfp)
 {
 	int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length);
 	int var_size3 = cookie->raw_addr_list_len;
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index f90eadf..f715497 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -53,7 +53,8 @@
 
 /* Forward declarations for internal helpers. */
 static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
-			      sctp_scope_t scope, int gfp, int flags);
+			      sctp_scope_t scope, unsigned int __nocast gfp,
+			      int flags);
 static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 
 /* First Level Abstractions. */
@@ -63,7 +64,8 @@
  */
 int sctp_bind_addr_copy(struct sctp_bind_addr *dest, 
 			const struct sctp_bind_addr *src,
-			sctp_scope_t scope, int gfp, int flags)
+			sctp_scope_t scope, unsigned int __nocast gfp,
+			int flags)
 {
 	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos;
@@ -144,7 +146,7 @@
 
 /* Add an address to the bind address list in the SCTP_bind_addr structure. */
 int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
-		       int gfp)
+		       unsigned int __nocast gfp)
 {
 	struct sctp_sockaddr_entry *addr;
 
@@ -197,7 +199,8 @@
  * The second argument is the return value for the length.
  */
 union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
-					 int *addrs_len, int gfp)
+					 int *addrs_len,
+					 unsigned int __nocast gfp)
 {
 	union sctp_params addrparms;
 	union sctp_params retval;
@@ -249,7 +252,7 @@
  * address parameters).
  */
 int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
-			   int addrs_len, __u16 port, int gfp)
+			   int addrs_len, __u16 port, unsigned int __nocast gfp)
 {
 	union sctp_addr_param *rawaddr;
 	struct sctp_paramhdr *param;
@@ -347,7 +350,8 @@
 /* Copy out addresses from the global local address list. */
 static int sctp_copy_one_addr(struct sctp_bind_addr *dest, 
 			      union sctp_addr *addr,
-			      sctp_scope_t scope, int gfp, int flags)
+			      sctp_scope_t scope, unsigned int __nocast gfp,
+			      int flags)
 {
 	int error = 0;
 
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 0c2ab78..61da293 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -62,7 +62,7 @@
 }
 
 /* Allocate and initialize datamsg. */
-SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(int gfp)
+SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(unsigned int __nocast gfp)
 {
 	struct sctp_datamsg *msg;
 	msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index c44bf41..e47ac0d 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -67,7 +67,8 @@
  * Initialize the base fields of the endpoint structure.
  */
 static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
-						struct sock *sk, int gfp)
+						struct sock *sk,
+						unsigned int __nocast gfp)
 {
 	struct sctp_sock *sp = sctp_sk(sk);
 	memset(ep, 0, sizeof(struct sctp_endpoint));
@@ -137,7 +138,8 @@
 /* Create a sctp_endpoint with all that boring stuff initialized.
  * Returns NULL if there isn't enough memory.
  */
-struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
+struct sctp_endpoint *sctp_endpoint_new(struct sock *sk,
+					unsigned int __nocast gfp)
 {
 	struct sctp_endpoint *ep;
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index e7f37fa..ce9245e 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -219,7 +219,7 @@
 
 /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
 int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
-			      int gfp, int copy_flags)
+			      unsigned int __nocast gfp, int copy_flags)
 {
 	struct sctp_sockaddr_entry *addr;
 	int error = 0;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 773cd93..00d32b7 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -78,7 +78,7 @@
 static int sctp_process_param(struct sctp_association *asoc,
 			      union sctp_params param,
 			      const union sctp_addr *peer_addr,
-			      int gfp);
+			      unsigned int __nocast gfp);
 
 /* What was the inbound interface for this chunk? */
 int sctp_chunk_iif(const struct sctp_chunk *chunk)
@@ -174,7 +174,7 @@
  */
 struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
 			     const struct sctp_bind_addr *bp,
-			     int gfp, int vparam_len)
+			     unsigned int __nocast gfp, int vparam_len)
 {
 	sctp_inithdr_t init;
 	union sctp_params addrs;
@@ -261,7 +261,7 @@
 
 struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
 				 const struct sctp_chunk *chunk,
-				 int gfp, int unkparam_len)
+				 unsigned int __nocast gfp, int unkparam_len)
 {
 	sctp_inithdr_t initack;
 	struct sctp_chunk *retval;
@@ -1233,7 +1233,8 @@
 
 /* Create a CLOSED association to use with an incoming packet.  */
 struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
-					struct sctp_chunk *chunk, int gfp)
+					struct sctp_chunk *chunk,
+					unsigned int __nocast gfp)
 {
 	struct sctp_association *asoc;
 	struct sk_buff *skb;
@@ -1348,7 +1349,7 @@
 struct sctp_association *sctp_unpack_cookie(
 	const struct sctp_endpoint *ep,
 	const struct sctp_association *asoc,
-	struct sctp_chunk *chunk, int gfp,
+	struct sctp_chunk *chunk, unsigned int __nocast gfp,
 	int *error, struct sctp_chunk **errp)
 {
 	struct sctp_association *retval = NULL;
@@ -1812,7 +1813,7 @@
  */
 int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
 		      const union sctp_addr *peer_addr,
-		      sctp_init_chunk_t *peer_init, int gfp)
+		      sctp_init_chunk_t *peer_init, unsigned int __nocast gfp)
 {
 	union sctp_params param;
 	struct sctp_transport *transport;
@@ -1983,7 +1984,7 @@
 static int sctp_process_param(struct sctp_association *asoc,
 			      union sctp_params param,
 			      const union sctp_addr *peer_addr,
-			      int gfp)
+			      unsigned int __nocast gfp)
 {
 	union sctp_addr addr;
 	int i;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 778639d..39c970b 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -63,7 +63,7 @@
 				void *event_arg,
 			 	sctp_disposition_t status,
 				sctp_cmd_seq_t *commands,
-				int gfp);
+				unsigned int __nocast gfp);
 static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
 			     sctp_state_t state,
 			     struct sctp_endpoint *ep,
@@ -71,7 +71,7 @@
 			     void *event_arg,
 			     sctp_disposition_t status,
 			     sctp_cmd_seq_t *commands,
-			     int gfp);
+			     unsigned int __nocast gfp);
 
 /********************************************************************
  * Helper functions
@@ -497,7 +497,8 @@
 static int sctp_cmd_process_init(sctp_cmd_seq_t *commands,
 				 struct sctp_association *asoc,
 				 struct sctp_chunk *chunk,
-				 sctp_init_chunk_t *peer_init, int gfp)
+				 sctp_init_chunk_t *peer_init,
+				 unsigned int __nocast gfp)
 {
 	int error;
 
@@ -852,7 +853,7 @@
 	       struct sctp_endpoint *ep,
 	       struct sctp_association *asoc,
 	       void *event_arg,
-	       int gfp)
+	       unsigned int __nocast gfp)
 {
 	sctp_cmd_seq_t commands;
 	const sctp_sm_table_entry_t *state_fn;
@@ -897,7 +898,7 @@
 			     void *event_arg,
 			     sctp_disposition_t status,
 			     sctp_cmd_seq_t *commands,
-			     int gfp)
+			     unsigned int __nocast gfp)
 {
 	int error;
 
@@ -985,7 +986,7 @@
 				void *event_arg,
 			 	sctp_disposition_t status,
 				sctp_cmd_seq_t *commands,
-				int gfp)
+				unsigned int __nocast gfp)
 {
 	int error = 0;
 	int force;
diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
index e627d2b..25037da 100644
--- a/net/sctp/ssnmap.c
+++ b/net/sctp/ssnmap.c
@@ -57,7 +57,8 @@
 /* Create a new sctp_ssnmap.
  * Allocate room to store at least 'len' contiguous TSNs.
  */
-struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp)
+struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
+				    unsigned int __nocast gfp)
 {
 	struct sctp_ssnmap *retval;
 	int size;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index a63b691..d2f04eb 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -57,7 +57,7 @@
 /* Initialize a new transport from provided memory.  */
 static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
 						  const union sctp_addr *addr,
-						  int gfp)
+						  unsigned int __nocast gfp)
 {
 	/* Copy in the address.  */
 	peer->ipaddr = *addr;
@@ -121,7 +121,8 @@
 }
 
 /* Allocate and initialize a new transport.  */
-struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int gfp)
+struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
+					  unsigned int __nocast gfp)
 {
         struct sctp_transport *transport;
 
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 17d0ff5..0abd510 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -74,7 +74,7 @@
 
 /* Create a new sctp_ulpevent.  */
 SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags,
-						    int gfp)
+						    unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sk_buff *skb;
@@ -136,7 +136,7 @@
 struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
 	const struct sctp_association *asoc,
 	__u16 flags, __u16 state, __u16 error, __u16 outbound,
-	__u16 inbound, int gfp)
+	__u16 inbound, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_assoc_change *sac;
@@ -237,7 +237,7 @@
 struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
 	const struct sctp_association *asoc,
 	const struct sockaddr_storage *aaddr,
-	int flags, int state, int error, int gfp)
+	int flags, int state, int error, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_paddr_change  *spc;
@@ -350,7 +350,7 @@
  */
 struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
 	const struct sctp_association *asoc, struct sctp_chunk *chunk,
-	__u16 flags, int gfp)
+	__u16 flags, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_remote_error *sre;
@@ -448,7 +448,7 @@
  */
 struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
 	const struct sctp_association *asoc, struct sctp_chunk *chunk,
-	__u16 flags, __u32 error, int gfp)
+	__u16 flags, __u32 error, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_send_failed *ssf;
@@ -557,7 +557,7 @@
  */
 struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
 	const struct sctp_association *asoc,
-	__u16 flags, int gfp)
+	__u16 flags, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_shutdown_event *sse;
@@ -620,7 +620,7 @@
  * 5.3.1.6 SCTP_ADAPTION_INDICATION
  */
 struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
-	const struct sctp_association *asoc, int gfp)
+	const struct sctp_association *asoc, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_adaption_event *sai;
@@ -657,7 +657,7 @@
  */
 struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
 						struct sctp_chunk *chunk,
-						int gfp)
+						unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event = NULL;
 	struct sk_buff *skb;
@@ -718,7 +718,8 @@
  *   various events.
  */
 struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
-	const struct sctp_association *asoc, __u32 indication, int gfp)
+	const struct sctp_association *asoc, __u32 indication,
+	unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_pdapi_event *pd;
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index d5dd2cf..8bbc279 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -100,7 +100,7 @@
 
 /* Process an incoming DATA chunk.  */
 int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
-			int gfp)
+			unsigned int __nocast gfp)
 {
 	struct sk_buff_head temp;
 	sctp_data_chunk_t *hdr;
@@ -778,7 +778,8 @@
 
 /* Partial deliver the first message as there is pressure on rwnd. */
 void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
-				struct sctp_chunk *chunk, int gfp)
+				struct sctp_chunk *chunk,
+				unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_association *asoc;
@@ -802,7 +803,7 @@
 
 /* Renege some packets to make room for an incoming chunk.  */
 void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
-		      int gfp)
+		      unsigned int __nocast gfp)
 {
 	struct sctp_association *asoc;
 	__u16 needed, freed;
@@ -841,7 +842,7 @@
 /* Notify the application if an association is aborted and in
  * partial delivery mode.  Send up any pending received messages.
  */
-void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, int gfp)
+void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, unsigned int __nocast gfp)
 {
 	struct sctp_ulpevent *ev = NULL;
 	struct sock *sk;
diff --git a/net/unix/Kconfig b/net/unix/Kconfig
new file mode 100644
index 0000000..5a69733
--- /dev/null
+++ b/net/unix/Kconfig
@@ -0,0 +1,21 @@
+#
+# Unix Domain Sockets
+#
+
+config UNIX
+	tristate "Unix domain sockets"
+	---help---
+	  If you say Y here, you will include support for Unix domain sockets;
+	  sockets are the standard Unix mechanism for establishing and
+	  accessing network connections.  Many commonly used programs such as
+	  the X Window system and syslog use these sockets even if your
+	  machine is not connected to any network.  Unless you are working on
+	  an embedded system or something similar, you therefore definitely
+	  want to say Y here.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called unix.  Note that several important services won't work
+	  correctly if you say M here and then neglect to load the module.
+
+	  Say Y unless you know what you are doing.
+
diff --git a/net/wanrouter/Kconfig b/net/wanrouter/Kconfig
new file mode 100644
index 0000000..1debe1c
--- /dev/null
+++ b/net/wanrouter/Kconfig
@@ -0,0 +1,29 @@
+#
+# Configuration for WAN router
+#
+
+config WAN_ROUTER
+	tristate "WAN router"
+	depends on EXPERIMENTAL
+	---help---
+	  Wide Area Networks (WANs), such as X.25, frame relay and leased
+	  lines, are used to interconnect Local Area Networks (LANs) over vast
+	  distances with data transfer rates significantly higher than those
+	  achievable with commonly used asynchronous modem connections.
+	  Usually, a quite expensive external device called a `WAN router' is
+	  needed to connect to a WAN.
+
+	  As an alternative, WAN routing can be built into the Linux kernel.
+	  With relatively inexpensive WAN interface cards available on the
+	  market, a perfectly usable router can be built for less than half
+	  the price of an external router.  If you have one of those cards and
+	  wish to use your Linux box as a WAN router, say Y here and also to
+	  the WAN driver for your card, below.  You will then need the
+	  wan-tools package which is available from <ftp://ftp.sangoma.com/>.
+	  Read <file:Documentation/networking/wan-router.txt> for more
+	  information.
+
+	  To compile WAN routing support as a module, choose M here: the
+	  module will be called wanrouter.
+
+	  If unsure, say N.
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index d6844ac..13b650a 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -358,10 +358,10 @@
  */
 
 
-unsigned short wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev)
+__be16 wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	int cnt = skb->data[0] ? 0 : 1;	/* there may be a pad present */
-	unsigned short ethertype;
+	__be16 ethertype;
 
 	switch (skb->data[cnt]) {
 	case NLPID_IP:		/* IP datagramm */
@@ -379,7 +379,7 @@
 				skb->data[cnt+3], dev->name);
 			return 0;
 		}
-		ethertype = *((unsigned short*)&skb->data[cnt+4]);
+		ethertype = *((__be16*)&skb->data[cnt+4]);
 		cnt += 6;
 		break;
 
diff --git a/net/x25/Kconfig b/net/x25/Kconfig
new file mode 100644
index 0000000..e6759c9
--- /dev/null
+++ b/net/x25/Kconfig
@@ -0,0 +1,36 @@
+#
+# CCITT X.25 Packet Layer
+#
+
+config X25
+	tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	---help---
+	  X.25 is a set of standardized network protocols, similar in scope to
+	  frame relay; the one physical line from your box to the X.25 network
+	  entry point can carry several logical point-to-point connections
+	  (called "virtual circuits") to other computers connected to the X.25
+	  network. Governments, banks, and other organizations tend to use it
+	  to connect to each other or to form Wide Area Networks (WANs). Many
+	  countries have public X.25 networks. X.25 consists of two
+	  protocols: the higher level Packet Layer Protocol (PLP) (say Y here
+	  if you want that) and the lower level data link layer protocol LAPB
+	  (say Y to "LAPB Data Link Driver" below if you want that).
+
+	  You can read more about X.25 at <http://www.sangoma.com/x25.htm> and
+	  <http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/cbook/cx25.htm>.
+	  Information about X.25 for Linux is contained in the files
+	  <file:Documentation/networking/x25.txt> and
+	  <file:Documentation/networking/x25-iface.txt>.
+
+	  One connects to an X.25 network either with a dedicated network card
+	  using the X.21 protocol (not yet supported by Linux) or one can do
+	  X.25 over a standard telephone line using an ordinary modem (say Y
+	  to "X.25 async driver" below) or over Ethernet using an ordinary
+	  Ethernet card and the LAPB over Ethernet (say Y to "LAPB Data Link
+	  Driver" and "LAPB over Ethernet driver" below).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called x25. If unsure, say N.
+
+
diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index 58ca6a9..0c1c043 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -1,6 +1,10 @@
 #
 # XFRM configuration
 #
+config XFRM
+       bool
+       depends on NET
+
 config XFRM_USER
 	tristate "IPsec user configuration interface"
 	depends on INET && XFRM
@@ -10,3 +14,14 @@
 
 	  If unsure, say Y.
 
+config NET_KEY
+	tristate "PF_KEY sockets"
+	select XFRM
+	---help---
+	  PF_KEYv2 socket family, compatible to KAME ones.
+	  They are required if you are going to use IPsec tools ported
+	  from KAME.
+
+	  Say Y unless you know what you are doing.
+
+