Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6

Conflicts:

	drivers/usb/input/Makefile
	drivers/usb/input/gtco.c
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 825bf88..f5de58a 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -15,7 +15,6 @@
 obj-$(CONFIG_USB_UHCI_HCD)	+= host/
 obj-$(CONFIG_USB_SL811_HCD)	+= host/
 obj-$(CONFIG_USB_U132_HCD)	+= host/
-obj-$(CONFIG_ETRAX_USB_HOST)	+= host/
 obj-$(CONFIG_USB_OHCI_AT91)	+= host/
 
 obj-$(CONFIG_USB_ACM)		+= class/
@@ -27,10 +26,7 @@
 obj-$(CONFIG_USB_ACECAD)	+= input/
 obj-$(CONFIG_USB_AIPTEK)	+= input/
 obj-$(CONFIG_USB_ATI_REMOTE)	+= input/
-obj-$(CONFIG_USB_HID)		+= input/
-obj-$(CONFIG_USB_KBD)		+= input/
 obj-$(CONFIG_USB_KBTAB)		+= input/
-obj-$(CONFIG_USB_MOUSE)		+= input/
 obj-$(CONFIG_USB_MTOUCH)	+= input/
 obj-$(CONFIG_USB_POWERMATE)	+= input/
 obj-$(CONFIG_USB_WACOM)		+= input/
@@ -51,6 +47,7 @@
 obj-$(CONFIG_USB_ADUTUX)	+= misc/
 obj-$(CONFIG_USB_APPLEDISPLAY)	+= misc/
 obj-$(CONFIG_USB_AUERSWALD)	+= misc/
+obj-$(CONFIG_USB_BERRY_CHARGE)	+= misc/
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
 obj-$(CONFIG_USB_CYTHERM)	+= misc/
 obj-$(CONFIG_USB_EMI26)		+= misc/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 3dfa3e4..30b7bfb 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan
  *  Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
+ *  Copyright (C) 2007 Simon Arlott
  *
  *  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
@@ -34,14 +35,14 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/device.h>	/* FIXME: linux/firmware.h should include it itself */
+#include <linux/device.h>
 #include <linux/firmware.h>
 #include <linux/mutex.h>
 
 #include "usbatm.h"
 
-#define DRIVER_AUTHOR	"Roman Kagan, David Woodhouse, Duncan Sands"
-#define DRIVER_VERSION	"0.2"
+#define DRIVER_AUTHOR	"Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
+#define DRIVER_VERSION	"0.3"
 #define DRIVER_DESC	"Conexant AccessRunner ADSL USB modem driver"
 
 static const char cxacru_driver_name[] = "cxacru";
@@ -64,7 +65,7 @@
 #define SDRAM_ENA	0x1
 
 #define CMD_TIMEOUT	2000	/* msecs */
-#define POLL_INTERVAL	5000	/* msecs */
+#define POLL_INTERVAL	1	/* secs */
 
 /* commands for interaction with the modem through the control channel before
  * firmware is loaded  */
@@ -146,6 +147,13 @@
 	CXINF_MAX = 0x1c,
 };
 
+enum cxacru_poll_state {
+	CXPOLL_STOPPING,
+	CXPOLL_STOPPED,
+	CXPOLL_POLLING,
+	CXPOLL_SHUTDOWN
+};
+
 struct cxacru_modem_type {
 	u32 pll_f_clk;
 	u32 pll_b_clk;
@@ -158,7 +166,12 @@
 	const struct cxacru_modem_type *modem_type;
 
 	int line_status;
+	struct mutex adsl_state_serialize;
+	int adsl_status;
 	struct delayed_work poll_work;
+	u32 card_info[CXINF_MAX];
+	struct mutex poll_state_serialize;
+	int poll_state;
 
 	/* contol handles */
 	struct mutex cm_serialize;
@@ -170,6 +183,275 @@
 	struct completion snd_done;
 };
 
+static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
+	u8 *wdata, int wsize, u8 *rdata, int rsize);
+static void cxacru_poll_status(struct work_struct *work);
+
+/* Card info exported through sysfs */
+#define CXACRU__ATTR_INIT(_name) \
+static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL)
+
+#define CXACRU_CMD_INIT(_name) \
+static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
+	cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
+
+#define CXACRU_ATTR_INIT(_value, _type, _name) \
+static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \
+	struct device_attribute *attr, char *buf) \
+{ \
+	struct usb_interface *intf = to_usb_interface(dev); \
+	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf); \
+	struct cxacru_data *instance = usbatm_instance->driver_data; \
+	return cxacru_sysfs_showattr_##_type(instance->card_info[_value], buf); \
+} \
+CXACRU__ATTR_INIT(_name)
+
+#define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name)
+#define CXACRU_CMD_CREATE(_name)          CXACRU_DEVICE_CREATE_FILE(_name)
+#define CXACRU__ATTR_CREATE(_name)        CXACRU_DEVICE_CREATE_FILE(_name)
+
+#define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name)
+#define CXACRU_CMD_REMOVE(_name)          CXACRU_DEVICE_REMOVE_FILE(_name)
+#define CXACRU__ATTR_REMOVE(_name)        CXACRU_DEVICE_REMOVE_FILE(_name)
+
+static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", value);
+}
+
+static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
+{
+	if (unlikely(value < 0)) {
+		return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
+						value / 100, -value % 100);
+	} else {
+		return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
+						value / 100, value % 100);
+	}
+}
+
+static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
+{
+	switch (value) {
+	case 0: return snprintf(buf, PAGE_SIZE, "no\n");
+	case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
+	default: return 0;
+	}
+}
+
+static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
+{
+	switch (value) {
+	case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
+	case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
+	case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
+	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
+	}
+}
+
+static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
+{
+	switch (value) {
+	case 0: return snprintf(buf, PAGE_SIZE, "down\n");
+	case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
+	case 2: return snprintf(buf, PAGE_SIZE, "training\n");
+	case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
+	case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
+	case 5: return snprintf(buf, PAGE_SIZE, "up\n");
+	case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
+	case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
+	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
+	}
+}
+
+static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
+{
+	switch (value) {
+	case 0: return 0;
+	case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
+	case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
+	case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
+	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
+	}
+}
+
+/*
+ * This could use MAC_ADDRESS_HIGH and MAC_ADDRESS_LOW, but since
+ * this data is already in atm_dev there's no point.
+ *
+ * MAC_ADDRESS_HIGH = 0x????5544
+ * MAC_ADDRESS_LOW  = 0x33221100
+ * Where 00-55 are bytes 0-5 of the MAC.
+ */
+static ssize_t cxacru_sysfs_show_mac_address(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
+	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
+
+	return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+			atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2],
+			atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);
+}
+
+static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
+	struct cxacru_data *instance = usbatm_instance->driver_data;
+	u32 value = instance->card_info[CXINF_LINE_STARTABLE];
+
+	switch (value) {
+	case 0: return snprintf(buf, PAGE_SIZE, "running\n");
+	case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
+	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
+	}
+}
+
+static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
+	struct cxacru_data *instance = usbatm_instance->driver_data;
+	int ret;
+	int poll = -1;
+	char str_cmd[8];
+	int len = strlen(buf);
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EACCES;
+
+	ret = sscanf(buf, "%7s", str_cmd);
+	if (ret != 1)
+		return -EINVAL;
+	ret = 0;
+
+	if (mutex_lock_interruptible(&instance->adsl_state_serialize))
+		return -ERESTARTSYS;
+
+	if (!strcmp(str_cmd, "stop") || !strcmp(str_cmd, "restart")) {
+		ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_STOP, NULL, 0, NULL, 0);
+		if (ret < 0) {
+			atm_err(usbatm_instance, "change adsl state:"
+				" CHIP_ADSL_LINE_STOP returned %d\n", ret);
+
+			ret = -EIO;
+		} else {
+			ret = len;
+			poll = CXPOLL_STOPPED;
+		}
+	}
+
+	/* Line status is only updated every second
+	 * and the device appears to only react to
+	 * START/STOP every second too. Wait 1.5s to
+	 * be sure that restart will have an effect. */
+	if (!strcmp(str_cmd, "restart"))
+		msleep(1500);
+
+	if (!strcmp(str_cmd, "start") || !strcmp(str_cmd, "restart")) {
+		ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
+		if (ret < 0) {
+			atm_err(usbatm_instance, "change adsl state:"
+				" CHIP_ADSL_LINE_START returned %d\n", ret);
+
+			ret = -EIO;
+		} else {
+			ret = len;
+			poll = CXPOLL_POLLING;
+		}
+	}
+
+	if (!strcmp(str_cmd, "poll")) {
+		ret = len;
+		poll = CXPOLL_POLLING;
+	}
+
+	if (ret == 0) {
+		ret = -EINVAL;
+		poll = -1;
+	}
+
+	if (poll == CXPOLL_POLLING) {
+		mutex_lock(&instance->poll_state_serialize);
+		switch (instance->poll_state) {
+		case CXPOLL_STOPPED:
+			/* start polling */
+			instance->poll_state = CXPOLL_POLLING;
+			break;
+
+		case CXPOLL_STOPPING:
+			/* abort stop request */
+			instance->poll_state = CXPOLL_POLLING;
+		case CXPOLL_POLLING:
+		case CXPOLL_SHUTDOWN:
+			/* don't start polling */
+			poll = -1;
+		}
+		mutex_unlock(&instance->poll_state_serialize);
+	} else if (poll == CXPOLL_STOPPED) {
+		mutex_lock(&instance->poll_state_serialize);
+		/* request stop */
+		if (instance->poll_state == CXPOLL_POLLING)
+			instance->poll_state = CXPOLL_STOPPING;
+		mutex_unlock(&instance->poll_state_serialize);
+	}
+
+	mutex_unlock(&instance->adsl_state_serialize);
+
+	if (poll == CXPOLL_POLLING)
+		cxacru_poll_status(&instance->poll_work.work);
+
+	return ret;
+}
+
+/*
+ * All device attributes are included in CXACRU_ALL_FILES
+ * so that the same list can be used multiple times:
+ *     INIT   (define the device attributes)
+ *     CREATE (create all the device files)
+ *     REMOVE (remove all the device files)
+ *
+ * With the last two being defined as needed in the functions
+ * they are used in before calling CXACRU_ALL_FILES()
+ */
+#define CXACRU_ALL_FILES(_action) \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_RATE,           u32,  downstream_rate); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_RATE,             u32,  upstream_rate); \
+CXACRU_ATTR_##_action(CXINF_LINK_STATUS,               LINK, link_status); \
+CXACRU_ATTR_##_action(CXINF_LINE_STATUS,               LINE, line_status); \
+CXACRU__ATTR_##_action(                                      mac_address); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_SNR_MARGIN,       dB,   upstream_snr_margin); \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_SNR_MARGIN,     dB,   downstream_snr_margin); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_ATTENUATION,      dB,   upstream_attenuation); \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_ATTENUATION,    dB,   downstream_attenuation); \
+CXACRU_ATTR_##_action(CXINF_TRANSMITTER_POWER,         s8,   transmitter_power); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_BITS_PER_FRAME,   u32,  upstream_bits_per_frame); \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_BITS_PER_FRAME, u32,  downstream_bits_per_frame); \
+CXACRU_ATTR_##_action(CXINF_STARTUP_ATTEMPTS,          u32,  startup_attempts); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_CRC_ERRORS,       u32,  upstream_crc_errors); \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_CRC_ERRORS,     u32,  downstream_crc_errors); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_FEC_ERRORS,       u32,  upstream_fec_errors); \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_FEC_ERRORS,     u32,  downstream_fec_errors); \
+CXACRU_ATTR_##_action(CXINF_UPSTREAM_HEC_ERRORS,       u32,  upstream_hec_errors); \
+CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_HEC_ERRORS,     u32,  downstream_hec_errors); \
+CXACRU_ATTR_##_action(CXINF_LINE_STARTABLE,            bool, line_startable); \
+CXACRU_ATTR_##_action(CXINF_MODULATION,                MODU, modulation); \
+CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND,              u32,  adsl_headend); \
+CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT,  u32,  adsl_headend_environment); \
+CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION,        u32,  adsl_controller_version); \
+CXACRU_CMD_##_action(                                        adsl_state);
+
+CXACRU_ALL_FILES(INIT);
+
 /* the following three functions are stolen from drivers/usb/core/message.c */
 static void cxacru_blocking_completion(struct urb *urb)
 {
@@ -347,8 +629,6 @@
 	return 0;
 }
 
-static void cxacru_poll_status(struct work_struct *work);
-
 static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
 		struct atm_dev *atm_dev)
 {
@@ -357,6 +637,7 @@
 	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
 	*/
 	int ret;
+	int start_polling = 1;
 
 	dbg("cxacru_atm_start");
 
@@ -369,14 +650,35 @@
 	}
 
 	/* start ADSL */
+	mutex_lock(&instance->adsl_state_serialize);
 	ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
 	if (ret < 0) {
 		atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
+		mutex_unlock(&instance->adsl_state_serialize);
 		return ret;
 	}
 
 	/* Start status polling */
-	cxacru_poll_status(&instance->poll_work.work);
+	mutex_lock(&instance->poll_state_serialize);
+	switch (instance->poll_state) {
+	case CXPOLL_STOPPED:
+		/* start polling */
+		instance->poll_state = CXPOLL_POLLING;
+		break;
+
+	case CXPOLL_STOPPING:
+		/* abort stop request */
+		instance->poll_state = CXPOLL_POLLING;
+	case CXPOLL_POLLING:
+	case CXPOLL_SHUTDOWN:
+		/* don't start polling */
+		start_polling = 0;
+	}
+	mutex_unlock(&instance->poll_state_serialize);
+	mutex_unlock(&instance->adsl_state_serialize);
+
+	if (start_polling)
+		cxacru_poll_status(&instance->poll_work.work);
 	return 0;
 }
 
@@ -387,14 +689,46 @@
 	u32 buf[CXINF_MAX] = {};
 	struct usbatm_data *usbatm = instance->usbatm;
 	struct atm_dev *atm_dev = usbatm->atm_dev;
+	int keep_polling = 1;
 	int ret;
 
 	ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
 	if (ret < 0) {
-		atm_warn(usbatm, "poll status: error %d\n", ret);
+		if (ret != -ESHUTDOWN)
+			atm_warn(usbatm, "poll status: error %d\n", ret);
+
+		mutex_lock(&instance->poll_state_serialize);
+		if (instance->poll_state != CXPOLL_SHUTDOWN) {
+			instance->poll_state = CXPOLL_STOPPED;
+
+			if (ret != -ESHUTDOWN)
+				atm_warn(usbatm, "polling disabled, set adsl_state"
+						" to 'start' or 'poll' to resume\n");
+		}
+		mutex_unlock(&instance->poll_state_serialize);
 		goto reschedule;
 	}
 
+	memcpy(instance->card_info, buf, sizeof(instance->card_info));
+
+	if (instance->adsl_status != buf[CXINF_LINE_STARTABLE]) {
+		instance->adsl_status = buf[CXINF_LINE_STARTABLE];
+
+		switch (instance->adsl_status) {
+		case 0:
+			atm_printk(KERN_INFO, usbatm, "ADSL state: running\n");
+			break;
+
+		case 1:
+			atm_printk(KERN_INFO, usbatm, "ADSL state: stopped\n");
+			break;
+
+		default:
+			atm_printk(KERN_INFO, usbatm, "Unknown adsl status %02x\n", instance->adsl_status);
+			break;
+		}
+	}
+
 	if (instance->line_status == buf[CXINF_LINE_STATUS])
 		goto reschedule;
 
@@ -449,7 +783,20 @@
 		break;
 	}
 reschedule:
-	schedule_delayed_work(&instance->poll_work, msecs_to_jiffies(POLL_INTERVAL));
+
+	mutex_lock(&instance->poll_state_serialize);
+	if (instance->poll_state == CXPOLL_STOPPING &&
+				instance->adsl_status == 1 && /* stopped */
+				instance->line_status == 0) /* down */
+		instance->poll_state = CXPOLL_STOPPED;
+
+	if (instance->poll_state == CXPOLL_STOPPED)
+		keep_polling = 0;
+	mutex_unlock(&instance->poll_state_serialize);
+
+	if (keep_polling)
+		schedule_delayed_work(&instance->poll_work,
+				round_jiffies_relative(POLL_INTERVAL*HZ));
 }
 
 static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
@@ -684,6 +1031,14 @@
 
 	instance->usbatm = usbatm_instance;
 	instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
+	memset(instance->card_info, 0, sizeof(instance->card_info));
+
+	mutex_init(&instance->poll_state_serialize);
+	instance->poll_state = CXPOLL_STOPPED;
+	instance->line_status = -1;
+	instance->adsl_status = -1;
+
+	mutex_init(&instance->adsl_state_serialize);
 
 	instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL);
 	if (!instance->rcv_buf) {
@@ -710,6 +1065,13 @@
 		goto fail;
 	}
 
+	#define CXACRU_DEVICE_CREATE_FILE(_name) \
+		ret = device_create_file(&intf->dev, &dev_attr_##_name); \
+		if (unlikely(ret)) \
+			goto fail_sysfs;
+	CXACRU_ALL_FILES(CREATE);
+	#undef CXACRU_DEVICE_CREATE_FILE
+
 	usb_fill_int_urb(instance->rcv_urb,
 			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
 			instance->rcv_buf, PAGE_SIZE,
@@ -730,6 +1092,14 @@
 
 	return 0;
 
+ fail_sysfs:
+	dbg("cxacru_bind: device_create_file failed (%d)\n", ret);
+
+	#define CXACRU_DEVICE_REMOVE_FILE(_name) \
+		device_remove_file(&intf->dev, &dev_attr_##_name);
+	CXACRU_ALL_FILES(REMOVE);
+	#undef CXACRU_DEVICE_REVOVE_FILE
+
  fail:
 	free_page((unsigned long) instance->snd_buf);
 	free_page((unsigned long) instance->rcv_buf);
@@ -744,6 +1114,7 @@
 		struct usb_interface *intf)
 {
 	struct cxacru_data *instance = usbatm_instance->driver_data;
+	int is_polling = 1;
 
 	dbg("cxacru_unbind entered");
 
@@ -752,8 +1123,20 @@
 		return;
 	}
 
-	while (!cancel_delayed_work(&instance->poll_work))
-	       flush_scheduled_work();
+	mutex_lock(&instance->poll_state_serialize);
+	BUG_ON(instance->poll_state == CXPOLL_SHUTDOWN);
+
+	/* ensure that status polling continues unless
+	 * it has already stopped */
+	if (instance->poll_state == CXPOLL_STOPPED)
+		is_polling = 0;
+
+	/* stop polling from being stopped or started */
+	instance->poll_state = CXPOLL_SHUTDOWN;
+	mutex_unlock(&instance->poll_state_serialize);
+
+	if (is_polling)
+		cancel_rearming_delayed_work(&instance->poll_work);
 
 	usb_kill_urb(instance->snd_urb);
 	usb_kill_urb(instance->rcv_urb);
@@ -762,6 +1145,12 @@
 
 	free_page((unsigned long) instance->snd_buf);
 	free_page((unsigned long) instance->rcv_buf);
+
+	#define CXACRU_DEVICE_REMOVE_FILE(_name) \
+		device_remove_file(&intf->dev, &dev_attr_##_name);
+	CXACRU_ALL_FILES(REMOVE);
+	#undef CXACRU_DEVICE_REVOVE_FILE
+
 	kfree(instance);
 
 	usbatm_instance->driver_data = NULL;
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index dae4ef1..4973e14 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -61,6 +61,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index ec63b0e..b3f779f 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -274,6 +274,9 @@
 			(!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
 			 urb->status != -EILSEQ ))
 	{
+		if (urb->status == -ESHUTDOWN)
+			return;
+
 		if (printk_ratelimit())
 			atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
 				__func__, urb, urb->status);
@@ -343,7 +346,7 @@
 		UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
 	}
 
-	memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
+	memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
 	__skb_put(sarb, ATM_CELL_PAYLOAD);
 
 	if (pti & 1) {
@@ -370,7 +373,7 @@
 			goto out;
 		}
 
-		if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
+		if (crc32_be(~0, skb_tail_pointer(sarb) - pdu_length, pdu_length) != 0xc704dd7b) {
 			atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
 				  __func__, vcc);
 			atomic_inc(&vcc->stats->rx_err);
@@ -396,7 +399,9 @@
 			goto out;	/* atm_charge increments rx_drop */
 		}
 
-		memcpy(skb->data, sarb->tail - pdu_length, length);
+		skb_copy_to_linear_data(skb,
+					skb_tail_pointer(sarb) - pdu_length,
+					length);
 		__skb_put(skb, length);
 
 		vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
@@ -484,7 +489,7 @@
 		ptr[4] = 0xec;
 		ptr += ATM_CELL_HEADER;
 
-		memcpy(ptr, skb->data, data_len);
+		skb_copy_from_linear_data(skb, ptr, data_len);
 		ptr += data_len;
 		__skb_pull(skb, data_len);
 
@@ -966,6 +971,14 @@
 	/* temp init ATM device, set to 128kbit */
 	atm_dev->link_rate = 128 * 1000 / 424;
 
+	ret = sysfs_create_link(&atm_dev->class_dev.kobj,
+				&instance->usb_intf->dev.kobj, "device");
+	if (ret) {
+		atm_err(instance, "%s: sysfs_create_link failed: %d\n",
+					__func__, ret);
+		goto fail_sysfs;
+	}
+
 	if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
 		atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
 		goto fail;
@@ -984,6 +997,8 @@
 	return 0;
 
  fail:
+	sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
+ fail_sysfs:
 	instance->atm_dev = NULL;
 	atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
 	return ret;
@@ -1316,8 +1331,10 @@
 	kfree(instance->cell_buf);
 
 	/* ATM finalize */
-	if (instance->atm_dev)
+	if (instance->atm_dev) {
+		sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
 		atm_dev_deregister(instance->atm_dev);
+	}
 
 	usbatm_put_instance(instance);	/* taken in usbatm_usb_probe */
 }
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9819962..14de3b1 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -212,7 +212,41 @@
 	}
 	return rc;
 }
+/*
+ * attributes exported through sysfs
+ */
+static ssize_t show_caps
+(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct acm *acm = usb_get_intfdata(intf);
 
+	return sprintf(buf, "%d", acm->ctrl_caps);
+}
+static DEVICE_ATTR(bmCapabilities, S_IRUGO, show_caps, NULL);
+
+static ssize_t show_country_codes
+(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct acm *acm = usb_get_intfdata(intf);
+
+	memcpy(buf, acm->country_codes, acm->country_code_size);
+	return acm->country_code_size;
+}
+
+static DEVICE_ATTR(wCountryCodes, S_IRUGO, show_country_codes, NULL);
+
+static ssize_t show_country_rel_date
+(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct acm *acm = usb_get_intfdata(intf);
+
+	return sprintf(buf, "%d", acm->country_rel_date);
+}
+
+static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL);
 /*
  * Interrupt handlers for various ACM device responses
  */
@@ -326,10 +360,16 @@
 	struct tty_struct *tty = acm->tty;
 	struct acm_ru *rcv;
 	unsigned long flags;
-	int i = 0;
+	unsigned char throttled;
 	dbg("Entering acm_rx_tasklet");
 
-	if (!ACM_READY(acm) || acm->throttle)
+	if (!ACM_READY(acm))
+		return;
+
+	spin_lock_irqsave(&acm->throttle_lock, flags);
+	throttled = acm->throttle;
+	spin_unlock_irqrestore(&acm->throttle_lock, flags);
+	if (throttled)
 		return;
 
 next_buffer:
@@ -346,22 +386,20 @@
 	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
 	tty_buffer_request_room(tty, buf->size);
-	if (!acm->throttle)
+	spin_lock_irqsave(&acm->throttle_lock, flags);
+	throttled = acm->throttle;
+	spin_unlock_irqrestore(&acm->throttle_lock, flags);
+	if (!throttled)
 		tty_insert_flip_string(tty, buf->base, buf->size);
 	tty_flip_buffer_push(tty);
 
-	spin_lock(&acm->throttle_lock);
-	if (acm->throttle) {
-		dbg("Throtteling noticed");
-		memmove(buf->base, buf->base + i, buf->size - i);
-		buf->size -= i;
-		spin_unlock(&acm->throttle_lock);
+	if (throttled) {
+		dbg("Throttling noticed");
 		spin_lock_irqsave(&acm->read_lock, flags);
 		list_add(&buf->list, &acm->filled_read_bufs);
 		spin_unlock_irqrestore(&acm->read_lock, flags);
 		return;
 	}
-	spin_unlock(&acm->throttle_lock);
 
 	spin_lock_irqsave(&acm->read_lock, flags);
 	list_add(&buf->list, &acm->spare_read_bufs);
@@ -467,7 +505,8 @@
 		goto bail_out;
 	}
 
-	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
+	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
+	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
 		goto full_bailout;
 
 	INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -480,6 +519,8 @@
 		list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
 	}
 
+	acm->throttle = 0;
+
 	tasklet_schedule(&acm->urb_task);
 
 done:
@@ -507,6 +548,7 @@
 	usb_free_urb(acm->writeurb);
 	for (i = 0; i < nr; i++)
 		usb_free_urb(acm->ru[i].urb);
+	kfree(acm->country_codes);
 	kfree(acm);
 }
 
@@ -754,6 +796,7 @@
 		      const struct usb_device_id *id)
 {
 	struct usb_cdc_union_desc *union_header = NULL;
+	struct usb_cdc_country_functional_desc *cfd = NULL;
 	char *buffer = intf->altsetting->extra;
 	int buflen = intf->altsetting->extralen;
 	struct usb_interface *control_interface;
@@ -817,8 +860,9 @@
 				union_header = (struct usb_cdc_union_desc *)
 							buffer;
 				break;
-			case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
-				break; /* for now we ignore it */
+			case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
+				cfd = (struct usb_cdc_country_functional_desc *)buffer;
+				break;
 			case USB_CDC_HEADER_TYPE: /* maybe check version */ 
 				break; /* for now we ignore it */ 
 			case USB_CDC_ACM_TYPE:
@@ -976,6 +1020,34 @@
 		goto alloc_fail7;
 	}
 
+	usb_set_intfdata (intf, acm);
+
+	i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
+	if (i < 0)
+		goto alloc_fail8;
+
+	if (cfd) { /* export the country data */
+		acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
+		if (!acm->country_codes)
+			goto skip_countries;
+		acm->country_code_size = cfd->bLength - 4;
+		memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, cfd->bLength - 4);
+		acm->country_rel_date = cfd->iCountryCodeRelDate;
+
+		i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
+		if (i < 0) {
+			kfree(acm->country_codes);
+			goto skip_countries;
+		}
+
+		i = device_create_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
+		if (i < 0) {
+			kfree(acm->country_codes);
+			goto skip_countries;
+		}
+	}
+
+skip_countries:
 	usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
 			 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
 	acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -999,9 +1071,10 @@
 	tty_register_device(acm_tty_driver, minor, &control_interface->dev);
 
 	acm_table[minor] = acm;
-	usb_set_intfdata (intf, acm);
-	return 0;
 
+	return 0;
+alloc_fail8:
+	usb_free_urb(acm->writeurb);
 alloc_fail7:
 	for (i = 0; i < num_rx_buf; i++)
 		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
@@ -1020,7 +1093,7 @@
 
 static void acm_disconnect(struct usb_interface *intf)
 {
-	struct acm *acm = usb_get_intfdata (intf);
+	struct acm *acm = usb_get_intfdata(intf);
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	int i;
 
@@ -1034,6 +1107,11 @@
 		mutex_unlock(&open_mutex);
 		return;
 	}
+	if (acm->country_codes){
+		device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
+		device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
+	}
+	device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
 	acm->dev = NULL;
 	usb_set_intfdata(acm->control, NULL);
 	usb_set_intfdata(acm->data, NULL);
@@ -1092,6 +1170,10 @@
 	{ USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
 	.driver_info = SINGLE_RX_URB, /* firmware bug */
 	},
+	{ USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
+	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+	},
+
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_ACM_PROTO_AT_V25TER) },
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 1bcaea3..09f7765 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -91,6 +91,9 @@
 	struct urb *ctrlurb, *writeurb;			/* urbs */
 	u8 *ctrl_buffer;				/* buffers of urbs */
 	dma_addr_t ctrl_dma;				/* dma handles of buffers */
+	u8 *country_codes;				/* country codes from device */
+	unsigned int country_code_size;			/* size of this buffer */
+	unsigned int country_rel_date;			/* release date of version */
 	struct acm_wb wb[ACM_NW];
 	struct acm_ru ru[ACM_NR];
 	struct acm_rb rb[ACM_NR];
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 63e50a1..6584cf0 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -202,6 +202,7 @@
 
 #define USBLP_QUIRK_BIDIR	0x1	/* reports bidir but requires unidirectional mode (no INs/reads) */
 #define USBLP_QUIRK_USB_INIT	0x2	/* needs vendor USB init string */
+#define USBLP_QUIRK_BAD_CLASS	0x4	/* descriptor uses vendor-specific Class or SubClass */
 
 static const struct quirk_printer_struct quirk_printers[] = {
 	{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
@@ -218,6 +219,7 @@
 	{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
 	{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
 	{ 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
+	{ 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */
 	{ 0, 0 }
 };
 
@@ -1048,7 +1050,8 @@
 		ifd = &if_alt->altsetting[i];
 
 		if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1)
-			continue;
+			if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS))
+				continue;
 
 		if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
 		    ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL)
@@ -1232,6 +1235,7 @@
 	{ USB_INTERFACE_INFO(7, 1, 1) },
 	{ USB_INTERFACE_INFO(7, 1, 2) },
 	{ USB_INTERFACE_INFO(7, 1, 3) },
+	{ USB_DEVICE(0x04b8, 0x0202) },	/* Seiko Epson Receipt Printer M129C */
 	{ }						/* Terminating entry */
 };
 
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 2fc0f88..f493fb1 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -31,7 +31,30 @@
 	  For the format of the various /proc/bus/usb/ files, please read
 	  <file:Documentation/usb/proc_usb_info.txt>.
 
-	  Most users want to say Y here.
+	  Usbfs files can't handle Access Control Lists (ACL), which are the
+	  default way to grant access to USB devices for untrusted users of a
+	  desktop system. The usbfs functionality is replaced by real
+	  device-nodes managed by udev. These nodes live in /dev/bus/usb and
+	  are used by libusb.
+
+config USB_DEVICE_CLASS
+	bool "USB device class-devices (DEPRECATED)"
+	depends on USB
+	default n
+	---help---
+	  Userspace access to USB devices is granted by device-nodes exported
+	  directly from the usbdev in sysfs. Old versions of the driver
+	  core and udev needed additional class devices to export device nodes.
+
+	  These additional devices are difficult to handle in userspace, if
+	  information about USB interfaces must be available. One device contains
+	  the device node, the other device contains the interface data. Both
+	  devices are at the same level in sysfs (siblings) and one can't access
+	  the other. The device node created directly by the usbdev is the parent
+	  device of the interface and therefore easily accessible from the interface
+	  event.
+
+	  This option provides backward compatibility if needed.
 
 config USB_DYNAMIC_MINORS
 	bool "Dynamic USB minor allocation (EXPERIMENTAL)"
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 34e9bac..b607870 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -4,7 +4,7 @@
 
 usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
 			config.o file.o buffer.o sysfs.o endpoint.o \
-			devio.o notify.o generic.o
+			devio.o notify.o generic.o quirks.o
 
 ifeq ($(CONFIG_PCI),y)
 	usbcore-objs	+= hcd-pci.o
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index a47c30b..6753ca0 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -246,7 +246,6 @@
 
 	if (start > end)
 		return start;
-	down_read(&usb_bus_type.subsys.rwsem);
 	if (iface) {
 		driver_name = (iface->dev.driver
 				? iface->dev.driver->name
@@ -263,7 +262,6 @@
 			 desc->bInterfaceSubClass,
 			 desc->bInterfaceProtocol,
 			 driver_name);
-	up_read(&usb_bus_type.subsys.rwsem);
 	return start;
 }
 
@@ -604,10 +602,6 @@
 	lock_kernel();
 	if (!st) {
 		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-		if (!st) {
-			unlock_kernel();
-			return POLLIN;
-		}
 
 		/* we may have dropped BKL - need to check for having lost the race */
 		if (file->private_data) {
@@ -615,6 +609,11 @@
 			st = file->private_data;
 			goto lost_race;
 		}
+		/* we haven't lost - check for allocation failure now */
+		if (!st) {
+			unlock_kernel();
+			return POLLIN;
+		}
 
 		/*
 		 * need to prevent the module from being unloaded, since
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 2087766..927a181 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -57,7 +57,6 @@
 
 #define USB_MAXBUS			64
 #define USB_DEVICE_MAX			USB_MAXBUS * 128
-static struct class *usb_device_class;
 
 /* Mutual exclusion for removal, open, and release */
 DEFINE_MUTEX(usbfs_mutex);
@@ -421,14 +420,11 @@
 	if (test_bit(ifnum, &ps->ifclaimed))
 		return 0;
 
-	/* lock against other changes to driver bindings */
-	down_write(&usb_bus_type.subsys.rwsem);
 	intf = usb_ifnum_to_if(dev, ifnum);
 	if (!intf)
 		err = -ENOENT;
 	else
 		err = usb_driver_claim_interface(&usbfs_driver, intf, ps);
-	up_write(&usb_bus_type.subsys.rwsem);
 	if (err == 0)
 		set_bit(ifnum, &ps->ifclaimed);
 	return err;
@@ -444,8 +440,6 @@
 	if (ifnum >= 8*sizeof(ps->ifclaimed))
 		return err;
 	dev = ps->dev;
-	/* lock against other changes to driver bindings */
-	down_write(&usb_bus_type.subsys.rwsem);
 	intf = usb_ifnum_to_if(dev, ifnum);
 	if (!intf)
 		err = -ENOENT;
@@ -453,7 +447,6 @@
 		usb_driver_release_interface(&usbfs_driver, intf);
 		err = 0;
 	}
-	up_write(&usb_bus_type.subsys.rwsem);
 	return err;
 }
 
@@ -520,22 +513,25 @@
 	return ret;
 }
 
-static struct usb_device *usbdev_lookup_minor(int minor)
+static int __match_minor(struct device *dev, void *data)
 {
-	struct device *device;
-	struct usb_device *udev = NULL;
+	int minor = *((int *)data);
 
-	down(&usb_device_class->sem);
-	list_for_each_entry(device, &usb_device_class->devices, node) {
-		if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
-			udev = device->platform_data;
-			break;
-		}
-	}
-	up(&usb_device_class->sem);
+	if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
+		return 1;
+	return 0;
+}
 
-	return udev;
-};
+static struct usb_device *usbdev_lookup_by_minor(int minor)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
+	if (!dev)
+		return NULL;
+	put_device(dev);
+	return container_of(dev, struct usb_device, dev);
+}
 
 /*
  * file operations
@@ -554,11 +550,14 @@
 		goto out;
 
 	ret = -ENOENT;
-	/* check if we are called from a real node or usbfs */
+	/* usbdev device-node */
 	if (imajor(inode) == USB_DEVICE_MAJOR)
-		dev = usbdev_lookup_minor(iminor(inode));
+		dev = usbdev_lookup_by_minor(iminor(inode));
+#ifdef CONFIG_USB_DEVICEFS
+	/* procfs file */
 	if (!dev)
 		dev = inode->i_private;
+#endif
 	if (!dev)
 		goto out;
 	ret = usb_autoresume_device(dev);
@@ -581,7 +580,7 @@
 	ps->disccontext = NULL;
 	ps->ifclaimed = 0;
 	security_task_getsecid(current, &ps->secid);
-	wmb();
+	smp_wmb();
 	list_add_tail(&ps->list, &dev->filelist);
 	file->private_data = ps;
  out:
@@ -813,7 +812,6 @@
 
 	if (copy_from_user(&gd, arg, sizeof(gd)))
 		return -EFAULT;
-	down_read(&usb_bus_type.subsys.rwsem);
 	intf = usb_ifnum_to_if(ps->dev, gd.interface);
 	if (!intf || !intf->dev.driver)
 		ret = -ENODATA;
@@ -822,7 +820,6 @@
 				sizeof(gd.driver));
 		ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0);
 	}
-	up_read(&usb_bus_type.subsys.rwsem);
 	return ret;
 }
 
@@ -857,11 +854,11 @@
 
 static int proc_setconfig(struct dev_state *ps, void __user *arg)
 {
-	unsigned int u;
+	int u;
 	int status = 0;
  	struct usb_host_config *actconfig;
 
-	if (get_user(u, (unsigned int __user *)arg))
+	if (get_user(u, (int __user *)arg))
 		return -EFAULT;
 
  	actconfig = ps->dev->actconfig;
@@ -912,7 +909,7 @@
 	struct async *as;
 	struct usb_ctrlrequest *dr = NULL;
 	unsigned int u, totlen, isofrmlen;
-	int ret, interval = 0, ifnum = -1;
+	int ret, ifnum = -1;
 
 	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
 			   URB_NO_FSBR|URB_ZERO_PACKET))
@@ -992,7 +989,6 @@
 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 				!= USB_ENDPOINT_XFER_ISOC)
 			return -EINVAL;
-		interval = 1 << min (15, ep->desc.bInterval - 1);
 		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 			return -ENOMEM;
@@ -1021,10 +1017,6 @@
 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 				!= USB_ENDPOINT_XFER_INT)
 			return -EINVAL;
-		if (ps->dev->speed == USB_SPEED_HIGH)
-			interval = 1 << min (15, ep->desc.bInterval - 1);
-		else
-			interval = ep->desc.bInterval;
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
@@ -1053,7 +1045,11 @@
 	as->urb->setup_packet = (unsigned char*)dr;
 	as->urb->start_frame = uurb->start_frame;
 	as->urb->number_of_packets = uurb->number_of_packets;
-	as->urb->interval = interval;
+	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+			ps->dev->speed == USB_SPEED_HIGH)
+		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
+	else
+		as->urb->interval = ep->desc.bInterval;
         as->urb->context = as;
         as->urb->complete = async_completed;
 	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
@@ -1352,15 +1348,12 @@
 
 	/* disconnect kernel driver from interface */
 	case USBDEVFS_DISCONNECT:
-
-		down_write(&usb_bus_type.subsys.rwsem);
 		if (intf->dev.driver) {
 			driver = to_usb_driver(intf->dev.driver);
 			dev_dbg (&intf->dev, "disconnect by usbfs\n");
 			usb_driver_release_interface(driver, intf);
 		} else
 			retval = -ENODATA;
-		up_write(&usb_bus_type.subsys.rwsem);
 		break;
 
 	/* let kernel drivers try to (re)bind to the interface */
@@ -1372,7 +1365,6 @@
 
 	/* talk directly to the interface's driver */
 	default:
-		down_read(&usb_bus_type.subsys.rwsem);
 		if (intf->dev.driver)
 			driver = to_usb_driver(intf->dev.driver);
 		if (driver == NULL || driver->ioctl == NULL) {
@@ -1382,7 +1374,6 @@
 			if (retval == -ENOIOCTLCMD)
 				retval = -ENOTTY;
 		}
-		up_read(&usb_bus_type.subsys.rwsem);
 	}
 
 	/* cleanup and return */
@@ -1584,7 +1575,7 @@
 	return mask;
 }
 
-const struct file_operations usbfs_device_file_operations = {
+const struct file_operations usbdev_file_operations = {
 	.llseek =	usbdev_lseek,
 	.read =		usbdev_read,
 	.poll =		usbdev_poll,
@@ -1593,50 +1584,53 @@
 	.release =	usbdev_release,
 };
 
-static int usbdev_add(struct usb_device *dev)
+#ifdef CONFIG_USB_DEVICE_CLASS
+static struct class *usb_classdev_class;
+
+static int usb_classdev_add(struct usb_device *dev)
 {
 	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
-	dev->usbfs_dev = device_create(usb_device_class, &dev->dev,
+	dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
 				MKDEV(USB_DEVICE_MAJOR, minor),
 				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
-	if (IS_ERR(dev->usbfs_dev))
-		return PTR_ERR(dev->usbfs_dev);
+	if (IS_ERR(dev->usb_classdev))
+		return PTR_ERR(dev->usb_classdev);
 
-	dev->usbfs_dev->platform_data = dev;
 	return 0;
 }
 
-static void usbdev_remove(struct usb_device *dev)
+static void usb_classdev_remove(struct usb_device *dev)
 {
-	device_unregister(dev->usbfs_dev);
+	device_unregister(dev->usb_classdev);
 }
 
-static int usbdev_notify(struct notifier_block *self, unsigned long action,
-			 void *dev)
+static int usb_classdev_notify(struct notifier_block *self,
+			       unsigned long action, void *dev)
 {
 	switch (action) {
 	case USB_DEVICE_ADD:
-		if (usbdev_add(dev))
+		if (usb_classdev_add(dev))
 			return NOTIFY_BAD;
 		break;
 	case USB_DEVICE_REMOVE:
-		usbdev_remove(dev);
+		usb_classdev_remove(dev);
 		break;
 	}
 	return NOTIFY_OK;
 }
 
 static struct notifier_block usbdev_nb = {
-	.notifier_call = 	usbdev_notify,
+	.notifier_call = 	usb_classdev_notify,
 };
+#endif
 
 static struct cdev usb_device_cdev = {
 	.kobj   = {.name = "usb_device", },
 	.owner  = THIS_MODULE,
 };
 
-int __init usbdev_init(void)
+int __init usb_devio_init(void)
 {
 	int retval;
 
@@ -1646,38 +1640,38 @@
 		err("unable to register minors for usb_device");
 		goto out;
 	}
-	cdev_init(&usb_device_cdev, &usbfs_device_file_operations);
+	cdev_init(&usb_device_cdev, &usbdev_file_operations);
 	retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
 	if (retval) {
 		err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
 		goto error_cdev;
 	}
-	usb_device_class = class_create(THIS_MODULE, "usb_device");
-	if (IS_ERR(usb_device_class)) {
+#ifdef CONFIG_USB_DEVICE_CLASS
+	usb_classdev_class = class_create(THIS_MODULE, "usb_device");
+	if (IS_ERR(usb_classdev_class)) {
 		err("unable to register usb_device class");
-		retval = PTR_ERR(usb_device_class);
-		goto error_class;
+		retval = PTR_ERR(usb_classdev_class);
+		cdev_del(&usb_device_cdev);
+		usb_classdev_class = NULL;
+		goto out;
 	}
 
 	usb_register_notify(&usbdev_nb);
-
+#endif
 out:
 	return retval;
 
-error_class:
-	usb_device_class = NULL;
-	cdev_del(&usb_device_cdev);
-
 error_cdev:
 	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
 	goto out;
 }
 
-void usbdev_cleanup(void)
+void usb_devio_cleanup(void)
 {
+#ifdef CONFIG_USB_DEVICE_CLASS
 	usb_unregister_notify(&usbdev_nb);
-	class_destroy(usb_device_class);
+	class_destroy(usb_classdev_class);
+#endif
 	cdev_del(&usb_device_cdev);
 	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
 }
-
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 600d1bc..b9f7f90 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -287,9 +287,9 @@
  * way to bind to an interface is to return the private data from
  * the driver's probe() method.
  *
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver probe() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
+ * Callers must own the device lock, so driver probe() entries don't need
+ * extra locking, but other call contexts may need to explicitly claim that
+ * lock.
  */
 int usb_driver_claim_interface(struct usb_driver *driver,
 				struct usb_interface *iface, void* priv)
@@ -330,9 +330,9 @@
  * also causes the driver disconnect() method to be called.
  *
  * This call is synchronous, and may not be used in an interrupt context.
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver disconnect() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
+ * Callers must own the device lock, so driver disconnect() entries don't
+ * need extra locking, but other call contexts may need to explicitly claim
+ * that lock.
  */
 void usb_driver_release_interface(struct usb_driver *driver,
 					struct usb_interface *iface)
@@ -366,19 +366,8 @@
 EXPORT_SYMBOL(usb_driver_release_interface);
 
 /* returns 0 if no match, 1 if match */
-int usb_match_one_id(struct usb_interface *interface,
-		     const struct usb_device_id *id)
+int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
 {
-	struct usb_host_interface *intf;
-	struct usb_device *dev;
-
-	/* proc_connectinfo in devio.c may call us with id == NULL. */
-	if (id == NULL)
-		return 0;
-
-	intf = interface->cur_altsetting;
-	dev = interface_to_usbdev(interface);
-
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
 	    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
 		return 0;
@@ -409,6 +398,26 @@
 	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
 		return 0;
 
+	return 1;
+}
+
+/* returns 0 if no match, 1 if match */
+int usb_match_one_id(struct usb_interface *interface,
+		     const struct usb_device_id *id)
+{
+	struct usb_host_interface *intf;
+	struct usb_device *dev;
+
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return 0;
+
+	intf = interface->cur_altsetting;
+	dev = interface_to_usbdev(interface);
+
+	if (!usb_match_device(dev, id))
+		return 0;
+
 	/* The interface class, subclass, and protocol should never be
 	 * checked for a match if the device class is Vendor Specific,
 	 * unless the match record specifies the Vendor ID. */
@@ -565,23 +574,10 @@
 }
 
 #ifdef	CONFIG_HOTPLUG
-
-/*
- * This sends an uevent to userspace, typically helping to load driver
- * or other modules, configure the device, and more.  Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- * We're called either from khubd (the typical case) or from root hub
- * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
- * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
- * device (and this configuration!) are still present.
- */
 static int usb_uevent(struct device *dev, char **envp, int num_envp,
 		      char *buffer, int buffer_size)
 {
-	struct usb_interface *intf;
 	struct usb_device *usb_dev;
-	struct usb_host_interface *alt;
 	int i = 0;
 	int length = 0;
 
@@ -591,13 +587,11 @@
 	/* driver is often null here; dev_dbg() would oops */
 	pr_debug ("usb %s: uevent\n", dev->bus_id);
 
-	if (is_usb_device(dev)) {
+	if (is_usb_device(dev))
 		usb_dev = to_usb_device(dev);
-		alt = NULL;
-	} else {
-		intf = to_usb_interface(dev);
+	else {
+		struct usb_interface *intf = to_usb_interface(dev);
 		usb_dev = interface_to_usbdev(intf);
-		alt = intf->cur_altsetting;
 	}
 
 	if (usb_dev->devnum < 0) {
@@ -612,9 +606,7 @@
 #ifdef	CONFIG_USB_DEVICEFS
 	/* If this is available, userspace programs can directly read
 	 * all the device descriptors we don't tell them about.  Or
-	 * even act as usermode drivers.
-	 *
-	 * FIXME reduce hardwired intelligence here
+	 * act as usermode drivers.
 	 */
 	if (add_uevent_var(envp, num_envp, &i,
 			   buffer, buffer_size, &length,
@@ -641,44 +633,29 @@
 			   usb_dev->descriptor.bDeviceProtocol))
 		return -ENOMEM;
 
-	if (!is_usb_device(dev)) {
-
-		if (add_uevent_var(envp, num_envp, &i,
+	if (add_uevent_var(envp, num_envp, &i,
 			   buffer, buffer_size, &length,
-			   "INTERFACE=%d/%d/%d",
-			   alt->desc.bInterfaceClass,
-			   alt->desc.bInterfaceSubClass,
-			   alt->desc.bInterfaceProtocol))
-			return -ENOMEM;
+			   "BUSNUM=%03d",
+			   usb_dev->bus->busnum))
+		return -ENOMEM;
 
-		if (add_uevent_var(envp, num_envp, &i,
+	if (add_uevent_var(envp, num_envp, &i,
 			   buffer, buffer_size, &length,
-			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-			   le16_to_cpu(usb_dev->descriptor.idVendor),
-			   le16_to_cpu(usb_dev->descriptor.idProduct),
-			   le16_to_cpu(usb_dev->descriptor.bcdDevice),
-			   usb_dev->descriptor.bDeviceClass,
-			   usb_dev->descriptor.bDeviceSubClass,
-			   usb_dev->descriptor.bDeviceProtocol,
-			   alt->desc.bInterfaceClass,
-			   alt->desc.bInterfaceSubClass,
-			   alt->desc.bInterfaceProtocol))
-			return -ENOMEM;
-	}
+			   "DEVNUM=%03d",
+			   usb_dev->devnum))
+		return -ENOMEM;
 
 	envp[i] = NULL;
-
 	return 0;
 }
 
 #else
 
 static int usb_uevent(struct device *dev, char **envp,
-			int num_envp, char *buffer, int buffer_size)
+		      int num_envp, char *buffer, int buffer_size)
 {
 	return -ENODEV;
 }
-
 #endif	/* CONFIG_HOTPLUG */
 
 /**
@@ -743,6 +720,7 @@
  * usb_register_driver - register a USB interface driver
  * @new_driver: USB operations for the interface driver
  * @owner: module owner of this driver.
+ * @mod_name: module name string
  *
  * Registers a USB interface driver with the USB core.  The list of
  * unattached interfaces will be rescanned whenever a new driver is
@@ -862,8 +840,10 @@
 
 done:
 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
-	if (status == 0)
+	if (status == 0) {
+		udev->autoresume_disabled = 0;
 		udev->dev.power.power_state.event = PM_EVENT_ON;
+	}
 	return status;
 }
 
@@ -952,13 +932,19 @@
 {
 	int			i;
 	struct usb_interface	*intf;
+	unsigned long		suspend_time;
 
-	/* For autosuspend, fail fast if anything is in use.
-	 * Also fail if any interfaces require remote wakeup but it
-	 * isn't available. */
+	/* For autosuspend, fail fast if anything is in use or autosuspend
+	 * is disabled.  Also fail if any interfaces require remote wakeup
+	 * but it isn't available.
+	 */
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 	if (udev->pm_usage_cnt > 0)
 		return -EBUSY;
+	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+		return -EPERM;
+
+	suspend_time = udev->last_busy + udev->autosuspend_delay;
 	if (udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
@@ -974,6 +960,24 @@
 			}
 		}
 	}
+
+	/* If everything is okay but the device hasn't been idle for long
+	 * enough, queue a delayed autosuspend request.
+	 */
+	if (time_after(suspend_time, jiffies)) {
+		if (!timer_pending(&udev->autosuspend.timer)) {
+
+			/* The value of jiffies may change between the
+			 * time_after() comparison above and the subtraction
+			 * below.  That's okay; the system behaves sanely
+			 * when a timer is registered for the present moment
+			 * or for the past.
+			 */
+			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+					suspend_time - jiffies);
+			}
+		return -EAGAIN;
+	}
 	return 0;
 }
 
@@ -981,7 +985,7 @@
 
 #define autosuspend_check(udev)		0
 
-#endif
+#endif	/* CONFIG_USB_SUSPEND */
 
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
@@ -1019,26 +1023,25 @@
  *
  * This routine can run only in process context.
  */
-int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 {
 	int			status = 0;
 	int			i = 0;
 	struct usb_interface	*intf;
 	struct usb_device	*parent = udev->parent;
 
-	cancel_delayed_work(&udev->autosuspend);
-	if (udev->state == USB_STATE_NOTATTACHED)
-		return 0;
-	if (udev->state == USB_STATE_SUSPENDED)
-		return 0;
+	if (udev->state == USB_STATE_NOTATTACHED ||
+			udev->state == USB_STATE_SUSPENDED)
+		goto done;
 
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 
 	if (udev->auto_pm) {
 		status = autosuspend_check(udev);
 		if (status < 0)
-			return status;
+			goto done;
 	}
+	cancel_delayed_work(&udev->autosuspend);
 
 	/* Suspend all the interfaces and then udev itself */
 	if (udev->actconfig) {
@@ -1063,6 +1066,7 @@
 	} else if (parent)
 		usb_autosuspend_device(parent);
 
+ done:
 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
 	return status;
 }
@@ -1095,7 +1099,7 @@
  *
  * This routine can run only in process context.
  */
-int usb_resume_both(struct usb_device *udev)
+static int usb_resume_both(struct usb_device *udev)
 {
 	int			status = 0;
 	int			i;
@@ -1103,11 +1107,17 @@
 	struct usb_device	*parent = udev->parent;
 
 	cancel_delayed_work(&udev->autosuspend);
-	if (udev->state == USB_STATE_NOTATTACHED)
-		return -ENODEV;
+	if (udev->state == USB_STATE_NOTATTACHED) {
+		status = -ENODEV;
+		goto done;
+	}
 
 	/* Propagate the resume up the tree, if necessary */
 	if (udev->state == USB_STATE_SUSPENDED) {
+		if (udev->auto_pm && udev->autoresume_disabled) {
+			status = -EPERM;
+			goto done;
+		}
 		if (parent) {
 			status = usb_autoresume_device(parent);
 			if (status == 0) {
@@ -1153,6 +1163,7 @@
 		}
 	}
 
+ done:
 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
 	return status;
 }
@@ -1167,20 +1178,34 @@
 	int	status = 0;
 
 	usb_pm_lock(udev);
+	udev->auto_pm = 1;
 	udev->pm_usage_cnt += inc_usage_cnt;
 	WARN_ON(udev->pm_usage_cnt < 0);
 	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
-		udev->auto_pm = 1;
-		status = usb_resume_both(udev);
+		if (udev->state == USB_STATE_SUSPENDED)
+			status = usb_resume_both(udev);
 		if (status != 0)
 			udev->pm_usage_cnt -= inc_usage_cnt;
-	} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
-		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-				USB_AUTOSUSPEND_DELAY);
+		else if (inc_usage_cnt)
+			udev->last_busy = jiffies;
+	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
+		if (inc_usage_cnt)
+			udev->last_busy = jiffies;
+		status = usb_suspend_both(udev, PMSG_SUSPEND);
+	}
 	usb_pm_unlock(udev);
 	return status;
 }
 
+/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+void usb_autosuspend_work(struct work_struct *work)
+{
+	struct usb_device *udev =
+		container_of(work, struct usb_device, autosuspend.work);
+
+	usb_autopm_do_device(udev, 0);
+}
+
 /**
  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
  * @udev: the usb_device to autosuspend
@@ -1211,6 +1236,26 @@
 }
 
 /**
+ * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
+ * @udev: the usb_device to autosuspend
+ *
+ * This routine should be called when a core subsystem thinks @udev may
+ * be ready to autosuspend.
+ *
+ * @udev's usage counter left unchanged.  If it or any of the usage counters
+ * for an active interface is greater than 0, or autosuspend is not allowed
+ * for any other reason, no autosuspend request will be queued.
+ *
+ * This routine can run only in process context.
+ */
+void usb_try_autosuspend_device(struct usb_device *udev)
+{
+	usb_autopm_do_device(udev, 0);
+	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+	// 		__FUNCTION__, udev->pm_usage_cnt);
+}
+
+/**
  * usb_autoresume_device - immediately autoresume a USB device and its interfaces
  * @udev: the usb_device to autoresume
  *
@@ -1252,15 +1297,20 @@
 	if (intf->condition == USB_INTERFACE_UNBOUND)
 		status = -ENODEV;
 	else {
+		udev->auto_pm = 1;
 		intf->pm_usage_cnt += inc_usage_cnt;
 		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
-			udev->auto_pm = 1;
-			status = usb_resume_both(udev);
+			if (udev->state == USB_STATE_SUSPENDED)
+				status = usb_resume_both(udev);
 			if (status != 0)
 				intf->pm_usage_cnt -= inc_usage_cnt;
-		} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
-			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-					USB_AUTOSUSPEND_DELAY);
+			else if (inc_usage_cnt)
+				udev->last_busy = jiffies;
+		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
+			if (inc_usage_cnt)
+				udev->last_busy = jiffies;
+			status = usb_suspend_both(udev, PMSG_SUSPEND);
+		}
 	}
 	usb_pm_unlock(udev);
 	return status;
@@ -1319,11 +1369,14 @@
  * or @intf is unbound.  A typical example would be a character-device
  * driver when its device file is opened.
  *
- * The routine increments @intf's usage counter.  So long as the counter
- * is greater than 0, autosuspend will not be allowed for @intf or its
- * usb_device.  When the driver is finished using @intf it should call
- * usb_autopm_put_interface() to decrement the usage counter and queue
- * a delayed autosuspend request (if the counter is <= 0).
+ *
+ * The routine increments @intf's usage counter.  (However if the
+ * autoresume fails then the counter is re-decremented.)  So long as the
+ * counter is greater than 0, autosuspend will not be allowed for @intf
+ * or its usb_device.  When the driver is finished using @intf it should
+ * call usb_autopm_put_interface() to decrement the usage counter and
+ * queue a delayed autosuspend request (if the counter is <= 0).
+ *
  *
  * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
  * core will not change its value other than the increment and decrement
@@ -1371,50 +1424,96 @@
 }
 EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
 
+#else
+
+void usb_autosuspend_work(struct work_struct *work)
+{}
+
 #endif /* CONFIG_USB_SUSPEND */
 
-static int usb_suspend(struct device *dev, pm_message_t message)
+/**
+ * usb_external_suspend_device - external suspend of a USB device and its interfaces
+ * @udev: the usb_device to suspend
+ * @msg: Power Management message describing this state transition
+ *
+ * This routine handles external suspend requests: ones not generated
+ * internally by a USB driver (autosuspend) but rather coming from the user
+ * (via sysfs) or the PM core (system sleep).  The suspend will be carried
+ * out regardless of @udev's usage counter or those of its interfaces,
+ * and regardless of whether or not remote wakeup is enabled.  Of course,
+ * interface drivers still have the option of failing the suspend (if
+ * there are unsuspended children, for example).
+ *
+ * The caller must hold @udev's device lock.
+ */
+int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
 {
 	int	status;
 
-	if (is_usb_device(dev)) {
-		struct usb_device *udev = to_usb_device(dev);
-
-		usb_pm_lock(udev);
-		udev->auto_pm = 0;
-		status = usb_suspend_both(udev, message);
-		usb_pm_unlock(udev);
-	} else
-		status = 0;
+	usb_pm_lock(udev);
+	udev->auto_pm = 0;
+	status = usb_suspend_both(udev, msg);
+	usb_pm_unlock(udev);
 	return status;
 }
 
+/**
+ * usb_external_resume_device - external resume of a USB device and its interfaces
+ * @udev: the usb_device to resume
+ *
+ * This routine handles external resume requests: ones not generated
+ * internally by a USB driver (autoresume) but rather coming from the user
+ * (via sysfs), the PM core (system resume), or the device itself (remote
+ * wakeup).  @udev's usage counter is unaffected.
+ *
+ * The caller must hold @udev's device lock.
+ */
+int usb_external_resume_device(struct usb_device *udev)
+{
+	int	status;
+
+	usb_pm_lock(udev);
+	udev->auto_pm = 0;
+	status = usb_resume_both(udev);
+	usb_pm_unlock(udev);
+
+	/* Now that the device is awake, we can start trying to autosuspend
+	 * it again. */
+	if (status == 0)
+		usb_try_autosuspend_device(udev);
+	return status;
+}
+
+static int usb_suspend(struct device *dev, pm_message_t message)
+{
+	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+		return 0;
+	return usb_external_suspend_device(to_usb_device(dev), message);
+}
+
 static int usb_resume(struct device *dev)
 {
-	int	status;
+	struct usb_device	*udev;
 
-	if (is_usb_device(dev)) {
-		struct usb_device *udev = to_usb_device(dev);
-
-		usb_pm_lock(udev);
-		udev->auto_pm = 0;
-		status = usb_resume_both(udev);
-		usb_pm_unlock(udev);
-
-		/* Rebind drivers that had no suspend method? */
-	} else
-		status = 0;
-	return status;
+	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+		return 0;
+	udev = to_usb_device(dev);
+	if (udev->autoresume_disabled)
+		return -EPERM;
+	return usb_external_resume_device(udev);
 }
 
+#else
+
+#define usb_suspend	NULL
+#define usb_resume	NULL
+
 #endif /* CONFIG_PM */
 
 struct bus_type usb_bus_type = {
 	.name =		"usb",
 	.match =	usb_device_match,
 	.uevent =	usb_uevent,
-#ifdef CONFIG_PM
 	.suspend =	usb_suspend,
 	.resume =	usb_resume,
-#endif
 };
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 5e628ae..e0ec704 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -229,7 +229,7 @@
 	kref_init(&ep_class->kref);
 	ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
 	if (IS_ERR(ep_class->class)) {
-		result = IS_ERR(ep_class->class);
+		result = PTR_ERR(ep_class->class);
 		goto class_create_error;
 	}
 
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index b531a4f..9bbcb20 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -184,7 +184,7 @@
 	/* if this is only an unbind, not a physical disconnect, then
 	 * unconfigure the device */
 	if (udev->actconfig)
-		usb_set_configuration(udev, 0);
+		usb_set_configuration(udev, -1);
 
 	usb_remove_sysfs_dev_files(udev);
 }
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index b26c19e..40cf882 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -37,6 +37,7 @@
 #include <asm/irq.h>
 #include <asm/byteorder.h>
 #include <linux/platform_device.h>
+#include <linux/workqueue.h>
 
 #include <linux/usb.h>
 
@@ -544,6 +545,8 @@
 	unsigned long	flags;
 	char		buffer[4];	/* Any root hubs with > 31 ports? */
 
+	if (unlikely(!hcd->rh_registered))
+		return;
 	if (!hcd->uses_new_polling && !hcd->status_urb)
 		return;
 
@@ -1296,14 +1299,26 @@
 	return status;
 }
 
+/* Workqueue routine for root-hub remote wakeup */
+static void hcd_resume_work(struct work_struct *work)
+{
+	struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work);
+	struct usb_device *udev = hcd->self.root_hub;
+
+	usb_lock_device(udev);
+	usb_mark_last_busy(udev);
+	usb_external_resume_device(udev);
+	usb_unlock_device(udev);
+}
+
 /**
  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
  * @hcd: host controller for this root hub
  *
  * The USB host controller calls this function when its root hub is
  * suspended (with the remote wakeup feature enabled) and a remote
- * wakeup request is received.  It queues a request for khubd to
- * resume the root hub (that is, manage its downstream ports again).
+ * wakeup request is received.  The routine submits a workqueue request
+ * to resume the root hub (that is, manage its downstream ports again).
  */
 void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
 {
@@ -1311,7 +1326,7 @@
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
 	if (hcd->rh_registered)
-		usb_resume_root_hub (hcd->self.root_hub);
+		queue_work(ksuspend_usb_wq, &hcd->wakeup_work);
 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
@@ -1500,6 +1515,9 @@
 	init_timer(&hcd->rh_timer);
 	hcd->rh_timer.function = rh_timer_func;
 	hcd->rh_timer.data = (unsigned long) hcd;
+#ifdef CONFIG_PM
+	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
+#endif
 
 	hcd->driver = driver;
 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
@@ -1666,16 +1684,20 @@
 	hcd->rh_registered = 0;
 	spin_unlock_irq (&hcd_root_hub_lock);
 
+#ifdef CONFIG_PM
+	flush_workqueue(ksuspend_usb_wq);
+#endif
+
 	mutex_lock(&usb_bus_list_lock);
 	usb_disconnect(&hcd->self.root_hub);
 	mutex_unlock(&usb_bus_list_lock);
 
-	hcd->poll_rh = 0;
-	del_timer_sync(&hcd->rh_timer);
-
 	hcd->driver->stop(hcd);
 	hcd->state = HC_STATE_HALT;
 
+	hcd->poll_rh = 0;
+	del_timer_sync(&hcd->rh_timer);
+
 	if (hcd->irq >= 0)
 		free_irq(hcd->irq, hcd);
 	usb_deregister_bus(&hcd->self);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 2a269ca..ef50fa4 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -68,6 +68,9 @@
 
 	struct timer_list	rh_timer;	/* drives root-hub polling */
 	struct urb		*status_urb;	/* the current status urb */
+#ifdef CONFIG_PM
+	struct work_struct	wakeup_work;	/* for remote wakeup */
+#endif
 
 	/*
 	 * hardware info/state
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 590ec82..bde29ab 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -44,6 +44,7 @@
 		struct usb_hub_status	hub;
 		struct usb_port_status	port;
 	}			*status;	/* buffer for status reports */
+	struct mutex		status_mutex;	/* for the status buffer */
 
 	int			error;		/* last reported error */
 	int			nerrors;	/* track consecutive errors */
@@ -118,8 +119,7 @@
 		"first one fails");
 
 
-#ifdef	DEBUG
-static inline char *portspeed (int portstatus)
+static inline char *portspeed(int portstatus)
 {
 	if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
     		return "480 Mb/s";
@@ -128,7 +128,6 @@
 	else
 		return "12 Mb/s";
 }
-#endif
 
 /* Note that hdev or one of its children must be locked! */
 static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev)
@@ -535,6 +534,7 @@
 {
 	int ret;
 
+	mutex_lock(&hub->status_mutex);
 	ret = get_hub_status(hub->hdev, &hub->status->hub);
 	if (ret < 0)
 		dev_err (hub->intfdev,
@@ -544,6 +544,7 @@
 		*change = le16_to_cpu(hub->status->hub.wHubChange); 
 		ret = 0;
 	}
+	mutex_unlock(&hub->status_mutex);
 	return ret;
 }
 
@@ -617,6 +618,7 @@
 		ret = -ENOMEM;
 		goto fail;
 	}
+	mutex_init(&hub->status_mutex);
 
 	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
 	if (!hub->descriptor) {
@@ -1277,11 +1279,8 @@
 {
 	int err;
 
-	/* Lock ourself into memory in order to keep a probe sequence
-	 * sleeping in a new thread from allowing us to be unloaded.
-	 */
-	if (!try_module_get(THIS_MODULE))
-		return -EINVAL;
+	/* Determine quirks */
+	usb_detect_quirks(udev);
 
 	err = usb_get_configuration(udev);
 	if (err < 0) {
@@ -1368,11 +1367,15 @@
 	}
 #endif
 
+	/* export the usbdev device-node for libusb */
+	udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
+			(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
+
 	/* Register the device.  The device driver is responsible
-	 * for adding the device files to usbfs and sysfs and for
-	 * configuring the device.
+	 * for adding the device files to sysfs and for configuring
+	 * the device.
 	 */
-	err = device_add (&udev->dev);
+	err = device_add(&udev->dev);
 	if (err) {
 		dev_err(&udev->dev, "can't device_add, error %d\n", err);
 		goto fail;
@@ -1383,7 +1386,6 @@
 		usb_autoresume_device(udev->parent);
 
 exit:
-	module_put(THIS_MODULE);
 	return err;
 
 fail:
@@ -1396,6 +1398,7 @@
 {
 	int ret;
 
+	mutex_lock(&hub->status_mutex);
 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
 	if (ret < 4) {
 		dev_err (hub->intfdev,
@@ -1407,6 +1410,7 @@
 		*change = le16_to_cpu(hub->status->port.wPortChange); 
 		ret = 0;
 	}
+	mutex_unlock(&hub->status_mutex);
 	return ret;
 }
 
@@ -1855,12 +1859,8 @@
 	usb_lock_device(udev);
 	if (udev->state == USB_STATE_SUSPENDED) {
 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
-		status = usb_autoresume_device(udev);
-
-		/* Give the interface drivers a chance to do something,
-		 * then autosuspend the device again. */
-		if (status == 0)
-			usb_autosuspend_device(udev);
+		usb_mark_last_busy(udev);
+		status = usb_external_resume_device(udev);
 	}
 	usb_unlock_device(udev);
 	return status;
@@ -1904,6 +1904,7 @@
 	struct usb_hub		*hub = usb_get_intfdata (intf);
 	struct usb_device	*hdev = hub->hdev;
 	unsigned		port1;
+	int			status = 0;
 
 	/* fail if children aren't already suspended */
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1927,24 +1928,18 @@
 
 	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
 
-	/* "global suspend" of the downstream HC-to-USB interface */
-	if (!hdev->parent) {
-		struct usb_bus	*bus = hdev->bus;
-		if (bus) {
-			int	status = hcd_bus_suspend (bus);
-
-			if (status != 0) {
-				dev_dbg(&hdev->dev, "'global' suspend %d\n",
-					status);
-				return status;
-			}
-		} else
-			return -EOPNOTSUPP;
-	}
-
 	/* stop khubd and related activity */
 	hub_quiesce(hub);
-	return 0;
+
+	/* "global suspend" of the downstream HC-to-USB interface */
+	if (!hdev->parent) {
+		status = hcd_bus_suspend(hdev->bus);
+		if (status != 0) {
+			dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
+			hub_activate(hub);
+		}
+	}
+	return status;
 }
 
 static int hub_resume(struct usb_interface *intf)
@@ -1989,13 +1984,6 @@
 #define hub_resume NULL
 #endif
 
-void usb_resume_root_hub(struct usb_device *hdev)
-{
-	struct usb_hub *hub = hdev_to_hub(hdev);
-
-	kick_khubd(hub);
-}
-
 
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
  *
@@ -2439,7 +2427,7 @@
 
 	if (portchange & USB_PORT_STAT_C_CONNECTION) {
 		status = hub_port_debounce(hub, port1);
-		if (status < 0) {
+		if (status < 0 && printk_ratelimit()) {
 			dev_err (hub_dev,
 				"connect-debounce failed, port %d disabled\n",
 				port1);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 11dad22..cddfc62 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -662,7 +662,7 @@
 	sprintf (name, "%03d", dev->devnum);
 	dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG,
 					    dev->bus->usbfs_dentry, dev,
-					    &usbfs_device_file_operations,
+					    &usbdev_file_operations,
 					    devuid, devgid);
 	if (dev->usbfs_dentry == NULL) {
 		err ("error creating usbfs device entry");
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 8aca357..b743478 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -11,6 +11,7 @@
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
+#include <linux/usb/quirks.h>
 #include <asm/byteorder.h>
 #include <asm/scatterlist.h>
 
@@ -220,10 +221,15 @@
 
 	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 			USB_ENDPOINT_XFER_INT) {
+		int interval;
+
+		if (usb_dev->speed == USB_SPEED_HIGH)
+			interval = 1 << min(15, ep->desc.bInterval - 1);
+		else
+			interval = ep->desc.bInterval;
 		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
 		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
-				usb_api_blocking_completion, NULL,
-				ep->desc.bInterval);
+				usb_api_blocking_completion, NULL, interval);
 	} else
 		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
 				usb_api_blocking_completion, NULL);
@@ -406,10 +412,24 @@
 		io->urbs [i]->status = -EINPROGRESS;
 		io->urbs [i]->actual_length = 0;
 
+		/*
+		 * Some systems need to revert to PIO when DMA is temporarily
+		 * unavailable.  For their sakes, both transfer_buffer and
+		 * transfer_dma are set when possible.  However this can only
+		 * work on systems without HIGHMEM, since DMA buffers located
+		 * in high memory are not directly addressable by the CPU for
+		 * PIO ... so when HIGHMEM is in use, transfer_buffer is NULL
+		 * to prevent stale pointers and to help spot bugs.
+		 */
 		if (dma) {
-			/* hc may use _only_ transfer_dma */
 			io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
 			len = sg_dma_len (sg + i);
+#ifdef CONFIG_HIGHMEM
+			io->urbs[i]->transfer_buffer = NULL;
+#else
+			io->urbs[i]->transfer_buffer =
+				page_address(sg[i].page) + sg[i].offset;
+#endif
 		} else {
 			/* hc may use _only_ transfer_buffer */
 			io->urbs [i]->transfer_buffer =
@@ -685,7 +705,10 @@
 
 	/* Try to read the string descriptor by asking for the maximum
 	 * possible number of bytes */
-	rc = usb_get_string(dev, langid, index, buf, 255);
+	if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
+		rc = -EIO;
+	else
+		rc = usb_get_string(dev, langid, index, buf, 255);
 
 	/* If that failed try to read the descriptor length, then
 	 * ask for just that many bytes */
@@ -1296,7 +1319,7 @@
 	return 0;
 }
 
-static void release_interface(struct device *dev)
+void usb_release_interface(struct device *dev)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_interface_cache *intfc =
@@ -1306,6 +1329,67 @@
 	kfree(intf);
 }
 
+#ifdef	CONFIG_HOTPLUG
+static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
+		 char *buffer, int buffer_size)
+{
+	struct usb_device *usb_dev;
+	struct usb_interface *intf;
+	struct usb_host_interface *alt;
+	int i = 0;
+	int length = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	/* driver is often null here; dev_dbg() would oops */
+	pr_debug ("usb %s: uevent\n", dev->bus_id);
+
+	intf = to_usb_interface(dev);
+	usb_dev = interface_to_usbdev(intf);
+	alt = intf->cur_altsetting;
+
+	if (add_uevent_var(envp, num_envp, &i,
+		   buffer, buffer_size, &length,
+		   "INTERFACE=%d/%d/%d",
+		   alt->desc.bInterfaceClass,
+		   alt->desc.bInterfaceSubClass,
+		   alt->desc.bInterfaceProtocol))
+		return -ENOMEM;
+
+	if (add_uevent_var(envp, num_envp, &i,
+		   buffer, buffer_size, &length,
+		   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+		   le16_to_cpu(usb_dev->descriptor.idVendor),
+		   le16_to_cpu(usb_dev->descriptor.idProduct),
+		   le16_to_cpu(usb_dev->descriptor.bcdDevice),
+		   usb_dev->descriptor.bDeviceClass,
+		   usb_dev->descriptor.bDeviceSubClass,
+		   usb_dev->descriptor.bDeviceProtocol,
+		   alt->desc.bInterfaceClass,
+		   alt->desc.bInterfaceSubClass,
+		   alt->desc.bInterfaceProtocol))
+		return -ENOMEM;
+
+	envp[i] = NULL;
+	return 0;
+}
+
+#else
+
+static int usb_if_uevent(struct device *dev, char **envp,
+			 int num_envp, char *buffer, int buffer_size)
+{
+	return -ENODEV;
+}
+#endif	/* CONFIG_HOTPLUG */
+
+struct device_type usb_if_device_type = {
+	.name =		"usb_interface",
+	.release =	usb_release_interface,
+	.uevent =	usb_if_uevent,
+};
+
 /*
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
@@ -1316,6 +1400,14 @@
  * use this kind of configurability; many devices only have one
  * configuration.
  *
+ * @configuration is the value of the configuration to be installed.
+ * According to the USB spec (e.g. section 9.1.1.5), configuration values
+ * must be non-zero; a value of zero indicates that the device in
+ * unconfigured.  However some devices erroneously use 0 as one of their
+ * configuration values.  To help manage such devices, this routine will
+ * accept @configuration = -1 as indicating the device should be put in
+ * an unconfigured state.
+ *
  * USB device configurations may affect Linux interoperability,
  * power consumption and the functionality available.  For example,
  * the default configuration is limited to using 100mA of bus power,
@@ -1332,7 +1424,7 @@
  *
  * This call is synchronous. The calling context must be able to sleep,
  * must own the device lock, and must not hold the driver model's USB
- * bus rwsem; usb device driver probe() methods cannot use this routine.
+ * bus mutex; usb device driver probe() methods cannot use this routine.
  *
  * Returns zero on success, or else the status code returned by the
  * underlying call that failed.  On successful completion, each interface
@@ -1347,10 +1439,15 @@
 	struct usb_interface **new_interfaces = NULL;
 	int n, nintf;
 
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-		if (dev->config[i].desc.bConfigurationValue == configuration) {
-			cp = &dev->config[i];
-			break;
+	if (configuration == -1)
+		configuration = 0;
+	else {
+		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+			if (dev->config[i].desc.bConfigurationValue ==
+					configuration) {
+				cp = &dev->config[i];
+				break;
+			}
 		}
 	}
 	if ((!cp && configuration != 0))
@@ -1359,6 +1456,7 @@
 	/* The USB spec says configuration 0 means unconfigured.
 	 * But if a device includes a configuration numbered 0,
 	 * we will accept it as a correctly configured state.
+	 * Use -1 if you really want to unconfigure the device.
 	 */
 	if (cp && configuration == 0)
 		dev_warn(&dev->dev, "config 0 descriptor??\n");
@@ -1455,8 +1553,8 @@
 		intf->dev.parent = &dev->dev;
 		intf->dev.driver = NULL;
 		intf->dev.bus = &usb_bus_type;
+		intf->dev.type = &usb_if_device_type;
 		intf->dev.dma_mask = dev->dev.dma_mask;
-		intf->dev.release = release_interface;
 		device_initialize (&intf->dev);
 		mark_quiesced(intf);
 		sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 627a5a2..7f31a49 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -31,7 +31,7 @@
 { USB_DEVICE_INFO(7, 1, 3) },
 #endif
 
-#ifdef	CONFIG_USB_CDCETHER
+#ifdef	CONFIG_USB_NET_CDCETHER
 /* Linux-USB CDC Ethernet gadget */
 { USB_DEVICE(0x0525, 0xa4a1), },
 /* Linux-USB CDC Ethernet + RNDIS gadget */
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
new file mode 100644
index 0000000..739f520
--- /dev/null
+++ b/drivers/usb/core/quirks.c
@@ -0,0 +1,78 @@
+/*
+ * USB device quirk handling logic and table
+ *
+ * Copyright (c) 2007 Oliver Neukum
+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.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, version 2.
+ *
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/quirks.h>
+#include "usb.h"
+
+/* List of quirky USB devices.  Please keep this list ordered by:
+ * 	1) Vendor ID
+ * 	2) Product ID
+ * 	3) Class ID
+ *
+ * as we want specific devices to be overridden first, and only after that, any
+ * class specific quirks.
+ *
+ * Right now the logic aborts if it finds a valid device in the table, we might
+ * want to change that in the future if it turns out that a whole class of
+ * devices is broken...
+ */
+static const struct usb_device_id usb_quirk_list[] = {
+	/* HP 5300/5370C scanner */
+	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+	/* Seiko Epson Corp - Perfection 1670 */
+	{ USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Elsa MicroLink 56k (V.250) */
+	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+	{ }  /* terminating entry must be last */
+};
+
+static void usb_autosuspend_quirk(struct usb_device *udev)
+{
+#ifdef	CONFIG_USB_SUSPEND
+	/* disable autosuspend, but allow the user to re-enable it via sysfs */
+	udev->autosuspend_disabled = 1;
+#endif
+}
+
+static const struct usb_device_id *find_id(struct usb_device *udev)
+{
+	const struct usb_device_id *id = usb_quirk_list;
+
+	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+			id->driver_info; id++) {
+		if (usb_match_device(udev, id))
+			return id;
+	}
+	return NULL;
+}
+
+/*
+ * Detect any quirks the device has, and do any housekeeping for it if needed.
+ */
+void usb_detect_quirks(struct usb_device *udev)
+{
+	const struct usb_device_id *id = usb_quirk_list;
+
+	id = find_id(udev);
+	if (id)
+		udev->quirks = (u32)(id->driver_info);
+	if (udev->quirks)
+		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+				udev->quirks);
+
+	/* do any special quirk handling here if needed */
+	if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
+		usb_autosuspend_quirk(udev);
+}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 4eaa0ee..e7c9823 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -11,6 +11,7 @@
 
 
 #include <linux/kernel.h>
+#include <linux/string.h>
 #include <linux/usb.h>
 #include "usb.h"
 
@@ -63,7 +64,7 @@
 	struct usb_device	*udev = to_usb_device(dev);
 	int			config, value;
 
-	if (sscanf(buf, "%u", &config) != 1 || config > 255)
+	if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255)
 		return -EINVAL;
 	usb_lock_device(udev);
 	value = usb_set_configuration(udev, config);
@@ -117,6 +118,16 @@
 static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL);
 
 static ssize_t
+show_busnum(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+
+	udev = to_usb_device(dev);
+	return sprintf(buf, "%d\n", udev->bus->busnum);
+}
+static DEVICE_ATTR(busnum, S_IRUGO, show_busnum, NULL);
+
+static ssize_t
 show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
@@ -148,6 +159,151 @@
 }
 static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
 
+static ssize_t
+show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+
+	udev = to_usb_device(dev);
+	return sprintf(buf, "0x%x\n", udev->quirks);
+}
+static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+
+#ifdef	CONFIG_USB_SUSPEND
+
+static ssize_t
+show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
+}
+
+static ssize_t
+set_autosuspend(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	int value;
+
+	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
+			value <= - INT_MAX/HZ)
+		return -EINVAL;
+	value *= HZ;
+
+	udev->autosuspend_delay = value;
+	if (value >= 0)
+		usb_try_autosuspend_device(udev);
+	else {
+		if (usb_autoresume_device(udev) == 0)
+			usb_autosuspend_device(udev);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
+		show_autosuspend, set_autosuspend);
+
+static const char on_string[] = "on";
+static const char auto_string[] = "auto";
+static const char suspend_string[] = "suspend";
+
+static ssize_t
+show_level(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	const char *p = auto_string;
+
+	if (udev->state == USB_STATE_SUSPENDED) {
+		if (udev->autoresume_disabled)
+			p = suspend_string;
+	} else {
+		if (udev->autosuspend_disabled)
+			p = on_string;
+	}
+	return sprintf(buf, "%s\n", p);
+}
+
+static ssize_t
+set_level(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	int len = count;
+	char *cp;
+	int rc = 0;
+
+	cp = memchr(buf, '\n', count);
+	if (cp)
+		len = cp - buf;
+
+	usb_lock_device(udev);
+
+	/* Setting the flags without calling usb_pm_lock is a subject to
+	 * races, but who cares...
+	 */
+	if (len == sizeof on_string - 1 &&
+			strncmp(buf, on_string, len) == 0) {
+		udev->autosuspend_disabled = 1;
+		udev->autoresume_disabled = 0;
+		rc = usb_external_resume_device(udev);
+
+	} else if (len == sizeof auto_string - 1 &&
+			strncmp(buf, auto_string, len) == 0) {
+		udev->autosuspend_disabled = 0;
+		udev->autoresume_disabled = 0;
+		rc = usb_external_resume_device(udev);
+
+	} else if (len == sizeof suspend_string - 1 &&
+			strncmp(buf, suspend_string, len) == 0) {
+		udev->autosuspend_disabled = 0;
+		udev->autoresume_disabled = 1;
+		rc = usb_external_suspend_device(udev, PMSG_SUSPEND);
+
+	} else
+		rc = -EINVAL;
+
+	usb_unlock_device(udev);
+	return (rc < 0 ? rc : count);
+}
+
+static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
+
+static char power_group[] = "power";
+
+static int add_power_attributes(struct device *dev)
+{
+	int rc = 0;
+
+	if (is_usb_device(dev)) {
+		rc = sysfs_add_file_to_group(&dev->kobj,
+				&dev_attr_autosuspend.attr,
+				power_group);
+		if (rc == 0)
+			rc = sysfs_add_file_to_group(&dev->kobj,
+					&dev_attr_level.attr,
+					power_group);
+	}
+	return rc;
+}
+
+static void remove_power_attributes(struct device *dev)
+{
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_level.attr,
+			power_group);
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_autosuspend.attr,
+			power_group);
+}
+
+#else
+
+#define add_power_attributes(dev)	0
+#define remove_power_attributes(dev)	do {} while (0)
+
+#endif	/* CONFIG_USB_SUSPEND */
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)			\
 static ssize_t								\
@@ -201,9 +357,11 @@
 	&dev_attr_bNumConfigurations.attr,
 	&dev_attr_bMaxPacketSize0.attr,
 	&dev_attr_speed.attr,
+	&dev_attr_busnum.attr,
 	&dev_attr_devnum.attr,
 	&dev_attr_version.attr,
 	&dev_attr_maxchild.attr,
+	&dev_attr_quirks.attr,
 	NULL,
 };
 static struct attribute_group dev_attr_grp = {
@@ -219,6 +377,10 @@
 	if (retval)
 		return retval;
 
+	retval = add_power_attributes(dev);
+	if (retval)
+		goto error;
+
 	if (udev->manufacturer) {
 		retval = device_create_file(dev, &dev_attr_manufacturer);
 		if (retval)
@@ -239,10 +401,7 @@
 		goto error;
 	return 0;
 error:
-	usb_remove_ep_files(&udev->ep0);
-	device_remove_file(dev, &dev_attr_manufacturer);
-	device_remove_file(dev, &dev_attr_product);
-	device_remove_file(dev, &dev_attr_serial);
+	usb_remove_sysfs_dev_files(udev);
 	return retval;
 }
 
@@ -251,14 +410,11 @@
 	struct device *dev = &udev->dev;
 
 	usb_remove_ep_files(&udev->ep0);
+	device_remove_file(dev, &dev_attr_manufacturer);
+	device_remove_file(dev, &dev_attr_product);
+	device_remove_file(dev, &dev_attr_serial);
+	remove_power_attributes(dev);
 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
-
-	if (udev->manufacturer)
-		device_remove_file(dev, &dev_attr_manufacturer);
-	if (udev->product)
-		device_remove_file(dev, &dev_attr_product);
-	if (udev->serial)
-		device_remove_file(dev, &dev_attr_serial);
 }
 
 /* Interface fields */
@@ -362,33 +518,28 @@
 
 int usb_create_sysfs_intf_files(struct usb_interface *intf)
 {
+	struct device *dev = &intf->dev;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct usb_host_interface *alt = intf->cur_altsetting;
 	int retval;
 
-	retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+	retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
 	if (retval)
-		goto error;
+		return retval;
 
 	if (alt->string == NULL)
 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
 	if (alt->string)
-		retval = device_create_file(&intf->dev, &dev_attr_interface);
+		retval = device_create_file(dev, &dev_attr_interface);
 	usb_create_intf_ep_files(intf, udev);
 	return 0;
-error:
-	if (alt->string)
-		device_remove_file(&intf->dev, &dev_attr_interface);
-	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
-	usb_remove_intf_ep_files(intf);
-	return retval;
 }
 
 void usb_remove_sysfs_intf_files(struct usb_interface *intf)
 {
-	usb_remove_intf_ep_files(intf);
-	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+	struct device *dev = &intf->dev;
 
-	if (intf->cur_altsetting->string)
-		device_remove_file(&intf->dev, &dev_attr_interface);
+	usb_remove_intf_ep_files(intf);
+	device_remove_file(dev, &dev_attr_interface);
+	sysfs_remove_group(&dev->kobj, &intf_attr_grp);
 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 3db721c..dfd1b5c 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
@@ -48,7 +49,18 @@
 
 static int nousb;	/* Disable USB when built into kernel image */
 
-struct workqueue_struct *ksuspend_usb_wq;	/* For autosuspend */
+/* Workqueue for autosuspend and for remote wakeup of root hubs */
+struct workqueue_struct *ksuspend_usb_wq;
+
+#ifdef	CONFIG_USB_SUSPEND
+static int usb_autosuspend_delay = 2;		/* Default delay value,
+						 * in seconds */
+module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
+MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
+
+#else
+#define usb_autosuspend_delay		0
+#endif
 
 
 /**
@@ -185,6 +197,11 @@
 	kfree(udev);
 }
 
+struct device_type usb_device_type = {
+	.name =		"usb_device",
+	.release =	usb_release_dev,
+};
+
 #ifdef	CONFIG_PM
 
 static int ksuspend_usb_init(void)
@@ -200,27 +217,6 @@
 	destroy_workqueue(ksuspend_usb_wq);
 }
 
-#ifdef	CONFIG_USB_SUSPEND
-
-/* usb_autosuspend_work - callback routine to autosuspend a USB device */
-static void usb_autosuspend_work(struct work_struct *work)
-{
-	struct usb_device *udev =
-		container_of(work, struct usb_device, autosuspend.work);
-
-	usb_pm_lock(udev);
-	udev->auto_pm = 1;
-	usb_suspend_both(udev, PMSG_SUSPEND);
-	usb_pm_unlock(udev);
-}
-
-#else
-
-static void usb_autosuspend_work(struct work_struct *work)
-{}
-
-#endif	/* CONFIG_USB_SUSPEND */
-
 #else
 
 #define ksuspend_usb_init()	0
@@ -256,13 +252,10 @@
 
 	device_initialize(&dev->dev);
 	dev->dev.bus = &usb_bus_type;
+	dev->dev.type = &usb_device_type;
 	dev->dev.dma_mask = bus->controller->dma_mask;
-	dev->dev.release = usb_release_dev;
 	dev->state = USB_STATE_ATTACHED;
 
-	/* This magic assignment distinguishes devices from interfaces */
-	dev->dev.platform_data = &usb_generic_driver;
-
 	INIT_LIST_HEAD(&dev->ep0.urb_list);
 	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
@@ -306,6 +299,7 @@
 #ifdef	CONFIG_PM
 	mutex_init(&dev->pm_mutex);
 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
+	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 #endif
 	return dev;
 }
@@ -890,9 +884,9 @@
 	retval = usb_register(&usbfs_driver);
 	if (retval)
 		goto driver_register_failed;
-	retval = usbdev_init();
+	retval = usb_devio_init();
 	if (retval)
-		goto usbdevice_init_failed;
+		goto usb_devio_init_failed;
 	retval = usbfs_init();
 	if (retval)
 		goto fs_init_failed;
@@ -907,8 +901,8 @@
 hub_init_failed:
 	usbfs_cleanup();
 fs_init_failed:
-	usbdev_cleanup();
-usbdevice_init_failed:
+	usb_devio_cleanup();
+usb_devio_init_failed:
 	usb_deregister(&usbfs_driver);
 driver_register_failed:
 	usb_major_cleanup();
@@ -935,7 +929,7 @@
 	usb_major_cleanup();
 	usbfs_cleanup();
 	usb_deregister(&usbfs_driver);
-	usbdev_cleanup();
+	usb_devio_cleanup();
 	usb_hub_cleanup();
 	usb_host_cleanup();
 	bus_unregister(&usb_bus_type);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 17830a8..bf2eb0d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -13,6 +13,7 @@
 		struct usb_interface *intf);
 extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
+extern void usb_detect_quirks(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
 		unsigned int size);
@@ -20,7 +21,8 @@
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_kick_khubd(struct usb_device *dev);
-extern void usb_resume_root_hub(struct usb_device *dev);
+extern int usb_match_device(struct usb_device *dev,
+			    const struct usb_device_id *id);
 
 extern int  usb_hub_init(void);
 extern void usb_hub_cleanup(void);
@@ -31,10 +33,12 @@
 
 #ifdef	CONFIG_PM
 
-extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
-extern int usb_resume_both(struct usb_device *udev);
+extern void usb_autosuspend_work(struct work_struct *work);
 extern int usb_port_suspend(struct usb_device *dev);
 extern int usb_port_resume(struct usb_device *dev);
+extern int usb_external_suspend_device(struct usb_device *udev,
+		pm_message_t msg);
+extern int usb_external_resume_device(struct usb_device *udev);
 
 static inline void usb_pm_lock(struct usb_device *udev)
 {
@@ -48,11 +52,6 @@
 
 #else
 
-#define usb_suspend_both(udev, msg)	0
-static inline int usb_resume_both(struct usb_device *udev)
-{
-	return 0;
-}
 #define usb_port_suspend(dev)		0
 #define usb_port_resume(dev)		0
 static inline void usb_pm_lock(struct usb_device *udev) {}
@@ -62,14 +61,14 @@
 
 #ifdef CONFIG_USB_SUSPEND
 
-#define USB_AUTOSUSPEND_DELAY	(HZ*2)
-
 extern void usb_autosuspend_device(struct usb_device *udev);
+extern void usb_try_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 
 #else
 
-#define usb_autosuspend_device(udev)	do {} while (0)
+#define usb_autosuspend_device(udev)		do {} while (0)
+#define usb_try_autosuspend_device(udev)	do {} while (0)
 static inline int usb_autoresume_device(struct usb_device *udev)
 {
 	return 0;
@@ -79,15 +78,13 @@
 
 extern struct workqueue_struct *ksuspend_usb_wq;
 extern struct bus_type usb_bus_type;
+extern struct device_type usb_device_type;
+extern struct device_type usb_if_device_type;
 extern struct usb_device_driver usb_generic_driver;
 
-/* Here's how we tell apart devices and interfaces.  Luckily there's
- * no such thing as a platform USB device, so we can steal the use
- * of the platform_data field. */
-
 static inline int is_usb_device(const struct device *dev)
 {
-	return dev->platform_data == &usb_generic_driver;
+	return dev->type == &usb_device_type;
 }
 
 /* Do the same for device drivers and interface drivers. */
@@ -123,11 +120,11 @@
 extern struct mutex usbfs_mutex;
 extern struct usb_driver usbfs_driver;
 extern const struct file_operations usbfs_devices_fops;
-extern const struct file_operations usbfs_device_file_operations;
+extern const struct file_operations usbdev_file_operations;
 extern void usbfs_conn_disc_event(void);
 
-extern int usbdev_init(void);
-extern void usbdev_cleanup(void);
+extern int usb_devio_init(void);
+extern void usb_devio_cleanup(void);
 
 struct dev_state {
 	struct list_head list;      /* state list */
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 4097a86..8065f2b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -68,6 +68,27 @@
 	   Many controller drivers are platform-specific; these
 	   often need board-specific hooks.
 
+config USB_GADGET_FSL_USB2
+	boolean "Freescale Highspeed USB DR Peripheral Controller"
+	depends on MPC834x || PPC_MPC831x
+	select USB_GADGET_DUALSPEED
+	help
+	   Some of Freescale PowerPC processors have a High Speed
+	   Dual-Role(DR) USB controller, which supports device mode.
+
+	   The number of programmable endpoints is different through
+	   SOC revisions.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "fsl_usb2_udc" and force
+	   all gadget drivers to also be dynamically linked.
+
+config USB_FSL_USB2
+	tristate
+	depends on USB_GADGET_FSL_USB2
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
 config USB_GADGET_NET2280
 	boolean "NetChip 228x"
 	depends on PCI
@@ -370,6 +391,7 @@
 
 config USB_FILE_STORAGE
 	tristate "File-backed Storage Gadget"
+	depends on BLOCK
 	help
 	  The File-backed Storage Gadget acts as a USB Mass Storage
 	  disk drive.  As its storage repository it can use a regular
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index e71e086..5db1939 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
 obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
 obj-$(CONFIG_USB_AT91)		+= at91_udc.o
+obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
 
 #
 # USB gadget drivers
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 36b36e0..2a6e316 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -784,7 +784,7 @@
 	return status;
 }
 
-static struct usb_ep_ops at91_ep_ops = {
+static const struct usb_ep_ops at91_ep_ops = {
 	.enable		= at91_ep_enable,
 	.disable	= at91_ep_disable,
 	.alloc_request	= at91_ep_alloc_request,
@@ -912,7 +912,7 @@
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
 		if (cpu_is_at91rm9200())
 			at91_set_gpio_value(udc->board.pullup_pin, 1);
-		else if (cpu_is_at91sam9260()) {
+		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 			txvc |= AT91_UDP_TXVC_PUON;
@@ -929,7 +929,7 @@
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		if (cpu_is_at91rm9200())
 			at91_set_gpio_value(udc->board.pullup_pin, 0);
-		else if (cpu_is_at91sam9260()) {
+		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 			txvc &= ~AT91_UDP_TXVC_PUON;
@@ -1651,7 +1651,7 @@
 	pullup(platform_get_drvdata(dev), 0);
 }
 
-static int __devinit at91udc_probe(struct platform_device *pdev)
+static int __init at91udc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct at91_udc	*udc;
@@ -1762,7 +1762,7 @@
 	return retval;
 }
 
-static int __devexit at91udc_remove(struct platform_device *pdev)
+static int __exit at91udc_remove(struct platform_device *pdev)
 {
 	struct at91_udc *udc = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -1835,9 +1835,8 @@
 #define	at91udc_resume	NULL
 #endif
 
-static struct platform_driver at91_udc = {
-	.probe		= at91udc_probe,
-	.remove		= __devexit_p(at91udc_remove),
+static struct platform_driver at91_udc_driver = {
+	.remove		= __exit_p(at91udc_remove),
 	.shutdown	= at91udc_shutdown,
 	.suspend	= at91udc_suspend,
 	.resume		= at91udc_resume,
@@ -1847,15 +1846,15 @@
 	},
 };
 
-static int __devinit udc_init_module(void)
+static int __init udc_init_module(void)
 {
-	return platform_driver_register(&at91_udc);
+	return platform_driver_probe(&at91_udc_driver, at91udc_probe);
 }
 module_init(udc_init_module);
 
-static void __devexit udc_exit_module(void)
+static void __exit udc_exit_module(void)
 {
-	platform_driver_unregister(&at91_udc);
+	platform_driver_unregister(&at91_udc_driver);
 }
 module_exit(udc_exit_module);
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 04e6b85..1dd8b57 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -282,6 +282,9 @@
 #define DEV_CONFIG_CDC
 #endif
 
+#ifdef CONFIG_USB_GADGET_FSL_USB2
+#define DEV_CONFIG_CDC
+#endif
 
 /* For CDC-incapable hardware, choose the simple cdc subset.
  * Anything that talks bulk (without notable bugs) can do this.
@@ -1735,7 +1738,8 @@
 		defer_kevent (dev, WORK_RX_MEMORY);
 	if (retval) {
 		DEBUG (dev, "rx submit --> %d\n", retval);
-		dev_kfree_skb_any (skb);
+		if (skb)
+			dev_kfree_skb_any(skb);
 		spin_lock(&dev->req_lock);
 		list_add (&req->list, &dev->rx_reqs);
 		spin_unlock(&dev->req_lock);
@@ -1766,7 +1770,6 @@
 			break;
 		}
 
-		skb->dev = dev->net;
 		skb->protocol = eth_type_trans (skb, dev->net);
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += skb->len;
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
new file mode 100644
index 0000000..157054e
--- /dev/null
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -0,0 +1,2500 @@
+/*
+ * Copyright (C) 2004-2007 Freescale Semicondutor, Inc. All rights reserved.
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ *         Jiang Bo <tanya.jiang@freescale.com>
+ *
+ * Description:
+ * Freescale high-speed USB SOC DR module device controller driver.
+ * This can be found on MPC8349E/MPC8313E cpus.
+ * The driver is previously named as mpc_udc.  Based on bare board
+ * code from Dave Liu and Shlomi Gridish.
+ *
+ * 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.
+ */
+
+#undef VERBOSE
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/dmapool.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/dma.h>
+#include <asm/cacheflush.h>
+
+#include "fsl_usb2_udc.h"
+
+#define	DRIVER_DESC	"Freescale High-Speed USB SOC Device Controller driver"
+#define	DRIVER_AUTHOR	"Li Yang/Jiang Bo"
+#define	DRIVER_VERSION	"Apr 20, 2007"
+
+#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+static const char driver_name[] = "fsl-usb2-udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+volatile static struct usb_dr_device *dr_regs = NULL;
+volatile static struct usb_sys_interface *usb_sys_regs = NULL;
+
+/* it is initialized in probe()  */
+static struct fsl_udc *udc_controller = NULL;
+
+static const struct usb_endpoint_descriptor
+fsl_ep0_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	0,
+	.bmAttributes =		USB_ENDPOINT_XFER_CONTROL,
+	.wMaxPacketSize =	USB_MAX_CTRL_PAYLOAD,
+};
+
+static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state);
+static int fsl_udc_resume(struct platform_device *pdev);
+static void fsl_ep_fifo_flush(struct usb_ep *_ep);
+
+#ifdef CONFIG_PPC32
+#define fsl_readl(addr)		in_le32(addr)
+#define fsl_writel(addr, val32) out_le32(val32, addr)
+#else
+#define fsl_readl(addr)		readl(addr)
+#define fsl_writel(addr, val32) writel(addr, val32)
+#endif
+
+/********************************************************************
+ *	Internal Used Function
+********************************************************************/
+/*-----------------------------------------------------------------
+ * done() - retire a request; caller blocked irqs
+ * @status : request status to be set, only works when
+ *	request is still in progress.
+ *--------------------------------------------------------------*/
+static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
+{
+	struct fsl_udc *udc = NULL;
+	unsigned char stopped = ep->stopped;
+	struct ep_td_struct *curr_td, *next_td;
+	int j;
+
+	udc = (struct fsl_udc *)ep->udc;
+	/* Removed the req from fsl_ep->queue */
+	list_del_init(&req->queue);
+
+	/* req.status should be set as -EINPROGRESS in ep_queue() */
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	/* Free dtd for the request */
+	next_td = req->head;
+	for (j = 0; j < req->dtd_count; j++) {
+		curr_td = next_td;
+		if (j != req->dtd_count - 1) {
+			next_td = curr_td->next_td_virt;
+		}
+		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
+	}
+
+	if (req->mapped) {
+		dma_unmap_single(ep->udc->gadget.dev.parent,
+			req->req.dma, req->req.length,
+			ep_is_in(ep)
+				? DMA_TO_DEVICE
+				: DMA_FROM_DEVICE);
+		req->req.dma = DMA_ADDR_INVALID;
+		req->mapped = 0;
+	} else
+		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
+			req->req.dma, req->req.length,
+			ep_is_in(ep)
+				? DMA_TO_DEVICE
+				: DMA_FROM_DEVICE);
+
+	if (status && (status != -ESHUTDOWN))
+		VDBG("complete %s req %p stat %d len %u/%u",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length);
+
+	ep->stopped = 1;
+
+	spin_unlock(&ep->udc->lock);
+	/* complete() is from gadget layer,
+	 * eg fsg->bulk_in_complete() */
+	if (req->req.complete)
+		req->req.complete(&ep->ep, &req->req);
+
+	spin_lock(&ep->udc->lock);
+	ep->stopped = stopped;
+}
+
+/*-----------------------------------------------------------------
+ * nuke(): delete all requests related to this ep
+ * called with spinlock held
+ *--------------------------------------------------------------*/
+static void nuke(struct fsl_ep *ep, int status)
+{
+	ep->stopped = 1;
+
+	/* Flush fifo */
+	fsl_ep_fifo_flush(&ep->ep);
+
+	/* Whether this eq has request linked */
+	while (!list_empty(&ep->queue)) {
+		struct fsl_req *req = NULL;
+
+		req = list_entry(ep->queue.next, struct fsl_req, queue);
+		done(ep, req, status);
+	}
+}
+
+/*------------------------------------------------------------------
+	Internal Hardware related function
+ ------------------------------------------------------------------*/
+
+static int dr_controller_setup(struct fsl_udc *udc)
+{
+	unsigned int tmp = 0, portctrl = 0, ctrl = 0;
+	unsigned long timeout;
+#define FSL_UDC_RESET_TIMEOUT 1000
+
+	/* before here, make sure dr_regs has been initialized */
+	if (!udc)
+		return -EINVAL;
+
+	/* Stop and reset the usb controller */
+	tmp = fsl_readl(&dr_regs->usbcmd);
+	tmp &= ~USB_CMD_RUN_STOP;
+	fsl_writel(tmp, &dr_regs->usbcmd);
+
+	tmp = fsl_readl(&dr_regs->usbcmd);
+	tmp |= USB_CMD_CTRL_RESET;
+	fsl_writel(tmp, &dr_regs->usbcmd);
+
+	/* Wait for reset to complete */
+	timeout = jiffies + FSL_UDC_RESET_TIMEOUT;
+	while (fsl_readl(&dr_regs->usbcmd) & USB_CMD_CTRL_RESET) {
+		if (time_after(jiffies, timeout)) {
+			ERR("udc reset timeout! \n");
+			return -ETIMEDOUT;
+		}
+		cpu_relax();
+	}
+
+	/* Set the controller as device mode */
+	tmp = fsl_readl(&dr_regs->usbmode);
+	tmp |= USB_MODE_CTRL_MODE_DEVICE;
+	/* Disable Setup Lockout */
+	tmp |= USB_MODE_SETUP_LOCK_OFF;
+	fsl_writel(tmp, &dr_regs->usbmode);
+
+	/* Clear the setup status */
+	fsl_writel(0, &dr_regs->usbsts);
+
+	tmp = udc->ep_qh_dma;
+	tmp &= USB_EP_LIST_ADDRESS_MASK;
+	fsl_writel(tmp, &dr_regs->endpointlistaddr);
+
+	VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x",
+		(int)udc->ep_qh, (int)tmp,
+		fsl_readl(&dr_regs->endpointlistaddr));
+
+	/* Config PHY interface */
+	portctrl = fsl_readl(&dr_regs->portsc1);
+	portctrl &= ~PORTSCX_PHY_TYPE_SEL;
+	switch (udc->phy_mode) {
+	case FSL_USB2_PHY_ULPI:
+		portctrl |= PORTSCX_PTS_ULPI;
+		break;
+	case FSL_USB2_PHY_UTMI:
+	case FSL_USB2_PHY_UTMI_WIDE:
+		portctrl |= PORTSCX_PTS_UTMI;
+		break;
+	case FSL_USB2_PHY_SERIAL:
+		portctrl |= PORTSCX_PTS_FSLS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	fsl_writel(portctrl, &dr_regs->portsc1);
+
+	/* Config control enable i/o output, cpu endian register */
+	ctrl = __raw_readl(&usb_sys_regs->control);
+	ctrl |= USB_CTRL_IOENB;
+	__raw_writel(ctrl, &usb_sys_regs->control);
+
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+	/* Turn on cache snooping hardware, since some PowerPC platforms
+	 * wholly rely on hardware to deal with cache coherent. */
+
+	/* Setup Snooping for all the 4GB space */
+	tmp = SNOOP_SIZE_2GB;	/* starts from 0x0, size 2G */
+	__raw_writel(tmp, &usb_sys_regs->snoop1);
+	tmp |= 0x80000000;	/* starts from 0x8000000, size 2G */
+	__raw_writel(tmp, &usb_sys_regs->snoop2);
+#endif
+
+	return 0;
+}
+
+/* Enable DR irq and set controller to run state */
+static void dr_controller_run(struct fsl_udc *udc)
+{
+	u32 temp;
+
+	/* Enable DR irq reg */
+	temp = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN
+		| USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN
+		| USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN;
+
+	fsl_writel(temp, &dr_regs->usbintr);
+
+	/* Clear stopped bit */
+	udc->stopped = 0;
+
+	/* Set the controller as device mode */
+	temp = fsl_readl(&dr_regs->usbmode);
+	temp |= USB_MODE_CTRL_MODE_DEVICE;
+	fsl_writel(temp, &dr_regs->usbmode);
+
+	/* Set controller to Run */
+	temp = fsl_readl(&dr_regs->usbcmd);
+	temp |= USB_CMD_RUN_STOP;
+	fsl_writel(temp, &dr_regs->usbcmd);
+
+	return;
+}
+
+static void dr_controller_stop(struct fsl_udc *udc)
+{
+	unsigned int tmp;
+
+	/* disable all INTR */
+	fsl_writel(0, &dr_regs->usbintr);
+
+	/* Set stopped bit for isr */
+	udc->stopped = 1;
+
+	/* disable IO output */
+/*	usb_sys_regs->control = 0; */
+
+	/* set controller to Stop */
+	tmp = fsl_readl(&dr_regs->usbcmd);
+	tmp &= ~USB_CMD_RUN_STOP;
+	fsl_writel(tmp, &dr_regs->usbcmd);
+
+	return;
+}
+
+void dr_ep_setup(unsigned char ep_num, unsigned char dir, unsigned char ep_type)
+{
+	unsigned int tmp_epctrl = 0;
+
+	tmp_epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+	if (dir) {
+		if (ep_num)
+			tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
+		tmp_epctrl |= EPCTRL_TX_ENABLE;
+		tmp_epctrl |= ((unsigned int)(ep_type)
+				<< EPCTRL_TX_EP_TYPE_SHIFT);
+	} else {
+		if (ep_num)
+			tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
+		tmp_epctrl |= EPCTRL_RX_ENABLE;
+		tmp_epctrl |= ((unsigned int)(ep_type)
+				<< EPCTRL_RX_EP_TYPE_SHIFT);
+	}
+
+	fsl_writel(tmp_epctrl, &dr_regs->endptctrl[ep_num]);
+}
+
+static void
+dr_ep_change_stall(unsigned char ep_num, unsigned char dir, int value)
+{
+	u32 tmp_epctrl = 0;
+
+	tmp_epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+
+	if (value) {
+		/* set the stall bit */
+		if (dir)
+			tmp_epctrl |= EPCTRL_TX_EP_STALL;
+		else
+			tmp_epctrl |= EPCTRL_RX_EP_STALL;
+	} else {
+		/* clear the stall bit and reset data toggle */
+		if (dir) {
+			tmp_epctrl &= ~EPCTRL_TX_EP_STALL;
+			tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
+		} else {
+			tmp_epctrl &= ~EPCTRL_RX_EP_STALL;
+			tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
+		}
+	}
+	fsl_writel(tmp_epctrl, &dr_regs->endptctrl[ep_num]);
+}
+
+/* Get stall status of a specific ep
+   Return: 0: not stalled; 1:stalled */
+static int dr_ep_get_stall(unsigned char ep_num, unsigned char dir)
+{
+	u32 epctrl;
+
+	epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+	if (dir)
+		return (epctrl & EPCTRL_TX_EP_STALL) ? 1 : 0;
+	else
+		return (epctrl & EPCTRL_RX_EP_STALL) ? 1 : 0;
+}
+
+/********************************************************************
+	Internal Structure Build up functions
+********************************************************************/
+
+/*------------------------------------------------------------------
+* struct_ep_qh_setup(): set the Endpoint Capabilites field of QH
+ * @zlt: Zero Length Termination Select (1: disable; 0: enable)
+ * @mult: Mult field
+ ------------------------------------------------------------------*/
+static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
+		unsigned char dir, unsigned char ep_type,
+		unsigned int max_pkt_len,
+		unsigned int zlt, unsigned char mult)
+{
+	struct ep_queue_head *p_QH = &udc->ep_qh[2 * ep_num + dir];
+	unsigned int tmp = 0;
+
+	/* set the Endpoint Capabilites in QH */
+	switch (ep_type) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		/* Interrupt On Setup (IOS). for control ep  */
+		tmp = (max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+			| EP_QUEUE_HEAD_IOS;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		tmp = (max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+			| (mult << EP_QUEUE_HEAD_MULT_POS);
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+	case USB_ENDPOINT_XFER_INT:
+		tmp = max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS;
+		break;
+	default:
+		VDBG("error ep type is %d", ep_type);
+		return;
+	}
+	if (zlt)
+		tmp |= EP_QUEUE_HEAD_ZLT_SEL;
+	p_QH->max_pkt_length = cpu_to_le32(tmp);
+
+	return;
+}
+
+/* Setup qh structure and ep register for ep0. */
+static void ep0_setup(struct fsl_udc *udc)
+{
+	/* the intialization of an ep includes: fields in QH, Regs,
+	 * fsl_ep struct */
+	struct_ep_qh_setup(udc, 0, USB_RECV, USB_ENDPOINT_XFER_CONTROL,
+			USB_MAX_CTRL_PAYLOAD, 0, 0);
+	struct_ep_qh_setup(udc, 0, USB_SEND, USB_ENDPOINT_XFER_CONTROL,
+			USB_MAX_CTRL_PAYLOAD, 0, 0);
+	dr_ep_setup(0, USB_RECV, USB_ENDPOINT_XFER_CONTROL);
+	dr_ep_setup(0, USB_SEND, USB_ENDPOINT_XFER_CONTROL);
+
+	return;
+
+}
+
+/***********************************************************************
+		Endpoint Management Functions
+***********************************************************************/
+
+/*-------------------------------------------------------------------------
+ * when configurations are set, or when interface settings change
+ * for example the do_set_interface() in gadget layer,
+ * the driver will enable or disable the relevant endpoints
+ * ep0 doesn't use this routine. It is always enabled.
+-------------------------------------------------------------------------*/
+static int fsl_ep_enable(struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
+{
+	struct fsl_udc *udc = NULL;
+	struct fsl_ep *ep = NULL;
+	unsigned short max = 0;
+	unsigned char mult = 0, zlt;
+	int retval = -EINVAL;
+	unsigned long flags = 0;
+
+	ep = container_of(_ep, struct fsl_ep, ep);
+
+	/* catch various bogus parameters */
+	if (!_ep || !desc || ep->desc
+			|| (desc->bDescriptorType != USB_DT_ENDPOINT))
+		return -EINVAL;
+
+	udc = ep->udc;
+
+	if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+
+	max = le16_to_cpu(desc->wMaxPacketSize);
+
+	/* Disable automatic zlp generation.  Driver is reponsible to indicate
+	 * explicitly through req->req.zero.  This is needed to enable multi-td
+	 * request. */
+	zlt = 1;
+
+	/* Assume the max packet size from gadget is always correct */
+	switch (desc->bmAttributes & 0x03) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+	case USB_ENDPOINT_XFER_INT:
+		/* mult = 0.  Execute N Transactions as demonstrated by
+		 * the USB variable length packet protocol where N is
+		 * computed using the Maximum Packet Length (dQH) and
+		 * the Total Bytes field (dTD) */
+		mult = 0;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		/* Calculate transactions needed for high bandwidth iso */
+		mult = (unsigned char)(1 + ((max >> 11) & 0x03));
+		max = max & 0x8ff;	/* bit 0~10 */
+		/* 3 transactions at most */
+		if (mult > 3)
+			goto en_done;
+		break;
+	default:
+		goto en_done;
+	}
+
+	spin_lock_irqsave(&udc->lock, flags);
+	ep->ep.maxpacket = max;
+	ep->desc = desc;
+	ep->stopped = 0;
+
+	/* Controller related setup */
+	/* Init EPx Queue Head (Ep Capabilites field in QH
+	 * according to max, zlt, mult) */
+	struct_ep_qh_setup(udc, (unsigned char) ep_index(ep),
+			(unsigned char) ((desc->bEndpointAddress & USB_DIR_IN)
+					?  USB_SEND : USB_RECV),
+			(unsigned char) (desc->bmAttributes
+					& USB_ENDPOINT_XFERTYPE_MASK),
+			max, zlt, mult);
+
+	/* Init endpoint ctrl register */
+	dr_ep_setup((unsigned char) ep_index(ep),
+			(unsigned char) ((desc->bEndpointAddress & USB_DIR_IN)
+					? USB_SEND : USB_RECV),
+			(unsigned char) (desc->bmAttributes
+					& USB_ENDPOINT_XFERTYPE_MASK));
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+	retval = 0;
+
+	VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name,
+			ep->desc->bEndpointAddress & 0x0f,
+			(desc->bEndpointAddress & USB_DIR_IN)
+				? "in" : "out", max);
+en_done:
+	return retval;
+}
+
+/*---------------------------------------------------------------------
+ * @ep : the ep being unconfigured. May not be ep0
+ * Any pending and uncomplete req will complete with status (-ESHUTDOWN)
+*---------------------------------------------------------------------*/
+static int fsl_ep_disable(struct usb_ep *_ep)
+{
+	struct fsl_udc *udc = NULL;
+	struct fsl_ep *ep = NULL;
+	unsigned long flags = 0;
+	u32 epctrl;
+	int ep_num;
+
+	ep = container_of(_ep, struct fsl_ep, ep);
+	if (!_ep || !ep->desc) {
+		VDBG("%s not enabled", _ep ? ep->ep.name : NULL);
+		return -EINVAL;
+	}
+
+	/* disable ep on controller */
+	ep_num = ep_index(ep);
+	epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+	if (ep_is_in(ep))
+		epctrl &= ~EPCTRL_TX_ENABLE;
+	else
+		epctrl &= ~EPCTRL_RX_ENABLE;
+	fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+
+	udc = (struct fsl_udc *)ep->udc;
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* nuke all pending requests (does flush) */
+	nuke(ep, -ESHUTDOWN);
+
+	ep->desc = 0;
+	ep->stopped = 1;
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	VDBG("disabled %s OK", _ep->name);
+	return 0;
+}
+
+/*---------------------------------------------------------------------
+ * allocate a request object used by this endpoint
+ * the main operation is to insert the req->queue to the eq->queue
+ * Returns the request, or null if one could not be allocated
+*---------------------------------------------------------------------*/
+static struct usb_request *
+fsl_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct fsl_req *req = NULL;
+
+	req = kzalloc(sizeof *req, gfp_flags);
+	if (!req)
+		return NULL;
+
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct fsl_req *req = NULL;
+
+	req = container_of(_req, struct fsl_req, req);
+
+	if (_req)
+		kfree(req);
+}
+
+/*------------------------------------------------------------------
+ * Allocate an I/O buffer
+*---------------------------------------------------------------------*/
+static void *fsl_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
+		dma_addr_t *dma, gfp_t gfp_flags)
+{
+	struct fsl_ep *ep;
+
+	if (!_ep)
+		return NULL;
+
+	ep = container_of(_ep, struct fsl_ep, ep);
+
+	return dma_alloc_coherent(ep->udc->gadget.dev.parent,
+			bytes, dma, gfp_flags);
+}
+
+/*------------------------------------------------------------------
+ * frees an i/o buffer
+*---------------------------------------------------------------------*/
+static void fsl_free_buffer(struct usb_ep *_ep, void *buf,
+		dma_addr_t dma, unsigned bytes)
+{
+	struct fsl_ep *ep;
+
+	if (!_ep)
+		return NULL;
+
+	ep = container_of(_ep, struct fsl_ep, ep);
+
+	dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
+}
+
+/*-------------------------------------------------------------------------*/
+static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
+{
+	int i = ep_index(ep) * 2 + ep_is_in(ep);
+	u32 temp, bitmask, tmp_stat;
+	struct ep_queue_head *dQH = &ep->udc->ep_qh[i];
+
+	/* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);
+	VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */
+
+	bitmask = ep_is_in(ep)
+		? (1 << (ep_index(ep) + 16))
+		: (1 << (ep_index(ep)));
+
+	/* check if the pipe is empty */
+	if (!(list_empty(&ep->queue))) {
+		/* Add td to the end */
+		struct fsl_req *lastreq;
+		lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
+		lastreq->tail->next_td_ptr =
+			cpu_to_le32(req->head->td_dma & DTD_ADDR_MASK);
+		/* Read prime bit, if 1 goto done */
+		if (fsl_readl(&dr_regs->endpointprime) & bitmask)
+			goto out;
+
+		do {
+			/* Set ATDTW bit in USBCMD */
+			temp = fsl_readl(&dr_regs->usbcmd);
+			fsl_writel(temp | USB_CMD_ATDTW, &dr_regs->usbcmd);
+
+			/* Read correct status bit */
+			tmp_stat = fsl_readl(&dr_regs->endptstatus) & bitmask;
+
+		} while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_ATDTW));
+
+		/* Write ATDTW bit to 0 */
+		temp = fsl_readl(&dr_regs->usbcmd);
+		fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);
+
+		if (tmp_stat)
+			goto out;
+	}
+
+	/* Write dQH next pointer and terminate bit to 0 */
+	temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
+	dQH->next_dtd_ptr = cpu_to_le32(temp);
+
+	/* Clear active and halt bit */
+	temp = cpu_to_le32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
+			| EP_QUEUE_HEAD_STATUS_HALT));
+	dQH->size_ioc_int_sts &= temp;
+
+	/* Prime endpoint by writing 1 to ENDPTPRIME */
+	temp = ep_is_in(ep)
+		? (1 << (ep_index(ep) + 16))
+		: (1 << (ep_index(ep)));
+	fsl_writel(temp, &dr_regs->endpointprime);
+out:
+	return 0;
+}
+
+/* Fill in the dTD structure
+ * @req: request that the transfer belongs to
+ * @length: return actually data length of the dTD
+ * @dma: return dma address of the dTD
+ * @is_last: return flag if it is the last dTD of the request
+ * return: pointer to the built dTD */
+static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
+		dma_addr_t *dma, int *is_last)
+{
+	u32 swap_temp;
+	struct ep_td_struct *dtd;
+
+	/* how big will this transfer be? */
+	*length = min(req->req.length - req->req.actual,
+			(unsigned)EP_MAX_LENGTH_TRANSFER);
+
+	dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+	if (dtd == NULL)
+		return dtd;
+
+	dtd->td_dma = *dma;
+	/* Clear reserved field */
+	swap_temp = cpu_to_le32(dtd->size_ioc_sts);
+	swap_temp &= ~DTD_RESERVED_FIELDS;
+	dtd->size_ioc_sts = cpu_to_le32(swap_temp);
+
+	/* Init all of buffer page pointers */
+	swap_temp = (u32) (req->req.dma + req->req.actual);
+	dtd->buff_ptr0 = cpu_to_le32(swap_temp);
+	dtd->buff_ptr1 = cpu_to_le32(swap_temp + 0x1000);
+	dtd->buff_ptr2 = cpu_to_le32(swap_temp + 0x2000);
+	dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000);
+	dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000);
+
+	req->req.actual += *length;
+
+	/* zlp is needed if req->req.zero is set */
+	if (req->req.zero) {
+		if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+			*is_last = 1;
+		else
+			*is_last = 0;
+	} else if (req->req.length == req->req.actual)
+		*is_last = 1;
+	else
+		*is_last = 0;
+
+	if ((*is_last) == 0)
+		VDBG("multi-dtd request!\n");
+	/* Fill in the transfer size; set active bit */
+	swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
+
+	/* Enable interrupt for the last dtd of a request */
+	if (*is_last && !req->req.no_interrupt)
+		swap_temp |= DTD_IOC;
+
+	dtd->size_ioc_sts = cpu_to_le32(swap_temp);
+
+	mb();
+
+	VDBG("length = %d address= 0x%x", *length, (int)*dma);
+
+	return dtd;
+}
+
+/* Generate dtd chain for a request */
+static int fsl_req_to_dtd(struct fsl_req *req)
+{
+	unsigned	count;
+	int		is_last;
+	int		is_first =1;
+	struct ep_td_struct	*last_dtd = NULL, *dtd;
+	dma_addr_t dma;
+
+	do {
+		dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+		if (dtd == NULL)
+			return -ENOMEM;
+
+		if (is_first) {
+			is_first = 0;
+			req->head = dtd;
+		} else {
+			last_dtd->next_td_ptr = cpu_to_le32(dma);
+			last_dtd->next_td_virt = dtd;
+		}
+		last_dtd = dtd;
+
+		req->dtd_count++;
+	} while (!is_last);
+
+	dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE);
+
+	req->tail = dtd;
+
+	return 0;
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int
+fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
+	struct fsl_req *req = container_of(_req, struct fsl_req, req);
+	struct fsl_udc *udc;
+	unsigned long flags;
+	int is_iso = 0;
+
+	/* catch various bogus parameters */
+	if (!_req || !req->req.complete || !req->req.buf
+			|| !list_empty(&req->queue)) {
+		VDBG("%s, bad params\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (!_ep || (!ep->desc && ep_index(ep))) {
+		VDBG("%s, bad ep\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		if (req->req.length > ep->ep.maxpacket)
+			return -EMSGSIZE;
+		is_iso = 1;
+	}
+
+	udc = ep->udc;
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	req->ep = ep;
+
+	/* map virtual address to hardware */
+	if (req->req.dma == DMA_ADDR_INVALID) {
+		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
+					req->req.buf,
+					req->req.length, ep_is_in(ep)
+						? DMA_TO_DEVICE
+						: DMA_FROM_DEVICE);
+		req->mapped = 1;
+	} else {
+		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
+					req->req.dma, req->req.length,
+					ep_is_in(ep)
+						? DMA_TO_DEVICE
+						: DMA_FROM_DEVICE);
+		req->mapped = 0;
+	}
+
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	req->dtd_count = 0;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* build dtds and push them to device queue */
+	if (!fsl_req_to_dtd(req)) {
+		fsl_queue_td(ep, req);
+	} else {
+		spin_unlock_irqrestore(&udc->lock, flags);
+		return -ENOMEM;
+	}
+
+	/* Update ep0 state */
+	if ((ep_index(ep) == 0))
+		udc->ep0_state = DATA_STATE_XMIT;
+
+	/* irq handler advances the queue */
+	if (req != NULL)
+		list_add_tail(&req->queue, &ep->queue);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
+	struct fsl_req *req;
+	unsigned long flags;
+	int ep_num, stopped, ret = 0;
+	u32 epctrl;
+
+	if (!_ep || !_req)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+	stopped = ep->stopped;
+
+	/* Stop the ep before we deal with the queue */
+	ep->stopped = 1;
+	ep_num = ep_index(ep);
+	epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+	if (ep_is_in(ep))
+		epctrl &= ~EPCTRL_TX_ENABLE;
+	else
+		epctrl &= ~EPCTRL_RX_ENABLE;
+	fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* The request is in progress, or completed but not dequeued */
+	if (ep->queue.next == &req->queue) {
+		_req->status = -ECONNRESET;
+		fsl_ep_fifo_flush(_ep);	/* flush current transfer */
+
+		/* The request isn't the last request in this ep queue */
+		if (req->queue.next != &ep->queue) {
+			struct ep_queue_head *qh;
+			struct fsl_req *next_req;
+
+			qh = ep->qh;
+			next_req = list_entry(req->queue.next, struct fsl_req,
+					queue);
+
+			/* Point the QH to the first TD of next request */
+			fsl_writel((u32) next_req->head, &qh->curr_dtd_ptr);
+		}
+
+		/* The request hasn't been processed, patch up the TD chain */
+	} else {
+		struct fsl_req *prev_req;
+
+		prev_req = list_entry(req->queue.prev, struct fsl_req, queue);
+		fsl_writel(fsl_readl(&req->tail->next_td_ptr),
+				&prev_req->tail->next_td_ptr);
+
+	}
+
+	done(ep, req, -ECONNRESET);
+
+	/* Enable EP */
+out:	epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+	if (ep_is_in(ep))
+		epctrl |= EPCTRL_TX_ENABLE;
+	else
+		epctrl |= EPCTRL_RX_ENABLE;
+	fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+	ep->stopped = stopped;
+
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+ * modify the endpoint halt feature
+ * @ep: the non-isochronous endpoint being stalled
+ * @value: 1--set halt  0--clear halt
+ * Returns zero, or a negative error code.
+*----------------------------------------------------------------*/
+static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
+{
+	struct fsl_ep *ep = NULL;
+	unsigned long flags = 0;
+	int status = -EOPNOTSUPP;	/* operation not supported */
+	unsigned char ep_dir = 0, ep_num = 0;
+	struct fsl_udc *udc = NULL;
+
+	ep = container_of(_ep, struct fsl_ep, ep);
+	udc = ep->udc;
+	if (!_ep || !ep->desc) {
+		status = -EINVAL;
+		goto out;
+	}
+
+	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		status = -EOPNOTSUPP;
+		goto out;
+	}
+
+	/* Attempt to halt IN ep will fail if any transfer requests
+	 * are still queue */
+	if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
+		status = -EAGAIN;
+		goto out;
+	}
+
+	status = 0;
+	ep_dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
+	ep_num = (unsigned char)(ep_index(ep));
+	spin_lock_irqsave(&ep->udc->lock, flags);
+	dr_ep_change_stall(ep_num, ep_dir, value);
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+	if (ep_index(ep) == 0) {
+		udc->ep0_state = WAIT_FOR_SETUP;
+		udc->ep0_dir = 0;
+	}
+out:
+	VDBG(" %s %s halt stat %d", ep->ep.name,
+			value ?  "set" : "clear", status);
+
+	return status;
+}
+
+static void fsl_ep_fifo_flush(struct usb_ep *_ep)
+{
+	struct fsl_ep *ep;
+	int ep_num, ep_dir;
+	u32 bits;
+	unsigned long timeout;
+#define FSL_UDC_FLUSH_TIMEOUT 1000
+
+	if (!_ep) {
+		return;
+	} else {
+		ep = container_of(_ep, struct fsl_ep, ep);
+		if (!ep->desc)
+			return;
+	}
+	ep_num = ep_index(ep);
+	ep_dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
+
+	if (ep_num == 0)
+		bits = (1 << 16) | 1;
+	else if (ep_dir == USB_SEND)
+		bits = 1 << (16 + ep_num);
+	else
+		bits = 1 << ep_num;
+
+	timeout = jiffies + FSL_UDC_FLUSH_TIMEOUT;
+	do {
+		fsl_writel(bits, &dr_regs->endptflush);
+
+		/* Wait until flush complete */
+		while (fsl_readl(&dr_regs->endptflush)) {
+			if (time_after(jiffies, timeout)) {
+				ERR("ep flush timeout\n");
+				return;
+			}
+			cpu_relax();
+		}
+		/* See if we need to flush again */
+	} while (fsl_readl(&dr_regs->endptstatus) & bits);
+}
+
+static struct usb_ep_ops fsl_ep_ops = {
+	.enable = fsl_ep_enable,
+	.disable = fsl_ep_disable,
+
+	.alloc_request = fsl_alloc_request,
+	.free_request = fsl_free_request,
+
+	.alloc_buffer = fsl_alloc_buffer,
+	.free_buffer = fsl_free_buffer,
+
+	.queue = fsl_ep_queue,
+	.dequeue = fsl_ep_dequeue,
+
+	.set_halt = fsl_ep_set_halt,
+	.fifo_flush = fsl_ep_fifo_flush,	/* flush fifo */
+};
+
+/*-------------------------------------------------------------------------
+		Gadget Driver Layer Operations
+-------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+ * Get the current frame number (from DR frame_index Reg )
+ *----------------------------------------------------------------------*/
+static int fsl_get_frame(struct usb_gadget *gadget)
+{
+	return (int)(fsl_readl(&dr_regs->frindex) & USB_FRINDEX_MASKS);
+}
+
+/*-----------------------------------------------------------------------
+ * Tries to wake up the host connected to this gadget
+ -----------------------------------------------------------------------*/
+static int fsl_wakeup(struct usb_gadget *gadget)
+{
+	struct fsl_udc *udc = container_of(gadget, struct fsl_udc, gadget);
+	u32 portsc;
+
+	/* Remote wakeup feature not enabled by host */
+	if (!udc->remote_wakeup)
+		return -ENOTSUPP;
+
+	portsc = fsl_readl(&dr_regs->portsc1);
+	/* not suspended? */
+	if (!(portsc & PORTSCX_PORT_SUSPEND))
+		return 0;
+	/* trigger force resume */
+	portsc |= PORTSCX_PORT_FORCE_RESUME;
+	fsl_writel(portsc, &dr_regs->portsc1);
+	return 0;
+}
+
+static int can_pullup(struct fsl_udc *udc)
+{
+	return udc->driver && udc->softconnect && udc->vbus_active;
+}
+
+/* Notify controller that VBUS is powered, Called by whatever
+   detects VBUS sessions */
+static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+	struct fsl_udc	*udc;
+	unsigned long	flags;
+
+	udc = container_of(gadget, struct fsl_udc, gadget);
+	spin_lock_irqsave(&udc->lock, flags);
+	VDBG("VBUS %s\n", is_active ? "on" : "off");
+	udc->vbus_active = (is_active != 0);
+	if (can_pullup(udc))
+		fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
+				&dr_regs->usbcmd);
+	else
+		fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
+				&dr_regs->usbcmd);
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return 0;
+}
+
+/* constrain controller's VBUS power usage
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume.  For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+#ifdef CONFIG_USB_OTG
+	struct fsl_udc *udc;
+
+	udc = container_of(gadget, struct fsl_udc, gadget);
+
+	if (udc->transceiver)
+		return otg_set_power(udc->transceiver, mA);
+#endif
+	return -ENOTSUPP;
+}
+
+/* Change Data+ pullup status
+ * this func is used by usb_gadget_connect/disconnet
+ */
+static int fsl_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct fsl_udc *udc;
+
+	udc = container_of(gadget, struct fsl_udc, gadget);
+	udc->softconnect = (is_on != 0);
+	if (can_pullup(udc))
+		fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
+				&dr_regs->usbcmd);
+	else
+		fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
+				&dr_regs->usbcmd);
+
+	return 0;
+}
+
+/* defined in usb_gadget.h */
+static struct usb_gadget_ops fsl_gadget_ops = {
+	.get_frame = fsl_get_frame,
+	.wakeup = fsl_wakeup,
+/*	.set_selfpowered = fsl_set_selfpowered,	*/ /* Always selfpowered */
+	.vbus_session = fsl_vbus_session,
+	.vbus_draw = fsl_vbus_draw,
+	.pullup = fsl_pullup,
+};
+
+/* Set protocol stall on ep0, protocol stall will automatically be cleared
+   on new transaction */
+static void ep0stall(struct fsl_udc *udc)
+{
+	u32 tmp;
+
+	/* must set tx and rx to stall at the same time */
+	tmp = fsl_readl(&dr_regs->endptctrl[0]);
+	tmp |= EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL;
+	fsl_writel(tmp, &dr_regs->endptctrl[0]);
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->ep0_dir = 0;
+}
+
+/* Prime a status phase for ep0 */
+static int ep0_prime_status(struct fsl_udc *udc, int direction)
+{
+	struct fsl_req *req = udc->status_req;
+	struct fsl_ep *ep;
+	int status = 0;
+
+	if (direction == EP_DIR_IN)
+		udc->ep0_dir = USB_DIR_IN;
+	else
+		udc->ep0_dir = USB_DIR_OUT;
+
+	ep = &udc->eps[0];
+	udc->ep0_state = WAIT_FOR_OUT_STATUS;
+
+	req->ep = ep;
+	req->req.length = 0;
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	req->req.complete = NULL;
+	req->dtd_count = 0;
+
+	if (fsl_req_to_dtd(req) == 0)
+		status = fsl_queue_td(ep, req);
+	else
+		return -ENOMEM;
+
+	if (status)
+		ERR("Can't queue ep0 status request \n");
+	list_add_tail(&req->queue, &ep->queue);
+
+	return status;
+}
+
+static inline int udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
+{
+	struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
+
+	if (!ep->name)
+		return 0;
+
+	nuke(ep, -ESHUTDOWN);
+
+	return 0;
+}
+
+/*
+ * ch9 Set address
+ */
+static void ch9setaddress(struct fsl_udc *udc, u16 value, u16 index, u16 length)
+{
+	/* Save the new address to device struct */
+	udc->device_address = (u8) value;
+	/* Update usb state */
+	udc->usb_state = USB_STATE_ADDRESS;
+	/* Status phase */
+	if (ep0_prime_status(udc, EP_DIR_IN))
+		ep0stall(udc);
+}
+
+/*
+ * ch9 Get status
+ */
+static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
+		u16 index, u16 length)
+{
+	u16 tmp = 0;		/* Status, cpu endian */
+
+	struct fsl_req *req;
+	struct fsl_ep *ep;
+	int status = 0;
+
+	ep = &udc->eps[0];
+
+	if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+		/* Get device status */
+		tmp = 1 << USB_DEVICE_SELF_POWERED;
+		tmp |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+	} else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
+		/* Get interface status */
+		/* We don't have interface information in udc driver */
+		tmp = 0;
+	} else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
+		/* Get endpoint status */
+		struct fsl_ep *target_ep;
+
+		target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index));
+
+		/* stall if endpoint doesn't exist */
+		if (!target_ep->desc)
+			goto stall;
+		tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep))
+				<< USB_ENDPOINT_HALT;
+	}
+
+	udc->ep0_dir = USB_DIR_IN;
+	/* Borrow the per device status_req */
+	req = udc->status_req;
+	/* Fill in the reqest structure */
+	*((u16 *) req->req.buf) = cpu_to_le16(tmp);
+	req->ep = ep;
+	req->req.length = 2;
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	req->req.complete = NULL;
+	req->dtd_count = 0;
+
+	/* prime the data phase */
+	if ((fsl_req_to_dtd(req) == 0))
+		status = fsl_queue_td(ep, req);
+	else			/* no mem */
+		goto stall;
+
+	if (status) {
+		ERR("Can't respond to getstatus request \n");
+		goto stall;
+	}
+	list_add_tail(&req->queue, &ep->queue);
+	udc->ep0_state = DATA_STATE_XMIT;
+	return;
+stall:
+	ep0stall(udc);
+}
+
+static void setup_received_irq(struct fsl_udc *udc,
+		struct usb_ctrlrequest *setup)
+{
+	u16 wValue = le16_to_cpu(setup->wValue);
+	u16 wIndex = le16_to_cpu(setup->wIndex);
+	u16 wLength = le16_to_cpu(setup->wLength);
+
+	udc_reset_ep_queue(udc, 0);
+
+	switch (setup->bRequest) {
+		/* Request that need Data+Status phase from udc */
+	case USB_REQ_GET_STATUS:
+		if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_STANDARD))
+					!= (USB_DIR_IN | USB_TYPE_STANDARD))
+			break;
+		ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
+		break;
+
+		/* Requests that need Status phase from udc */
+	case USB_REQ_SET_ADDRESS:
+		if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
+						| USB_RECIP_DEVICE))
+			break;
+		ch9setaddress(udc, wValue, wIndex, wLength);
+		break;
+
+		/* Handled by udc, no data, status by udc */
+	case USB_REQ_CLEAR_FEATURE:
+	case USB_REQ_SET_FEATURE:
+	{	/* status transaction */
+		int rc = -EOPNOTSUPP;
+
+		if ((setup->bRequestType & USB_RECIP_MASK)
+				== USB_RECIP_ENDPOINT) {
+			int pipe = get_pipe_by_windex(wIndex);
+			struct fsl_ep *ep;
+
+			if (wValue != 0 || wLength != 0 || pipe > udc->max_ep)
+				break;
+			ep = get_ep_by_pipe(udc, pipe);
+
+			spin_unlock(&udc->lock);
+			rc = fsl_ep_set_halt(&ep->ep,
+					(setup->bRequest == USB_REQ_SET_FEATURE)
+						? 1 : 0);
+			spin_lock(&udc->lock);
+
+		} else if ((setup->bRequestType & USB_RECIP_MASK)
+				== USB_RECIP_DEVICE) {
+			/* Note: The driver has not include OTG support yet.
+			 * This will be set when OTG support is added */
+			if (!udc->gadget.is_otg)
+				break;
+			else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
+				udc->gadget.b_hnp_enable = 1;
+			else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
+				udc->gadget.a_hnp_support = 1;
+			else if (setup->bRequest ==
+					USB_DEVICE_A_ALT_HNP_SUPPORT)
+				udc->gadget.a_alt_hnp_support = 1;
+			rc = 0;
+		}
+		if (rc == 0) {
+			if (ep0_prime_status(udc, EP_DIR_IN))
+				ep0stall(udc);
+		}
+		break;
+	}
+		/* Requests handled by gadget */
+	default:
+		if (wLength) {
+			/* Data phase from gadget, status phase from udc */
+			udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+					?  USB_DIR_IN : USB_DIR_OUT;
+			spin_unlock(&udc->lock);
+			if (udc->driver->setup(&udc->gadget,
+					&udc->local_setup_buff) < 0)
+				ep0stall(udc);
+			spin_lock(&udc->lock);
+			udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
+					?  DATA_STATE_XMIT : DATA_STATE_RECV;
+
+		} else {
+			/* No data phase, IN status from gadget */
+			udc->ep0_dir = USB_DIR_IN;
+			spin_unlock(&udc->lock);
+			if (udc->driver->setup(&udc->gadget,
+					&udc->local_setup_buff) < 0)
+				ep0stall(udc);
+			spin_lock(&udc->lock);
+			udc->ep0_state = WAIT_FOR_OUT_STATUS;
+		}
+		break;
+	}
+}
+
+/* Process request for Data or Status phase of ep0
+ * prime status phase if needed */
+static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
+		struct fsl_req *req)
+{
+	if (udc->usb_state == USB_STATE_ADDRESS) {
+		/* Set the new address */
+		u32 new_address = (u32) udc->device_address;
+		fsl_writel(new_address << USB_DEVICE_ADDRESS_BIT_POS,
+				&dr_regs->deviceaddr);
+	}
+
+	done(ep0, req, 0);
+
+	switch (udc->ep0_state) {
+	case DATA_STATE_XMIT:
+		/* receive status phase */
+		if (ep0_prime_status(udc, EP_DIR_OUT))
+			ep0stall(udc);
+		break;
+	case DATA_STATE_RECV:
+		/* send status phase */
+		if (ep0_prime_status(udc, EP_DIR_IN))
+			ep0stall(udc);
+		break;
+	case WAIT_FOR_OUT_STATUS:
+		udc->ep0_state = WAIT_FOR_SETUP;
+		break;
+	case WAIT_FOR_SETUP:
+		ERR("Unexpect ep0 packets \n");
+		break;
+	default:
+		ep0stall(udc);
+		break;
+	}
+}
+
+/* Tripwire mechanism to ensure a setup packet payload is extracted without
+ * being corrupted by another incoming setup packet */
+static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr)
+{
+	u32 temp;
+	struct ep_queue_head *qh;
+
+	qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT];
+
+	/* Clear bit in ENDPTSETUPSTAT */
+	temp = fsl_readl(&dr_regs->endptsetupstat);
+	fsl_writel(temp | (1 << ep_num), &dr_regs->endptsetupstat);
+
+	/* while a hazard exists when setup package arrives */
+	do {
+		/* Set Setup Tripwire */
+		temp = fsl_readl(&dr_regs->usbcmd);
+		fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd);
+
+		/* Copy the setup packet to local buffer */
+		memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8);
+	} while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW));
+
+	/* Clear Setup Tripwire */
+	temp = fsl_readl(&dr_regs->usbcmd);
+	fsl_writel(temp & ~USB_CMD_SUTW, &dr_regs->usbcmd);
+}
+
+/* process-ep_req(): free the completed Tds for this req */
+static int process_ep_req(struct fsl_udc *udc, int pipe,
+		struct fsl_req *curr_req)
+{
+	struct ep_td_struct *curr_td;
+	int	td_complete, actual, remaining_length, j, tmp;
+	int	status = 0;
+	int	errors = 0;
+	struct  ep_queue_head *curr_qh = &udc->ep_qh[pipe];
+	int direction = pipe % 2;
+
+	curr_td = curr_req->head;
+	td_complete = 0;
+	actual = curr_req->req.length;
+
+	for (j = 0; j < curr_req->dtd_count; j++) {
+		remaining_length = (le32_to_cpu(curr_td->size_ioc_sts)
+					& DTD_PACKET_SIZE)
+				>> DTD_LENGTH_BIT_POS;
+		actual -= remaining_length;
+
+		if ((errors = le32_to_cpu(curr_td->size_ioc_sts) &
+						DTD_ERROR_MASK)) {
+			if (errors & DTD_STATUS_HALTED) {
+				ERR("dTD error %08x QH=%d\n", errors, pipe);
+				/* Clear the errors and Halt condition */
+				tmp = le32_to_cpu(curr_qh->size_ioc_int_sts);
+				tmp &= ~errors;
+				curr_qh->size_ioc_int_sts = cpu_to_le32(tmp);
+				status = -EPIPE;
+				/* FIXME: continue with next queued TD? */
+
+				break;
+			}
+			if (errors & DTD_STATUS_DATA_BUFF_ERR) {
+				VDBG("Transfer overflow");
+				status = -EPROTO;
+				break;
+			} else if (errors & DTD_STATUS_TRANSACTION_ERR) {
+				VDBG("ISO error");
+				status = -EILSEQ;
+				break;
+			} else
+				ERR("Unknown error has occured (0x%x)!\r\n",
+					errors);
+
+		} else if (le32_to_cpu(curr_td->size_ioc_sts)
+				& DTD_STATUS_ACTIVE) {
+			VDBG("Request not complete");
+			status = REQ_UNCOMPLETE;
+			return status;
+		} else if (remaining_length) {
+			if (direction) {
+				VDBG("Transmit dTD remaining length not zero");
+				status = -EPROTO;
+				break;
+			} else {
+				td_complete++;
+				break;
+			}
+		} else {
+			td_complete++;
+			VDBG("dTD transmitted successful ");
+		}
+
+		if (j != curr_req->dtd_count - 1)
+			curr_td = (struct ep_td_struct *)curr_td->next_td_virt;
+	}
+
+	if (status)
+		return status;
+
+	curr_req->req.actual = actual;
+
+	return 0;
+}
+
+/* Process a DTD completion interrupt */
+static void dtd_complete_irq(struct fsl_udc *udc)
+{
+	u32 bit_pos;
+	int i, ep_num, direction, bit_mask, status;
+	struct fsl_ep *curr_ep;
+	struct fsl_req *curr_req, *temp_req;
+
+	/* Clear the bits in the register */
+	bit_pos = fsl_readl(&dr_regs->endptcomplete);
+	fsl_writel(bit_pos, &dr_regs->endptcomplete);
+
+	if (!bit_pos)
+		return;
+
+	for (i = 0; i < udc->max_ep * 2; i++) {
+		ep_num = i >> 1;
+		direction = i % 2;
+
+		bit_mask = 1 << (ep_num + 16 * direction);
+
+		if (!(bit_pos & bit_mask))
+			continue;
+
+		curr_ep = get_ep_by_pipe(udc, i);
+
+		/* If the ep is configured */
+		if (curr_ep->name == NULL) {
+			WARN("Invalid EP?");
+			continue;
+		}
+
+		/* process the req queue until an uncomplete request */
+		list_for_each_entry_safe(curr_req, temp_req, &curr_ep->queue,
+				queue) {
+			status = process_ep_req(udc, i, curr_req);
+
+			VDBG("status of process_ep_req= %d, ep = %d",
+					status, ep_num);
+			if (status == REQ_UNCOMPLETE)
+				break;
+			/* write back status to req */
+			curr_req->req.status = status;
+
+			if (ep_num == 0) {
+				ep0_req_complete(udc, curr_ep, curr_req);
+				break;
+			} else
+				done(curr_ep, curr_req, status);
+		}
+	}
+}
+
+/* Process a port change interrupt */
+static void port_change_irq(struct fsl_udc *udc)
+{
+	u32 speed;
+
+	if (udc->bus_reset)
+		udc->bus_reset = 0;
+
+	/* Bus resetting is finished */
+	if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) {
+		/* Get the speed */
+		speed = (fsl_readl(&dr_regs->portsc1)
+				& PORTSCX_PORT_SPEED_MASK);
+		switch (speed) {
+		case PORTSCX_PORT_SPEED_HIGH:
+			udc->gadget.speed = USB_SPEED_HIGH;
+			break;
+		case PORTSCX_PORT_SPEED_FULL:
+			udc->gadget.speed = USB_SPEED_FULL;
+			break;
+		case PORTSCX_PORT_SPEED_LOW:
+			udc->gadget.speed = USB_SPEED_LOW;
+			break;
+		default:
+			udc->gadget.speed = USB_SPEED_UNKNOWN;
+			break;
+		}
+	}
+
+	/* Update USB state */
+	if (!udc->resume_state)
+		udc->usb_state = USB_STATE_DEFAULT;
+}
+
+/* Process suspend interrupt */
+static void suspend_irq(struct fsl_udc *udc)
+{
+	udc->resume_state = udc->usb_state;
+	udc->usb_state = USB_STATE_SUSPENDED;
+
+	/* report suspend to the driver, serial.c does not support this */
+	if (udc->driver->suspend)
+		udc->driver->suspend(&udc->gadget);
+}
+
+static void bus_resume(struct fsl_udc *udc)
+{
+	udc->usb_state = udc->resume_state;
+	udc->resume_state = 0;
+
+	/* report resume to the driver, serial.c does not support this */
+	if (udc->driver->resume)
+		udc->driver->resume(&udc->gadget);
+}
+
+/* Clear up all ep queues */
+static int reset_queues(struct fsl_udc *udc)
+{
+	u8 pipe;
+
+	for (pipe = 0; pipe < udc->max_pipes; pipe++)
+		udc_reset_ep_queue(udc, pipe);
+
+	/* report disconnect; the driver is already quiesced */
+	udc->driver->disconnect(&udc->gadget);
+
+	return 0;
+}
+
+/* Process reset interrupt */
+static void reset_irq(struct fsl_udc *udc)
+{
+	u32 temp;
+	unsigned long timeout;
+
+	/* Clear the device address */
+	temp = fsl_readl(&dr_regs->deviceaddr);
+	fsl_writel(temp & ~USB_DEVICE_ADDRESS_MASK, &dr_regs->deviceaddr);
+
+	udc->device_address = 0;
+
+	/* Clear usb state */
+	udc->resume_state = 0;
+	udc->ep0_dir = 0;
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->remote_wakeup = 0;	/* default to 0 on reset */
+	udc->gadget.b_hnp_enable = 0;
+	udc->gadget.a_hnp_support = 0;
+	udc->gadget.a_alt_hnp_support = 0;
+
+	/* Clear all the setup token semaphores */
+	temp = fsl_readl(&dr_regs->endptsetupstat);
+	fsl_writel(temp, &dr_regs->endptsetupstat);
+
+	/* Clear all the endpoint complete status bits */
+	temp = fsl_readl(&dr_regs->endptcomplete);
+	fsl_writel(temp, &dr_regs->endptcomplete);
+
+	timeout = jiffies + 100;
+	while (fsl_readl(&dr_regs->endpointprime)) {
+		/* Wait until all endptprime bits cleared */
+		if (time_after(jiffies, timeout)) {
+			ERR("Timeout for reset\n");
+			break;
+		}
+		cpu_relax();
+	}
+
+	/* Write 1s to the flush register */
+	fsl_writel(0xffffffff, &dr_regs->endptflush);
+
+	if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
+		VDBG("Bus reset");
+		/* Bus is reseting */
+		udc->bus_reset = 1;
+		/* Reset all the queues, include XD, dTD, EP queue
+		 * head and TR Queue */
+		reset_queues(udc);
+		udc->usb_state = USB_STATE_DEFAULT;
+	} else {
+		VDBG("Controller reset");
+		/* initialize usb hw reg except for regs for EP, not
+		 * touch usbintr reg */
+		dr_controller_setup(udc);
+
+		/* Reset all internal used Queues */
+		reset_queues(udc);
+
+		ep0_setup(udc);
+
+		/* Enable DR IRQ reg, Set Run bit, change udc state */
+		dr_controller_run(udc);
+		udc->usb_state = USB_STATE_ATTACHED;
+	}
+}
+
+/*
+ * USB device controller interrupt handler
+ */
+static irqreturn_t fsl_udc_irq(int irq, void *_udc)
+{
+	struct fsl_udc *udc = _udc;
+	u32 irq_src;
+	irqreturn_t status = IRQ_NONE;
+	unsigned long flags;
+
+	/* Disable ISR for OTG host mode */
+	if (udc->stopped)
+		return IRQ_NONE;
+	spin_lock_irqsave(&udc->lock, flags);
+	irq_src = fsl_readl(&dr_regs->usbsts) & fsl_readl(&dr_regs->usbintr);
+	/* Clear notification bits */
+	fsl_writel(irq_src, &dr_regs->usbsts);
+
+	/* VDBG("irq_src [0x%8x]", irq_src); */
+
+	/* Need to resume? */
+	if (udc->usb_state == USB_STATE_SUSPENDED)
+		if ((fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_SUSPEND) == 0)
+			bus_resume(udc);
+
+	/* USB Interrupt */
+	if (irq_src & USB_STS_INT) {
+		VDBG("Packet int");
+		/* Setup package, we only support ep0 as control ep */
+		if (fsl_readl(&dr_regs->endptsetupstat) & EP_SETUP_STATUS_EP0) {
+			tripwire_handler(udc, 0,
+					(u8 *) (&udc->local_setup_buff));
+			setup_received_irq(udc, &udc->local_setup_buff);
+			status = IRQ_HANDLED;
+		}
+
+		/* completion of dtd */
+		if (fsl_readl(&dr_regs->endptcomplete)) {
+			dtd_complete_irq(udc);
+			status = IRQ_HANDLED;
+		}
+	}
+
+	/* SOF (for ISO transfer) */
+	if (irq_src & USB_STS_SOF) {
+		status = IRQ_HANDLED;
+	}
+
+	/* Port Change */
+	if (irq_src & USB_STS_PORT_CHANGE) {
+		port_change_irq(udc);
+		status = IRQ_HANDLED;
+	}
+
+	/* Reset Received */
+	if (irq_src & USB_STS_RESET) {
+		reset_irq(udc);
+		status = IRQ_HANDLED;
+	}
+
+	/* Sleep Enable (Suspend) */
+	if (irq_src & USB_STS_SUSPEND) {
+		suspend_irq(udc);
+		status = IRQ_HANDLED;
+	}
+
+	if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
+		VDBG("Error IRQ %x ", irq_src);
+	}
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return status;
+}
+
+/*----------------------------------------------------------------*
+ * Hook to gadget drivers
+ * Called by initialization code of gadget drivers
+*----------------------------------------------------------------*/
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	int retval = -ENODEV;
+	unsigned long flags = 0;
+
+	if (!udc_controller)
+		return -ENODEV;
+
+	if (!driver || (driver->speed != USB_SPEED_FULL
+				&& driver->speed != USB_SPEED_HIGH)
+			|| !driver->bind || !driver->disconnect
+			|| !driver->setup)
+		return -EINVAL;
+
+	if (udc_controller->driver)
+		return -EBUSY;
+
+	/* lock is needed but whether should use this lock or another */
+	spin_lock_irqsave(&udc_controller->lock, flags);
+
+	driver->driver.bus = 0;
+	/* hook up the driver */
+	udc_controller->driver = driver;
+	udc_controller->gadget.dev.driver = &driver->driver;
+	spin_unlock_irqrestore(&udc_controller->lock, flags);
+
+	/* bind udc driver to gadget driver */
+	retval = driver->bind(&udc_controller->gadget);
+	if (retval) {
+		VDBG("bind to %s --> %d", driver->driver.name, retval);
+		udc_controller->gadget.dev.driver = 0;
+		udc_controller->driver = 0;
+		goto out;
+	}
+
+	/* Enable DR IRQ reg and Set usbcmd reg  Run bit */
+	dr_controller_run(udc_controller);
+	udc_controller->usb_state = USB_STATE_ATTACHED;
+	udc_controller->ep0_state = WAIT_FOR_SETUP;
+	udc_controller->ep0_dir = 0;
+	printk(KERN_INFO "%s: bind to driver %s \n",
+			udc_controller->gadget.name, driver->driver.name);
+
+out:
+	if (retval)
+		printk("retval %d \n", retval);
+	return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+/* Disconnect from gadget driver */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct fsl_ep *loop_ep;
+	unsigned long flags;
+
+	if (!udc_controller)
+		return -ENODEV;
+
+	if (!driver || driver != udc_controller->driver || !driver->unbind)
+		return -EINVAL;
+
+#ifdef CONFIG_USB_OTG
+	if (udc_controller->transceiver)
+		(void)otg_set_peripheral(udc_controller->transceiver, 0);
+#endif
+
+	/* stop DR, disable intr */
+	dr_controller_stop(udc_controller);
+
+	/* in fact, no needed */
+	udc_controller->usb_state = USB_STATE_ATTACHED;
+	udc_controller->ep0_state = WAIT_FOR_SETUP;
+	udc_controller->ep0_dir = 0;
+
+	/* stand operation */
+	spin_lock_irqsave(&udc_controller->lock, flags);
+	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+	nuke(&udc_controller->eps[0], -ESHUTDOWN);
+	list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
+			ep.ep_list)
+		nuke(loop_ep, -ESHUTDOWN);
+	spin_unlock_irqrestore(&udc_controller->lock, flags);
+
+	/* unbind gadget and unhook driver. */
+	driver->unbind(&udc_controller->gadget);
+	udc_controller->gadget.dev.driver = 0;
+	udc_controller->driver = 0;
+
+	printk("unregistered gadget driver '%s'\r\n", driver->driver.name);
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------
+		PROC File System Support
+-------------------------------------------------------------------------*/
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+#include <linux/seq_file.h>
+
+static const char proc_filename[] = "driver/fsl_usb2_udc";
+
+static int fsl_proc_read(char *page, char **start, off_t off, int count,
+		int *eof, void *_dev)
+{
+	char *buf = page;
+	char *next = buf;
+	unsigned size = count;
+	unsigned long flags;
+	int t, i;
+	u32 tmp_reg;
+	struct fsl_ep *ep = NULL;
+	struct fsl_req *req;
+
+	struct fsl_udc *udc = udc_controller;
+	if (off != 0)
+		return 0;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* ------basic driver infomation ---- */
+	t = scnprintf(next, size,
+			DRIVER_DESC "\n"
+			"%s version: %s\n"
+			"Gadget driver: %s\n\n",
+			driver_name, DRIVER_VERSION,
+			udc->driver ? udc->driver->driver.name : "(none)");
+	size -= t;
+	next += t;
+
+	/* ------ DR Registers ----- */
+	tmp_reg = fsl_readl(&dr_regs->usbcmd);
+	t = scnprintf(next, size,
+			"USBCMD reg:\n"
+			"SetupTW: %d\n"
+			"Run/Stop: %s\n\n",
+			(tmp_reg & USB_CMD_SUTW) ? 1 : 0,
+			(tmp_reg & USB_CMD_RUN_STOP) ? "Run" : "Stop");
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->usbsts);
+	t = scnprintf(next, size,
+			"USB Status Reg:\n"
+			"Dr Suspend: %d" "Reset Received: %d" "System Error: %s"
+			"USB Error Interrupt: %s\n\n",
+			(tmp_reg & USB_STS_SUSPEND) ? 1 : 0,
+			(tmp_reg & USB_STS_RESET) ? 1 : 0,
+			(tmp_reg & USB_STS_SYS_ERR) ? "Err" : "Normal",
+			(tmp_reg & USB_STS_ERR) ? "Err detected" : "No err");
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->usbintr);
+	t = scnprintf(next, size,
+			"USB Intrrupt Enable Reg:\n"
+			"Sleep Enable: %d" "SOF Received Enable: %d"
+			"Reset Enable: %d\n"
+			"System Error Enable: %d"
+			"Port Change Dectected Enable: %d\n"
+			"USB Error Intr Enable: %d" "USB Intr Enable: %d\n\n",
+			(tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0,
+			(tmp_reg & USB_INTR_SOF_EN) ? 1 : 0,
+			(tmp_reg & USB_INTR_RESET_EN) ? 1 : 0,
+			(tmp_reg & USB_INTR_SYS_ERR_EN) ? 1 : 0,
+			(tmp_reg & USB_INTR_PTC_DETECT_EN) ? 1 : 0,
+			(tmp_reg & USB_INTR_ERR_INT_EN) ? 1 : 0,
+			(tmp_reg & USB_INTR_INT_EN) ? 1 : 0);
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->frindex);
+	t = scnprintf(next, size,
+			"USB Frame Index Reg:" "Frame Number is 0x%x\n\n",
+			(tmp_reg & USB_FRINDEX_MASKS));
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->deviceaddr);
+	t = scnprintf(next, size,
+			"USB Device Address Reg:" "Device Addr is 0x%x\n\n",
+			(tmp_reg & USB_DEVICE_ADDRESS_MASK));
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
+	t = scnprintf(next, size,
+			"USB Endpoint List Address Reg:"
+			"Device Addr is 0x%x\n\n",
+			(tmp_reg & USB_EP_LIST_ADDRESS_MASK));
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->portsc1);
+	t = scnprintf(next, size,
+		"USB Port Status&Control Reg:\n"
+		"Port Transceiver Type : %s" "Port Speed: %s \n"
+		"PHY Low Power Suspend: %s" "Port Reset: %s"
+		"Port Suspend Mode: %s \n" "Over-current Change: %s"
+		"Port Enable/Disable Change: %s\n"
+		"Port Enabled/Disabled: %s"
+		"Current Connect Status: %s\n\n", ( {
+			char *s;
+			switch (tmp_reg & PORTSCX_PTS_FSLS) {
+			case PORTSCX_PTS_UTMI:
+				s = "UTMI"; break;
+			case PORTSCX_PTS_ULPI:
+				s = "ULPI "; break;
+			case PORTSCX_PTS_FSLS:
+				s = "FS/LS Serial"; break;
+			default:
+				s = "None"; break;
+			}
+			s;} ), ( {
+			char *s;
+			switch (tmp_reg & PORTSCX_PORT_SPEED_UNDEF) {
+			case PORTSCX_PORT_SPEED_FULL:
+				s = "Full Speed"; break;
+			case PORTSCX_PORT_SPEED_LOW:
+				s = "Low Speed"; break;
+			case PORTSCX_PORT_SPEED_HIGH:
+				s = "High Speed"; break;
+			default:
+				s = "Undefined"; break;
+			}
+			s;
+		} ),
+		(tmp_reg & PORTSCX_PHY_LOW_POWER_SPD) ?
+		"Normal PHY mode" : "Low power mode",
+		(tmp_reg & PORTSCX_PORT_RESET) ? "In Reset" :
+		"Not in Reset",
+		(tmp_reg & PORTSCX_PORT_SUSPEND) ? "In " : "Not in",
+		(tmp_reg & PORTSCX_OVER_CURRENT_CHG) ? "Dected" :
+		"No",
+		(tmp_reg & PORTSCX_PORT_EN_DIS_CHANGE) ? "Disable" :
+		"Not change",
+		(tmp_reg & PORTSCX_PORT_ENABLE) ? "Enable" :
+		"Not correct",
+		(tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?
+		"Attached" : "Not-Att");
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->usbmode);
+	t = scnprintf(next, size,
+			"USB Mode Reg:" "Controller Mode is : %s\n\n", ( {
+				char *s;
+				switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
+				case USB_MODE_CTRL_MODE_IDLE:
+					s = "Idle"; break;
+				case USB_MODE_CTRL_MODE_DEVICE:
+					s = "Device Controller"; break;
+				case USB_MODE_CTRL_MODE_HOST:
+					s = "Host Controller"; break;
+				default:
+					s = "None"; break;
+				}
+				s;
+			} ));
+	size -= t;
+	next += t;
+
+	tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
+	t = scnprintf(next, size,
+			"Endpoint Setup Status Reg:" "SETUP on ep 0x%x\n\n",
+			(tmp_reg & EP_SETUP_STATUS_MASK));
+	size -= t;
+	next += t;
+
+	for (i = 0; i < udc->max_ep / 2; i++) {
+		tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);
+		t = scnprintf(next, size, "EP Ctrl Reg [0x%x]: = [0x%x]\n",
+				i, tmp_reg);
+		size -= t;
+		next += t;
+	}
+	tmp_reg = fsl_readl(&dr_regs->endpointprime);
+	t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n", tmp_reg);
+	size -= t;
+	next += t;
+
+	tmp_reg = usb_sys_regs->snoop1;
+	t = scnprintf(next, size, "\nSnoop1 Reg : = [0x%x]\n\n", tmp_reg);
+	size -= t;
+	next += t;
+
+	tmp_reg = usb_sys_regs->control;
+	t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
+			tmp_reg);
+	size -= t;
+	next += t;
+
+	/* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
+	ep = &udc->eps[0];
+	t = scnprintf(next, size, "For %s Maxpkt is 0x%x index is 0x%x\n",
+			ep->ep.name, ep_maxpacket(ep), ep_index(ep));
+	size -= t;
+	next += t;
+
+	if (list_empty(&ep->queue)) {
+		t = scnprintf(next, size, "its req queue is empty\n\n");
+		size -= t;
+		next += t;
+	} else {
+		list_for_each_entry(req, &ep->queue, queue) {
+			t = scnprintf(next, size,
+				"req %p actual 0x%x length 0x%x  buf %p\n",
+				&req->req, req->req.actual,
+				req->req.length, req->req.buf);
+			size -= t;
+			next += t;
+		}
+	}
+	/* other gadget->eplist ep */
+	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+		if (ep->desc) {
+			t = scnprintf(next, size,
+					"\nFor %s Maxpkt is 0x%x "
+					"index is 0x%x\n",
+					ep->ep.name, ep_maxpacket(ep),
+					ep_index(ep));
+			size -= t;
+			next += t;
+
+			if (list_empty(&ep->queue)) {
+				t = scnprintf(next, size,
+						"its req queue is empty\n\n");
+				size -= t;
+				next += t;
+			} else {
+				list_for_each_entry(req, &ep->queue, queue) {
+					t = scnprintf(next, size,
+						"req %p actual 0x%x length"
+						"0x%x  buf %p\n",
+						&req->req, req->req.actual,
+						req->req.length, req->req.buf);
+					size -= t;
+					next += t;
+					}	/* end for each_entry of ep req */
+				}	/* end for else */
+			}	/* end for if(ep->queue) */
+		}		/* end (ep->desc) */
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	*eof = 1;
+	return count - size;
+}
+
+#define create_proc_file()	create_proc_read_entry(proc_filename, \
+				0, NULL, fsl_proc_read, NULL)
+
+#define remove_proc_file()	remove_proc_entry(proc_filename, NULL)
+
+#else				/* !CONFIG_USB_GADGET_DEBUG_FILES */
+
+#define create_proc_file()	do {} while (0)
+#define remove_proc_file()	do {} while (0)
+
+#endif				/* CONFIG_USB_GADGET_DEBUG_FILES */
+
+/*-------------------------------------------------------------------------*/
+
+/* Release udc structures */
+static void fsl_udc_release(struct device *dev)
+{
+	complete(udc_controller->done);
+	dma_free_coherent(dev, udc_controller->ep_qh_size,
+			udc_controller->ep_qh, udc_controller->ep_qh_dma);
+	kfree(udc_controller);
+}
+
+/******************************************************************
+	Internal structure setup functions
+*******************************************************************/
+/*------------------------------------------------------------------
+ * init resource for globle controller
+ * Return the udc handle on success or NULL on failure
+ ------------------------------------------------------------------*/
+static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
+{
+	struct fsl_udc *udc;
+	struct fsl_usb2_platform_data *pdata;
+	size_t size;
+
+	udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
+	if (udc == NULL) {
+		ERR("malloc udc failed\n");
+		return NULL;
+	}
+
+	pdata = pdev->dev.platform_data;
+	udc->phy_mode = pdata->phy_mode;
+	/* max_ep_nr is bidirectional ep number, max_ep doubles the number */
+	udc->max_ep = pdata->max_ep_nr * 2;
+
+	udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
+	if (!udc->eps) {
+		ERR("malloc fsl_ep failed\n");
+		goto cleanup;
+	}
+
+	/* initialized QHs, take care of alignment */
+	size = udc->max_ep * sizeof(struct ep_queue_head);
+	if (size < QH_ALIGNMENT)
+		size = QH_ALIGNMENT;
+	else if ((size % QH_ALIGNMENT) != 0) {
+		size += QH_ALIGNMENT + 1;
+		size &= ~(QH_ALIGNMENT - 1);
+	}
+	udc->ep_qh = dma_alloc_coherent(&pdev->dev, size,
+					&udc->ep_qh_dma, GFP_KERNEL);
+	if (!udc->ep_qh) {
+		ERR("malloc QHs for udc failed\n");
+		kfree(udc->eps);
+		goto cleanup;
+	}
+
+	udc->ep_qh_size = size;
+
+	/* Initialize ep0 status request structure */
+	/* FIXME: fsl_alloc_request() ignores ep argument */
+	udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
+			struct fsl_req, req);
+	/* allocate a small amount of memory to get valid address */
+	udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
+	udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf);
+
+	udc->resume_state = USB_STATE_NOTATTACHED;
+	udc->usb_state = USB_STATE_POWERED;
+	udc->ep0_dir = 0;
+	udc->remote_wakeup = 0;	/* default to 0 on reset */
+	spin_lock_init(&udc->lock);
+
+	return udc;
+
+cleanup:
+	kfree(udc);
+	return NULL;
+}
+
+/*----------------------------------------------------------------
+ * Setup the fsl_ep struct for eps
+ * Link fsl_ep->ep to gadget->ep_list
+ * ep0out is not used so do nothing here
+ * ep0in should be taken care
+ *--------------------------------------------------------------*/
+static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
+		char *name, int link)
+{
+	struct fsl_ep *ep = &udc->eps[index];
+
+	ep->udc = udc;
+	strcpy(ep->name, name);
+	ep->ep.name = ep->name;
+
+	ep->ep.ops = &fsl_ep_ops;
+	ep->stopped = 0;
+
+	/* for ep0: maxP defined in desc
+	 * for other eps, maxP is set by epautoconfig() called by gadget layer
+	 */
+	ep->ep.maxpacket = (unsigned short) ~0;
+
+	/* the queue lists any req for this ep */
+	INIT_LIST_HEAD(&ep->queue);
+
+	/* gagdet.ep_list used for ep_autoconfig so no ep0 */
+	if (link)
+		list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+	ep->gadget = &udc->gadget;
+	ep->qh = &udc->ep_qh[index];
+
+	return 0;
+}
+
+/* Driver probe function
+ * all intialize operations implemented here except enabling usb_intr reg
+ */
+static int __init fsl_udc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret = -ENODEV;
+	unsigned int i;
+
+	if (strcmp(pdev->name, driver_name)) {
+		VDBG("Wrong device\n");
+		return -ENODEV;
+	}
+
+	/* board setup should have been done in the platform code */
+
+	/* Initialize the udc structure including QH member and other member */
+	udc_controller = struct_udc_setup(pdev);
+	if (!udc_controller) {
+		VDBG("udc_controller is NULL \n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				driver_name)) {
+		ERR("request mem region for %s failed \n", pdev->name);
+		return -EBUSY;
+	}
+
+	dr_regs = ioremap(res->start, res->end - res->start + 1);
+	if (!dr_regs) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	usb_sys_regs = (struct usb_sys_interface *)
+			((u32)dr_regs + USB_DR_SYS_OFFSET);
+
+	udc_controller->irq = platform_get_irq(pdev, 0);
+	if (!udc_controller->irq) {
+		ret = -ENODEV;
+		goto err2;
+	}
+
+	ret = request_irq(udc_controller->irq, fsl_udc_irq, SA_SHIRQ,
+			driver_name, udc_controller);
+	if (ret != 0) {
+		ERR("cannot request irq %d err %d \n",
+				udc_controller->irq, ret);
+		goto err2;
+	}
+
+	/* initialize usb hw reg except for regs for EP,
+	 * leave usbintr reg untouched */
+	dr_controller_setup(udc_controller);
+
+	/* Setup gadget structure */
+	udc_controller->gadget.ops = &fsl_gadget_ops;
+	udc_controller->gadget.is_dualspeed = 1;
+	udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
+	INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
+	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+	udc_controller->gadget.name = driver_name;
+
+	/* Setup gadget.dev and register with kernel */
+	strcpy(udc_controller->gadget.dev.bus_id, "gadget");
+	udc_controller->gadget.dev.release = fsl_udc_release;
+	udc_controller->gadget.dev.parent = &pdev->dev;
+	ret = device_register(&udc_controller->gadget.dev);
+	if (ret < 0)
+		goto err3;
+
+	/* setup QH and epctrl for ep0 */
+	ep0_setup(udc_controller);
+
+	/* setup udc->eps[] for ep0 */
+	struct_ep_setup(udc_controller, 0, "ep0", 0);
+	/* for ep0: the desc defined here;
+	 * for other eps, gadget layer called ep_enable with defined desc
+	 */
+	udc_controller->eps[0].desc = &fsl_ep0_desc;
+	udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD;
+
+	/* setup the udc->eps[] for non-control endpoints and link
+	 * to gadget.ep_list */
+	for (i = 1; i < (int)(udc_controller->max_ep / 2); i++) {
+		char name[14];
+
+		sprintf(name, "ep%dout", i);
+		struct_ep_setup(udc_controller, i * 2, name, 1);
+		sprintf(name, "ep%din", i);
+		struct_ep_setup(udc_controller, i * 2 + 1, name, 1);
+	}
+
+	/* use dma_pool for TD management */
+	udc_controller->td_pool = dma_pool_create("udc_td", &pdev->dev,
+			sizeof(struct ep_td_struct),
+			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
+	if (udc_controller->td_pool == NULL) {
+		ret = -ENOMEM;
+		goto err4;
+	}
+	create_proc_file();
+	return 0;
+
+err4:
+	device_unregister(&udc_controller->gadget.dev);
+err3:
+	free_irq(udc_controller->irq, udc_controller);
+err2:
+	iounmap(dr_regs);
+err1:
+	release_mem_region(res->start, res->end - res->start + 1);
+	return ret;
+}
+
+/* Driver removal function
+ * Free resources and finish pending transactions
+ */
+static int __exit fsl_udc_remove(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	DECLARE_COMPLETION(done);
+
+	if (!udc_controller)
+		return -ENODEV;
+	udc_controller->done = &done;
+
+	/* DR has been stopped in usb_gadget_unregister_driver() */
+	remove_proc_file();
+
+	/* Free allocated memory */
+	kfree(udc_controller->status_req->req.buf);
+	kfree(udc_controller->status_req);
+	kfree(udc_controller->eps);
+
+	dma_pool_destroy(udc_controller->td_pool);
+	free_irq(udc_controller->irq, udc_controller);
+	iounmap(dr_regs);
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	device_unregister(&udc_controller->gadget.dev);
+	/* free udc --wait for the release() finished */
+	wait_for_completion(&done);
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Modify Power management attributes
+ * Used by OTG statemachine to disable gadget temporarily
+ -----------------------------------------------------------------*/
+static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	dr_controller_stop(udc_controller);
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Invoked on USB resume. May be called in_interrupt.
+ * Here we start the DR controller and enable the irq
+ *-----------------------------------------------------------------*/
+static int fsl_udc_resume(struct platform_device *pdev)
+{
+	/* Enable DR irq reg and set controller Run */
+	if (udc_controller->stopped) {
+		dr_controller_setup(udc_controller);
+		dr_controller_run(udc_controller);
+	}
+	udc_controller->usb_state = USB_STATE_ATTACHED;
+	udc_controller->ep0_state = WAIT_FOR_SETUP;
+	udc_controller->ep0_dir = 0;
+	return 0;
+}
+
+/*-------------------------------------------------------------------------
+	Register entry point for the peripheral controller driver
+--------------------------------------------------------------------------*/
+
+static struct platform_driver udc_driver = {
+	.remove  = __exit_p(fsl_udc_remove),
+	/* these suspend and resume are not usb suspend and resume */
+	.suspend = fsl_udc_suspend,
+	.resume  = fsl_udc_resume,
+	.driver  = {
+		.name = (char *)driver_name,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init udc_init(void)
+{
+	printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
+	return platform_driver_probe(&udc_driver, fsl_udc_probe);
+}
+
+module_init(udc_init);
+
+static void __exit udc_exit(void)
+{
+	platform_driver_unregister(&udc_driver);
+	printk("%s unregistered \n", driver_desc);
+}
+
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
new file mode 100644
index 0000000..c6291e0
--- /dev/null
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -0,0 +1,579 @@
+/*
+ * Freescale USB device/endpoint management registers
+ */
+#ifndef __FSL_USB2_UDC_H
+#define __FSL_USB2_UDC_H
+
+/* ### define USB registers here
+ */
+#define USB_MAX_CTRL_PAYLOAD		64
+#define USB_DR_SYS_OFFSET		0x400
+
+ /* USB DR device mode registers (Little Endian) */
+struct usb_dr_device {
+	/* Capability register */
+	u8 res1[256];
+	u16 caplength;		/* Capability Register Length */
+	u16 hciversion;		/* Host Controller Interface Version */
+	u32 hcsparams;		/* Host Controller Structual Parameters */
+	u32 hccparams;		/* Host Controller Capability Parameters */
+	u8 res2[20];
+	u32 dciversion;		/* Device Controller Interface Version */
+	u32 dccparams;		/* Device Controller Capability Parameters */
+	u8 res3[24];
+	/* Operation register */
+	u32 usbcmd;		/* USB Command Register */
+	u32 usbsts;		/* USB Status Register */
+	u32 usbintr;		/* USB Interrupt Enable Register */
+	u32 frindex;		/* Frame Index Register */
+	u8 res4[4];
+	u32 deviceaddr;		/* Device Address */
+	u32 endpointlistaddr;	/* Endpoint List Address Register */
+	u8 res5[4];
+	u32 burstsize;		/* Master Interface Data Burst Size Register */
+	u32 txttfilltuning;	/* Transmit FIFO Tuning Controls Register */
+	u8 res6[24];
+	u32 configflag;		/* Configure Flag Register */
+	u32 portsc1;		/* Port 1 Status and Control Register */
+	u8 res7[28];
+	u32 otgsc;		/* On-The-Go Status and Control */
+	u32 usbmode;		/* USB Mode Register */
+	u32 endptsetupstat;	/* Endpoint Setup Status Register */
+	u32 endpointprime;	/* Endpoint Initialization Register */
+	u32 endptflush;		/* Endpoint Flush Register */
+	u32 endptstatus;	/* Endpoint Status Register */
+	u32 endptcomplete;	/* Endpoint Complete Register */
+	u32 endptctrl[6];	/* Endpoint Control Registers */
+};
+
+ /* USB DR host mode registers (Little Endian) */
+struct usb_dr_host {
+	/* Capability register */
+	u8 res1[256];
+	u16 caplength;		/* Capability Register Length */
+	u16 hciversion;		/* Host Controller Interface Version */
+	u32 hcsparams;		/* Host Controller Structual Parameters */
+	u32 hccparams;		/* Host Controller Capability Parameters */
+	u8 res2[20];
+	u32 dciversion;		/* Device Controller Interface Version */
+	u32 dccparams;		/* Device Controller Capability Parameters */
+	u8 res3[24];
+	/* Operation register */
+	u32 usbcmd;		/* USB Command Register */
+	u32 usbsts;		/* USB Status Register */
+	u32 usbintr;		/* USB Interrupt Enable Register */
+	u32 frindex;		/* Frame Index Register */
+	u8 res4[4];
+	u32 periodiclistbase;	/* Periodic Frame List Base Address Register */
+	u32 asynclistaddr;	/* Current Asynchronous List Address Register */
+	u8 res5[4];
+	u32 burstsize;		/* Master Interface Data Burst Size Register */
+	u32 txttfilltuning;	/* Transmit FIFO Tuning Controls Register */
+	u8 res6[24];
+	u32 configflag;		/* Configure Flag Register */
+	u32 portsc1;		/* Port 1 Status and Control Register */
+	u8 res7[28];
+	u32 otgsc;		/* On-The-Go Status and Control */
+	u32 usbmode;		/* USB Mode Register */
+	u32 endptsetupstat;	/* Endpoint Setup Status Register */
+	u32 endpointprime;	/* Endpoint Initialization Register */
+	u32 endptflush;		/* Endpoint Flush Register */
+	u32 endptstatus;	/* Endpoint Status Register */
+	u32 endptcomplete;	/* Endpoint Complete Register */
+	u32 endptctrl[6];	/* Endpoint Control Registers */
+};
+
+ /* non-EHCI USB system interface registers (Big Endian) */
+struct usb_sys_interface {
+	u32 snoop1;
+	u32 snoop2;
+	u32 age_cnt_thresh;	/* Age Count Threshold Register */
+	u32 pri_ctrl;		/* Priority Control Register */
+	u32 si_ctrl;		/* System Interface Control Register */
+	u8 res[236];
+	u32 control;		/* General Purpose Control Register */
+};
+
+/* ep0 transfer state */
+#define WAIT_FOR_SETUP          0
+#define DATA_STATE_XMIT         1
+#define DATA_STATE_NEED_ZLP     2
+#define WAIT_FOR_OUT_STATUS     3
+#define DATA_STATE_RECV         4
+
+/* Frame Index Register Bit Masks */
+#define	USB_FRINDEX_MASKS			0x3fff
+/* USB CMD  Register Bit Masks */
+#define  USB_CMD_RUN_STOP                     0x00000001
+#define  USB_CMD_CTRL_RESET                   0x00000002
+#define  USB_CMD_PERIODIC_SCHEDULE_EN         0x00000010
+#define  USB_CMD_ASYNC_SCHEDULE_EN            0x00000020
+#define  USB_CMD_INT_AA_DOORBELL              0x00000040
+#define  USB_CMD_ASP                          0x00000300
+#define  USB_CMD_ASYNC_SCH_PARK_EN            0x00000800
+#define  USB_CMD_SUTW                         0x00002000
+#define  USB_CMD_ATDTW                        0x00004000
+#define  USB_CMD_ITC                          0x00FF0000
+
+/* bit 15,3,2 are frame list size */
+#define  USB_CMD_FRAME_SIZE_1024              0x00000000
+#define  USB_CMD_FRAME_SIZE_512               0x00000004
+#define  USB_CMD_FRAME_SIZE_256               0x00000008
+#define  USB_CMD_FRAME_SIZE_128               0x0000000C
+#define  USB_CMD_FRAME_SIZE_64                0x00008000
+#define  USB_CMD_FRAME_SIZE_32                0x00008004
+#define  USB_CMD_FRAME_SIZE_16                0x00008008
+#define  USB_CMD_FRAME_SIZE_8                 0x0000800C
+
+/* bit 9-8 are async schedule park mode count */
+#define  USB_CMD_ASP_00                       0x00000000
+#define  USB_CMD_ASP_01                       0x00000100
+#define  USB_CMD_ASP_10                       0x00000200
+#define  USB_CMD_ASP_11                       0x00000300
+#define  USB_CMD_ASP_BIT_POS                  8
+
+/* bit 23-16 are interrupt threshold control */
+#define  USB_CMD_ITC_NO_THRESHOLD             0x00000000
+#define  USB_CMD_ITC_1_MICRO_FRM              0x00010000
+#define  USB_CMD_ITC_2_MICRO_FRM              0x00020000
+#define  USB_CMD_ITC_4_MICRO_FRM              0x00040000
+#define  USB_CMD_ITC_8_MICRO_FRM              0x00080000
+#define  USB_CMD_ITC_16_MICRO_FRM             0x00100000
+#define  USB_CMD_ITC_32_MICRO_FRM             0x00200000
+#define  USB_CMD_ITC_64_MICRO_FRM             0x00400000
+#define  USB_CMD_ITC_BIT_POS                  16
+
+/* USB STS Register Bit Masks */
+#define  USB_STS_INT                          0x00000001
+#define  USB_STS_ERR                          0x00000002
+#define  USB_STS_PORT_CHANGE                  0x00000004
+#define  USB_STS_FRM_LST_ROLL                 0x00000008
+#define  USB_STS_SYS_ERR                      0x00000010
+#define  USB_STS_IAA                          0x00000020
+#define  USB_STS_RESET                        0x00000040
+#define  USB_STS_SOF                          0x00000080
+#define  USB_STS_SUSPEND                      0x00000100
+#define  USB_STS_HC_HALTED                    0x00001000
+#define  USB_STS_RCL                          0x00002000
+#define  USB_STS_PERIODIC_SCHEDULE            0x00004000
+#define  USB_STS_ASYNC_SCHEDULE               0x00008000
+
+/* USB INTR Register Bit Masks */
+#define  USB_INTR_INT_EN                      0x00000001
+#define  USB_INTR_ERR_INT_EN                  0x00000002
+#define  USB_INTR_PTC_DETECT_EN               0x00000004
+#define  USB_INTR_FRM_LST_ROLL_EN             0x00000008
+#define  USB_INTR_SYS_ERR_EN                  0x00000010
+#define  USB_INTR_ASYN_ADV_EN                 0x00000020
+#define  USB_INTR_RESET_EN                    0x00000040
+#define  USB_INTR_SOF_EN                      0x00000080
+#define  USB_INTR_DEVICE_SUSPEND              0x00000100
+
+/* Device Address bit masks */
+#define  USB_DEVICE_ADDRESS_MASK              0xFE000000
+#define  USB_DEVICE_ADDRESS_BIT_POS           25
+
+/* endpoint list address bit masks */
+#define USB_EP_LIST_ADDRESS_MASK              0xfffff800
+
+/* PORTSCX  Register Bit Masks */
+#define  PORTSCX_CURRENT_CONNECT_STATUS       0x00000001
+#define  PORTSCX_CONNECT_STATUS_CHANGE        0x00000002
+#define  PORTSCX_PORT_ENABLE                  0x00000004
+#define  PORTSCX_PORT_EN_DIS_CHANGE           0x00000008
+#define  PORTSCX_OVER_CURRENT_ACT             0x00000010
+#define  PORTSCX_OVER_CURRENT_CHG             0x00000020
+#define  PORTSCX_PORT_FORCE_RESUME            0x00000040
+#define  PORTSCX_PORT_SUSPEND                 0x00000080
+#define  PORTSCX_PORT_RESET                   0x00000100
+#define  PORTSCX_LINE_STATUS_BITS             0x00000C00
+#define  PORTSCX_PORT_POWER                   0x00001000
+#define  PORTSCX_PORT_INDICTOR_CTRL           0x0000C000
+#define  PORTSCX_PORT_TEST_CTRL               0x000F0000
+#define  PORTSCX_WAKE_ON_CONNECT_EN           0x00100000
+#define  PORTSCX_WAKE_ON_CONNECT_DIS          0x00200000
+#define  PORTSCX_WAKE_ON_OVER_CURRENT         0x00400000
+#define  PORTSCX_PHY_LOW_POWER_SPD            0x00800000
+#define  PORTSCX_PORT_FORCE_FULL_SPEED        0x01000000
+#define  PORTSCX_PORT_SPEED_MASK              0x0C000000
+#define  PORTSCX_PORT_WIDTH                   0x10000000
+#define  PORTSCX_PHY_TYPE_SEL                 0xC0000000
+
+/* bit 11-10 are line status */
+#define  PORTSCX_LINE_STATUS_SE0              0x00000000
+#define  PORTSCX_LINE_STATUS_JSTATE           0x00000400
+#define  PORTSCX_LINE_STATUS_KSTATE           0x00000800
+#define  PORTSCX_LINE_STATUS_UNDEF            0x00000C00
+#define  PORTSCX_LINE_STATUS_BIT_POS          10
+
+/* bit 15-14 are port indicator control */
+#define  PORTSCX_PIC_OFF                      0x00000000
+#define  PORTSCX_PIC_AMBER                    0x00004000
+#define  PORTSCX_PIC_GREEN                    0x00008000
+#define  PORTSCX_PIC_UNDEF                    0x0000C000
+#define  PORTSCX_PIC_BIT_POS                  14
+
+/* bit 19-16 are port test control */
+#define  PORTSCX_PTC_DISABLE                  0x00000000
+#define  PORTSCX_PTC_JSTATE                   0x00010000
+#define  PORTSCX_PTC_KSTATE                   0x00020000
+#define  PORTSCX_PTC_SEQNAK                   0x00030000
+#define  PORTSCX_PTC_PACKET                   0x00040000
+#define  PORTSCX_PTC_FORCE_EN                 0x00050000
+#define  PORTSCX_PTC_BIT_POS                  16
+
+/* bit 27-26 are port speed */
+#define  PORTSCX_PORT_SPEED_FULL              0x00000000
+#define  PORTSCX_PORT_SPEED_LOW               0x04000000
+#define  PORTSCX_PORT_SPEED_HIGH              0x08000000
+#define  PORTSCX_PORT_SPEED_UNDEF             0x0C000000
+#define  PORTSCX_SPEED_BIT_POS                26
+
+/* bit 28 is parallel transceiver width for UTMI interface */
+#define  PORTSCX_PTW                          0x10000000
+#define  PORTSCX_PTW_8BIT                     0x00000000
+#define  PORTSCX_PTW_16BIT                    0x10000000
+
+/* bit 31-30 are port transceiver select */
+#define  PORTSCX_PTS_UTMI                     0x00000000
+#define  PORTSCX_PTS_ULPI                     0x80000000
+#define  PORTSCX_PTS_FSLS                     0xC0000000
+#define  PORTSCX_PTS_BIT_POS                  30
+
+/* otgsc Register Bit Masks */
+#define  OTGSC_CTRL_VUSB_DISCHARGE            0x00000001
+#define  OTGSC_CTRL_VUSB_CHARGE               0x00000002
+#define  OTGSC_CTRL_OTG_TERM                  0x00000008
+#define  OTGSC_CTRL_DATA_PULSING              0x00000010
+#define  OTGSC_STS_USB_ID                     0x00000100
+#define  OTGSC_STS_A_VBUS_VALID               0x00000200
+#define  OTGSC_STS_A_SESSION_VALID            0x00000400
+#define  OTGSC_STS_B_SESSION_VALID            0x00000800
+#define  OTGSC_STS_B_SESSION_END              0x00001000
+#define  OTGSC_STS_1MS_TOGGLE                 0x00002000
+#define  OTGSC_STS_DATA_PULSING               0x00004000
+#define  OTGSC_INTSTS_USB_ID                  0x00010000
+#define  OTGSC_INTSTS_A_VBUS_VALID            0x00020000
+#define  OTGSC_INTSTS_A_SESSION_VALID         0x00040000
+#define  OTGSC_INTSTS_B_SESSION_VALID         0x00080000
+#define  OTGSC_INTSTS_B_SESSION_END           0x00100000
+#define  OTGSC_INTSTS_1MS                     0x00200000
+#define  OTGSC_INTSTS_DATA_PULSING            0x00400000
+#define  OTGSC_INTR_USB_ID                    0x01000000
+#define  OTGSC_INTR_A_VBUS_VALID              0x02000000
+#define  OTGSC_INTR_A_SESSION_VALID           0x04000000
+#define  OTGSC_INTR_B_SESSION_VALID           0x08000000
+#define  OTGSC_INTR_B_SESSION_END             0x10000000
+#define  OTGSC_INTR_1MS_TIMER                 0x20000000
+#define  OTGSC_INTR_DATA_PULSING              0x40000000
+
+/* USB MODE Register Bit Masks */
+#define  USB_MODE_CTRL_MODE_IDLE              0x00000000
+#define  USB_MODE_CTRL_MODE_DEVICE            0x00000002
+#define  USB_MODE_CTRL_MODE_HOST              0x00000003
+#define  USB_MODE_CTRL_MODE_RSV               0x00000001
+#define  USB_MODE_SETUP_LOCK_OFF              0x00000008
+#define  USB_MODE_STREAM_DISABLE              0x00000010
+/* Endpoint Flush Register */
+#define EPFLUSH_TX_OFFSET		      0x00010000
+#define EPFLUSH_RX_OFFSET		      0x00000000
+
+/* Endpoint Setup Status bit masks */
+#define  EP_SETUP_STATUS_MASK                 0x0000003F
+#define  EP_SETUP_STATUS_EP0		      0x00000001
+
+/* ENDPOINTCTRLx  Register Bit Masks */
+#define  EPCTRL_TX_ENABLE                     0x00800000
+#define  EPCTRL_TX_DATA_TOGGLE_RST            0x00400000	/* Not EP0 */
+#define  EPCTRL_TX_DATA_TOGGLE_INH            0x00200000	/* Not EP0 */
+#define  EPCTRL_TX_TYPE                       0x000C0000
+#define  EPCTRL_TX_DATA_SOURCE                0x00020000	/* Not EP0 */
+#define  EPCTRL_TX_EP_STALL                   0x00010000
+#define  EPCTRL_RX_ENABLE                     0x00000080
+#define  EPCTRL_RX_DATA_TOGGLE_RST            0x00000040	/* Not EP0 */
+#define  EPCTRL_RX_DATA_TOGGLE_INH            0x00000020	/* Not EP0 */
+#define  EPCTRL_RX_TYPE                       0x0000000C
+#define  EPCTRL_RX_DATA_SINK                  0x00000002	/* Not EP0 */
+#define  EPCTRL_RX_EP_STALL                   0x00000001
+
+/* bit 19-18 and 3-2 are endpoint type */
+#define  EPCTRL_EP_TYPE_CONTROL               0
+#define  EPCTRL_EP_TYPE_ISO                   1
+#define  EPCTRL_EP_TYPE_BULK                  2
+#define  EPCTRL_EP_TYPE_INTERRUPT             3
+#define  EPCTRL_TX_EP_TYPE_SHIFT              18
+#define  EPCTRL_RX_EP_TYPE_SHIFT              2
+
+/* SNOOPn Register Bit Masks */
+#define  SNOOP_ADDRESS_MASK                   0xFFFFF000
+#define  SNOOP_SIZE_ZERO                      0x00	/* snooping disable */
+#define  SNOOP_SIZE_4KB                       0x0B	/* 4KB snoop size */
+#define  SNOOP_SIZE_8KB                       0x0C
+#define  SNOOP_SIZE_16KB                      0x0D
+#define  SNOOP_SIZE_32KB                      0x0E
+#define  SNOOP_SIZE_64KB                      0x0F
+#define  SNOOP_SIZE_128KB                     0x10
+#define  SNOOP_SIZE_256KB                     0x11
+#define  SNOOP_SIZE_512KB                     0x12
+#define  SNOOP_SIZE_1MB                       0x13
+#define  SNOOP_SIZE_2MB                       0x14
+#define  SNOOP_SIZE_4MB                       0x15
+#define  SNOOP_SIZE_8MB                       0x16
+#define  SNOOP_SIZE_16MB                      0x17
+#define  SNOOP_SIZE_32MB                      0x18
+#define  SNOOP_SIZE_64MB                      0x19
+#define  SNOOP_SIZE_128MB                     0x1A
+#define  SNOOP_SIZE_256MB                     0x1B
+#define  SNOOP_SIZE_512MB                     0x1C
+#define  SNOOP_SIZE_1GB                       0x1D
+#define  SNOOP_SIZE_2GB                       0x1E	/* 2GB snoop size */
+
+/* pri_ctrl Register Bit Masks */
+#define  PRI_CTRL_PRI_LVL1                    0x0000000C
+#define  PRI_CTRL_PRI_LVL0                    0x00000003
+
+/* si_ctrl Register Bit Masks */
+#define  SI_CTRL_ERR_DISABLE                  0x00000010
+#define  SI_CTRL_IDRC_DISABLE                 0x00000008
+#define  SI_CTRL_RD_SAFE_EN                   0x00000004
+#define  SI_CTRL_RD_PREFETCH_DISABLE          0x00000002
+#define  SI_CTRL_RD_PREFEFETCH_VAL            0x00000001
+
+/* control Register Bit Masks */
+#define  USB_CTRL_IOENB                       0x00000004
+#define  USB_CTRL_ULPI_INT0EN                 0x00000001
+
+/* Endpoint Queue Head data struct
+ * Rem: all the variables of qh are LittleEndian Mode
+ * and NEXT_POINTER_MASK should operate on a LittleEndian, Phy Addr
+ */
+struct ep_queue_head {
+	u32 max_pkt_length;	/* Mult(31-30) , Zlt(29) , Max Pkt len
+				   and IOS(15) */
+	u32 curr_dtd_ptr;	/* Current dTD Pointer(31-5) */
+	u32 next_dtd_ptr;	/* Next dTD Pointer(31-5), T(0) */
+	u32 size_ioc_int_sts;	/* Total bytes (30-16), IOC (15),
+				   MultO(11-10), STS (7-0)  */
+	u32 buff_ptr0;		/* Buffer pointer Page 0 (31-12) */
+	u32 buff_ptr1;		/* Buffer pointer Page 1 (31-12) */
+	u32 buff_ptr2;		/* Buffer pointer Page 2 (31-12) */
+	u32 buff_ptr3;		/* Buffer pointer Page 3 (31-12) */
+	u32 buff_ptr4;		/* Buffer pointer Page 4 (31-12) */
+	u32 res1;
+	u8 setup_buffer[8];	/* Setup data 8 bytes */
+	u32 res2[4];
+};
+
+/* Endpoint Queue Head Bit Masks */
+#define  EP_QUEUE_HEAD_MULT_POS               30
+#define  EP_QUEUE_HEAD_ZLT_SEL                0x20000000
+#define  EP_QUEUE_HEAD_MAX_PKT_LEN_POS        16
+#define  EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info)   (((ep_info)>>16)&0x07ff)
+#define  EP_QUEUE_HEAD_IOS                    0x00008000
+#define  EP_QUEUE_HEAD_NEXT_TERMINATE         0x00000001
+#define  EP_QUEUE_HEAD_IOC                    0x00008000
+#define  EP_QUEUE_HEAD_MULTO                  0x00000C00
+#define  EP_QUEUE_HEAD_STATUS_HALT	      0x00000040
+#define  EP_QUEUE_HEAD_STATUS_ACTIVE          0x00000080
+#define  EP_QUEUE_CURRENT_OFFSET_MASK         0x00000FFF
+#define  EP_QUEUE_HEAD_NEXT_POINTER_MASK      0xFFFFFFE0
+#define  EP_QUEUE_FRINDEX_MASK                0x000007FF
+#define  EP_MAX_LENGTH_TRANSFER               0x4000
+
+/* Endpoint Transfer Descriptor data struct */
+/* Rem: all the variables of td are LittleEndian Mode */
+struct ep_td_struct {
+	u32 next_td_ptr;	/* Next TD pointer(31-5), T(0) set
+				   indicate invalid */
+	u32 size_ioc_sts;	/* Total bytes (30-16), IOC (15),
+				   MultO(11-10), STS (7-0)  */
+	u32 buff_ptr0;		/* Buffer pointer Page 0 */
+	u32 buff_ptr1;		/* Buffer pointer Page 1 */
+	u32 buff_ptr2;		/* Buffer pointer Page 2 */
+	u32 buff_ptr3;		/* Buffer pointer Page 3 */
+	u32 buff_ptr4;		/* Buffer pointer Page 4 */
+	u32 res;
+	/* 32 bytes */
+	dma_addr_t td_dma;	/* dma address for this td */
+	/* virtual address of next td specified in next_td_ptr */
+	struct ep_td_struct *next_td_virt;
+};
+
+/* Endpoint Transfer Descriptor bit Masks */
+#define  DTD_NEXT_TERMINATE                   0x00000001
+#define  DTD_IOC                              0x00008000
+#define  DTD_STATUS_ACTIVE                    0x00000080
+#define  DTD_STATUS_HALTED                    0x00000040
+#define  DTD_STATUS_DATA_BUFF_ERR             0x00000020
+#define  DTD_STATUS_TRANSACTION_ERR           0x00000008
+#define  DTD_RESERVED_FIELDS                  0x80007300
+#define  DTD_ADDR_MASK                        0xFFFFFFE0
+#define  DTD_PACKET_SIZE                      0x7FFF0000
+#define  DTD_LENGTH_BIT_POS                   16
+#define  DTD_ERROR_MASK                       (DTD_STATUS_HALTED | \
+                                               DTD_STATUS_DATA_BUFF_ERR | \
+                                               DTD_STATUS_TRANSACTION_ERR)
+/* Alignment requirements; must be a power of two */
+#define DTD_ALIGNMENT				0x20
+#define QH_ALIGNMENT				2048
+
+/* Controller dma boundary */
+#define UDC_DMA_BOUNDARY			0x1000
+
+/* -----------------------------------------------------------------------*/
+/* ##### enum data
+*/
+typedef enum {
+	e_ULPI,
+	e_UTMI_8BIT,
+	e_UTMI_16BIT,
+	e_SERIAL
+} e_PhyInterface;
+
+/*-------------------------------------------------------------------------*/
+
+/* ### driver private data
+ */
+struct fsl_req {
+	struct usb_request req;
+	struct list_head queue;
+	/* ep_queue() func will add
+	   a request->queue into a udc_ep->queue 'd tail */
+	struct fsl_ep *ep;
+	unsigned mapped:1;
+
+	struct ep_td_struct *head, *tail;	/* For dTD List
+						   cpu endian Virtual addr */
+	unsigned int dtd_count;
+};
+
+#define REQ_UNCOMPLETE			1
+
+struct fsl_ep {
+	struct usb_ep ep;
+	struct list_head queue;
+	struct fsl_udc *udc;
+	struct ep_queue_head *qh;
+	const struct usb_endpoint_descriptor *desc;
+	struct usb_gadget *gadget;
+
+	char name[14];
+	unsigned stopped:1;
+};
+
+#define EP_DIR_IN	1
+#define EP_DIR_OUT	0
+
+struct fsl_udc {
+
+	struct usb_gadget gadget;
+	struct usb_gadget_driver *driver;
+	struct fsl_ep *eps;
+	unsigned int max_ep;
+	unsigned int irq;
+
+	struct usb_ctrlrequest local_setup_buff;
+	spinlock_t lock;
+	struct otg_transceiver *transceiver;
+	unsigned softconnect:1;
+	unsigned vbus_active:1;
+	unsigned stopped:1;
+	unsigned remote_wakeup:1;
+
+	struct ep_queue_head *ep_qh;	/* Endpoints Queue-Head */
+	struct fsl_req *status_req;	/* ep0 status request */
+	struct dma_pool *td_pool;	/* dma pool for DTD */
+	enum fsl_usb2_phy_modes phy_mode;
+
+	size_t ep_qh_size;		/* size after alignment adjustment*/
+	dma_addr_t ep_qh_dma;		/* dma address of QH */
+
+	u32 max_pipes;		/* Device max pipes */
+	u32 max_use_endpts;	/* Max endpointes to be used */
+	u32 bus_reset;		/* Device is bus reseting */
+	u32 resume_state;	/* USB state to resume */
+	u32 usb_state;		/* USB current state */
+	u32 usb_next_state;	/* USB next state */
+	u32 ep0_state;		/* Endpoint zero state */
+	u32 ep0_dir;		/* Endpoint zero direction: can be
+				   USB_DIR_IN or USB_DIR_OUT */
+	u32 usb_sof_count;	/* SOF count */
+	u32 errors;		/* USB ERRORs count */
+	u8 device_address;	/* Device USB address */
+
+	struct completion *done;	/* to make sure release() is done */
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+#define DBG(fmt, args...) 	printk(KERN_DEBUG "[%s]  " fmt "\n", \
+				__FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)	do{}while(0)
+#endif
+
+#if 0
+static void dump_msg(const char *label, const u8 * buf, unsigned int length)
+{
+	unsigned int start, num, i;
+	char line[52], *p;
+
+	if (length >= 512)
+		return;
+	DBG("%s, length %u:\n", label, length);
+	start = 0;
+	while (length > 0) {
+		num = min(length, 16u);
+		p = line;
+		for (i = 0; i < num; ++i) {
+			if (i == 8)
+				*p++ = ' ';
+			sprintf(p, " %02x", buf[i]);
+			p += 3;
+		}
+		*p = 0;
+		printk(KERN_DEBUG "%6x: %s\n", start, line);
+		buf += num;
+		start += num;
+		length -= num;
+	}
+}
+#endif
+
+#ifdef VERBOSE
+#define VDBG		DBG
+#else
+#define VDBG(stuff...)	do{}while(0)
+#endif
+
+#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
+#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
+#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+
+/*-------------------------------------------------------------------------*/
+
+/* ### Add board specific defines here
+ */
+
+/*
+ * ### pipe direction macro from device view
+ */
+#define USB_RECV	0	/* OUT EP */
+#define USB_SEND	1	/* IN EP */
+
+/*
+ * ### internal used help routines.
+ */
+#define ep_index(EP)		((EP)->desc->bEndpointAddress&0xF)
+#define ep_maxpacket(EP)	((EP)->ep.maxpacket)
+#define ep_is_in(EP)	( (ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
+			USB_DIR_IN ):((EP)->desc->bEndpointAddress \
+			& USB_DIR_IN)==USB_DIR_IN)
+#define get_ep_by_pipe(udc, pipe)	((pipe == 1)? &udc->eps[0]: \
+					&udc->eps[pipe])
+#define get_pipe_by_windex(windex)	((windex & USB_ENDPOINT_NUMBER_MASK) \
+					* 2 + ((windex & USB_DIR_IN) ? 1 : 0))
+#define get_pipe_by_ep(EP)	(ep_index(EP) * 2 + ep_is_in(EP))
+
+#endif
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 2e3d662..d041b91 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -99,6 +99,12 @@
 #define gadget_is_imx(g)	0
 #endif
 
+#ifdef CONFIG_USB_GADGET_FSL_USB2
+#define gadget_is_fsl_usb2(g)	!strcmp("fsl-usb2-udc", (g)->name)
+#else
+#define gadget_is_fsl_usb2(g)	0
+#endif
+
 /* Mentor high speed function controller */
 #ifdef CONFIG_USB_GADGET_MUSBHSFC
 #define gadget_is_musbhsfc(g)	!strcmp("musbhsfc_udc", (g)->name)
@@ -177,5 +183,7 @@
 		return 0x17;
 	else if (gadget_is_husb2dev(gadget))
 		return 0x18;
+	else if (gadget_is_fsl_usb2(gadget))
+		return 0x19;
 	return -ENOENT;
 }
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 7b3a326..65c91d3 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -297,27 +297,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
- *
- * other platforms need more care, with 2.6 having a moderately general
- * solution except for the common "buffer is smaller than a page" case.
- */
-#if	defined(CONFIG_X86)
-#define USE_KMALLOC
-
-#elif	defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
-#define USE_KMALLOC
-
-#elif	defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
-
-#endif
-
 /* allocating buffers this way eliminates dma mapping overhead, which
  * on some platforms will mean eliminating a per-io buffer copy.  with
  * some kinds of system caches, further tweaks may still be needed.
@@ -334,11 +313,6 @@
 		return NULL;
 	*dma = DMA_ADDR_INVALID;
 
-#if	defined(USE_KMALLOC)
-	retval = kmalloc(bytes, gfp_flags);
-	if (retval)
-		*dma = virt_to_phys(retval);
-#else
 	if (ep->dma) {
 		/* the main problem with this call is that it wastes memory
 		 * on typical 1/N page allocations: it allocates 1-N pages.
@@ -348,7 +322,6 @@
 				bytes, dma, gfp_flags);
 	} else
 		retval = kmalloc(bytes, gfp_flags);
-#endif
 	return retval;
 }
 
@@ -356,7 +329,6 @@
 goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
 {
 	/* free memory into the right allocator */
-#ifndef	USE_KMALLOC
 	if (dma != DMA_ADDR_INVALID) {
 		struct goku_ep	*ep;
 
@@ -365,7 +337,6 @@
 			return;
 		dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
 	} else
-#endif
 		kfree (buf);
 }
 
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 34296e7..188c74a 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -553,6 +553,7 @@
 {
 	struct kiocb_priv	*priv = iocb->private;
 	ssize_t			len, total;
+	void			*to_copy;
 	int			i;
 
 	/* we "retry" to get the right mm context for this: */
@@ -560,10 +561,11 @@
 	/* copy stuff into user buffers */
 	total = priv->actual;
 	len = 0;
+	to_copy = priv->buf;
 	for (i=0; i < priv->nr_segs; i++) {
 		ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
 
-		if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
+		if (copy_to_user(priv->iv[i].iov_base, to_copy, this)) {
 			if (len == 0)
 				len = -EFAULT;
 			break;
@@ -571,6 +573,7 @@
 
 		total -= this;
 		len += this;
+		to_copy += this;
 		if (total == 0)
 			break;
 	}
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 8f9a2b6..b394e63 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -296,6 +296,15 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * dma-coherent memory allocation (for dma-capable endpoints)
+ *
+ * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
+ * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
+ * respect to calls with irqs disabled:  alloc is safe, free is not.
+ * We currently work around (b), but not (a).
+ */
+
 static void *
 omap_alloc_buffer(
 	struct usb_ep	*_ep,
@@ -307,6 +316,9 @@
 	void		*retval;
 	struct omap_ep	*ep;
 
+	if (!_ep)
+		return NULL;
+
 	ep = container_of(_ep, struct omap_ep, ep);
 	if (use_dma && ep->has_dma) {
 		static int	warned;
@@ -326,6 +338,35 @@
 	return retval;
 }
 
+static DEFINE_SPINLOCK(buflock);
+static LIST_HEAD(buffers);
+
+struct free_record {
+	struct list_head	list;
+	struct device		*dev;
+	unsigned		bytes;
+	dma_addr_t		dma;
+};
+
+static void do_free(unsigned long ignored)
+{
+	spin_lock_irq(&buflock);
+	while (!list_empty(&buffers)) {
+		struct free_record	*buf;
+
+		buf = list_entry(buffers.next, struct free_record, list);
+		list_del(&buf->list);
+		spin_unlock_irq(&buflock);
+
+		dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
+
+		spin_lock_irq(&buflock);
+	}
+	spin_unlock_irq(&buflock);
+}
+
+static DECLARE_TASKLET(deferred_free, do_free, 0);
+
 static void omap_free_buffer(
 	struct usb_ep	*_ep,
 	void		*buf,
@@ -333,13 +374,29 @@
 	unsigned	bytes
 )
 {
-	struct omap_ep	*ep;
+	if (!_ep) {
+		WARN_ON(1);
+		return;
+	}
 
-	ep = container_of(_ep, struct omap_ep, ep);
-	if (use_dma && _ep && ep->has_dma)
-		dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
-	else
-		kfree (buf);
+	/* free memory into the right allocator */
+	if (dma != DMA_ADDR_INVALID) {
+		struct omap_ep		*ep;
+		struct free_record	*rec = buf;
+		unsigned long		flags;
+
+		ep = container_of(_ep, struct omap_ep, ep);
+
+		rec->dev = ep->udc->gadget.dev.parent;
+		rec->bytes = bytes;
+		rec->dma = dma;
+
+		spin_lock_irqsave(&buflock, flags);
+		list_add_tail(&rec->list, &buffers);
+		tasklet_schedule(&deferred_free);
+		spin_unlock_irqrestore(&buflock, flags);
+	} else
+		kfree(buf);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1691,12 +1748,38 @@
 			udc->ep0_pending = 0;
 			break;
 		case USB_REQ_GET_STATUS:
+			/* USB_ENDPOINT_HALT status? */
+			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
+				goto intf_status;
+
+			/* ep0 never stalls */
+			if (!(w_index & 0xf))
+				goto zero_status;
+
+			/* only active endpoints count */
+			ep = &udc->ep[w_index & 0xf];
+			if (w_index & USB_DIR_IN)
+				ep += 16;
+			if (!ep->desc)
+				goto do_stall;
+
+			/* iso never stalls */
+			if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+				goto zero_status;
+
+			/* FIXME don't assume non-halted endpoints!! */
+			ERR("%s status, can't report\n", ep->ep.name);
+			goto do_stall;
+
+intf_status:
 			/* return interface status.  if we were pedantic,
 			 * we'd detect non-existent interfaces, and stall.
 			 */
 			if (u.r.bRequestType
 					!= (USB_DIR_IN|USB_RECIP_INTERFACE))
 				goto delegate;
+
+zero_status:
 			/* return two zero bytes */
 			UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
 			UDC_DATA_REG = 0;
@@ -2068,7 +2151,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static inline int machine_needs_vbus_session(void)
+static inline int machine_without_vbus_sense(void)
 {
 	return (machine_is_omap_innovator()
 		|| machine_is_omap_osk()
@@ -2156,7 +2239,7 @@
 	/* boards that don't have VBUS sensing can't autogate 48MHz;
 	 * can't enter deep sleep while a gadget driver is active.
 	 */
-	if (machine_needs_vbus_session())
+	if (machine_without_vbus_sense())
 		omap_vbus_session(&udc->gadget, 1);
 
 done:
@@ -2179,7 +2262,7 @@
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(1);
 
-	if (machine_needs_vbus_session())
+	if (machine_without_vbus_sense())
 		omap_vbus_session(&udc->gadget, 0);
 
 	if (udc->transceiver)
@@ -2822,7 +2905,7 @@
 		hmc = HMC_1510;
 		type = "(unknown)";
 
-		if (machine_is_omap_innovator() || machine_is_sx1()) {
+		if (machine_without_vbus_sense()) {
 			/* just set up software VBUS detect, and then
 			 * later rig it so we always report VBUS.
 			 * FIXME without really sensing VBUS, we can't
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 27904a5..2c043a1 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -71,7 +71,7 @@
  * by the host to interact with this device, and allocates endpoints to
  * the different protocol interfaces.  The controller driver virtualizes
  * usb hardware so that the gadget drivers will be more portable.
- * 
+ *
  * This UDC hardware wants to implement a bit too much USB protocol, so
  * it constrains the sorts of USB configuration change events that work.
  * The errata for these chips are misleading; some "fixed" bugs from
@@ -141,7 +141,7 @@
 #endif
 
 /* ---------------------------------------------------------------------------
- * 	endpoint related parts of the api to the usb controller hardware,
+ *	endpoint related parts of the api to the usb controller hardware,
  *	used by gadget driver; and the inner talker-to-hardware core.
  * ---------------------------------------------------------------------------
  */
@@ -155,7 +155,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_vbus)
-		return pxa_gpio_get(mach->gpio_vbus);
+		return udc_gpio_get(mach->gpio_vbus);
 	if (mach->udc_is_connected)
 		return mach->udc_is_connected();
 	return 1;
@@ -167,7 +167,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_pullup)
-		pxa_gpio_set(mach->gpio_pullup, 0);
+		udc_gpio_set(mach->gpio_pullup, 0);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
@@ -177,7 +177,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_pullup)
-		pxa_gpio_set(mach->gpio_pullup, 1);
+		udc_gpio_set(mach->gpio_pullup, 1);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
@@ -293,7 +293,7 @@
 
 #ifdef	USE_DMA
 	/* for (some) bulk and ISO endpoints, try to get a DMA channel and
-	 * bind it to the endpoint.  otherwise use PIO. 
+	 * bind it to the endpoint.  otherwise use PIO.
 	 */
 	switch (ep->bmAttributes) {
 	case USB_ENDPOINT_XFER_ISOC:
@@ -304,7 +304,7 @@
 		if (!use_dma || !ep->reg_drcmr)
 			break;
 		ep->dma = pxa_request_dma ((char *)_ep->name,
- 				(le16_to_cpu (desc->wMaxPacketSize) > 64)
+				(le16_to_cpu (desc->wMaxPacketSize) > 64)
 					? DMA_PRIO_MEDIUM /* some iso */
 					: DMA_PRIO_LOW,
 				dma_nodesc_handler, ep);
@@ -361,7 +361,7 @@
  */
 
 /*
- * 	pxa2xx_ep_alloc_request - allocate a request data structure
+ *	pxa2xx_ep_alloc_request - allocate a request data structure
  */
 static struct usb_request *
 pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
@@ -378,7 +378,7 @@
 
 
 /*
- * 	pxa2xx_ep_free_request - deallocate a request data structure
+ *	pxa2xx_ep_free_request - deallocate a request data structure
  */
 static void
 pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
@@ -1031,7 +1031,7 @@
 
 
 /*
- * 	nuke - dequeue ALL requests
+ *	nuke - dequeue ALL requests
  */
 static void nuke(struct pxa2xx_ep *ep, int status)
 {
@@ -1136,16 +1136,16 @@
 		ep->dev->req_pending = 0;
 		ep->dev->ep0state = EP0_STALL;
 
- 	/* and bulk/intr endpoints like dropping stalls too */
- 	} else {
- 		unsigned i;
- 		for (i = 0; i < 1000; i += 20) {
- 			if (*ep->reg_udccs & UDCCS_BI_SST)
- 				break;
- 			udelay(20);
- 		}
-  	}
- 	local_irq_restore(flags);
+	/* and bulk/intr endpoints like dropping stalls too */
+	} else {
+		unsigned i;
+		for (i = 0; i < 1000; i += 20) {
+			if (*ep->reg_udccs & UDCCS_BI_SST)
+				break;
+			udelay(20);
+		}
+	}
+	local_irq_restore(flags);
 
 	DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
 	return 0;
@@ -1216,7 +1216,7 @@
 
 
 /* ---------------------------------------------------------------------------
- * 	device-scoped parts of the api to the usb controller hardware
+ *	device-scoped parts of the api to the usb controller hardware
  * ---------------------------------------------------------------------------
  */
 
@@ -1239,7 +1239,7 @@
 static void udc_disable(struct pxa2xx_udc *);
 
 /* We disable the UDC -- and its 48 MHz clock -- whenever it's not
- * in active use.  
+ * in active use.
  */
 static int pullup(struct pxa2xx_udc *udc, int is_active)
 {
@@ -1464,24 +1464,10 @@
 
 #endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
 
-/* "function" sysfs attribute */
-static ssize_t
-show_function (struct device *_dev, struct device_attribute *attr, char *buf)
-{
-	struct pxa2xx_udc	*dev = dev_get_drvdata (_dev);
-
-	if (!dev->driver
-			|| !dev->driver->function
-			|| strlen (dev->driver->function) > PAGE_SIZE)
-		return 0;
-	return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
-}
-static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
-
 /*-------------------------------------------------------------------------*/
 
 /*
- * 	udc_disable - disable USB device controller
+ *	udc_disable - disable USB device controller
  */
 static void udc_disable(struct pxa2xx_udc *dev)
 {
@@ -1507,7 +1493,7 @@
 
 
 /*
- * 	udc_reinit - initialize software state
+ *	udc_reinit - initialize software state
  */
 static void udc_reinit(struct pxa2xx_udc *dev)
 {
@@ -1635,18 +1621,20 @@
 	dev->gadget.dev.driver = &driver->driver;
 	dev->pullup = 1;
 
-	device_add (&dev->gadget.dev);
+	retval = device_add (&dev->gadget.dev);
+	if (retval) {
+fail:
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
+		return retval;
+	}
 	retval = driver->bind(&dev->gadget);
 	if (retval) {
 		DMSG("bind to driver %s --> error %d\n",
 				driver->driver.name, retval);
 		device_del (&dev->gadget.dev);
-
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
+		goto fail;
 	}
-	device_create_file(dev->dev, &dev_attr_function);
 
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
@@ -1704,7 +1692,6 @@
 	dev->driver = NULL;
 
 	device_del (&dev->gadget.dev);
-	device_remove_file(dev->dev, &dev_attr_function);
 
 	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
 	dump_state(dev);
@@ -1755,7 +1742,7 @@
 static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 {
 	struct pxa2xx_udc	*dev = _dev;
-	int			vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+	int			vbus = udc_gpio_get(dev->mach->gpio_vbus);
 
 	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	return IRQ_HANDLED;
@@ -2474,12 +2461,12 @@
 #define IXP465_AD		0x00000200
 
 /*
- * 	probe - binds to the platform device
+ *	probe - binds to the platform device
  */
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
 	struct pxa2xx_udc *dev = &memory;
-	int retval, out_dma = 1, vbus_irq;
+	int retval, out_dma = 1, vbus_irq, irq;
 	u32 chiprev;
 
 	/* insist on Intel/ARM/XScale */
@@ -2522,7 +2509,11 @@
 		return -ENODEV;
 	}
 
-	pr_debug("%s: IRQ %d%s%s%s\n", driver_name, IRQ_USB,
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq,
 		dev->has_cfr ? "" : " (!cfr)",
 		out_dma ? "" : " (broken dma-out)",
 		SIZE_STR DMASTR
@@ -2545,15 +2536,13 @@
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
 	if (dev->mach->gpio_vbus) {
-		vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR);
-		pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR)
-				| GPIO_IN);
+		udc_gpio_init_vbus(dev->mach->gpio_vbus);
+		vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
 		set_irq_type(vbus_irq, IRQT_BOTHEDGE);
 	} else
 		vbus_irq = 0;
 	if (dev->mach->gpio_pullup)
-		pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR)
-				| GPIO_OUT | GPIO_DFLT_LOW);
+		udc_gpio_init_pullup(dev->mach->gpio_pullup);
 
 	init_timer(&dev->timer);
 	dev->timer.function = udc_watchdog;
@@ -2572,11 +2561,11 @@
 	dev->vbus = is_vbus_present();
 
 	/* irq setup after old hardware state is cleaned up */
-	retval = request_irq(IRQ_USB, pxa2xx_udc_irq,
+	retval = request_irq(irq, pxa2xx_udc_irq,
 			IRQF_DISABLED, driver_name, dev);
 	if (retval != 0) {
-		printk(KERN_ERR "%s: can't get irq %i, err %d\n",
-			driver_name, IRQ_USB, retval);
+		printk(KERN_ERR "%s: can't get irq %d, err %d\n",
+			driver_name, irq, retval);
 		return -EBUSY;
 	}
 	dev->got_irq = 1;
@@ -2591,7 +2580,7 @@
 			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 lubbock_fail0:
-			free_irq(IRQ_USB, dev);
+			free_irq(irq, dev);
 			return -EBUSY;
 		}
 		retval = request_irq(LUBBOCK_USB_IRQ,
@@ -2618,7 +2607,7 @@
 		if (retval != 0) {
 			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
 				driver_name, vbus_irq, retval);
-			free_irq(IRQ_USB, dev);
+			free_irq(irq, dev);
 			return -EBUSY;
 		}
 	}
@@ -2643,7 +2632,7 @@
 	remove_proc_files();
 
 	if (dev->got_irq) {
-		free_irq(IRQ_USB, dev);
+		free_irq(platform_get_irq(pdev, 0), dev);
 		dev->got_irq = 0;
 	}
 #ifdef CONFIG_ARCH_LUBBOCK
@@ -2670,7 +2659,7 @@
  *
  * For now, we punt and forcibly disconnect from the USB host when PXA
  * enters any suspend state.  While we're disconnected, we always disable
- * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states. 
+ * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
  * Boards without software pullup control shouldn't use those states.
  * VBUS IRQs should probably be ignored so that the PXA device just acts
  * "dead" to USB hosts until system resume.
@@ -2703,7 +2692,6 @@
 /*-------------------------------------------------------------------------*/
 
 static struct platform_driver udc_driver = {
-	.probe		= pxa2xx_udc_probe,
 	.shutdown	= pxa2xx_udc_shutdown,
 	.remove		= __exit_p(pxa2xx_udc_remove),
 	.suspend	= pxa2xx_udc_suspend,
@@ -2717,7 +2705,7 @@
 static int __init udc_init(void)
 {
 	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
-	return platform_driver_register(&udc_driver);
+	return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
 }
 module_init(udc_init);
 
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 8e598c8..773e549 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -177,21 +177,6 @@
 
 static struct pxa2xx_udc *the_controller;
 
-static inline int pxa_gpio_get(unsigned gpio)
-{
-	return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void pxa_gpio_set(unsigned gpio, int is_on)
-{
-	int mask = GPIO_bit(gpio);
-
-	if (is_on)
-		GPSR(gpio) = mask;
-	else
-		GPCR(gpio) = mask;
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 4c3c725..397b149 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -195,7 +195,7 @@
 	__le32	PerPacketInfoLength;
 	__le32	VcHandle;
 	__le32	Reserved;
-};
+} __attribute__ ((packed));
 
 struct rndis_config_parameter
 {
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index e6c19aa..e552668 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1699,6 +1699,7 @@
 			memcpy(&port->port_line_coding, req->buf, ret);
 			spin_unlock(&port->port_lock);
 		}
+		ret = 0;
 		break;
 
 	case USB_CDC_REQ_GET_LINE_CODING:
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index a2e58c8..2ff396b 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -15,4 +15,3 @@
 obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o
 obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o
-obj-$(CONFIG_ETRAX_ARCH_V10)	+= hc_crisv10.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 246afea..43eddae 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -322,7 +322,7 @@
 
 #else
 
-/* troubleshooting help: expose state in driverfs */
+/* troubleshooting help: expose state in sysfs */
 
 #define speed_char(info1) ({ char tmp; \
 		switch (info1 & (3 << 12)) { \
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index caac0d1..f28736a 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -31,7 +31,7 @@
 #define FSL_SOC_USB_SNOOP1	0x400	/* NOTE: big-endian */
 #define FSL_SOC_USB_SNOOP2	0x404	/* NOTE: big-endian */
 #define FSL_SOC_USB_AGECNTTHRSH	0x408	/* NOTE: big-endian */
-#define FSL_SOC_USB_SICTRL	0x40c	/* NOTE: big-endian */
-#define FSL_SOC_USB_PRICTRL	0x410	/* NOTE: big-endian */
+#define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */
+#define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
 #endif				/* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 185721d..c7458f7 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -42,6 +42,9 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
 
 
 /*-------------------------------------------------------------------------*/
@@ -299,6 +302,19 @@
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
+/* On some systems, leaving remote wakeup enabled prevents system shutdown.
+ * The firmware seems to think that powering off is a wakeup event!
+ * This routine turns off remote wakeup and everything else, on all ports.
+ */
+static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+{
+	int	port = HCS_N_PORTS(ehci->hcs_params);
+
+	while (port--)
+		ehci_writel(ehci, PORT_RWC_BITS,
+				&ehci->regs->port_status[port]);
+}
+
 /* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
  * This forcibly disables dma and IRQs, helping kexec and other cases
  * where the next system software may expect clean state.
@@ -310,9 +326,13 @@
 
 	ehci = hcd_to_ehci (hcd);
 	(void) ehci_halt (ehci);
+	ehci_turn_off_all_ports(ehci);
 
 	/* make BIOS/etc use companion controller during reboot */
 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+
+	/* unblock posted writes */
+	ehci_readl(ehci, &ehci->regs->configured_flag);
 }
 
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -649,6 +669,7 @@
 			 */
 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
 		}
 	}
 
@@ -951,15 +972,18 @@
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-	if (retval < 0) {
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+		retval = ps3_system_bus_driver_register(
+				&PS3_SYSTEM_BUS_DRIVER);
+		if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-		platform_driver_unregister(&PLATFORM_DRIVER);
+			platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-		pci_unregister_driver(&PCI_DRIVER);
+			pci_unregister_driver(&PCI_DRIVER);
 #endif
-		return retval;
+			return retval;
+		}
 	}
 #endif
 
@@ -976,7 +1000,8 @@
 	pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 0d83c6d..f4d301b 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -36,6 +36,8 @@
 	int			port;
 	int			mask;
 
+	ehci_dbg(ehci, "suspend root hub\n");
+
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
 
@@ -134,6 +136,10 @@
 	/* restore CMD_RUN, framelist size, and irq threshold */
 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
 
+	/* Some controller/firmware combinations need a delay during which
+	 * they set up the port statuses.  See Bugzilla #8190. */
+	mdelay(8);
+
 	/* manually resume the ports we suspended during bus_suspend() */
 	i = HCS_N_PORTS (ehci->hcs_params);
 	while (i--) {
@@ -651,8 +657,7 @@
 	if (status & ~0xffff)	/* only if wPortChange is interesting */
 #endif
 		dbg_port (ehci, "GetStatus", wIndex + 1, temp);
-		// we "know" this alignment is good, caller used kmalloc()...
-		*((__le32 *) buf) = cpu_to_le32 (status);
+		put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
 		break;
 	case SetHubFeature:
 		switch (wValue) {
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
deleted file mode 100644
index 32f7caf..0000000
--- a/drivers/usb/host/hc_crisv10.c
+++ /dev/null
@@ -1,4550 +0,0 @@
-/*
- * usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD)
- *
- * Copyright (c) 2002, 2003 Axis Communications AB.
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/arch/svinto.h>
-
-#include <linux/usb.h>
-/* Ugly include because we don't live with the other host drivers. */
-#include <../drivers/usb/core/hcd.h>
-#include <../drivers/usb/core/usb.h>
-
-#include "hc_crisv10.h"
-
-#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR
-#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR
-#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR
-
-static const char *usb_hcd_version = "$Revision: 1.2 $";
-
-#undef KERN_DEBUG
-#define KERN_DEBUG ""
-
-
-#undef USB_DEBUG_RH
-#undef USB_DEBUG_EPID
-#undef USB_DEBUG_SB
-#undef USB_DEBUG_DESC
-#undef USB_DEBUG_URB
-#undef USB_DEBUG_TRACE
-#undef USB_DEBUG_BULK
-#undef USB_DEBUG_CTRL
-#undef USB_DEBUG_INTR
-#undef USB_DEBUG_ISOC
-
-#ifdef USB_DEBUG_RH
-#define dbg_rh(format, arg...) printk(KERN_DEBUG __FILE__ ": (RH) " format "\n" , ## arg)
-#else
-#define dbg_rh(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_EPID
-#define dbg_epid(format, arg...) printk(KERN_DEBUG __FILE__ ": (EPID) " format "\n" , ## arg)
-#else
-#define dbg_epid(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_SB
-#define dbg_sb(format, arg...) printk(KERN_DEBUG __FILE__ ": (SB) " format "\n" , ## arg)
-#else
-#define dbg_sb(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_CTRL
-#define dbg_ctrl(format, arg...) printk(KERN_DEBUG __FILE__ ": (CTRL) " format "\n" , ## arg)
-#else
-#define dbg_ctrl(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_BULK
-#define dbg_bulk(format, arg...) printk(KERN_DEBUG __FILE__ ": (BULK) " format "\n" , ## arg)
-#else
-#define dbg_bulk(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_INTR
-#define dbg_intr(format, arg...) printk(KERN_DEBUG __FILE__ ": (INTR) " format "\n" , ## arg)
-#else
-#define dbg_intr(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_ISOC
-#define dbg_isoc(format, arg...) printk(KERN_DEBUG __FILE__ ": (ISOC) " format "\n" , ## arg)
-#else
-#define dbg_isoc(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_TRACE
-#define DBFENTER (printk(": Entering: %s\n", __FUNCTION__))
-#define DBFEXIT  (printk(": Exiting:  %s\n", __FUNCTION__))
-#else
-#define DBFENTER do {} while (0)
-#define DBFEXIT  do {} while (0)
-#endif
-
-#define usb_pipeslow(pipe)	(((pipe) >> 26) & 1)
-
-/*-------------------------------------------------------------------
- Virtual Root Hub
- -------------------------------------------------------------------*/
-
-static __u8 root_hub_dev_des[] =
-{
-	0x12,  /*  __u8  bLength; */
-	0x01,  /*  __u8  bDescriptorType; Device */
-	0x00,  /*  __le16 bcdUSB; v1.0 */
-	0x01,
-	0x09,  /*  __u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,  /*  __u8  bDeviceSubClass; */
-	0x00,  /*  __u8  bDeviceProtocol; */
-	0x08,  /*  __u8  bMaxPacketSize0; 8 Bytes */
-	0x00,  /*  __le16 idVendor; */
-	0x00,
-	0x00,  /*  __le16 idProduct; */
-	0x00,
-	0x00,  /*  __le16 bcdDevice; */
-	0x00,
-	0x00,  /*  __u8  iManufacturer; */
-	0x02,  /*  __u8  iProduct; */
-	0x01,  /*  __u8  iSerialNumber; */
-	0x01   /*  __u8  bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
-	0x09,  /*  __u8  bLength; */
-	0x02,  /*  __u8  bDescriptorType; Configuration */
-	0x19,  /*  __le16 wTotalLength; */
-	0x00,
-	0x01,  /*  __u8  bNumInterfaces; */
-	0x01,  /*  __u8  bConfigurationValue; */
-	0x00,  /*  __u8  iConfiguration; */
-	0x40,  /*  __u8  bmAttributes; Bit 7: Bus-powered */
-	0x00,  /*  __u8  MaxPower; */
-
-     /* interface */
-	0x09,  /*  __u8  if_bLength; */
-	0x04,  /*  __u8  if_bDescriptorType; Interface */
-	0x00,  /*  __u8  if_bInterfaceNumber; */
-	0x00,  /*  __u8  if_bAlternateSetting; */
-	0x01,  /*  __u8  if_bNumEndpoints; */
-	0x09,  /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,  /*  __u8  if_bInterfaceSubClass; */
-	0x00,  /*  __u8  if_bInterfaceProtocol; */
-	0x00,  /*  __u8  if_iInterface; */
-
-     /* endpoint */
-	0x07,  /*  __u8  ep_bLength; */
-	0x05,  /*  __u8  ep_bDescriptorType; Endpoint */
-	0x81,  /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-	0x03,  /*  __u8  ep_bmAttributes; Interrupt */
-	0x08,  /*  __le16 ep_wMaxPacketSize; 8 Bytes */
-	0x00,
-	0xff   /*  __u8  ep_bInterval; 255 ms */
-};
-
-static __u8 root_hub_hub_des[] =
-{
-	0x09,  /*  __u8  bLength; */
-	0x29,  /*  __u8  bDescriptorType; Hub-descriptor */
-	0x02,  /*  __u8  bNbrPorts; */
-	0x00,  /* __u16  wHubCharacteristics; */
-	0x00,
-	0x01,  /*  __u8  bPwrOn2pwrGood; 2ms */
-	0x00,  /*  __u8  bHubContrCurrent; 0 mA */
-	0x00,  /*  __u8  DeviceRemovable; *** 7 Ports max *** */
-	0xff   /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0);
-static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
-
-/* We want the start timer to expire before the eot timer, because the former might start
-   traffic, thus making it unnecessary for the latter to time out. */
-#define BULK_START_TIMER_INTERVAL (HZ/10) /* 100 ms */
-#define BULK_EOT_TIMER_INTERVAL (HZ/10+2) /* 120 ms */
-
-#define OK(x) len = (x); dbg_rh("OK(%d): line: %d", x, __LINE__); break
-#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
-{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
-
-#define SLAB_FLAG     (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
-#define KMALLOC_FLAG  (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
-
-/* Most helpful debugging aid */
-#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
-
-/* Alternative assert define which stops after a failed assert. */
-/*
-#define assert(expr)                                      \
-{                                                         \
-        if (!(expr)) {                                    \
-                err("assert failed at line %d",__LINE__); \
-                while (1);                                \
-        }                                                 \
-}
-*/
-
-
-/* FIXME: Should RX_BUF_SIZE be a config option, or maybe we should adjust it dynamically?
-   To adjust it dynamically we would have to get an interrupt when we reach the end
-   of the rx descriptor list, or when we get close to the end, and then allocate more
-   descriptors. */
-
-#define NBR_OF_RX_DESC     512
-#define RX_DESC_BUF_SIZE   1024
-#define RX_BUF_SIZE        (NBR_OF_RX_DESC * RX_DESC_BUF_SIZE)
-
-/* The number of epids is, among other things, used for pre-allocating
-   ctrl, bulk and isoc EP descriptors (one for each epid).
-   Assumed to be > 1 when initiating the DMA lists. */
-#define NBR_OF_EPIDS       32
-
-/* Support interrupt traffic intervals up to 128 ms. */
-#define MAX_INTR_INTERVAL 128
-
-/* If periodic traffic (intr or isoc) is to be used, then one entry in the EP table
-   must be "invalid". By this we mean that we shouldn't care about epid attentions
-   for this epid, or at least handle them differently from epid attentions for "valid"
-   epids. This define determines which one to use (don't change it). */
-#define INVALID_EPID     31
-/* A special epid for the bulk dummys. */
-#define DUMMY_EPID       30
-
-/* This is just a software cache for the valid entries in R_USB_EPT_DATA. */
-static __u32 epid_usage_bitmask;
-
-/* A bitfield to keep information on in/out traffic is needed to uniquely identify
-   an endpoint on a device, since the most significant bit which indicates traffic
-   direction is lacking in the ep_id field (ETRAX epids can handle both in and
-   out traffic on endpoints that are otherwise identical). The USB framework, however,
-   relies on them to be handled separately.  For example, bulk IN and OUT urbs cannot
-   be queued in the same list, since they would block each other. */
-static __u32 epid_out_traffic;
-
-/* DMA IN cache bug. Align the DMA IN buffers to 32 bytes, i.e. a cache line.
-   Since RX_DESC_BUF_SIZE is 1024 is a multiple of 32, all rx buffers will be cache aligned. */
-static volatile unsigned char RxBuf[RX_BUF_SIZE] __attribute__ ((aligned (32)));
-static volatile USB_IN_Desc_t RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4)));
-
-/* Pointers into RxDescList. */
-static volatile USB_IN_Desc_t *myNextRxDesc;
-static volatile USB_IN_Desc_t *myLastRxDesc;
-static volatile USB_IN_Desc_t *myPrevRxDesc;
-
-/* EP descriptors must be 32-bit aligned. */
-static volatile USB_EP_Desc_t TxCtrlEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
-static volatile USB_EP_Desc_t TxBulkEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
-/* After each enabled bulk EP (IN or OUT) we put two disabled EP descriptors with the eol flag set,
-   causing the DMA to stop the DMA channel. The first of these two has the intr flag set, which
-   gives us a dma8_sub0_descr interrupt. When we receive this, we advance the DMA one step in the
-   EP list and then restart the bulk channel, thus forcing a switch between bulk EP descriptors
-   in each frame. */
-static volatile USB_EP_Desc_t TxBulkDummyEPList[NBR_OF_EPIDS][2] __attribute__ ((aligned (4)));
-
-static volatile USB_EP_Desc_t TxIsocEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
-static volatile USB_SB_Desc_t TxIsocSB_zout __attribute__ ((aligned (4)));
-
-static volatile USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));
-static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
-
-/* A zout transfer makes a memory access at the address of its buf pointer, which means that setting
-   this buf pointer to 0 will cause an access to the flash. In addition to this, setting sw_len to 0
-   results in a 16/32 bytes (depending on DMA burst size) transfer. Instead, we set it to 1, and point
-   it to this buffer. */
-static int zout_buffer[4] __attribute__ ((aligned (4)));
-
-/* Cache for allocating new EP and SB descriptors. */
-static struct kmem_cache *usb_desc_cache;
-
-/* Cache for the registers allocated in the top half. */
-static struct kmem_cache *top_half_reg_cache;
-
-/* Cache for the data allocated in the isoc descr top half. */
-static struct kmem_cache *isoc_compl_cache;
-
-static struct usb_bus *etrax_usb_bus;
-
-/* This is a circular (double-linked) list of the active urbs for each epid.
-   The head is never removed, and new urbs are linked onto the list as
-   urb_entry_t elements. Don't reference urb_list directly; use the wrapper
-   functions instead. Note that working with these lists might require spinlock
-   protection. */
-static struct list_head urb_list[NBR_OF_EPIDS];
-
-/* Read about the need and usage of this lock in submit_ctrl_urb. */
-static spinlock_t urb_list_lock;
-
-/* Used when unlinking asynchronously. */
-static struct list_head urb_unlink_list;
-
-/* for returning string descriptors in UTF-16LE */
-static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
-{
-	int retval;
-
-	for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
-		*utf++ = *ascii++ & 0x7f;
-		*utf++ = 0;
-	}
-	return retval;
-}
-
-static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
-{
-	char buf [30];
-
-	// assert (len > (2 * (sizeof (buf) + 1)));
-	// assert (strlen (type) <= 8);
-
-	// language ids
-	if (id == 0) {
-		*data++ = 4; *data++ = 3;	/* 4 bytes data */
-		*data++ = 0; *data++ = 0;	/* some language id */
-		return 4;
-
-	// serial number
-	} else if (id == 1) {
-		sprintf (buf, "%x", serial);
-
-	// product description
-	} else if (id == 2) {
-		sprintf (buf, "USB %s Root Hub", type);
-
-	// id 3 == vendor description
-
-	// unsupported IDs --> "stall"
-	} else
-	    return 0;
-
-	data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
-	data [1] = 3;
-	return data [0];
-}
-
-/* Wrappers around the list functions (include/linux/list.h). */
-
-static inline int urb_list_empty(int epid)
-{
-	return list_empty(&urb_list[epid]);
-}
-
-/* Returns first urb for this epid, or NULL if list is empty. */
-static inline struct urb *urb_list_first(int epid)
-{
-	struct urb *first_urb = 0;
-
-	if (!urb_list_empty(epid)) {
-		/* Get the first urb (i.e. head->next). */
-		urb_entry_t *urb_entry = list_entry((&urb_list[epid])->next, urb_entry_t, list);
-		first_urb = urb_entry->urb;
-	}
-	return first_urb;
-}
-
-/* Adds an urb_entry last in the list for this epid. */
-static inline void urb_list_add(struct urb *urb, int epid)
-{
-	urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
-	assert(urb_entry);
-
-	urb_entry->urb = urb;
-	list_add_tail(&urb_entry->list, &urb_list[epid]);
-}
-
-/* Search through the list for an element that contains this urb. (The list
-   is expected to be short and the one we are about to delete will often be
-   the first in the list.) */
-static inline urb_entry_t *__urb_list_entry(struct urb *urb, int epid)
-{
-	struct list_head *entry;
-	struct list_head *tmp;
-	urb_entry_t *urb_entry;
-
-	list_for_each_safe(entry, tmp, &urb_list[epid]) {
-		urb_entry = list_entry(entry, urb_entry_t, list);
-		assert(urb_entry);
-		assert(urb_entry->urb);
-
-		if (urb_entry->urb == urb) {
-			return urb_entry;
-		}
-	}
-	return 0;
-}
-
-/* Delete an urb from the list. */
-static inline void urb_list_del(struct urb *urb, int epid)
-{
-	urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
-	assert(urb_entry);
-
-	/* Delete entry and free. */
-	list_del(&urb_entry->list);
-	kfree(urb_entry);
-}
-
-/* Move an urb to the end of the list. */
-static inline void urb_list_move_last(struct urb *urb, int epid)
-{
-	urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
-	assert(urb_entry);
-
-	list_move_tail(&urb_entry->list, &urb_list[epid]);
-}
-
-/* Get the next urb in the list. */
-static inline struct urb *urb_list_next(struct urb *urb, int epid)
-{
-	urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
-
-	assert(urb_entry);
-
-	if (urb_entry->list.next != &urb_list[epid]) {
-		struct list_head *elem = urb_entry->list.next;
-		urb_entry = list_entry(elem, urb_entry_t, list);
-		return urb_entry->urb;
-	} else {
-		return NULL;
-	}
-}
-
-
-
-/* For debug purposes only. */
-static inline void urb_list_dump(int epid)
-{
-	struct list_head *entry;
-	struct list_head *tmp;
-	urb_entry_t *urb_entry;
-	int i = 0;
-
-	info("Dumping urb list for epid %d", epid);
-
-	list_for_each_safe(entry, tmp, &urb_list[epid]) {
-		urb_entry = list_entry(entry, urb_entry_t, list);
-		info("   entry %d, urb = 0x%lx", i, (unsigned long)urb_entry->urb);
-	}
-}
-
-static void init_rx_buffers(void);
-static int etrax_rh_unlink_urb(struct urb *urb);
-static void etrax_rh_send_irq(struct urb *urb);
-static void etrax_rh_init_int_timer(struct urb *urb);
-static void etrax_rh_int_timer_do(unsigned long ptr);
-
-static int etrax_usb_setup_epid(struct urb *urb);
-static int etrax_usb_lookup_epid(struct urb *urb);
-static int etrax_usb_allocate_epid(void);
-static void etrax_usb_free_epid(int epid);
-
-static int etrax_remove_from_sb_list(struct urb *urb);
-
-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);
-static void etrax_usb_add_to_ctrl_sb_list(struct urb *urb, int epid);
-static void etrax_usb_add_to_intr_sb_list(struct urb *urb, int epid);
-static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid);
-
-static int etrax_usb_submit_bulk_urb(struct urb *urb);
-static int etrax_usb_submit_ctrl_urb(struct urb *urb);
-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, 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);
-
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc);
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc);
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc);
-static void etrax_usb_hc_interrupt_bottom_half(void *data);
-
-static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data);
-
-
-/* The following is a list of interrupt handlers for the host controller interrupts we use.
-   They are called from etrax_usb_hc_interrupt_bottom_half. */
-static void etrax_usb_hc_isoc_eof_interrupt(void);
-static void etrax_usb_hc_bulk_eot_interrupt(int timer_induced);
-static void etrax_usb_hc_epid_attn_interrupt(usb_interrupt_registers_t *reg);
-static void etrax_usb_hc_port_status_interrupt(usb_interrupt_registers_t *reg);
-static void etrax_usb_hc_ctl_status_interrupt(usb_interrupt_registers_t *reg);
-
-static int etrax_rh_submit_urb (struct urb *urb);
-
-/* Forward declaration needed because they are used in the rx interrupt routine. */
-static void etrax_usb_complete_urb(struct urb *urb, int status);
-static void etrax_usb_complete_bulk_urb(struct urb *urb, int status);
-static void etrax_usb_complete_ctrl_urb(struct urb *urb, int status);
-static void etrax_usb_complete_intr_urb(struct urb *urb, int status);
-static void etrax_usb_complete_isoc_urb(struct urb *urb, int status);
-
-static int etrax_usb_hc_init(void);
-static void etrax_usb_hc_cleanup(void);
-
-static struct usb_operations etrax_usb_device_operations =
-{
-	.get_frame_number = etrax_usb_get_frame_number,
-	.submit_urb = etrax_usb_submit_urb,
-	.unlink_urb = etrax_usb_unlink_urb,
-        .buffer_alloc = etrax_usb_buffer_alloc,
-        .buffer_free = etrax_usb_buffer_free
-};
-
-/* Note that these functions are always available in their "__" variants, for use in
-   error situations. The "__" missing variants are controlled by the USB_DEBUG_DESC/
-   USB_DEBUG_URB macros. */
-static void __dump_urb(struct urb* purb)
-{
-	printk("\nurb                  :0x%08lx\n", (unsigned long)purb);
-	printk("dev                   :0x%08lx\n", (unsigned long)purb->dev);
-	printk("pipe                  :0x%08x\n", purb->pipe);
-	printk("status                :%d\n", purb->status);
-	printk("transfer_flags        :0x%08x\n", purb->transfer_flags);
-	printk("transfer_buffer       :0x%08lx\n", (unsigned long)purb->transfer_buffer);
-	printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
-	printk("actual_length         :%d\n", purb->actual_length);
-	printk("setup_packet          :0x%08lx\n", (unsigned long)purb->setup_packet);
-	printk("start_frame           :%d\n", purb->start_frame);
-	printk("number_of_packets     :%d\n", purb->number_of_packets);
-	printk("interval              :%d\n", purb->interval);
-	printk("error_count           :%d\n", purb->error_count);
-	printk("context               :0x%08lx\n", (unsigned long)purb->context);
-	printk("complete              :0x%08lx\n\n", (unsigned long)purb->complete);
-}
-
-static void __dump_in_desc(volatile USB_IN_Desc_t *in)
-{
-	printk("\nUSB_IN_Desc at 0x%08lx\n", (unsigned long)in);
-	printk("  sw_len  : 0x%04x (%d)\n", in->sw_len, in->sw_len);
-	printk("  command : 0x%04x\n", in->command);
-	printk("  next    : 0x%08lx\n", in->next);
-	printk("  buf     : 0x%08lx\n", in->buf);
-	printk("  hw_len  : 0x%04x (%d)\n", in->hw_len, in->hw_len);
-	printk("  status  : 0x%04x\n\n", in->status);
-}
-
-static void __dump_sb_desc(volatile USB_SB_Desc_t *sb)
-{
-	char tt = (sb->command & 0x30) >> 4;
-	char *tt_string;
-
-	switch (tt) {
-	case 0:
-		tt_string = "zout";
-		break;
-	case 1:
-		tt_string = "in";
-		break;
-	case 2:
-		tt_string = "out";
-		break;
-	case 3:
-		tt_string = "setup";
-		break;
-	default:
-		tt_string = "unknown (weird)";
-	}
-
-	printk("\n   USB_SB_Desc at 0x%08lx\n", (unsigned long)sb);
-	printk("     command : 0x%04x\n", sb->command);
-	printk("        rem     : %d\n", (sb->command & 0x3f00) >> 8);
-	printk("        full    : %d\n", (sb->command & 0x40) >> 6);
-	printk("        tt      : %d (%s)\n", tt, tt_string);
-	printk("        intr    : %d\n", (sb->command & 0x8) >> 3);
-	printk("        eot     : %d\n", (sb->command & 0x2) >> 1);
-	printk("        eol     : %d\n", sb->command & 0x1);
-	printk("     sw_len  : 0x%04x (%d)\n", sb->sw_len, sb->sw_len);
-	printk("     next    : 0x%08lx\n", sb->next);
-	printk("     buf     : 0x%08lx\n\n", sb->buf);
-}
-
-
-static void __dump_ep_desc(volatile USB_EP_Desc_t *ep)
-{
-	printk("\nUSB_EP_Desc at 0x%08lx\n", (unsigned long)ep);
-	printk("  command : 0x%04x\n", ep->command);
-	printk("     ep_id   : %d\n", (ep->command & 0x1f00) >> 8);
-	printk("     enable  : %d\n", (ep->command & 0x10) >> 4);
-	printk("     intr    : %d\n", (ep->command & 0x8) >> 3);
-	printk("     eof     : %d\n", (ep->command & 0x2) >> 1);
-	printk("     eol     : %d\n", ep->command & 0x1);
-	printk("  hw_len  : 0x%04x (%d)\n", ep->hw_len, ep->hw_len);
-	printk("  next    : 0x%08lx\n", ep->next);
-	printk("  sub     : 0x%08lx\n\n", ep->sub);
-}
-
-static inline void __dump_ep_list(int pipe_type)
-{
-	volatile USB_EP_Desc_t *ep;
-	volatile USB_EP_Desc_t *first_ep;
-	volatile USB_SB_Desc_t *sb;
-
-	switch (pipe_type)
-	{
-	case PIPE_BULK:
-		first_ep = &TxBulkEPList[0];
-		break;
-	case PIPE_CONTROL:
-		first_ep = &TxCtrlEPList[0];
-		break;
-	case PIPE_INTERRUPT:
-		first_ep = &TxIntrEPList[0];
-		break;
-	case PIPE_ISOCHRONOUS:
-		first_ep = &TxIsocEPList[0];
-		break;
-	default:
-		warn("Cannot dump unknown traffic type");
-		return;
-	}
-	ep = first_ep;
-
-	printk("\n\nDumping EP list...\n\n");
-
-	do {
-		__dump_ep_desc(ep);
-		/* Cannot phys_to_virt on 0 as it turns into 80000000, which is != 0. */
-		sb = ep->sub ? phys_to_virt(ep->sub) : 0;
-		while (sb) {
-			__dump_sb_desc(sb);
-			sb = sb->next ? phys_to_virt(sb->next) : 0;
-		}
-		ep = (volatile USB_EP_Desc_t *)(phys_to_virt(ep->next));
-
-	} while (ep != first_ep);
-}
-
-static inline void __dump_ept_data(int epid)
-{
-	unsigned long flags;
-	__u32 r_usb_ept_data;
-
-	if (epid < 0 || epid > 31) {
-		printk("Cannot dump ept data for invalid epid %d\n", epid);
-		return;
-	}
-
-	save_flags(flags);
-	cli();
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-	r_usb_ept_data = *R_USB_EPT_DATA;
-	restore_flags(flags);
-
-	printk("\nR_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid);
-	if (r_usb_ept_data == 0) {
-		/* No need for more detailed printing. */
-		return;
-	}
-	printk("  valid           : %d\n", (r_usb_ept_data & 0x80000000) >> 31);
-	printk("  hold            : %d\n", (r_usb_ept_data & 0x40000000) >> 30);
-	printk("  error_count_in  : %d\n", (r_usb_ept_data & 0x30000000) >> 28);
-	printk("  t_in            : %d\n", (r_usb_ept_data & 0x08000000) >> 27);
-	printk("  low_speed       : %d\n", (r_usb_ept_data & 0x04000000) >> 26);
-	printk("  port            : %d\n", (r_usb_ept_data & 0x03000000) >> 24);
-	printk("  error_code      : %d\n", (r_usb_ept_data & 0x00c00000) >> 22);
-	printk("  t_out           : %d\n", (r_usb_ept_data & 0x00200000) >> 21);
-	printk("  error_count_out : %d\n", (r_usb_ept_data & 0x00180000) >> 19);
-	printk("  max_len         : %d\n", (r_usb_ept_data & 0x0003f800) >> 11);
-	printk("  ep              : %d\n", (r_usb_ept_data & 0x00000780) >> 7);
-	printk("  dev             : %d\n", (r_usb_ept_data & 0x0000003f));
-}
-
-static inline void __dump_ept_data_list(void)
-{
-	int i;
-
-	printk("Dumping the whole R_USB_EPT_DATA list\n");
-
-	for (i = 0; i < 32; i++) {
-		__dump_ept_data(i);
-	}
-}
-#ifdef USB_DEBUG_DESC
-#define dump_in_desc(...) __dump_in_desc(...)
-#define dump_sb_desc(...) __dump_sb_desc(...)
-#define dump_ep_desc(...) __dump_ep_desc(...)
-#else
-#define dump_in_desc(...) do {} while (0)
-#define dump_sb_desc(...) do {} while (0)
-#define dump_ep_desc(...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_URB
-#define dump_urb(x)     __dump_urb(x)
-#else
-#define dump_urb(x)     do {} while (0)
-#endif
-
-static void init_rx_buffers(void)
-{
-	int i;
-
-	DBFENTER;
-
-	for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
-		RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
-		RxDescList[i].command = 0;
-		RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);
-		RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
-		RxDescList[i].hw_len = 0;
-		RxDescList[i].status = 0;
-
-		/* DMA IN cache bug. (struct etrax_dma_descr has the same layout as USB_IN_Desc
-		   for the relevant fields.) */
-		prepare_rx_descriptor((struct etrax_dma_descr*)&RxDescList[i]);
-
-	}
-
-	RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
-	RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes);
-	RxDescList[i].next = virt_to_phys(&RxDescList[0]);
-	RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
-	RxDescList[i].hw_len = 0;
-	RxDescList[i].status = 0;
-
-	myNextRxDesc = &RxDescList[0];
-	myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
-	myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
-
-	*R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc);
-	*R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start);
-
-	DBFEXIT;
-}
-
-static void init_tx_bulk_ep(void)
-{
-	int i;
-
-	DBFENTER;
-
-	for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {
-		CHECK_ALIGN(&TxBulkEPList[i]);
-		TxBulkEPList[i].hw_len = 0;
-		TxBulkEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
-		TxBulkEPList[i].sub = 0;
-		TxBulkEPList[i].next = virt_to_phys(&TxBulkEPList[i + 1]);
-
-		/* Initiate two EPs, disabled and with the eol flag set. No need for any
-		   preserved epid. */
-
-		/* The first one has the intr flag set so we get an interrupt when the DMA
-		   channel is about to become disabled. */
-		CHECK_ALIGN(&TxBulkDummyEPList[i][0]);
-		TxBulkDummyEPList[i][0].hw_len = 0;
-		TxBulkDummyEPList[i][0].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) |
-						   IO_STATE(USB_EP_command, eol, yes) |
-						   IO_STATE(USB_EP_command, intr, yes));
-		TxBulkDummyEPList[i][0].sub = 0;
-		TxBulkDummyEPList[i][0].next = virt_to_phys(&TxBulkDummyEPList[i][1]);
-
-		/* The second one. */
-		CHECK_ALIGN(&TxBulkDummyEPList[i][1]);
-		TxBulkDummyEPList[i][1].hw_len = 0;
-		TxBulkDummyEPList[i][1].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) |
-						   IO_STATE(USB_EP_command, eol, yes));
-		TxBulkDummyEPList[i][1].sub = 0;
-		/* The last dummy's next pointer is the same as the current EP's next pointer. */
-		TxBulkDummyEPList[i][1].next = virt_to_phys(&TxBulkEPList[i + 1]);
-	}
-
-	/* Configure the last one. */
-	CHECK_ALIGN(&TxBulkEPList[i]);
-	TxBulkEPList[i].hw_len = 0;
-	TxBulkEPList[i].command = (IO_STATE(USB_EP_command, eol, yes) |
-				   IO_FIELD(USB_EP_command, epid, i));
-	TxBulkEPList[i].sub = 0;
-	TxBulkEPList[i].next = virt_to_phys(&TxBulkEPList[0]);
-
-	/* No need configuring dummy EPs for the last one as it will never be used for
-	   bulk traffic (i == INVALD_EPID at this point). */
-
-	/* Set up to start on the last EP so we will enable it when inserting traffic
-	   for the first time (imitating the situation where the DMA has stopped
-	   because there was no more traffic). */
-	*R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[i]);
-	/* No point in starting the bulk channel yet.
-	 *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */
-	DBFEXIT;
-}
-
-static void init_tx_ctrl_ep(void)
-{
-	int i;
-
-	DBFENTER;
-
-	for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {
-		CHECK_ALIGN(&TxCtrlEPList[i]);
-		TxCtrlEPList[i].hw_len = 0;
-		TxCtrlEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
-		TxCtrlEPList[i].sub = 0;
-		TxCtrlEPList[i].next = virt_to_phys(&TxCtrlEPList[i + 1]);
-	}
-
-	CHECK_ALIGN(&TxCtrlEPList[i]);
-	TxCtrlEPList[i].hw_len = 0;
-	TxCtrlEPList[i].command = (IO_STATE(USB_EP_command, eol, yes) |
-				   IO_FIELD(USB_EP_command, epid, i));
-
-	TxCtrlEPList[i].sub = 0;
-	TxCtrlEPList[i].next = virt_to_phys(&TxCtrlEPList[0]);
-
-	*R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[0]);
-	*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
-
-	DBFEXIT;
-}
-
-
-static void init_tx_intr_ep(void)
-{
-	int i;
-
-	DBFENTER;
-
-	/* Read comment at zout_buffer declaration for an explanation to this. */
-	TxIntrSB_zout.sw_len = 1;
-	TxIntrSB_zout.next = 0;
-	TxIntrSB_zout.buf = virt_to_phys(&zout_buffer[0]);
-	TxIntrSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) |
-				 IO_STATE(USB_SB_command, tt, zout) |
-				 IO_STATE(USB_SB_command, full, yes) |
-				 IO_STATE(USB_SB_command, eot, yes) |
-				 IO_STATE(USB_SB_command, eol, yes));
-
-	for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) {
-		CHECK_ALIGN(&TxIntrEPList[i]);
-		TxIntrEPList[i].hw_len = 0;
-		TxIntrEPList[i].command =
-			(IO_STATE(USB_EP_command, eof, yes) |
-			 IO_STATE(USB_EP_command, enable, yes) |
-			 IO_FIELD(USB_EP_command, epid, INVALID_EPID));
-		TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
-		TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[i + 1]);
-	}
-
-	CHECK_ALIGN(&TxIntrEPList[i]);
-	TxIntrEPList[i].hw_len = 0;
-	TxIntrEPList[i].command =
-		(IO_STATE(USB_EP_command, eof, yes) |
-		 IO_STATE(USB_EP_command, eol, yes) |
-		 IO_STATE(USB_EP_command, enable, yes) |
-		 IO_FIELD(USB_EP_command, epid, INVALID_EPID));
-	TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
-	TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[0]);
-
-	*R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);
-	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
-	DBFEXIT;
-}
-
-static void init_tx_isoc_ep(void)
-{
-	int i;
-
-	DBFENTER;
-
-	/* Read comment at zout_buffer declaration for an explanation to this. */
-	TxIsocSB_zout.sw_len = 1;
-	TxIsocSB_zout.next = 0;
-	TxIsocSB_zout.buf = virt_to_phys(&zout_buffer[0]);
-	TxIsocSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) |
-				 IO_STATE(USB_SB_command, tt, zout) |
-				 IO_STATE(USB_SB_command, full, yes) |
-				 IO_STATE(USB_SB_command, eot, yes) |
-				 IO_STATE(USB_SB_command, eol, yes));
-
-	/* The last isochronous EP descriptor is a dummy. */
-
-	for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {
-		CHECK_ALIGN(&TxIsocEPList[i]);
-		TxIsocEPList[i].hw_len = 0;
-		TxIsocEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
-		TxIsocEPList[i].sub = 0;
-		TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[i + 1]);
-	}
-
-	CHECK_ALIGN(&TxIsocEPList[i]);
-	TxIsocEPList[i].hw_len = 0;
-
-	/* Must enable the last EP descr to get eof interrupt. */
-	TxIsocEPList[i].command = (IO_STATE(USB_EP_command, enable, yes) |
-				   IO_STATE(USB_EP_command, eof, yes) |
-				   IO_STATE(USB_EP_command, eol, yes) |
-				   IO_FIELD(USB_EP_command, epid, INVALID_EPID));
-	TxIsocEPList[i].sub = virt_to_phys(&TxIsocSB_zout);
-	TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[0]);
-
-	*R_DMA_CH8_SUB3_EP = virt_to_phys(&TxIsocEPList[0]);
-	*R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);
-
-	DBFEXIT;
-}
-
-static void etrax_usb_unlink_intr_urb(struct urb *urb)
-{
-	volatile USB_EP_Desc_t *first_ep;  /* First EP in the list. */
-	volatile USB_EP_Desc_t *curr_ep;   /* Current EP, the iterator. */
-	volatile USB_EP_Desc_t *next_ep;   /* The EP after current. */
-	volatile USB_EP_Desc_t *unlink_ep; /* The one we should remove from the list. */
-
-	int epid;
-
-	/* Read 8.8.4 in Designer's Reference, "Removing an EP Descriptor from the List". */
-
-	DBFENTER;
-
-	epid = ((etrax_urb_priv_t *)urb->hcpriv)->epid;
-
-	first_ep = &TxIntrEPList[0];
-	curr_ep = first_ep;
-
-
-	/* Note that this loop removes all EP descriptors with this epid. This assumes
-	   that all EP descriptors belong to the one and only urb for this epid. */
-
-	do {
-		next_ep = (USB_EP_Desc_t *)phys_to_virt(curr_ep->next);
-
-		if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) {
-
-			dbg_intr("Found EP to unlink for epid %d", epid);
-
-			/* This is the one we should unlink. */
-			unlink_ep = next_ep;
-
-			/* Actually unlink the EP from the DMA list. */
-			curr_ep->next = unlink_ep->next;
-
-			/* Wait until the DMA is no longer at this descriptor. */
-			while (*R_DMA_CH8_SUB2_EP == virt_to_phys(unlink_ep));
-
-			/* Now we are free to remove it and its SB descriptor.
-			   Note that it is assumed here that there is only one sb in the
-			   sb list for this ep. */
-			kmem_cache_free(usb_desc_cache, phys_to_virt(unlink_ep->sub));
-			kmem_cache_free(usb_desc_cache, (USB_EP_Desc_t *)unlink_ep);
-		}
-
-		curr_ep = phys_to_virt(curr_ep->next);
-
-	} while (curr_ep != first_ep);
-        urb->hcpriv = NULL;
-}
-
-void etrax_usb_do_intr_recover(int epid)
-{
-	USB_EP_Desc_t *first_ep, *tmp_ep;
-
-	DBFENTER;
-
-	first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);
-	tmp_ep = first_ep;
-
-	/* What this does is simply to walk the list of interrupt
-	   ep descriptors and enable those that are disabled. */
-
-	do {
-		if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid &&
-		    !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) {
-			tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes);
-		}
-
-		tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next);
-
-	} while (tmp_ep != first_ep);
-
-
-	DBFEXIT;
-}
-
-static int etrax_rh_unlink_urb (struct urb *urb)
-{
-	etrax_hc_t *hc;
-
-	DBFENTER;
-
-	hc = urb->dev->bus->hcpriv;
-
-	if (hc->rh.urb == urb) {
-		hc->rh.send = 0;
-		del_timer(&hc->rh.rh_int_timer);
-	}
-
-	DBFEXIT;
-	return 0;
-}
-
-static void etrax_rh_send_irq(struct urb *urb)
-{
-	__u16 data = 0;
-	etrax_hc_t *hc = urb->dev->bus->hcpriv;
-	DBFENTER;
-
-/*
-  dbg_rh("R_USB_FM_NUMBER   : 0x%08X", *R_USB_FM_NUMBER);
-  dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING);
-*/
-
-	data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0;
-	data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0;
-
-	*((__u16 *)urb->transfer_buffer) = cpu_to_le16(data);
-	/* FIXME: Why is actual_length set to 1 when data is 2 bytes?
-	   Since only 1 byte is used, why not declare data as __u8? */
-	urb->actual_length = 1;
-	urb->status = 0;
-
-	if (hc->rh.send && urb->complete) {
-		dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1);
-		dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2);
-
-		urb->complete(urb, NULL);
-	}
-
-	DBFEXIT;
-}
-
-static void etrax_rh_init_int_timer(struct urb *urb)
-{
-	etrax_hc_t *hc;
-
-	DBFENTER;
-
-	hc = urb->dev->bus->hcpriv;
-	hc->rh.interval = urb->interval;
-	init_timer(&hc->rh.rh_int_timer);
-	hc->rh.rh_int_timer.function = etrax_rh_int_timer_do;
-	hc->rh.rh_int_timer.data = (unsigned long)urb;
-	/* FIXME: Is the jiffies resolution enough? All intervals < 10 ms will be mapped
-	   to 0, and the rest to the nearest lower 10 ms. */
-	hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000);
-	add_timer(&hc->rh.rh_int_timer);
-
-	DBFEXIT;
-}
-
-static void etrax_rh_int_timer_do(unsigned long ptr)
-{
-	struct urb *urb;
-	etrax_hc_t *hc;
-
-	DBFENTER;
-
-	urb = (struct urb*)ptr;
-	hc = urb->dev->bus->hcpriv;
-
-	if (hc->rh.send) {
-		etrax_rh_send_irq(urb);
-	}
-
-	DBFEXIT;
-}
-
-static int etrax_usb_setup_epid(struct urb *urb)
-{
-	int epid;
-	char devnum, endpoint, out_traffic, slow;
-	int maxlen;
-	unsigned long flags;
-
-	DBFENTER;
-
-	epid = etrax_usb_lookup_epid(urb);
-	if ((epid != -1)){
-		/* An epid that fits this urb has been found. */
-		DBFEXIT;
-		return epid;
-	}
-
-	/* We must find and initiate a new epid for this urb. */
-	epid = etrax_usb_allocate_epid();
-
-	if (epid == -1) {
-		/* Failed to allocate a new epid. */
-		DBFEXIT;
-		return epid;
-	}
-
-	/* We now have a new epid to use. Initiate it. */
-	set_bit(epid, (void *)&epid_usage_bitmask);
-
-	devnum = usb_pipedevice(urb->pipe);
-	endpoint = usb_pipeendpoint(urb->pipe);
-	slow = usb_pipeslow(urb->pipe);
-	maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-		/* We want both IN and OUT control traffic to be put on the same EP/SB list. */
-		out_traffic = 1;
-	} else {
-		out_traffic = usb_pipeout(urb->pipe);
-	}
-
-	save_flags(flags);
-	cli();
-
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-
-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-		*R_USB_EPT_DATA_ISO = IO_STATE(R_USB_EPT_DATA_ISO, valid, yes) |
-			/* FIXME: Change any to the actual port? */
-			IO_STATE(R_USB_EPT_DATA_ISO, port, any) |
-			IO_FIELD(R_USB_EPT_DATA_ISO, max_len, maxlen) |
-			IO_FIELD(R_USB_EPT_DATA_ISO, ep, endpoint) |
-			IO_FIELD(R_USB_EPT_DATA_ISO, dev, devnum);
-	} else {
-		*R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) |
-			IO_FIELD(R_USB_EPT_DATA, low_speed, slow) |
-			/* FIXME: Change any to the actual port? */
-			IO_STATE(R_USB_EPT_DATA, port, any) |
-			IO_FIELD(R_USB_EPT_DATA, max_len, maxlen) |
-			IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |
-			IO_FIELD(R_USB_EPT_DATA, dev, devnum);
-	}
-
-	restore_flags(flags);
-
-	if (out_traffic) {
-		set_bit(epid, (void *)&epid_out_traffic);
-	} else {
-		clear_bit(epid, (void *)&epid_out_traffic);
-	}
-
-	dbg_epid("Setting up epid %d with devnum %d, endpoint %d and max_len %d (%s)",
-		 epid, devnum, endpoint, maxlen, out_traffic ? "OUT" : "IN");
-
-	DBFEXIT;
-	return epid;
-}
-
-static void etrax_usb_free_epid(int epid)
-{
-	unsigned long flags;
-
-	DBFENTER;
-
-	if (!test_bit(epid, (void *)&epid_usage_bitmask)) {
-		warn("Trying to free unused epid %d", epid);
-		DBFEXIT;
-		return;
-	}
-
-	save_flags(flags);
-	cli();
-
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-	while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold));
-	/* This will, among other things, set the valid field to 0. */
-	*R_USB_EPT_DATA = 0;
-	restore_flags(flags);
-
-	clear_bit(epid, (void *)&epid_usage_bitmask);
-
-
-	dbg_epid("Freed epid %d", epid);
-
-	DBFEXIT;
-}
-
-static int etrax_usb_lookup_epid(struct urb *urb)
-{
-	int i;
-	__u32 data;
-	char devnum, endpoint, slow, out_traffic;
-	int maxlen;
-	unsigned long flags;
-
-	DBFENTER;
-
-	devnum = usb_pipedevice(urb->pipe);
-	endpoint = usb_pipeendpoint(urb->pipe);
-	slow = usb_pipeslow(urb->pipe);
-	maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-		/* We want both IN and OUT control traffic to be put on the same EP/SB list. */
-		out_traffic = 1;
-	} else {
-		out_traffic = usb_pipeout(urb->pipe);
-	}
-
-	/* Step through att epids. */
-	for (i = 0; i < NBR_OF_EPIDS; i++) {
-		if (test_bit(i, (void *)&epid_usage_bitmask) &&
-		    test_bit(i, (void *)&epid_out_traffic) == out_traffic) {
-
-			save_flags(flags);
-			cli();
-			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i);
-			nop();
-
-			if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-				data = *R_USB_EPT_DATA_ISO;
-				restore_flags(flags);
-
-				if ((IO_MASK(R_USB_EPT_DATA_ISO, valid) & data) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA_ISO, dev, data) == devnum) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA_ISO, ep, data) == endpoint) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len, data) == maxlen)) {
-					dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)",
-						 i, devnum, endpoint, out_traffic ? "OUT" : "IN");
-					DBFEXIT;
-					return i;
-				}
-			} else {
-				data = *R_USB_EPT_DATA;
-				restore_flags(flags);
-
-				if ((IO_MASK(R_USB_EPT_DATA, valid) & data) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxlen)) {
-					dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)",
-						 i, devnum, endpoint, out_traffic ? "OUT" : "IN");
-					DBFEXIT;
-					return i;
-				}
-			}
-		}
-	}
-
-	DBFEXIT;
-	return -1;
-}
-
-static int etrax_usb_allocate_epid(void)
-{
-	int i;
-
-	DBFENTER;
-
-	for (i = 0; i < NBR_OF_EPIDS; i++) {
-		if (!test_bit(i, (void *)&epid_usage_bitmask)) {
-			dbg_epid("Found free epid %d", i);
-			DBFEXIT;
-			return i;
-		}
-	}
-
-	dbg_epid("Found no free epids");
-	DBFEXIT;
-	return -1;
-}
-
-static int etrax_usb_submit_urb(struct urb *urb, unsigned mem_flags)
-{
-	etrax_hc_t *hc;
-	int ret = -EINVAL;
-
-	DBFENTER;
-
-	if (!urb->dev || !urb->dev->bus) {
-		return -ENODEV;
-	}
-	if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) <= 0) {
-		info("Submit urb to pipe with maxpacketlen 0, pipe 0x%X\n", urb->pipe);
-		return -EMSGSIZE;
-	}
-
-	if (urb->timeout) {
-		/* FIXME. */
-		warn("urb->timeout specified, ignoring.");
-	}
-
-	hc = (etrax_hc_t*)urb->dev->bus->hcpriv;
-
-	if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
-		/* This request is for the Virtual Root Hub. */
-		ret = etrax_rh_submit_urb(urb);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-
-		ret = etrax_usb_submit_bulk_urb(urb);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-
-		ret = etrax_usb_submit_ctrl_urb(urb);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
-		int bustime;
-
-		if (urb->bandwidth == 0) {
-			bustime = usb_check_bandwidth(urb->dev, urb);
-			if (bustime < 0) {
-				ret = bustime;
-			} else {
-				ret = etrax_usb_submit_intr_urb(urb);
-				if (ret == 0)
-					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
-			}
-		} else {
-			/* Bandwidth already set. */
-			ret = etrax_usb_submit_intr_urb(urb);
-		}
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-		int bustime;
-
-		if (urb->bandwidth == 0) {
-			bustime = usb_check_bandwidth(urb->dev, urb);
-			if (bustime < 0) {
-				ret = bustime;
-			} else {
-				ret = etrax_usb_submit_isoc_urb(urb);
-				if (ret == 0)
-					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
-			}
-		} else {
-			/* Bandwidth already set. */
-			ret = etrax_usb_submit_isoc_urb(urb);
-		}
-	}
-
-	DBFEXIT;
-
-        if (ret != 0)
-          printk("Submit URB error %d\n", ret);
-
-	return ret;
-}
-
-static int etrax_usb_unlink_urb(struct urb *urb, int status)
-{
-	etrax_hc_t *hc;
-	etrax_urb_priv_t *urb_priv;
-	int epid;
-	unsigned int flags;
-
-	DBFENTER;
-
-	if (!urb) {
-		return -EINVAL;
-	}
-
-	/* Disable interrupts here since a descriptor interrupt for the isoc epid
-	   will modify the sb list.  This could possibly be done more granular, but
-	   unlink_urb should not be used frequently anyway.
-	*/
-
-	save_flags(flags);
-	cli();
-
-	if (!urb->dev || !urb->dev->bus) {
-		restore_flags(flags);
-		return -ENODEV;
-	}
-	if (!urb->hcpriv) {
-		/* This happens if a device driver calls unlink on an urb that
-		   was never submitted (lazy driver) or if the urb was completed
-		   while unlink was being called. */
-		restore_flags(flags);
-		return 0;
-	}
-	if (urb->transfer_flags & URB_ASYNC_UNLINK) {
-		/* FIXME. */
-		/* If URB_ASYNC_UNLINK is set:
-		   unlink
-		   move to a separate urb list
-		   call complete at next sof with ECONNRESET
-
-		   If not:
-		   wait 1 ms
-		   unlink
-		   call complete with ENOENT
-		*/
-		warn("URB_ASYNC_UNLINK set, ignoring.");
-	}
-
-	/* One might think that urb->status = -EINPROGRESS would be a requirement for unlinking,
-	   but that doesn't work for interrupt and isochronous traffic since they are completed
-	   repeatedly, and urb->status is set then. That may in itself be a bug though. */
-
-	hc = urb->dev->bus->hcpriv;
-	urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	epid = urb_priv->epid;
-
-	/* Set the urb status (synchronous unlink). */
-	urb->status = -ENOENT;
-	urb_priv->urb_state = UNLINK;
-
-	if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
-		int ret;
-		ret = etrax_rh_unlink_urb(urb);
-		DBFEXIT;
-		restore_flags(flags);
-		return ret;
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-
-		dbg_bulk("Unlink of bulk urb (0x%lx)", (unsigned long)urb);
-
-		if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
-			/* The EP was enabled, disable it and wait. */
-			TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
-
-			/* Ah, the luxury of busy-wait. */
-			while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid]));
-		}
-		/* Kicking dummy list out of the party. */
-		TxBulkEPList[epid].next = virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-
-		dbg_ctrl("Unlink of ctrl urb (0x%lx)", (unsigned long)urb);
-
-		if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
-			/* The EP was enabled, disable it and wait. */
-			TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
-
-			/* Ah, the luxury of busy-wait. */
-			while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid]));
-		}
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
-
-		dbg_intr("Unlink of intr urb (0x%lx)", (unsigned long)urb);
-
-		/* Separate function because it's a tad more complicated. */
-		etrax_usb_unlink_intr_urb(urb);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-
-		dbg_isoc("Unlink of isoc urb (0x%lx)", (unsigned long)urb);
-
-		if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
-			/* The EP was enabled, disable it and wait. */
-			TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
-
-			/* Ah, the luxury of busy-wait. */
-			while (*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid]));
-		}
-	}
-
-	/* Note that we need to remove the urb from the urb list *before* removing its SB
-	   descriptors. (This means that the isoc eof handler might get a null urb when we
-	   are unlinking the last urb.) */
-
-	if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-
-		urb_list_del(urb, epid);
-		TxBulkEPList[epid].sub = 0;
-		etrax_remove_from_sb_list(urb);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-
-		urb_list_del(urb, epid);
-		TxCtrlEPList[epid].sub = 0;
-		etrax_remove_from_sb_list(urb);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
-
-		urb_list_del(urb, epid);
-		/* Sanity check (should never happen). */
-		assert(urb_list_empty(epid));
-
-		/* Release allocated bandwidth. */
-		usb_release_bandwidth(urb->dev, urb, 0);
-
-	} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-
-		if (usb_pipeout(urb->pipe)) {
-
-			USB_SB_Desc_t *iter_sb, *prev_sb, *next_sb;
-
-			if (__urb_list_entry(urb, epid)) {
-
-				urb_list_del(urb, epid);
-				iter_sb = TxIsocEPList[epid].sub ? phys_to_virt(TxIsocEPList[epid].sub) : 0;
-				prev_sb = 0;
-				while (iter_sb && (iter_sb != urb_priv->first_sb)) {
-					prev_sb = iter_sb;
-					iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0;
-				}
-
-				if (iter_sb == 0) {
-					/* Unlink of the URB currently being transmitted. */
-					prev_sb = 0;
-					iter_sb = TxIsocEPList[epid].sub ? phys_to_virt(TxIsocEPList[epid].sub) : 0;
-				}
-
-				while (iter_sb && (iter_sb != urb_priv->last_sb)) {
-					iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0;
-				}
-				if (iter_sb) {
-					next_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0;
-				} else {
-					/* This should only happen if the DMA has completed
-					   processing the SB list for this EP while interrupts
-					   are disabled. */
-					dbg_isoc("Isoc urb not found, already sent?");
-					next_sb = 0;
-				}
-				if (prev_sb) {
-					prev_sb->next = next_sb ? virt_to_phys(next_sb) : 0;
-				} else {
-					TxIsocEPList[epid].sub = next_sb ? virt_to_phys(next_sb) : 0;
-				}
-
-				etrax_remove_from_sb_list(urb);
-				if (urb_list_empty(epid)) {
-					TxIsocEPList[epid].sub = 0;
-					dbg_isoc("Last isoc out urb epid %d", epid);
-				} else if (next_sb || prev_sb) {
-					dbg_isoc("Re-enable isoc out epid %d", epid);
-
-					TxIsocEPList[epid].hw_len = 0;
-					TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-				} else {
-					TxIsocEPList[epid].sub = 0;
-					dbg_isoc("URB list non-empty and no SB list, EP disabled");
-				}
-			} else {
-				dbg_isoc("Urb 0x%p not found, completed already?", urb);
-			}
-		} else {
-
-			urb_list_del(urb, epid);
-
-			/* For in traffic there is only one SB descriptor for each EP even
-			   though there may be several urbs (all urbs point at the same SB). */
-			if (urb_list_empty(epid)) {
-				/* No more urbs, remove the SB. */
-				TxIsocEPList[epid].sub = 0;
-				etrax_remove_from_sb_list(urb);
-			} else {
-				TxIsocEPList[epid].hw_len = 0;
-				TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-			}
-		}
-		/* Release allocated bandwidth. */
-		usb_release_bandwidth(urb->dev, urb, 1);
-	}
-	/* Free the epid if urb list is empty. */
-	if (urb_list_empty(epid)) {
-		etrax_usb_free_epid(epid);
-	}
-	restore_flags(flags);
-
-	/* Must be done before calling completion handler. */
-	kfree(urb_priv);
-	urb->hcpriv = 0;
-
-	if (urb->complete) {
-		urb->complete(urb, NULL);
-	}
-
-	DBFEXIT;
-	return 0;
-}
-
-static int etrax_usb_get_frame_number(struct usb_device *usb_dev)
-{
-	DBFENTER;
-	DBFEXIT;
-	return (*R_USB_FM_NUMBER & 0x7ff);
-}
-
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc)
-{
-	DBFENTER;
-
-	/* This interrupt handler could be used when unlinking EP descriptors. */
-
-	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {
-		USB_EP_Desc_t *ep;
-
-		//dbg_bulk("dma8_sub0_descr (BULK) intr.");
-
-		/* It should be safe clearing the interrupt here, since we don't expect to get a new
-		   one until we restart the bulk channel. */
-		*R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);
-
-		/* Wait while the DMA is running (though we don't expect it to be). */
-		while (*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd));
-
-		/* Advance the DMA to the next EP descriptor. */
-		ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP);
-
-		//dbg_bulk("descr intr: DMA is at 0x%lx", (unsigned long)ep);
-
-		/* ep->next is already a physical address; no need for a virt_to_phys. */
-		*R_DMA_CH8_SUB0_EP = ep->next;
-
-		/* Start the DMA bulk channel again. */
-		*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
-	}
-	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {
-		struct urb *urb;
-		int epid;
-		etrax_urb_priv_t *urb_priv;
-		unsigned long int flags;
-
-		dbg_ctrl("dma8_sub1_descr (CTRL) intr.");
-		*R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);
-
-		/* The complete callback gets called so we cli. */
-		save_flags(flags);
-		cli();
-
-		for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {
-			if ((TxCtrlEPList[epid].sub == 0) ||
-			    (epid == DUMMY_EPID) ||
-			    (epid == INVALID_EPID)) {
-				/* Nothing here to see. */
-				continue;
-			}
-
-			/* Get the first urb (if any). */
-			urb = urb_list_first(epid);
-
-			if (urb) {
-
-				/* Sanity check. */
-				assert(usb_pipetype(urb->pipe) == PIPE_CONTROL);
-
-				urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-				assert(urb_priv);
-
-				if (urb_priv->urb_state == WAITING_FOR_DESCR_INTR) {
-					assert(!(TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)));
-
-					etrax_usb_complete_urb(urb, 0);
-				}
-			}
-		}
-		restore_flags(flags);
-	}
-	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {
-		dbg_intr("dma8_sub2_descr (INTR) intr.");
-		*R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);
-	}
-	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {
-		struct urb *urb;
-		int epid;
-		int epid_done;
-		etrax_urb_priv_t *urb_priv;
-		USB_SB_Desc_t *sb_desc;
-
-		usb_isoc_complete_data_t *comp_data = NULL;
-
-		/* One or more isoc out transfers are done. */
-		dbg_isoc("dma8_sub3_descr (ISOC) intr.");
-
-		/* For each isoc out EP search for the first sb_desc with the intr flag
-		   set.  This descriptor must be the last packet from an URB.  Then
-		   traverse the URB list for the EP until the URB with urb_priv->last_sb
-		   matching the intr-marked sb_desc is found.  All URBs before this have
-		   been sent.
-		*/
-
-		for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {
-			/* Skip past epids with no SB lists, epids used for in traffic,
-			   and special (dummy, invalid) epids. */
-			if ((TxIsocEPList[epid].sub == 0) ||
-			    (test_bit(epid, (void *)&epid_out_traffic) == 0) ||
-			    (epid == DUMMY_EPID) ||
-			    (epid == INVALID_EPID)) {
-				/* Nothing here to see. */
-				continue;
-			}
-			sb_desc = phys_to_virt(TxIsocEPList[epid].sub);
-
-			/* Find the last descriptor of the currently active URB for this ep.
-			   This is the first descriptor in the sub list marked for a descriptor
-			   interrupt. */
-			while (sb_desc && !IO_EXTRACT(USB_SB_command, intr, sb_desc->command)) {
-				sb_desc = sb_desc->next ? phys_to_virt(sb_desc->next) : 0;
-			}
-			assert(sb_desc);
-
-			dbg_isoc("Check epid %d, sub 0x%p, SB 0x%p",
-				 epid,
-				 phys_to_virt(TxIsocEPList[epid].sub),
-				 sb_desc);
-
-			epid_done = 0;
-
-			/* Get the first urb (if any). */
-			urb = urb_list_first(epid);
-			assert(urb);
-
-			while (urb && !epid_done) {
-
-				/* Sanity check. */
-				assert(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);
-
-				if (!usb_pipeout(urb->pipe)) {
-					/* descr interrupts are generated only for out pipes. */
-					epid_done = 1;
-					continue;
-				}
-
-				urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-				assert(urb_priv);
-
-				if (sb_desc != urb_priv->last_sb) {
-
-					/* This urb has been sent. */
-					dbg_isoc("out URB 0x%p sent", urb);
-
-					urb_priv->urb_state = TRANSFER_DONE;
-
-				} else if ((sb_desc == urb_priv->last_sb) &&
-					   !(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) {
-
-					assert((sb_desc->command & IO_MASK(USB_SB_command, eol)) == IO_STATE(USB_SB_command, eol, yes));
-					assert(sb_desc->next == 0);
-
-					dbg_isoc("out URB 0x%p last in list, epid disabled", urb);
-					TxIsocEPList[epid].sub = 0;
-					TxIsocEPList[epid].hw_len = 0;
-					urb_priv->urb_state = TRANSFER_DONE;
-
-					epid_done = 1;
-
-				} else {
-					epid_done = 1;
-				}
-				if (!epid_done) {
-					urb = urb_list_next(urb, epid);
-				}
-			}
-
-		}
-
-		*R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);
-
-		comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC);
-		assert(comp_data != NULL);
-
-                INIT_WORK(&comp_data->usb_bh, etrax_usb_isoc_descr_interrupt_bottom_half, comp_data);
-                schedule_work(&comp_data->usb_bh);
-	}
-
-	DBFEXIT;
-        return IRQ_HANDLED;
-}
-
-static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data)
-{
-	usb_isoc_complete_data_t *comp_data = (usb_isoc_complete_data_t*)data;
-
-	struct urb *urb;
-	int epid;
-	int epid_done;
-	etrax_urb_priv_t *urb_priv;
-
-	DBFENTER;
-
-	dbg_isoc("dma8_sub3_descr (ISOC) bottom half.");
-
-	for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {
-		unsigned long flags;
-
-		save_flags(flags);
-		cli();
-
-		epid_done = 0;
-
-		/* The descriptor interrupt handler has marked all transmitted isoch. out
-		   URBs with TRANSFER_DONE.  Now we traverse all epids and for all that
- 		   have isoch. out traffic traverse its URB list and complete the
-		   transmitted URB.
-		*/
-
-		while (!epid_done) {
-
-			/* Get the first urb (if any). */
-			urb = urb_list_first(epid);
-			if (urb == 0) {
-				epid_done = 1;
-				continue;
-			}
-
-			if (usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) {
-					epid_done = 1;
-					continue;
-			}
-
-			if (!usb_pipeout(urb->pipe)) {
-				/* descr interrupts are generated only for out pipes. */
-				epid_done = 1;
-				continue;
-			}
-
-			dbg_isoc("Check epid %d, SB 0x%p", epid, (char*)TxIsocEPList[epid].sub);
-
-			urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-			assert(urb_priv);
-
-			if (urb_priv->urb_state == TRANSFER_DONE) {
-				int i;
-				struct usb_iso_packet_descriptor *packet;
-
-				/* This urb has been sent. */
-				dbg_isoc("Completing isoc out URB 0x%p", urb);
-
-				for (i = 0; i < urb->number_of_packets; i++) {
-					packet = &urb->iso_frame_desc[i];
-					packet->status = 0;
-					packet->actual_length = packet->length;
-				}
-
-				etrax_usb_complete_isoc_urb(urb, 0);
-
-				if (urb_list_empty(epid)) {
-					etrax_usb_free_epid(epid);
-					epid_done = 1;
-				}
-			} else {
-				epid_done = 1;
-			}
-		}
-		restore_flags(flags);
-
-	}
-	kmem_cache_free(isoc_compl_cache, comp_data);
-
-	DBFEXIT;
-}
-
-
-
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc)
-{
-	struct urb *urb;
-	etrax_urb_priv_t *urb_priv;
-	int epid = 0;
-	unsigned long flags;
-
-	/* Isoc diagnostics. */
-	static int curr_fm = 0;
-	static int prev_fm = 0;
-
-	DBFENTER;
-
-	/* Clear this interrupt. */
-	*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);
-
-	/* Note that this while loop assumes that all packets span only
-	   one rx descriptor. */
-
-	/* The reason we cli here is that we call the driver's callback functions. */
-	save_flags(flags);
-	cli();
-
-	while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {
-
-		epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);
-		urb = urb_list_first(epid);
-
-		//printk("eop for epid %d, first urb 0x%lx\n", epid, (unsigned long)urb);
-
-		if (!urb) {
-			err("No urb for epid %d in rx interrupt", epid);
-			__dump_ept_data(epid);
-			goto skip_out;
-		}
-
-		/* Note that we cannot indescriminately assert(usb_pipein(urb->pipe)) since
-		   ctrl pipes are not. */
-
-		if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {
-			__u32 r_usb_ept_data;
-			int no_error = 0;
-
-			assert(test_bit(epid, (void *)&epid_usage_bitmask));
-
-			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-			nop();
-			if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-				r_usb_ept_data = *R_USB_EPT_DATA_ISO;
-
-				if ((r_usb_ept_data & IO_MASK(R_USB_EPT_DATA_ISO, valid)) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data) == 0) &&
-				    (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata))) {
-					/* Not an error, just a failure to receive an expected iso
-					   in packet in this frame.  This is not documented
-					   in the designers reference.
-					*/
-					no_error++;
-				} else {
-					warn("R_USB_EPT_DATA_ISO for epid %d = 0x%x", epid, r_usb_ept_data);
-				}
-			} else {
-				r_usb_ept_data = *R_USB_EPT_DATA;
-				warn("R_USB_EPT_DATA for epid %d = 0x%x", epid, r_usb_ept_data);
-			}
-
-			if (!no_error){
-				warn("error in rx desc->status, epid %d, first urb = 0x%lx",
-				     epid, (unsigned long)urb);
-				__dump_in_desc(myNextRxDesc);
-
-				warn("R_USB_STATUS = 0x%x", *R_USB_STATUS);
-
-				/* Check that ept was disabled when error occurred. */
-				switch (usb_pipetype(urb->pipe)) {
-				case PIPE_BULK:
-					assert(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)));
-					break;
-				case PIPE_CONTROL:
-					assert(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)));
-					break;
-				case PIPE_INTERRUPT:
-					assert(!(TxIntrEPList[epid].command & IO_MASK(USB_EP_command, enable)));
-					break;
-				case PIPE_ISOCHRONOUS:
-					assert(!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)));
-					break;
-				default:
-					warn("etrax_usb_rx_interrupt: bad pipetype %d in urb 0x%p",
-					     usb_pipetype(urb->pipe),
-					     urb);
-				}
-				etrax_usb_complete_urb(urb, -EPROTO);
-				goto skip_out;
-			}
-		}
-
-		urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-		assert(urb_priv);
-
-		if ((usb_pipetype(urb->pipe) == PIPE_BULK) ||
-		    (usb_pipetype(urb->pipe) == PIPE_CONTROL) ||
-		    (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
-
-			if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {
-				/* We get nodata for empty data transactions, and the rx descriptor's
-				   hw_len field is not valid in that case. No data to copy in other
-				   words. */
-			} else {
-				/* Make sure the data fits in the buffer. */
-				assert(urb_priv->rx_offset + myNextRxDesc->hw_len
-				       <= urb->transfer_buffer_length);
-
-				memcpy(urb->transfer_buffer + urb_priv->rx_offset,
-				       phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len);
-				urb_priv->rx_offset += myNextRxDesc->hw_len;
-			}
-
-			if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) {
-				if ((usb_pipetype(urb->pipe) == PIPE_CONTROL) &&
-				    ((TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)) ==
-				     IO_STATE(USB_EP_command, enable, yes))) {
-					/* The EP is still enabled, so the OUT packet used to ack
-					   the in data is probably not processed yet.  If the EP
-					   sub pointer has not moved beyond urb_priv->last_sb mark
-					   it for a descriptor interrupt and complete the urb in
-					   the descriptor interrupt handler.
-					*/
-					USB_SB_Desc_t *sub = TxCtrlEPList[urb_priv->epid].sub ? phys_to_virt(TxCtrlEPList[urb_priv->epid].sub) : 0;
-
-					while ((sub != NULL) && (sub != urb_priv->last_sb)) {
-						sub = sub->next ? phys_to_virt(sub->next) : 0;
-					}
-					if (sub != NULL) {
-						/* The urb has not been fully processed. */
-						urb_priv->urb_state = WAITING_FOR_DESCR_INTR;
-					} else {
-						warn("(CTRL) epid enabled and urb (0x%p) processed, ep->sub=0x%p", urb, (char*)TxCtrlEPList[urb_priv->epid].sub);
-						etrax_usb_complete_urb(urb, 0);
-					}
-				} else {
-					etrax_usb_complete_urb(urb, 0);
-				}
-			}
-
-		} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-
-			struct usb_iso_packet_descriptor *packet;
-
-			if (urb_priv->urb_state == UNLINK) {
-				info("Ignoring rx data for urb being unlinked.");
-				goto skip_out;
-			} else if (urb_priv->urb_state == NOT_STARTED) {
-				info("What? Got rx data for urb that isn't started?");
-				goto skip_out;
-			}
-
-			packet = &urb->iso_frame_desc[urb_priv->isoc_packet_counter];
-			packet->status = 0;
-
-			if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {
-				/* We get nodata for empty data transactions, and the rx descriptor's
-				   hw_len field is not valid in that case. We copy 0 bytes however to
-				   stay in synch. */
-				packet->actual_length = 0;
-			} else {
-				packet->actual_length = myNextRxDesc->hw_len;
-				/* Make sure the data fits in the buffer. */
-				assert(packet->actual_length <= packet->length);
-				memcpy(urb->transfer_buffer + packet->offset,
-				       phys_to_virt(myNextRxDesc->buf), packet->actual_length);
-			}
-
-			/* Increment the packet counter. */
-			urb_priv->isoc_packet_counter++;
-
-			/* Note that we don't care about the eot field in the rx descriptor's status.
-			   It will always be set for isoc traffic. */
-			if (urb->number_of_packets == urb_priv->isoc_packet_counter) {
-
-				/* Out-of-synch diagnostics. */
-				curr_fm = (*R_USB_FM_NUMBER & 0x7ff);
-				if (((prev_fm + urb_priv->isoc_packet_counter) % (0x7ff + 1)) != curr_fm) {
-					/* This test is wrong, if there is more than one isoc
-					   in endpoint active it will always calculate wrong
-					   since prev_fm is shared by all endpoints.
-
-					   FIXME Make this check per URB using urb->start_frame.
-					*/
-					dbg_isoc("Out of synch? Previous frame = %d, current frame = %d",
-						 prev_fm, curr_fm);
-
-				}
-				prev_fm = curr_fm;
-
-				/* Complete the urb with status OK. */
-				etrax_usb_complete_isoc_urb(urb, 0);
-			}
-		}
-
-	skip_out:
-
-		/* DMA IN cache bug. Flush the DMA IN buffer from the cache. (struct etrax_dma_descr
-		   has the same layout as USB_IN_Desc for the relevant fields.) */
-		prepare_rx_descriptor((struct etrax_dma_descr*)myNextRxDesc);
-
-		myPrevRxDesc = myNextRxDesc;
-		myPrevRxDesc->command |= IO_MASK(USB_IN_command, eol);
-		myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol);
-		myLastRxDesc = myPrevRxDesc;
-
-		myNextRxDesc->status = 0;
-		myNextRxDesc = phys_to_virt(myNextRxDesc->next);
-	}
-
-	restore_flags(flags);
-
-	DBFEXIT;
-
-        return IRQ_HANDLED;
-}
-
-
-/* This function will unlink the SB descriptors associated with this urb. */
-static int etrax_remove_from_sb_list(struct urb *urb)
-{
-	USB_SB_Desc_t *next_sb, *first_sb, *last_sb;
-	etrax_urb_priv_t *urb_priv;
-	int i = 0;
-
-	DBFENTER;
-
-	urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	assert(urb_priv);
-
-	/* Just a sanity check. Since we don't fiddle with the DMA list the EP descriptor
-	   doesn't really need to be disabled, it's just that we expect it to be. */
-	if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-		assert(!(TxBulkEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)));
-	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-		assert(!(TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)));
-	}
-
-	first_sb = urb_priv->first_sb;
-	last_sb = urb_priv->last_sb;
-
-	assert(first_sb);
-	assert(last_sb);
-
-	while (first_sb != last_sb) {
-		next_sb = (USB_SB_Desc_t *)phys_to_virt(first_sb->next);
-		kmem_cache_free(usb_desc_cache, first_sb);
-		first_sb = next_sb;
-		i++;
-	}
-	kmem_cache_free(usb_desc_cache, last_sb);
-	i++;
-	dbg_sb("%d SB descriptors freed", i);
-	/* Compare i with urb->number_of_packets for Isoc traffic.
-	   Should be same when calling unlink_urb */
-
-	DBFEXIT;
-
-	return i;
-}
-
-static int etrax_usb_submit_bulk_urb(struct urb *urb)
-{
-	int epid;
-	int empty;
-	unsigned long flags;
-	etrax_urb_priv_t *urb_priv;
-
-	DBFENTER;
-
-	/* Epid allocation, empty check and list add must be protected.
-	   Read about this in etrax_usb_submit_ctrl_urb. */
-
-	spin_lock_irqsave(&urb_list_lock, flags);
-	epid = etrax_usb_setup_epid(urb);
-	if (epid == -1) {
-		DBFEXIT;
-		spin_unlock_irqrestore(&urb_list_lock, flags);
-		return -ENOMEM;
-	}
-	empty = urb_list_empty(epid);
-	urb_list_add(urb, epid);
-	spin_unlock_irqrestore(&urb_list_lock, flags);
-
-	dbg_bulk("Adding bulk %s urb 0x%lx to %s list, epid %d",
-		 usb_pipein(urb->pipe) ? "IN" : "OUT", (unsigned long)urb, empty ? "empty" : "", epid);
-
-	/* Mark the urb as being in progress. */
-	urb->status = -EINPROGRESS;
-
-	/* Setup the hcpriv data. */
-	urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
-	assert(urb_priv != NULL);
-	/* This sets rx_offset to 0. */
-	urb_priv->urb_state = NOT_STARTED;
-	urb->hcpriv = urb_priv;
-
-	if (empty) {
-		etrax_usb_add_to_bulk_sb_list(urb, epid);
-	}
-
-	DBFEXIT;
-
-	return 0;
-}
-
-static void etrax_usb_add_to_bulk_sb_list(struct urb *urb, int epid)
-{
-	USB_SB_Desc_t *sb_desc;
-	etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	unsigned long flags;
-	char maxlen;
-
-	DBFENTER;
-
-	dbg_bulk("etrax_usb_add_to_bulk_sb_list, urb 0x%lx", (unsigned long)urb);
-
-	maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-
-	sb_desc = kmem_cache_zalloc(usb_desc_cache, SLAB_FLAG);
-	assert(sb_desc != NULL);
-
-
-	if (usb_pipeout(urb->pipe)) {
-
-		dbg_bulk("Grabbing bulk OUT, urb 0x%lx, epid %d", (unsigned long)urb, epid);
-
-		/* This is probably a sanity check of the bulk transaction length
-		   not being larger than 64 kB. */
-		if (urb->transfer_buffer_length > 0xffff) {
-			panic("urb->transfer_buffer_length > 0xffff");
-		}
-
-		sb_desc->sw_len = urb->transfer_buffer_length;
-
-		/* The rem field is don't care if it's not a full-length transfer, so setting
-		   it shouldn't hurt. Also, rem isn't used for OUT traffic. */
-		sb_desc->command = (IO_FIELD(USB_SB_command, rem, 0) |
-				    IO_STATE(USB_SB_command, tt, out) |
-				    IO_STATE(USB_SB_command, eot, yes) |
-				    IO_STATE(USB_SB_command, eol, yes));
-
-		/* The full field is set to yes, even if we don't actually check that this is
-		   a full-length transfer (i.e., that transfer_buffer_length % maxlen = 0).
-		   Setting full prevents the USB controller from sending an empty packet in
-		   that case.  However, if URB_ZERO_PACKET was set we want that. */
-		if (!(urb->transfer_flags & URB_ZERO_PACKET)) {
-			sb_desc->command |= IO_STATE(USB_SB_command, full, yes);
-		}
-
-		sb_desc->buf = virt_to_phys(urb->transfer_buffer);
-		sb_desc->next = 0;
-
-	} else if (usb_pipein(urb->pipe)) {
-
-		dbg_bulk("Grabbing bulk IN, urb 0x%lx, epid %d", (unsigned long)urb, epid);
-
-		sb_desc->sw_len = urb->transfer_buffer_length ?
-			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
-
-		/* The rem field is don't care if it's not a full-length transfer, so setting
-		   it shouldn't hurt. */
-		sb_desc->command =
-			(IO_FIELD(USB_SB_command, rem,
-				  urb->transfer_buffer_length % maxlen) |
-			 IO_STATE(USB_SB_command, tt, in) |
-			 IO_STATE(USB_SB_command, eot, yes) |
-			 IO_STATE(USB_SB_command, eol, yes));
-
-		sb_desc->buf = 0;
-		sb_desc->next = 0;
-	}
-
-	urb_priv->first_sb = sb_desc;
-	urb_priv->last_sb = sb_desc;
-	urb_priv->epid = epid;
-
-	urb->hcpriv = urb_priv;
-
-	/* Reset toggle bits and reset error count. */
-	save_flags(flags);
-	cli();
-
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-
-	/* FIXME: Is this a special case since the hold field is checked,
-	   or should we check hold in a lot of other cases as well? */
-	if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
-		panic("Hold was set in %s", __FUNCTION__);
-	}
-
-	/* Reset error counters (regardless of which direction this traffic is). */
-	*R_USB_EPT_DATA &=
-		~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
-		  IO_MASK(R_USB_EPT_DATA, error_count_out));
-
-	/* Software must preset the toggle bits. */
-	if (usb_pipeout(urb->pipe)) {
-		char toggle =
-			usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-		*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out);
-		*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle);
-	} else {
-		char toggle =
-			usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-		*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in);
-		*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle);
-	}
-
-	/* Assert that the EP descriptor is disabled. */
-	assert(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)));
-
-	/* The reason we set the EP's sub pointer directly instead of
-	   walking the SB list and linking it last in the list is that we only
-	   have one active urb at a time (the rest are queued). */
-
-	/* Note that we cannot have interrupts running when we have set the SB descriptor
-	   but the EP is not yet enabled.  If a bulk eot happens for another EP, we will
-	   find this EP disabled and with a SB != 0, which will make us think that it's done. */
-	TxBulkEPList[epid].sub = virt_to_phys(sb_desc);
-	TxBulkEPList[epid].hw_len = 0;
-	/* Note that we don't have to fill in the ep_id field since this
-	   was done when we allocated the EP descriptors in init_tx_bulk_ep. */
-
-	/* Check if the dummy list is already with us (if several urbs were queued). */
-	if (TxBulkEPList[epid].next != virt_to_phys(&TxBulkDummyEPList[epid][0])) {
-
-		dbg_bulk("Inviting dummy list to the party for urb 0x%lx, epid %d",
-			 (unsigned long)urb, epid);
-
-		/* The last EP in the dummy list already has its next pointer set to
-		   TxBulkEPList[epid].next. */
-
-		/* We don't need to check if the DMA is at this EP or not before changing the
-		   next pointer, since we will do it in one 32-bit write (EP descriptors are
-		   32-bit aligned). */
-		TxBulkEPList[epid].next = virt_to_phys(&TxBulkDummyEPList[epid][0]);
-	}
-	/* Enable the EP descr. */
-	dbg_bulk("Enabling bulk EP for urb 0x%lx, epid %d", (unsigned long)urb, epid);
-	TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-
-	/* Everything is set up, safe to enable interrupts again. */
-	restore_flags(flags);
-
-	/* If the DMA bulk channel isn't running, we need to restart it if it
-	   has stopped at the last EP descriptor (DMA stopped because there was
-	   no more traffic) or if it has stopped at a dummy EP with the intr flag
-	   set (DMA stopped because we were too slow in inserting new traffic). */
-	if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {
-
-		USB_EP_Desc_t *ep;
-		ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP);
-		dbg_bulk("DMA channel not running in add");
-		dbg_bulk("DMA is at 0x%lx", (unsigned long)ep);
-
-		if (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[NBR_OF_EPIDS - 1]) ||
-		    (ep->command & 0x8) >> 3) {
-			*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
-			/* Update/restart the bulk start timer since we just started the channel. */
-			mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);
-			/* Update/restart the bulk eot timer since we just inserted traffic. */
-			mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);
-		}
-	}
-
-	DBFEXIT;
-}
-
-static void etrax_usb_complete_bulk_urb(struct urb *urb, int status)
-{
-	etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	int epid = urb_priv->epid;
-	unsigned long flags;
-
-	DBFENTER;
-
-	if (status)
-		warn("Completing bulk urb with status %d.", status);
-
-	dbg_bulk("Completing bulk urb 0x%lx for epid %d", (unsigned long)urb, epid);
-
-	/* Update the urb list. */
-	urb_list_del(urb, epid);
-
-	/* For an IN pipe, we always set the actual length, regardless of whether there was
-	   an error or not (which means the device driver can use the data if it wants to). */
-	if (usb_pipein(urb->pipe)) {
-		urb->actual_length = urb_priv->rx_offset;
-	} else {
-		/* Set actual_length for OUT urbs also; the USB mass storage driver seems
-		   to want that. We wouldn't know of any partial writes if there was an error. */
-		if (status == 0) {
-			urb->actual_length = urb->transfer_buffer_length;
-		} else {
-			urb->actual_length = 0;
-		}
-	}
-
-	/* FIXME: Is there something of the things below we shouldn't do if there was an error?
-	   Like, maybe we shouldn't toggle the toggle bits, or maybe we shouldn't insert more traffic. */
-
-	save_flags(flags);
-	cli();
-
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-
-	/* We need to fiddle with the toggle bits because the hardware doesn't do it for us. */
-	if (usb_pipeout(urb->pipe)) {
-		char toggle =
-			IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA);
-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			      usb_pipeout(urb->pipe), toggle);
-	} else {
-		char toggle =
-			IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA);
-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			      usb_pipeout(urb->pipe), toggle);
-	}
-	restore_flags(flags);
-
-	/* Remember to free the SBs. */
-	etrax_remove_from_sb_list(urb);
-	kfree(urb_priv);
-	urb->hcpriv = 0;
-
-	/* If there are any more urb's in the list we'd better start sending */
-	if (!urb_list_empty(epid)) {
-
-		struct urb *new_urb;
-
-		/* Get the first urb. */
-		new_urb = urb_list_first(epid);
-		assert(new_urb);
-
-		dbg_bulk("More bulk for epid %d", epid);
-
-		etrax_usb_add_to_bulk_sb_list(new_urb, epid);
-	}
-
-	urb->status = status;
-
-	/* We let any non-zero status from the layer above have precedence. */
-	if (status == 0) {
-		/* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's max length)
-		   is to be treated as an error. */
-		if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-			if (usb_pipein(urb->pipe) &&
-			    (urb->actual_length !=
-			     usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))) {
-				urb->status = -EREMOTEIO;
-			}
-		}
-	}
-
-	if (urb->complete) {
-		urb->complete(urb, NULL);
-	}
-
-	if (urb_list_empty(epid)) {
-		/* This means that this EP is now free, deconfigure it. */
-		etrax_usb_free_epid(epid);
-
-		/* No more traffic; time to clean up.
-		   Must set sub pointer to 0, since we look at the sub pointer when handling
-		   the bulk eot interrupt. */
-
-		dbg_bulk("No bulk for epid %d", epid);
-
-		TxBulkEPList[epid].sub = 0;
-
-		/* Unlink the dummy list. */
-
-		dbg_bulk("Kicking dummy list out of party for urb 0x%lx, epid %d",
-			 (unsigned long)urb, epid);
-
-		/* No need to wait for the DMA before changing the next pointer.
-		   The modulo NBR_OF_EPIDS isn't actually necessary, since we will never use
-		   the last one (INVALID_EPID) for actual traffic. */
-		TxBulkEPList[epid].next =
-			virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);
-	}
-
-	DBFEXIT;
-}
-
-static int etrax_usb_submit_ctrl_urb(struct urb *urb)
-{
-	int epid;
-	int empty;
-	unsigned long flags;
-	etrax_urb_priv_t *urb_priv;
-
-	DBFENTER;
-
-	/* FIXME: Return -ENXIO if there is already a queued urb for this endpoint? */
-
-	/* Epid allocation, empty check and list add must be protected.
-
-	   Epid allocation because if we find an existing epid for this endpoint an urb might be
-	   completed (emptying the list) before we add the new urb to the list, causing the epid
-	   to be de-allocated. We would then start the transfer with an invalid epid -> epid attn.
-
-	   Empty check and add because otherwise we might conclude that the list is not empty,
-	   after which it becomes empty before we add the new urb to the list, causing us not to
-	   insert the new traffic into the SB list. */
-
-	spin_lock_irqsave(&urb_list_lock, flags);
-	epid = etrax_usb_setup_epid(urb);
-	if (epid == -1) {
-		spin_unlock_irqrestore(&urb_list_lock, flags);
-		DBFEXIT;
-		return -ENOMEM;
-	}
-	empty = urb_list_empty(epid);
-	urb_list_add(urb, epid);
-	spin_unlock_irqrestore(&urb_list_lock, flags);
-
-	dbg_ctrl("Adding ctrl urb 0x%lx to %s list, epid %d",
-		 (unsigned long)urb, empty ? "empty" : "", epid);
-
-	/* Mark the urb as being in progress. */
-	urb->status = -EINPROGRESS;
-
-	/* Setup the hcpriv data. */
-	urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
-	assert(urb_priv != NULL);
-	/* This sets rx_offset to 0. */
-	urb_priv->urb_state = NOT_STARTED;
-	urb->hcpriv = urb_priv;
-
-	if (empty) {
-		etrax_usb_add_to_ctrl_sb_list(urb, epid);
-	}
-
-	DBFEXIT;
-
-	return 0;
-}
-
-static void etrax_usb_add_to_ctrl_sb_list(struct urb *urb, int epid)
-{
-	USB_SB_Desc_t *sb_desc_setup;
-	USB_SB_Desc_t *sb_desc_data;
-	USB_SB_Desc_t *sb_desc_status;
-
-	etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-
-	unsigned long flags;
-	char maxlen;
-
-	DBFENTER;
-
-	maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-
-	sb_desc_setup = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
-	assert(sb_desc_setup != NULL);
-	sb_desc_status = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
-	assert(sb_desc_status != NULL);
-
-	/* Initialize the mandatory setup SB descriptor (used only in control transfers) */
-	sb_desc_setup->sw_len = 8;
-	sb_desc_setup->command = (IO_FIELD(USB_SB_command, rem, 0) |
-				  IO_STATE(USB_SB_command, tt, setup) |
-				  IO_STATE(USB_SB_command, full, yes) |
-				  IO_STATE(USB_SB_command, eot, yes));
-
-	sb_desc_setup->buf = virt_to_phys(urb->setup_packet);
-
-	if (usb_pipeout(urb->pipe)) {
-		dbg_ctrl("Transfer for epid %d is OUT", epid);
-
-		/* If this Control OUT transfer has an optional data stage we add an OUT token
-		   before the mandatory IN (status) token, hence the reordered SB list */
-
-		sb_desc_setup->next = virt_to_phys(sb_desc_status);
-		if (urb->transfer_buffer) {
-
-			dbg_ctrl("This OUT transfer has an extra data stage");
-
-			sb_desc_data = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
-			assert(sb_desc_data != NULL);
-
-			sb_desc_setup->next = virt_to_phys(sb_desc_data);
-
-			sb_desc_data->sw_len = urb->transfer_buffer_length;
-			sb_desc_data->command = (IO_STATE(USB_SB_command, tt, out) |
-						 IO_STATE(USB_SB_command, full, yes) |
-						 IO_STATE(USB_SB_command, eot, yes));
-			sb_desc_data->buf = virt_to_phys(urb->transfer_buffer);
-			sb_desc_data->next = virt_to_phys(sb_desc_status);
-		}
-
-		sb_desc_status->sw_len = 1;
-		sb_desc_status->command = (IO_FIELD(USB_SB_command, rem, 0) |
-					   IO_STATE(USB_SB_command, tt, in) |
-					   IO_STATE(USB_SB_command, eot, yes) |
-					   IO_STATE(USB_SB_command, intr, yes) |
-					   IO_STATE(USB_SB_command, eol, yes));
-
-		sb_desc_status->buf = 0;
-		sb_desc_status->next = 0;
-
-	} else if (usb_pipein(urb->pipe)) {
-
-		dbg_ctrl("Transfer for epid %d is IN", epid);
-		dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length);
-		dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
-
-		sb_desc_data = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
-		assert(sb_desc_data != NULL);
-
-		sb_desc_setup->next = virt_to_phys(sb_desc_data);
-
-		sb_desc_data->sw_len = urb->transfer_buffer_length ?
-			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
-		dbg_ctrl("sw_len got %d", sb_desc_data->sw_len);
-
-		sb_desc_data->command =
-			(IO_FIELD(USB_SB_command, rem,
-				  urb->transfer_buffer_length % maxlen) |
-			 IO_STATE(USB_SB_command, tt, in) |
-			 IO_STATE(USB_SB_command, eot, yes));
-
-		sb_desc_data->buf = 0;
-		sb_desc_data->next = virt_to_phys(sb_desc_status);
-
-		/* Read comment at zout_buffer declaration for an explanation to this. */
-		sb_desc_status->sw_len = 1;
-		sb_desc_status->command = (IO_FIELD(USB_SB_command, rem, 0) |
-					   IO_STATE(USB_SB_command, tt, zout) |
-					   IO_STATE(USB_SB_command, full, yes) |
-					   IO_STATE(USB_SB_command, eot, yes) |
-					   IO_STATE(USB_SB_command, intr, yes) |
-					   IO_STATE(USB_SB_command, eol, yes));
-
-		sb_desc_status->buf = virt_to_phys(&zout_buffer[0]);
-		sb_desc_status->next = 0;
-	}
-
-	urb_priv->first_sb = sb_desc_setup;
-	urb_priv->last_sb = sb_desc_status;
-	urb_priv->epid = epid;
-
-	urb_priv->urb_state = STARTED;
-
-	/* Reset toggle bits and reset error count, remember to di and ei */
-	/* Warning: it is possible that this locking doesn't work with bottom-halves */
-
-	save_flags(flags);
-	cli();
-
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-	if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
-		panic("Hold was set in %s", __FUNCTION__);
-	}
-
-
-	/* FIXME: Compare with etrax_usb_add_to_bulk_sb_list where the toggle bits
-	   are set to a specific value. Why the difference? Read "Transfer and Toggle Bits
-	   in Designer's Reference, p. 8 - 11. */
-	*R_USB_EPT_DATA &=
-		~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
-		  IO_MASK(R_USB_EPT_DATA, error_count_out) |
-		  IO_MASK(R_USB_EPT_DATA, t_in) |
-		  IO_MASK(R_USB_EPT_DATA, t_out));
-
-	/* Since we use the rx interrupt to complete ctrl urbs, we can enable interrupts now
-	   (i.e. we don't check the sub pointer on an eot interrupt like we do for bulk traffic). */
-	restore_flags(flags);
-
-	/* Assert that the EP descriptor is disabled. */
-	assert(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)));
-
-	/* Set up and enable the EP descriptor. */
-	TxCtrlEPList[epid].sub = virt_to_phys(sb_desc_setup);
-	TxCtrlEPList[epid].hw_len = 0;
-	TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-
-	/* We start the DMA sub channel without checking if it's running or not, because:
-	   1) If it's already running, issuing the start command is a nop.
-	   2) We avoid a test-and-set race condition. */
-	*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
-
-	DBFEXIT;
-}
-
-static void etrax_usb_complete_ctrl_urb(struct urb *urb, int status)
-{
-	etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	int epid = urb_priv->epid;
-
-	DBFENTER;
-
-	if (status)
-		warn("Completing ctrl urb with status %d.", status);
-
-	dbg_ctrl("Completing ctrl epid %d, urb 0x%lx", epid, (unsigned long)urb);
-
-	/* Remove this urb from the list. */
-	urb_list_del(urb, epid);
-
-	/* For an IN pipe, we always set the actual length, regardless of whether there was
-	   an error or not (which means the device driver can use the data if it wants to). */
-	if (usb_pipein(urb->pipe)) {
-		urb->actual_length = urb_priv->rx_offset;
-	}
-
-	/* FIXME: Is there something of the things below we shouldn't do if there was an error?
-	   Like, maybe we shouldn't insert more traffic. */
-
-	/* Remember to free the SBs. */
-	etrax_remove_from_sb_list(urb);
-	kfree(urb_priv);
-	urb->hcpriv = 0;
-
-	/* If there are any more urbs in the list we'd better start sending. */
-	if (!urb_list_empty(epid)) {
-		struct urb *new_urb;
-
-		/* Get the first urb. */
-		new_urb = urb_list_first(epid);
-		assert(new_urb);
-
-		dbg_ctrl("More ctrl for epid %d, first urb = 0x%lx", epid, (unsigned long)new_urb);
-
-		etrax_usb_add_to_ctrl_sb_list(new_urb, epid);
-	}
-
-	urb->status = status;
-
-	/* We let any non-zero status from the layer above have precedence. */
-	if (status == 0) {
-		/* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's max length)
-		   is to be treated as an error. */
-		if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-			if (usb_pipein(urb->pipe) &&
-			    (urb->actual_length !=
-			     usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))) {
-				urb->status = -EREMOTEIO;
-			}
-		}
-	}
-
-	if (urb->complete) {
-		urb->complete(urb, NULL);
-	}
-
-	if (urb_list_empty(epid)) {
-		/* No more traffic. Time to clean up. */
-		etrax_usb_free_epid(epid);
-		/* Must set sub pointer to 0. */
-		dbg_ctrl("No ctrl for epid %d", epid);
-		TxCtrlEPList[epid].sub = 0;
-	}
-
-	DBFEXIT;
-}
-
-static int etrax_usb_submit_intr_urb(struct urb *urb)
-{
-
-	int epid;
-
-	DBFENTER;
-
-	if (usb_pipeout(urb->pipe)) {
-		/* Unsupported transfer type.
-		   We don't support interrupt out traffic. (If we do, we can't support
-		   intervals for neither in or out traffic, but are forced to schedule all
-		   interrupt traffic in one frame.) */
-		return -EINVAL;
-	}
-
-	epid = etrax_usb_setup_epid(urb);
-	if (epid == -1) {
-		DBFEXIT;
-		return -ENOMEM;
-	}
-
-	if (!urb_list_empty(epid)) {
-		/* There is already a queued urb for this endpoint. */
-		etrax_usb_free_epid(epid);
-		return -ENXIO;
-	}
-
-	urb->status = -EINPROGRESS;
-
-	dbg_intr("Add intr urb 0x%lx, to list, epid %d", (unsigned long)urb, epid);
-
-	urb_list_add(urb, epid);
-	etrax_usb_add_to_intr_sb_list(urb, epid);
-
-	return 0;
-
-	DBFEXIT;
-}
-
-static void etrax_usb_add_to_intr_sb_list(struct urb *urb, int epid)
-{
-
-	volatile USB_EP_Desc_t *tmp_ep;
-	volatile USB_EP_Desc_t *first_ep;
-
-	char maxlen;
-	int interval;
-	int i;
-
-	etrax_urb_priv_t *urb_priv;
-
-	DBFENTER;
-
-	maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	interval = urb->interval;
-
-	urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
-	assert(urb_priv != NULL);
-	urb->hcpriv = urb_priv;
-
-	first_ep = &TxIntrEPList[0];
-
-	/* Round of the interval to 2^n, it is obvious that this code favours
-	   smaller numbers, but that is actually a good thing */
-	/* FIXME: The "rounding error" for larger intervals will be quite
-	   large. For in traffic this shouldn't be a problem since it will only
-	   mean that we "poll" more often. */
-	for (i = 0; interval; i++) {
-		interval = interval >> 1;
-	}
-	interval = 1 << (i - 1);
-
-	dbg_intr("Interval rounded to %d", interval);
-
-	tmp_ep = first_ep;
-	i = 0;
-	do {
-		if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) {
-			if ((i % interval) == 0) {
-				/* Insert the traffic ep after tmp_ep */
-				USB_EP_Desc_t *ep_desc;
-				USB_SB_Desc_t *sb_desc;
-
-				dbg_intr("Inserting EP for epid %d", epid);
-
-				ep_desc = (USB_EP_Desc_t *)
-					kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
-				sb_desc = (USB_SB_Desc_t *)
-					kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
-				assert(ep_desc != NULL);
-				CHECK_ALIGN(ep_desc);
-				assert(sb_desc != NULL);
-
-				ep_desc->sub = virt_to_phys(sb_desc);
-				ep_desc->hw_len = 0;
-				ep_desc->command = (IO_FIELD(USB_EP_command, epid, epid) |
-						    IO_STATE(USB_EP_command, enable, yes));
-
-
-				/* Round upwards the number of packets of size maxlen
-				   that this SB descriptor should receive. */
-				sb_desc->sw_len = urb->transfer_buffer_length ?
-					(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
-				sb_desc->next = 0;
-				sb_desc->buf = 0;
-				sb_desc->command =
-					(IO_FIELD(USB_SB_command, rem, urb->transfer_buffer_length % maxlen) |
-					 IO_STATE(USB_SB_command, tt, in) |
-					 IO_STATE(USB_SB_command, eot, yes) |
-					 IO_STATE(USB_SB_command, eol, yes));
-
-				ep_desc->next = tmp_ep->next;
-				tmp_ep->next = virt_to_phys(ep_desc);
-			}
-			i++;
-		}
-		tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next);
-	} while (tmp_ep != first_ep);
-
-
-	/* Note that first_sb/last_sb doesn't apply to interrupt traffic. */
-	urb_priv->epid = epid;
-
-	/* We start the DMA sub channel without checking if it's running or not, because:
-	   1) If it's already running, issuing the start command is a nop.
-	   2) We avoid a test-and-set race condition. */
-	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
-
-	DBFEXIT;
-}
-
-
-
-static void etrax_usb_complete_intr_urb(struct urb *urb, int status)
-{
-	etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	int epid = urb_priv->epid;
-
-	DBFENTER;
-
-	if (status)
-		warn("Completing intr urb with status %d.", status);
-
-	dbg_intr("Completing intr epid %d, urb 0x%lx", epid, (unsigned long)urb);
-
-	urb->status = status;
-	urb->actual_length = urb_priv->rx_offset;
-
-	dbg_intr("interrupt urb->actual_length = %d", urb->actual_length);
-
-	/* We let any non-zero status from the layer above have precedence. */
-	if (status == 0) {
-		/* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's max length)
-		   is to be treated as an error. */
-		if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-			if (urb->actual_length !=
-			    usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) {
-				urb->status = -EREMOTEIO;
-			}
-		}
-	}
-
-	/* The driver will resubmit the URB so we need to remove it first */
-        etrax_usb_unlink_urb(urb, 0);
-	if (urb->complete) {
-		urb->complete(urb, NULL);
-	}
-
-	DBFEXIT;
-}
-
-
-static int etrax_usb_submit_isoc_urb(struct urb *urb)
-{
-	int epid;
-	unsigned long flags;
-
-	DBFENTER;
-
-	dbg_isoc("Submitting isoc urb = 0x%lx", (unsigned long)urb);
-
-	/* Epid allocation, empty check and list add must be protected.
-	   Read about this in etrax_usb_submit_ctrl_urb. */
-
-	spin_lock_irqsave(&urb_list_lock, flags);
-	/* Is there an active epid for this urb ? */
-	epid = etrax_usb_setup_epid(urb);
-	if (epid == -1) {
-		DBFEXIT;
-		spin_unlock_irqrestore(&urb_list_lock, flags);
-		return -ENOMEM;
-	}
-
-	/* Ok, now we got valid endpoint, lets insert some traffic */
-
-	urb->status = -EINPROGRESS;
-
-	/* Find the last urb in the URB_List and add this urb after that one.
-	   Also add the traffic, that is do an etrax_usb_add_to_isoc_sb_list.  This
-	   is important to make this in "real time" since isochronous traffic is
-	   time sensitive. */
-
-	dbg_isoc("Adding isoc urb to (possibly empty) list");
-	urb_list_add(urb, epid);
-	etrax_usb_add_to_isoc_sb_list(urb, epid);
-	spin_unlock_irqrestore(&urb_list_lock, flags);
-
-	DBFEXIT;
-
-	return 0;
-}
-
-static void etrax_usb_check_error_isoc_ep(const int epid)
-{
-	unsigned long int flags;
-	int error_code;
-	__u32 r_usb_ept_data;
-
-	/* We can't read R_USB_EPID_ATTN here since it would clear the iso_eof,
-	   bulk_eot and epid_attn interrupts.  So we just check the status of
-	   the epid without testing if for it in R_USB_EPID_ATTN. */
-
-
-	save_flags(flags);
-	cli();
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-	nop();
-	/* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO
-	   registers, they are located at the same address and are of the same size.
-	   In other words, this read should be ok for isoc also. */
-	r_usb_ept_data = *R_USB_EPT_DATA;
-	restore_flags(flags);
-
-	error_code = IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data);
-
-	if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) {
-		warn("Hold was set for epid %d.", epid);
-		return;
-	}
-
-	if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA_ISO, error_code, no_error)) {
-
-		/* This indicates that the SB list of the ept was completed before
-		   new data was appended to it.  This is not an error, but indicates
-		   large system or USB load and could possibly cause trouble for
-		   very timing sensitive USB device drivers so we log it.
-		*/
-		info("Isoc. epid %d disabled with no error", epid);
-		return;
-
-	} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA_ISO, error_code, stall)) {
-		/* Not really a protocol error, just says that the endpoint gave
-		   a stall response. Note that error_code cannot be stall for isoc. */
-		panic("Isoc traffic cannot stall");
-
-	} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA_ISO, error_code, bus_error)) {
-		/* Two devices responded to a transaction request. Must be resolved
-		   by software. FIXME: Reset ports? */
-		panic("Bus error for epid %d."
-		      " Two devices responded to transaction request",
-		      epid);
-
-	} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) {
-		/* DMA overrun or underrun. */
-		warn("Buffer overrun/underrun for epid %d. DMA too busy?", epid);
-
-		/* It seems that error_code = buffer_error in
-		   R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS
-		   are the same error. */
-	}
-}
-
-
-static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid)
-{
-
-	int i = 0;
-
-	etrax_urb_priv_t *urb_priv;
-	USB_SB_Desc_t *prev_sb_desc,  *next_sb_desc, *temp_sb_desc;
-
-	DBFENTER;
-
-	prev_sb_desc = next_sb_desc = temp_sb_desc = NULL;
-
-	urb_priv = kzalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC);
-	assert(urb_priv != NULL);
-
-	urb->hcpriv = urb_priv;
-	urb_priv->epid = epid;
-
-	if (usb_pipeout(urb->pipe)) {
-
-		if (urb->number_of_packets == 0) panic("etrax_usb_add_to_isoc_sb_list 0 packets\n");
-
-		dbg_isoc("Transfer for epid %d is OUT", epid);
-		dbg_isoc("%d packets in URB", urb->number_of_packets);
-
-		/* Create one SB descriptor for each packet and link them together. */
-		for (i = 0; i < urb->number_of_packets; i++) {
-			if (!urb->iso_frame_desc[i].length)
-				continue;
-
-			next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC);
-			assert(next_sb_desc != NULL);
-
-			if (urb->iso_frame_desc[i].length > 0) {
-
-				next_sb_desc->command = (IO_STATE(USB_SB_command, tt, out) |
-							 IO_STATE(USB_SB_command, eot, yes));
-
-				next_sb_desc->sw_len = urb->iso_frame_desc[i].length;
-				next_sb_desc->buf = virt_to_phys((char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset);
-
-				/* Check if full length transfer. */
-				if (urb->iso_frame_desc[i].length ==
-				    usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) {
-					next_sb_desc->command |= IO_STATE(USB_SB_command, full, yes);
-				}
-			} else {
-				dbg_isoc("zero len packet");
-				next_sb_desc->command = (IO_FIELD(USB_SB_command, rem, 0) |
-							 IO_STATE(USB_SB_command, tt, zout) |
-							 IO_STATE(USB_SB_command, eot, yes) |
-							 IO_STATE(USB_SB_command, full, yes));
-
-				next_sb_desc->sw_len = 1;
-				next_sb_desc->buf = virt_to_phys(&zout_buffer[0]);
-			}
-
-			/* First SB descriptor that belongs to this urb */
-			if (i == 0)
-				urb_priv->first_sb = next_sb_desc;
-			else
-				prev_sb_desc->next = virt_to_phys(next_sb_desc);
-
-			prev_sb_desc = next_sb_desc;
-		}
-
-		next_sb_desc->command |= (IO_STATE(USB_SB_command, intr, yes) |
-					  IO_STATE(USB_SB_command, eol, yes));
-		next_sb_desc->next = 0;
-		urb_priv->last_sb = next_sb_desc;
-
-	} else if (usb_pipein(urb->pipe)) {
-
-		dbg_isoc("Transfer for epid %d is IN", epid);
-		dbg_isoc("transfer_buffer_length = %d", urb->transfer_buffer_length);
-		dbg_isoc("rem is calculated to %d", urb->iso_frame_desc[urb->number_of_packets - 1].length);
-
-		/* Note that in descriptors for periodic traffic are not consumed. This means that
-		   the USB controller never propagates in the SB list. In other words, if there already
-		   is an SB descriptor in the list for this EP we don't have to do anything. */
-		if (TxIsocEPList[epid].sub == 0) {
-			dbg_isoc("Isoc traffic not already running, allocating SB");
-
-			next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC);
-			assert(next_sb_desc != NULL);
-
-			next_sb_desc->command = (IO_STATE(USB_SB_command, tt, in) |
-						 IO_STATE(USB_SB_command, eot, yes) |
-						 IO_STATE(USB_SB_command, eol, yes));
-
-			next_sb_desc->next = 0;
-			next_sb_desc->sw_len = 1; /* Actual number of packets is not relevant
-						     for periodic in traffic as long as it is more
-						     than zero.  Set to 1 always. */
-			next_sb_desc->buf = 0;
-
-			/* The rem field is don't care for isoc traffic, so we don't set it. */
-
-			/* Only one SB descriptor that belongs to this urb. */
-			urb_priv->first_sb = next_sb_desc;
-			urb_priv->last_sb = next_sb_desc;
-
-		} else {
-
-			dbg_isoc("Isoc traffic already running, just setting first/last_sb");
-
-			/* Each EP for isoc in will have only one SB descriptor, setup when submitting the
-			   already active urb. Note that even though we may have several first_sb/last_sb
-			   pointing at the same SB descriptor, they are freed only once (when the list has
-			   become empty). */
-			urb_priv->first_sb = phys_to_virt(TxIsocEPList[epid].sub);
-			urb_priv->last_sb = phys_to_virt(TxIsocEPList[epid].sub);
-			return;
-		}
-
-	}
-
-	/* Find the spot to insert this urb and add it. */
-	if (TxIsocEPList[epid].sub == 0) {
-		/* First SB descriptor inserted in this list (in or out). */
-		dbg_isoc("Inserting SB desc first in list");
-		TxIsocEPList[epid].hw_len = 0;
-		TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb);
-
-	} else {
-		/* Isochronous traffic is already running, insert new traffic last (only out). */
-		dbg_isoc("Inserting SB desc last in list");
-		temp_sb_desc = phys_to_virt(TxIsocEPList[epid].sub);
-		while ((temp_sb_desc->command & IO_MASK(USB_SB_command, eol)) !=
-		       IO_STATE(USB_SB_command, eol, yes)) {
-			assert(temp_sb_desc->next);
-			temp_sb_desc = phys_to_virt(temp_sb_desc->next);
-		}
-		dbg_isoc("Appending list on desc 0x%p", temp_sb_desc);
-
-		/* Next pointer must be set before eol is removed. */
-		temp_sb_desc->next = virt_to_phys(urb_priv->first_sb);
-		/* Clear the previous end of list flag since there is a new in the
-		   added SB descriptor list. */
-		temp_sb_desc->command &= ~IO_MASK(USB_SB_command, eol);
-
-		if (!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) {
-			/* 8.8.5 in Designer's Reference says we should check for and correct
-			   any errors in the EP here.  That should not be necessary if epid_attn
-			   is handled correctly, so we assume all is ok. */
-			dbg_isoc("EP disabled");
-			etrax_usb_check_error_isoc_ep(epid);
-
-			/* The SB list was exhausted. */
-			if (virt_to_phys(urb_priv->last_sb) != TxIsocEPList[epid].sub) {
-				/* The new sublist did not get processed before the EP was
-				   disabled.  Setup the EP again. */
-				dbg_isoc("Set EP sub to new list");
-				TxIsocEPList[epid].hw_len = 0;
-				TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb);
-			}
-		}
-	}
-
-	if (urb->transfer_flags & URB_ISO_ASAP) {
-		/* The isoc transfer should be started as soon as possible. The start_frame
-		   field is a return value if URB_ISO_ASAP was set. Comparing R_USB_FM_NUMBER
-		   with a USB Chief trace shows that the first isoc IN token is sent 2 frames
-		   later. I'm not sure how this affects usage of the start_frame field by the
-		   device driver, or how it affects things when USB_ISO_ASAP is not set, so
-		   therefore there's no compensation for the 2 frame "lag" here. */
-		urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff);
-		TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-		urb_priv->urb_state = STARTED;
-		dbg_isoc("URB_ISO_ASAP set, urb->start_frame set to %d", urb->start_frame);
-	} else {
-		/* Not started yet. */
-		urb_priv->urb_state = NOT_STARTED;
-		dbg_isoc("urb_priv->urb_state set to NOT_STARTED");
-	}
-
-       /* We start the DMA sub channel without checking if it's running or not, because:
-	  1) If it's already running, issuing the start command is a nop.
-	  2) We avoid a test-and-set race condition. */
-	*R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);
-
-	DBFEXIT;
-}
-
-static void etrax_usb_complete_isoc_urb(struct urb *urb, int status)
-{
-	etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-	int epid = urb_priv->epid;
-	int auto_resubmit = 0;
-
-	DBFENTER;
-	dbg_isoc("complete urb 0x%p, status %d", urb, status);
-
-	if (status)
-		warn("Completing isoc urb with status %d.", status);
-
-	if (usb_pipein(urb->pipe)) {
-		int i;
-
-		/* Make that all isoc packets have status and length set before
-		   completing the urb. */
-		for (i = urb_priv->isoc_packet_counter; i < urb->number_of_packets; i++) {
-			urb->iso_frame_desc[i].actual_length = 0;
-			urb->iso_frame_desc[i].status = -EPROTO;
-		}
-
-		urb_list_del(urb, epid);
-
-		if (!list_empty(&urb_list[epid])) {
-			((etrax_urb_priv_t *)(urb_list_first(epid)->hcpriv))->urb_state = STARTED;
-		} else {
-			unsigned long int flags;
-			if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
-				/* The EP was enabled, disable it and wait. */
-				TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
-
-				/* Ah, the luxury of busy-wait. */
-				while (*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid]));
-			}
-
-			etrax_remove_from_sb_list(urb);
-			TxIsocEPList[epid].sub = 0;
-			TxIsocEPList[epid].hw_len = 0;
-
-			save_flags(flags);
-			cli();
-			etrax_usb_free_epid(epid);
-			restore_flags(flags);
-		}
-
-		urb->hcpriv = 0;
-		kfree(urb_priv);
-
-		/* Release allocated bandwidth. */
-		usb_release_bandwidth(urb->dev, urb, 0);
-	} else if (usb_pipeout(urb->pipe)) {
-		int freed_descr;
-
-		dbg_isoc("Isoc out urb complete 0x%p", urb);
-
-		/* Update the urb list. */
-		urb_list_del(urb, epid);
-
-		freed_descr = etrax_remove_from_sb_list(urb);
-		dbg_isoc("freed %d descriptors of %d packets", freed_descr, urb->number_of_packets);
-		assert(freed_descr == urb->number_of_packets);
-		urb->hcpriv = 0;
-		kfree(urb_priv);
-
-		/* Release allocated bandwidth. */
-		usb_release_bandwidth(urb->dev, urb, 0);
-	}
-
-	urb->status = status;
-	if (urb->complete) {
-		urb->complete(urb, NULL);
-	}
-
-	if (auto_resubmit) {
-		/* Check that urb was not unlinked by the complete callback. */
-		if (__urb_list_entry(urb, epid)) {
-			/* Move this one down the list. */
-			urb_list_move_last(urb, epid);
-
-			/* Mark the now first urb as started (may already be). */
-			((etrax_urb_priv_t *)(urb_list_first(epid)->hcpriv))->urb_state = STARTED;
-
-			/* Must set this to 0 since this urb is still active after
-			   completion. */
-			urb_priv->isoc_packet_counter = 0;
-		} else {
-			warn("(ISOC) automatic resubmit urb 0x%p removed by complete.", urb);
-		}
-	}
-
-	DBFEXIT;
-}
-
-static void etrax_usb_complete_urb(struct urb *urb, int status)
-{
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_BULK:
-		etrax_usb_complete_bulk_urb(urb, status);
-		break;
-	case PIPE_CONTROL:
-		etrax_usb_complete_ctrl_urb(urb, status);
-		break;
-	case PIPE_INTERRUPT:
-		etrax_usb_complete_intr_urb(urb, status);
-		break;
-	case PIPE_ISOCHRONOUS:
-		etrax_usb_complete_isoc_urb(urb, status);
-		break;
-	default:
-		err("Unknown pipetype");
-	}
-}
-
-
-
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc)
-{
-	usb_interrupt_registers_t *reg;
-	unsigned long flags;
-	__u32 irq_mask;
-	__u8 status;
-	__u32 epid_attn;
-	__u16 port_status_1;
-	__u16 port_status_2;
-	__u32 fm_number;
-
-	DBFENTER;
-
-	/* Read critical registers into local variables, do kmalloc afterwards. */
-	save_flags(flags);
-	cli();
-
-	irq_mask = *R_USB_IRQ_MASK_READ;
-	/* Reading R_USB_STATUS clears the ctl_status interrupt. Note that R_USB_STATUS
-	   must be read before R_USB_EPID_ATTN since reading the latter clears the
-	   ourun and perror fields of R_USB_STATUS. */
-	status = *R_USB_STATUS;
-
-	/* Reading R_USB_EPID_ATTN clears the iso_eof, bulk_eot and epid_attn interrupts. */
-	epid_attn = *R_USB_EPID_ATTN;
-
-	/* Reading R_USB_RH_PORT_STATUS_1 and R_USB_RH_PORT_STATUS_2 clears the
-	   port_status interrupt. */
-	port_status_1 = *R_USB_RH_PORT_STATUS_1;
-	port_status_2 = *R_USB_RH_PORT_STATUS_2;
-
-	/* Reading R_USB_FM_NUMBER clears the sof interrupt. */
-	/* Note: the lower 11 bits contain the actual frame number, sent with each sof. */
-	fm_number = *R_USB_FM_NUMBER;
-
-	restore_flags(flags);
-
-	reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, GFP_ATOMIC);
-
-	assert(reg != NULL);
-
-	reg->hc = (etrax_hc_t *)vhc;
-
-	/* Now put register values into kmalloc'd area. */
-	reg->r_usb_irq_mask_read = irq_mask;
-	reg->r_usb_status = status;
-	reg->r_usb_epid_attn = epid_attn;
-	reg->r_usb_rh_port_status_1 = port_status_1;
-	reg->r_usb_rh_port_status_2 = port_status_2;
-	reg->r_usb_fm_number = fm_number;
-
-        INIT_WORK(&reg->usb_bh, etrax_usb_hc_interrupt_bottom_half, reg);
-        schedule_work(&reg->usb_bh);
-
-	DBFEXIT;
-
-        return IRQ_HANDLED;
-}
-
-static void etrax_usb_hc_interrupt_bottom_half(void *data)
-{
-	usb_interrupt_registers_t *reg = (usb_interrupt_registers_t *)data;
-	__u32 irq_mask = reg->r_usb_irq_mask_read;
-
-	DBFENTER;
-
-	/* Interrupts are handled in order of priority. */
-	if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, epid_attn)) {
-		etrax_usb_hc_epid_attn_interrupt(reg);
-	}
-	if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {
-		etrax_usb_hc_port_status_interrupt(reg);
-	}
-	if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, ctl_status)) {
-		etrax_usb_hc_ctl_status_interrupt(reg);
-	}
-	if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, iso_eof)) {
-		etrax_usb_hc_isoc_eof_interrupt();
-	}
-	if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, bulk_eot)) {
-		/* Update/restart the bulk start timer since obviously the channel is running. */
-		mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);
-		/* Update/restart the bulk eot timer since we just received an bulk eot interrupt. */
-		mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);
-
-		etrax_usb_hc_bulk_eot_interrupt(0);
-	}
-
-	kmem_cache_free(top_half_reg_cache, reg);
-
-	DBFEXIT;
-}
-
-
-void etrax_usb_hc_isoc_eof_interrupt(void)
-{
-	struct urb *urb;
-	etrax_urb_priv_t *urb_priv;
-	int epid;
-	unsigned long flags;
-
-	DBFENTER;
-
-	/* Do not check the invalid epid (it has a valid sub pointer). */
-	for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {
-
-		/* Do not check the invalid epid (it has a valid sub pointer). */
-		if ((epid == DUMMY_EPID) || (epid == INVALID_EPID))
-			continue;
-
-		/* Disable interrupts to block the isoc out descriptor interrupt handler
-		   from being called while the isoc EPID list is being checked.
-		*/
-		save_flags(flags);
-		cli();
-
-		if (TxIsocEPList[epid].sub == 0) {
-			/* Nothing here to see. */
-			restore_flags(flags);
-			continue;
-		}
-
-		/* Get the first urb (if any). */
-		urb = urb_list_first(epid);
-		if (urb == 0) {
-			warn("Ignoring NULL urb");
-			restore_flags(flags);
-			continue;
-		}
-		if (usb_pipein(urb->pipe)) {
-
-			/* Sanity check. */
-			assert(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);
-
-			urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-			assert(urb_priv);
-
-			if (urb_priv->urb_state == NOT_STARTED) {
-
-				/* If ASAP is not set and urb->start_frame is the current frame,
-				   start the transfer. */
-				if (!(urb->transfer_flags & URB_ISO_ASAP) &&
-				    (urb->start_frame == (*R_USB_FM_NUMBER & 0x7ff))) {
-
-					dbg_isoc("Enabling isoc IN EP descr for epid %d", epid);
-					TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-
-					/* This urb is now active. */
-					urb_priv->urb_state = STARTED;
-					continue;
-				}
-			}
-		}
-		restore_flags(flags);
-	}
-
-	DBFEXIT;
-
-}
-
-void etrax_usb_hc_bulk_eot_interrupt(int timer_induced)
-{
- 	int epid;
-
-	/* The technique is to run one urb at a time, wait for the eot interrupt at which
-	   point the EP descriptor has been disabled. */
-
-	DBFENTER;
-	dbg_bulk("bulk eot%s", timer_induced ? ", called by timer" : "");
-
-	for (epid = 0; epid < NBR_OF_EPIDS; epid++) {
-
-		if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) &&
-		    (TxBulkEPList[epid].sub != 0)) {
-
-			struct urb *urb;
-			etrax_urb_priv_t *urb_priv;
-			unsigned long flags;
-			__u32 r_usb_ept_data;
-
-			/* Found a disabled EP descriptor which has a non-null sub pointer.
-			   Verify that this ctrl EP descriptor got disabled no errors.
-			   FIXME: Necessary to check error_code? */
-			dbg_bulk("for epid %d?", epid);
-
-			/* Get the first urb. */
-			urb = urb_list_first(epid);
-
-			/* FIXME: Could this happen for valid reasons? Why did it disappear? Because of
-			   wrong unlinking? */
-			if (!urb) {
-				warn("NULL urb for epid %d", epid);
-				continue;
-			}
-
-			assert(urb);
-			urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-			assert(urb_priv);
-
-			/* Sanity checks. */
-			assert(usb_pipetype(urb->pipe) == PIPE_BULK);
-			if (phys_to_virt(TxBulkEPList[epid].sub) != urb_priv->last_sb) {
-				err("bulk endpoint got disabled before reaching last sb");
-			}
-
-			/* For bulk IN traffic, there seems to be a race condition between
-			   between the bulk eot and eop interrupts, or rather an uncertainty regarding
-			   the order in which they happen. Normally we expect the eop interrupt from
-			   DMA channel 9 to happen before the eot interrupt.
-
-			   Therefore, we complete the bulk IN urb in the rx interrupt handler instead. */
-
-			if (usb_pipein(urb->pipe)) {
-				dbg_bulk("in urb, continuing");
-				continue;
-			}
-
-			save_flags(flags);
-			cli();
-			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-			nop();
-			r_usb_ept_data = *R_USB_EPT_DATA;
-			restore_flags(flags);
-
-			if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==
-			    IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
-				/* This means that the endpoint has no error, is disabled
-				   and had inserted traffic, i.e. transfer successfully completed. */
-				etrax_usb_complete_bulk_urb(urb, 0);
-			} else {
-				/* Shouldn't happen. We expect errors to be caught by epid attention. */
-				err("Found disabled bulk EP desc, error_code != no_error");
-			}
-		}
-	}
-
-	/* Normally, we should find (at least) one disabled EP descriptor with a valid sub pointer.
-	   However, because of the uncertainty in the deliverance of the eop/eot interrupts, we may
-	   not.  Also, we might find two disabled EPs when handling an eot interrupt, and then find
-	   none the next time. */
-
-	DBFEXIT;
-
-}
-
-void etrax_usb_hc_epid_attn_interrupt(usb_interrupt_registers_t *reg)
-{
-	/* This function handles the epid attention interrupt.  There are a variety of reasons
-	   for this interrupt to happen (Designer's Reference, p. 8 - 22 for the details):
-
-	   invalid ep_id  - Invalid epid in an EP (EP disabled).
-	   stall	  - Not strictly an error condition (EP disabled).
-	   3rd error      - Three successive transaction errors  (EP disabled).
-	   buffer ourun   - Buffer overrun or underrun (EP disabled).
-	   past eof1      - Intr or isoc transaction proceeds past EOF1.
-	   near eof       - Intr or isoc transaction would not fit inside the frame.
-	   zout transfer  - If zout transfer for a bulk endpoint (EP disabled).
-	   setup transfer - If setup transfer for a non-ctrl endpoint (EP disabled). */
-
-	int epid;
-
-
-	DBFENTER;
-
-	assert(reg != NULL);
-
-	/* Note that we loop through all epids. We still want to catch errors for
-	   the invalid one, even though we might handle them differently. */
-	for (epid = 0; epid < NBR_OF_EPIDS; epid++) {
-
-		if (test_bit(epid, (void *)&reg->r_usb_epid_attn)) {
-
-			struct urb *urb;
-			__u32 r_usb_ept_data;
-			unsigned long flags;
-			int error_code;
-
-			save_flags(flags);
-			cli();
-			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
-			nop();
-			/* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO
-			   registers, they are located at the same address and are of the same size.
-			   In other words, this read should be ok for isoc also. */
-			r_usb_ept_data = *R_USB_EPT_DATA;
-			restore_flags(flags);
-
-			/* First some sanity checks. */
-			if (epid == INVALID_EPID) {
-				/* FIXME: What if it became disabled? Could seriously hurt interrupt
-				   traffic. (Use do_intr_recover.) */
-				warn("Got epid_attn for INVALID_EPID (%d).", epid);
-				err("R_USB_EPT_DATA = 0x%x", r_usb_ept_data);
-				err("R_USB_STATUS = 0x%x", reg->r_usb_status);
-				continue;
-			} else 	if (epid == DUMMY_EPID) {
-				/* We definitely don't care about these ones. Besides, they are
-				   always disabled, so any possible disabling caused by the
-				   epid attention interrupt is irrelevant. */
-				warn("Got epid_attn for DUMMY_EPID (%d).", epid);
-				continue;
-			}
-
-			/* Get the first urb in the urb list for this epid. We blatantly assume
-			   that only the first urb could have caused the epid attention.
-			   (For bulk and ctrl, only one urb is active at any one time. For intr
-			   and isoc we remove them once they are completed.) */
-			urb = urb_list_first(epid);
-
-			if (urb == NULL) {
-				err("Got epid_attn for epid %i with no urb.", epid);
-				err("R_USB_EPT_DATA = 0x%x", r_usb_ept_data);
-				err("R_USB_STATUS = 0x%x", reg->r_usb_status);
-				continue;
-			}
-
-			switch (usb_pipetype(urb->pipe)) {
-			case PIPE_BULK:
-				warn("Got epid attn for bulk endpoint, epid %d", epid);
-				break;
-			case PIPE_CONTROL:
-				warn("Got epid attn for control endpoint, epid %d", epid);
-				break;
-			case PIPE_INTERRUPT:
-				warn("Got epid attn for interrupt endpoint, epid %d", epid);
-				break;
-			case PIPE_ISOCHRONOUS:
-				warn("Got epid attn for isochronous endpoint, epid %d", epid);
-				break;
-			}
-
-			if (usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) {
-				if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) {
-					warn("Hold was set for epid %d.", epid);
-					continue;
-				}
-			}
-
-			/* Even though error_code occupies bits 22 - 23 in both R_USB_EPT_DATA and
-			   R_USB_EPT_DATA_ISOC, we separate them here so we don't forget in other places. */
-			if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-				error_code = IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data);
-			} else {
-				error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data);
-			}
-
-			/* Using IO_STATE_VALUE on R_USB_EPT_DATA should be ok for isoc also. */
-			if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
-
-				/* Isoc traffic doesn't have error_count_in/error_count_out. */
-				if ((usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) &&
-				    (IO_EXTRACT(R_USB_EPT_DATA, error_count_in, r_usb_ept_data) == 3 ||
-				     IO_EXTRACT(R_USB_EPT_DATA, error_count_out, r_usb_ept_data) == 3)) {
-					/* 3rd error. */
-					warn("3rd error for epid %i", epid);
-					etrax_usb_complete_urb(urb, -EPROTO);
-
-				} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
-
-					warn("Perror for epid %d", epid);
-
-					if (!(r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, valid))) {
-						/* invalid ep_id */
-						panic("Perror because of invalid epid."
-						      " Deconfigured too early?");
-					} else {
-						/* past eof1, near eof, zout transfer, setup transfer */
-
-						/* Dump the urb and the relevant EP descriptor list. */
-
-						__dump_urb(urb);
-						__dump_ept_data(epid);
-						__dump_ep_list(usb_pipetype(urb->pipe));
-
-						panic("Something wrong with DMA descriptor contents."
-						      " Too much traffic inserted?");
-					}
-				} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
-					/* buffer ourun */
-					panic("Buffer overrun/underrun for epid %d. DMA too busy?", epid);
-				}
-
-			} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, stall)) {
-				/* Not really a protocol error, just says that the endpoint gave
-				   a stall response. Note that error_code cannot be stall for isoc. */
-				if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-					panic("Isoc traffic cannot stall");
-				}
-
-				warn("Stall for epid %d", epid);
-				etrax_usb_complete_urb(urb, -EPIPE);
-
-			} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, bus_error)) {
-				/* Two devices responded to a transaction request. Must be resolved
-				   by software. FIXME: Reset ports? */
-				panic("Bus error for epid %d."
-				      " Two devices responded to transaction request",
-				      epid);
-
-			} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) {
-				/* DMA overrun or underrun. */
-				warn("Buffer overrun/underrun for epid %d. DMA too busy?", epid);
-
-				/* It seems that error_code = buffer_error in
-				   R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS
-				   are the same error. */
-				etrax_usb_complete_urb(urb, -EPROTO);
-			}
-		}
-	}
-
-	DBFEXIT;
-
-}
-
-void etrax_usb_bulk_start_timer_func(unsigned long dummy)
-{
-
-	/* We might enable an EP descriptor behind the current DMA position when it's about
-	   to decide that there are no more bulk traffic and it should stop the bulk channel.
-	   Therefore we periodically check if the bulk channel is stopped and there is an
-	   enabled bulk EP descriptor, in which case we start the bulk channel. */
-	dbg_bulk("bulk_start_timer timed out.");
-
-	if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {
-		int epid;
-
-		dbg_bulk("Bulk DMA channel not running.");
-
-		for (epid = 0; epid < NBR_OF_EPIDS; epid++) {
-			if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
-				dbg_bulk("Found enabled EP for epid %d, starting bulk channel.\n",
-					 epid);
-				*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
-
-				/* Restart the bulk eot timer since we just started the bulk channel. */
-				mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);
-
-				/* No need to search any further. */
-				break;
-			}
-		}
-	} else {
-		dbg_bulk("Bulk DMA channel running.");
-	}
-}
-
-void etrax_usb_hc_port_status_interrupt(usb_interrupt_registers_t *reg)
-{
-	etrax_hc_t *hc = reg->hc;
-	__u16 r_usb_rh_port_status_1 = reg->r_usb_rh_port_status_1;
-	__u16 r_usb_rh_port_status_2 = reg->r_usb_rh_port_status_2;
-
-	DBFENTER;
-
-	/* The Etrax RH does not include a wPortChange register, so this has to be handled in software
-	   (by saving the old port status value for comparison when the port status interrupt happens).
-	   See section 11.16.2.6.2 in the USB 1.1 spec for details. */
-
-	dbg_rh("hc->rh.prev_wPortStatus_1 = 0x%x", hc->rh.prev_wPortStatus_1);
-	dbg_rh("hc->rh.prev_wPortStatus_2 = 0x%x", hc->rh.prev_wPortStatus_2);
-	dbg_rh("r_usb_rh_port_status_1 = 0x%x", r_usb_rh_port_status_1);
-	dbg_rh("r_usb_rh_port_status_2 = 0x%x", r_usb_rh_port_status_2);
-
-	/* C_PORT_CONNECTION is set on any transition. */
-	hc->rh.wPortChange_1 |=
-		((r_usb_rh_port_status_1 & (1 << RH_PORT_CONNECTION)) !=
-		 (hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_CONNECTION))) ?
-		(1 << RH_PORT_CONNECTION) : 0;
-
-	hc->rh.wPortChange_2 |=
-		((r_usb_rh_port_status_2 & (1 << RH_PORT_CONNECTION)) !=
-		 (hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_CONNECTION))) ?
-		(1 << RH_PORT_CONNECTION) : 0;
-
-	/* C_PORT_ENABLE is _only_ set on a one to zero transition, i.e. when
-	   the port is disabled, not when it's enabled. */
-	hc->rh.wPortChange_1 |=
-		((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_ENABLE))
-		 && !(r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?
-		(1 << RH_PORT_ENABLE) : 0;
-
-	hc->rh.wPortChange_2 |=
-		((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_ENABLE))
-		 && !(r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?
-		(1 << RH_PORT_ENABLE) : 0;
-
-	/* C_PORT_SUSPEND is set to one when the device has transitioned out
-	   of the suspended state, i.e. when suspend goes from one to zero. */
-	hc->rh.wPortChange_1 |=
-		((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_SUSPEND))
-		 && !(r_usb_rh_port_status_1 & (1 << RH_PORT_SUSPEND))) ?
-		(1 << RH_PORT_SUSPEND) : 0;
-
-	hc->rh.wPortChange_2 |=
-		((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_SUSPEND))
-		 && !(r_usb_rh_port_status_2 & (1 << RH_PORT_SUSPEND))) ?
-		(1 << RH_PORT_SUSPEND) : 0;
-
-
-	/* C_PORT_RESET is set when reset processing on this port is complete. */
-	hc->rh.wPortChange_1 |=
-		((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_RESET))
-		 && !(r_usb_rh_port_status_1 & (1 << RH_PORT_RESET))) ?
-		(1 << RH_PORT_RESET) : 0;
-
-	hc->rh.wPortChange_2 |=
-		((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_RESET))
-		 && !(r_usb_rh_port_status_2 & (1 << RH_PORT_RESET))) ?
-		(1 << RH_PORT_RESET) : 0;
-
-	/* Save the new values for next port status change. */
-	hc->rh.prev_wPortStatus_1 = r_usb_rh_port_status_1;
-	hc->rh.prev_wPortStatus_2 = r_usb_rh_port_status_2;
-
-	dbg_rh("hc->rh.wPortChange_1 set to 0x%x", hc->rh.wPortChange_1);
-	dbg_rh("hc->rh.wPortChange_2 set to 0x%x", hc->rh.wPortChange_2);
-
-	DBFEXIT;
-
-}
-
-void etrax_usb_hc_ctl_status_interrupt(usb_interrupt_registers_t *reg)
-{
-	DBFENTER;
-
-	/* FIXME: What should we do if we get ourun or perror? Dump the EP and SB
-	   list for the corresponding epid? */
-	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
-		panic("USB controller got ourun.");
-	}
-	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
-
-		/* Before, etrax_usb_do_intr_recover was called on this epid if it was
-		   an interrupt pipe. I don't see how re-enabling all EP descriptors
-		   will help if there was a programming error. */
-		panic("USB controller got perror.");
-	}
-
-	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, device_mode)) {
-		/* We should never operate in device mode. */
-		panic("USB controller in device mode.");
-	}
-
-	/* These if-statements could probably be nested. */
-	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, host_mode)) {
-		info("USB controller in host mode.");
-	}
-	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, started)) {
-		info("USB controller started.");
-	}
-	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, running)) {
-		info("USB controller running.");
-	}
-
-	DBFEXIT;
-
-}
-
-
-static int etrax_rh_submit_urb(struct urb *urb)
-{
-	struct usb_device *usb_dev = urb->dev;
-	etrax_hc_t *hc = usb_dev->bus->hcpriv;
-	unsigned int pipe = urb->pipe;
-	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
-	void *data = urb->transfer_buffer;
-	int leni = urb->transfer_buffer_length;
-	int len = 0;
-	int stat = 0;
-
-	__u16 bmRType_bReq;
-	__u16 wValue;
-	__u16 wIndex;
-	__u16 wLength;
-
-	DBFENTER;
-
-	/* FIXME: What is this interrupt urb that is sent to the root hub? */
-	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
-		dbg_rh("Root-Hub submit IRQ: every %d ms", urb->interval);
-		hc->rh.urb = urb;
-		hc->rh.send = 1;
-		/* FIXME: We could probably remove this line since it's done
-		   in etrax_rh_init_int_timer. (Don't remove it from
-		   etrax_rh_init_int_timer though.) */
-		hc->rh.interval = urb->interval;
-		etrax_rh_init_int_timer(urb);
-		DBFEXIT;
-
-		return 0;
-	}
-
-	bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8);
-	wValue = le16_to_cpu(cmd->wValue);
-	wIndex = le16_to_cpu(cmd->wIndex);
-	wLength = le16_to_cpu(cmd->wLength);
-
-	dbg_rh("bmRType_bReq : 0x%04x (%d)", bmRType_bReq, bmRType_bReq);
-	dbg_rh("wValue       : 0x%04x (%d)", wValue, wValue);
-	dbg_rh("wIndex       : 0x%04x (%d)", wIndex, wIndex);
-	dbg_rh("wLength      : 0x%04x (%d)", wLength, wLength);
-
-	switch (bmRType_bReq) {
-
-		/* Request Destination:
-		   without flags: Device,
-		   RH_INTERFACE: interface,
-		   RH_ENDPOINT: endpoint,
-		   RH_CLASS means HUB here,
-		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
-		 */
-
-	case RH_GET_STATUS:
-		*(__u16 *) data = cpu_to_le16 (1);
-		OK (2);
-
-	case RH_GET_STATUS | RH_INTERFACE:
-		*(__u16 *) data = cpu_to_le16 (0);
-		OK (2);
-
-	case RH_GET_STATUS | RH_ENDPOINT:
-		*(__u16 *) data = cpu_to_le16 (0);
-		OK (2);
-
-	case RH_GET_STATUS | RH_CLASS:
-		*(__u32 *) data = cpu_to_le32 (0);
-		OK (4);		/* hub power ** */
-
-	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-		if (wIndex == 1) {
-			*((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_1);
-			*((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_1);
-		} else if (wIndex == 2) {
-			*((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_2);
-			*((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_2);
-		} else {
-			dbg_rh("RH_GET_STATUS whith invalid wIndex!");
-			OK(0);
-		}
-
-		OK(4);
-
-	case RH_CLEAR_FEATURE | RH_ENDPOINT:
-		switch (wValue) {
-		case (RH_ENDPOINT_STALL):
-			OK (0);
-		}
-		break;
-
-	case RH_CLEAR_FEATURE | RH_CLASS:
-		switch (wValue) {
-		case (RH_C_HUB_OVER_CURRENT):
-			OK (0);	/* hub power over current ** */
-		}
-		break;
-
-	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-		switch (wValue) {
-		case (RH_PORT_ENABLE):
-			if (wIndex == 1) {
-
-				dbg_rh("trying to do disable port 1");
-
-				*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes);
-
-				while (hc->rh.prev_wPortStatus_1 &
-				       IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes));
-				*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);
-				dbg_rh("Port 1 is disabled");
-
-			} else if (wIndex == 2) {
-
-				dbg_rh("trying to do disable port 2");
-
-				*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes);
-
-				while (hc->rh.prev_wPortStatus_2 &
-				       IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes));
-				*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);
-				dbg_rh("Port 2 is disabled");
-
-			} else {
-				dbg_rh("RH_CLEAR_FEATURE->RH_PORT_ENABLE "
-				       "with invalid wIndex == %d!", wIndex);
-			}
-
-			OK (0);
-		case (RH_PORT_SUSPEND):
-			/* Opposite to suspend should be resume, so we'll do a resume. */
-			/* FIXME: USB 1.1, 11.16.2.2 says:
-			   "Clearing the PORT_SUSPEND feature causes a host-initiated resume
-			   on the specified port. If the port is not in the Suspended state,
-			   the hub should treat this request as a functional no-operation."
-			   Shouldn't we check if the port is in a suspended state before
-			   resuming? */
-
-			/* Make sure the controller isn't busy. */
-			while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-			if (wIndex == 1) {
-				*R_USB_COMMAND =
-					IO_STATE(R_USB_COMMAND, port_sel, port1) |
-					IO_STATE(R_USB_COMMAND, port_cmd, resume) |
-					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
-			} else if (wIndex == 2) {
-				*R_USB_COMMAND =
-					IO_STATE(R_USB_COMMAND, port_sel, port2) |
-					IO_STATE(R_USB_COMMAND, port_cmd, resume) |
-					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
-			} else {
-				dbg_rh("RH_CLEAR_FEATURE->RH_PORT_SUSPEND "
-				       "with invalid wIndex == %d!", wIndex);
-			}
-
-			OK (0);
-		case (RH_PORT_POWER):
-			OK (0);	/* port power ** */
-		case (RH_C_PORT_CONNECTION):
-			if (wIndex == 1) {
-				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_CONNECTION);
-			} else if (wIndex == 2) {
-				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_CONNECTION);
-			} else {
-				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_CONNECTION "
-				       "with invalid wIndex == %d!", wIndex);
-			}
-
-			OK (0);
-		case (RH_C_PORT_ENABLE):
-			if (wIndex == 1) {
-				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_ENABLE);
-			} else if (wIndex == 2) {
-				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_ENABLE);
-			} else {
-				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_ENABLE "
-				       "with invalid wIndex == %d!", wIndex);
-			}
-			OK (0);
-		case (RH_C_PORT_SUSPEND):
-/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
-			OK (0);
-		case (RH_C_PORT_OVER_CURRENT):
-			OK (0);	/* port power over current ** */
-		case (RH_C_PORT_RESET):
-			if (wIndex == 1) {
-				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_RESET);
-			} else if (wIndex == 2) {
-				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_RESET);
-			} else {
-				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_RESET "
-				       "with invalid index == %d!", wIndex);
-			}
-
-			OK (0);
-
-		}
-		break;
-
-	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-		switch (wValue) {
-		case (RH_PORT_SUSPEND):
-
-			/* Make sure the controller isn't busy. */
-			while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-			if (wIndex == 1) {
-				*R_USB_COMMAND =
-					IO_STATE(R_USB_COMMAND, port_sel, port1) |
-					IO_STATE(R_USB_COMMAND, port_cmd, suspend) |
-					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
-			} else if (wIndex == 2) {
-				*R_USB_COMMAND =
-					IO_STATE(R_USB_COMMAND, port_sel, port2) |
-					IO_STATE(R_USB_COMMAND, port_cmd, suspend) |
-					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
-			} else {
-				dbg_rh("RH_SET_FEATURE->RH_PORT_SUSPEND "
-				       "with invalid wIndex == %d!", wIndex);
-			}
-
-			OK (0);
-		case (RH_PORT_RESET):
-			if (wIndex == 1) {
-
-			port_1_reset:
-				dbg_rh("Doing reset of port 1");
-
-				/* Make sure the controller isn't busy. */
-				while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-				*R_USB_COMMAND =
-					IO_STATE(R_USB_COMMAND, port_sel, port1) |
-					IO_STATE(R_USB_COMMAND, port_cmd, reset) |
-					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
-
-				/* We must wait at least 10 ms for the device to recover.
-				   15 ms should be enough. */
-				udelay(15000);
-
-				/* Wait for reset bit to go low (should be done by now). */
-				while (hc->rh.prev_wPortStatus_1 &
-				       IO_STATE(R_USB_RH_PORT_STATUS_1, reset, yes));
-
-				/* If the port status is
-				   1) connected and enabled then there is a device and everything is fine
-				   2) neither connected nor enabled then there is no device, also fine
-				   3) connected and not enabled then we try again
-				   (Yes, there are other port status combinations besides these.) */
-
-				if ((hc->rh.prev_wPortStatus_1 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) &&
-				    (hc->rh.prev_wPortStatus_1 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, no))) {
-					dbg_rh("Connected device on port 1, but port not enabled?"
-					       " Trying reset again.");
-					goto port_2_reset;
-				}
-
-				/* Diagnostic printouts. */
-				if ((hc->rh.prev_wPortStatus_1 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_1, connected, no)) &&
-				    (hc->rh.prev_wPortStatus_1 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, no))) {
-					dbg_rh("No connected device on port 1");
-				} else if ((hc->rh.prev_wPortStatus_1 &
-					    IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) &&
-					   (hc->rh.prev_wPortStatus_1 &
-					    IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes))) {
-					dbg_rh("Connected device on port 1, port 1 enabled");
-				}
-
-			} else if (wIndex == 2) {
-
-			port_2_reset:
-				dbg_rh("Doing reset of port 2");
-
-				/* Make sure the controller isn't busy. */
-				while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-				/* Issue the reset command. */
-				*R_USB_COMMAND =
-					IO_STATE(R_USB_COMMAND, port_sel, port2) |
-					IO_STATE(R_USB_COMMAND, port_cmd, reset) |
-					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
-
-				/* We must wait at least 10 ms for the device to recover.
-				   15 ms should be enough. */
-				udelay(15000);
-
-				/* Wait for reset bit to go low (should be done by now). */
-				while (hc->rh.prev_wPortStatus_2 &
-				       IO_STATE(R_USB_RH_PORT_STATUS_2, reset, yes));
-
-				/* If the port status is
-				   1) connected and enabled then there is a device and everything is fine
-				   2) neither connected nor enabled then there is no device, also fine
-				   3) connected and not enabled then we try again
-				   (Yes, there are other port status combinations besides these.) */
-
-				if ((hc->rh.prev_wPortStatus_2 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_2, connected, yes)) &&
-				    (hc->rh.prev_wPortStatus_2 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, no))) {
-					dbg_rh("Connected device on port 2, but port not enabled?"
-					       " Trying reset again.");
-					goto port_2_reset;
-				}
-
-				/* Diagnostic printouts. */
-				if ((hc->rh.prev_wPortStatus_2 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_2, connected, no)) &&
-				    (hc->rh.prev_wPortStatus_2 &
-				     IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, no))) {
-					dbg_rh("No connected device on port 2");
-				} else if ((hc->rh.prev_wPortStatus_2 &
-					    IO_STATE(R_USB_RH_PORT_STATUS_2, connected, yes)) &&
-					   (hc->rh.prev_wPortStatus_2 &
-					    IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes))) {
-					dbg_rh("Connected device on port 2, port 2 enabled");
-				}
-
-			} else {
-				dbg_rh("RH_SET_FEATURE->RH_PORT_RESET with invalid wIndex = %d", wIndex);
-			}
-
-			/* Make sure the controller isn't busy. */
-			while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-			/* If all enabled ports were disabled the host controller goes down into
-			   started mode, so we need to bring it back into the running state.
-			   (This is safe even if it's already in the running state.) */
-			*R_USB_COMMAND =
-				IO_STATE(R_USB_COMMAND, port_sel, nop) |
-				IO_STATE(R_USB_COMMAND, port_cmd, reset) |
-				IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
-
-			dbg_rh("...Done");
-			OK(0);
-
-		case (RH_PORT_POWER):
-			OK (0);	/* port power ** */
-		case (RH_PORT_ENABLE):
-			/* There is no port enable command in the host controller, so if the
-			   port is already enabled, we do nothing. If not, we reset the port
-			   (with an ugly goto). */
-
-			if (wIndex == 1) {
-				if (hc->rh.prev_wPortStatus_1 &
-				    IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, no)) {
-					goto port_1_reset;
-				}
-			} else if (wIndex == 2) {
-				if (hc->rh.prev_wPortStatus_2 &
-				    IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, no)) {
-					goto port_2_reset;
-				}
-			} else {
-				dbg_rh("RH_SET_FEATURE->RH_GET_STATUS with invalid wIndex = %d", wIndex);
-			}
-			OK (0);
-		}
-		break;
-
-	case RH_SET_ADDRESS:
-		hc->rh.devnum = wValue;
-		dbg_rh("RH address set to: %d", hc->rh.devnum);
-		OK (0);
-
-	case RH_GET_DESCRIPTOR:
-		switch ((wValue & 0xff00) >> 8) {
-		case (0x01):	/* device descriptor */
-			len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_dev_des), wLength));
-			memcpy (data, root_hub_dev_des, len);
-			OK (len);
-		case (0x02):	/* configuration descriptor */
-			len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength));
-			memcpy (data, root_hub_config_des, len);
-			OK (len);
-		case (0x03):	/* string descriptors */
-			len = usb_root_hub_string (wValue & 0xff,
-						   0xff, "ETRAX 100LX",
-						   data, wLength);
-			if (len > 0) {
-				OK(min(leni, len));
-			} else {
-				stat = -EPIPE;
-			}
-
-		}
-		break;
-
-	case RH_GET_DESCRIPTOR | RH_CLASS:
-		root_hub_hub_des[2] = hc->rh.numports;
-		len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
-		memcpy (data, root_hub_hub_des, len);
-		OK (len);
-
-	case RH_GET_CONFIGURATION:
-		*(__u8 *) data = 0x01;
-		OK (1);
-
-	case RH_SET_CONFIGURATION:
-		OK (0);
-
-	default:
-		stat = -EPIPE;
-	}
-
-	urb->actual_length = len;
-	urb->status = stat;
-	urb->dev = NULL;
-	if (urb->complete) {
-		urb->complete(urb, NULL);
-	}
-	DBFEXIT;
-
-	return 0;
-}
-
-static void
-etrax_usb_bulk_eot_timer_func(unsigned long dummy)
-{
-	/* Because of a race condition in the top half, we might miss a bulk eot.
-	   This timer "simulates" a bulk eot if we don't get one for a while, hopefully
-	   correcting the situation. */
-	dbg_bulk("bulk_eot_timer timed out.");
-	etrax_usb_hc_bulk_eot_interrupt(1);
-}
-
-static void*
-etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size,
-	unsigned mem_flags, dma_addr_t *dma)
-{
-  return kmalloc(size, mem_flags);
-}
-
-static void
-etrax_usb_buffer_free(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma)
-{
-  kfree(addr);
-}
-
-
-static struct device fake_device;
-
-static int __init etrax_usb_hc_init(void)
-{
-	static etrax_hc_t *hc;
-	struct usb_bus *bus;
-	struct usb_device *usb_rh;
-	int i;
-
-	DBFENTER;
-
-	info("ETRAX 100LX USB-HCD %s (c) 2001-2003 Axis Communications AB\n", usb_hcd_version);
-
- 	hc = kmalloc(sizeof(etrax_hc_t), GFP_KERNEL);
-	assert(hc != NULL);
-
-	/* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */
-	/* Note that we specify sizeof(USB_EP_Desc_t) as the size, but also allocate
-	   SB descriptors from this cache. This is ok since sizeof(USB_EP_Desc_t) ==
-	   sizeof(USB_SB_Desc_t). */
-
-	usb_desc_cache = kmem_cache_create("usb_desc_cache", sizeof(USB_EP_Desc_t), 0,
-					   SLAB_HWCACHE_ALIGN, 0, 0);
-	assert(usb_desc_cache != NULL);
-
-	top_half_reg_cache = kmem_cache_create("top_half_reg_cache",
-					       sizeof(usb_interrupt_registers_t),
-					       0, SLAB_HWCACHE_ALIGN, 0, 0);
-	assert(top_half_reg_cache != NULL);
-
-	isoc_compl_cache = kmem_cache_create("isoc_compl_cache",
-						sizeof(usb_isoc_complete_data_t),
-						0, SLAB_HWCACHE_ALIGN, 0, 0);
-	assert(isoc_compl_cache != NULL);
-
-	etrax_usb_bus = bus = usb_alloc_bus(&etrax_usb_device_operations);
-	hc->bus = bus;
-	bus->bus_name="ETRAX 100LX";
-	bus->hcpriv = hc;
-
-	/* Initialize RH to the default address.
-	   And make sure that we have no status change indication */
-	hc->rh.numports = 2;  /* The RH has two ports */
-	hc->rh.devnum = 1;
-	hc->rh.wPortChange_1 = 0;
-	hc->rh.wPortChange_2 = 0;
-
-	/* Also initate the previous values to zero */
-	hc->rh.prev_wPortStatus_1 = 0;
-	hc->rh.prev_wPortStatus_2 = 0;
-
-	/* Initialize the intr-traffic flags */
-	/* FIXME: This isn't used. (Besides, the error field isn't initialized.) */
-	hc->intr.sleeping = 0;
-	hc->intr.wq = NULL;
-
-	epid_usage_bitmask = 0;
-	epid_out_traffic = 0;
-
-	/* Mark the invalid epid as being used. */
-	set_bit(INVALID_EPID, (void *)&epid_usage_bitmask);
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, INVALID_EPID);
-	nop();
-	/* The valid bit should still be set ('invalid' is in our world; not the hardware's). */
-	*R_USB_EPT_DATA = (IO_STATE(R_USB_EPT_DATA, valid, yes) |
-			   IO_FIELD(R_USB_EPT_DATA, max_len, 1));
-
-	/* Mark the dummy epid as being used. */
-	set_bit(DUMMY_EPID, (void *)&epid_usage_bitmask);
-	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, DUMMY_EPID);
-	nop();
-	*R_USB_EPT_DATA = (IO_STATE(R_USB_EPT_DATA, valid, no) |
-			   IO_FIELD(R_USB_EPT_DATA, max_len, 1));
-
-	/* Initialize the urb list by initiating a head for each list. */
-	for (i = 0; i < NBR_OF_EPIDS; i++) {
-		INIT_LIST_HEAD(&urb_list[i]);
-	}
-	spin_lock_init(&urb_list_lock);
-
-	INIT_LIST_HEAD(&urb_unlink_list);
-
-
-	/* Initiate the bulk start timer. */
-	init_timer(&bulk_start_timer);
-	bulk_start_timer.expires = jiffies + BULK_START_TIMER_INTERVAL;
-	bulk_start_timer.function = etrax_usb_bulk_start_timer_func;
-	add_timer(&bulk_start_timer);
-
-
-	/* Initiate the bulk eot timer. */
-	init_timer(&bulk_eot_timer);
-	bulk_eot_timer.expires = jiffies + BULK_EOT_TIMER_INTERVAL;
-	bulk_eot_timer.function = etrax_usb_bulk_eot_timer_func;
-	add_timer(&bulk_eot_timer);
-
-	/* Set up the data structures for USB traffic. Note that this must be done before
-	   any interrupt that relies on sane DMA list occurrs. */
-	init_rx_buffers();
-	init_tx_bulk_ep();
-	init_tx_ctrl_ep();
-	init_tx_intr_ep();
-	init_tx_isoc_ep();
-
-        device_initialize(&fake_device);
-        kobject_set_name(&fake_device.kobj, "etrax_usb");
-        kobject_add(&fake_device.kobj);
-	kobject_uevent(&fake_device.kobj, KOBJ_ADD);
-        hc->bus->controller = &fake_device;
-	usb_register_bus(hc->bus);
-
-	*R_IRQ_MASK2_SET =
-		/* Note that these interrupts are not used. */
-		IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) |
-		/* Sub channel 1 (ctrl) descr. interrupts are used. */
-		IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) |
-		IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) |
-		/* Sub channel 3 (isoc) descr. interrupts are used. */
-		IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set);
-
-	/* Note that the dma9_descr interrupt is not used. */
-	*R_IRQ_MASK2_SET =
-		IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) |
-		IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);
-
-	/* FIXME: Enable iso_eof only when isoc traffic is running. */
-	*R_USB_IRQ_MASK_SET =
-		IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set) |
-		IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) |
-		IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) |
-		IO_STATE(R_USB_IRQ_MASK_SET, port_status, set) |
-		IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set);
-
-
-	if (request_irq(ETRAX_USB_HC_IRQ, etrax_usb_hc_interrupt_top_half, 0,
-			"ETRAX 100LX built-in USB (HC)", hc)) {
-		err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ);
-		etrax_usb_hc_cleanup();
-		DBFEXIT;
-		return -1;
-	}
-
-	if (request_irq(ETRAX_USB_RX_IRQ, etrax_usb_rx_interrupt, 0,
-			"ETRAX 100LX built-in USB (Rx)", hc)) {
-		err("Could not allocate IRQ %d for USB", ETRAX_USB_RX_IRQ);
-		etrax_usb_hc_cleanup();
-		DBFEXIT;
-		return -1;
-	}
-
-	if (request_irq(ETRAX_USB_TX_IRQ, etrax_usb_tx_interrupt, 0,
-			"ETRAX 100LX built-in USB (Tx)", hc)) {
-		err("Could not allocate IRQ %d for USB", ETRAX_USB_TX_IRQ);
-		etrax_usb_hc_cleanup();
-		DBFEXIT;
-		return -1;
-	}
-
-	/* R_USB_COMMAND:
-	   USB commands in host mode. The fields in this register should all be
-	   written to in one write. Do not read-modify-write one field at a time. A
-	   write to this register will trigger events in the USB controller and an
-	   incomplete command may lead to unpredictable results, and in worst case
-	   even to a deadlock in the controller.
-	   (Note however that the busy field is read-only, so no need to write to it.) */
-
-	/* Check the busy bit before writing to R_USB_COMMAND. */
-
-	while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-	/* Reset the USB interface. */
-	*R_USB_COMMAND =
-		IO_STATE(R_USB_COMMAND, port_sel, nop) |
-		IO_STATE(R_USB_COMMAND, port_cmd, reset) |
-		IO_STATE(R_USB_COMMAND, ctrl_cmd, reset);
-
-	/* Designer's Reference, p. 8 - 10 says we should Initate R_USB_FM_PSTART to 0x2A30 (10800),
-	   to guarantee that control traffic gets 10% of the bandwidth, and periodic transfer may
-	   allocate the rest (90%). This doesn't work though. Read on for a lenghty explanation.
-
-	   While there is a difference between rev. 2 and rev. 3 of the ETRAX 100LX regarding the NAK
-	   behaviour, it doesn't solve this problem. What happens is that a control transfer will not
-	   be interrupted in its data stage when PSTART happens (the point at which periodic traffic
-	   is started). Thus, if PSTART is set to 10800 and its IN or OUT token is NAKed until just before
-	   PSTART happens, it will continue the IN/OUT transfer as long as it's ACKed. After it's done,
-	   there may be too little time left for an isochronous transfer, causing an epid attention
-	   interrupt due to perror. The work-around for this is to let the control transfers run at the
-	   end of the frame instead of at the beginning, and will be interrupted just fine if it doesn't
-	   fit into the frame. However, since there will *always* be a control transfer at the beginning
-	   of the frame, regardless of what we set PSTART to, that transfer might be a 64-byte transfer
-	   which consumes up to 15% of the frame, leaving only 85% for periodic traffic. The solution to
-	   this would be to 'dummy allocate' 5% of the frame with the usb_claim_bandwidth function to make
-	   sure that the periodic transfers that are inserted will always fit in the frame.
-
-	   The idea was suggested that a control transfer could be split up into several 8 byte transfers,
-	   so that it would be interrupted by PSTART, but since this can't be done for an IN transfer this
-	   hasn't been implemented.
-
-	   The value 11960 is chosen to be just after the SOF token, with a couple of bit times extra
-	   for possible bit stuffing. */
-
-	*R_USB_FM_PSTART = IO_FIELD(R_USB_FM_PSTART, value, 11960);
-
-#ifdef CONFIG_ETRAX_USB_HOST_PORT1
-	*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);
-#endif
-
-#ifdef CONFIG_ETRAX_USB_HOST_PORT2
-	*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);
-#endif
-
-	while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-	/* Configure the USB interface as a host controller. */
-	*R_USB_COMMAND =
-		IO_STATE(R_USB_COMMAND, port_sel, nop) |
-		IO_STATE(R_USB_COMMAND, port_cmd, reset) |
-		IO_STATE(R_USB_COMMAND, ctrl_cmd, host_config);
-
-	/* Note: Do not reset any ports here. Await the port status interrupts, to have a controlled
-	   sequence of resetting the ports. If we reset both ports now, and there are devices
-	   on both ports, we will get a bus error because both devices will answer the set address
-	   request. */
-
-	while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-	/* Start processing of USB traffic. */
-	*R_USB_COMMAND =
-		IO_STATE(R_USB_COMMAND, port_sel, nop) |
-		IO_STATE(R_USB_COMMAND, port_cmd, reset) |
-		IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
-
-	while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
-	usb_rh = usb_alloc_dev(NULL, hc->bus, 0);
-	hc->bus->root_hub = usb_rh;
-        usb_rh->state = USB_STATE_ADDRESS;
-        usb_rh->speed = USB_SPEED_FULL;
-        usb_rh->devnum = 1;
-        hc->bus->devnum_next = 2;
-        usb_rh->ep0.desc.wMaxPacketSize = __const_cpu_to_le16(64);
-        usb_get_device_descriptor(usb_rh, USB_DT_DEVICE_SIZE);
-	usb_new_device(usb_rh);
-
-	DBFEXIT;
-
-	return 0;
-}
-
-static void etrax_usb_hc_cleanup(void)
-{
-	DBFENTER;
-
-	free_irq(ETRAX_USB_HC_IRQ, NULL);
-	free_irq(ETRAX_USB_RX_IRQ, NULL);
-	free_irq(ETRAX_USB_TX_IRQ, NULL);
-
-	usb_deregister_bus(etrax_usb_bus);
-
-	/* FIXME: call kmem_cache_destroy here? */
-
-	DBFEXIT;
-}
-
-module_init(etrax_usb_hc_init);
-module_exit(etrax_usb_hc_cleanup);
diff --git a/drivers/usb/host/hc_crisv10.h b/drivers/usb/host/hc_crisv10.h
deleted file mode 100644
index 62f7711..0000000
--- a/drivers/usb/host/hc_crisv10.h
+++ /dev/null
@@ -1,289 +0,0 @@
-#ifndef __LINUX_ETRAX_USB_H
-#define __LINUX_ETRAX_USB_H
-
-#include <linux/types.h>
-#include <linux/list.h>
-
-typedef struct USB_IN_Desc {
-	volatile __u16 sw_len;
-	volatile __u16 command;
-	volatile unsigned long next;
-	volatile unsigned long buf;
-	volatile __u16 hw_len;
-	volatile __u16 status;
-} USB_IN_Desc_t;
-
-typedef struct USB_SB_Desc {
-	volatile __u16 sw_len;
-	volatile __u16 command;
-	volatile unsigned long next;
-	volatile unsigned long buf;
-	__u32 dummy;
-} USB_SB_Desc_t;
-
-typedef struct USB_EP_Desc {
-	volatile __u16 hw_len;
-	volatile __u16 command;
-	volatile unsigned long sub;
-	volatile unsigned long next;
-	__u32 dummy;
-} USB_EP_Desc_t;
-
-struct virt_root_hub {
-	int devnum;
-	void *urb;
-	void *int_addr;
-	int send;
-	int interval;
-	int numports;
-	struct timer_list rh_int_timer;
-	volatile __u16 wPortChange_1;
-	volatile __u16 wPortChange_2;
-	volatile __u16 prev_wPortStatus_1;
-	volatile __u16 prev_wPortStatus_2;
-};
-
-struct etrax_usb_intr_traffic {
-	int sleeping;
-	int error;
-	struct wait_queue *wq;
-};
-
-typedef struct etrax_usb_hc {
-	struct usb_bus *bus;
-	struct virt_root_hub rh;
-	struct etrax_usb_intr_traffic intr;
-} etrax_hc_t;
-
-typedef enum {
-	STARTED,
-	NOT_STARTED,
-	UNLINK,
-	TRANSFER_DONE,
-	WAITING_FOR_DESCR_INTR
-} etrax_usb_urb_state_t;
-
-
-
-typedef struct etrax_usb_urb_priv {
-	/* The first_sb field is used for freeing all SB descriptors belonging
-	   to an urb. The corresponding ep descriptor's sub pointer cannot be
-	   used for this since the DMA advances the sub pointer as it processes
-	   the sb list. */
-	USB_SB_Desc_t *first_sb;
-	/* The last_sb field referes to the last SB descriptor that belongs to
-	   this urb. This is important to know so we can free the SB descriptors
-	   that ranges between first_sb and last_sb. */
-	USB_SB_Desc_t *last_sb;
-
-	/* The rx_offset field is used in ctrl and bulk traffic to keep track
-	   of the offset in the urb's transfer_buffer where incoming data should be
-	   copied to. */
-	__u32 rx_offset;
-
-	/* Counter used in isochronous transfers to keep track of the
-	   number of packets received/transmitted.  */
-	__u32 isoc_packet_counter;
-
-	/* This field is used to pass information about the urb's current state between
-	   the various interrupt handlers (thus marked volatile). */
-	volatile etrax_usb_urb_state_t urb_state;
-
-	/* Connection between the submitted urb and ETRAX epid number */
-	__u8 epid;
-
-	/* The rx_data_list field is used for periodic traffic, to hold
-	   received data for later processing in the the complete_urb functions,
-	   where the data us copied to the urb's transfer_buffer. Basically, we
-	   use this intermediate storage because we don't know when it's safe to
-	   reuse the transfer_buffer (FIXME?). */
-	struct list_head rx_data_list;
-} etrax_urb_priv_t;
-
-/* This struct is for passing data from the top half to the bottom half. */
-typedef struct usb_interrupt_registers
-{
-	etrax_hc_t *hc;
-	__u32 r_usb_epid_attn;
-	__u8 r_usb_status;
-	__u16 r_usb_rh_port_status_1;
-	__u16 r_usb_rh_port_status_2;
-	__u32 r_usb_irq_mask_read;
-	__u32 r_usb_fm_number;
-	struct work_struct usb_bh;
-} usb_interrupt_registers_t;
-
-/* This struct is for passing data from the isoc top half to the isoc bottom half. */
-typedef struct usb_isoc_complete_data
-{
-	struct urb *urb;
-	struct work_struct usb_bh;
-} usb_isoc_complete_data_t;
-
-/* This struct holds data we get from the rx descriptors for DMA channel 9
-   for periodic traffic (intr and isoc). */
-typedef struct rx_data
-{
-	void *data;
-	int length;
-	struct list_head list;
-} rx_data_t;
-
-typedef struct urb_entry
-{
-	struct urb *urb;
-	struct list_head list;
-} urb_entry_t;
-
-/* ---------------------------------------------------------------------------
-   Virtual Root HUB
-   ------------------------------------------------------------------------- */
-/* destination of request */
-#define RH_INTERFACE               0x01
-#define RH_ENDPOINT                0x02
-#define RH_OTHER                   0x03
-
-#define RH_CLASS                   0x20
-#define RH_VENDOR                  0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS           0x0080
-#define RH_CLEAR_FEATURE        0x0100
-#define RH_SET_FEATURE          0x0300
-#define RH_SET_ADDRESS		0x0500
-#define RH_GET_DESCRIPTOR	0x0680
-#define RH_SET_DESCRIPTOR       0x0700
-#define RH_GET_CONFIGURATION	0x0880
-#define RH_SET_CONFIGURATION	0x0900
-#define RH_GET_STATE            0x0280
-#define RH_GET_INTERFACE        0x0A80
-#define RH_SET_INTERFACE        0x0B00
-#define RH_SYNC_FRAME           0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP               0x2000
-
-
-/* Hub port features */
-#define RH_PORT_CONNECTION         0x00
-#define RH_PORT_ENABLE             0x01
-#define RH_PORT_SUSPEND            0x02
-#define RH_PORT_OVER_CURRENT       0x03
-#define RH_PORT_RESET              0x04
-#define RH_PORT_POWER              0x08
-#define RH_PORT_LOW_SPEED          0x09
-#define RH_C_PORT_CONNECTION       0x10
-#define RH_C_PORT_ENABLE           0x11
-#define RH_C_PORT_SUSPEND          0x12
-#define RH_C_PORT_OVER_CURRENT     0x13
-#define RH_C_PORT_RESET            0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER       0x00
-#define RH_C_HUB_OVER_CURRENT      0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP    0x00
-#define RH_ENDPOINT_STALL          0x01
-
-/* Our Vendor Specific feature */
-#define RH_REMOVE_EP               0x00
-
-
-#define RH_ACK                     0x01
-#define RH_REQ_ERR                 -1
-#define RH_NACK                    0x00
-
-/* Field definitions for */
-
-#define USB_IN_command__eol__BITNR      0 /* command macros */
-#define USB_IN_command__eol__WIDTH      1
-#define USB_IN_command__eol__no         0
-#define USB_IN_command__eol__yes        1
-
-#define USB_IN_command__intr__BITNR     3
-#define USB_IN_command__intr__WIDTH     1
-#define USB_IN_command__intr__no        0
-#define USB_IN_command__intr__yes       1
-
-#define USB_IN_status__eop__BITNR       1 /* status macros. */
-#define USB_IN_status__eop__WIDTH       1
-#define USB_IN_status__eop__no          0
-#define USB_IN_status__eop__yes         1
-
-#define USB_IN_status__eot__BITNR       5
-#define USB_IN_status__eot__WIDTH       1
-#define USB_IN_status__eot__no          0
-#define USB_IN_status__eot__yes         1
-
-#define USB_IN_status__error__BITNR     6
-#define USB_IN_status__error__WIDTH     1
-#define USB_IN_status__error__no        0
-#define USB_IN_status__error__yes       1
-
-#define USB_IN_status__nodata__BITNR    7
-#define USB_IN_status__nodata__WIDTH    1
-#define USB_IN_status__nodata__no       0
-#define USB_IN_status__nodata__yes      1
-
-#define USB_IN_status__epid__BITNR      8
-#define USB_IN_status__epid__WIDTH      5
-
-#define USB_EP_command__eol__BITNR      0
-#define USB_EP_command__eol__WIDTH      1
-#define USB_EP_command__eol__no         0
-#define USB_EP_command__eol__yes        1
-
-#define USB_EP_command__eof__BITNR      1
-#define USB_EP_command__eof__WIDTH      1
-#define USB_EP_command__eof__no         0
-#define USB_EP_command__eof__yes        1
-
-#define USB_EP_command__intr__BITNR     3
-#define USB_EP_command__intr__WIDTH     1
-#define USB_EP_command__intr__no        0
-#define USB_EP_command__intr__yes       1
-
-#define USB_EP_command__enable__BITNR   4
-#define USB_EP_command__enable__WIDTH   1
-#define USB_EP_command__enable__no      0
-#define USB_EP_command__enable__yes     1
-
-#define USB_EP_command__hw_valid__BITNR 5
-#define USB_EP_command__hw_valid__WIDTH 1
-#define USB_EP_command__hw_valid__no    0
-#define USB_EP_command__hw_valid__yes   1
-
-#define USB_EP_command__epid__BITNR     8
-#define USB_EP_command__epid__WIDTH     5
-
-#define USB_SB_command__eol__BITNR      0 /* command macros. */
-#define USB_SB_command__eol__WIDTH      1
-#define USB_SB_command__eol__no         0
-#define USB_SB_command__eol__yes        1
-
-#define USB_SB_command__eot__BITNR      1
-#define USB_SB_command__eot__WIDTH      1
-#define USB_SB_command__eot__no         0
-#define USB_SB_command__eot__yes        1
-
-#define USB_SB_command__intr__BITNR     3
-#define USB_SB_command__intr__WIDTH     1
-#define USB_SB_command__intr__no        0
-#define USB_SB_command__intr__yes       1
-
-#define USB_SB_command__tt__BITNR       4
-#define USB_SB_command__tt__WIDTH       2
-#define USB_SB_command__tt__zout        0
-#define USB_SB_command__tt__in          1
-#define USB_SB_command__tt__out         2
-#define USB_SB_command__tt__setup       3
-
-
-#define USB_SB_command__rem__BITNR      8
-#define USB_SB_command__rem__WIDTH      6
-
-#define USB_SB_command__full__BITNR     6
-#define USB_SB_command__full__WIDTH     1
-#define USB_SB_command__full__no        0
-#define USB_SB_command__full__yes       1
-
-#endif
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 2718b5d..46873f253 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1577,7 +1577,7 @@
 
 #define resource_len(r) (((r)->end - (r)->start) + 1)
 
-static int __init isp116x_probe(struct platform_device *pdev)
+static int __devinit isp116x_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	struct isp116x *isp116x;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 9303464..d849c80 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -18,19 +18,38 @@
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #ifndef CONFIG_ARCH_AT91
 #error "CONFIG_ARCH_AT91 must be defined."
 #endif
 
-/* interface and function clocks */
-static struct clk *iclk, *fclk;
+/* interface and function clocks; sometimes also an AHB clock */
+static struct clk *iclk, *fclk, *hclk;
 static int clocked;
 
 extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
 
+static void at91_start_clock(void)
+{
+	if (cpu_is_at91sam9261())
+		clk_enable(hclk);
+	clk_enable(iclk);
+	clk_enable(fclk);
+	clocked = 1;
+}
+
+static void at91_stop_clock(void)
+{
+	clk_disable(fclk);
+	clk_disable(iclk);
+	if (cpu_is_at91sam9261())
+		clk_disable(hclk);
+	clocked = 0;
+}
+
 static void at91_start_hc(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -41,9 +60,7 @@
 	/*
 	 * Start the USB clocks.
 	 */
-	clk_enable(iclk);
-	clk_enable(fclk);
-	clocked = 1;
+	at91_start_clock();
 
 	/*
 	 * The USB host controller must remain in reset.
@@ -66,9 +83,7 @@
 	/*
 	 * Stop the USB clocks.
 	 */
-	clk_disable(fclk);
-	clk_disable(iclk);
-	clocked = 0;
+	at91_stop_clock();
 }
 
 
@@ -126,6 +141,8 @@
 
 	iclk = clk_get(&pdev->dev, "ohci_clk");
 	fclk = clk_get(&pdev->dev, "uhpck");
+	if (cpu_is_at91sam9261())
+		hclk = clk_get(&pdev->dev, "hck0");
 
 	at91_start_hc(pdev);
 	ohci_hcd_init(hcd_to_ohci(hcd));
@@ -137,6 +154,8 @@
 	/* Error handling */
 	at91_stop_hc(pdev);
 
+	if (cpu_is_at91sam9261())
+		clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
 
@@ -171,9 +190,11 @@
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
+	if (cpu_is_at91sam9261())
+		clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
-	fclk = iclk = NULL;
+	fclk = iclk = hclk = NULL;
 
 	dev_set_drvdata(&pdev->dev, NULL);
 	return 0;
@@ -280,9 +301,7 @@
 	 */
 	if (at91_suspend_entering_slow_clock()) {
 		ohci_usb_reset (ohci);
-		clk_disable(fclk);
-		clk_disable(iclk);
-		clocked = 0;
+		at91_stop_clock();
 	}
 
 	return 0;
@@ -295,11 +314,8 @@
 	if (device_may_wakeup(&pdev->dev))
 		disable_irq_wake(hcd->irq);
 
-	if (!clocked) {
-		clk_enable(iclk);
-		clk_enable(fclk);
-		clocked = 1;
-	}
+	if (!clocked)
+		at91_start_clock();
 
 	return 0;
 }
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index fa6a7ce..e8bbe8b 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -42,6 +42,9 @@
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
 
 #include "../core/hcd.h"
 
@@ -483,9 +486,6 @@
 	 * or if bus glue did the same (e.g. for PCI add-in cards with
 	 * PCI PM support).
 	 */
-	ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n",
-			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-			ohci_readl (ohci, &ohci->regs->control));
 	if ((ohci->hc_control & OHCI_CTRL_RWC) != 0
 			&& !device_may_wakeup(hcd->self.controller))
 		device_init_wakeup(hcd->self.controller, 1);
@@ -741,9 +741,6 @@
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
-	ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n",
-		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-		hcd->state);
 	ohci_dump (ohci, 1);
 
 	flush_scheduled_work();
@@ -944,9 +941,12 @@
 		sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-	if (retval < 0)
-		goto error_ps3;
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+		retval = ps3_system_bus_driver_register(
+				&PS3_SYSTEM_BUS_DRIVER);
+		if (retval < 0)
+			goto error_ps3;
+	}
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -992,7 +992,8 @@
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
 	return retval;
@@ -1014,7 +1015,8 @@
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index b331ac4..7970560 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -20,10 +20,16 @@
 
 /*-------------------------------------------------------------------------*/
 
+static int broken_suspend(struct usb_hcd *hcd)
+{
+	device_init_wakeup(&hcd->self.root_hub->dev, 0);
+	return 0;
+}
+
 /* AMD 756, for most chips (early revs), corrupts register
  * values on read ... so enable the vendor workaround.
  */
-static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd)
+static int ohci_quirk_amd756(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 
@@ -31,16 +37,14 @@
 	ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
 
 	/* also erratum 10 (suspend/resume issues) */
-	device_init_wakeup(&hcd->self.root_hub->dev, 0);
-
-	return 0;
+	return broken_suspend(hcd);
 }
 
 /* Apple's OHCI driver has a lot of bizarre workarounds
  * for this chip.  Evidently control and bulk lists
  * can get confused.  (B&W G3 models, and ...)
  */
-static int __devinit ohci_quirk_opti(struct usb_hcd *hcd)
+static int ohci_quirk_opti(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 
@@ -53,7 +57,7 @@
  * identify the USB (fn2). This quirk might apply to more or
  * even all NSC stuff.
  */
-static int __devinit ohci_quirk_ns(struct usb_hcd *hcd)
+static int ohci_quirk_ns(struct usb_hcd *hcd)
 {
 	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 	struct pci_dev	*b;
@@ -75,7 +79,7 @@
  * delays before control or bulk queues get re-activated
  * in finish_unlinks()
  */
-static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
+static int ohci_quirk_zfmicro(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 
@@ -88,7 +92,7 @@
 /* Check for Toshiba SCC OHCI which has big endian registers
  * and little endian in memory data structures
  */
-static int __devinit ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
+static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 
@@ -129,6 +133,18 @@
 		PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6),
 		.driver_data = (unsigned long)ohci_quirk_toshiba_scc,
 	},
+	{
+		/* Toshiba portege 4000 */
+		.vendor		= PCI_VENDOR_ID_AL,
+		.device		= 0x5237,
+		.subvendor	= PCI_VENDOR_ID_TOSHIBA_2,
+		.subdevice	= 0x0004,
+		.driver_data	= (unsigned long) broken_suspend,
+	},
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_ITE, 0x8152),
+		.driver_data = (unsigned long) broken_suspend,
+	},
 	/* FIXME for some of the early AMD 760 southbridges, OHCI
 	 * won't work at all.  blacklist them.
 	 */
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 5d6c06b..1497371 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -145,7 +145,8 @@
 	return out - buf;
 }
 
-static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+static int uhci_show_qh(struct uhci_hcd *uhci,
+		struct uhci_qh *qh, char *buf, int len, int space)
 {
 	char *out = buf;
 	int i, nurbs;
@@ -190,13 +191,16 @@
 
 	if (list_empty(&qh->queue)) {
 		out += sprintf(out, "%*s  queue is empty\n", space, "");
+		if (qh == uhci->skel_async_qh)
+			out += uhci_show_td(uhci->term_td, out,
+					len - (out - buf), 0);
 	} else {
 		struct urb_priv *urbp = list_entry(qh->queue.next,
 				struct urb_priv, node);
 		struct uhci_td *td = list_entry(urbp->td_list.next,
 				struct uhci_td, list);
 
-		if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
+		if (element != LINK_TO_TD(td))
 			out += sprintf(out, "%*s Element != First TD\n",
 					space, "");
 		i = nurbs = 0;
@@ -220,16 +224,6 @@
 	return out - buf;
 }
 
-static const char * const qh_names[] = {
-  "skel_unlink_qh", "skel_iso_qh",
-  "skel_int128_qh", "skel_int64_qh",
-  "skel_int32_qh", "skel_int16_qh",
-  "skel_int8_qh", "skel_int4_qh",
-  "skel_int2_qh", "skel_int1_qh",
-  "skel_ls_control_qh", "skel_fs_control_qh",
-  "skel_bulk_qh", "skel_term_qh"
-};
-
 static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
 {
 	char *out = buf;
@@ -352,6 +346,13 @@
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
 	int nframes, nerrs;
+	__le32 link;
+	__le32 fsbr_link;
+
+	static const char * const qh_names[] = {
+		"unlink", "iso", "int128", "int64", "int32", "int16",
+		"int8", "int4", "int2", "async", "term"
+	};
 
 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
 	out += sprintf(out, "HC status\n");
@@ -374,7 +375,7 @@
 	nframes = 10;
 	nerrs = 0;
 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-		__le32 link, qh_dma;
+		__le32 qh_dma;
 
 		j = 0;
 		td = uhci->frame_cpu[i];
@@ -393,7 +394,7 @@
 		do {
 			td = list_entry(tmp, struct uhci_td, fl_list);
 			tmp = tmp->next;
-			if (cpu_to_le32(td->dma_handle) != link) {
+			if (link != LINK_TO_TD(td)) {
 				if (nframes > 0)
 					out += sprintf(out, "    link does "
 						"not match list entry!\n");
@@ -428,25 +429,24 @@
 
 	out += sprintf(out, "Skeleton QHs\n");
 
+	fsbr_link = 0;
 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
 		int cnt = 0;
 
 		qh = uhci->skelqh[i];
-		out += sprintf(out, "- %s\n", qh_names[i]); \
-		out += uhci_show_qh(qh, out, len - (out - buf), 4);
+		out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
+		out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4);
 
 		/* Last QH is the Terminating QH, it's different */
-		if (i == UHCI_NUM_SKELQH - 1) {
-			if (qh->link != UHCI_PTR_TERM)
-				out += sprintf(out, "    bandwidth reclamation on!\n");
-
-			if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))
+		if (i == SKEL_TERM) {
+			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
 				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
-
-			continue;
+			link = fsbr_link;
+			if (!link)
+				link = LINK_TO_QH(uhci->skel_term_qh);
+			goto check_qh_link;
 		}
 
-		j = (i < 9) ? 9 : i+1;		/* Next skeleton */
 		head = &qh->node;
 		tmp = head->next;
 
@@ -454,17 +454,26 @@
 			qh = list_entry(tmp, struct uhci_qh, node);
 			tmp = tmp->next;
 			if (++cnt <= 10)
-				out += uhci_show_qh(qh, out,
+				out += uhci_show_qh(uhci, qh, out,
 						len - (out - buf), 4);
+			if (!fsbr_link && qh->skel >= SKEL_FSBR)
+				fsbr_link = LINK_TO_QH(qh);
 		}
 		if ((cnt -= 10) > 0)
 			out += sprintf(out, "    Skipped %d QHs\n", cnt);
 
-		if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
-			if (qh->link !=
-			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
-				out += sprintf(out, "    last QH not linked to next skeleton!\n");
-		}
+		link = UHCI_PTR_TERM;
+		if (i <= SKEL_ISO)
+			;
+		else if (i < SKEL_ASYNC)
+			link = LINK_TO_QH(uhci->skel_async_qh);
+		else if (!uhci->fsbr_is_on)
+			;
+		else
+			link = LINK_TO_QH(uhci->skel_term_qh);
+check_qh_link:
+		if (qh->link != link)
+			out += sprintf(out, "    last QH not linked to next skeleton!\n");
 	}
 
 	return out - buf;
@@ -568,8 +577,8 @@
 static inline void lprintk(char *buf)
 {}
 
-static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
-		int len, int space)
+static inline int uhci_show_qh(struct uhci_hcd *uhci,
+		struct uhci_qh *qh, char *buf, int len, int space)
 {
 	return 0;
 }
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index ded4df3..d22da26 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -107,16 +107,16 @@
 	 * interrupt QHs, which will help spread out bandwidth utilization.
 	 *
 	 * ffs (Find First bit Set) does exactly what we need:
-	 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
-	 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
+	 * 1,3,5,...  => ffs = 0 => use period-2 QH = skelqh[8],
+	 * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc.
 	 * ffs >= 7 => not on any high-period queue, so use
-	 *	skel_int1_qh = skelqh[9].
+	 *	period-1 QH = skelqh[9].
 	 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
 	 */
 	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
 	if (skelnum <= 1)
 		skelnum = 9;
-	return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
+	return LINK_TO_QH(uhci->skelqh[skelnum]);
 }
 
 #include "uhci-debug.c"
@@ -540,16 +540,18 @@
  *
  * The hardware doesn't really know any difference
  * in the queues, but the order does matter for the
- * protocols higher up. The order is:
+ * protocols higher up.  The order in which the queues
+ * are encountered by the hardware is:
  *
- *  - any isochronous events handled before any
+ *  - All isochronous events are handled before any
  *    of the queues. We don't do that here, because
  *    we'll create the actual TD entries on demand.
- *  - The first queue is the interrupt queue.
- *  - The second queue is the control queue, split into low- and full-speed
- *  - The third queue is bulk queue.
- *  - The fourth queue is the bandwidth reclamation queue, which loops back
- *    to the full-speed control queue.
+ *  - The first queue is the high-period interrupt queue.
+ *  - The second queue is the period-1 interrupt and async
+ *    (low-speed control, full-speed control, then bulk) queue.
+ *  - The third queue is the terminating bandwidth reclamation queue,
+ *    which contains no members, loops back to itself, and is present
+ *    only when FSBR is on and there are no full-speed control or bulk QHs.
  */
 static int uhci_start(struct usb_hcd *hcd)
 {
@@ -626,34 +628,19 @@
 	}
 
 	/*
-	 * 8 Interrupt queues; link all higher int queues to int1,
-	 * then link int1 to control and control to bulk
+	 * 8 Interrupt queues; link all higher int queues to int1 = async
 	 */
-	uhci->skel_int128_qh->link =
-			uhci->skel_int64_qh->link =
-			uhci->skel_int32_qh->link =
-			uhci->skel_int16_qh->link =
-			uhci->skel_int8_qh->link =
-			uhci->skel_int4_qh->link =
-			uhci->skel_int2_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_int1_qh->dma_handle);
-
-	uhci->skel_int1_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
-	uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
-	uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
-	uhci->skel_bulk_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_term_qh->dma_handle);
+	for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
+		uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
+	uhci->skel_async_qh->link = UHCI_PTR_TERM;
+	uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
 
 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
 	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
-		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
-
-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
-	uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
+			(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
+	uhci->term_td->link = UHCI_PTR_TERM;
+	uhci->skel_async_qh->element = uhci->skel_term_qh->element =
+			LINK_TO_TD(uhci->term_td);
 
 	/*
 	 * Fill the frame list: make all entries point to the proper
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 74469b5..1b3d234 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -129,11 +129,12 @@
 	__le32 element;			/* Queue element (TD) pointer */
 
 	/* Software fields */
+	dma_addr_t dma_handle;
+
 	struct list_head node;		/* Node in the list of QHs */
 	struct usb_host_endpoint *hep;	/* Endpoint information */
 	struct usb_device *udev;
 	struct list_head queue;		/* Queue of urbps for this QH */
-	struct uhci_qh *skel;		/* Skeleton for this QH */
 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
 	struct uhci_td *post_td;	/* Last TD completed */
 
@@ -149,8 +150,7 @@
 
 	int state;			/* QH_STATE_xxx; see above */
 	int type;			/* Queue type (control, bulk, etc) */
-
-	dma_addr_t dma_handle;
+	int skel;			/* Skeleton queue number */
 
 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
@@ -171,6 +171,8 @@
 	return element;
 }
 
+#define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
+
 
 /*
  *	Transfer Descriptors
@@ -264,6 +266,8 @@
 	return le32_to_cpu(status);
 }
 
+#define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))
+
 
 /*
  *	Skeleton Queue Headers
@@ -272,12 +276,13 @@
 /*
  * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
  * automatic queuing. To make it easy to insert entries into the schedule,
- * we have a skeleton of QHs for each predefined Interrupt latency,
- * low-speed control, full-speed control, bulk, and terminating QH
- * (see explanation for the terminating QH below).
+ * we have a skeleton of QHs for each predefined Interrupt latency.
+ * Asynchronous QHs (low-speed control, full-speed control, and bulk)
+ * go onto the period-1 interrupt list, since they all get accessed on
+ * every frame.
  *
- * When we want to add a new QH, we add it to the end of the list for the
- * skeleton QH.  For instance, the schedule list can look like this:
+ * When we want to add a new QH, we add it to the list starting from the
+ * appropriate skeleton QH.  For instance, the schedule can look like this:
  *
  * skel int128 QH
  * dev 1 interrupt QH
@@ -285,50 +290,47 @@
  * skel int64 QH
  * skel int32 QH
  * ...
- * skel int1 QH
- * skel low-speed control QH
- * dev 5 control QH
- * skel full-speed control QH
- * skel bulk QH
+ * skel int1 + async QH
+ * dev 5 low-speed control QH
  * dev 1 bulk QH
  * dev 2 bulk QH
- * skel terminating QH
  *
- * The terminating QH is used for 2 reasons:
- * - To place a terminating TD which is used to workaround a PIIX bug
- *   (see Intel errata for explanation), and
- * - To loop back to the full-speed control queue for full-speed bandwidth
- *   reclamation.
+ * There is a special terminating QH used to keep full-speed bandwidth
+ * reclamation active when no full-speed control or bulk QHs are linked
+ * into the schedule.  It has an inactive TD (to work around a PIIX bug,
+ * see the Intel errata) and it points back to itself.
  *
- * There's a special skeleton QH for Isochronous QHs.  It never appears
- * on the schedule, and Isochronous TDs go on the schedule before the
+ * There's a special skeleton QH for Isochronous QHs which never appears
+ * on the schedule.  Isochronous TDs go on the schedule before the
  * the skeleton QHs.  The hardware accesses them directly rather than
  * through their QH, which is used only for bookkeeping purposes.
  * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
  * it doesn't use them either.  And the spec says that queues never
  * advance on an error completion status, which makes them totally
  * unsuitable for Isochronous transfers.
+ *
+ * There's also a special skeleton QH used for QHs which are in the process
+ * of unlinking and so may still be in use by the hardware.  It too never
+ * appears on the schedule.
  */
 
-#define UHCI_NUM_SKELQH		14
-#define skel_unlink_qh		skelqh[0]
-#define skel_iso_qh		skelqh[1]
-#define skel_int128_qh		skelqh[2]
-#define skel_int64_qh		skelqh[3]
-#define skel_int32_qh		skelqh[4]
-#define skel_int16_qh		skelqh[5]
-#define skel_int8_qh		skelqh[6]
-#define skel_int4_qh		skelqh[7]
-#define skel_int2_qh		skelqh[8]
-#define skel_int1_qh		skelqh[9]
-#define skel_ls_control_qh	skelqh[10]
-#define skel_fs_control_qh	skelqh[11]
-#define skel_bulk_qh		skelqh[12]
-#define skel_term_qh		skelqh[13]
+#define UHCI_NUM_SKELQH		11
+#define SKEL_UNLINK		0
+#define skel_unlink_qh		skelqh[SKEL_UNLINK]
+#define SKEL_ISO		1
+#define skel_iso_qh		skelqh[SKEL_ISO]
+	/* int128, int64, ..., int1 = 2, 3, ..., 9 */
+#define SKEL_INDEX(exponent)	(9 - exponent)
+#define SKEL_ASYNC		9
+#define skel_async_qh		skelqh[SKEL_ASYNC]
+#define SKEL_TERM		10
+#define skel_term_qh		skelqh[SKEL_TERM]
 
-/* Find the skelqh entry corresponding to an interval exponent */
-#define UHCI_SKEL_INDEX(exponent)	(9 - exponent)
-
+/* The following entries refer to sublists of skel_async_qh */
+#define SKEL_LS_CONTROL		20
+#define SKEL_FS_CONTROL		21
+#define SKEL_FSBR		SKEL_FS_CONTROL
+#define SKEL_BULK		22
 
 /*
  *	The UHCI controller and root hub
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index bacc25c..8e4427a 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -33,6 +33,9 @@
 /* status change bits:  nonzero writes will clear */
 #define RWC_BITS	(USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
 
+/* suspend/resume bits: port suspended or port resuming */
+#define SUSPEND_BITS	(USBPORTSC_SUSP | USBPORTSC_RD)
+
 /* A port that either is connected or has a changed-bit set will prevent
  * us from AUTO_STOPPING.
  */
@@ -96,8 +99,8 @@
 	int status;
 	int i;
 
-	if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
-		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
+	if (inw(port_addr) & SUSPEND_BITS) {
+		CLR_RH_PORTSTAT(SUSPEND_BITS);
 		if (test_bit(port, &uhci->resuming_ports))
 			set_bit(port, &uhci->port_c_suspend);
 
@@ -107,7 +110,7 @@
 		 * Experiments show that some controllers take longer, so
 		 * we'll poll for completion. */
 		for (i = 0; i < 10; ++i) {
-			if (!(inw(port_addr) & USBPORTSC_RD))
+			if (!(inw(port_addr) & SUSPEND_BITS))
 				break;
 			udelay(1);
 		}
@@ -289,7 +292,7 @@
 			wPortStatus |= USB_PORT_STAT_CONNECTION;
 		if (status & USBPORTSC_PE) {
 			wPortStatus |= USB_PORT_STAT_ENABLE;
-			if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
+			if (status & SUSPEND_BITS)
 				wPortStatus |= USB_PORT_STAT_SUSPEND;
 		}
 		if (status & USBPORTSC_OC)
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 68e66b3..4aed305 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  */
 
 
@@ -45,15 +45,27 @@
  */
 static void uhci_fsbr_on(struct uhci_hcd *uhci)
 {
+	struct uhci_qh *lqh;
+
+	/* The terminating skeleton QH always points back to the first
+	 * FSBR QH.  Make the last async QH point to the terminating
+	 * skeleton QH. */
 	uhci->fsbr_is_on = 1;
-	uhci->skel_term_qh->link = cpu_to_le32(
-			uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+	lqh = list_entry(uhci->skel_async_qh->node.prev,
+			struct uhci_qh, node);
+	lqh->link = LINK_TO_QH(uhci->skel_term_qh);
 }
 
 static void uhci_fsbr_off(struct uhci_hcd *uhci)
 {
+	struct uhci_qh *lqh;
+
+	/* Remove the link from the last async QH to the terminating
+	 * skeleton QH. */
 	uhci->fsbr_is_on = 0;
-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
+	lqh = list_entry(uhci->skel_async_qh->node.prev,
+			struct uhci_qh, node);
+	lqh->link = UHCI_PTR_TERM;
 }
 
 static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
@@ -111,10 +123,14 @@
 
 static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
 {
-	if (!list_empty(&td->list))
+	if (!list_empty(&td->list)) {
 		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
-	if (!list_empty(&td->fl_list))
+		WARN_ON(1);
+	}
+	if (!list_empty(&td->fl_list)) {
 		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
+		WARN_ON(1);
+	}
 
 	dma_pool_free(uhci->td_pool, td, td->dma_handle);
 }
@@ -158,11 +174,11 @@
 
 		td->link = ltd->link;
 		wmb();
-		ltd->link = cpu_to_le32(td->dma_handle);
+		ltd->link = LINK_TO_TD(td);
 	} else {
 		td->link = uhci->frame[framenum];
 		wmb();
-		uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+		uhci->frame[framenum] = LINK_TO_TD(td);
 		uhci->frame_cpu[framenum] = td;
 	}
 }
@@ -184,7 +200,7 @@
 			struct uhci_td *ntd;
 
 			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-			uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+			uhci->frame[td->frame] = LINK_TO_TD(ntd);
 			uhci->frame_cpu[td->frame] = ntd;
 		}
 	} else {
@@ -279,8 +295,10 @@
 static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
-	if (!list_empty(&qh->queue))
+	if (!list_empty(&qh->queue)) {
 		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
+		WARN_ON(1);
+	}
 
 	list_del(&qh->node);
 	if (qh->udev) {
@@ -405,12 +423,66 @@
 }
 
 /*
+ * Link an Isochronous QH into its skeleton's list
+ */
+static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	list_add_tail(&qh->node, &uhci->skel_iso_qh->node);
+
+	/* Isochronous QHs aren't linked by the hardware */
+}
+
+/*
+ * Link a high-period interrupt QH into the schedule at the end of its
+ * skeleton's list
+ */
+static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+
+	list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node);
+
+	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+	qh->link = pqh->link;
+	wmb();
+	pqh->link = LINK_TO_QH(qh);
+}
+
+/*
+ * Link a period-1 interrupt or async QH into the schedule at the
+ * correct spot in the async skeleton's list, and update the FSBR link
+ */
+static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+	__le32 link_to_new_qh;
+
+	/* Find the predecessor QH for our new one and insert it in the list.
+	 * The list of QHs is expected to be short, so linear search won't
+	 * take too long. */
+	list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) {
+		if (pqh->skel <= qh->skel)
+			break;
+	}
+	list_add(&qh->node, &pqh->node);
+
+	/* Link it into the schedule */
+	qh->link = pqh->link;
+	wmb();
+	link_to_new_qh = LINK_TO_QH(qh);
+	pqh->link = link_to_new_qh;
+
+	/* If this is now the first FSBR QH, link the terminating skeleton
+	 * QH to it. */
+	if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
+		uhci->skel_term_qh->link = link_to_new_qh;
+}
+
+/*
  * Put a QH on the schedule in both hardware and software
  */
 static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
-	struct uhci_qh *pqh;
-
 	WARN_ON(list_empty(&qh->queue));
 
 	/* Set the element pointer if it isn't set already.
@@ -421,7 +493,7 @@
 		struct uhci_td *td = list_entry(urbp->td_list.next,
 				struct uhci_td, list);
 
-		qh->element = cpu_to_le32(td->dma_handle);
+		qh->element = LINK_TO_TD(td);
 	}
 
 	/* Treat the queue as if it has just advanced */
@@ -432,18 +504,49 @@
 		return;
 	qh->state = QH_STATE_ACTIVE;
 
-	/* Move the QH from its old list to the end of the appropriate
+	/* Move the QH from its old list to the correct spot in the appropriate
 	 * skeleton's list */
 	if (qh == uhci->next_qh)
 		uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
 				node);
-	list_move_tail(&qh->node, &qh->skel->node);
+	list_del(&qh->node);
 
-	/* Link it into the schedule */
+	if (qh->skel == SKEL_ISO)
+		link_iso(uhci, qh);
+	else if (qh->skel < SKEL_ASYNC)
+		link_interrupt(uhci, qh);
+	else
+		link_async(uhci, qh);
+}
+
+/*
+ * Unlink a high-period interrupt QH from the schedule
+ */
+static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+
 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-	qh->link = pqh->link;
-	wmb();
-	pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
+	pqh->link = qh->link;
+	mb();
+}
+
+/*
+ * Unlink a period-1 interrupt or async QH from the schedule
+ */
+static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+	__le32 link_to_next_qh = qh->link;
+
+	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+	pqh->link = link_to_next_qh;
+
+	/* If this was the old first FSBR QH, link the terminating skeleton
+	 * QH to the next (new first FSBR) QH. */
+	if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
+		uhci->skel_term_qh->link = link_to_next_qh;
+	mb();
 }
 
 /*
@@ -451,17 +554,18 @@
  */
 static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
-	struct uhci_qh *pqh;
-
 	if (qh->state == QH_STATE_UNLINKING)
 		return;
 	WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev);
 	qh->state = QH_STATE_UNLINKING;
 
 	/* Unlink the QH from the schedule and record when we did it */
-	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-	pqh->link = qh->link;
-	mb();
+	if (qh->skel == SKEL_ISO)
+		;
+	else if (qh->skel < SKEL_ASYNC)
+		unlink_interrupt(uhci, qh);
+	else
+		unlink_async(uhci, qh);
 
 	uhci_get_current_frame_number(uhci);
 	qh->unlink_frame = uhci->frame_number;
@@ -642,9 +746,11 @@
 {
 	struct uhci_td *td, *tmp;
 
-	if (!list_empty(&urbp->node))
+	if (!list_empty(&urbp->node)) {
 		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
 				urbp->urb);
+		WARN_ON(1);
+	}
 
 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
 		uhci_remove_td_from_urbp(td);
@@ -697,6 +803,7 @@
 	dma_addr_t data = urb->transfer_dma;
 	__le32 *plink;
 	struct urb_priv *urbp = urb->hcpriv;
+	int skel;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -737,7 +844,7 @@
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			goto nomem;
-		*plink = cpu_to_le32(td->dma_handle);
+		*plink = LINK_TO_TD(td);
 
 		/* Alternate Data0/1 (start with Data1) */
 		destination ^= TD_TOKEN_TOGGLE;
@@ -757,7 +864,7 @@
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = cpu_to_le32(td->dma_handle);
+	*plink = LINK_TO_TD(td);
 
 	/*
 	 * It's IN if the pipe is an output pipe or we're not expecting
@@ -784,7 +891,7 @@
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = cpu_to_le32(td->dma_handle);
+	*plink = LINK_TO_TD(td);
 
 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
@@ -797,11 +904,13 @@
 	 * isn't in the CONFIGURED state. */
 	if (urb->dev->speed == USB_SPEED_LOW ||
 			urb->dev->state != USB_STATE_CONFIGURED)
-		qh->skel = uhci->skel_ls_control_qh;
+		skel = SKEL_LS_CONTROL;
 	else {
-		qh->skel = uhci->skel_fs_control_qh;
+		skel = SKEL_FS_CONTROL;
 		uhci_add_fsbr(uhci, urb);
 	}
+	if (qh->state != QH_STATE_ACTIVE)
+		qh->skel = skel;
 
 	urb->actual_length = -8;	/* Account for the SETUP packet */
 	return 0;
@@ -860,7 +969,7 @@
 			td = uhci_alloc_td(uhci);
 			if (!td)
 				goto nomem;
-			*plink = cpu_to_le32(td->dma_handle);
+			*plink = LINK_TO_TD(td);
 		}
 		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status,
@@ -888,7 +997,7 @@
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			goto nomem;
-		*plink = cpu_to_le32(td->dma_handle);
+		*plink = LINK_TO_TD(td);
 
 		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status,
@@ -914,7 +1023,7 @@
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = cpu_to_le32(td->dma_handle);
+	*plink = LINK_TO_TD(td);
 
 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
@@ -931,7 +1040,7 @@
 	return -ENOMEM;
 }
 
-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
 		struct uhci_qh *qh)
 {
 	int ret;
@@ -940,7 +1049,8 @@
 	if (urb->dev->speed == USB_SPEED_LOW)
 		return -EINVAL;
 
-	qh->skel = uhci->skel_bulk_qh;
+	if (qh->state != QH_STATE_ACTIVE)
+		qh->skel = SKEL_BULK;
 	ret = uhci_submit_common(uhci, urb, qh);
 	if (ret == 0)
 		uhci_add_fsbr(uhci, urb);
@@ -968,7 +1078,7 @@
 		if (exponent < 0)
 			return -EINVAL;
 		qh->period = 1 << exponent;
-		qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
+		qh->skel = SKEL_INDEX(exponent);
 
 		/* For now, interrupt phase is fixed by the layout
 		 * of the QH lists. */
@@ -1005,7 +1115,7 @@
 		 * the queue at the status stage transaction, which is
 		 * the last TD. */
 		WARN_ON(list_empty(&urbp->td_list));
-		qh->element = cpu_to_le32(td->dma_handle);
+		qh->element = LINK_TO_TD(td);
 		tmp = td->list.prev;
 		ret = -EINPROGRESS;
 
@@ -1069,7 +1179,7 @@
 
 				if (debug > 1 && errbuf) {
 					/* Print the chain for debugging */
-					uhci_show_qh(urbp->qh, errbuf,
+					uhci_show_qh(uhci, urbp->qh, errbuf,
 							ERRBUF_LEN, 0);
 					lprintk(errbuf);
 				}
@@ -1216,7 +1326,7 @@
 		qh->iso_status = 0;
 	}
 
-	qh->skel = uhci->skel_iso_qh;
+	qh->skel = SKEL_ISO;
 	if (!qh->bandwidth_reserved)
 		uhci_reserve_bandwidth(uhci, qh);
 	return 0;
@@ -1566,8 +1676,7 @@
 	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
 
 		/* Detect the Intel bug and work around it */
-		if (qh->post_td && qh_element(qh) ==
-				cpu_to_le32(qh->post_td->dma_handle)) {
+		if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
 			qh->element = qh->post_td->link;
 			qh->advance_jiffies = jiffies;
 			ret = 1;
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 69a9f3b..a792e42 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -4,151 +4,6 @@
 comment "USB Input Devices"
 	depends on USB
 
-config USB_HID
-	tristate "USB Human Interface Device (full HID) support"
-	default y
-	depends on USB && INPUT
-	select HID
-	---help---
-	  Say Y here if you want full HID support to connect USB keyboards,
-	  mice, joysticks, graphic tablets, or any other HID based devices
-	  to your computer via USB, as well as Uninterruptible Power Supply
-	  (UPS) and monitor control devices.
-
-	  You can't use this driver and the HIDBP (Boot Protocol) keyboard
-	  and mouse drivers at the same time. More information is available:
-	  <file:Documentation/input/input.txt>.
-
-	  If unsure, say Y.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called usbhid.
-
-comment "Input core support is needed for USB HID input layer or HIDBP support"
-	depends on USB_HID && INPUT=n
-
-config USB_HIDINPUT_POWERBOOK
-	bool "Enable support for iBook/PowerBook special keys"
-	default n
-	depends on USB_HID
-	help
-	  Say Y here if you want support for the special keys (Fn, Numlock) on
-	  Apple iBooks and PowerBooks.
-
-	  If unsure, say N.
-
-config HID_FF
-	bool "Force feedback support (EXPERIMENTAL)"
-	depends on USB_HID && EXPERIMENTAL
-	help
-	  Say Y here is you want force feedback support for a few HID devices.
-	  See below for a list of supported devices.
-
-	  See <file:Documentation/input/ff.txt> for a description of the force
-	  feedback API.
-
-	  If unsure, say N.
-
-config HID_PID
-	bool "PID device support"
-	depends on HID_FF
-	help
-	  Say Y here if you have a PID-compliant device and wish to enable force
-	  feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such
-	  devices.
-
-config LOGITECH_FF
-	bool "Logitech devices support"
-	depends on HID_FF
-	select INPUT_FF_MEMLESS if USB_HID
-	help
-	  Say Y here if you have one of these devices:
-	  - Logitech WingMan Cordless RumblePad
-	  - Logitech WingMan Cordless RumblePad 2
-	  - Logitech WingMan Force 3D
-	  - Logitech Formula Force EX
-	  - Logitech MOMO Force wheel
-
-	  and if you want to enable force feedback for them.
-	  Note: if you say N here, this device will still be supported, but without
-	  force feedback.
-
-config PANTHERLORD_FF
-	bool "PantherLord USB/PS2 2in1 Adapter support"
-	depends on HID_FF
-	select INPUT_FF_MEMLESS if USB_HID
-	help
-	  Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want
-	  to enable force feedback support for it.
-
-config THRUSTMASTER_FF
-	bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)"
-	depends on HID_FF && EXPERIMENTAL
-	select INPUT_FF_MEMLESS if USB_HID
-	help
-	  Say Y here if you have a THRUSTMASTER FireStore Dual Power 2,
-	  and want to enable force feedback support for it.
-	  Note: if you say N here, this device will still be supported, but without
-	  force feedback.
-
-config ZEROPLUS_FF
-	bool "Zeroplus based game controller support"
-	depends on HID_FF
-	select INPUT_FF_MEMLESS if USB_HID
-	help
-	  Say Y here if you have a Zeroplus based game controller and want to
-	  enable force feedback for it.
-
-config USB_HIDDEV
-	bool "/dev/hiddev raw HID device support"
-	depends on USB_HID
-	help
-	  Say Y here if you want to support HID devices (from the USB
-	  specification standpoint) that aren't strictly user interface
-	  devices, like monitor controls and Uninterruptable Power Supplies.
-
-	  This module supports these devices separately using a separate
-	  event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
-
-	  If unsure, say Y.
-
-menu "USB HID Boot Protocol drivers"
-	depends on USB!=n && USB_HID!=y
-
-config USB_KBD
-	tristate "USB HIDBP Keyboard (simple Boot) support"
-	depends on USB && INPUT
-	---help---
-	  Say Y here only if you are absolutely sure that you don't want
-	  to use the generic HID driver for your USB keyboard and prefer
-	  to use the keyboard in its limited Boot Protocol mode instead.
-
-	  This is almost certainly not what you want.  This is mostly
-	  useful for embedded applications or simple keyboards.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called usbkbd.
-
-	  If even remotely unsure, say N.
-
-config USB_MOUSE
-	tristate "USB HIDBP Mouse (simple Boot) support"
-	depends on USB && INPUT
-	---help---
-	  Say Y here only if you are absolutely sure that you don't want
-	  to use the generic HID driver for your USB mouse and prefer
-	  to use the mouse in its limited Boot Protocol mode instead.
-
-	  This is almost certainly not what you want.  This is mostly
-	  useful for embedded applications or simple mice.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called usbmouse.
-
-	  If even remotely unsure, say N.
-
-endmenu
-
 config USB_AIPTEK
 	tristate "Aiptek 6000U/8000U tablet support"
 	depends on USB && INPUT
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index f8c35b6..284a073 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -4,40 +4,12 @@
 
 # Multipart objects.
 wacom-objs	:= wacom_wac.o wacom_sys.o
-usbhid-objs	:= hid-core.o
-
-# Optional parts of multipart objects.
-
-ifeq ($(CONFIG_USB_HIDDEV),y)
-	usbhid-objs	+= hiddev.o
-endif
-ifeq ($(CONFIG_HID_PID),y)
-	usbhid-objs	+= hid-pidff.o
-endif
-ifeq ($(CONFIG_LOGITECH_FF),y)
-	usbhid-objs	+= hid-lgff.o
-endif
-ifeq ($(CONFIG_PANTHERLORD_FF),y)
-	usbhid-objs	+= hid-plff.o
-endif
-ifeq ($(CONFIG_THRUSTMASTER_FF),y)
-	usbhid-objs	+= hid-tmff.o
-endif
-ifeq ($(CONFIG_ZEROPLUS_FF),y)
-	usbhid-objs	+= hid-zpff.o
-endif
-ifeq ($(CONFIG_HID_FF),y)
-	usbhid-objs	+= hid-ff.o
-endif
 
 obj-$(CONFIG_USB_AIPTEK)	+= aiptek.o
 obj-$(CONFIG_USB_ATI_REMOTE)	+= ati_remote.o
 obj-$(CONFIG_USB_ATI_REMOTE2)	+= ati_remote2.o
-obj-$(CONFIG_USB_HID)		+= usbhid.o
-obj-$(CONFIG_USB_KBD)		+= usbkbd.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
 obj-$(CONFIG_USB_KEYSPAN_REMOTE)	+= keyspan_remote.o
-obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o
 obj-$(CONFIG_USB_TOUCHSCREEN)	+= usbtouchscreen.o
 obj-$(CONFIG_USB_POWERMATE)	+= powermate.o
 obj-$(CONFIG_USB_WACOM)		+= wacom.o
@@ -45,7 +17,7 @@
 obj-$(CONFIG_USB_YEALINK)	+= yealink.o
 obj-$(CONFIG_USB_XPAD)		+= xpad.o
 obj-$(CONFIG_USB_APPLETOUCH)	+= appletouch.o
-obj-$(CONFIG_USB_GTCO)         += gtco.o
+obj-$(CONFIG_USB_GTCO)		+= gtco.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/usb/input/gtco.c b/drivers/usb/input/gtco.c
index dbd207e..b2ca10f2f 100644
--- a/drivers/usb/input/gtco.c
+++ b/drivers/usb/input/gtco.c
@@ -223,7 +223,7 @@
 	__u32 oldval[TAG_GLOB_MAX];
 
 	/* Debug stuff */
-	char  maintype='x';
+	char  maintype = 'x';
 	char  globtype[12];
 	int   indent = 0;
 	char  indentstr[10] = "";
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
deleted file mode 100644
index 4d8ed3d..0000000
--- a/drivers/usb/input/hid-core.c
+++ /dev/null
@@ -1,1459 +0,0 @@
-/*
- *  USB HID support for Linux
- *
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006 Jiri Kosina
- */
-
-/*
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-#include <linux/input.h>
-#include <linux/wait.h>
-
-#undef DEBUG
-#undef DEBUG_DATA
-
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include <linux/hiddev.h>
-#include <linux/hid-debug.h>
-#include "usbhid.h"
-
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v2.6"
-#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
-#define DRIVER_DESC "USB HID core driver"
-#define DRIVER_LICENSE "GPL"
-
-static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
-				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
-/*
- * Module parameters.
- */
-
-static unsigned int hid_mousepoll_interval;
-module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
-MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
-
-/*
- * Input submission and I/O error handler.
- */
-
-static void hid_io_error(struct hid_device *hid);
-
-/* Start up the input URB */
-static int hid_start_in(struct hid_device *hid)
-{
-	unsigned long flags;
-	int rc = 0;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	spin_lock_irqsave(&usbhid->inlock, flags);
-	if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
-			!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
-		rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
-		if (rc != 0)
-			clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-	}
-	spin_unlock_irqrestore(&usbhid->inlock, flags);
-	return rc;
-}
-
-/* I/O retry timer routine */
-static void hid_retry_timeout(unsigned long _hid)
-{
-	struct hid_device *hid = (struct hid_device *) _hid;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
-	if (hid_start_in(hid))
-		hid_io_error(hid);
-}
-
-/* Workqueue routine to reset the device or clear a halt */
-static void hid_reset(struct work_struct *work)
-{
-	struct usbhid_device *usbhid =
-		container_of(work, struct usbhid_device, reset_work);
-	struct hid_device *hid = usbhid->hid;
-	int rc_lock, rc = 0;
-
-	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
-		dev_dbg(&usbhid->intf->dev, "clear halt\n");
-		rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe);
-		clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
-		hid_start_in(hid);
-	}
-
-	else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
-		dev_dbg(&usbhid->intf->dev, "resetting device\n");
-		rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
-		if (rc_lock >= 0) {
-			rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf);
-			if (rc_lock)
-				usb_unlock_device(hid_to_usb_dev(hid));
-		}
-		clear_bit(HID_RESET_PENDING, &usbhid->iofl);
-	}
-
-	switch (rc) {
-	case 0:
-		if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
-			hid_io_error(hid);
-		break;
-	default:
-		err("can't reset device, %s-%s/input%d, status %d",
-				hid_to_usb_dev(hid)->bus->bus_name,
-				hid_to_usb_dev(hid)->devpath,
-				usbhid->ifnum, rc);
-		/* FALLTHROUGH */
-	case -EHOSTUNREACH:
-	case -ENODEV:
-	case -EINTR:
-		break;
-	}
-}
-
-/* Main I/O error handler */
-static void hid_io_error(struct hid_device *hid)
-{
-	unsigned long flags;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	spin_lock_irqsave(&usbhid->inlock, flags);
-
-	/* Stop when disconnected */
-	if (usb_get_intfdata(usbhid->intf) == NULL)
-		goto done;
-
-	/* When an error occurs, retry at increasing intervals */
-	if (usbhid->retry_delay == 0) {
-		usbhid->retry_delay = 13;	/* Then 26, 52, 104, 104, ... */
-		usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
-	} else if (usbhid->retry_delay < 100)
-		usbhid->retry_delay *= 2;
-
-	if (time_after(jiffies, usbhid->stop_retry)) {
-
-		/* Retries failed, so do a port reset */
-		if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
-			schedule_work(&usbhid->reset_work);
-			goto done;
-		}
-	}
-
-	mod_timer(&usbhid->io_retry,
-			jiffies + msecs_to_jiffies(usbhid->retry_delay));
-done:
-	spin_unlock_irqrestore(&usbhid->inlock, flags);
-}
-
-/*
- * Input interrupt completion handler.
- */
-
-static void hid_irq_in(struct urb *urb)
-{
-	struct hid_device	*hid = urb->context;
-	struct usbhid_device 	*usbhid = hid->driver_data;
-	int			status;
-
-	switch (urb->status) {
-		case 0:			/* success */
-			usbhid->retry_delay = 0;
-			hid_input_report(urb->context, HID_INPUT_REPORT,
-					 urb->transfer_buffer,
-					 urb->actual_length, 1);
-			break;
-		case -EPIPE:		/* stall */
-			clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-			set_bit(HID_CLEAR_HALT, &usbhid->iofl);
-			schedule_work(&usbhid->reset_work);
-			return;
-		case -ECONNRESET:	/* unlink */
-		case -ENOENT:
-		case -ESHUTDOWN:	/* unplug */
-			clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-			return;
-		case -EILSEQ:		/* protocol error or unplug */
-		case -EPROTO:		/* protocol error or unplug */
-		case -ETIME:		/* protocol error or unplug */
-		case -ETIMEDOUT:	/* Should never happen, but... */
-			clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-			hid_io_error(hid);
-			return;
-		default:		/* error */
-			warn("input irq status %d received", urb->status);
-	}
-
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status) {
-		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-		if (status != -EPERM) {
-			err("can't resubmit intr, %s-%s/input%d, status %d",
-					hid_to_usb_dev(hid)->bus->bus_name,
-					hid_to_usb_dev(hid)->devpath,
-					usbhid->ifnum, status);
-			hid_io_error(hid);
-		}
-	}
-}
-
-static int hid_submit_out(struct hid_device *hid)
-{
-	struct hid_report *report;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	report = usbhid->out[usbhid->outtail];
-
-	hid_output_report(report, usbhid->outbuf);
-	usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-	usbhid->urbout->dev = hid_to_usb_dev(hid);
-
-	dbg("submitting out urb");
-
-	if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
-		err("usb_submit_urb(out) failed");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int hid_submit_ctrl(struct hid_device *hid)
-{
-	struct hid_report *report;
-	unsigned char dir;
-	int len;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	report = usbhid->ctrl[usbhid->ctrltail].report;
-	dir = usbhid->ctrl[usbhid->ctrltail].dir;
-
-	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-	if (dir == USB_DIR_OUT) {
-		hid_output_report(report, usbhid->ctrlbuf);
-		usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
-		usbhid->urbctrl->transfer_buffer_length = len;
-	} else {
-		int maxpacket, padlen;
-
-		usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
-		maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0);
-		if (maxpacket > 0) {
-			padlen = (len + maxpacket - 1) / maxpacket;
-			padlen *= maxpacket;
-			if (padlen > usbhid->bufsize)
-				padlen = usbhid->bufsize;
-		} else
-			padlen = 0;
-		usbhid->urbctrl->transfer_buffer_length = padlen;
-	}
-	usbhid->urbctrl->dev = hid_to_usb_dev(hid);
-
-	usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
-	usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
-	usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
-	usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
-	usbhid->cr->wLength = cpu_to_le16(len);
-
-	dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
-		usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
-		usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
-
-	if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
-		err("usb_submit_urb(ctrl) failed");
-		return -1;
-	}
-
-	return 0;
-}
-
-/*
- * Output interrupt completion handler.
- */
-
-static void hid_irq_out(struct urb *urb)
-{
-	struct hid_device *hid = urb->context;
-	struct usbhid_device *usbhid = hid->driver_data;
-	unsigned long flags;
-	int unplug = 0;
-
-	switch (urb->status) {
-		case 0:			/* success */
-			break;
-		case -ESHUTDOWN:	/* unplug */
-			unplug = 1;
-		case -EILSEQ:		/* protocol error or unplug */
-		case -EPROTO:		/* protocol error or unplug */
-		case -ECONNRESET:	/* unlink */
-		case -ENOENT:
-			break;
-		default:		/* error */
-			warn("output irq status %d received", urb->status);
-	}
-
-	spin_lock_irqsave(&usbhid->outlock, flags);
-
-	if (unplug)
-		usbhid->outtail = usbhid->outhead;
-	else
-		usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
-
-	if (usbhid->outhead != usbhid->outtail) {
-		if (hid_submit_out(hid)) {
-			clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
-			wake_up(&hid->wait);
-		}
-		spin_unlock_irqrestore(&usbhid->outlock, flags);
-		return;
-	}
-
-	clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
-	spin_unlock_irqrestore(&usbhid->outlock, flags);
-	wake_up(&hid->wait);
-}
-
-/*
- * Control pipe completion handler.
- */
-
-static void hid_ctrl(struct urb *urb)
-{
-	struct hid_device *hid = urb->context;
-	struct usbhid_device *usbhid = hid->driver_data;
-	unsigned long flags;
-	int unplug = 0;
-
-	spin_lock_irqsave(&usbhid->ctrllock, flags);
-
-	switch (urb->status) {
-		case 0:			/* success */
-			if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
-				hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
-						urb->transfer_buffer, urb->actual_length, 0);
-			break;
-		case -ESHUTDOWN:	/* unplug */
-			unplug = 1;
-		case -EILSEQ:		/* protocol error or unplug */
-		case -EPROTO:		/* protocol error or unplug */
-		case -ECONNRESET:	/* unlink */
-		case -ENOENT:
-		case -EPIPE:		/* report not available */
-			break;
-		default:		/* error */
-			warn("ctrl urb status %d received", urb->status);
-	}
-
-	if (unplug)
-		usbhid->ctrltail = usbhid->ctrlhead;
-	else
-		usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
-
-	if (usbhid->ctrlhead != usbhid->ctrltail) {
-		if (hid_submit_ctrl(hid)) {
-			clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
-			wake_up(&hid->wait);
-		}
-		spin_unlock_irqrestore(&usbhid->ctrllock, flags);
-		return;
-	}
-
-	clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
-	spin_unlock_irqrestore(&usbhid->ctrllock, flags);
-	wake_up(&hid->wait);
-}
-
-void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
-{
-	int head;
-	unsigned long flags;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
-		return;
-
-	if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
-
-		spin_lock_irqsave(&usbhid->outlock, flags);
-
-		if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
-			spin_unlock_irqrestore(&usbhid->outlock, flags);
-			warn("output queue full");
-			return;
-		}
-
-		usbhid->out[usbhid->outhead] = report;
-		usbhid->outhead = head;
-
-		if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
-			if (hid_submit_out(hid))
-				clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
-
-		spin_unlock_irqrestore(&usbhid->outlock, flags);
-		return;
-	}
-
-	spin_lock_irqsave(&usbhid->ctrllock, flags);
-
-	if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
-		spin_unlock_irqrestore(&usbhid->ctrllock, flags);
-		warn("control queue full");
-		return;
-	}
-
-	usbhid->ctrl[usbhid->ctrlhead].report = report;
-	usbhid->ctrl[usbhid->ctrlhead].dir = dir;
-	usbhid->ctrlhead = head;
-
-	if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
-		if (hid_submit_ctrl(hid))
-			clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
-
-	spin_unlock_irqrestore(&usbhid->ctrllock, flags);
-}
-
-static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	struct hid_device *hid = dev->private;
-	struct hid_field *field;
-	int offset;
-
-	if (type == EV_FF)
-		return input_ff_event(dev, type, code, value);
-
-	if (type != EV_LED)
-		return -1;
-
-	if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
-		warn("event field not found");
-		return -1;
-	}
-
-	hid_set_field(field, offset, value);
-	usbhid_submit_report(hid, field->report, USB_DIR_OUT);
-
-	return 0;
-}
-
-int usbhid_wait_io(struct hid_device *hid)
-{
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
-					!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
-					10*HZ)) {
-		dbg("timeout waiting for ctrl or out queue to clear");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report,
-		ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
-}
-
-static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
-		unsigned char type, void *buf, int size)
-{
-	int result, retries = 4;
-
-	memset(buf, 0, size);
-
-	do {
-		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-				USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
-				(type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT);
-		retries--;
-	} while (result < size && retries);
-	return result;
-}
-
-int usbhid_open(struct hid_device *hid)
-{
-	++hid->open;
-	if (hid_start_in(hid))
-		hid_io_error(hid);
-	return 0;
-}
-
-void usbhid_close(struct hid_device *hid)
-{
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	if (!--hid->open)
-		usb_kill_urb(usbhid->urbin);
-}
-
-#define USB_VENDOR_ID_PANJIT		0x134c
-
-#define USB_VENDOR_ID_TURBOX		0x062a
-#define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
-
-/*
- * Initialize all reports
- */
-
-void usbhid_init_reports(struct hid_device *hid)
-{
-	struct hid_report *report;
-	struct usbhid_device *usbhid = hid->driver_data;
-	int err, ret;
-
-	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
-		usbhid_submit_report(hid, report, USB_DIR_IN);
-
-	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
-		usbhid_submit_report(hid, report, USB_DIR_IN);
-
-	err = 0;
-	ret = usbhid_wait_io(hid);
-	while (ret) {
-		err |= ret;
-		if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
-			usb_kill_urb(usbhid->urbctrl);
-		if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
-			usb_kill_urb(usbhid->urbout);
-		ret = usbhid_wait_io(hid);
-	}
-
-	if (err)
-		warn("timeout initializing reports");
-}
-
-#define USB_VENDOR_ID_GTCO		0x078c
-#define USB_VENDOR_ID_GTCO_IPANEL_2     0x5543
-#define USB_DEVICE_ID_GTCO_90		0x0090
-#define USB_DEVICE_ID_GTCO_100		0x0100
-#define USB_DEVICE_ID_GTCO_101		0x0101
-#define USB_DEVICE_ID_GTCO_103		0x0103
-#define USB_DEVICE_ID_GTCO_104		0x0104
-#define USB_DEVICE_ID_GTCO_105		0x0105
-#define USB_DEVICE_ID_GTCO_106		0x0106
-#define USB_DEVICE_ID_GTCO_107		0x0107
-#define USB_DEVICE_ID_GTCO_108		0x0108
-#define USB_DEVICE_ID_GTCO_200		0x0200
-#define USB_DEVICE_ID_GTCO_201		0x0201
-#define USB_DEVICE_ID_GTCO_202		0x0202
-#define USB_DEVICE_ID_GTCO_203		0x0203
-#define USB_DEVICE_ID_GTCO_204		0x0204
-#define USB_DEVICE_ID_GTCO_205		0x0205
-#define USB_DEVICE_ID_GTCO_206		0x0206
-#define USB_DEVICE_ID_GTCO_207		0x0207
-#define USB_DEVICE_ID_GTCO_300		0x0300
-#define USB_DEVICE_ID_GTCO_301		0x0301
-#define USB_DEVICE_ID_GTCO_302		0x0302
-#define USB_DEVICE_ID_GTCO_303		0x0303
-#define USB_DEVICE_ID_GTCO_304		0x0304
-#define USB_DEVICE_ID_GTCO_305		0x0305
-#define USB_DEVICE_ID_GTCO_306		0x0306
-#define USB_DEVICE_ID_GTCO_307		0x0307
-#define USB_DEVICE_ID_GTCO_308		0x0308
-#define USB_DEVICE_ID_GTCO_309		0x0309
-#define USB_DEVICE_ID_GTCO_400		0x0400
-#define USB_DEVICE_ID_GTCO_401		0x0401
-#define USB_DEVICE_ID_GTCO_402		0x0402
-#define USB_DEVICE_ID_GTCO_403		0x0403
-#define USB_DEVICE_ID_GTCO_404		0x0404
-#define USB_DEVICE_ID_GTCO_405		0x0405
-#define USB_DEVICE_ID_GTCO_500		0x0500
-#define USB_DEVICE_ID_GTCO_501		0x0501
-#define USB_DEVICE_ID_GTCO_502		0x0502
-#define USB_DEVICE_ID_GTCO_503		0x0503
-#define USB_DEVICE_ID_GTCO_504		0x0504
-#define USB_DEVICE_ID_GTCO_1000		0x1000
-#define USB_DEVICE_ID_GTCO_1001		0x1001
-#define USB_DEVICE_ID_GTCO_1002		0x1002
-#define USB_DEVICE_ID_GTCO_1003		0x1003
-#define USB_DEVICE_ID_GTCO_1004		0x1004
-#define USB_DEVICE_ID_GTCO_1005		0x1005
-#define USB_DEVICE_ID_GTCO_1006		0x1006
-#define USB_DEVICE_ID_GTCO_8		0x0008
-#define USB_DEVICE_ID_GTCO_d            0x000d
-
-#define USB_VENDOR_ID_WACOM		0x056a
-
-#define USB_VENDOR_ID_ACECAD		0x0460
-#define USB_DEVICE_ID_ACECAD_FLAIR	0x0004
-#define USB_DEVICE_ID_ACECAD_302	0x0008
-
-#define USB_VENDOR_ID_KBGEAR		0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO	0x1001
-
-#define USB_VENDOR_ID_AIPTEK		0x08ca
-#define USB_DEVICE_ID_AIPTEK_01		0x0001
-#define USB_DEVICE_ID_AIPTEK_10		0x0010
-#define USB_DEVICE_ID_AIPTEK_20		0x0020
-#define USB_DEVICE_ID_AIPTEK_21		0x0021
-#define USB_DEVICE_ID_AIPTEK_22		0x0022
-#define USB_DEVICE_ID_AIPTEK_23		0x0023
-#define USB_DEVICE_ID_AIPTEK_24		0x0024
-
-#define USB_VENDOR_ID_GRIFFIN		0x077d
-#define USB_DEVICE_ID_POWERMATE		0x0410
-#define USB_DEVICE_ID_SOUNDKNOB		0x04AA
-
-#define USB_VENDOR_ID_ATEN		0x0557
-#define USB_DEVICE_ID_ATEN_UC100KM	0x2004
-#define USB_DEVICE_ID_ATEN_CS124U	0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM	0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM	0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC	0x2208
-
-#define USB_VENDOR_ID_TOPMAX		0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD	0x0103
-
-#define USB_VENDOR_ID_HAPP		0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING	0x0010
-#define USB_DEVICE_ID_UGCI_FLYING	0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
-
-#define USB_VENDOR_ID_MGE		0x0463
-#define USB_DEVICE_ID_MGE_UPS		0xffff
-#define USB_DEVICE_ID_MGE_UPS1		0x0001
-
-#define USB_VENDOR_ID_ONTRAK		0x0a07
-#define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
-
-#define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
-
-#define USB_VENDOR_ID_A4TECH		0x09da
-#define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
-
-#define USB_VENDOR_ID_AASHIMA		0x06d6
-#define USB_DEVICE_ID_AASHIMA_GAMEPAD	0x0025
-#define USB_DEVICE_ID_AASHIMA_PREDATOR	0x0026
-
-#define USB_VENDOR_ID_CYPRESS		0x04b4
-#define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
-#define USB_DEVICE_ID_CYPRESS_HIDCOM	0x5500
-#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE	0x7417
-
-#define USB_VENDOR_ID_BERKSHIRE		0x0c98
-#define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
-
-#define USB_VENDOR_ID_ALPS		0x0433
-#define USB_DEVICE_ID_IBM_GAMEPAD	0x1101
-
-#define USB_VENDOR_ID_SAITEK		0x06a3
-#define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
-
-#define USB_VENDOR_ID_NEC		0x073e
-#define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
-
-#define USB_VENDOR_ID_CHIC		0x05fe
-#define USB_DEVICE_ID_CHIC_GAMEPAD	0x0014
-
-#define USB_VENDOR_ID_GLAB		0x06c2
-#define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
-#define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
-#define USB_DEVICE_ID_0_0_4_IF_KIT	0x0040
-#define USB_DEVICE_ID_0_16_16_IF_KIT	0x0044
-#define USB_DEVICE_ID_8_8_8_IF_KIT	0x0045
-#define USB_DEVICE_ID_0_8_7_IF_KIT	0x0051
-#define USB_DEVICE_ID_0_8_8_IF_KIT	0x0053
-#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL	0x0058
-
-#define USB_VENDOR_ID_WISEGROUP		0x0925
-#define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
-#define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
-#define USB_DEVICE_ID_8_8_4_IF_KIT	0x8201
-#define USB_DEVICE_ID_DUAL_USB_JOYPAD   0x8866
-
-#define USB_VENDOR_ID_WISEGROUP_LTD	0x6677
-#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
-
-#define USB_VENDOR_ID_CODEMERCS		0x07c0
-#define USB_DEVICE_ID_CODEMERCS_IOW40	0x1500
-#define USB_DEVICE_ID_CODEMERCS_IOW24	0x1501
-#define USB_DEVICE_ID_CODEMERCS_IOW48	0x1502
-#define USB_DEVICE_ID_CODEMERCS_IOW28	0x1503
-
-#define USB_VENDOR_ID_DELORME		0x1163
-#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
-#define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
-
-#define USB_VENDOR_ID_MCC		0x09db
-#define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
-#define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
-
-#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
-
-#define USB_VENDOR_ID_LD		0x0f11
-#define USB_DEVICE_ID_LD_CASSY		0x1000
-#define USB_DEVICE_ID_LD_POCKETCASSY	0x1010
-#define USB_DEVICE_ID_LD_MOBILECASSY	0x1020
-#define USB_DEVICE_ID_LD_JWM		0x1080
-#define USB_DEVICE_ID_LD_DMMP		0x1081
-#define USB_DEVICE_ID_LD_UMIP		0x1090
-#define USB_DEVICE_ID_LD_XRAY1		0x1100
-#define USB_DEVICE_ID_LD_XRAY2		0x1101
-#define USB_DEVICE_ID_LD_VIDEOCOM	0x1200
-#define USB_DEVICE_ID_LD_COM3LAB	0x2000
-#define USB_DEVICE_ID_LD_TELEPORT	0x2010
-#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
-#define USB_DEVICE_ID_LD_POWERCONTROL	0x2030
-#define USB_DEVICE_ID_LD_MACHINETEST	0x2040
-
-#define USB_VENDOR_ID_APPLE		0x05ac
-#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI	0x020e
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO	0x020f
-#define USB_DEVICE_ID_APPLE_GEYSER_ANSI	0x0214
-#define USB_DEVICE_ID_APPLE_GEYSER_ISO	0x0215
-#define USB_DEVICE_ID_APPLE_GEYSER_JIS	0x0216
-#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI	0x0217
-#define USB_DEVICE_ID_APPLE_GEYSER3_ISO	0x0218
-#define USB_DEVICE_ID_APPLE_GEYSER3_JIS	0x0219
-#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI	0x021a
-#define USB_DEVICE_ID_APPLE_GEYSER4_ISO	0x021b
-#define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
-#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
-#define USB_DEVICE_ID_APPLE_IR		0x8240
-
-#define USB_VENDOR_ID_CHERRY		0x046a
-#define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
-
-#define USB_VENDOR_ID_YEALINK		0x6993
-#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
-
-#define USB_VENDOR_ID_ALCOR		0x058f
-#define USB_DEVICE_ID_ALCOR_USBRS232	0x9720
-
-#define USB_VENDOR_ID_SUN		0x0430
-#define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
-
-#define USB_VENDOR_ID_AIRCABLE		0x16CA
-#define USB_DEVICE_ID_AIRCABLE1		0x1502
-
-#define USB_VENDOR_ID_LOGITECH		0x046d
-#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER	0xc101
-
-#define USB_VENDOR_ID_IMATION		0x0718
-#define USB_DEVICE_ID_DISC_STAKKA	0xd000
-
-#define USB_VENDOR_ID_PANTHERLORD	0x0810
-#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK	0x0001
-
-#define USB_VENDOR_ID_SONY			0x054c
-#define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
-
-/*
- * Alphabetically sorted blacklist by quirk type.
- */
-
-static const struct hid_blacklist {
-	__u16 idVendor;
-	__u16 idProduct;
-	unsigned quirks;
-} hid_blacklist[] = {
-
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
-	{ 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_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, 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 },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
-
-	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
-
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
-	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
-
-	{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-
-	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
-
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE },
-
-	{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
-
-	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
-
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
-
-	{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
-
-	{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
-
-	{ 0, 0 }
-};
-
-/*
- * Traverse the supplied list of reports and find the longest
- */
-static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
-{
-	struct hid_report *report;
-	int size;
-
-	list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
-		size = ((report->size - 1) >> 3) + 1;
-		if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
-			size++;
-		if (*max < size)
-			*max = size;
-	}
-}
-
-static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
-{
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
-		return -1;
-	if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
-		return -1;
-	if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
-		return -1;
-	if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
-		return -1;
-
-	return 0;
-}
-
-static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
-{
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	if (usbhid->inbuf)
-		usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
-	if (usbhid->outbuf)
-		usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
-	if (usbhid->cr)
-		usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
-	if (usbhid->ctrlbuf)
-		usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
-}
-
-/*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-
-static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
-	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
-		info("Fixing up Cherry Cymotion report descriptor");
-		rdesc[11] = rdesc[16] = 0xff;
-		rdesc[12] = rdesc[17] = 0x03;
-	}
-}
-
-/*
- * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
- * to "operational".  Without this, the ps3 controller will not report any
- * events.
- */
-static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
-{
-	int result;
-	char *buf = kmalloc(18, GFP_KERNEL);
-
-	if (!buf)
-		return;
-
-	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-				 HID_REQ_GET_REPORT,
-				 USB_DIR_IN | USB_TYPE_CLASS |
-				 USB_RECIP_INTERFACE,
-				 (3 << 8) | 0xf2, ifnum, buf, 17,
-				 USB_CTRL_GET_TIMEOUT);
-
-	if (result < 0)
-		err("%s failed: %d\n", __func__, result);
-
-	kfree(buf);
-}
-
-static struct hid_device *usb_hid_configure(struct usb_interface *intf)
-{
-	struct usb_host_interface *interface = intf->cur_altsetting;
-	struct usb_device *dev = interface_to_usbdev (intf);
-	struct hid_descriptor *hdesc;
-	struct hid_device *hid;
-	unsigned quirks = 0, rsize = 0;
-	char *rdesc;
-	int n, len, insize = 0;
-	struct usbhid_device *usbhid;
-
-        /* Ignore all Wacom devices */
-        if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
-                return NULL;
-
-	for (n = 0; hid_blacklist[n].idVendor; n++)
-		if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
-			(hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
-				quirks = hid_blacklist[n].quirks;
-
-	/* Many keyboards and mice don't like to be polled for reports,
-	 * so we will always set the HID_QUIRK_NOGET flag for them. */
-	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
-		if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD ||
-			interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
-				quirks |= HID_QUIRK_NOGET;
-	}
-
-	if (quirks & HID_QUIRK_IGNORE)
-		return NULL;
-
-	if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
-		(interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
-			return NULL;
-
-
-	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
-	    (!interface->desc.bNumEndpoints ||
-	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
-		dbg("class descriptor not present\n");
-		return NULL;
-	}
-
-	for (n = 0; n < hdesc->bNumDescriptors; n++)
-		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
-			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
-
-	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
-		dbg("weird size of report descriptor (%u)", rsize);
-		return NULL;
-	}
-
-	if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
-		dbg("couldn't allocate rdesc memory");
-		return NULL;
-	}
-
-	hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
-
-	if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
-		dbg("reading report descriptor failed");
-		kfree(rdesc);
-		return NULL;
-	}
-
-	if ((quirks & HID_QUIRK_CYMOTION))
-		hid_fixup_cymotion_descriptor(rdesc, rsize);
-
-#ifdef DEBUG_DATA
-	printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
-	for (n = 0; n < rsize; n++)
-		printk(" %02x", (unsigned char) rdesc[n]);
-	printk("\n");
-#endif
-
-	if (!(hid = hid_parse_report(rdesc, n))) {
-		dbg("parsing report descriptor failed");
-		kfree(rdesc);
-		return NULL;
-	}
-
-	kfree(rdesc);
-	hid->quirks = quirks;
-
-	if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
-		goto fail;
-
-	hid->driver_data = usbhid;
-	usbhid->hid = hid;
-
-	usbhid->bufsize = HID_MIN_BUFFER_SIZE;
-	hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
-	hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
-	hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize);
-
-	if (usbhid->bufsize > HID_MAX_BUFFER_SIZE)
-		usbhid->bufsize = HID_MAX_BUFFER_SIZE;
-
-	hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
-
-	if (insize > HID_MAX_BUFFER_SIZE)
-		insize = HID_MAX_BUFFER_SIZE;
-
-	if (hid_alloc_buffers(dev, hid)) {
-		hid_free_buffers(dev, hid);
-		goto fail;
-	}
-
-	for (n = 0; n < interface->desc.bNumEndpoints; n++) {
-
-		struct usb_endpoint_descriptor *endpoint;
-		int pipe;
-		int interval;
-
-		endpoint = &interface->endpoint[n].desc;
-		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
-			continue;
-
-		interval = endpoint->bInterval;
-
-		/* Change the polling interval of mice. */
-		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
-			interval = hid_mousepoll_interval;
-
-		if (usb_endpoint_dir_in(endpoint)) {
-			if (usbhid->urbin)
-				continue;
-			if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
-				goto fail;
-			pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-			usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize,
-					 hid_irq_in, hid, interval);
-			usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
-			usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-		} else {
-			if (usbhid->urbout)
-				continue;
-			if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
-				goto fail;
-			pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
-			usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0,
-					 hid_irq_out, hid, interval);
-			usbhid->urbout->transfer_dma = usbhid->outbuf_dma;
-			usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-		}
-	}
-
-	if (!usbhid->urbin) {
-		err("couldn't find an input interrupt endpoint");
-		goto fail;
-	}
-
-	init_waitqueue_head(&hid->wait);
-
-	INIT_WORK(&usbhid->reset_work, hid_reset);
-	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
-
-	spin_lock_init(&usbhid->inlock);
-	spin_lock_init(&usbhid->outlock);
-	spin_lock_init(&usbhid->ctrllock);
-
-	hid->version = le16_to_cpu(hdesc->bcdHID);
-	hid->country = hdesc->bCountryCode;
-	hid->dev = &intf->dev;
-	usbhid->intf = intf;
-	usbhid->ifnum = interface->desc.bInterfaceNumber;
-
-	hid->name[0] = 0;
-
-	if (dev->manufacturer)
-		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
-
-	if (dev->product) {
-		if (dev->manufacturer)
-			strlcat(hid->name, " ", sizeof(hid->name));
-		strlcat(hid->name, dev->product, sizeof(hid->name));
-	}
-
-	if (!strlen(hid->name))
-		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
-			 le16_to_cpu(dev->descriptor.idVendor),
-			 le16_to_cpu(dev->descriptor.idProduct));
-
-	hid->bus = BUS_USB;
-	hid->vendor = dev->descriptor.idVendor;
-	hid->product = dev->descriptor.idProduct;
-
-	usb_make_path(dev, hid->phys, sizeof(hid->phys));
-	strlcat(hid->phys, "/input", sizeof(hid->phys));
-	len = strlen(hid->phys);
-	if (len < sizeof(hid->phys) - 1)
-		snprintf(hid->phys + len, sizeof(hid->phys) - len,
-			 "%d", intf->altsetting[0].desc.bInterfaceNumber);
-
-	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
-		hid->uniq[0] = 0;
-
-	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
-	if (!usbhid->urbctrl)
-		goto fail;
-
-	usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
-			     usbhid->ctrlbuf, 1, hid_ctrl, hid);
-	usbhid->urbctrl->setup_dma = usbhid->cr_dma;
-	usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
-	usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
-	hid->hidinput_input_event = usb_hidinput_input_event;
-	hid->hid_open = usbhid_open;
-	hid->hid_close = usbhid_close;
-#ifdef CONFIG_USB_HIDDEV
-	hid->hiddev_hid_event = hiddev_hid_event;
-	hid->hiddev_report_event = hiddev_report_event;
-#endif
-	return hid;
-
-fail:
-	usb_free_urb(usbhid->urbin);
-	usb_free_urb(usbhid->urbout);
-	usb_free_urb(usbhid->urbctrl);
-	hid_free_buffers(dev, hid);
-	hid_free_device(hid);
-
-	return NULL;
-}
-
-static void hid_disconnect(struct usb_interface *intf)
-{
-	struct hid_device *hid = usb_get_intfdata (intf);
-	struct usbhid_device *usbhid;
-
-	if (!hid)
-		return;
-
-	usbhid = hid->driver_data;
-
-	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
-	usb_set_intfdata(intf, NULL);
-	spin_unlock_irq(&usbhid->inlock);
-	usb_kill_urb(usbhid->urbin);
-	usb_kill_urb(usbhid->urbout);
-	usb_kill_urb(usbhid->urbctrl);
-
-	del_timer_sync(&usbhid->io_retry);
-	flush_scheduled_work();
-
-	if (hid->claimed & HID_CLAIMED_INPUT)
-		hidinput_disconnect(hid);
-	if (hid->claimed & HID_CLAIMED_HIDDEV)
-		hiddev_disconnect(hid);
-
-	usb_free_urb(usbhid->urbin);
-	usb_free_urb(usbhid->urbctrl);
-	usb_free_urb(usbhid->urbout);
-
-	hid_free_buffers(hid_to_usb_dev(hid), hid);
-	hid_free_device(hid);
-}
-
-static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct hid_device *hid;
-	char path[64];
-	int i;
-	char *c;
-
-	dbg("HID probe called for ifnum %d",
-			intf->altsetting->desc.bInterfaceNumber);
-
-	if (!(hid = usb_hid_configure(intf)))
-		return -ENODEV;
-
-	usbhid_init_reports(hid);
-	hid_dump_device(hid);
-
-	if (!hidinput_connect(hid))
-		hid->claimed |= HID_CLAIMED_INPUT;
-	if (!hiddev_connect(hid))
-		hid->claimed |= HID_CLAIMED_HIDDEV;
-
-	usb_set_intfdata(intf, hid);
-
-	if (!hid->claimed) {
-		printk ("HID device not claimed by input or hiddev\n");
-		hid_disconnect(intf);
-		return -ENODEV;
-	}
-
-	if ((hid->claimed & HID_CLAIMED_INPUT))
-		hid_ff_init(hid);
-
-	if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
-		hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
-			intf->cur_altsetting->desc.bInterfaceNumber);
-
-	printk(KERN_INFO);
-
-	if (hid->claimed & HID_CLAIMED_INPUT)
-		printk("input");
-	if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
-		printk(",");
-	if (hid->claimed & HID_CLAIMED_HIDDEV)
-		printk("hiddev%d", hid->minor);
-
-	c = "Device";
-	for (i = 0; i < hid->maxcollection; i++) {
-		if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
-		    (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
-		    (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) {
-			c = hid_types[hid->collection[i].usage & 0xffff];
-			break;
-		}
-	}
-
-	usb_make_path(interface_to_usbdev(intf), path, 63);
-
-	printk(": USB HID v%x.%02x %s [%s] on %s\n",
-		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
-
-	return 0;
-}
-
-static int hid_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct hid_device *hid = usb_get_intfdata (intf);
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
-	set_bit(HID_SUSPENDED, &usbhid->iofl);
-	spin_unlock_irq(&usbhid->inlock);
-	del_timer(&usbhid->io_retry);
-	usb_kill_urb(usbhid->urbin);
-	dev_dbg(&intf->dev, "suspend\n");
-	return 0;
-}
-
-static int hid_resume(struct usb_interface *intf)
-{
-	struct hid_device *hid = usb_get_intfdata (intf);
-	struct usbhid_device *usbhid = hid->driver_data;
-	int status;
-
-	clear_bit(HID_SUSPENDED, &usbhid->iofl);
-	usbhid->retry_delay = 0;
-	status = hid_start_in(hid);
-	dev_dbg(&intf->dev, "resume status %d\n", status);
-	return status;
-}
-
-/* Treat USB reset pretty much the same as suspend/resume */
-static void hid_pre_reset(struct usb_interface *intf)
-{
-	/* FIXME: What if the interface is already suspended? */
-	hid_suspend(intf, PMSG_ON);
-}
-
-static void hid_post_reset(struct usb_interface *intf)
-{
-	struct usb_device *dev = interface_to_usbdev (intf);
-
-	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
-	/* FIXME: Any more reinitialization needed? */
-
-	hid_resume(intf);
-}
-
-static struct usb_device_id hid_usb_ids [] = {
-	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
-		.bInterfaceClass = USB_INTERFACE_CLASS_HID },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hid_usb_ids);
-
-static struct usb_driver hid_driver = {
-	.name =		"usbhid",
-	.probe =	hid_probe,
-	.disconnect =	hid_disconnect,
-	.suspend =	hid_suspend,
-	.resume =	hid_resume,
-	.pre_reset =	hid_pre_reset,
-	.post_reset =	hid_post_reset,
-	.id_table =	hid_usb_ids,
-};
-
-static int __init hid_init(void)
-{
-	int retval;
-	retval = hiddev_init();
-	if (retval)
-		goto hiddev_init_fail;
-	retval = usb_register(&hid_driver);
-	if (retval)
-		goto usb_register_fail;
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-usb_register_fail:
-	hiddev_exit();
-hiddev_init_fail:
-	return retval;
-}
-
-static void __exit hid_exit(void)
-{
-	usb_deregister(&hid_driver);
-	hiddev_exit();
-}
-
-module_init(hid_init);
-module_exit(hid_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
deleted file mode 100644
index e431faa..0000000
--- a/drivers/usb/input/hid-ff.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $
- *
- *  Force feedback support for hid devices.
- *  Not all hid devices use the same protocol. For example, some use PID,
- *  other use their own proprietary procotol.
- *
- *  Copyright (c) 2002-2004 Johann Deneux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <johann.deneux@it.uu.se>
- */
-
-#include <linux/input.h>
-
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include "usbhid.h"
-
-/*
- * This table contains pointers to initializers. To add support for new
- * devices, you need to add the USB vendor and product ids here.
- */
-struct hid_ff_initializer {
-	u16 idVendor;
-	u16 idProduct;
-	int (*init)(struct hid_device*);
-};
-
-/*
- * We try pidff when no other driver is found because PID is the
- * standards compliant way of implementing force feedback in HID.
- * pidff_init() will quickly abort if the device doesn't appear to
- * be a PID device
- */
-static struct hid_ff_initializer inits[] = {
-#ifdef CONFIG_LOGITECH_FF
-	{ 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
-	{ 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
-	{ 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
-	{ 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
-	{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
-	{ 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
-#endif
-#ifdef CONFIG_PANTHERLORD_FF
-	{ 0x810, 0x0001, hid_plff_init },
-#endif
-#ifdef CONFIG_THRUSTMASTER_FF
-	{ 0x44f, 0xb304, hid_tmff_init },
-#endif
-#ifdef CONFIG_ZEROPLUS_FF
-	{ 0xc12, 0x0005, hid_zpff_init },
-	{ 0xc12, 0x0030, hid_zpff_init },
-#endif
-	{ 0,	 0,	 hid_pidff_init}  /* Matches anything */
-};
-
-int hid_ff_init(struct hid_device* hid)
-{
-	struct hid_ff_initializer *init;
-	int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
-	int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);
-
-	for (init = inits; init->idVendor; init++)
-		if (init->idVendor == vendor && init->idProduct == product)
-			break;
-
-	return init->init(hid);
-}
-EXPORT_SYMBOL_GPL(hid_ff_init);
-
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
deleted file mode 100644
index e6f3af3..0000000
--- a/drivers/usb/input/hid-lgff.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Force feedback support for hid-compliant for some of the devices from
- * Logitech, namely:
- * - WingMan Cordless RumblePad
- * - WingMan Force 3D
- *
- *  Copyright (c) 2002-2004 Johann Deneux
- *  Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <johann.deneux@it.uu.se>
- */
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct dev_type {
-	u16 idVendor;
-	u16 idProduct;
-	const signed short *ff;
-};
-
-static const signed short ff_rumble[] = {
-	FF_RUMBLE,
-	-1
-};
-
-static const signed short ff_joystick[] = {
-	FF_CONSTANT,
-	-1
-};
-
-static const struct dev_type devices[] = {
-	{ 0x046d, 0xc211, ff_rumble },
-	{ 0x046d, 0xc219, ff_rumble },
-	{ 0x046d, 0xc283, ff_joystick },
-	{ 0x046d, 0xc294, ff_joystick },
-	{ 0x046d, 0xc295, ff_joystick },
-	{ 0x046d, 0xca03, ff_joystick },
-};
-
-static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
-{
-	struct hid_device *hid = dev->private;
-	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-	int x, y;
-	unsigned int left, right;
-
-#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
-
-	switch (effect->type) {
-	case FF_CONSTANT:
-		x = effect->u.ramp.start_level + 0x7f;	/* 0x7f is center */
-		y = effect->u.ramp.end_level + 0x7f;
-		CLAMP(x);
-		CLAMP(y);
-		report->field[0]->value[0] = 0x51;
-		report->field[0]->value[1] = 0x08;
-		report->field[0]->value[2] = x;
-		report->field[0]->value[3] = y;
-		dbg("(x, y)=(%04x, %04x)", x, y);
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
-		break;
-
-	case FF_RUMBLE:
-		right = effect->u.rumble.strong_magnitude;
-		left = effect->u.rumble.weak_magnitude;
-		right = right * 0xff / 0xffff;
-		left = left * 0xff / 0xffff;
-		CLAMP(left);
-		CLAMP(right);
-		report->field[0]->value[0] = 0x42;
-		report->field[0]->value[1] = 0x00;
-		report->field[0]->value[2] = left;
-		report->field[0]->value[3] = right;
-		dbg("(left, right)=(%04x, %04x)", left, right);
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
-		break;
-	}
-	return 0;
-}
-
-int hid_lgff_init(struct hid_device* hid)
-{
-	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct input_dev *dev = hidinput->input;
-	struct hid_report *report;
-	struct hid_field *field;
-	const signed short *ff_bits = ff_joystick;
-	int error;
-	int i;
-
-	/* Find the report to use */
-	if (list_empty(report_list)) {
-		err("No output report found");
-		return -1;
-	}
-
-	/* Check that the report looks ok */
-	report = list_entry(report_list->next, struct hid_report, list);
-	if (!report) {
-		err("NULL output report");
-		return -1;
-	}
-
-	field = report->field[0];
-	if (!field) {
-		err("NULL field");
-		return -1;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(devices); i++) {
-		if (dev->id.vendor == devices[i].idVendor &&
-		    dev->id.product == devices[i].idProduct) {
-			ff_bits = devices[i].ff;
-			break;
-		}
-	}
-
-	for (i = 0; ff_bits[i] >= 0; i++)
-		set_bit(ff_bits[i], dev->ffbit);
-
-	error = input_ff_create_memless(dev, NULL, hid_lgff_play);
-	if (error)
-		return error;
-
-	printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
-
-	return 0;
-}
diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c
deleted file mode 100644
index f5a90e9..0000000
--- a/drivers/usb/input/hid-pidff.c
+++ /dev/null
@@ -1,1331 +0,0 @@
-/*
- *  Force feedback driver for USB HID PID compliant devices
- *
- *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg)
-
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-
-#include "usbhid.h"
-
-#define	PID_EFFECTS_MAX		64
-
-/* Report usage table used to put reports into an array */
-
-#define PID_SET_EFFECT		0
-#define PID_EFFECT_OPERATION	1
-#define PID_DEVICE_GAIN		2
-#define PID_POOL		3
-#define PID_BLOCK_LOAD		4
-#define PID_BLOCK_FREE		5
-#define PID_DEVICE_CONTROL	6
-#define PID_CREATE_NEW_EFFECT	7
-
-#define PID_REQUIRED_REPORTS	7
-
-#define PID_SET_ENVELOPE	8
-#define PID_SET_CONDITION	9
-#define PID_SET_PERIODIC	10
-#define PID_SET_CONSTANT	11
-#define PID_SET_RAMP		12
-static const u8 pidff_reports[] = {
-	0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab,
-	0x5a, 0x5f, 0x6e, 0x73, 0x74
-};
-
-/* device_control is really 0x95, but 0x96 specified as it is the usage of
-the only field in that report */
-
-/* Value usage tables used to put fields and values into arrays */
-
-#define PID_EFFECT_BLOCK_INDEX	0
-
-#define PID_DURATION		1
-#define PID_GAIN		2
-#define PID_TRIGGER_BUTTON	3
-#define PID_TRIGGER_REPEAT_INT	4
-#define PID_DIRECTION_ENABLE	5
-#define PID_START_DELAY		6
-static const u8 pidff_set_effect[] = {
-	0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7
-};
-
-#define PID_ATTACK_LEVEL	1
-#define PID_ATTACK_TIME		2
-#define PID_FADE_LEVEL		3
-#define PID_FADE_TIME		4
-static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e };
-
-#define PID_PARAM_BLOCK_OFFSET	1
-#define PID_CP_OFFSET		2
-#define PID_POS_COEFFICIENT	3
-#define PID_NEG_COEFFICIENT	4
-#define PID_POS_SATURATION	5
-#define PID_NEG_SATURATION	6
-#define PID_DEAD_BAND		7
-static const u8 pidff_set_condition[] = {
-	0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65
-};
-
-#define PID_MAGNITUDE		1
-#define PID_OFFSET		2
-#define PID_PHASE		3
-#define PID_PERIOD		4
-static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 };
-static const u8 pidff_set_constant[] = { 0x22, 0x70 };
-
-#define PID_RAMP_START		1
-#define PID_RAMP_END		2
-static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 };
-
-#define PID_RAM_POOL_AVAILABLE	1
-static const u8 pidff_block_load[] = { 0x22, 0xac };
-
-#define PID_LOOP_COUNT		1
-static const u8 pidff_effect_operation[] = { 0x22, 0x7c };
-
-static const u8 pidff_block_free[] = { 0x22 };
-
-#define PID_DEVICE_GAIN_FIELD	0
-static const u8 pidff_device_gain[] = { 0x7e };
-
-#define PID_RAM_POOL_SIZE	0
-#define PID_SIMULTANEOUS_MAX	1
-#define PID_DEVICE_MANAGED_POOL	2
-static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
-
-/* Special field key tables used to put special field keys into arrays */
-
-#define PID_ENABLE_ACTUATORS	0
-#define PID_RESET		1
-static const u8 pidff_device_control[] = { 0x97, 0x9a };
-
-#define PID_CONSTANT	0
-#define PID_RAMP	1
-#define PID_SQUARE	2
-#define PID_SINE	3
-#define PID_TRIANGLE	4
-#define PID_SAW_UP	5
-#define PID_SAW_DOWN	6
-#define PID_SPRING	7
-#define PID_DAMPER	8
-#define PID_INERTIA	9
-#define PID_FRICTION	10
-static const u8 pidff_effect_types[] = {
-	0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34,
-	0x40, 0x41, 0x42, 0x43
-};
-
-#define PID_BLOCK_LOAD_SUCCESS	0
-#define PID_BLOCK_LOAD_FULL	1
-static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
-
-#define PID_EFFECT_START	0
-#define PID_EFFECT_STOP		1
-static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
-
-struct pidff_usage {
-	struct hid_field *field;
-	s32 *value;
-};
-
-struct pidff_device {
-	struct hid_device *hid;
-
-	struct hid_report *reports[sizeof(pidff_reports)];
-
-	struct pidff_usage set_effect[sizeof(pidff_set_effect)];
-	struct pidff_usage set_envelope[sizeof(pidff_set_envelope)];
-	struct pidff_usage set_condition[sizeof(pidff_set_condition)];
-	struct pidff_usage set_periodic[sizeof(pidff_set_periodic)];
-	struct pidff_usage set_constant[sizeof(pidff_set_constant)];
-	struct pidff_usage set_ramp[sizeof(pidff_set_ramp)];
-
-	struct pidff_usage device_gain[sizeof(pidff_device_gain)];
-	struct pidff_usage block_load[sizeof(pidff_block_load)];
-	struct pidff_usage pool[sizeof(pidff_pool)];
-	struct pidff_usage effect_operation[sizeof(pidff_effect_operation)];
-	struct pidff_usage block_free[sizeof(pidff_block_free)];
-
-	/* Special field is a field that is not composed of
-	   usage<->value pairs that pidff_usage values are */
-
-	/* Special field in create_new_effect */
-	struct hid_field *create_new_effect_type;
-
-	/* Special fields in set_effect */
-	struct hid_field *set_effect_type;
-	struct hid_field *effect_direction;
-
-	/* Special field in device_control */
-	struct hid_field *device_control;
-
-	/* Special field in block_load */
-	struct hid_field *block_load_status;
-
-	/* Special field in effect_operation */
-	struct hid_field *effect_operation_status;
-
-	int control_id[sizeof(pidff_device_control)];
-	int type_id[sizeof(pidff_effect_types)];
-	int status_id[sizeof(pidff_block_load_status)];
-	int operation_id[sizeof(pidff_effect_operation_status)];
-
-	int pid_id[PID_EFFECTS_MAX];
-};
-
-/*
- * Scale an unsigned value with range 0..max for the given field
- */
-static int pidff_rescale(int i, int max, struct hid_field *field)
-{
-	return i * (field->logical_maximum - field->logical_minimum) / max +
-	    field->logical_minimum;
-}
-
-/*
- * Scale a signed value in range -0x8000..0x7fff for the given field
- */
-static int pidff_rescale_signed(int i, struct hid_field *field)
-{
-	return i == 0 ? 0 : i >
-	    0 ? i * field->logical_maximum / 0x7fff : i *
-	    field->logical_minimum / -0x8000;
-}
-
-static void pidff_set(struct pidff_usage *usage, u16 value)
-{
-	usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
-	debug("calculated from %d to %d", value, usage->value[0]);
-}
-
-static void pidff_set_signed(struct pidff_usage *usage, s16 value)
-{
-	if (usage->field->logical_minimum < 0)
-		usage->value[0] = pidff_rescale_signed(value, usage->field);
-	else {
-		if (value < 0)
-			usage->value[0] =
-			    pidff_rescale(-value, 0x8000, usage->field);
-		else
-			usage->value[0] =
-			    pidff_rescale(value, 0x7fff, usage->field);
-	}
-	debug("calculated from %d to %d", value, usage->value[0]);
-}
-
-/*
- * Send envelope report to the device
- */
-static void pidff_set_envelope_report(struct pidff_device *pidff,
-				      struct ff_envelope *envelope)
-{
-	pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] =
-	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-
-	pidff->set_envelope[PID_ATTACK_LEVEL].value[0] =
-	    pidff_rescale(envelope->attack_level >
-			  0x7fff ? 0x7fff : envelope->attack_level, 0x7fff,
-			  pidff->set_envelope[PID_ATTACK_LEVEL].field);
-	pidff->set_envelope[PID_FADE_LEVEL].value[0] =
-	    pidff_rescale(envelope->fade_level >
-			  0x7fff ? 0x7fff : envelope->fade_level, 0x7fff,
-			  pidff->set_envelope[PID_FADE_LEVEL].field);
-
-	pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
-	pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
-
-	debug("attack %u => %d", envelope->attack_level,
-	      pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
-
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
-			  USB_DIR_OUT);
-}
-
-/*
- * Test if the new envelope differs from old one
- */
-static int pidff_needs_set_envelope(struct ff_envelope *envelope,
-				    struct ff_envelope *old)
-{
-	return envelope->attack_level != old->attack_level ||
-	       envelope->fade_level != old->fade_level ||
-	       envelope->attack_length != old->attack_length ||
-	       envelope->fade_length != old->fade_length;
-}
-
-/*
- * Send constant force report to the device
- */
-static void pidff_set_constant_force_report(struct pidff_device *pidff,
-					    struct ff_effect *effect)
-{
-	pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-	pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
-			 effect->u.constant.level);
-
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
-			  USB_DIR_OUT);
-}
-
-/*
- * Test if the constant parameters have changed between effects
- */
-static int pidff_needs_set_constant(struct ff_effect *effect,
-				    struct ff_effect *old)
-{
-	return effect->u.constant.level != old->u.constant.level;
-}
-
-/*
- * Send set effect report to the device
- */
-static void pidff_set_effect_report(struct pidff_device *pidff,
-				    struct ff_effect *effect)
-{
-	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-	pidff->set_effect_type->value[0] =
-		pidff->create_new_effect_type->value[0];
-	pidff->set_effect[PID_DURATION].value[0] = effect->replay.length;
-	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
-	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
-		effect->trigger.interval;
-	pidff->set_effect[PID_GAIN].value[0] =
-		pidff->set_effect[PID_GAIN].field->logical_maximum;
-	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
-	pidff->effect_direction->value[0] =
-		pidff_rescale(effect->direction, 0xffff,
-				pidff->effect_direction);
-	pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
-
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
-			  USB_DIR_OUT);
-}
-
-/*
- * Test if the values used in set_effect have changed
- */
-static int pidff_needs_set_effect(struct ff_effect *effect,
-				  struct ff_effect *old)
-{
-	return effect->replay.length != old->replay.length ||
-	       effect->trigger.interval != old->trigger.interval ||
-	       effect->trigger.button != old->trigger.button ||
-	       effect->direction != old->direction ||
-	       effect->replay.delay != old->replay.delay;
-}
-
-/*
- * Send periodic effect report to the device
- */
-static void pidff_set_periodic_report(struct pidff_device *pidff,
-				      struct ff_effect *effect)
-{
-	pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-	pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE],
-			 effect->u.periodic.magnitude);
-	pidff_set_signed(&pidff->set_periodic[PID_OFFSET],
-			 effect->u.periodic.offset);
-	pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
-	pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
-
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
-			  USB_DIR_OUT);
-
-}
-
-/*
- * Test if periodic effect parameters have changed
- */
-static int pidff_needs_set_periodic(struct ff_effect *effect,
-				    struct ff_effect *old)
-{
-	return effect->u.periodic.magnitude != old->u.periodic.magnitude ||
-	       effect->u.periodic.offset != old->u.periodic.offset ||
-	       effect->u.periodic.phase != old->u.periodic.phase ||
-	       effect->u.periodic.period != old->u.periodic.period;
-}
-
-/*
- * Send condition effect reports to the device
- */
-static void pidff_set_condition_report(struct pidff_device *pidff,
-				       struct ff_effect *effect)
-{
-	int i;
-
-	pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-
-	for (i = 0; i < 2; i++) {
-		pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
-		pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
-				 effect->u.condition[i].center);
-		pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT],
-				 effect->u.condition[i].right_coeff);
-		pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT],
-				 effect->u.condition[i].left_coeff);
-		pidff_set(&pidff->set_condition[PID_POS_SATURATION],
-			  effect->u.condition[i].right_saturation);
-		pidff_set(&pidff->set_condition[PID_NEG_SATURATION],
-			  effect->u.condition[i].left_saturation);
-		pidff_set(&pidff->set_condition[PID_DEAD_BAND],
-			  effect->u.condition[i].deadband);
-		usbhid_wait_io(pidff->hid);
-		usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
-				  USB_DIR_OUT);
-	}
-}
-
-/*
- * Test if condition effect parameters have changed
- */
-static int pidff_needs_set_condition(struct ff_effect *effect,
-				     struct ff_effect *old)
-{
-	int i;
-	int ret = 0;
-
-	for (i = 0; i < 2; i++) {
-		struct ff_condition_effect *cond = &effect->u.condition[i];
-		struct ff_condition_effect *old_cond = &old->u.condition[i];
-
-		ret |= cond->center != old_cond->center ||
-		       cond->right_coeff != old_cond->right_coeff ||
-		       cond->left_coeff != old_cond->left_coeff ||
-		       cond->right_saturation != old_cond->right_saturation ||
-		       cond->left_saturation != old_cond->left_saturation ||
-		       cond->deadband != old_cond->deadband;
-	}
-
-	return ret;
-}
-
-/*
- * Send ramp force report to the device
- */
-static void pidff_set_ramp_force_report(struct pidff_device *pidff,
-					struct ff_effect *effect)
-{
-	pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-	pidff_set_signed(&pidff->set_ramp[PID_RAMP_START],
-			 effect->u.ramp.start_level);
-	pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
-			 effect->u.ramp.end_level);
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
-			  USB_DIR_OUT);
-}
-
-/*
- * Test if ramp force parameters have changed
- */
-static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old)
-{
-	return effect->u.ramp.start_level != old->u.ramp.start_level ||
-	       effect->u.ramp.end_level != old->u.ramp.end_level;
-}
-
-/*
- * Send a request for effect upload to the device
- *
- * Returns 0 if device reported success, -ENOSPC if the device reported memory
- * is full. Upon unknown response the function will retry for 60 times, if
- * still unsuccessful -EIO is returned.
- */
-static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
-{
-	int j;
-
-	pidff->create_new_effect_type->value[0] = efnum;
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
-			  USB_DIR_OUT);
-	debug("create_new_effect sent, type: %d", efnum);
-
-	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
-	pidff->block_load_status->value[0] = 0;
-	usbhid_wait_io(pidff->hid);
-
-	for (j = 0; j < 60; j++) {
-		debug("pid_block_load requested");
-		usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
-				  USB_DIR_IN);
-		usbhid_wait_io(pidff->hid);
-		if (pidff->block_load_status->value[0] ==
-		    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
-			debug("device reported free memory: %d bytes",
-			      pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
-				pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
-			return 0;
-		}
-		if (pidff->block_load_status->value[0] ==
-		    pidff->status_id[PID_BLOCK_LOAD_FULL]) {
-			debug("not enough memory free: %d bytes",
-			      pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
-				pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
-			return -ENOSPC;
-		}
-	}
-	printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n");
-	return -EIO;
-}
-
-/*
- * Play the effect with PID id n times
- */
-static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
-{
-	pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
-
-	if (n == 0) {
-		pidff->effect_operation_status->value[0] =
-			pidff->operation_id[PID_EFFECT_STOP];
-	} else {
-		pidff->effect_operation_status->value[0] =
-			pidff->operation_id[PID_EFFECT_START];
-		pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
-	}
-
-	usbhid_wait_io(pidff->hid);
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
-			  USB_DIR_OUT);
-}
-
-/**
- * Play the effect with effect id @effect_id for @value times
- */
-static int pidff_playback(struct input_dev *dev, int effect_id, int value)
-{
-	struct pidff_device *pidff = dev->ff->private;
-
-	pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
-
-	return 0;
-}
-
-/*
- * Erase effect with PID id
- */
-static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
-{
-	pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
-			  USB_DIR_OUT);
-}
-
-/*
- * Stop and erase effect with effect_id
- */
-static int pidff_erase_effect(struct input_dev *dev, int effect_id)
-{
-	struct pidff_device *pidff = dev->ff->private;
-	int pid_id = pidff->pid_id[effect_id];
-
-	debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]);
-	pidff_playback_pid(pidff, pid_id, 0);
-	pidff_erase_pid(pidff, pid_id);
-
-	return 0;
-}
-
-/*
- * Effect upload handler
- */
-static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
-			       struct ff_effect *old)
-{
-	struct pidff_device *pidff = dev->ff->private;
-	int type_id;
-	int error;
-
-	switch (effect->type) {
-	case FF_CONSTANT:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_CONSTANT]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_constant(effect, old))
-			pidff_set_constant_force_report(pidff, effect);
-		if (!old ||
-		    pidff_needs_set_envelope(&effect->u.constant.envelope,
-					&old->u.constant.envelope))
-			pidff_set_envelope_report(pidff,
-					&effect->u.constant.envelope);
-		break;
-
-	case FF_PERIODIC:
-		if (!old) {
-			switch (effect->u.periodic.waveform) {
-			case FF_SQUARE:
-				type_id = PID_SQUARE;
-				break;
-			case FF_TRIANGLE:
-				type_id = PID_TRIANGLE;
-				break;
-			case FF_SINE:
-				type_id = PID_SINE;
-				break;
-			case FF_SAW_UP:
-				type_id = PID_SAW_UP;
-				break;
-			case FF_SAW_DOWN:
-				type_id = PID_SAW_DOWN;
-				break;
-			default:
-				printk(KERN_ERR
-				       "hid-pidff: invalid waveform\n");
-				return -EINVAL;
-			}
-
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[type_id]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_periodic(effect, old))
-			pidff_set_periodic_report(pidff, effect);
-		if (!old ||
-		    pidff_needs_set_envelope(&effect->u.periodic.envelope,
-					&old->u.periodic.envelope))
-			pidff_set_envelope_report(pidff,
-					&effect->u.periodic.envelope);
-		break;
-
-	case FF_RAMP:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_RAMP]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_ramp(effect, old))
-			pidff_set_ramp_force_report(pidff, effect);
-		if (!old ||
-		    pidff_needs_set_envelope(&effect->u.ramp.envelope,
-					&old->u.ramp.envelope))
-			pidff_set_envelope_report(pidff,
-					&effect->u.ramp.envelope);
-		break;
-
-	case FF_SPRING:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_SPRING]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_condition(effect, old))
-			pidff_set_condition_report(pidff, effect);
-		break;
-
-	case FF_FRICTION:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_FRICTION]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_condition(effect, old))
-			pidff_set_condition_report(pidff, effect);
-		break;
-
-	case FF_DAMPER:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_DAMPER]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_condition(effect, old))
-			pidff_set_condition_report(pidff, effect);
-		break;
-
-	case FF_INERTIA:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_INERTIA]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_condition(effect, old))
-			pidff_set_condition_report(pidff, effect);
-		break;
-
-	default:
-		printk(KERN_ERR "hid-pidff: invalid type\n");
-		return -EINVAL;
-	}
-
-	if (!old)
-		pidff->pid_id[effect->id] =
-		    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-
-	debug("uploaded");
-
-	return 0;
-}
-
-/*
- * set_gain() handler
- */
-static void pidff_set_gain(struct input_dev *dev, u16 gain)
-{
-	struct pidff_device *pidff = dev->ff->private;
-
-	pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
-			  USB_DIR_OUT);
-}
-
-static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
-{
-	struct hid_field *field =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].field;
-
-	if (!magnitude) {
-		pidff_playback_pid(pidff, field->logical_minimum, 0);
-		return;
-	}
-
-	pidff_playback_pid(pidff, field->logical_minimum, 1);
-
-	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum;
-	pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING];
-	pidff->set_effect[PID_DURATION].value[0] = 0;
-	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
-	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
-	pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
-	pidff->set_effect[PID_START_DELAY].value[0] = 0;
-
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
-			  USB_DIR_OUT);
-}
-
-/*
- * pidff_set_autocenter() handler
- */
-static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
-{
-	struct pidff_device *pidff = dev->ff->private;
-
-	pidff_autocenter(pidff, magnitude);
-}
-
-/*
- * Find fields from a report and fill a pidff_usage
- */
-static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
-			     struct hid_report *report, int count, int strict)
-{
-	int i, j, k, found;
-
-	for (k = 0; k < count; k++) {
-		found = 0;
-		for (i = 0; i < report->maxfield; i++) {
-			if (report->field[i]->maxusage !=
-			    report->field[i]->report_count) {
-				debug("maxusage and report_count do not match, "
-				      "skipping");
-				continue;
-			}
-			for (j = 0; j < report->field[i]->maxusage; j++) {
-				if (report->field[i]->usage[j].hid ==
-				    (HID_UP_PID | table[k])) {
-					debug("found %d at %d->%d", k, i, j);
-					usage[k].field = report->field[i];
-					usage[k].value =
-						&report->field[i]->value[j];
-					found = 1;
-					break;
-				}
-			}
-			if (found)
-				break;
-		}
-		if (!found && strict) {
-			debug("failed to locate %d", k);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-/*
- * Return index into pidff_reports for the given usage
- */
-static int pidff_check_usage(int usage)
-{
-	int i;
-
-	for (i = 0; i < sizeof(pidff_reports); i++)
-		if (usage == (HID_UP_PID | pidff_reports[i]))
-			return i;
-
-	return -1;
-}
-
-/*
- * Find the reports and fill pidff->reports[]
- * report_type specifies either OUTPUT or FEATURE reports
- */
-static void pidff_find_reports(struct hid_device *hid, int report_type,
-			       struct pidff_device *pidff)
-{
-	struct hid_report *report;
-	int i, ret;
-
-	list_for_each_entry(report,
-			    &hid->report_enum[report_type].report_list, list) {
-		if (report->maxfield < 1)
-			continue;
-		ret = pidff_check_usage(report->field[0]->logical);
-		if (ret != -1) {
-			debug("found usage 0x%02x from field->logical",
-			      pidff_reports[ret]);
-			pidff->reports[ret] = report;
-			continue;
-		}
-
-		/*
-		 * Sometimes logical collections are stacked to indicate
-		 * different usages for the report and the field, in which
-		 * case we want the usage of the parent. However, Linux HID
-		 * implementation hides this fact, so we have to dig it up
-		 * ourselves
-		 */
-		i = report->field[0]->usage[0].collection_index;
-		if (i <= 0 ||
-		    hid->collection[i - 1].type != HID_COLLECTION_LOGICAL)
-			continue;
-		ret = pidff_check_usage(hid->collection[i - 1].usage);
-		if (ret != -1 && !pidff->reports[ret]) {
-			debug("found usage 0x%02x from collection array",
-			      pidff_reports[ret]);
-			pidff->reports[ret] = report;
-		}
-	}
-}
-
-/*
- * Test if the required reports have been found
- */
-static int pidff_reports_ok(struct pidff_device *pidff)
-{
-	int i;
-
-	for (i = 0; i <= PID_REQUIRED_REPORTS; i++) {
-		if (!pidff->reports[i]) {
-			debug("%d missing", i);
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-/*
- * Find a field with a specific usage within a report
- */
-static struct hid_field *pidff_find_special_field(struct hid_report *report,
-						  int usage, int enforce_min)
-{
-	int i;
-
-	for (i = 0; i < report->maxfield; i++) {
-		if (report->field[i]->logical == (HID_UP_PID | usage) &&
-		    report->field[i]->report_count > 0) {
-			if (!enforce_min ||
-			    report->field[i]->logical_minimum == 1)
-				return report->field[i];
-			else {
-				printk(KERN_ERR "hid-pidff: logical_minimum "
-					"is not 1 as it should be\n");
-				return NULL;
-			}
-		}
-	}
-	return NULL;
-}
-
-/*
- * Fill a pidff->*_id struct table
- */
-static int pidff_find_special_keys(int *keys, struct hid_field *fld,
-				   const u8 *usagetable, int count)
-{
-
-	int i, j;
-	int found = 0;
-
-	for (i = 0; i < count; i++) {
-		for (j = 0; j < fld->maxusage; j++) {
-			if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) {
-				keys[i] = j + 1;
-				found++;
-				break;
-			}
-		}
-	}
-	return found;
-}
-
-#define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \
-	pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
-		sizeof(pidff_ ## name))
-
-/*
- * Find and check the special fields
- */
-static int pidff_find_special_fields(struct pidff_device *pidff)
-{
-	debug("finding special fields");
-
-	pidff->create_new_effect_type =
-		pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
-					 0x25, 1);
-	pidff->set_effect_type =
-		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
-					 0x25, 1);
-	pidff->effect_direction =
-		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
-					 0x57, 0);
-	pidff->device_control =
-		pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
-					 0x96, 1);
-	pidff->block_load_status =
-		pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
-					 0x8b, 1);
-	pidff->effect_operation_status =
-		pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
-					 0x78, 1);
-
-	debug("search done");
-
-	if (!pidff->create_new_effect_type || !pidff->set_effect_type) {
-		printk(KERN_ERR "hid-pidff: effect lists not found\n");
-		return -1;
-	}
-
-	if (!pidff->effect_direction) {
-		printk(KERN_ERR "hid-pidff: direction field not found\n");
-		return -1;
-	}
-
-	if (!pidff->device_control) {
-		printk(KERN_ERR "hid-pidff: device control field not found\n");
-		return -1;
-	}
-
-	if (!pidff->block_load_status) {
-		printk(KERN_ERR
-		       "hid-pidff: block load status field not found\n");
-		return -1;
-	}
-
-	if (!pidff->effect_operation_status) {
-		printk(KERN_ERR
-		       "hid-pidff: effect operation field not found\n");
-		return -1;
-	}
-
-	pidff_find_special_keys(pidff->control_id, pidff->device_control,
-				pidff_device_control,
-				sizeof(pidff_device_control));
-
-	PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control);
-
-	if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
-				     effect_types)) {
-		printk(KERN_ERR "hid-pidff: no effect types found\n");
-		return -1;
-	}
-
-	if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status,
-				    block_load_status) !=
-			sizeof(pidff_block_load_status)) {
-		printk(KERN_ERR
-		       "hidpidff: block load status identifiers not found\n");
-		return -1;
-	}
-
-	if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status,
-				    effect_operation_status) !=
-			sizeof(pidff_effect_operation_status)) {
-		printk(KERN_ERR
-		       "hidpidff: effect operation identifiers not found\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-/**
- * Find the implemented effect types
- */
-static int pidff_find_effects(struct pidff_device *pidff,
-			      struct input_dev *dev)
-{
-	int i;
-
-	for (i = 0; i < sizeof(pidff_effect_types); i++) {
-		int pidff_type = pidff->type_id[i];
-		if (pidff->set_effect_type->usage[pidff_type].hid !=
-		    pidff->create_new_effect_type->usage[pidff_type].hid) {
-			printk(KERN_ERR "hid-pidff: "
-			       "effect type number %d is invalid\n", i);
-			return -1;
-		}
-	}
-
-	if (pidff->type_id[PID_CONSTANT])
-		set_bit(FF_CONSTANT, dev->ffbit);
-	if (pidff->type_id[PID_RAMP])
-		set_bit(FF_RAMP, dev->ffbit);
-	if (pidff->type_id[PID_SQUARE]) {
-		set_bit(FF_SQUARE, dev->ffbit);
-		set_bit(FF_PERIODIC, dev->ffbit);
-	}
-	if (pidff->type_id[PID_SINE]) {
-		set_bit(FF_SINE, dev->ffbit);
-		set_bit(FF_PERIODIC, dev->ffbit);
-	}
-	if (pidff->type_id[PID_TRIANGLE]) {
-		set_bit(FF_TRIANGLE, dev->ffbit);
-		set_bit(FF_PERIODIC, dev->ffbit);
-	}
-	if (pidff->type_id[PID_SAW_UP]) {
-		set_bit(FF_SAW_UP, dev->ffbit);
-		set_bit(FF_PERIODIC, dev->ffbit);
-	}
-	if (pidff->type_id[PID_SAW_DOWN]) {
-		set_bit(FF_SAW_DOWN, dev->ffbit);
-		set_bit(FF_PERIODIC, dev->ffbit);
-	}
-	if (pidff->type_id[PID_SPRING])
-		set_bit(FF_SPRING, dev->ffbit);
-	if (pidff->type_id[PID_DAMPER])
-		set_bit(FF_DAMPER, dev->ffbit);
-	if (pidff->type_id[PID_INERTIA])
-		set_bit(FF_INERTIA, dev->ffbit);
-	if (pidff->type_id[PID_FRICTION])
-		set_bit(FF_FRICTION, dev->ffbit);
-
-	return 0;
-
-}
-
-#define PIDFF_FIND_FIELDS(name, report, strict) \
-	pidff_find_fields(pidff->name, pidff_ ## name, \
-		pidff->reports[report], \
-		sizeof(pidff_ ## name), strict)
-
-/*
- * Fill and check the pidff_usages
- */
-static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
-{
-	int envelope_ok = 0;
-
-	if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown set_effect report layout\n");
-		return -ENODEV;
-	}
-
-	PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
-	if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown pid_block_load report layout\n");
-		return -ENODEV;
-	}
-
-	if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown effect_operation report layout\n");
-		return -ENODEV;
-	}
-
-	if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown pid_block_free report layout\n");
-		return -ENODEV;
-	}
-
-	if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1))
-		envelope_ok = 1;
-
-	if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev))
-		return -ENODEV;
-
-	if (!envelope_ok) {
-		if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
-			printk(KERN_WARNING "hid-pidff: "
-			       "has constant effect but no envelope\n");
-		if (test_and_clear_bit(FF_RAMP, dev->ffbit))
-			printk(KERN_WARNING "hid-pidff: "
-				"has ramp effect but no envelope\n");
-
-		if (test_and_clear_bit(FF_PERIODIC, dev->ffbit))
-			printk(KERN_WARNING "hid-pidff: "
-				"has periodic effect but no envelope\n");
-	}
-
-	if (test_bit(FF_CONSTANT, dev->ffbit) &&
-	    PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) {
-		printk(KERN_WARNING
-		       "hid-pidff: unknown constant effect layout\n");
-		clear_bit(FF_CONSTANT, dev->ffbit);
-	}
-
-	if (test_bit(FF_RAMP, dev->ffbit) &&
-	    PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) {
-		printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n");
-		clear_bit(FF_RAMP, dev->ffbit);
-	}
-
-	if ((test_bit(FF_SPRING, dev->ffbit) ||
-	     test_bit(FF_DAMPER, dev->ffbit) ||
-	     test_bit(FF_FRICTION, dev->ffbit) ||
-	     test_bit(FF_INERTIA, dev->ffbit)) &&
-	    PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
-		printk(KERN_WARNING
-		       "hid-pidff: unknown condition effect layout\n");
-		clear_bit(FF_SPRING, dev->ffbit);
-		clear_bit(FF_DAMPER, dev->ffbit);
-		clear_bit(FF_FRICTION, dev->ffbit);
-		clear_bit(FF_INERTIA, dev->ffbit);
-	}
-
-	if (test_bit(FF_PERIODIC, dev->ffbit) &&
-	    PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) {
-		printk(KERN_WARNING
-		       "hid-pidff: unknown periodic effect layout\n");
-		clear_bit(FF_PERIODIC, dev->ffbit);
-	}
-
-	PIDFF_FIND_FIELDS(pool, PID_POOL, 0);
-
-	if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1))
-		set_bit(FF_GAIN, dev->ffbit);
-
-	return 0;
-}
-
-/*
- * Reset the device
- */
-static void pidff_reset(struct pidff_device *pidff)
-{
-	struct hid_device *hid = pidff->hid;
-	int i = 0;
-
-	pidff->device_control->value[0] = pidff->control_id[PID_RESET];
-	/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
-	usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-	usbhid_wait_io(hid);
-	usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-	usbhid_wait_io(hid);
-
-	pidff->device_control->value[0] =
-		pidff->control_id[PID_ENABLE_ACTUATORS];
-	usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-	usbhid_wait_io(hid);
-
-	/* pool report is sometimes messed up, refetch it */
-	usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
-	usbhid_wait_io(hid);
-
-	if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
-		int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0];
-		while (sim_effects < 2) {
-			if (i++ > 20) {
-				printk(KERN_WARNING "hid-pidff: device reports "
-				       "%d simultaneous effects\n",
-				       sim_effects);
-				break;
-			}
-			debug("pid_pool requested again");
-			usbhid_submit_report(hid, pidff->reports[PID_POOL],
-					  USB_DIR_IN);
-			usbhid_wait_io(hid);
-		}
-	}
-}
-
-/*
- * Test if autocenter modification is using the supported method
- */
-static int pidff_check_autocenter(struct pidff_device *pidff,
-				  struct input_dev *dev)
-{
-	int error;
-
-	/*
-	 * Let's find out if autocenter modification is supported
-	 * Specification doesn't specify anything, so we request an
-	 * effect upload and cancel it immediately. If the approved
-	 * effect id was one above the minimum, then we assume the first
-	 * effect id is a built-in spring type effect used for autocenter
-	 */
-
-	error = pidff_request_effect_upload(pidff, 1);
-	if (error) {
-		printk(KERN_ERR "hid-pidff: upload request failed\n");
-		return error;
-	}
-
-	if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] ==
-	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) {
-		pidff_autocenter(pidff, 0xffff);
-		set_bit(FF_AUTOCENTER, dev->ffbit);
-	} else {
-		printk(KERN_NOTICE "hid-pidff: "
-		       "device has unknown autocenter control method\n");
-	}
-
-	pidff_erase_pid(pidff,
-			pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]);
-
-	return 0;
-
-}
-
-/*
- * Check if the device is PID and initialize it
- */
-int hid_pidff_init(struct hid_device *hid)
-{
-	struct pidff_device *pidff;
-	struct hid_input *hidinput = list_entry(hid->inputs.next,
-						struct hid_input, list);
-	struct input_dev *dev = hidinput->input;
-	struct ff_device *ff;
-	int max_effects;
-	int error;
-
-	debug("starting pid init");
-
-	if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) {
-		debug("not a PID device, no output report");
-		return -ENODEV;
-	}
-
-	pidff = kzalloc(sizeof(*pidff), GFP_KERNEL);
-	if (!pidff)
-		return -ENOMEM;
-
-	pidff->hid = hid;
-
-	pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff);
-	pidff_find_reports(hid, HID_FEATURE_REPORT, pidff);
-
-	if (!pidff_reports_ok(pidff)) {
-		debug("reports not ok, aborting");
-		error = -ENODEV;
-		goto fail;
-	}
-
-	error = pidff_init_fields(pidff, dev);
-	if (error)
-		goto fail;
-
-	pidff_reset(pidff);
-
-	if (test_bit(FF_GAIN, dev->ffbit)) {
-		pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
-		usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
-				  USB_DIR_OUT);
-	}
-
-	error = pidff_check_autocenter(pidff, dev);
-	if (error)
-		goto fail;
-
-	max_effects =
-	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum -
-	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum +
-	    1;
-	debug("max effects is %d", max_effects);
-
-	if (max_effects > PID_EFFECTS_MAX)
-		max_effects = PID_EFFECTS_MAX;
-
-	if (pidff->pool[PID_SIMULTANEOUS_MAX].value)
-		debug("max simultaneous effects is %d",
-		      pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
-
-	if (pidff->pool[PID_RAM_POOL_SIZE].value)
-		debug("device memory size is %d bytes",
-		      pidff->pool[PID_RAM_POOL_SIZE].value[0]);
-
-	if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
-	    pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
-		printk(KERN_NOTICE "hid-pidff: "
-		       "device does not support device managed pool\n");
-		goto fail;
-	}
-
-	error = input_ff_create(dev, max_effects);
-	if (error)
-		goto fail;
-
-	ff = dev->ff;
-	ff->private = pidff;
-	ff->upload = pidff_upload_effect;
-	ff->erase = pidff_erase_effect;
-	ff->set_gain = pidff_set_gain;
-	ff->set_autocenter = pidff_set_autocenter;
-	ff->playback = pidff_playback;
-
-	printk(KERN_INFO "Force feedback for USB HID PID devices by "
-	       "Anssi Hannula <anssi.hannula@gmail.com>\n");
-
-	return 0;
-
- fail:
-	kfree(pidff);
-	return error;
-}
diff --git a/drivers/usb/input/hid-plff.c b/drivers/usb/input/hid-plff.c
deleted file mode 100644
index 76d2e6e..0000000
--- a/drivers/usb/input/hid-plff.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  Force feedback support for PantherLord USB/PS2 2in1 Adapter devices
- *
- *  Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg)
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct plff_device {
-	struct hid_report *report;
-};
-
-static int hid_plff_play(struct input_dev *dev, void *data,
-			 struct ff_effect *effect)
-{
-	struct hid_device *hid = dev->private;
-	struct plff_device *plff = data;
-	int left, right;
-
-	left = effect->u.rumble.strong_magnitude;
-	right = effect->u.rumble.weak_magnitude;
-	debug("called with 0x%04x 0x%04x", left, right);
-
-	left = left * 0x7f / 0xffff;
-	right = right * 0x7f / 0xffff;
-
-	plff->report->field[0]->value[2] = left;
-	plff->report->field[0]->value[3] = right;
-	debug("running with 0x%02x 0x%02x", left, right);
-	usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
-
-	return 0;
-}
-
-int hid_plff_init(struct hid_device *hid)
-{
-	struct plff_device *plff;
-	struct hid_report *report;
-	struct hid_input *hidinput;
-	struct list_head *report_list =
-			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct list_head *report_ptr = report_list;
-	struct input_dev *dev;
-	int error;
-
-	/* The device contains 2 output reports (one for each
-	   HID_QUIRK_MULTI_INPUT device), both containing 1 field, which
-	   contains 4 ff00.0002 usages and 4 16bit absolute values.
-
-	   The 2 input reports also contain a field which contains
-	   8 ff00.0001 usages and 8 boolean values. Their meaning is
-	   currently unknown. */
-
-	if (list_empty(report_list)) {
-		printk(KERN_ERR "hid-plff: no output reports found\n");
-		return -ENODEV;
-	}
-
-	list_for_each_entry(hidinput, &hid->inputs, list) {
-
-		report_ptr = report_ptr->next;
-
-		if (report_ptr == report_list) {
-			printk(KERN_ERR "hid-plff: required output report is missing\n");
-			return -ENODEV;
-		}
-
-		report = list_entry(report_ptr, struct hid_report, list);
-		if (report->maxfield < 1) {
-			printk(KERN_ERR "hid-plff: no fields in the report\n");
-			return -ENODEV;
-		}
-
-		if (report->field[0]->report_count < 4) {
-			printk(KERN_ERR "hid-plff: not enough values in the field\n");
-			return -ENODEV;
-		}
-
-		plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL);
-		if (!plff)
-			return -ENOMEM;
-
-		dev = hidinput->input;
-
-		set_bit(FF_RUMBLE, dev->ffbit);
-
-		error = input_ff_create_memless(dev, plff, hid_plff_play);
-		if (error) {
-			kfree(plff);
-			return error;
-		}
-
-		plff->report = report;
-		plff->report->field[0]->value[0] = 0x00;
-		plff->report->field[0]->value[1] = 0x00;
-		plff->report->field[0]->value[2] = 0x00;
-		plff->report->field[0]->value[3] = 0x00;
-		usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
-	}
-
-	printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 "
-	       "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n");
-
-	return 0;
-}
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c
deleted file mode 100644
index ab67331..0000000
--- a/drivers/usb/input/hid-tmff.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Force feedback support for various HID compliant devices by ThrustMaster:
- *    ThrustMaster FireStorm Dual Power 2
- * and possibly others whose device ids haven't been added.
- *
- *  Modified to support ThrustMaster devices by Zinx Verituse
- *  on 2003-01-25 from the Logitech force feedback driver,
- *  which is by Johann Deneux.
- *
- *  Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org>
- *  Copyright (c) 2002 Johann Deneux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/input.h>
-
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include "usbhid.h"
-
-/* Usages for thrustmaster devices I know about */
-#define THRUSTMASTER_USAGE_RUMBLE_LR	(HID_UP_GENDESK | 0xbb)
-
-
-struct tmff_device {
-	struct hid_report *report;
-	struct hid_field *rumble;
-};
-
-/* Changes values from 0 to 0xffff into values from minimum to maximum */
-static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum)
-{
-	int ret;
-
-	ret = (in * (maximum - minimum) / 0xffff) + minimum;
-	if (ret < minimum)
-		return minimum;
-	if (ret > maximum)
-		return maximum;
-	return ret;
-}
-
-static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
-{
-	struct hid_device *hid = dev->private;
-	struct tmff_device *tmff = data;
-	int left, right;	/* Rumbling */
-
-	left = hid_tmff_scale(effect->u.rumble.weak_magnitude,
-		tmff->rumble->logical_minimum, tmff->rumble->logical_maximum);
-	right = hid_tmff_scale(effect->u.rumble.strong_magnitude,
-		tmff->rumble->logical_minimum, tmff->rumble->logical_maximum);
-
-	tmff->rumble->value[0] = left;
-	tmff->rumble->value[1] = right;
-	dbg("(left,right)=(%08x, %08x)", left, right);
-	usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
-
-	return 0;
-}
-
-int hid_tmff_init(struct hid_device *hid)
-{
-	struct tmff_device *tmff;
-	struct list_head *pos;
-	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-	struct input_dev *input_dev = hidinput->input;
-	int error;
-
-	tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
-	if (!tmff)
-		return -ENOMEM;
-
-	/* Find the report to use */
-	__list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
-		struct hid_report *report = (struct hid_report *)pos;
-		int fieldnum;
-
-		for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
-			struct hid_field *field = report->field[fieldnum];
-
-			if (field->maxusage <= 0)
-				continue;
-
-			switch (field->usage[0].hid) {
-				case THRUSTMASTER_USAGE_RUMBLE_LR:
-					if (field->report_count < 2) {
-						warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2");
-						continue;
-					}
-
-					if (field->logical_maximum == field->logical_minimum) {
-						warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum");
-						continue;
-					}
-
-					if (tmff->report && tmff->report != report) {
-						warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report");
-						continue;
-					}
-
-					if (tmff->rumble && tmff->rumble != field) {
-						warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR");
-						continue;
-					}
-
-					tmff->report = report;
-					tmff->rumble = field;
-
-					set_bit(FF_RUMBLE, input_dev->ffbit);
-					break;
-
-				default:
-					warn("ignoring unknown output usage %08x", field->usage[0].hid);
-					continue;
-			}
-		}
-	}
-
-	error = input_ff_create_memless(input_dev, tmff, hid_tmff_play);
-	if (error) {
-		kfree(tmff);
-		return error;
-	}
-
-	info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>");
-
-	return 0;
-}
-
diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c
deleted file mode 100644
index 7bd8238..0000000
--- a/drivers/usb/input/hid-zpff.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *  Force feedback support for Zeroplus based devices
- *
- *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct zpff_device {
-	struct hid_report *report;
-};
-
-static int hid_zpff_play(struct input_dev *dev, void *data,
-			 struct ff_effect *effect)
-{
-	struct hid_device *hid = dev->private;
-	struct zpff_device *zpff = data;
-	int left, right;
-
-	/*
-	 * The following is specified the other way around in the Zeroplus
-	 * datasheet but the order below is correct for the XFX Executioner;
-	 * however it is possible that the XFX Executioner is an exception
-	 */
-
-	left = effect->u.rumble.strong_magnitude;
-	right = effect->u.rumble.weak_magnitude;
-	debug("called with 0x%04x 0x%04x", left, right);
-
-	left = left * 0x7f / 0xffff;
-	right = right * 0x7f / 0xffff;
-
-	zpff->report->field[2]->value[0] = left;
-	zpff->report->field[3]->value[0] = right;
-	debug("running with 0x%02x 0x%02x", left, right);
-	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
-
-	return 0;
-}
-
-int hid_zpff_init(struct hid_device *hid)
-{
-	struct zpff_device *zpff;
-	struct hid_report *report;
-	struct hid_input *hidinput = list_entry(hid->inputs.next,
-						struct hid_input, list);
-	struct list_head *report_list =
-			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct input_dev *dev = hidinput->input;
-	int error;
-
-	if (list_empty(report_list)) {
-		printk(KERN_ERR "hid-zpff: no output report found\n");
-		return -ENODEV;
-	}
-
-	report = list_entry(report_list->next, struct hid_report, list);
-
-	if (report->maxfield < 4) {
-		printk(KERN_ERR "hid-zpff: not enough fields in report\n");
-		return -ENODEV;
-	}
-
-	zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL);
-	if (!zpff)
-		return -ENOMEM;
-
-	set_bit(FF_RUMBLE, dev->ffbit);
-
-	error = input_ff_create_memless(dev, zpff, hid_zpff_play);
-	if (error) {
-		kfree(zpff);
-		return error;
-	}
-
-	zpff->report = report;
-	zpff->report->field[0]->value[0] = 0x00;
-	zpff->report->field[1]->value[0] = 0x02;
-	zpff->report->field[2]->value[0] = 0x00;
-	zpff->report->field[3]->value[0] = 0x00;
-	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
-
-	printk(KERN_INFO "Force feedback for Zeroplus based devices by "
-	       "Anssi Hannula <anssi.hannula@gmail.com>\n");
-
-	return 0;
-}
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
deleted file mode 100644
index a8b3d66..0000000
--- a/drivers/usb/input/hiddev.c
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
- *  Copyright (c) 2001 Paul Stewart
- *  Copyright (c) 2001 Vojtech Pavlik
- *
- *  HID char devices, giving access to raw HID device events.
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net>
- */
-
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include <linux/hiddev.h>
-#include "usbhid.h"
-
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define HIDDEV_MINOR_BASE	0
-#define HIDDEV_MINORS		256
-#else
-#define HIDDEV_MINOR_BASE	96
-#define HIDDEV_MINORS		16
-#endif
-#define HIDDEV_BUFFER_SIZE	64
-
-struct hiddev {
-	int exist;
-	int open;
-	wait_queue_head_t wait;
-	struct hid_device *hid;
-	struct list_head list;
-};
-
-struct hiddev_list {
-	struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
-	int head;
-	int tail;
-	unsigned flags;
-	struct fasync_struct *fasync;
-	struct hiddev *hiddev;
-	struct list_head node;
-};
-
-static struct hiddev *hiddev_table[HIDDEV_MINORS];
-
-/*
- * Find a report, given the report's type and ID.  The ID can be specified
- * indirectly by REPORT_ID_FIRST (which returns the first report of the given
- * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
- * given type which follows old_id.
- */
-static struct hid_report *
-hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
-{
-	unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
-	unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK;
-	struct hid_report_enum *report_enum;
-	struct hid_report *report;
-	struct list_head *list;
-
-	if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
-	    rinfo->report_type > HID_REPORT_TYPE_MAX)
-		return NULL;
-
-	report_enum = hid->report_enum +
-		(rinfo->report_type - HID_REPORT_TYPE_MIN);
-
-	switch (flags) {
-	case 0: /* Nothing to do -- report_id is already set correctly */
-		break;
-
-	case HID_REPORT_ID_FIRST:
-		if (list_empty(&report_enum->report_list))
-			return NULL;
-
-		list = report_enum->report_list.next;
-		report = list_entry(list, struct hid_report, list);
-		rinfo->report_id = report->id;
-		break;
-
-	case HID_REPORT_ID_NEXT:
-		report = report_enum->report_id_hash[rid];
-		if (!report)
-			return NULL;
-
-		list = report->list.next;
-		if (list == &report_enum->report_list)
-			return NULL;
-
-		report = list_entry(list, struct hid_report, list);
-		rinfo->report_id = report->id;
-		break;
-
-	default:
-		return NULL;
-	}
-
-	return report_enum->report_id_hash[rinfo->report_id];
-}
-
-/*
- * Perform an exhaustive search of the report table for a usage, given its
- * type and usage id.
- */
-static struct hid_field *
-hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
-{
-	int i, j;
-	struct hid_report *report;
-	struct hid_report_enum *report_enum;
-	struct hid_field *field;
-
-	if (uref->report_type < HID_REPORT_TYPE_MIN ||
-	    uref->report_type > HID_REPORT_TYPE_MAX)
-		return NULL;
-
-	report_enum = hid->report_enum +
-		(uref->report_type - HID_REPORT_TYPE_MIN);
-
-	list_for_each_entry(report, &report_enum->report_list, list) {
-		for (i = 0; i < report->maxfield; i++) {
-			field = report->field[i];
-			for (j = 0; j < field->maxusage; j++) {
-				if (field->usage[j].hid == uref->usage_code) {
-					uref->report_id = report->id;
-					uref->field_index = i;
-					uref->usage_index = j;
-					return field;
-				}
-			}
-		}
-	}
-
-	return NULL;
-}
-
-static void hiddev_send_event(struct hid_device *hid,
-			      struct hiddev_usage_ref *uref)
-{
-	struct hiddev *hiddev = hid->hiddev;
-	struct hiddev_list *list;
-
-	list_for_each_entry(list, &hiddev->list, node) {
-		if (uref->field_index != HID_FIELD_INDEX_NONE ||
-		    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
-			list->buffer[list->head] = *uref;
-			list->head = (list->head + 1) &
-				(HIDDEV_BUFFER_SIZE - 1);
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
-		}
-	}
-
-	wake_up_interruptible(&hiddev->wait);
-}
-
-/*
- * This is where hid.c calls into hiddev to pass an event that occurred over
- * the interrupt pipe
- */
-void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
-		      struct hid_usage *usage, __s32 value)
-{
-	unsigned type = field->report_type;
-	struct hiddev_usage_ref uref;
-
-	uref.report_type =
-	  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
-	  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
-	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
-	uref.report_id = field->report->id;
-	uref.field_index = field->index;
-	uref.usage_index = (usage - field->usage);
-	uref.usage_code = usage->hid;
-	uref.value = value;
-
-	hiddev_send_event(hid, &uref);
-}
-EXPORT_SYMBOL_GPL(hiddev_hid_event);
-
-void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
-{
-	unsigned type = report->type;
-	struct hiddev_usage_ref uref;
-
-	memset(&uref, 0, sizeof(uref));
-	uref.report_type =
-	  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
-	  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
-	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
-	uref.report_id = report->id;
-	uref.field_index = HID_FIELD_INDEX_NONE;
-
-	hiddev_send_event(hid, &uref);
-}
-
-/*
- * fasync file op
- */
-static int hiddev_fasync(int fd, struct file *file, int on)
-{
-	int retval;
-	struct hiddev_list *list = file->private_data;
-
-	retval = fasync_helper(fd, file, on, &list->fasync);
-
-	return retval < 0 ? retval : 0;
-}
-
-
-/*
- * release file op
- */
-static int hiddev_release(struct inode * inode, struct file * file)
-{
-	struct hiddev_list *list = file->private_data;
-
-	hiddev_fasync(-1, file, 0);
-	list_del(&list->node);
-
-	if (!--list->hiddev->open) {
-		if (list->hiddev->exist)
-			usbhid_close(list->hiddev->hid);
-		else
-			kfree(list->hiddev);
-	}
-
-	kfree(list);
-
-	return 0;
-}
-
-/*
- * open file op
- */
-static int hiddev_open(struct inode *inode, struct file *file)
-{
-	struct hiddev_list *list;
-
-	int i = iminor(inode) - HIDDEV_MINOR_BASE;
-
-	if (i >= HIDDEV_MINORS || !hiddev_table[i])
-		return -ENODEV;
-
-	if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
-		return -ENOMEM;
-
-	list->hiddev = hiddev_table[i];
-	list_add_tail(&list->node, &hiddev_table[i]->list);
-	file->private_data = list;
-
-	if (!list->hiddev->open++)
-		if (list->hiddev->exist)
-			usbhid_open(hiddev_table[i]->hid);
-
-	return 0;
-}
-
-/*
- * "write" file op
- */
-static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-/*
- * "read" file op
- */
-static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct hiddev_list *list = file->private_data;
-	int event_size;
-	int retval = 0;
-
-	event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
-		sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
-
-	if (count < event_size)
-		return 0;
-
-	while (retval == 0) {
-		if (list->head == list->tail) {
-			add_wait_queue(&list->hiddev->wait, &wait);
-			set_current_state(TASK_INTERRUPTIBLE);
-
-			while (list->head == list->tail) {
-				if (file->f_flags & O_NONBLOCK) {
-					retval = -EAGAIN;
-					break;
-				}
-				if (signal_pending(current)) {
-					retval = -ERESTARTSYS;
-					break;
-				}
-				if (!list->hiddev->exist) {
-					retval = -EIO;
-					break;
-				}
-
-				schedule();
-				set_current_state(TASK_INTERRUPTIBLE);
-			}
-
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&list->hiddev->wait, &wait);
-		}
-
-		if (retval)
-			return retval;
-
-
-		while (list->head != list->tail &&
-		       retval + event_size <= count) {
-			if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
-				if (list->buffer[list->tail].field_index !=
-				    HID_FIELD_INDEX_NONE) {
-					struct hiddev_event event;
-					event.hid = list->buffer[list->tail].usage_code;
-					event.value = list->buffer[list->tail].value;
-					if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
-						return -EFAULT;
-					retval += sizeof(struct hiddev_event);
-				}
-			} else {
-				if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
-				    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
-					if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
-						return -EFAULT;
-					retval += sizeof(struct hiddev_usage_ref);
-				}
-			}
-			list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
-		}
-
-	}
-
-	return retval;
-}
-
-/*
- * "poll" file op
- * No kernel lock - fine
- */
-static unsigned int hiddev_poll(struct file *file, poll_table *wait)
-{
-	struct hiddev_list *list = file->private_data;
-
-	poll_wait(file, &list->hiddev->wait, wait);
-	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
-	if (!list->hiddev->exist)
-		return POLLERR | POLLHUP;
-	return 0;
-}
-
-/*
- * "ioctl" file op
- */
-static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct hiddev_list *list = file->private_data;
-	struct hiddev *hiddev = list->hiddev;
-	struct hid_device *hid = hiddev->hid;
-	struct usb_device *dev = hid_to_usb_dev(hid);
-	struct hiddev_collection_info cinfo;
-	struct hiddev_report_info rinfo;
-	struct hiddev_field_info finfo;
-	struct hiddev_usage_ref_multi *uref_multi = NULL;
-	struct hiddev_usage_ref *uref;
-	struct hiddev_devinfo dinfo;
-	struct hid_report *report;
-	struct hid_field *field;
-	struct usbhid_device *usbhid = hid->driver_data;
-	void __user *user_arg = (void __user *)arg;
-	int i;
-
-	if (!hiddev->exist)
-		return -EIO;
-
-	switch (cmd) {
-
-	case HIDIOCGVERSION:
-		return put_user(HID_VERSION, (int __user *)arg);
-
-	case HIDIOCAPPLICATION:
-		if (arg < 0 || arg >= hid->maxapplication)
-			return -EINVAL;
-
-		for (i = 0; i < hid->maxcollection; i++)
-			if (hid->collection[i].type ==
-			    HID_COLLECTION_APPLICATION && arg-- == 0)
-				break;
-
-		if (i == hid->maxcollection)
-			return -EINVAL;
-
-		return hid->collection[i].usage;
-
-	case HIDIOCGDEVINFO:
-		dinfo.bustype = BUS_USB;
-		dinfo.busnum = dev->bus->busnum;
-		dinfo.devnum = dev->devnum;
-		dinfo.ifnum = usbhid->ifnum;
-		dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
-		dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
-		dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
-		dinfo.num_applications = hid->maxapplication;
-		if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
-			return -EFAULT;
-
-		return 0;
-
-	case HIDIOCGFLAG:
-		if (put_user(list->flags, (int __user *)arg))
-			return -EFAULT;
-
-		return 0;
-
-	case HIDIOCSFLAG:
-		{
-			int newflags;
-			if (get_user(newflags, (int __user *)arg))
-				return -EFAULT;
-
-			if ((newflags & ~HIDDEV_FLAGS) != 0 ||
-			    ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
-			     (newflags & HIDDEV_FLAG_UREF) == 0))
-				return -EINVAL;
-
-			list->flags = newflags;
-
-			return 0;
-		}
-
-	case HIDIOCGSTRING:
-		{
-			int idx, len;
-			char *buf;
-
-			if (get_user(idx, (int __user *)arg))
-				return -EFAULT;
-
-			if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
-				return -ENOMEM;
-
-			if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
-				kfree(buf);
-				return -EINVAL;
-			}
-
-			if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
-				kfree(buf);
-				return -EFAULT;
-			}
-
-			kfree(buf);
-
-			return len;
-		}
-
-	case HIDIOCINITREPORT:
-		usbhid_init_reports(hid);
-
-		return 0;
-
-	case HIDIOCGREPORT:
-		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
-			return -EFAULT;
-
-		if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
-			return -EINVAL;
-
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		usbhid_submit_report(hid, report, USB_DIR_IN);
-		usbhid_wait_io(hid);
-
-		return 0;
-
-	case HIDIOCSREPORT:
-		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
-			return -EFAULT;
-
-		if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
-			return -EINVAL;
-
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
-		usbhid_wait_io(hid);
-
-		return 0;
-
-	case HIDIOCGREPORTINFO:
-		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
-			return -EFAULT;
-
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		rinfo.num_fields = report->maxfield;
-
-		if (copy_to_user(user_arg, &rinfo, sizeof(rinfo)))
-			return -EFAULT;
-
-		return 0;
-
-	case HIDIOCGFIELDINFO:
-		if (copy_from_user(&finfo, user_arg, sizeof(finfo)))
-			return -EFAULT;
-		rinfo.report_type = finfo.report_type;
-		rinfo.report_id = finfo.report_id;
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		if (finfo.field_index >= report->maxfield)
-			return -EINVAL;
-
-		field = report->field[finfo.field_index];
-		memset(&finfo, 0, sizeof(finfo));
-		finfo.report_type = rinfo.report_type;
-		finfo.report_id = rinfo.report_id;
-		finfo.field_index = field->report_count - 1;
-		finfo.maxusage = field->maxusage;
-		finfo.flags = field->flags;
-		finfo.physical = field->physical;
-		finfo.logical = field->logical;
-		finfo.application = field->application;
-		finfo.logical_minimum = field->logical_minimum;
-		finfo.logical_maximum = field->logical_maximum;
-		finfo.physical_minimum = field->physical_minimum;
-		finfo.physical_maximum = field->physical_maximum;
-		finfo.unit_exponent = field->unit_exponent;
-		finfo.unit = field->unit;
-
-		if (copy_to_user(user_arg, &finfo, sizeof(finfo)))
-			return -EFAULT;
-
-		return 0;
-
-	case HIDIOCGUCODE:
-		uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
-		if (!uref_multi)
-			return -ENOMEM;
-		uref = &uref_multi->uref;
-		if (copy_from_user(uref, user_arg, sizeof(*uref)))
-			goto fault;
-
-		rinfo.report_type = uref->report_type;
-		rinfo.report_id = uref->report_id;
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			goto inval;
-
-		if (uref->field_index >= report->maxfield)
-			goto inval;
-
-		field = report->field[uref->field_index];
-		if (uref->usage_index >= field->maxusage)
-			goto inval;
-
-		uref->usage_code = field->usage[uref->usage_index].hid;
-
-		if (copy_to_user(user_arg, uref, sizeof(*uref)))
-			goto fault;
-
-		kfree(uref_multi);
-		return 0;
-
-	case HIDIOCGUSAGE:
-	case HIDIOCSUSAGE:
-	case HIDIOCGUSAGES:
-	case HIDIOCSUSAGES:
-	case HIDIOCGCOLLECTIONINDEX:
-		uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
-		if (!uref_multi)
-			return -ENOMEM;
-		uref = &uref_multi->uref;
-		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-			if (copy_from_user(uref_multi, user_arg,
-					   sizeof(*uref_multi)))
-				goto fault;
-		} else {
-			if (copy_from_user(uref, user_arg, sizeof(*uref)))
-				goto fault;
-		}
-
-		if (cmd != HIDIOCGUSAGE &&
-		    cmd != HIDIOCGUSAGES &&
-		    uref->report_type == HID_REPORT_TYPE_INPUT)
-			goto inval;
-
-		if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, uref);
-			if (field == NULL)
-				goto inval;
-		} else {
-			rinfo.report_type = uref->report_type;
-			rinfo.report_id = uref->report_id;
-			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-				goto inval;
-
-			if (uref->field_index >= report->maxfield)
-				goto inval;
-
-			field = report->field[uref->field_index];
-
-			if (cmd == HIDIOCGCOLLECTIONINDEX) {
-				if (uref->usage_index >= field->maxusage)
-					goto inval;
-			} else if (uref->usage_index >= field->report_count)
-				goto inval;
-
-			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
-				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
-				  uref->usage_index + uref_multi->num_values > field->report_count))
-				goto inval;
-			}
-
-		switch (cmd) {
-			case HIDIOCGUSAGE:
-				uref->value = field->value[uref->usage_index];
-				if (copy_to_user(user_arg, uref, sizeof(*uref)))
-					goto fault;
-				goto goodreturn;
-
-			case HIDIOCSUSAGE:
-				field->value[uref->usage_index] = uref->value;
-				goto goodreturn;
-
-			case HIDIOCGCOLLECTIONINDEX:
-				kfree(uref_multi);
-				return field->usage[uref->usage_index].collection_index;
-			case HIDIOCGUSAGES:
-				for (i = 0; i < uref_multi->num_values; i++)
-					uref_multi->values[i] =
-					    field->value[uref->usage_index + i];
-				if (copy_to_user(user_arg, uref_multi,
-						 sizeof(*uref_multi)))
-					goto fault;
-				goto goodreturn;
-			case HIDIOCSUSAGES:
-				for (i = 0; i < uref_multi->num_values; i++)
-					field->value[uref->usage_index + i] =
-					    uref_multi->values[i];
-				goto goodreturn;
-		}
-
-goodreturn:
-		kfree(uref_multi);
-		return 0;
-fault:
-		kfree(uref_multi);
-		return -EFAULT;
-inval:
-		kfree(uref_multi);
-		return -EINVAL;
-
-	case HIDIOCGCOLLECTIONINFO:
-		if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
-			return -EFAULT;
-
-		if (cinfo.index >= hid->maxcollection)
-			return -EINVAL;
-
-		cinfo.type = hid->collection[cinfo.index].type;
-		cinfo.usage = hid->collection[cinfo.index].usage;
-		cinfo.level = hid->collection[cinfo.index].level;
-
-		if (copy_to_user(user_arg, &cinfo, sizeof(cinfo)))
-			return -EFAULT;
-		return 0;
-
-	default:
-
-		if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
-			return -EINVAL;
-
-		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
-			int len;
-			if (!hid->name)
-				return 0;
-			len = strlen(hid->name) + 1;
-			if (len > _IOC_SIZE(cmd))
-				 len = _IOC_SIZE(cmd);
-			return copy_to_user(user_arg, hid->name, len) ?
-				-EFAULT : len;
-		}
-
-		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
-			int len;
-			if (!hid->phys)
-				return 0;
-			len = strlen(hid->phys) + 1;
-			if (len > _IOC_SIZE(cmd))
-				len = _IOC_SIZE(cmd);
-			return copy_to_user(user_arg, hid->phys, len) ?
-				-EFAULT : len;
-		}
-	}
-	return -EINVAL;
-}
-
-static const struct file_operations hiddev_fops = {
-	.owner =	THIS_MODULE,
-	.read =		hiddev_read,
-	.write =	hiddev_write,
-	.poll =		hiddev_poll,
-	.open =		hiddev_open,
-	.release =	hiddev_release,
-	.ioctl =	hiddev_ioctl,
-	.fasync =	hiddev_fasync,
-};
-
-static struct usb_class_driver hiddev_class = {
-	.name =		"hiddev%d",
-	.fops =		&hiddev_fops,
-	.minor_base =	HIDDEV_MINOR_BASE,
-};
-
-/*
- * This is where hid.c calls us to connect a hid device to the hiddev driver
- */
-int hiddev_connect(struct hid_device *hid)
-{
-	struct hiddev *hiddev;
-	struct usbhid_device *usbhid = hid->driver_data;
-	int i;
-	int retval;
-
-	for (i = 0; i < hid->maxcollection; i++)
-		if (hid->collection[i].type ==
-		    HID_COLLECTION_APPLICATION &&
-		    !IS_INPUT_APPLICATION(hid->collection[i].usage))
-			break;
-
-	if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0)
-		return -1;
-
-	if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
-		return -1;
-
-	retval = usb_register_dev(usbhid->intf, &hiddev_class);
-	if (retval) {
-		err("Not able to get a minor for this device.");
-		kfree(hiddev);
-		return -1;
-	}
-
-	init_waitqueue_head(&hiddev->wait);
-	INIT_LIST_HEAD(&hiddev->list);
-	hiddev->hid = hid;
-	hiddev->exist = 1;
-
-	hid->minor = usbhid->intf->minor;
-	hid->hiddev = hiddev;
-
-	hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
-
-	return 0;
-}
-
-/*
- * This is where hid.c calls us to disconnect a hiddev device from the
- * corresponding hid device (usually because the usb device has disconnected)
- */
-static struct usb_class_driver hiddev_class;
-void hiddev_disconnect(struct hid_device *hid)
-{
-	struct hiddev *hiddev = hid->hiddev;
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	hiddev->exist = 0;
-
-	hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
-	usb_deregister_dev(usbhid->intf, &hiddev_class);
-
-	if (hiddev->open) {
-		usbhid_close(hiddev->hid);
-		wake_up_interruptible(&hiddev->wait);
-	} else {
-		kfree(hiddev);
-	}
-}
-
-/* Currently this driver is a USB driver.  It's not a conventional one in
- * the sense that it doesn't probe at the USB level.  Instead it waits to
- * be connected by HID through the hiddev_connect / hiddev_disconnect
- * routines.  The reason to register as a USB device is to gain part of the
- * minor number space from the USB major.
- *
- * In theory, should the HID code be generalized to more than one physical
- * medium (say, IEEE 1384), this driver will probably need to register its
- * own major number, and in doing so, no longer need to register with USB.
- * At that point the probe routine and hiddev_driver struct below will no
- * longer be useful.
- */
-
-
-/* We never attach in this manner, and rely on HID to connect us.  This
- * is why there is no disconnect routine defined in the usb_driver either.
- */
-static int hiddev_usbd_probe(struct usb_interface *intf,
-			     const struct usb_device_id *hiddev_info)
-{
-	return -ENODEV;
-}
-
-
-static /* const */ struct usb_driver hiddev_driver = {
-	.name =		"hiddev",
-	.probe =	hiddev_usbd_probe,
-};
-
-int __init hiddev_init(void)
-{
-	return usb_register(&hiddev_driver);
-}
-
-void hiddev_exit(void)
-{
-	usb_deregister(&hiddev_driver);
-}
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h
deleted file mode 100644
index 0023f96..0000000
--- a/drivers/usb/input/usbhid.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __USBHID_H
-#define __USBHID_H
-
-/*
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *  Copyright (c) 2006 Jiri Kosina
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <linux/input.h>
-
-/*  API provided by hid-core.c for USB HID drivers */
-int usbhid_wait_io(struct hid_device* hid);
-void usbhid_close(struct hid_device *hid);
-int usbhid_open(struct hid_device *hid);
-void usbhid_init_reports(struct hid_device *hid);
-void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
-
-/*
- * USB-specific HID struct, to be pointed to
- * from struct hid_device->driver_data
- */
-
-struct usbhid_device {
-	struct hid_device *hid;						/* pointer to corresponding HID dev */
-
-	struct usb_interface *intf;                                     /* USB interface */
-	int ifnum;                                                      /* USB interface number */
-
-	unsigned int bufsize;                                           /* URB buffer size */
-
-	struct urb *urbin;                                              /* Input URB */
-	char *inbuf;                                                    /* Input buffer */
-	dma_addr_t inbuf_dma;                                           /* Input buffer dma */
-	spinlock_t inlock;                                              /* Input fifo spinlock */
-
-	struct urb *urbctrl;                                            /* Control URB */
-	struct usb_ctrlrequest *cr;                                     /* Control request struct */
-	dma_addr_t cr_dma;                                              /* Control request struct dma */
-	struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];  		/* Control fifo */
-	unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
-	char *ctrlbuf;                                                  /* Control buffer */
-	dma_addr_t ctrlbuf_dma;                                         /* Control buffer dma */
-	spinlock_t ctrllock;                                            /* Control fifo spinlock */
-
-	struct urb *urbout;                                             /* Output URB */
-	struct hid_report *out[HID_CONTROL_FIFO_SIZE];                  /* Output pipe fifo */
-	unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
-	char *outbuf;                                                   /* Output buffer */
-	dma_addr_t outbuf_dma;                                          /* Output buffer dma */
-	spinlock_t outlock;                                             /* Output fifo spinlock */
-
-	unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
-	struct timer_list io_retry;                                     /* Retry timer */
-	unsigned long stop_retry;                                       /* Time to give up, in jiffies */
-	unsigned int retry_delay;                                       /* Delay length in ms */
-	struct work_struct reset_work;                                  /* Task context for resets */
-
-};
-
-#define	hid_to_usb_dev(hid_dev) \
-	container_of(hid_dev->dev->parent, struct usb_device, dev)
-
-#endif
-
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
deleted file mode 100644
index 8505824..0000000
--- a/drivers/usb/input/usbkbd.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  USB HIDBP Keyboard support
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION ""
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-static unsigned char usb_kbd_keycode[256] = {
-	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
-	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
-	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
-	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
-	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
-	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
-	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
-	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
-	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
-	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
-	150,158,159,128,136,177,178,176,142,152,173,140
-};
-
-struct usb_kbd {
-	struct input_dev *dev;
-	struct usb_device *usbdev;
-	unsigned char old[8];
-	struct urb *irq, *led;
-	unsigned char newleds;
-	char name[128];
-	char phys[64];
-
-	unsigned char *new;
-	struct usb_ctrlrequest *cr;
-	unsigned char *leds;
-	dma_addr_t cr_dma;
-	dma_addr_t new_dma;
-	dma_addr_t leds_dma;
-};
-
-static void usb_kbd_irq(struct urb *urb)
-{
-	struct usb_kbd *kbd = urb->context;
-	int i;
-
-	switch (urb->status) {
-	case 0:			/* success */
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	/* -EPIPE:  should clear the halt */
-	default:		/* error */
-		goto resubmit;
-	}
-
-	for (i = 0; i < 8; i++)
-		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
-	for (i = 2; i < 8; i++) {
-
-		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
-			if (usb_kbd_keycode[kbd->old[i]])
-				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
-			else
-				info("Unknown key (scancode %#x) released.", kbd->old[i]);
-		}
-
-		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
-			if (usb_kbd_keycode[kbd->new[i]])
-				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
-			else
-				info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
-		}
-	}
-
-	input_sync(kbd->dev);
-
-	memcpy(kbd->old, kbd->new, 8);
-
-resubmit:
-	i = usb_submit_urb (urb, GFP_ATOMIC);
-	if (i)
-		err ("can't resubmit intr, %s-%s/input0, status %d",
-				kbd->usbdev->bus->bus_name,
-				kbd->usbdev->devpath, i);
-}
-
-static int usb_kbd_event(struct input_dev *dev, unsigned int type,
-			 unsigned int code, int value)
-{
-	struct usb_kbd *kbd = dev->private;
-
-	if (type != EV_LED)
-		return -1;
-
-
-	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
-		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
-		       (!!test_bit(LED_NUML,    dev->led));
-
-	if (kbd->led->status == -EINPROGRESS)
-		return 0;
-
-	if (*(kbd->leds) == kbd->newleds)
-		return 0;
-
-	*(kbd->leds) = kbd->newleds;
-	kbd->led->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
-
-	return 0;
-}
-
-static void usb_kbd_led(struct urb *urb)
-{
-	struct usb_kbd *kbd = urb->context;
-
-	if (urb->status)
-		warn("led urb status %d received", urb->status);
-
-	if (*(kbd->leds) == kbd->newleds)
-		return;
-
-	*(kbd->leds) = kbd->newleds;
-	kbd->led->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
-}
-
-static int usb_kbd_open(struct input_dev *dev)
-{
-	struct usb_kbd *kbd = dev->private;
-
-	kbd->irq->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void usb_kbd_close(struct input_dev *dev)
-{
-	struct usb_kbd *kbd = dev->private;
-
-	usb_kill_urb(kbd->irq);
-}
-
-static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
-{
-	if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
-		return -1;
-	if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
-		return -1;
-	if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
-		return -1;
-	if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
-		return -1;
-	if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
-		return -1;
-
-	return 0;
-}
-
-static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
-{
-	usb_free_urb(kbd->irq);
-	usb_free_urb(kbd->led);
-	if (kbd->new)
-		usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
-	if (kbd->cr)
-		usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
-	if (kbd->leds)
-		usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
-}
-
-static int usb_kbd_probe(struct usb_interface *iface,
-			 const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(iface);
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_kbd *kbd;
-	struct input_dev *input_dev;
-	int i, pipe, maxp;
-
-	interface = iface->cur_altsetting;
-
-	if (interface->desc.bNumEndpoints != 1)
-		return -ENODEV;
-
-	endpoint = &interface->endpoint[0].desc;
-	if (!usb_endpoint_is_int_in(endpoint))
-		return -ENODEV;
-
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!kbd || !input_dev)
-		goto fail1;
-
-	if (usb_kbd_alloc_mem(dev, kbd))
-		goto fail2;
-
-	kbd->usbdev = dev;
-	kbd->dev = input_dev;
-
-	if (dev->manufacturer)
-		strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
-
-	if (dev->product) {
-		if (dev->manufacturer)
-			strlcat(kbd->name, " ", sizeof(kbd->name));
-		strlcat(kbd->name, dev->product, sizeof(kbd->name));
-	}
-
-	if (!strlen(kbd->name))
-		snprintf(kbd->name, sizeof(kbd->name),
-			 "USB HIDBP Keyboard %04x:%04x",
-			 le16_to_cpu(dev->descriptor.idVendor),
-			 le16_to_cpu(dev->descriptor.idProduct));
-
-	usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
-	strlcpy(kbd->phys, "/input0", sizeof(kbd->phys));
-
-	input_dev->name = kbd->name;
-	input_dev->phys = kbd->phys;
-	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &iface->dev;
-	input_dev->private = kbd;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-	input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
-
-	for (i = 0; i < 255; i++)
-		set_bit(usb_kbd_keycode[i], input_dev->keybit);
-	clear_bit(0, input_dev->keybit);
-
-	input_dev->event = usb_kbd_event;
-	input_dev->open = usb_kbd_open;
-	input_dev->close = usb_kbd_close;
-
-	usb_fill_int_urb(kbd->irq, dev, pipe,
-			 kbd->new, (maxp > 8 ? 8 : maxp),
-			 usb_kbd_irq, kbd, endpoint->bInterval);
-	kbd->irq->transfer_dma = kbd->new_dma;
-	kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	kbd->cr->bRequest = 0x09;
-	kbd->cr->wValue = cpu_to_le16(0x200);
-	kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
-	kbd->cr->wLength = cpu_to_le16(1);
-
-	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
-			     (void *) kbd->cr, kbd->leds, 1,
-			     usb_kbd_led, kbd);
-	kbd->led->setup_dma = kbd->cr_dma;
-	kbd->led->transfer_dma = kbd->leds_dma;
-	kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
-
-	input_register_device(kbd->dev);
-
-	usb_set_intfdata(iface, kbd);
-	return 0;
-
-fail2:	usb_kbd_free_mem(dev, kbd);
-fail1:	input_free_device(input_dev);
-	kfree(kbd);
-	return -ENOMEM;
-}
-
-static void usb_kbd_disconnect(struct usb_interface *intf)
-{
-	struct usb_kbd *kbd = usb_get_intfdata (intf);
-
-	usb_set_intfdata(intf, NULL);
-	if (kbd) {
-		usb_kill_urb(kbd->irq);
-		input_unregister_device(kbd->dev);
-		usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
-		kfree(kbd);
-	}
-}
-
-static struct usb_device_id usb_kbd_id_table [] = {
-	{ USB_INTERFACE_INFO(3, 1, 1) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
-
-static struct usb_driver usb_kbd_driver = {
-	.name =		"usbkbd",
-	.probe =	usb_kbd_probe,
-	.disconnect =	usb_kbd_disconnect,
-	.id_table =	usb_kbd_id_table,
-};
-
-static int __init usb_kbd_init(void)
-{
-	int result = usb_register(&usb_kbd_driver);
-	if (result == 0)
-		info(DRIVER_VERSION ":" DRIVER_DESC);
-	return result;
-}
-
-static void __exit usb_kbd_exit(void)
-{
-	usb_deregister(&usb_kbd_driver);
-}
-
-module_init(usb_kbd_init);
-module_exit(usb_kbd_exit);
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
deleted file mode 100644
index 64a33e4..0000000
--- a/drivers/usb/input/usbmouse.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  USB HIDBP Mouse support
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.6"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-struct usb_mouse {
-	char name[128];
-	char phys[64];
-	struct usb_device *usbdev;
-	struct input_dev *dev;
-	struct urb *irq;
-
-	signed char *data;
-	dma_addr_t data_dma;
-};
-
-static void usb_mouse_irq(struct urb *urb)
-{
-	struct usb_mouse *mouse = urb->context;
-	signed char *data = mouse->data;
-	struct input_dev *dev = mouse->dev;
-	int status;
-
-	switch (urb->status) {
-	case 0:			/* success */
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	/* -EPIPE:  should clear the halt */
-	default:		/* error */
-		goto resubmit;
-	}
-
-	input_report_key(dev, BTN_LEFT,   data[0] & 0x01);
-	input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);
-	input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
-	input_report_key(dev, BTN_SIDE,   data[0] & 0x08);
-	input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);
-
-	input_report_rel(dev, REL_X,     data[1]);
-	input_report_rel(dev, REL_Y,     data[2]);
-	input_report_rel(dev, REL_WHEEL, data[3]);
-
-	input_sync(dev);
-resubmit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
-		err ("can't resubmit intr, %s-%s/input0, status %d",
-				mouse->usbdev->bus->bus_name,
-				mouse->usbdev->devpath, status);
-}
-
-static int usb_mouse_open(struct input_dev *dev)
-{
-	struct usb_mouse *mouse = dev->private;
-
-	mouse->irq->dev = mouse->usbdev;
-	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void usb_mouse_close(struct input_dev *dev)
-{
-	struct usb_mouse *mouse = dev->private;
-
-	usb_kill_urb(mouse->irq);
-}
-
-static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_mouse *mouse;
-	struct input_dev *input_dev;
-	int pipe, maxp;
-
-	interface = intf->cur_altsetting;
-
-	if (interface->desc.bNumEndpoints != 1)
-		return -ENODEV;
-
-	endpoint = &interface->endpoint[0].desc;
-	if (!usb_endpoint_is_int_in(endpoint))
-		return -ENODEV;
-
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!mouse || !input_dev)
-		goto fail1;
-
-	mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
-	if (!mouse->data)
-		goto fail1;
-
-	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!mouse->irq)
-		goto fail2;
-
-	mouse->usbdev = dev;
-	mouse->dev = input_dev;
-
-	if (dev->manufacturer)
-		strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
-
-	if (dev->product) {
-		if (dev->manufacturer)
-			strlcat(mouse->name, " ", sizeof(mouse->name));
-		strlcat(mouse->name, dev->product, sizeof(mouse->name));
-	}
-
-	if (!strlen(mouse->name))
-		snprintf(mouse->name, sizeof(mouse->name),
-			 "USB HIDBP Mouse %04x:%04x",
-			 le16_to_cpu(dev->descriptor.idVendor),
-			 le16_to_cpu(dev->descriptor.idProduct));
-
-	usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
-	strlcat(mouse->phys, "/input0", sizeof(mouse->phys));
-
-	input_dev->name = mouse->name;
-	input_dev->phys = mouse->phys;
-	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-	input_dev->relbit[0] |= BIT(REL_WHEEL);
-
-	input_dev->private = mouse;
-	input_dev->open = usb_mouse_open;
-	input_dev->close = usb_mouse_close;
-
-	usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
-			 (maxp > 8 ? 8 : maxp),
-			 usb_mouse_irq, mouse, endpoint->bInterval);
-	mouse->irq->transfer_dma = mouse->data_dma;
-	mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	input_register_device(mouse->dev);
-
-	usb_set_intfdata(intf, mouse);
-	return 0;
-
-fail2:	usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
-fail1:	input_free_device(input_dev);
-	kfree(mouse);
-	return -ENOMEM;
-}
-
-static void usb_mouse_disconnect(struct usb_interface *intf)
-{
-	struct usb_mouse *mouse = usb_get_intfdata (intf);
-
-	usb_set_intfdata(intf, NULL);
-	if (mouse) {
-		usb_kill_urb(mouse->irq);
-		input_unregister_device(mouse->dev);
-		usb_free_urb(mouse->irq);
-		usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
-		kfree(mouse);
-	}
-}
-
-static struct usb_device_id usb_mouse_id_table [] = {
-	{ USB_INTERFACE_INFO(3, 1, 2) },
-	{ }	/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
-
-static struct usb_driver usb_mouse_driver = {
-	.name		= "usbmouse",
-	.probe		= usb_mouse_probe,
-	.disconnect	= usb_mouse_disconnect,
-	.id_table	= usb_mouse_id_table,
-};
-
-static int __init usb_mouse_init(void)
-{
-	int retval = usb_register(&usb_mouse_driver);
-	if (retval == 0)
-		info(DRIVER_VERSION ":" DRIVER_DESC);
-	return retval;
-}
-
-static void __exit usb_mouse_exit(void)
-{
-	usb_deregister(&usb_mouse_driver);
-}
-
-module_init(usb_mouse_init);
-module_exit(usb_mouse_exit);
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
index 4142e36..4f3e9bc 100644
--- a/drivers/usb/input/wacom_wac.c
+++ b/drivers/usb/input/wacom_wac.c
@@ -163,7 +163,7 @@
 	}
 
 	id = STYLUS_DEVICE_ID;
-	if (data[1] & 0x10) { /* in prox */
+	if (data[1] & 0x80) { /* in prox */
 
 		switch ((data[1] >> 5) & 3) {
 
@@ -196,9 +196,6 @@
 					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
 				break;
 		}
-	}
-
-	if (data[1] & 0x90) {
 		x = wacom_le16_to_cpu(&data[2]);
 		y = wacom_le16_to_cpu(&data[4]);
 		wacom_report_abs(wcombo, ABS_X, x);
@@ -210,19 +207,28 @@
 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
 		}
 		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
-	}
-	else
-		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-
-	if (data[1] & 0x10)  /* only report prox-in when in area */
 		wacom_report_key(wcombo, wacom->tool[0], 1);
-	if (!(data[1] & 0x90))  /* report prox-out when physically out */
+	} else if (!(data[1] & 0x90)) {
+		wacom_report_abs(wcombo, ABS_X, 0);
+		wacom_report_abs(wcombo, ABS_Y, 0);
+		if (wacom->tool[0] == BTN_TOOL_MOUSE) {
+			wacom_report_key(wcombo, BTN_LEFT, 0);
+			wacom_report_key(wcombo, BTN_RIGHT, 0);
+			wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+		} else {
+			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom_report_key(wcombo, BTN_STYLUS, 0);
+			wacom_report_key(wcombo, BTN_STYLUS2, 0);
+		}
+		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
 		wacom_report_key(wcombo, wacom->tool[0], 0);
-	wacom_input_sync(wcombo);
+	}
 
 	/* send pad data */
 	if (wacom->features->type == WACOM_G4) {
-		if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) {
+		if (data[7] & 0xf8) {
+			wacom_input_sync(wcombo); /* sync last event */
 			wacom->id[1] = 1;
 			wacom->serial[1] = (data[7] & 0xf8);
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
@@ -230,10 +236,15 @@
 			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
 			wacom_report_rel(wcombo, REL_WHEEL, rw);
 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
+			wacom_input_sync(wcombo); /* sync last event */
 			wacom->id[1] = 0;
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+			wacom_report_abs(wcombo, ABS_MISC, 0);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		}
 	}
@@ -304,28 +315,35 @@
 			default: /* Unknown tool */
 				wacom->tool[idx] = BTN_TOOL_PEN;
 		}
-		/* only large I3 support Lens Cursor */
-		if(!((wacom->tool[idx] == BTN_TOOL_LENS)
-				 && ((wacom->features->type == INTUOS3)
-				 || (wacom->features->type == INTUOS3S)))) {
-			wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
-			wacom_report_key(wcombo, wacom->tool[idx], 1);
-			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-			return 2;
-		}
 		return 1;
 	}
 
 	/* Exit report */
 	if ((data[1] & 0xfe) == 0x80) {
- 		if(!((wacom->tool[idx] == BTN_TOOL_LENS)
-				 && ((wacom->features->type == INTUOS3)
-				 || (wacom->features->type == INTUOS3S)))) {
-			wacom_report_key(wcombo, wacom->tool[idx], 0);
-			wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-			return 2;
+		wacom_report_abs(wcombo, ABS_X, 0);
+		wacom_report_abs(wcombo, ABS_Y, 0);
+		wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
+			wacom_report_key(wcombo, BTN_LEFT, 0);
+			wacom_report_key(wcombo, BTN_MIDDLE, 0);
+			wacom_report_key(wcombo, BTN_RIGHT, 0);
+			wacom_report_key(wcombo, BTN_SIDE, 0);
+			wacom_report_key(wcombo, BTN_EXTRA, 0);
+			wacom_report_abs(wcombo, ABS_THROTTLE, 0);
+			wacom_report_abs(wcombo, ABS_RZ, 0);
+ 		} else {
+			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+			wacom_report_abs(wcombo, ABS_TILT_X, 0);
+			wacom_report_abs(wcombo, ABS_TILT_Y, 0);
+			wacom_report_key(wcombo, BTN_STYLUS, 0);
+			wacom_report_key(wcombo, BTN_STYLUS2, 0);
+			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom_report_abs(wcombo, ABS_WHEEL, 0);
 		}
+		wacom_report_key(wcombo, wacom->tool[idx], 0);
+		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+		return 2;
 	}
 	return 0;
 }
@@ -394,6 +412,7 @@
 			wacom_report_key(wcombo, wacom->tool[1], 1);
 		else
 			wacom_report_key(wcombo, wacom->tool[1], 0);
+		wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
 		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
                 return 1;
 	}
@@ -403,6 +422,12 @@
 	if (result)
                 return result-1;
 
+	/* Only large I3 and I1 & I2 support Lense Cursor */
+ 	if((wacom->tool[idx] == BTN_TOOL_LENS)
+			&& ((wacom->features->type == INTUOS3)
+		 	|| (wacom->features->type == INTUOS3S)))
+		return 0;
+
 	/* Cintiq doesn't send data when RDY bit isn't set */
 	if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
                  return 0;
@@ -554,11 +579,11 @@
 	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
 	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
 	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 63, GRAPHIRE },
-	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 63, INTUOS },
-	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 63, INTUOS },
-	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 63, INTUOS },
-	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 63, INTUOS },
-	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS },
 	{ "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
 	{ "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
 	{ "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
@@ -571,11 +596,11 @@
 	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
 	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
 	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
 	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
 	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
 	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
@@ -584,7 +609,7 @@
 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
 	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
 	{ }
 };
 
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h
index a1d9ce0..a230222 100644
--- a/drivers/usb/input/wacom_wac.h
+++ b/drivers/usb/input/wacom_wac.h
@@ -12,6 +12,7 @@
 #define STYLUS_DEVICE_ID	0x02
 #define CURSOR_DEVICE_ID	0x06
 #define ERASER_DEVICE_ID	0x0A
+#define PAD_DEVICE_ID		0x0F
 
 enum {
 	PENPARTNER = 0,
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a74bf86..9c7eb61 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -88,6 +88,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usblcd.
 
+config USB_BERRY_CHARGE
+	tristate "USB BlackBerry recharge support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a BlackBerry device to your
+	  computer's USB port and have it automatically switch to "recharge"
+	  mode.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called berry_charge.
+
 config USB_LED
 	tristate "USB LED driver support"
 	depends on USB
@@ -233,6 +244,20 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called trancevibrator.
 
+config USB_IOWARRIOR
+	tristate "IO Warrior driver support"
+	depends on USB
+	help
+	  Say Y here if you want to support the IO Warrior devices from Code
+	  Mercenaries.  This includes support for the following devices:
+	  	IO Warrior 40
+		IO Warrior 24
+		IO Warrior 56
+		IO Warrior 24 Power Vampire
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iowarrior.
+
 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 2cba07d..b68e6b7 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -6,12 +6,14 @@
 obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
 obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
 obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
+obj-$(CONFIG_USB_BERRY_CHARGE)	+= berry_charge.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
 obj-$(CONFIG_USB_EMI26)		+= emi26.o
 obj-$(CONFIG_USB_EMI62)		+= emi62.o
 obj-$(CONFIG_USB_FTDI_ELAN)	+= ftdi-elan.o
 obj-$(CONFIG_USB_IDMOUSE)	+= idmouse.o
+obj-$(CONFIG_USB_IOWARRIOR)	+= iowarrior.o
 obj-$(CONFIG_USB_LCD)		+= usblcd.o
 obj-$(CONFIG_USB_LD)		+= ldusb.o
 obj-$(CONFIG_USB_LED)		+= usbled.o
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 75bfab9..77145f9 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -285,23 +285,24 @@
 	/* save device in the file's private structure */
 	file->private_data = dev;
 
-	/* initialize in direction */
-	dev->read_buffer_length = 0;
+	if (dev->open_count == 1) {
+		/* initialize in direction */
+		dev->read_buffer_length = 0;
 
-	/* fixup first read by having urb waiting for it */
-	usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
-			 usb_rcvintpipe(dev->udev,
-			 		dev->interrupt_in_endpoint->bEndpointAddress),
-			 dev->interrupt_in_buffer,
-			 le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
-			 adu_interrupt_in_callback, dev,
-			 dev->interrupt_in_endpoint->bInterval);
-	/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
-	dev->read_urb_finished = 0;
-	usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
-	/* we ignore failure */
-	/* end of fixup for first read */
-
+		/* fixup first read by having urb waiting for it */
+		usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+				 usb_rcvintpipe(dev->udev,
+				 		dev->interrupt_in_endpoint->bEndpointAddress),
+				 dev->interrupt_in_buffer,
+				 le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+				 adu_interrupt_in_callback, dev,
+				 dev->interrupt_in_endpoint->bInterval);
+		/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+		dev->read_urb_finished = 0;
+		retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+		if (retval)
+			--dev->open_count;
+	}
 	up(&dev->sem);
 
 exit_no_device:
@@ -469,7 +470,7 @@
 							 adu_interrupt_in_callback,
 							 dev,
 							 dev->interrupt_in_endpoint->bInterval);
-					retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+					retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
 					if (!retval) {
 						spin_unlock_irqrestore(&dev->buflock, flags);
 						dbg(2," %s : submitted OK", __FUNCTION__);
@@ -539,7 +540,7 @@
 	size_t bytes_written = 0;
 	size_t bytes_to_write;
 	size_t buffer_size;
-	int retval = 0;
+	int retval;
 	int timeout = 0;
 
 	dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
@@ -547,7 +548,9 @@
 	dev = file->private_data;
 
 	/* lock this object */
-	down_interruptible(&dev->sem);
+	retval = down_interruptible(&dev->sem);
+	if (retval)
+		goto exit_nolock;
 
 	/* verify that the device wasn't unplugged */
 	if (dev->udev == NULL || dev->minor == 0) {
@@ -575,7 +578,11 @@
 			}
 			up(&dev->sem);
 			timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
-			down_interruptible(&dev->sem);
+			retval = down_interruptible(&dev->sem);
+			if (retval) {
+				retval = bytes_written ? bytes_written : retval;
+				goto exit_nolock;
+			}
 			if (timeout > 0) {
 				break;
 			}
@@ -637,6 +644,7 @@
 exit:
 	/* unlock the device */
 	up(&dev->sem);
+exit_nolock:
 
 	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
 
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 32f0e3a..cf70c16 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -141,7 +141,7 @@
 	int retval;
 
 	pdata->msgdata[0] = 0x10;
-	pdata->msgdata[1] = bd->props->brightness;
+	pdata->msgdata[1] = bd->props.brightness;
 
 	retval = usb_control_msg(
 		pdata->udev,
@@ -177,11 +177,9 @@
 		return pdata->msgdata[1];
 }
 
-static struct backlight_properties appledisplay_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops appledisplay_bl_data = {
 	.get_brightness	= appledisplay_bl_get_brightness,
 	.update_status	= appledisplay_bl_update_status,
-	.max_brightness	= 0xFF
 };
 
 static void appledisplay_work(struct work_struct *work)
@@ -190,11 +188,9 @@
 		container_of(work, struct appledisplay, work.work);
 	int retval;
 
-	up(&pdata->bd->sem);
 	retval = appledisplay_bl_get_brightness(pdata->bd);
 	if (retval >= 0)
-		pdata->bd->props->brightness = retval;
-	down(&pdata->bd->sem);
+		pdata->bd->props.brightness = retval;
 
 	/* Poll again in about 125ms if there's still a button pressed */
 	if (pdata->button_pressed)
@@ -281,17 +277,17 @@
 	/* Register backlight device */
 	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
 		atomic_inc_return(&count_displays) - 1);
-	pdata->bd = backlight_device_register(bl_name, NULL,
-		pdata, &appledisplay_bl_data);
+	pdata->bd = backlight_device_register(bl_name, NULL, pdata,
+						&appledisplay_bl_data);
 	if (IS_ERR(pdata->bd)) {
 		err("appledisplay: Backlight registration failed");
 		goto error;
 	}
 
+	pdata->bd->props.max_brightness = 0xff;
+
 	/* Try to get brightness */
-	up(&pdata->bd->sem);
 	brightness = appledisplay_bl_get_brightness(pdata->bd);
-	down(&pdata->bd->sem);
 
 	if (brightness < 0) {
 		retval = brightness;
@@ -300,9 +296,7 @@
 	}
 
 	/* Set brightness in backlight device */
-	up(&pdata->bd->sem);
-	pdata->bd->props->brightness = brightness;
-	down(&pdata->bd->sem);
+	pdata->bd->props.brightness = brightness;
 
 	/* save our data pointer in the interface device */
 	usb_set_intfdata(iface, pdata);
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
new file mode 100644
index 0000000..b15f2fd
--- /dev/null
+++ b/drivers/usb/misc/berry_charge.c
@@ -0,0 +1,140 @@
+/*
+ * USB BlackBerry charging module
+ *
+ * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.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, version 2.
+ *
+ * Information on how to switch configs was taken by the bcharge.cc file
+ * created by the barry.sf.net project.
+ *
+ * bcharge.cc has the following copyright:
+ * 	Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/)
+ * and is released under the GPLv2.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define RIM_VENDOR		0x0fca
+#define BLACKBERRY		0x0001
+
+static int debug;
+
+#ifdef dbg
+#undef dbg
+#endif
+#define dbg(dev, format, arg...)				\
+	if (debug)						\
+		dev_printk(KERN_DEBUG , dev , format , ## arg)
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+	{ },					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int magic_charge(struct usb_device *udev)
+{
+	char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+	int retval;
+
+	if (!dummy_buffer)
+		return -ENOMEM;
+
+	/* send two magic commands and then set the configuration.  The device
+	 * will then reset itself with the new power usage and should start
+	 * charging. */
+
+	/* Note, with testing, it only seems that the first message is really
+	 * needed (at least for the 8700c), but to be safe, we emulate what
+	 * other operating systems seem to be sending to their device.  We
+	 * really need to get some specs for this device to be sure about what
+	 * is going on here.
+	 */
+	dbg(&udev->dev, "Sending first magic command\n");
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
+	if (retval != 2) {
+		dev_err(&udev->dev, "First magic command failed: %d.\n",
+			retval);
+		return retval;
+	}
+
+	dbg(&udev->dev, "Sending second magic command\n");
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
+	if (retval != 0) {
+		dev_err(&udev->dev, "Second magic command failed: %d.\n",
+			retval);
+		return retval;
+	}
+
+	dbg(&udev->dev, "Calling set_configuration\n");
+	retval = usb_driver_set_configuration(udev, 1);
+	if (retval)
+		dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+	return retval;
+}
+
+static int berry_probe(struct usb_interface *intf,
+		       const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	dbg(&udev->dev, "Power is set to %dmA\n",
+	    udev->actconfig->desc.bMaxPower * 2);
+
+	/* check the power usage so we don't try to enable something that is
+	 * already enabled */
+	if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
+		dbg(&udev->dev, "device is already charging, power is "
+		    "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
+		return -ENODEV;
+	}
+
+	/* turn the power on */
+	magic_charge(udev);
+
+	/* we don't really want to bind to the device, userspace programs can
+	 * handle the syncing just fine, so get outta here. */
+	return -ENODEV;
+}
+
+static void berry_disconnect(struct usb_interface *intf)
+{
+}
+
+static struct usb_driver berry_driver = {
+	.name =		"berry_charge",
+	.probe =	berry_probe,
+	.disconnect =	berry_disconnect,
+	.id_table =	id_table,
+};
+
+static int __init berry_init(void)
+{
+	return usb_register(&berry_driver);
+}
+
+static void __exit berry_exit(void)
+{
+	usb_deregister(&berry_driver);
+}
+
+module_init(berry_init);
+module_exit(berry_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index b63b5f3..d721380 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -246,11 +246,13 @@
 	struct cypress *dev;
 
 	dev = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
 
 	/* remove device attribute files */
 	device_remove_file(&interface->dev, &dev_attr_port0);
 	device_remove_file(&interface->dev, &dev_attr_port1);
+	/* the intfdata can be set to NULL only after the
+	 * device files have been removed */
+	usb_set_intfdata(interface, NULL);
 
 	usb_put_dev(dev->udev);
 
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 0c1d66d..e2172e5 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -2304,7 +2304,6 @@
 #define OHCI_QUIRK_SUPERIO 0x02
 #define OHCI_QUIRK_INITRESET 0x04
 #define OHCI_BIG_ENDIAN 0x08
-#define OHCI_QUIRK_ZFMICRO 0x10
 #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
 #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
         OHCI_INTR_WDH)
@@ -2905,17 +2904,35 @@
 {
         int result;
         printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
-                 __TIME__, __DATE__);
+	       __TIME__, __DATE__);
         init_MUTEX(&ftdi_module_lock);
         INIT_LIST_HEAD(&ftdi_static_list);
         status_queue = create_singlethread_workqueue("ftdi-status-control");
+	if (!status_queue)
+		goto err_status_queue;
         command_queue = create_singlethread_workqueue("ftdi-command-engine");
+	if (!command_queue)
+		goto err_command_queue;
         respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
+	if (!respond_queue)
+		goto err_respond_queue;
         result = usb_register(&ftdi_elan_driver);
-        if (result)
+        if (result) {
+		destroy_workqueue(status_queue);
+		destroy_workqueue(command_queue);
+		destroy_workqueue(respond_queue);
                 printk(KERN_ERR "usb_register failed. Error number %d\n",
-                        result);
+		       result);
+	}
         return result;
+
+ err_respond_queue:
+	destroy_workqueue(command_queue);
+ err_command_queue:
+	destroy_workqueue(status_queue);
+ err_status_queue:
+	printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name);
+	return -ENOMEM;
 }
 
 static void __exit ftdi_elan_exit(void)
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
new file mode 100644
index 0000000..fc51207
--- /dev/null
+++ b/drivers/usb/misc/iowarrior.c
@@ -0,0 +1,925 @@
+/*
+ *  Native support for the I/O-Warrior USB devices
+ *
+ *  Copyright (c) 2003-2005  Code Mercenaries GmbH
+ *  written by Christian Lucht <lucht@codemercs.com>
+ *
+ *  based on
+
+ *  usb-skeleton.c by Greg Kroah-Hartman  <greg@kroah.com>
+ *  brlvger.c by Stephane Dalton  <sdalton@videotron.ca>
+ *           and St�hane Doyon   <s.doyon@videotron.ca>
+ *
+ *  Released under the GPLv2.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/version.h>
+#include <linux/usb/iowarrior.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v0.4.0"
+#define DRIVER_AUTHOR "Christian Lucht <lucht@codemercs.com>"
+#define DRIVER_DESC "USB IO-Warrior driver (Linux 2.6.x)"
+
+#define USB_VENDOR_ID_CODEMERCS		1984
+/* low speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW40	0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW24	0x1501
+#define USB_DEVICE_ID_CODEMERCS_IOWPV1	0x1511
+#define USB_DEVICE_ID_CODEMERCS_IOWPV2	0x1512
+/* full speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW56	0x1503
+
+/* Get a minor range for your devices from the usb maintainer */
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define IOWARRIOR_MINOR_BASE	0
+#else
+#define IOWARRIOR_MINOR_BASE	208	// SKELETON_MINOR_BASE 192 + 16, not offical yet
+#endif
+
+/* interrupt input queue size */
+#define MAX_INTERRUPT_BUFFER 16
+/*
+   maximum number of urbs that are submitted for writes at the same time,
+   this applies to the IOWarrior56 only!
+   IOWarrior24 and IOWarrior40 use synchronous usb_control_msg calls.
+*/
+#define MAX_WRITES_IN_FLIGHT 4
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg( format, arg... ) do { if( debug ) printk( KERN_DEBUG __FILE__ ": " format "\n" , ## arg ); } while ( 0 )
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module parameters */
+static int debug = 0;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "debug=1 enables debugging messages");
+
+static struct usb_driver iowarrior_driver;
+
+/*--------------*/
+/*     data     */
+/*--------------*/
+
+/* Structure to hold all of our device specific stuff */
+struct iowarrior {
+	struct mutex mutex;			/* locks this structure */
+	struct usb_device *udev;		/* save off the usb device pointer */
+	struct usb_interface *interface;	/* the interface for this device */
+	unsigned char minor;			/* the starting minor number for this device */
+	struct usb_endpoint_descriptor *int_out_endpoint;	/* endpoint for reading (needed for IOW56 only) */
+	struct usb_endpoint_descriptor *int_in_endpoint;	/* endpoint for reading */
+	struct urb *int_in_urb;		/* the urb for reading data */
+	unsigned char *int_in_buffer;	/* buffer for data to be read */
+	unsigned char serial_number;	/* to detect lost packages */
+	unsigned char *read_queue;	/* size is MAX_INTERRUPT_BUFFER * packet size */
+	wait_queue_head_t read_wait;
+	wait_queue_head_t write_wait;	/* wait-queue for writing to the device */
+	atomic_t write_busy;		/* number of write-urbs submitted */
+	atomic_t read_idx;
+	atomic_t intr_idx;
+	spinlock_t intr_idx_lock;	/* protects intr_idx */
+	atomic_t overflow_flag;		/* signals an index 'rollover' */
+	int present;			/* this is 1 as long as the device is connected */
+	int opened;			/* this is 1 if the device is currently open */
+	char chip_serial[9];		/* the serial number string of the chip connected */
+	int report_size;		/* number of bytes in a report */
+	u16 product_id;
+};
+
+/*--------------*/
+/*    globals   */
+/*--------------*/
+/* prevent races between open() and disconnect() */
+static DECLARE_MUTEX(disconnect_sem);
+
+/*
+ *  USB spec identifies 5 second timeouts.
+ */
+#define GET_TIMEOUT 5
+#define USB_REQ_GET_REPORT  0x01
+//#if 0
+static int usb_get_report(struct usb_device *dev,
+			  struct usb_host_interface *inter, unsigned char type,
+			  unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			       USB_REQ_GET_REPORT,
+			       USB_DIR_IN | USB_TYPE_CLASS |
+			       USB_RECIP_INTERFACE, (type << 8) + id,
+			       inter->desc.bInterfaceNumber, buf, size,
+			       GET_TIMEOUT*HZ);
+}
+//#endif
+
+#define USB_REQ_SET_REPORT 0x09
+
+static int usb_set_report(struct usb_interface *intf, unsigned char type,
+			  unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(interface_to_usbdev(intf),
+			       usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+			       USB_REQ_SET_REPORT,
+			       USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			       (type << 8) + id,
+			       intf->cur_altsetting->desc.bInterfaceNumber, buf,
+			       size, HZ);
+}
+
+/*---------------------*/
+/* driver registration */
+/*---------------------*/
+/* table of devices that work with this driver */
+static struct usb_device_id iowarrior_ids[] = {
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)},
+	{}			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, iowarrior_ids);
+
+/*
+ * USB callback handler for reading data
+ */
+static void iowarrior_callback(struct urb *urb)
+{
+	struct iowarrior *dev = (struct iowarrior *)urb->context;
+	int intr_idx;
+	int read_idx;
+	int aux_idx;
+	int offset;
+	int status;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:
+		goto exit;
+	}
+
+	spin_lock(&dev->intr_idx_lock);
+	intr_idx = atomic_read(&dev->intr_idx);
+	/* aux_idx become previous intr_idx */
+	aux_idx = (intr_idx == 0) ? (MAX_INTERRUPT_BUFFER - 1) : (intr_idx - 1);
+	read_idx = atomic_read(&dev->read_idx);
+
+	/* queue is not empty and it's interface 0 */
+	if ((intr_idx != read_idx)
+	    && (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0)) {
+		/* + 1 for serial number */
+		offset = aux_idx * (dev->report_size + 1);
+		if (!memcmp
+		    (dev->read_queue + offset, urb->transfer_buffer,
+		     dev->report_size)) {
+			/* equal values on interface 0 will be ignored */
+			spin_unlock(&dev->intr_idx_lock);
+			goto exit;
+		}
+	}
+
+	/* aux_idx become next intr_idx */
+	aux_idx = (intr_idx == (MAX_INTERRUPT_BUFFER - 1)) ? 0 : (intr_idx + 1);
+	if (read_idx == aux_idx) {
+		/* queue full, dropping oldest input */
+		read_idx = (++read_idx == MAX_INTERRUPT_BUFFER) ? 0 : read_idx;
+		atomic_set(&dev->read_idx, read_idx);
+		atomic_set(&dev->overflow_flag, 1);
+	}
+
+	/* +1 for serial number */
+	offset = intr_idx * (dev->report_size + 1);
+	memcpy(dev->read_queue + offset, urb->transfer_buffer,
+	       dev->report_size);
+	*(dev->read_queue + offset + (dev->report_size)) = dev->serial_number++;
+
+	atomic_set(&dev->intr_idx, aux_idx);
+	spin_unlock(&dev->intr_idx_lock);
+	/* tell the blocking read about the new data */
+	wake_up_interruptible(&dev->read_wait);
+
+exit:
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status)
+		dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d",
+			__FUNCTION__, status);
+
+}
+
+/*
+ * USB Callback handler for write-ops
+ */
+static void iowarrior_write_callback(struct urb *urb)
+{
+	struct iowarrior *dev;
+	dev = (struct iowarrior *)urb->context;
+	/* sync/async unlink faults aren't errors */
+	if (urb->status &&
+	    !(urb->status == -ENOENT ||
+	      urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __func__, urb->status);
+	}
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+			urb->transfer_buffer, urb->transfer_dma);
+	/* tell a waiting writer the interrupt-out-pipe is available again */
+	atomic_dec(&dev->write_busy);
+	wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ *	iowarrior_delete
+ */
+static inline void iowarrior_delete(struct iowarrior *dev)
+{
+	dbg("%s - minor %d", __func__, dev->minor);
+	kfree(dev->int_in_buffer);
+	usb_free_urb(dev->int_in_urb);
+	kfree(dev->read_queue);
+	kfree(dev);
+}
+
+/*---------------------*/
+/* fops implementation */
+/*---------------------*/
+
+static int read_index(struct iowarrior *dev)
+{
+	int intr_idx, read_idx;
+
+	read_idx = atomic_read(&dev->read_idx);
+	intr_idx = atomic_read(&dev->intr_idx);
+
+	return (read_idx == intr_idx ? -1 : read_idx);
+}
+
+/**
+ *  iowarrior_read
+ */
+static ssize_t iowarrior_read(struct file *file, char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+	struct iowarrior *dev;
+	int read_idx;
+	int offset;
+
+	dev = (struct iowarrior *)file->private_data;
+
+	/* verify that the device wasn't unplugged */
+	if (dev == NULL || !dev->present)
+		return -ENODEV;
+
+	dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
+
+	/* read count must be packet size (+ time stamp) */
+	if ((count != dev->report_size)
+	    && (count != (dev->report_size + 1)))
+		return -EINVAL;
+
+	/* repeat until no buffer overrun in callback handler occur */
+	do {
+		atomic_set(&dev->overflow_flag, 0);
+		if ((read_idx = read_index(dev)) == -1) {
+			/* queue emty */
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+			else {
+				//next line will return when there is either new data, or the device is unplugged
+				int r = wait_event_interruptible(dev->read_wait,
+								 (!dev->present
+								  || (read_idx =
+								      read_index
+								      (dev)) !=
+								  -1));
+				if (r) {
+					//we were interrupted by a signal
+					return -ERESTART;
+				}
+				if (!dev->present) {
+					//The device was unplugged
+					return -ENODEV;
+				}
+				if (read_idx == -1) {
+					// Can this happen ???
+					return 0;
+				}
+			}
+		}
+
+		offset = read_idx * (dev->report_size + 1);
+		if (copy_to_user(buffer, dev->read_queue + offset, count)) {
+			return -EFAULT;
+		}
+	} while (atomic_read(&dev->overflow_flag));
+
+	read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
+	atomic_set(&dev->read_idx, read_idx);
+	return count;
+}
+
+/*
+ * iowarrior_write
+ */
+static ssize_t iowarrior_write(struct file *file,
+			       const char __user *user_buffer,
+			       size_t count, loff_t *ppos)
+{
+	struct iowarrior *dev;
+	int retval = 0;
+	char *buf = NULL;	/* for IOW24 and IOW56 we need a buffer */
+	struct urb *int_out_urb = NULL;
+
+	dev = (struct iowarrior *)file->private_data;
+
+	mutex_lock(&dev->mutex);
+	/* verify that the device wasn't unplugged */
+	if (dev == NULL || !dev->present) {
+		retval = -ENODEV;
+		goto exit;
+	}
+	dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
+	/* if count is 0 we're already done */
+	if (count == 0) {
+		retval = 0;
+		goto exit;
+	}
+	/* We only accept full reports */
+	if (count != dev->report_size) {
+		retval = -EINVAL;
+		goto exit;
+	}
+	switch (dev->product_id) {
+	case USB_DEVICE_ID_CODEMERCS_IOW24:
+	case USB_DEVICE_ID_CODEMERCS_IOWPV1:
+	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
+	case USB_DEVICE_ID_CODEMERCS_IOW40:
+		/* IOW24 and IOW40 use a synchronous call */
+		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
+		if (!buf) {
+			retval = -ENOMEM;
+			goto exit;
+		}
+		if (copy_from_user(buf, user_buffer, count)) {
+			retval = -EFAULT;
+			kfree(buf);
+			goto exit;
+		}
+		retval = usb_set_report(dev->interface, 2, 0, buf, count);
+		kfree(buf);
+		goto exit;
+		break;
+	case USB_DEVICE_ID_CODEMERCS_IOW56:
+		/* The IOW56 uses asynchronous IO and more urbs */
+		if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
+			/* Wait until we are below the limit for submitted urbs */
+			if (file->f_flags & O_NONBLOCK) {
+				retval = -EAGAIN;
+				goto exit;
+			} else {
+				retval = wait_event_interruptible(dev->write_wait,
+								  (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT)));
+				if (retval) {
+					/* we were interrupted by a signal */
+					retval = -ERESTART;
+					goto exit;
+				}
+				if (!dev->present) {
+					/* The device was unplugged */
+					retval = -ENODEV;
+					goto exit;
+				}
+				if (!dev->opened) {
+					/* We were closed while waiting for an URB */
+					retval = -ENODEV;
+					goto exit;
+				}
+			}
+		}
+		atomic_inc(&dev->write_busy);
+		int_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!int_out_urb) {
+			retval = -ENOMEM;
+			dbg("%s Unable to allocate urb ", __func__);
+			goto error_no_urb;
+		}
+		buf = usb_buffer_alloc(dev->udev, dev->report_size,
+				       GFP_KERNEL, &int_out_urb->transfer_dma);
+		if (!buf) {
+			retval = -ENOMEM;
+			dbg("%s Unable to allocate buffer ", __func__);
+			goto error_no_buffer;
+		}
+		usb_fill_int_urb(int_out_urb, dev->udev,
+				 usb_sndintpipe(dev->udev,
+						dev->int_out_endpoint->bEndpointAddress),
+				 buf, dev->report_size,
+				 iowarrior_write_callback, dev,
+				 dev->int_out_endpoint->bInterval);
+		int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		if (copy_from_user(buf, user_buffer, count)) {
+			retval = -EFAULT;
+			goto error;
+		}
+		retval = usb_submit_urb(int_out_urb, GFP_KERNEL);
+		if (retval) {
+			dbg("%s submit error %d for urb nr.%d", __func__,
+			    retval, atomic_read(&dev->write_busy));
+			goto error;
+		}
+		/* submit was ok */
+		retval = count;
+		usb_free_urb(int_out_urb);
+		goto exit;
+		break;
+	default:
+		/* what do we have here ? An unsupported Product-ID ? */
+		dev_err(&dev->interface->dev, "%s - not supported for product=0x%x",
+			__FUNCTION__, dev->product_id);
+		retval = -EFAULT;
+		goto exit;
+		break;
+	}
+error:
+	usb_buffer_free(dev->udev, dev->report_size, buf,
+			int_out_urb->transfer_dma);
+error_no_buffer:
+	usb_free_urb(int_out_urb);
+error_no_urb:
+	atomic_dec(&dev->write_busy);
+	wake_up_interruptible(&dev->write_wait);
+exit:
+	mutex_unlock(&dev->mutex);
+	return retval;
+}
+
+/**
+ *	iowarrior_ioctl
+ */
+static int iowarrior_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	struct iowarrior *dev = NULL;
+	__u8 *buffer;
+	__u8 __user *user_buffer;
+	int retval;
+	int io_res;		/* checks for bytes read/written and copy_to/from_user results */
+
+	dev = (struct iowarrior *)file->private_data;
+	if (dev == NULL) {
+		return -ENODEV;
+	}
+
+	buffer = kzalloc(dev->report_size, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	/* lock this object */
+	mutex_lock(&dev->mutex);
+
+	/* verify that the device wasn't unplugged */
+	if (!dev->present) {
+		mutex_unlock(&dev->mutex);
+		return -ENODEV;
+	}
+
+	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd,
+	    arg);
+
+	retval = 0;
+	io_res = 0;
+	switch (cmd) {
+	case IOW_WRITE:
+		if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||
+		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||
+		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||
+		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {
+			user_buffer = (__u8 __user *)arg;
+			io_res = copy_from_user(buffer, user_buffer,
+						dev->report_size);
+			if (io_res) {
+				retval = -EFAULT;
+			} else {
+				io_res = usb_set_report(dev->interface, 2, 0,
+							buffer,
+							dev->report_size);
+				if (io_res < 0)
+					retval = io_res;
+			}
+		} else {
+			retval = -EINVAL;
+			dev_err(&dev->interface->dev,
+				"ioctl 'IOW_WRITE' is not supported for product=0x%x.",
+				dev->product_id);
+		}
+		break;
+	case IOW_READ:
+		user_buffer = (__u8 __user *)arg;
+		io_res = usb_get_report(dev->udev,
+					dev->interface->cur_altsetting, 1, 0,
+					buffer, dev->report_size);
+		if (io_res < 0)
+			retval = io_res;
+		else {
+			io_res = copy_to_user(user_buffer, buffer, dev->report_size);
+			if (io_res < 0)
+				retval = -EFAULT;
+		}
+		break;
+	case IOW_GETINFO:
+		{
+			/* Report available information for the device */
+			struct iowarrior_info info;
+			/* needed for power consumption */
+			struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc;
+
+			/* directly from the descriptor */
+			info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+			info.product = dev->product_id;
+			info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);
+
+			/* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */
+			info.speed = le16_to_cpu(dev->udev->speed);
+			info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber;
+			info.report_size = dev->report_size;
+
+			/* serial number string has been read earlier 8 chars or empty string */
+			memcpy(info.serial, dev->chip_serial,
+			       sizeof(dev->chip_serial));
+			if (cfg_descriptor == NULL) {
+				info.power = -1;	/* no information available */
+			} else {
+				/* the MaxPower is stored in units of 2mA to make it fit into a byte-value */
+				info.power = cfg_descriptor->bMaxPower * 2;
+			}
+			io_res = copy_to_user((struct iowarrior_info __user *)arg, &info,
+					 sizeof(struct iowarrior_info));
+			if (io_res < 0)
+				retval = -EFAULT;
+			break;
+		}
+	default:
+		/* return that we did not understand this ioctl call */
+		retval = -ENOTTY;
+		break;
+	}
+
+	/* unlock the device */
+	mutex_unlock(&dev->mutex);
+	return retval;
+}
+
+/**
+ *	iowarrior_open
+ */
+static int iowarrior_open(struct inode *inode, struct file *file)
+{
+	struct iowarrior *dev = NULL;
+	struct usb_interface *interface;
+	int subminor;
+	int retval = 0;
+
+	dbg("%s", __func__);
+
+	subminor = iminor(inode);
+
+	/* prevent disconnects */
+	down(&disconnect_sem);
+
+	interface = usb_find_interface(&iowarrior_driver, subminor);
+	if (!interface) {
+		err("%s - error, can't find device for minor %d", __FUNCTION__,
+		    subminor);
+		retval = -ENODEV;
+		goto out;
+	}
+
+	dev = usb_get_intfdata(interface);
+	if (!dev) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Only one process can open each device, no sharing. */
+	if (dev->opened) {
+		retval = -EBUSY;
+		goto out;
+	}
+
+	/* setup interrupt handler for receiving values */
+	if ((retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL)) < 0) {
+		dev_err(&interface->dev, "Error %d while submitting URB\n", retval);
+		retval = -EFAULT;
+		goto out;
+	}
+	/* increment our usage count for the driver */
+	++dev->opened;
+	/* save our object in the file's private structure */
+	file->private_data = dev;
+	retval = 0;
+
+out:
+	up(&disconnect_sem);
+	return retval;
+}
+
+/**
+ *	iowarrior_release
+ */
+static int iowarrior_release(struct inode *inode, struct file *file)
+{
+	struct iowarrior *dev;
+	int retval = 0;
+
+	dev = (struct iowarrior *)file->private_data;
+	if (dev == NULL) {
+		return -ENODEV;
+	}
+
+	dbg("%s - minor %d", __func__, dev->minor);
+
+	/* lock our device */
+	mutex_lock(&dev->mutex);
+
+	if (dev->opened <= 0) {
+		retval = -ENODEV;	/* close called more than once */
+		mutex_unlock(&dev->mutex);
+	} else {
+		dev->opened = 0;	/* we're closeing now */
+		retval = 0;
+		if (dev->present) {
+			/*
+			   The device is still connected so we only shutdown
+			   pending read-/write-ops.
+			 */
+			usb_kill_urb(dev->int_in_urb);
+			wake_up_interruptible(&dev->read_wait);
+			wake_up_interruptible(&dev->write_wait);
+			mutex_unlock(&dev->mutex);
+		} else {
+			/* The device was unplugged, cleanup resources */
+			mutex_unlock(&dev->mutex);
+			iowarrior_delete(dev);
+		}
+	}
+	return retval;
+}
+
+static unsigned iowarrior_poll(struct file *file, poll_table * wait)
+{
+	struct iowarrior *dev = file->private_data;
+	unsigned int mask = 0;
+
+	if (!dev->present)
+		return POLLERR | POLLHUP;
+
+	poll_wait(file, &dev->read_wait, wait);
+	poll_wait(file, &dev->write_wait, wait);
+
+	if (!dev->present)
+		return POLLERR | POLLHUP;
+
+	if (read_index(dev) != -1)
+		mask |= POLLIN | POLLRDNORM;
+
+	if (atomic_read(&dev->write_busy) < MAX_WRITES_IN_FLIGHT)
+		mask |= POLLOUT | POLLWRNORM;
+	return mask;
+}
+
+/*
+ * File operations needed when we register this driver.
+ * This assumes that this driver NEEDS file operations,
+ * of course, which means that the driver is expected
+ * to have a node in the /dev directory. If the USB
+ * device were for a network interface then the driver
+ * would use "struct net_driver" instead, and a serial
+ * device would use "struct tty_driver".
+ */
+static struct file_operations iowarrior_fops = {
+	.owner = THIS_MODULE,
+	.write = iowarrior_write,
+	.read = iowarrior_read,
+	.ioctl = iowarrior_ioctl,
+	.open = iowarrior_open,
+	.release = iowarrior_release,
+	.poll = iowarrior_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 iowarrior_class = {
+	.name = "iowarrior%d",
+	.fops = &iowarrior_fops,
+	.minor_base = IOWARRIOR_MINOR_BASE,
+};
+
+/*---------------------------------*/
+/*  probe and disconnect functions */
+/*---------------------------------*/
+/**
+ *	iowarrior_probe
+ *
+ *	Called by the usb core when a new device is connected that it thinks
+ *	this driver might be interested in.
+ */
+static int iowarrior_probe(struct usb_interface *interface,
+			   const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct iowarrior *dev = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int i;
+	int retval = -ENOMEM;
+
+	/* allocate memory for our device state and intialize it */
+	dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "Out of memory");
+		return retval;
+	}
+
+	mutex_init(&dev->mutex);
+
+	atomic_set(&dev->intr_idx, 0);
+	atomic_set(&dev->read_idx, 0);
+	spin_lock_init(&dev->intr_idx_lock);
+	atomic_set(&dev->overflow_flag, 0);
+	init_waitqueue_head(&dev->read_wait);
+	atomic_set(&dev->write_busy, 0);
+	init_waitqueue_head(&dev->write_wait);
+
+	dev->udev = udev;
+	dev->interface = interface;
+
+	iface_desc = interface->cur_altsetting;
+	dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
+
+	/* set up the endpoint information */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_int_in(endpoint))
+			dev->int_in_endpoint = endpoint;
+		if (usb_endpoint_is_int_out(endpoint))
+			/* this one will match for the IOWarrior56 only */
+			dev->int_out_endpoint = endpoint;
+	}
+	/* we have to check the report_size often, so remember it in the endianess suitable for our machine */
+	dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize);
+	if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
+	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))
+		/* IOWarrior56 has wMaxPacketSize different from report size */
+		dev->report_size = 7;
+
+	/* create the urb and buffer for reading */
+	dev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->int_in_urb) {
+		dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
+		goto error;
+	}
+	dev->int_in_buffer = kmalloc(dev->report_size, GFP_KERNEL);
+	if (!dev->int_in_buffer) {
+		dev_err(&interface->dev, "Couldn't allocate int_in_buffer\n");
+		goto error;
+	}
+	usb_fill_int_urb(dev->int_in_urb, dev->udev,
+			 usb_rcvintpipe(dev->udev,
+					dev->int_in_endpoint->bEndpointAddress),
+			 dev->int_in_buffer, dev->report_size,
+			 iowarrior_callback, dev,
+			 dev->int_in_endpoint->bInterval);
+	/* create an internal buffer for interrupt data from the device */
+	dev->read_queue =
+	    kmalloc(((dev->report_size + 1) * MAX_INTERRUPT_BUFFER),
+		    GFP_KERNEL);
+	if (!dev->read_queue) {
+		dev_err(&interface->dev, "Couldn't allocate read_queue\n");
+		goto error;
+	}
+	/* Get the serial-number of the chip */
+	memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));
+	usb_string(udev, udev->descriptor.iSerialNumber, dev->chip_serial,
+		   sizeof(dev->chip_serial));
+	if (strlen(dev->chip_serial) != 8)
+		memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));
+
+	/* Set the idle timeout to 0, if this is interface 0 */
+	if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) {
+	    usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			    0x0A,
+			    USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
+			    0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+	}
+	/* allow device read and ioctl */
+	dev->present = 1;
+
+	/* we can register the device now, as it is ready */
+	usb_set_intfdata(interface, dev);
+
+	retval = usb_register_dev(interface, &iowarrior_class);
+	if (retval) {
+		/* something prevented us from registering this driver */
+		dev_err(&interface->dev, "Not able to get a minor for this device.\n");
+		usb_set_intfdata(interface, NULL);
+		goto error;
+	}
+
+	dev->minor = interface->minor;
+
+	/* let the user know what node this device is now attached to */
+	dev_info(&interface->dev, "IOWarrior product=0x%x, serial=%s interface=%d "
+		 "now attached to iowarrior%d\n", dev->product_id, dev->chip_serial,
+		 iface_desc->desc.bInterfaceNumber, dev->minor - IOWARRIOR_MINOR_BASE);
+	return retval;
+
+error:
+	iowarrior_delete(dev);
+	return retval;
+}
+
+/**
+ *	iowarrior_disconnect
+ *
+ *	Called by the usb core when the device is removed from the system.
+ */
+static void iowarrior_disconnect(struct usb_interface *interface)
+{
+	struct iowarrior *dev;
+	int minor;
+
+	/* prevent races with open() */
+	down(&disconnect_sem);
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	mutex_lock(&dev->mutex);
+
+	minor = dev->minor;
+
+	/* give back our minor */
+	usb_deregister_dev(interface, &iowarrior_class);
+
+	/* prevent device read, write and ioctl */
+	dev->present = 0;
+
+	mutex_unlock(&dev->mutex);
+
+	if (dev->opened) {
+		/* There is a process that holds a filedescriptor to the device ,
+		   so we only shutdown read-/write-ops going on.
+		   Deleting the device is postponed until close() was called.
+		 */
+		usb_kill_urb(dev->int_in_urb);
+		wake_up_interruptible(&dev->read_wait);
+		wake_up_interruptible(&dev->write_wait);
+	} else {
+		/* no process is using the device, cleanup now */
+		iowarrior_delete(dev);
+	}
+	up(&disconnect_sem);
+
+	dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
+		 minor - IOWARRIOR_MINOR_BASE);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver iowarrior_driver = {
+	.name = "iowarrior",
+	.probe = iowarrior_probe,
+	.disconnect = iowarrior_disconnect,
+	.id_table = iowarrior_ids,
+};
+
+static int __init iowarrior_init(void)
+{
+	return usb_register(&iowarrior_driver);
+}
+
+static void __exit iowarrior_exit(void)
+{
+	usb_deregister(&iowarrior_driver);
+}
+
+module_init(iowarrior_init);
+module_exit(iowarrior_exit);
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 788a11e..11555bd 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -62,6 +62,8 @@
 #define USB_DEVICE_ID_VERNIER_SKIP	0x0003
 #define USB_DEVICE_ID_VERNIER_CYCLOPS	0x0004
 
+#define USB_VENDOR_ID_MICROCHIP		0x04d8
+#define USB_DEVICE_ID_PICDEM		0x000c
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
 #define USB_LD_MINOR_BASE	0
@@ -89,6 +91,7 @@
 	{ 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) },
+	{ USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICDEM) },
 	{ }					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, ld_usb_table);
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index ada2ebc..887ef95 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -47,6 +47,7 @@
 #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
 
 static struct usb_driver lcd_driver;
+static DEFINE_MUTEX(usb_lcd_open_mutex);
 
 
 static void lcd_delete(struct kref *kref)
@@ -68,6 +69,7 @@
 
 	subminor = iminor(inode);
 
+	mutex_lock(&usb_lcd_open_mutex);
 	interface = usb_find_interface(&lcd_driver, subminor);
 	if (!interface) {
 		err ("USBLCD: %s - error, can't find device for minor %d",
@@ -89,6 +91,7 @@
 	file->private_data = dev;
 
 exit:
+	mutex_unlock(&usb_lcd_open_mutex);
 	return retval;
 }
 
@@ -347,7 +350,7 @@
         int minor = interface->minor;
 
         /* prevent skel_open() from racing skel_disconnect() */
-        lock_kernel();
+        mutex_lock(&usb_lcd_open_mutex);
 
         dev = usb_get_intfdata(interface);
         usb_set_intfdata(interface, NULL);
@@ -355,7 +358,7 @@
         /* give back our minor */
         usb_deregister_dev(interface, &lcd_class);
  
-	unlock_kernel();
+	mutex_unlock(&usb_lcd_open_mutex);
 
 	/* decrement our usage count */
 	kref_put(&dev->kref, lcd_delete);
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index c01dfe6..0af11a6 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -356,8 +356,10 @@
 	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
 		return '-';
 
-	if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+	if (urb->dev->bus->uses_dma &&
+	    (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
 		return mon_dmapeek(setupb, urb->setup_dma, SETUP_LEN);
+	}
 	if (urb->setup_packet == NULL)
 		return 'Z';
 
@@ -369,7 +371,8 @@
     unsigned int offset, struct urb *urb, unsigned int length)
 {
 
-	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) {
+	if (urb->dev->bus->uses_dma &&
+	    (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
 		mon_dmapeek_vec(rp, offset, urb->transfer_dma, length);
 		return 0;
 	}
@@ -440,7 +443,7 @@
 	/* We use the fact that usb_pipein() returns 0x80 */
 	ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
 	ep->devnum = usb_pipedevice(urb->pipe);
-	ep->busnum = rp->r.m_bus->u_bus->busnum;
+	ep->busnum = urb->dev->bus->busnum;
 	ep->id = (unsigned long) urb;
 	ep->ts_sec = ts.tv_sec;
 	ep->ts_usec = ts.tv_usec;
@@ -500,7 +503,7 @@
 	/* We use the fact that usb_pipein() returns 0x80 */
 	ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
 	ep->devnum = usb_pipedevice(urb->pipe);
-	ep->busnum = rp->r.m_bus->u_bus->busnum;
+	ep->busnum = urb->dev->bus->busnum;
 	ep->id = (unsigned long) urb;
 	ep->status = error;
 
@@ -515,7 +518,6 @@
 static int mon_bin_open(struct inode *inode, struct file *file)
 {
 	struct mon_bus *mbus;
-	struct usb_bus *ubus;
 	struct mon_reader_bin *rp;
 	size_t size;
 	int rc;
@@ -525,7 +527,7 @@
 		mutex_unlock(&mon_lock);
 		return -ENODEV;
 	}
-	if ((ubus = mbus->u_bus) == NULL) {
+	if (mbus != &mon_bus0 && mbus->u_bus == NULL) {
 		printk(KERN_ERR TAG ": consistency error on open\n");
 		mutex_unlock(&mon_lock);
 		return -ENODEV;
@@ -1165,7 +1167,7 @@
 	return rc;
 }
 
-void __exit mon_bin_exit(void)
+void mon_bin_exit(void)
 {
 	cdev_del(&mon_bin_cdev);
 	unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index c9739e7..8a1df2c 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -16,8 +16,6 @@
 #include "usb_mon.h"
 #include "../core/hcd.h"
 
-static void mon_submit(struct usb_bus *ubus, struct urb *urb);
-static void mon_complete(struct usb_bus *ubus, struct urb *urb);
 static void mon_stop(struct mon_bus *mbus);
 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
 static void mon_bus_drop(struct kref *r);
@@ -25,6 +23,7 @@
 
 DEFINE_MUTEX(mon_lock);
 
+struct mon_bus mon_bus0;		/* Pseudo bus meaning "all buses" */
 static LIST_HEAD(mon_buses);		/* All buses we know: struct mon_bus */
 
 /*
@@ -35,22 +34,19 @@
 void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
 {
 	unsigned long flags;
-	struct usb_bus *ubus;
+	struct list_head *p;
 
 	spin_lock_irqsave(&mbus->lock, flags);
 	if (mbus->nreaders == 0) {
-		ubus = mbus->u_bus;
-		if (ubus->monitored) {
-			/*
-			 * Something is really broken, refuse to go on and
-			 * possibly corrupt ops pointers or worse.
-			 */
-			printk(KERN_ERR TAG ": bus %d is already monitored\n",
-			    ubus->busnum);
-			spin_unlock_irqrestore(&mbus->lock, flags);
-			return;
+		if (mbus == &mon_bus0) {
+			list_for_each (p, &mon_buses) {
+				struct mon_bus *m1;
+				m1 = list_entry(p, struct mon_bus, bus_link);
+				m1->u_bus->monitored = 1;
+			}
+		} else {
+			mbus->u_bus->monitored = 1;
 		}
-		ubus->monitored = 1;
 	}
 	mbus->nreaders++;
 	list_add_tail(&r->r_link, &mbus->r_list);
@@ -80,77 +76,79 @@
 
 /*
  */
-static void mon_submit(struct usb_bus *ubus, struct urb *urb)
+static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb)
 {
-	struct mon_bus *mbus;
 	unsigned long flags;
 	struct list_head *pos;
 	struct mon_reader *r;
 
-	mbus = ubus->mon_bus;
-	if (mbus == NULL)
-		goto out_unlocked;
-
 	spin_lock_irqsave(&mbus->lock, flags);
-	if (mbus->nreaders == 0)
-		goto out_locked;
-
 	mbus->cnt_events++;
 	list_for_each (pos, &mbus->r_list) {
 		r = list_entry(pos, struct mon_reader, r_link);
 		r->rnf_submit(r->r_data, urb);
 	}
-
 	spin_unlock_irqrestore(&mbus->lock, flags);
 	return;
+}
 
-out_locked:
-	spin_unlock_irqrestore(&mbus->lock, flags);
-out_unlocked:
-	return;
+static void mon_submit(struct usb_bus *ubus, struct urb *urb)
+{
+	struct mon_bus *mbus;
+
+	if ((mbus = ubus->mon_bus) != NULL)
+		mon_bus_submit(mbus, urb);
+	mon_bus_submit(&mon_bus0, urb);
 }
 
 /*
  */
-static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int error)
 {
-	struct mon_bus *mbus;
 	unsigned long flags;
 	struct list_head *pos;
 	struct mon_reader *r;
 
-	mbus = ubus->mon_bus;
-	if (mbus == NULL)
-		goto out_unlocked;
-
 	spin_lock_irqsave(&mbus->lock, flags);
-	if (mbus->nreaders == 0)
-		goto out_locked;
-
 	mbus->cnt_events++;
 	list_for_each (pos, &mbus->r_list) {
 		r = list_entry(pos, struct mon_reader, r_link);
 		r->rnf_error(r->r_data, urb, error);
 	}
-
 	spin_unlock_irqrestore(&mbus->lock, flags);
 	return;
+}
 
-out_locked:
-	spin_unlock_irqrestore(&mbus->lock, flags);
-out_unlocked:
-	return;
+static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+{
+	struct mon_bus *mbus;
+
+	if ((mbus = ubus->mon_bus) != NULL)
+		mon_bus_submit_error(mbus, urb, error);
+	mon_bus_submit_error(&mon_bus0, urb, error);
 }
 
 /*
  */
-static void mon_complete(struct usb_bus *ubus, struct urb *urb)
+static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb)
 {
-	struct mon_bus *mbus;
 	unsigned long flags;
 	struct list_head *pos;
 	struct mon_reader *r;
 
+	spin_lock_irqsave(&mbus->lock, flags);
+	mbus->cnt_events++;
+	list_for_each (pos, &mbus->r_list) {
+		r = list_entry(pos, struct mon_reader, r_link);
+		r->rnf_complete(r->r_data, urb);
+	}
+	spin_unlock_irqrestore(&mbus->lock, flags);
+}
+
+static void mon_complete(struct usb_bus *ubus, struct urb *urb)
+{
+	struct mon_bus *mbus;
+
 	mbus = ubus->mon_bus;
 	if (mbus == NULL) {
 		/*
@@ -162,13 +160,8 @@
 		return;
 	}
 
-	spin_lock_irqsave(&mbus->lock, flags);
-	mbus->cnt_events++;
-	list_for_each (pos, &mbus->r_list) {
-		r = list_entry(pos, struct mon_reader, r_link);
-		r->rnf_complete(r->r_data, urb);
-	}
-	spin_unlock_irqrestore(&mbus->lock, flags);
+	mon_bus_complete(mbus, urb);
+	mon_bus_complete(&mon_bus0, urb);
 }
 
 /* int (*unlink_urb) (struct urb *urb, int status); */
@@ -179,14 +172,26 @@
 static void mon_stop(struct mon_bus *mbus)
 {
 	struct usb_bus *ubus = mbus->u_bus;
+	struct list_head *p;
 
-	/*
-	 * A stop can be called for a dissolved mon_bus in case of
-	 * a reader staying across an rmmod foo_hcd.
-	 */
-	if (ubus != NULL) {
-		ubus->monitored = 0;
-		mb();
+	if (mbus == &mon_bus0) {
+		list_for_each (p, &mon_buses) {
+			mbus = list_entry(p, struct mon_bus, bus_link);
+			/*
+			 * We do not change nreaders here, so rely on mon_lock.
+			 */
+			if (mbus->nreaders == 0 && (ubus = mbus->u_bus) != NULL)
+				ubus->monitored = 0;
+		}
+	} else {
+		/*
+		 * A stop can be called for a dissolved mon_bus in case of
+		 * a reader staying across an rmmod foo_hcd, so test ->u_bus.
+		 */
+		if (mon_bus0.nreaders == 0 && (ubus = mbus->u_bus) != NULL) {
+			ubus->monitored = 0;
+			mb();
+		}
 	}
 }
 
@@ -199,6 +204,10 @@
 static void mon_bus_add(struct usb_bus *ubus)
 {
 	mon_bus_init(ubus);
+	mutex_lock(&mon_lock);
+	if (mon_bus0.nreaders != 0)
+		ubus->monitored = 1;
+	mutex_unlock(&mon_lock);
 }
 
 /*
@@ -250,12 +259,7 @@
 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
 {
 
-	/*
-	 * Never happens, but...
-	 */
 	if (ubus->monitored) {
-		printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n",
-		    ubus->busnum);
 		ubus->monitored = 0;
 		mb();
 	}
@@ -263,6 +267,8 @@
 	ubus->mon_bus = NULL;
 	mbus->u_bus = NULL;
 	mb();
+
+	/* We want synchronize_irq() here, but that needs an argument. */
 }
 
 /*
@@ -295,9 +301,8 @@
 	 */
 	mbus->u_bus = ubus;
 	ubus->mon_bus = mbus;
-	mbus->uses_dma = ubus->uses_dma;
 
-	mbus->text_inited = mon_text_add(mbus, ubus);
+	mbus->text_inited = mon_text_add(mbus, ubus->busnum);
 	// mon_bin_add(...)
 
 	mutex_lock(&mon_lock);
@@ -309,6 +314,18 @@
 	return;
 }
 
+static void mon_bus0_init(void)
+{
+	struct mon_bus *mbus = &mon_bus0;
+
+	kref_init(&mbus->ref);
+	spin_lock_init(&mbus->lock);
+	INIT_LIST_HEAD(&mbus->r_list);
+
+	mbus->text_inited = mon_text_add(mbus, 0);
+	// mbus->bin_inited = mon_bin_add(mbus, 0);
+}
+
 /*
  * Search a USB bus by number. Notice that USB bus numbers start from one,
  * which we may later use to identify "all" with zero.
@@ -322,6 +339,9 @@
 	struct list_head *p;
 	struct mon_bus *mbus;
 
+	if (num == 0) {
+		return &mon_bus0;
+	}
 	list_for_each (p, &mon_buses) {
 		mbus = list_entry(p, struct mon_bus, bus_link);
 		if (mbus->u_bus->busnum == num) {
@@ -341,6 +361,8 @@
 	if ((rc = mon_bin_init()) != 0)
 		goto err_bin;
 
+	mon_bus0_init();
+
 	if (usb_mon_register(&mon_ops_0) != 0) {
 		printk(KERN_NOTICE TAG ": unable to register with the core\n");
 		rc = -ENODEV;
@@ -374,6 +396,7 @@
 	usb_mon_deregister();
 
 	mutex_lock(&mon_lock);
+
 	while (!list_empty(&mon_buses)) {
 		p = mon_buses.next;
 		mbus = list_entry(p, struct mon_bus, bus_link);
@@ -397,6 +420,11 @@
 		mon_dissolve(mbus, mbus->u_bus);
 		kref_put(&mbus->ref, mon_bus_drop);
 	}
+
+	mbus = &mon_bus0;
+	if (mbus->text_inited)
+		mon_text_del(mbus);
+
 	mutex_unlock(&mon_lock);
 
 	mon_text_exit();
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index d38a127..ec0cc51 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -31,9 +31,21 @@
  * to a local DoS. But we have to keep to root in order to prevent
  * password sniffing from HID devices.
  */
-#define EVENT_MAX  (2*PAGE_SIZE / sizeof(struct mon_event_text))
+#define EVENT_MAX  (4*PAGE_SIZE / sizeof(struct mon_event_text))
 
-#define PRINTF_DFL  160
+/*
+ * Potentially unlimited number; we limit it for similar allocations.
+ * The usbfs limits this to 128, but we're not quite as generous.
+ */
+#define ISODESC_MAX   5
+
+#define PRINTF_DFL  250   /* with 5 ISOs segs */
+
+struct mon_iso_desc {
+	int status;
+	unsigned int offset;
+	unsigned int length;	/* Unsigned here, signed in URB. Historic. */
+};
 
 struct mon_event_text {
 	struct list_head e_link;
@@ -41,10 +53,16 @@
 	unsigned int pipe;	/* Pipe */
 	unsigned long id;	/* From pointer, most of the time */
 	unsigned int tstamp;
+	int busnum;
 	int length;		/* Depends on type: xfer length or act length */
 	int status;
+	int interval;
+	int start_frame;
+	int error_count;
 	char setup_flag;
 	char data_flag;
+	int numdesc;		/* Full number */
+	struct mon_iso_desc isodesc[ISODESC_MAX];
 	unsigned char setup[SETUP_MAX];
 	unsigned char data[DATA_MAX];
 };
@@ -68,6 +86,28 @@
 
 static void mon_text_ctor(void *, struct kmem_cache *, unsigned long);
 
+struct mon_text_ptr {
+	int cnt, limit;
+	char *pbuf;
+};
+
+static struct mon_event_text *
+    mon_text_read_wait(struct mon_reader_text *rp, struct file *file);
+static void mon_text_read_head_t(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_head_u(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_statset(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_intstat(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_isostat(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_isodesc(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_data(struct mon_reader_text *rp,
+    struct mon_text_ptr *p, const struct mon_event_text *ep);
+
 /*
  * mon_text_submit
  * mon_text_complete
@@ -84,8 +124,10 @@
 	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
 		return '-';
 
-	if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+	if (urb->dev->bus->uses_dma &&
+	    (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
 		return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
+	}
 	if (urb->setup_packet == NULL)
 		return 'Z';	/* '0' would be not as pretty. */
 
@@ -104,10 +146,10 @@
 		len = DATA_MAX;
 
 	if (usb_pipein(pipe)) {
-		if (ev_type == 'S')
+		if (ev_type != 'C')
 			return '<';
 	} else {
-		if (ev_type == 'C')
+		if (ev_type != 'S')
 			return '>';
 	}
 
@@ -120,8 +162,10 @@
 	 * contain non-NULL garbage in case the upper level promised to
 	 * set DMA for the HCD.
 	 */
-	if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+	if (urb->dev->bus->uses_dma &&
+	    (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
 		return mon_dmapeek(ep->data, urb->transfer_dma, len);
+	}
 
 	if (urb->transfer_buffer == NULL)
 		return 'Z';	/* '0' would be not as pretty. */
@@ -146,6 +190,9 @@
 {
 	struct mon_event_text *ep;
 	unsigned int stamp;
+	struct usb_iso_packet_descriptor *fp;
+	struct mon_iso_desc *dp;
+	int i, ndesc;
 
 	stamp = mon_get_timestamp();
 
@@ -158,12 +205,36 @@
 	ep->type = ev_type;
 	ep->pipe = urb->pipe;
 	ep->id = (unsigned long) urb;
+	ep->busnum = urb->dev->bus->busnum;
 	ep->tstamp = stamp;
 	ep->length = (ev_type == 'S') ?
 	    urb->transfer_buffer_length : urb->actual_length;
 	/* Collecting status makes debugging sense for submits, too */
 	ep->status = urb->status;
 
+	if (usb_pipeint(urb->pipe)) {
+		ep->interval = urb->interval;
+	} else if (usb_pipeisoc(urb->pipe)) {
+		ep->interval = urb->interval;
+		ep->start_frame = urb->start_frame;
+		ep->error_count = urb->error_count;
+	}
+	ep->numdesc = urb->number_of_packets;
+	if (usb_pipeisoc(urb->pipe) && urb->number_of_packets > 0) {
+		if ((ndesc = urb->number_of_packets) > ISODESC_MAX)
+			ndesc = ISODESC_MAX;
+		fp = urb->iso_frame_desc;
+		dp = ep->isodesc;
+		for (i = 0; i < ndesc; i++) {
+			dp->status = fp->status;
+			dp->offset = fp->offset;
+			dp->length = (ev_type == 'S') ?
+			    fp->length : fp->actual_length;
+			fp++;
+			dp++;
+		}
+	}
+
 	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
 	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
 			rp->r.m_bus);
@@ -199,6 +270,7 @@
 	ep->type = 'E';
 	ep->pipe = urb->pipe;
 	ep->id = (unsigned long) urb;
+	ep->busnum = 0;
 	ep->tstamp = 0;
 	ep->length = 0;
 	ep->status = error;
@@ -237,13 +309,11 @@
 static int mon_text_open(struct inode *inode, struct file *file)
 {
 	struct mon_bus *mbus;
-	struct usb_bus *ubus;
 	struct mon_reader_text *rp;
 	int rc;
 
 	mutex_lock(&mon_lock);
 	mbus = inode->i_private;
-	ubus = mbus->u_bus;
 
 	rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
 	if (rp == NULL) {
@@ -267,8 +337,7 @@
 	rp->r.rnf_error = mon_text_error;
 	rp->r.rnf_complete = mon_text_complete;
 
-	snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
-	    (long)rp);
+	snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp);
 	rp->e_slab = kmem_cache_create(rp->slab_name,
 	    sizeof(struct mon_event_text), sizeof(long), 0,
 	    mon_text_ctor, NULL);
@@ -300,17 +369,75 @@
  *   dd if=/dbg/usbmon/0t bs=10
  * Also, we do not allow seeks and do not bother advancing the offset.
  */
-static ssize_t mon_text_read(struct file *file, char __user *buf,
+static ssize_t mon_text_read_t(struct file *file, char __user *buf,
 				size_t nbytes, loff_t *ppos)
 {
 	struct mon_reader_text *rp = file->private_data;
+	struct mon_event_text *ep;
+	struct mon_text_ptr ptr;
+
+	if (IS_ERR(ep = mon_text_read_wait(rp, file)))
+		return PTR_ERR(ep);
+	mutex_lock(&rp->printf_lock);
+	ptr.cnt = 0;
+	ptr.pbuf = rp->printf_buf;
+	ptr.limit = rp->printf_size;
+
+	mon_text_read_head_t(rp, &ptr, ep);
+	mon_text_read_statset(rp, &ptr, ep);
+	ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
+	    " %d", ep->length);
+	mon_text_read_data(rp, &ptr, ep);
+
+	if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
+		ptr.cnt = -EFAULT;
+	mutex_unlock(&rp->printf_lock);
+	kmem_cache_free(rp->e_slab, ep);
+	return ptr.cnt;
+}
+
+static ssize_t mon_text_read_u(struct file *file, char __user *buf,
+				size_t nbytes, loff_t *ppos)
+{
+	struct mon_reader_text *rp = file->private_data;
+	struct mon_event_text *ep;
+	struct mon_text_ptr ptr;
+
+	if (IS_ERR(ep = mon_text_read_wait(rp, file)))
+		return PTR_ERR(ep);
+	mutex_lock(&rp->printf_lock);
+	ptr.cnt = 0;
+	ptr.pbuf = rp->printf_buf;
+	ptr.limit = rp->printf_size;
+
+	mon_text_read_head_u(rp, &ptr, ep);
+	if (ep->type == 'E') {
+		mon_text_read_statset(rp, &ptr, ep);
+	} else if (usb_pipeisoc(ep->pipe)) {
+		mon_text_read_isostat(rp, &ptr, ep);
+		mon_text_read_isodesc(rp, &ptr, ep);
+	} else if (usb_pipeint(ep->pipe)) {
+		mon_text_read_intstat(rp, &ptr, ep);
+	} else {
+		mon_text_read_statset(rp, &ptr, ep);
+	}
+	ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
+	    " %d", ep->length);
+	mon_text_read_data(rp, &ptr, ep);
+
+	if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
+		ptr.cnt = -EFAULT;
+	mutex_unlock(&rp->printf_lock);
+	kmem_cache_free(rp->e_slab, ep);
+	return ptr.cnt;
+}
+
+static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp,
+    struct file *file)
+{
 	struct mon_bus *mbus = rp->r.m_bus;
 	DECLARE_WAITQUEUE(waita, current);
 	struct mon_event_text *ep;
-	int cnt, limit;
-	char *pbuf;
-	char udir, utype;
-	int data_len, i;
 
 	add_wait_queue(&rp->wait, &waita);
 	set_current_state(TASK_INTERRUPTIBLE);
@@ -318,7 +445,7 @@
 		if (file->f_flags & O_NONBLOCK) {
 			set_current_state(TASK_RUNNING);
 			remove_wait_queue(&rp->wait, &waita);
-			return -EWOULDBLOCK;	/* Same as EAGAIN in Linux */
+			return ERR_PTR(-EWOULDBLOCK);
 		}
 		/*
 		 * We do not count nwaiters, because ->release is supposed
@@ -327,17 +454,19 @@
 		schedule();
 		if (signal_pending(current)) {
 			remove_wait_queue(&rp->wait, &waita);
-			return -EINTR;
+			return ERR_PTR(-EINTR);
 		}
 		set_current_state(TASK_INTERRUPTIBLE);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&rp->wait, &waita);
+	return ep;
+}
 
-	mutex_lock(&rp->printf_lock);
-	cnt = 0;
-	pbuf = rp->printf_buf;
-	limit = rp->printf_size;
+static void mon_text_read_head_t(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+	char udir, utype;
 
 	udir = usb_pipein(ep->pipe) ? 'i' : 'o';
 	switch (usb_pipetype(ep->pipe)) {
@@ -346,13 +475,38 @@
 	case PIPE_CONTROL:	utype = 'C'; break;
 	default: /* PIPE_BULK */  utype = 'B';
 	}
-	cnt += snprintf(pbuf + cnt, limit - cnt,
+	p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
 	    "%lx %u %c %c%c:%03u:%02u",
 	    ep->id, ep->tstamp, ep->type,
-	    utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+	    utype, udir,
+	    usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+}
+
+static void mon_text_read_head_u(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+	char udir, utype;
+
+	udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+	switch (usb_pipetype(ep->pipe)) {
+	case PIPE_ISOCHRONOUS:	utype = 'Z'; break;
+	case PIPE_INTERRUPT:	utype = 'I'; break;
+	case PIPE_CONTROL:	utype = 'C'; break;
+	default: /* PIPE_BULK */  utype = 'B';
+	}
+	p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+	    "%lx %u %c %c%c:%d:%03u:%u",
+	    ep->id, ep->tstamp, ep->type,
+	    utype, udir,
+	    ep->busnum, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+}
+
+static void mon_text_read_statset(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
 
 	if (ep->setup_flag == 0) {   /* Setup packet is present and captured */
-		cnt += snprintf(pbuf + cnt, limit - cnt,
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
 		    " s %02x %02x %04x %04x %04x",
 		    ep->setup[0],
 		    ep->setup[1],
@@ -360,40 +514,86 @@
 		    (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,
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
 		    " %c __ __ ____ ____ ____", ep->setup_flag);
 	} else {                     /* No setup for this kind of URB */
-		cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status);
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+		    " %d", ep->status);
 	}
-	cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length);
+}
+
+static void mon_text_read_intstat(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+	p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+	    " %d:%d", ep->status, ep->interval);
+}
+
+static void mon_text_read_isostat(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+	if (ep->type == 'S') {
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+		    " %d:%d:%d", ep->status, ep->interval, ep->start_frame);
+	} else {
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+		    " %d:%d:%d:%d",
+		    ep->status, ep->interval, ep->start_frame, ep->error_count);
+	}
+}
+
+static void mon_text_read_isodesc(struct mon_reader_text *rp,
+	struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+	int ndesc;	/* Display this many */
+	int i;
+	const struct mon_iso_desc *dp;
+
+	p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+	    " %d", ep->numdesc);
+	ndesc = ep->numdesc;
+	if (ndesc > ISODESC_MAX)
+		ndesc = ISODESC_MAX;
+	if (ndesc < 0)
+		ndesc = 0;
+	dp = ep->isodesc;
+	for (i = 0; i < ndesc; i++) {
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+		    " %d:%u:%u", dp->status, dp->offset, dp->length);
+		dp++;
+	}
+}
+
+static void mon_text_read_data(struct mon_reader_text *rp,
+    struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+	int data_len, i;
 
 	if ((data_len = ep->length) > 0) {
 		if (ep->data_flag == 0) {
-			cnt += snprintf(pbuf + cnt, limit - cnt, " =");
+			p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+			    " =");
 			if (data_len >= DATA_MAX)
 				data_len = DATA_MAX;
 			for (i = 0; i < data_len; i++) {
 				if (i % 4 == 0) {
-					cnt += snprintf(pbuf + cnt, limit - cnt,
+					p->cnt += snprintf(p->pbuf + p->cnt,
+					    p->limit - p->cnt,
 					    " ");
 				}
-				cnt += snprintf(pbuf + cnt, limit - cnt,
+				p->cnt += snprintf(p->pbuf + p->cnt,
+				    p->limit - p->cnt,
 				    "%02x", ep->data[i]);
 			}
-			cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+			p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+			    "\n");
 		} else {
-			cnt += snprintf(pbuf + cnt, limit - cnt,
+			p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
 			    " %c\n", ep->data_flag);
 		}
 	} else {
-		cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+		p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n");
 	}
-
-	if (copy_to_user(buf, rp->printf_buf, cnt))
-		cnt = -EFAULT;
-	mutex_unlock(&rp->printf_lock);
-	kmem_cache_free(rp->e_slab, ep);
-	return cnt;
 }
 
 static int mon_text_release(struct inode *inode, struct file *file)
@@ -439,34 +639,46 @@
 	return 0;
 }
 
-static const struct file_operations mon_fops_text = {
+static const struct file_operations mon_fops_text_t = {
 	.owner =	THIS_MODULE,
 	.open =		mon_text_open,
 	.llseek =	no_llseek,
-	.read =		mon_text_read,
-	/* .write =	mon_text_write, */
-	/* .poll =		mon_text_poll, */
-	/* .ioctl =	mon_text_ioctl, */
+	.read =		mon_text_read_t,
 	.release =	mon_text_release,
 };
 
-int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
+static const struct file_operations mon_fops_text_u = {
+	.owner =	THIS_MODULE,
+	.open =		mon_text_open,
+	.llseek =	no_llseek,
+	.read =		mon_text_read_u,
+	.release =	mon_text_release,
+};
+
+int mon_text_add(struct mon_bus *mbus, int busnum)
 {
 	struct dentry *d;
 	enum { NAMESZ = 10 };
 	char name[NAMESZ];
 	int rc;
 
-	rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
+	rc = snprintf(name, NAMESZ, "%dt", busnum);
 	if (rc <= 0 || rc >= NAMESZ)
 		goto err_print_t;
-	d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text);
+	d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t);
 	if (d == NULL)
 		goto err_create_t;
 	mbus->dent_t = d;
 
-	/* XXX The stats do not belong to here (text API), but oh well... */
-	rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
+	rc = snprintf(name, NAMESZ, "%du", busnum);
+	if (rc <= 0 || rc >= NAMESZ)
+		goto err_print_u;
+	d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_u);
+	if (d == NULL)
+		goto err_create_u;
+	mbus->dent_u = d;
+
+	rc = snprintf(name, NAMESZ, "%ds", busnum);
 	if (rc <= 0 || rc >= NAMESZ)
 		goto err_print_s;
 	d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_stat);
@@ -478,6 +690,10 @@
 
 err_create_s:
 err_print_s:
+	debugfs_remove(mbus->dent_u);
+	mbus->dent_u = NULL;
+err_create_u:
+err_print_u:
 	debugfs_remove(mbus->dent_t);
 	mbus->dent_t = NULL;
 err_create_t:
@@ -487,6 +703,7 @@
 
 void mon_text_del(struct mon_bus *mbus)
 {
+	debugfs_remove(mbus->dent_u);
 	debugfs_remove(mbus->dent_t);
 	debugfs_remove(mbus->dent_s);
 }
@@ -520,7 +737,7 @@
 	return 0;
 }
 
-void __exit mon_text_exit(void)
+void mon_text_exit(void)
 {
 	debugfs_remove(mon_dir);
 }
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 4f949ce..13d6325 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -22,7 +22,7 @@
 	int text_inited;
 	struct dentry *dent_s;		/* Debugging file */
 	struct dentry *dent_t;		/* Text interface file */
-	int uses_dma;
+	struct dentry *dent_u;		/* Second text interface file */
 
 	/* Ref */
 	int nreaders;			/* Under mon_lock AND mbus->lock */
@@ -52,14 +52,14 @@
 
 struct mon_bus *mon_bus_lookup(unsigned int num);
 
-int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus);
+int /*bool*/ mon_text_add(struct mon_bus *mbus, int busnum);
 void mon_text_del(struct mon_bus *mbus);
 // void mon_bin_add(struct mon_bus *);
 
 int __init mon_text_init(void);
-void __exit mon_text_exit(void);
+void mon_text_exit(void);
 int __init mon_bin_init(void);
-void __exit mon_bin_exit(void);
+void mon_bin_exit(void);
 
 /*
  * DMA interface.
@@ -81,4 +81,6 @@
 
 extern const struct file_operations mon_fops_stat;
 
+extern struct mon_bus mon_bus0;		/* Only for redundant checks */
+
 #endif /* __USB_MON_H */
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index a2b94ef5..3de564b 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -84,6 +84,7 @@
 config USB_RTL8150
 	tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	select MII
 	help
 	  Say Y here if you have RTL8150 based usb-ethernet adapter.
 	  Send me <petkan@users.sourceforge.net> any comments you may have.
@@ -98,7 +99,7 @@
 
 config USB_USBNET
 	tristate "Multi-purpose USB Networking Framework"
-	select MII if USBNET_MII != n
+	select MII if USB_USBNET_MII != n
 	---help---
 	  This driver supports several kinds of network links over USB,
 	  with "minidrivers" built around a common network driver core
@@ -185,6 +186,15 @@
 	  IEEE 802 "local assignment" bit is set in the address, a "usbX"
 	  name is used instead.
 
+config USB_NET_DM9601
+	tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+	depends on USB_USBNET
+	select CRC32
+	select USB_USBNET_MII
+	help
+	  This option adds support for Davicom DM9601 based USB 1.1
+	  10/100 Ethernet adapters.
+
 config USB_NET_GL620A
 	tristate "GeneSys GL620USB-A based cables"
 	depends on USB_USBNET
@@ -239,6 +249,7 @@
 config USB_NET_CDC_SUBSET
 	tristate "Simple USB Network Links (CDC Ethernet subset)"
 	depends on USB_USBNET
+	default y
 	help
 	  This driver module supports USB network devices that can work
 	  without any device-specific information.  Select it if you have
@@ -298,6 +309,13 @@
 	  Choose this option to support the usb networking links used
 	  by some sample firmware from Epson.
 
+config USB_KC2190
+	boolean "KT Technology KC2190 based cables (InstaNet)"
+	depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
+	help
+	  Choose this option if you're using a host-to-host cable
+	  with one of these chips.
+
 config USB_NET_ZAURUS
 	tristate "Sharp Zaurus (stock ROMs) and compatible"
 	depends on USB_USBNET
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 7b51964..595a539 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_USB_RTL8150)	+= rtl8150.o
 obj-$(CONFIG_USB_NET_AX8817X)	+= asix.o
 obj-$(CONFIG_USB_NET_CDCETHER)	+= cdc_ether.o
+obj-$(CONFIG_USB_NET_DM9601)	+= dm9601.o
 obj-$(CONFIG_USB_NET_GL620A)	+= gl620a.o
 obj-$(CONFIG_USB_NET_NET1080)	+= net1080.o
 obj-$(CONFIG_USB_NET_PLUSB)	+= plusb.o
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index bd357e1..d5ef97b 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -298,7 +298,7 @@
 		if (ax_skb) {
 			ax_skb->len = size;
 			ax_skb->data = packet;
-			ax_skb->tail = packet + size;
+			skb_set_tail_pointer(ax_skb, size);
 			usbnet_skb_return(dev, ax_skb);
 		} else {
 			return 0;
@@ -338,7 +338,7 @@
 	    && ((headroom + tailroom) >= (4 + padlen))) {
 		if ((headroom < 4) || (tailroom < padlen)) {
 			skb->data = memmove(skb->head + 4, skb->data, skb->len);
-			skb->tail = skb->data + skb->len;
+			skb_set_tail_pointer(skb, skb->len);
 		}
 	} else {
 		struct sk_buff *skb2;
@@ -351,10 +351,12 @@
 
 	skb_push(skb, 4);
 	packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-	memcpy(skb->data, &packet_len, sizeof(packet_len));
+	cpu_to_le32s(&packet_len);
+	skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
 
 	if ((skb->len % 512) == 0) {
-		memcpy( skb->tail, &padbytes, sizeof(padbytes));
+		cpu_to_le32s(&padbytes);
+		memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
 		skb_put(skb, sizeof(padbytes));
 	}
 	return skb;
@@ -1393,9 +1395,9 @@
 	USB_DEVICE (0x07b8, 0x420a),
 	.driver_info =  (unsigned long) &hawking_uf200_info,
 }, {
-        // Billionton Systems, USB2AR
-        USB_DEVICE (0x08dd, 0x90ff),
-        .driver_info =  (unsigned long) &ax8817x_info,
+	// Billionton Systems, USB2AR
+	USB_DEVICE (0x08dd, 0x90ff),
+	.driver_info =  (unsigned long) &ax8817x_info,
 }, {
 	// ATEN UC210T
 	USB_DEVICE (0x0557, 0x2009),
@@ -1421,9 +1423,13 @@
 	USB_DEVICE (0x1631, 0x6200),
 	.driver_info = (unsigned long) &ax8817x_info,
 }, {
+	// JVC MP-PRX1 Port Replicator
+	USB_DEVICE (0x04f1, 0x3008),
+	.driver_info = (unsigned long) &ax8817x_info,
+}, {
 	// ASIX AX88772 10/100
-        USB_DEVICE (0x0b95, 0x7720),
-        .driver_info = (unsigned long) &ax88772_info,
+	USB_DEVICE (0x0b95, 0x7720),
+	.driver_info = (unsigned long) &ax88772_info,
 }, {
 	// ASIX AX88178 10/100/1000
 	USB_DEVICE (0x0b95, 0x1780),
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index 4852012..86e90c5 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -255,7 +255,6 @@
 		if (!(skb = dev_alloc_skb(pkt_len)))
 			return;
 
-		skb->dev = catc->netdev;
 		eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
 		skb_put(skb, pkt_len);
 
@@ -356,7 +355,7 @@
  * Transmit routines.
  */
 
-static void catc_tx_run(struct catc *catc)
+static int catc_tx_run(struct catc *catc)
 {
 	int status;
 
@@ -374,12 +373,14 @@
 	catc->tx_ptr = 0;
 
 	catc->netdev->trans_start = jiffies;
+	return status;
 }
 
 static void catc_tx_done(struct urb *urb)
 {
 	struct catc *catc = urb->context;
 	unsigned long flags;
+	int r;
 
 	if (urb->status == -ECONNRESET) {
 		dbg("Tx Reset.");
@@ -398,10 +399,13 @@
 
 	spin_lock_irqsave(&catc->tx_lock, flags);
 
-	if (catc->tx_ptr)
-		catc_tx_run(catc);
-	else
+	if (catc->tx_ptr) {
+		r = catc_tx_run(catc);
+		if (unlikely(r < 0))
+			clear_bit(TX_RUNNING, &catc->flags);
+	} else {
 		clear_bit(TX_RUNNING, &catc->flags);
+	}
 
 	netif_wake_queue(catc->netdev);
 
@@ -412,6 +416,7 @@
 {
 	struct catc *catc = netdev_priv(netdev);
 	unsigned long flags;
+	int r = 0;
 	char *tx_buf;
 
 	spin_lock_irqsave(&catc->tx_lock, flags);
@@ -419,11 +424,14 @@
 	catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
 	tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
 	*((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
-	memcpy(tx_buf + 2, skb->data, skb->len);
+	skb_copy_from_linear_data(skb, tx_buf + 2, skb->len);
 	catc->tx_ptr += skb->len + 2;
 
-	if (!test_and_set_bit(TX_RUNNING, &catc->flags))
-		catc_tx_run(catc);
+	if (!test_and_set_bit(TX_RUNNING, &catc->flags)) {
+		r = catc_tx_run(catc);
+		if (r < 0)
+			clear_bit(TX_RUNNING, &catc->flags);
+	}
 
 	if ((catc->is_f5u011 && catc->tx_ptr)
 	     || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
@@ -431,8 +439,10 @@
 
 	spin_unlock_irqrestore(&catc->tx_lock, flags);
 
-	catc->stats.tx_bytes += skb->len;
-	catc->stats.tx_packets++;
+	if (r >= 0) {
+		catc->stats.tx_bytes += skb->len;
+		catc->stats.tx_packets++;
+	}
 
 	dev_kfree_skb(skb);
 
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
index ae8fb06..bc62b01 100644
--- a/drivers/usb/net/cdc_subset.c
+++ b/drivers/usb/net/cdc_subset.c
@@ -79,13 +79,19 @@
  *
  * ALi M5632 driver ... does high speed
  *
+ * NOTE that the MS-Windows drivers for this chip use some funky and
+ * (naturally) undocumented 7-byte prefix to each packet, so this is a
+ * case where we don't currently interoperate.  Also, once you unplug
+ * one end of the cable, you need to replug the other end too ... since
+ * chip docs are unavailable, there's no way to reset the relevant state
+ * short of a power cycle.
+ *
  *-------------------------------------------------------------------------*/
 
 static const struct driver_info	ali_m5632_info = {
 	.description =	"ALi M5632",
 };
 
-
 #endif
 
 
@@ -159,6 +165,11 @@
 #endif	/* CONFIG_USB_EPSON2888 */
 
 
+/*-------------------------------------------------------------------------
+ *
+ * info from Jonathan McDowell <noodles@earth.li>
+ *
+ *-------------------------------------------------------------------------*/
 #ifdef CONFIG_USB_KC2190
 #define HAVE_HARDWARE
 static const struct driver_info kc2190_info = {
@@ -223,6 +234,10 @@
 	USB_DEVICE (0x0402, 0x5632),	// ALi defaults
 	.driver_info =	(unsigned long) &ali_m5632_info,
 },
+{
+	USB_DEVICE (0x182d,0x207c),	// SiteCom CN-124
+	.driver_info =	(unsigned long) &ali_m5632_info,
+},
 #endif
 
 #ifdef	CONFIG_USB_AN2720
@@ -314,13 +329,13 @@
 
 static int __init cdc_subset_init(void)
 {
- 	return usb_register(&cdc_subset_driver);
+	return usb_register(&cdc_subset_driver);
 }
 module_init(cdc_subset_init);
 
 static void __exit cdc_subset_exit(void)
 {
- 	usb_deregister(&cdc_subset_driver);
+	usb_deregister(&cdc_subset_driver);
 }
 module_exit(cdc_subset_exit);
 
diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c
new file mode 100644
index 0000000..a676386
--- /dev/null
+++ b/drivers/usb/net/dm9601.c
@@ -0,0 +1,619 @@
+/*
+ * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+//#define DEBUG
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+
+#include "usbnet.h"
+
+/* datasheet:
+ http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
+*/
+
+/* control requests */
+#define DM_READ_REGS	0x00
+#define DM_WRITE_REGS	0x01
+#define DM_READ_MEMS	0x02
+#define DM_WRITE_REG	0x03
+#define DM_WRITE_MEMS	0x05
+#define DM_WRITE_MEM	0x07
+
+/* registers */
+#define DM_NET_CTRL	0x00
+#define DM_RX_CTRL	0x05
+#define DM_SHARED_CTRL	0x0b
+#define DM_SHARED_ADDR	0x0c
+#define DM_SHARED_DATA	0x0d	/* low + high */
+#define DM_PHY_ADDR	0x10	/* 6 bytes */
+#define DM_MCAST_ADDR	0x16	/* 8 bytes */
+#define DM_GPR_CTRL	0x1e
+#define DM_GPR_DATA	0x1f
+
+#define DM_MAX_MCAST	64
+#define DM_MCAST_SIZE	8
+#define DM_EEPROM_LEN	256
+#define DM_TX_OVERHEAD	2	/* 2 byte header */
+#define DM_RX_OVERHEAD	7	/* 3 byte header + 4 byte crc tail */
+#define DM_TIMEOUT	1000
+
+
+static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+	devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length);
+	return usb_control_msg(dev->udev,
+			       usb_rcvctrlpipe(dev->udev, 0),
+			       DM_READ_REGS,
+			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       0, reg, data, length, USB_CTRL_SET_TIMEOUT);
+}
+
+static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
+{
+	return dm_read(dev, reg, 1, value);
+}
+
+static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+	devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length);
+	return usb_control_msg(dev->udev,
+			       usb_sndctrlpipe(dev->udev, 0),
+			       DM_WRITE_REGS,
+			       USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
+			       0, reg, data, length, USB_CTRL_SET_TIMEOUT);
+}
+
+static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
+{
+	devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value);
+	return usb_control_msg(dev->udev,
+			       usb_sndctrlpipe(dev->udev, 0),
+			       DM_WRITE_REG,
+			       USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
+			       value, reg, NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static void dm_write_async_callback(struct urb *urb)
+{
+	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+
+	if (urb->status < 0)
+		printk(KERN_DEBUG "dm_write_async_callback() failed with %d",
+		       urb->status);
+
+	kfree(req);
+	usb_free_urb(urb);
+}
+
+static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+	struct usb_ctrlrequest *req;
+	struct urb *urb;
+	int status;
+
+	devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		deverr(dev, "Error allocating URB in dm_write_async!");
+		return;
+	}
+
+	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+	if (!req) {
+		deverr(dev, "Failed to allocate memory for control request");
+		usb_free_urb(urb);
+		return;
+	}
+
+	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+	req->bRequest = DM_WRITE_REGS;
+	req->wValue = 0;
+	req->wIndex = cpu_to_le16(reg);
+	req->wLength = cpu_to_le16(length);
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, data, length,
+			     dm_write_async_callback, req);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status < 0) {
+		deverr(dev, "Error submitting the control message: status=%d",
+		       status);
+		kfree(req);
+		usb_free_urb(urb);
+	}
+}
+
+static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
+{
+	struct usb_ctrlrequest *req;
+	struct urb *urb;
+	int status;
+
+	devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x",
+	       reg, value);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		deverr(dev, "Error allocating URB in dm_write_async!");
+		return;
+	}
+
+	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+	if (!req) {
+		deverr(dev, "Failed to allocate memory for control request");
+		usb_free_urb(urb);
+		return;
+	}
+
+	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+	req->bRequest = DM_WRITE_REG;
+	req->wValue = cpu_to_le16(value);
+	req->wIndex = cpu_to_le16(reg);
+	req->wLength = 0;
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, NULL, 0, dm_write_async_callback, req);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status < 0) {
+		deverr(dev, "Error submitting the control message: status=%d",
+		       status);
+		kfree(req);
+		usb_free_urb(urb);
+	}
+}
+
+static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
+{
+	int ret, i;
+
+	mutex_lock(&dev->phy_mutex);
+
+	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
+	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);
+
+	for (i = 0; i < DM_TIMEOUT; i++) {
+		u8 tmp;
+
+		udelay(1);
+		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
+		if (ret < 0)
+			goto out;
+
+		/* ready */
+		if ((tmp & 1) == 0)
+			break;
+	}
+
+	if (i == DM_TIMEOUT) {
+		deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom");
+		ret = -EIO;
+		goto out;
+	}
+
+	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
+	ret = dm_read(dev, DM_SHARED_DATA, 2, value);
+
+	devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d",
+	       phy, reg, *value, ret);
+
+ out:
+	mutex_unlock(&dev->phy_mutex);
+	return ret;
+}
+
+static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value)
+{
+	int ret, i;
+
+	mutex_lock(&dev->phy_mutex);
+
+	ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
+	if (ret < 0)
+		goto out;
+
+	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
+	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14);
+
+	for (i = 0; i < DM_TIMEOUT; i++) {
+		u8 tmp;
+
+		udelay(1);
+		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
+		if (ret < 0)
+			goto out;
+
+		/* ready */
+		if ((tmp & 1) == 0)
+			break;
+	}
+
+	if (i == DM_TIMEOUT) {
+		deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom");
+		ret = -EIO;
+		goto out;
+	}
+
+	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
+
+out:
+	mutex_unlock(&dev->phy_mutex);
+	return ret;
+}
+
+static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
+{
+	return dm_read_shared_word(dev, 0, offset, value);
+}
+
+
+
+static int dm9601_get_eeprom_len(struct net_device *dev)
+{
+	return DM_EEPROM_LEN;
+}
+
+static int dm9601_get_eeprom(struct net_device *net,
+			     struct ethtool_eeprom *eeprom, u8 * data)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u16 *ebuf = (u16 *) data;
+	int i;
+
+	/* access is 16bit */
+	if ((eeprom->offset % 2) || (eeprom->len % 2))
+		return -EINVAL;
+
+	for (i = 0; i < eeprom->len / 2; i++) {
+		if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i,
+					&ebuf[i]) < 0)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+	struct usbnet *dev = netdev_priv(netdev);
+
+	u16 res;
+
+	if (phy_id) {
+		devdbg(dev, "Only internal phy supported");
+		return 0;
+	}
+
+	dm_read_shared_word(dev, 1, loc, &res);
+
+	devdbg(dev,
+	       "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x",
+	       phy_id, loc, le16_to_cpu(res));
+
+	return le16_to_cpu(res);
+}
+
+static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
+			      int val)
+{
+	struct usbnet *dev = netdev_priv(netdev);
+	u16 res = cpu_to_le16(val);
+
+	if (phy_id) {
+		devdbg(dev, "Only internal phy supported");
+		return;
+	}
+
+	devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x",
+	       phy_id, loc, val);
+
+	dm_write_shared_word(dev, 1, loc, res);
+}
+
+static void dm9601_get_drvinfo(struct net_device *net,
+			       struct ethtool_drvinfo *info)
+{
+	/* Inherit standard device info */
+	usbnet_get_drvinfo(net, info);
+	info->eedump_len = DM_EEPROM_LEN;
+}
+
+static u32 dm9601_get_link(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	return mii_link_ok(&dev->mii);
+}
+
+static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static struct ethtool_ops dm9601_ethtool_ops = {
+	.get_drvinfo	= dm9601_get_drvinfo,
+	.get_link	= dm9601_get_link,
+	.get_msglevel	= usbnet_get_msglevel,
+	.set_msglevel	= usbnet_set_msglevel,
+	.get_eeprom_len	= dm9601_get_eeprom_len,
+	.get_eeprom	= dm9601_get_eeprom,
+	.get_settings	= usbnet_get_settings,
+	.set_settings	= usbnet_set_settings,
+	.nway_reset	= usbnet_nway_reset,
+};
+
+static void dm9601_set_multicast(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+	/* We use the 20 byte dev->data for our 8 byte filter buffer
+	 * to avoid allocating memory that is tricky to free later */
+	u8 *hashes = (u8 *) & dev->data;
+	u8 rx_ctl = 0x01;
+
+	memset(hashes, 0x00, DM_MCAST_SIZE);
+	hashes[DM_MCAST_SIZE - 1] |= 0x80;	/* broadcast address */
+
+	if (net->flags & IFF_PROMISC) {
+		rx_ctl |= 0x02;
+	} else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) {
+		rx_ctl |= 0x04;
+	} else if (net->mc_count) {
+		struct dev_mc_list *mc_list = net->mc_list;
+		int i;
+
+		for (i = 0; i < net->mc_count; i++) {
+			u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26;
+			hashes[crc >> 3] |= 1 << (crc & 0x7);
+		}
+	}
+
+	dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes);
+	dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
+}
+
+static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret)
+		goto out;
+
+	dev->net->do_ioctl = dm9601_ioctl;
+	dev->net->set_multicast_list = dm9601_set_multicast;
+	dev->net->ethtool_ops = &dm9601_ethtool_ops;
+	dev->net->hard_header_len += DM_TX_OVERHEAD;
+	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+	dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD;
+
+	dev->mii.dev = dev->net;
+	dev->mii.mdio_read = dm9601_mdio_read;
+	dev->mii.mdio_write = dm9601_mdio_write;
+	dev->mii.phy_id_mask = 0x1f;
+	dev->mii.reg_num_mask = 0x1f;
+
+	/* reset */
+	ret = dm_write_reg(dev, DM_NET_CTRL, 1);
+	udelay(20);
+
+	/* read MAC */
+	ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
+	if (ret < 0) {
+		printk(KERN_ERR "Error reading MAC address\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+
+	/* power up phy */
+	dm_write_reg(dev, DM_GPR_CTRL, 1);
+	dm_write_reg(dev, DM_GPR_DATA, 0);
+
+	/* receive broadcast packets */
+	dm9601_set_multicast(dev->net);
+
+	dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+			  ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+	mii_nway_restart(&dev->mii);
+
+out:
+	return ret;
+}
+
+static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	u8 status;
+	int len;
+
+	/* format:
+	   b0: rx status
+	   b1: packet length (incl crc) low
+	   b2: packet length (incl crc) high
+	   b3..n-4: packet data
+	   bn-3..bn: ethernet crc
+	 */
+
+	if (unlikely(skb->len < DM_RX_OVERHEAD)) {
+		dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
+		return 0;
+	}
+
+	status = skb->data[0];
+	len = (skb->data[1] | (skb->data[2] << 8)) - 4;
+
+	if (unlikely(status & 0xbf)) {
+		if (status & 0x01) dev->stats.rx_fifo_errors++;
+		if (status & 0x02) dev->stats.rx_crc_errors++;
+		if (status & 0x04) dev->stats.rx_frame_errors++;
+		if (status & 0x20) dev->stats.rx_missed_errors++;
+		if (status & 0x90) dev->stats.rx_length_errors++;
+		return 0;
+	}
+
+	skb_pull(skb, 3);
+	skb_trim(skb, len);
+
+	return 1;
+}
+
+static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+				       gfp_t flags)
+{
+	int len;
+
+	/* format:
+	   b0: packet length low
+	   b1: packet length high
+	   b3..n: packet data
+	*/
+
+	if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+		struct sk_buff *skb2;
+
+		skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+		dev_kfree_skb_any(skb);
+		skb = skb2;
+		if (!skb)
+			return NULL;
+	}
+
+	__skb_push(skb, DM_TX_OVERHEAD);
+
+	len = skb->len;
+	/* usbnet adds padding if length is a multiple of packet size
+	   if so, adjust length value in header */
+	if ((len % dev->maxpacket) == 0)
+		len++;
+
+	skb->data[0] = len;
+	skb->data[1] = len >> 8;
+
+	return skb;
+}
+
+static void dm9601_status(struct usbnet *dev, struct urb *urb)
+{
+	int link;
+	u8 *buf;
+
+	/* format:
+	   b0: net status
+	   b1: tx status 1
+	   b2: tx status 2
+	   b3: rx status
+	   b4: rx overflow
+	   b5: rx count
+	   b6: tx count
+	   b7: gpr
+	*/
+
+	if (urb->actual_length < 8)
+		return;
+
+	buf = urb->transfer_buffer;
+
+	link = !!(buf[0] & 0x40);
+	if (netif_carrier_ok(dev->net) != link) {
+		if (link) {
+			netif_carrier_on(dev->net);
+			usbnet_defer_kevent (dev, EVENT_LINK_RESET);
+		}
+		else
+			netif_carrier_off(dev->net);
+		devdbg(dev, "Link Status is: %d", link);
+	}
+}
+
+static int dm9601_link_reset(struct usbnet *dev)
+{
+	struct ethtool_cmd ecmd;
+
+	mii_check_media(&dev->mii, 1, 1);
+	mii_ethtool_gset(&dev->mii, &ecmd);
+
+	devdbg(dev, "link_reset() speed: %d duplex: %d",
+	       ecmd.speed, ecmd.duplex);
+
+	return 0;
+}
+
+static const struct driver_info dm9601_info = {
+	.description	= "Davicom DM9601 USB Ethernet",
+	.flags		= FLAG_ETHER,
+	.bind		= dm9601_bind,
+	.rx_fixup	= dm9601_rx_fixup,
+	.tx_fixup	= dm9601_tx_fixup,
+	.status		= dm9601_status,
+	.link_reset	= dm9601_link_reset,
+	.reset		= dm9601_link_reset,
+};
+
+static const struct usb_device_id products[] = {
+	{
+	 USB_DEVICE(0x07aa, 0x9601),	/* Corega FEther USB-TXC */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
+	{
+	 USB_DEVICE(0x0a46, 0x9601),	/* Davicom USB-100 */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
+	{
+	 USB_DEVICE(0x0a46, 0x6688),	/* ZT6688 USB NIC */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
+	{
+	 USB_DEVICE(0x0a46, 0x0268),	/* ShanTou ST268 USB NIC */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
+	{},			// END
+};
+
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver dm9601_driver = {
+	.name = "dm9601",
+	.id_table = products,
+	.probe = usbnet_probe,
+	.disconnect = usbnet_disconnect,
+	.suspend = usbnet_suspend,
+	.resume = usbnet_resume,
+};
+
+static int __init dm9601_init(void)
+{
+	return usb_register(&dm9601_driver);
+}
+
+static void __exit dm9601_exit(void)
+{
+	usb_deregister(&dm9601_driver);
+}
+
+module_init(dm9601_init);
+module_exit(dm9601_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index d257a8e..031cf5c 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -157,7 +157,7 @@
 		if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
 			skb->data = memmove(skb->head + (4 + 4*1),
 					     skb->data, skb->len);
-			skb->tail = skb->data + skb->len;
+			skb_set_tail_pointer(skb, skb->len);
 		}
 	} else {
 		struct sk_buff	*skb2;
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index de95268..a0cc05d 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -636,8 +636,6 @@
 
 		skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
 
-		skb->dev = net;
-
 		eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
 
 		skb_put(skb, pkt_len);
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index ccebfde..19bf8da 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -520,7 +520,7 @@
 			skb->data = memmove(skb->head
 						+ sizeof (struct nc_header),
 					    skb->data, skb->len);
-			skb->tail = skb->data + len;
+			skb_set_tail_pointer(skb, len);
 			goto encapsulate;
 		}
 	}
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index d48c024..a05fd97 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -316,6 +316,7 @@
 	return ret;
 }
 
+/* Returns 0 on success, error on failure */
 static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
 {
 	int i;
@@ -574,7 +575,6 @@
 		 */
 		if (pegasus->rx_pool[i] == NULL)
 			return;
-		pegasus->rx_pool[i]->dev = pegasus->net;
 		skb_reserve(pegasus->rx_pool[i], 2);
 	}
 }
@@ -847,10 +847,6 @@
 		 * d[0].NO_CARRIER kicks in only with failed TX.
 		 * ... so monitoring with MII may be safest.
 		 */
-		if (d[0] & NO_CARRIER)
-			netif_carrier_off(net);	
-		else
-			netif_carrier_on(net);
 
 		/* bytes 3-4 == rx_lostpkt, reg 2E/2F */
 		pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
@@ -883,7 +879,7 @@
 	netif_stop_queue(net);
 
 	((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
-	memcpy(pegasus->tx_buff + 2, skb->data, skb->len);
+	skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len);
 	usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb,
 			  usb_sndbulkpipe(pegasus->usb, 2),
 			  pegasus->tx_buff, count,
@@ -950,7 +946,7 @@
 	pegasus_t *pegasus = netdev_priv(net);
 	u16 tmp;
 
-	if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
+	if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
 		return;
 
 	if (tmp & BMSR_LSTATUS)
@@ -1408,8 +1404,10 @@
 	unlink_all_urbs(pegasus);
 	free_all_urbs(pegasus);
 	free_skb_pool(pegasus);
-	if (pegasus->rx_skb)
+	if (pegasus->rx_skb != NULL) {
 		dev_kfree_skb(pegasus->rx_skb);
+		pegasus->rx_skb = NULL;
+	}
 	free_netdev(pegasus->net);
 }
 
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 39a21c7..980e4aa 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -253,6 +253,7 @@
  * of that mess as possible.
  */
 #define OID_802_3_PERMANENT_ADDRESS	ccpu2(0x01010101)
+#define OID_GEN_MAXIMUM_FRAME_SIZE	ccpu2(0x00010106)
 #define OID_GEN_CURRENT_PACKET_FILTER	ccpu2(0x0001010e)
 
 /*
@@ -349,7 +350,7 @@
 			case RNDIS_MSG_INDICATE: {	/* fault */
 				// struct rndis_indicate *msg = (void *)buf;
 				dev_info(&info->control->dev,
-					 "rndis fault indication\n");
+					"rndis fault indication\n");
 				}
 				break;
 			case RNDIS_MSG_KEEPALIVE: {	/* ping */
@@ -387,6 +388,71 @@
 	return -ETIMEDOUT;
 }
 
+/*
+ * rndis_query:
+ *
+ * Performs a query for @oid along with 0 or more bytes of payload as
+ * specified by @in_len. If @reply_len is not set to -1 then the reply
+ * length is checked against this value, resulting in an error if it
+ * doesn't match.
+ *
+ * NOTE: Adding a payload exactly or greater than the size of the expected
+ * response payload is an evident requirement MSFT added for ActiveSync.
+ *
+ * The only exception is for OIDs that return a variably sized response,
+ * in which case no payload should be added.  This undocumented (and
+ * nonsensical!) issue was found by sniffing protocol requests from the
+ * ActiveSync 4.1 Windows driver.
+ */
+static int rndis_query(struct usbnet *dev, struct usb_interface *intf,
+		void *buf, u32 oid, u32 in_len,
+		void **reply, int *reply_len)
+{
+	int retval;
+	union {
+		void			*buf;
+		struct rndis_msg_hdr	*header;
+		struct rndis_query	*get;
+		struct rndis_query_c	*get_c;
+	} u;
+	u32 off, len;
+
+	u.buf = buf;
+
+	memset(u.get, 0, sizeof *u.get + in_len);
+	u.get->msg_type = RNDIS_MSG_QUERY;
+	u.get->msg_len = cpu_to_le32(sizeof *u.get + in_len);
+	u.get->oid = oid;
+	u.get->len = cpu_to_le32(in_len);
+	u.get->offset = ccpu2(20);
+
+	retval = rndis_command(dev, u.header);
+	if (unlikely(retval < 0)) {
+		dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) failed, %d\n",
+				oid, retval);
+		return retval;
+	}
+
+	off = le32_to_cpu(u.get_c->offset);
+	len = le32_to_cpu(u.get_c->len);
+	if (unlikely((8 + off + len) > CONTROL_BUFFER_SIZE))
+		goto response_error;
+
+	if (*reply_len != -1 && len != *reply_len)
+		goto response_error;
+
+	*reply = (unsigned char *) &u.get_c->request_id + off;
+	*reply_len = len;
+
+	return retval;
+
+response_error:
+	dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) "
+			"invalid response - off %d len %d\n",
+		oid, off, len);
+	return -EDOM;
+}
+
 static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int			retval;
@@ -403,6 +469,8 @@
 		struct rndis_set_c	*set_c;
 	} u;
 	u32			tmp;
+	int			reply_len;
+	unsigned char		*bp;
 
 	/* we can't rely on i/o from stack working, or stack allocation */
 	u.buf = kmalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
@@ -421,6 +489,12 @@
 	 * TX we'll stick to one Ethernet packet plus RNDIS framing.
 	 * For RX we handle drivers that zero-pad to end-of-packet.
 	 * Don't let userspace change these settings.
+	 *
+	 * NOTE: there still seems to be wierdness here, as if we need
+	 * to do some more things to make sure WinCE targets accept this.
+	 * They default to jumbograms of 8KB or 16KB, which is absurd
+	 * for such low data rates and which is also more than Linux
+	 * can usually expect to allocate for SKB data...
 	 */
 	net->hard_header_len += sizeof (struct rndis_data_hdr);
 	dev->hard_mtu = net->mtu + net->hard_header_len;
@@ -434,7 +508,7 @@
 	if (unlikely(retval < 0)) {
 		/* it might not even be an RNDIS device!! */
 		dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
- 		goto fail_and_release;
+		goto fail_and_release;
 	}
 	tmp = le32_to_cpu(u.init_c->max_transfer_size);
 	if (tmp < dev->hard_mtu) {
@@ -450,34 +524,15 @@
 		dev->hard_mtu, tmp, dev->rx_urb_size,
 		1 << le32_to_cpu(u.init_c->packet_alignment));
 
-	/* Get designated host ethernet address.
-	 *
-	 * Adding a payload exactly the same size as the expected response
-	 * payload is an evident requirement MSFT added for ActiveSync.
-	 * This undocumented (and nonsensical) issue was found by sniffing
-	 * protocol requests from the ActiveSync 4.1 Windows driver.
-	 */
-	memset(u.get, 0, sizeof *u.get + 48);
-	u.get->msg_type = RNDIS_MSG_QUERY;
-	u.get->msg_len = ccpu2(sizeof *u.get + 48);
-	u.get->oid = OID_802_3_PERMANENT_ADDRESS;
-	u.get->len = ccpu2(48);
-	u.get->offset = ccpu2(20);
-
-	retval = rndis_command(dev, u.header);
-	if (unlikely(retval < 0)) {
+	/* Get designated host ethernet address */
+	reply_len = ETH_ALEN;
+	retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS,
+			48, (void **) &bp, &reply_len);
+	if (unlikely(retval< 0)) {
 		dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
 		goto fail_and_release;
 	}
-	tmp = le32_to_cpu(u.get_c->offset);
-	if (unlikely((tmp + 8) > (CONTROL_BUFFER_SIZE - ETH_ALEN)
-			|| u.get_c->len != ccpu2(ETH_ALEN))) {
-		dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n",
-			tmp, le32_to_cpu(u.get_c->len));
-		retval = -EDOM;
-		goto fail_and_release;
-	}
-	memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN);
+	memcpy(net->dev_addr, bp, ETH_ALEN);
 
 	/* set a nonzero filter to enable data transfers */
 	memset(u.set, 0, sizeof *u.set);
@@ -502,6 +557,7 @@
 fail_and_release:
 	usb_set_intfdata(info->data, NULL);
 	usb_driver_release_interface(driver_of(intf), info->data);
+	info->data = NULL;
 fail:
 	kfree(u.buf);
 	return retval;
@@ -588,7 +644,7 @@
 		if (likely((sizeof *hdr) <= room)) {
 			skb->data = memmove(skb->head + sizeof *hdr,
 					    skb->data, len);
-			skb->tail = skb->data + len;
+			skb_set_tail_pointer(skb, len);
 			goto fill;
 		}
 	}
@@ -618,7 +674,7 @@
 
 static const struct driver_info	rndis_info = {
 	.description =	"RNDIS device",
-	.flags =	FLAG_ETHER | FLAG_FRAMING_RN,
+	.flags =	FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT,
 	.bind =		rndis_bind,
 	.unbind =	rndis_unbind,
 	.status =	rndis_status,
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index ea153dc..fa598f0 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -646,7 +646,6 @@
 		if (!skb) {
 			return;
 		}
-		skb->dev = dev->netdev;
 		skb_reserve(skb, 2);
 		dev->rx_skb_pool[i] = skb;
 	}
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 43ba61a..f9cd42d 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -147,7 +147,7 @@
 		if (tmp < 0)
 			return tmp;
 	}
-	
+
 	dev->in = usb_rcvbulkpipe (dev->udev,
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 	dev->out = usb_sndbulkpipe (dev->udev,
@@ -203,7 +203,6 @@
 {
 	int	status;
 
-	skb->dev = dev->net;
 	skb->protocol = eth_type_trans (skb, dev->net);
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += skb->len;
@@ -327,7 +326,7 @@
 	if (netif_running (dev->net)
 			&& netif_device_present (dev->net)
 			&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
-		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ 
+		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
 		case -EPIPE:
 			usbnet_defer_kevent (dev, EVENT_RX_HALT);
 			break;
@@ -443,7 +442,7 @@
 	    case -EOVERFLOW:
 		dev->stats.rx_over_errors++;
 		// FALLTHROUGH
-	    
+
 	    default:
 		entry->state = rx_cleanup;
 		dev->stats.rx_errors++;
@@ -560,7 +559,7 @@
 
 	if (netif_msg_ifdown (dev))
 		devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
-			dev->stats.rx_packets, dev->stats.tx_packets, 
+			dev->stats.rx_packets, dev->stats.tx_packets,
 			dev->stats.rx_errors, dev->stats.tx_errors
 			);
 
@@ -578,7 +577,7 @@
 			devdbg (dev, "waited for %d urb completions", temp);
 	}
 	dev->wait = NULL;
-	remove_wait_queue (&unlink_wakeup, &wait); 
+	remove_wait_queue (&unlink_wakeup, &wait);
 
 	usb_kill_urb(dev->interrupt);
 
@@ -735,8 +734,7 @@
 {
 	struct usbnet *dev = netdev_priv(net);
 
-	/* REVISIT don't always return "usbnet" */
-	strncpy (info->driver, driver_name, sizeof info->driver);
+	strncpy (info->driver, dev->driver_name, sizeof info->driver);
 	strncpy (info->version, DRIVER_VERSION, sizeof info->version);
 	strncpy (info->fw_version, dev->driver_info->description,
 		sizeof info->fw_version);
@@ -834,7 +832,7 @@
 	}
 
 	if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
-		struct driver_info 	*info = dev->driver_info;
+		struct driver_info	*info = dev->driver_info;
 		int			retval = 0;
 
 		clear_bit (EVENT_LINK_RESET, &dev->flags);
@@ -1066,7 +1064,7 @@
  * USB Device Driver support
  *
  *-------------------------------------------------------------------------*/
- 
+
 // precondition: never called in_interrupt
 
 void usbnet_disconnect (struct usb_interface *intf)
@@ -1087,7 +1085,7 @@
 			intf->dev.driver->name,
 			xdev->bus->bus_name, xdev->devpath,
 			dev->driver_info->description);
-	
+
 	net = dev->net;
 	unregister_netdev (net);
 
@@ -1111,15 +1109,17 @@
 usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 {
 	struct usbnet			*dev;
-	struct net_device 		*net;
+	struct net_device		*net;
 	struct usb_host_interface	*interface;
 	struct driver_info		*info;
 	struct usb_device		*xdev;
 	int				status;
+	const char			*name;
 
+	name = udev->dev.driver->name;
 	info = (struct driver_info *) prod->driver_info;
 	if (!info) {
-		dev_dbg (&udev->dev, "blacklisted by %s\n", driver_name);
+		dev_dbg (&udev->dev, "blacklisted by %s\n", name);
 		return -ENODEV;
 	}
 	xdev = interface_to_usbdev (udev);
@@ -1139,6 +1139,7 @@
 	dev = netdev_priv(net);
 	dev->udev = xdev;
 	dev->driver_info = info;
+	dev->driver_name = name;
 	dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
 				| NETIF_MSG_PROBE | NETIF_MSG_LINK);
 	skb_queue_head_init (&dev->rxq);
@@ -1181,6 +1182,9 @@
 	// NOTE net->name still not usable ...
 	if (info->bind) {
 		status = info->bind (dev, udev);
+		if (status < 0)
+			goto out1;
+
 		// heuristic:  "usb%d" for links we know are two-host,
 		// else "eth%d" when there's reasonable doubt.  userspace
 		// can rename the link if it knows better.
@@ -1207,12 +1211,12 @@
 	if (status == 0 && dev->status)
 		status = init_status (dev, udev);
 	if (status < 0)
-		goto out1;
+		goto out3;
 
 	if (!dev->rx_urb_size)
 		dev->rx_urb_size = dev->hard_mtu;
 	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
-	
+
 	SET_NETDEV_DEV(net, &udev->dev);
 	status = register_netdev (net);
 	if (status)
@@ -1255,7 +1259,7 @@
 int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
-	
+
 	/* accelerate emptying of the rx and queues, to avoid
 	 * having everything error out.
 	 */
@@ -1286,7 +1290,7 @@
 			< sizeof (struct skb_data));
 
 	random_ether_addr(node_id);
- 	return 0;
+	return 0;
 }
 module_init(usbnet_init);
 
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
index 07c70ab..cbb53e0 100644
--- a/drivers/usb/net/usbnet.h
+++ b/drivers/usb/net/usbnet.h
@@ -29,6 +29,7 @@
 	/* housekeeping */
 	struct usb_device	*udev;
 	struct driver_info	*driver_info;
+	const char		*driver_name;
 	wait_queue_head_t	*wait;
 	struct mutex		phy_mutex;
 
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 2f4d303..ba5d1dc 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -423,11 +423,11 @@
 	  module will be called mct_u232.
 
 config USB_SERIAL_MOS7720
-	tristate "USB Moschip 7720 Single Port Serial Driver"
+	tristate "USB Moschip 7720 Serial Driver"
 	depends on USB_SERIAL
 	---help---
-	  Say Y here if you want to use a USB Serial single port adapter from
-	  Moschip Semiconductor Tech.
+	  Say Y here if you want to use USB Serial single and double
+	  port adapters from Moschip Semiconductor Tech.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called mos7720.
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 11dad42..b675735 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -209,6 +209,7 @@
 	int count, result;
 	struct aircable_private *priv = usb_get_serial_port_data(port);
 	unsigned char* buf;
+	u16 *dbuf;
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	if (port->write_urb_busy)
 		return;
@@ -226,8 +227,8 @@
 
 	buf[0] = TX_HEADER_0;
 	buf[1] = TX_HEADER_1;
-	buf[2] = (unsigned char)count;
-	buf[3] = (unsigned char)(count >> 8);
+	dbuf = (u16 *)&buf[2];
+	*dbuf = cpu_to_le16((u16)count);
 	serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
 
 	memcpy(port->write_urb->transfer_buffer, buf,
@@ -434,7 +435,7 @@
 			    __FUNCTION__, urb->status);
 			port->write_urb->transfer_buffer_length = 1;
 			port->write_urb->dev = port->serial->dev;
-			result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+			result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 			if (result)
 				dev_err(&urb->dev->dev,
 					"%s - failed resubmitting write urb, error %d\n",
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 0af42e3..39a4983 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -18,11 +18,6 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
-	{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
-	{ USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */
-	{ USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */
-	{ USB_DEVICE(0x1410, 0x1430) },	/* Novatel Merlin XU870 HSDPA/3G */
-	{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
 	{ USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
 	{ },
 };
@@ -44,8 +39,43 @@
 	int outstanding_urbs;
 	int throttled;
 	struct urb *read_urbp[NUM_READ_URBS];
+
+	/* Settings for the port */
+	int rts_state;	/* Handshaking pins (outputs) */
+	int dtr_state;
+	int cts_state;	/* Handshaking pins (inputs) */
+	int dsr_state;
+	int dcd_state;
+	int ri_state;
 };
 
+static int airprime_send_setup(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct airprime_private *priv;
+
+	dbg("%s", __FUNCTION__);
+
+	if (port->number != 0)
+		return 0;
+
+	priv = usb_get_serial_port_data(port);
+
+	if (port->tty) {
+		int val = 0;
+		if (priv->dtr_state)
+			val |= 0x01;
+		if (priv->rts_state)
+			val |= 0x02;
+
+		return usb_control_msg(serial->dev,
+				usb_rcvctrlpipe(serial->dev, 0),
+				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+	}
+
+	return 0;
+}
+
 static void airprime_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
@@ -58,11 +88,6 @@
 	if (urb->status) {
 		dbg("%s - nonzero read bulk status received: %d",
 		    __FUNCTION__, urb->status);
-		/* something happened, so free up the memory for this urb */
-		if (urb->transfer_buffer) {
-			kfree (urb->transfer_buffer);
-			urb->transfer_buffer = NULL;
-		}
 		return;
 	}
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -123,6 +148,10 @@
 		usb_set_serial_port_data(port, priv);
 	}
 
+	/* Set some sane defaults */
+	priv->rts_state = 1;
+	priv->dtr_state = 1;
+
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
@@ -146,6 +175,8 @@
 				  airprime_read_bulk_callback, port);
 		result = usb_submit_urb(urb, GFP_KERNEL);
 		if (result) {
+			usb_free_urb(urb);
+			kfree(buffer);
 			dev_err(&port->dev,
 				"%s - failed submitting read urb %d for port %d, error %d\n",
 				__FUNCTION__, i, port->number, result);
@@ -154,33 +185,21 @@
 		/* remember this urb so we can kill it when the port is closed */
 		priv->read_urbp[i] = urb;
 	}
+
+	airprime_send_setup(port);
+
 	goto out;
 
  errout:
 	/* some error happened, cancel any submitted urbs and clean up anything that
 	   got allocated successfully */
 
-	for ( ; i >= 0; --i) {
+	while (i-- != 0) {
 		urb = priv->read_urbp[i];
-		if (urb) {
-			/* This urb was submitted successfully. So we have to
-			   cancel it.
-			   Unlinking the urb will invoke read_bulk_callback()
-			   with an error status, so its transfer buffer will
-			   be freed there */
-			if (usb_unlink_urb (urb) != -EINPROGRESS) {
-				/* comments in drivers/usb/core/urb.c say this
-				   can only happen if the urb was never submitted,
-				   or has completed already.
-				   Either way we may have to free the transfer
-				   buffer here. */
-				if (urb->transfer_buffer) {
-					kfree (urb->transfer_buffer);
-					urb->transfer_buffer = NULL;
-				}
-			}
-			usb_free_urb (urb);
-		}
+		buffer = urb->transfer_buffer;
+		usb_kill_urb (urb);
+		usb_free_urb (urb);
+		kfree (buffer);
 	}
 
  out:
@@ -194,10 +213,14 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	/* killing the urb will invoke read_bulk_callback() with an error status,
-	   so the transfer buffer will be freed there */
+	priv->rts_state = 0;
+	priv->dtr_state = 0;
+
+	airprime_send_setup(port);
+
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		usb_kill_urb (priv->read_urbp[i]);
+		kfree (priv->read_urbp[i]->transfer_buffer);
 		usb_free_urb (priv->read_urbp[i]);
 	}
 
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index edd6857..ea2175b 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -341,7 +341,7 @@
 
 	result = usb_serial_generic_open(port, filp);
 	if (result)
-		return result;
+		goto err_out;
 
 	/* open */
 	ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf);
@@ -372,6 +372,7 @@
 	if (port->tty)
 		ark3116_set_termios(port, &tmp_termios);
 
+err_out:
 	kfree(buf);
 
 	return result;
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 3ec2487..e831cb7 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -58,17 +58,22 @@
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
+	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
 	{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
 	{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+	{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
 	{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
 	{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
+	{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
+	{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
 	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
 	{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
 	{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ } /* Terminating Entry */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 4695952..95a1805 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -315,6 +315,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
@@ -341,6 +342,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USBX_707_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
@@ -420,6 +422,14 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
 	/*
 	 * These will probably use user-space drivers.  Uncomment them if
 	 * you need them or use the user-specified vendor/product module
@@ -459,6 +469,7 @@
 	{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
 	{ USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
+	{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
@@ -513,6 +524,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
 	{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
+	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -532,6 +544,7 @@
 	[FT8U232AM] = "FT8U232AM",
 	[FT232BM] = "FT232BM",
 	[FT2232C] = "FT2232C",
+	[FT232RL] = "FT232RL",
 };
 
 
@@ -587,6 +600,8 @@
 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_sio_port_probe	(struct usb_serial_port *port);
+static int  ftdi_sio_port_remove	(struct usb_serial_port *port);
 static int  ftdi_open			(struct usb_serial_port *port, struct file *filp);
 static void ftdi_close			(struct usb_serial_port *port, struct file *filp);
 static int  ftdi_write			(struct usb_serial_port *port, const unsigned char *buf, int count);
@@ -621,6 +636,8 @@
 	.num_bulk_out =		1,
 	.num_ports =		1,
 	.probe =		ftdi_sio_probe,
+	.port_probe =		ftdi_sio_port_probe,
+	.port_remove =		ftdi_sio_port_remove,
 	.open =			ftdi_open,
 	.close =		ftdi_close,
 	.throttle =		ftdi_throttle,
@@ -863,6 +880,7 @@
 		break;
 	case FT232BM: /* FT232BM chip */
 	case FT2232C: /* FT2232C chip */
+	case FT232RL:
 		if (baud <= 3000000) {
 			div_value = ftdi_232bm_baud_to_divisor(baud);
 		} else {
@@ -1005,9 +1023,12 @@
 		/* (It might be a BM because of the iSerialNumber bug,
 		 * but it will still work as an AM device.) */
 		priv->chip_type = FT8U232AM;
-	} else {
+	} else if (version < 0x600) {
 		/* Assume its an FT232BM (or FT245BM) */
 		priv->chip_type = FT232BM;
+	} else {
+		/* Assume its an FT232R  */
+		priv->chip_type = FT232RL;
 	}
 	info("Detected %s", ftdi_chip_name[priv->chip_type]);
 }
@@ -1023,11 +1044,10 @@
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct usb_device *udev;
+	struct usb_device *udev = port->serial->dev;
 	unsigned short latency = 0;
 	int rv = 0;
 
-	udev = to_usb_device(dev);
 
 	dbg("%s",__FUNCTION__);
 
@@ -1051,13 +1071,11 @@
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct usb_device *udev;
+	struct usb_device *udev = port->serial->dev;
 	char buf[1];
 	int v = simple_strtoul(valbuf, NULL, 10);
 	int rv = 0;
 
-	udev = to_usb_device(dev);
-
 	dbg("%s: setting latency timer = %i", __FUNCTION__, v);
 
 	rv = usb_control_msg(udev,
@@ -1082,13 +1100,11 @@
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct usb_device *udev;
+	struct usb_device *udev = port->serial->dev;
 	char buf[1];
 	int v = simple_strtoul(valbuf, NULL, 10);
 	int rv = 0;
 
-	udev = to_usb_device(dev);
-
 	dbg("%s: setting event char = %i", __FUNCTION__, v);
 
 	rv = usb_control_msg(udev,
@@ -1109,46 +1125,38 @@
 static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
 static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
 
-static int create_sysfs_attrs(struct usb_serial *serial)
+static int create_sysfs_attrs(struct usb_serial_port *port)
 {
-	struct ftdi_private *priv;
-	struct usb_device *udev;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	int retval = 0;
 
 	dbg("%s",__FUNCTION__);
 
-	priv = usb_get_serial_port_data(serial->port[0]);
-	udev = serial->dev;
-
 	/* XXX I've no idea if the original SIO supports the event_char
 	 * sysfs parameter, so I'm playing it safe.  */
 	if (priv->chip_type != SIO) {
 		dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
-		retval = device_create_file(&udev->dev, &dev_attr_event_char);
+		retval = device_create_file(&port->dev, &dev_attr_event_char);
 		if ((!retval) &&
 		    (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
-			retval = device_create_file(&udev->dev,
+			retval = device_create_file(&port->dev,
 						    &dev_attr_latency_timer);
 		}
 	}
 	return retval;
 }
 
-static void remove_sysfs_attrs(struct usb_serial *serial)
+static void remove_sysfs_attrs(struct usb_serial_port *port)
 {
-	struct ftdi_private *priv;
-	struct usb_device *udev;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
 	dbg("%s",__FUNCTION__);
 
-	priv = usb_get_serial_port_data(serial->port[0]);
-	udev = serial->dev;
-
 	/* XXX see create_sysfs_attrs */
 	if (priv->chip_type != SIO) {
-		device_remove_file(&udev->dev, &dev_attr_event_char);
+		device_remove_file(&port->dev, &dev_attr_event_char);
 		if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
-			device_remove_file(&udev->dev, &dev_attr_latency_timer);
+			device_remove_file(&port->dev, &dev_attr_latency_timer);
 		}
 	}
 
@@ -1168,13 +1176,9 @@
 	return (0);
 }
 
-/* attach subroutine */
-static int ftdi_sio_attach (struct usb_serial *serial)
+static int ftdi_sio_port_probe(struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = serial->port[0];
 	struct ftdi_private *priv;
-	struct ftdi_sio_quirk *quirk;
-	int retval;
 
 	dbg("%s",__FUNCTION__);
 
@@ -1214,19 +1218,21 @@
 	kfree(port->bulk_out_buffer);
 	port->bulk_out_buffer = NULL;
 
-	usb_set_serial_port_data(serial->port[0], priv);
+	usb_set_serial_port_data(port, priv);
 
-	ftdi_determine_type (serial->port[0]);
-	retval = create_sysfs_attrs(serial);
-	if (retval)
-		dev_err(&serial->dev->dev, "Error creating sysfs files, "
-			"continuing\n");
+	ftdi_determine_type (port);
+	create_sysfs_attrs(port);
+	return 0;
+}
 
+/* attach subroutine */
+static int ftdi_sio_attach (struct usb_serial *serial)
+{
 	/* Check for device requiring special set up. */
-	quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
-	if (quirk && quirk->setup) {
+	struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
+
+	if (quirk && quirk->setup)
 		quirk->setup(serial);
-	}
 
 	return 0;
 } /* ftdi_sio_attach */
@@ -1270,17 +1276,18 @@
  *      calls __serial_close for each open of the port
  *      shutdown is called then (ie ftdi_shutdown)
  */
-
-
 static void ftdi_shutdown (struct usb_serial *serial)
-{ /* ftdi_shutdown */
+{
+	dbg("%s", __FUNCTION__);
+}
 
-	struct usb_serial_port *port = serial->port[0];
+static int ftdi_sio_port_remove(struct usb_serial_port *port)
+{
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
 	dbg("%s", __FUNCTION__);
 
-	remove_sysfs_attrs(serial);
+	remove_sysfs_attrs(port);
 
 	/* all open ports are closed at this point
          *    (by usbserial.c:__serial_close, which calls ftdi_close)
@@ -1290,8 +1297,9 @@
 		usb_set_serial_port_data(port, NULL);
 		kfree(priv);
 	}
-} /* ftdi_shutdown */
 
+	return 0;
+}
 
 static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_open */
@@ -1426,6 +1434,7 @@
 		dbg("%s - write limit hit\n", __FUNCTION__);
 		return 0;
 	}
+	priv->tx_outstanding_urbs++;
 	spin_unlock_irqrestore(&priv->tx_lock, flags);
 
 	data_offset = priv->write_offset;
@@ -1443,14 +1452,15 @@
 	buffer = kmalloc (transfer_size, GFP_ATOMIC);
 	if (!buffer) {
 		err("%s ran out of kernel memory for urb ...", __FUNCTION__);
-		return -ENOMEM;
+		count = -ENOMEM;
+		goto error_no_buffer;
 	}
 
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		err("%s - no more free urbs", __FUNCTION__);
-		kfree (buffer);
-		return -ENOMEM;
+		count = -ENOMEM;
+		goto error_no_urb;
 	}
 
 	/* Copy data */
@@ -1492,10 +1502,9 @@
 	if (status) {
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
 		count = status;
-		kfree (buffer);
+		goto error;
 	} else {
 		spin_lock_irqsave(&priv->tx_lock, flags);
-		++priv->tx_outstanding_urbs;
 		priv->tx_outstanding_bytes += count;
 		priv->tx_bytes += count;
 		spin_unlock_irqrestore(&priv->tx_lock, flags);
@@ -1503,10 +1512,19 @@
 
 	/* we are done with this urb, so let the host driver
 	 * really free it when it is finished with it */
-	usb_free_urb (urb);
+	usb_free_urb(urb);
 
 	dbg("%s write returning: %d", __FUNCTION__, count);
 	return count;
+error:
+	usb_free_urb(urb);
+error_no_urb:
+	kfree (buffer);
+error_no_buffer:
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	priv->tx_outstanding_urbs--;
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+	return count;
 } /* ftdi_write */
 
 
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 7eff1c0..77ad0a0 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -27,9 +27,11 @@
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
+#define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
+#define FTDI_USBX_707_PID 0xF857	/* ADSTech IR Blaster USBX-707 */
 
 
 /* www.canusb.com Lawicel CANUSB device */
@@ -339,6 +341,12 @@
 #define FTDI_SUUNTO_SPORTS_PID	0xF680	/* Suunto Sports instrument */
 
 /*
+ * TTi (Thurlby Thandar Instruments)
+ */
+#define TTI_VID			0x103E	/* Vendor Id */
+#define TTI_QL355P_PID		0x03E8	/* TTi QL355P power supply */
+
+/*
  * Definitions for B&B Electronics products.
  */
 #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */
@@ -491,6 +499,25 @@
 #define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
 #define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
 
+/*
+ * Telldus Technologies
+ */
+#define TELLDUS_VID			0x1781	/* Vendor ID */
+#define TELLDUS_TELLSTICK_PID		0x0C30	/* RF control dongle 433 MHz using FT232RL */
+
+/*
+ * IBS elektronik product ids
+ * Submitted by Thomas Schleusener
+ */
+#define FTDI_IBS_US485_PID	0xff38  /* IBS US485 (USB<-->RS422/485 interface) */
+#define FTDI_IBS_PICPRO_PID	0xff39  /* IBS PIC-Programmer */
+#define FTDI_IBS_PCMCIA_PID	0xff3a  /* IBS Card reader for PCMCIA SRAM-cards */
+#define FTDI_IBS_PK1_PID	0xff3b  /* IBS PK1 - Particel counter */
+#define FTDI_IBS_RS232MON_PID	0xff3c  /* IBS RS232 - Monitor */
+#define FTDI_IBS_APP70_PID	0xff3d  /* APP 70 (dust monitoring system) */
+#define FTDI_IBS_PEDO_PID	0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
+#define FTDI_IBS_PROD_PID	0xff3f  /* future device */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
@@ -614,6 +641,7 @@
 	FT8U232AM = 2,
 	FT232BM = 3,
 	FT2232C = 4,
+	FT232RL = 5,
 } ftdi_chip_type_t;
 
 typedef enum {
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 601e064..4f8282a 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -20,13 +20,14 @@
 #include <linux/usb/serial.h>
 #include <asm/uaccess.h>
 
-static int generic_probe(struct usb_interface *interface,
-			 const struct usb_device_id *id);
-
 
 static int debug;
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
+
+static int generic_probe(struct usb_interface *interface,
+			 const struct usb_device_id *id);
+
 static __u16 vendor  = 0x05f9;
 static __u16 product = 0xffff;
 
@@ -66,6 +67,8 @@
 	.num_bulk_out =		NUM_DONT_CARE,
 	.num_ports =		1,
 	.shutdown =		usb_serial_generic_shutdown,
+	.throttle =		usb_serial_generic_throttle,
+	.unthrottle =		usb_serial_generic_unthrottle,
 };
 
 static int generic_probe(struct usb_interface *interface,
@@ -115,6 +118,7 @@
 {
 	struct usb_serial *serial = port->serial;
 	int result = 0;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -124,7 +128,13 @@
 	if (port->tty)
 		port->tty->low_latency = 1;
 
-	/* if we have a bulk interrupt, start reading from it */
+	/* clear the throttle flags */
+	spin_lock_irqsave(&port->lock, flags);
+	port->throttled = 0;
+	port->throttle_req = 0;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	/* if we have a bulk endpoint, start reading from it */
 	if (serial->num_bulk_in) {
 		/* Start reading from the device */
 		usb_fill_bulk_urb (port->read_urb, serial->dev,
@@ -253,31 +263,22 @@
 	return (chars);
 }
 
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = port->serial;
-	struct tty_struct *tty;
-	unsigned char *data = urb->transfer_buffer;
+	struct urb *urb = port->read_urb;
+	struct tty_struct *tty = port->tty;
 	int result;
 
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-
-	tty = port->tty;
+	/* Push data to tty */
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
-		tty_insert_flip_string(tty, data, urb->actual_length);
-	  	tty_flip_buffer_push(tty);
+		tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
+	  	tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
 	}
 
-	/* Continue trying to always read  */
+	/* Continue reading from device */
 	usb_fill_bulk_urb (port->read_urb, serial->dev,
 			   usb_rcvbulkpipe (serial->dev,
 				   	    port->bulk_in_endpointAddress),
@@ -290,6 +291,40 @@
 	if (result)
 		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
 }
+
+void usb_serial_generic_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	int is_throttled;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (urb->status) {
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+		return;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+
+	/* Throttle the device if requested by tty */
+	if (urb->actual_length) {
+		spin_lock_irqsave(&port->lock, flags);
+		is_throttled = port->throttled = port->throttle_req;
+		spin_unlock_irqrestore(&port->lock, flags);
+		if (is_throttled) {
+			/* Let the received data linger in the read URB;
+			 * usb_serial_generic_unthrottle() will pick it
+			 * up later. */
+			dbg("%s - throttling device", __FUNCTION__);
+			return;
+		}
+	}
+
+	/* Handle data and continue reading from device */
+	flush_and_resubmit_read_urb(port);
+}
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 void usb_serial_generic_write_bulk_callback (struct urb *urb)
@@ -308,6 +343,38 @@
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 
+void usb_serial_generic_throttle (struct usb_serial_port *port)
+{
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* Set the throttle request flag. It will be picked up
+	 * by usb_serial_generic_read_bulk_callback(). */
+	spin_lock_irqsave(&port->lock, flags);
+	port->throttle_req = 1;
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+{
+	int was_throttled;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* Clear the throttle flags */
+	spin_lock_irqsave(&port->lock, flags);
+	was_throttled = port->throttled;
+	port->throttled = port->throttle_req = 0;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (was_throttled) {
+		/* Handle pending data and resume reading from device */
+		flush_and_resubmit_read_urb(port);
+	}
+}
+
 void usb_serial_generic_shutdown (struct usb_serial *serial)
 {
 	int i;
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 6a26a2e..18f74ac 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -111,7 +111,7 @@
 
 	struct TxFifo		txfifo;			/* transmit fifo -- size will be maxTxCredits */
 	struct urb		*write_urb;		/* write URB for this port */
-	char			write_in_progress;	/* TRUE while a write URB is outstanding */
+	bool			write_in_progress;	/* 'true' while a write URB is outstanding */
 	spinlock_t		ep_lock;
 
 	__u8			shadowLCR;		/* last LCR value received */
@@ -123,11 +123,11 @@
 	__u8			validDataMask;
 	__u32			baudRate;
 
-	char			open;
-	char			openPending;
-	char			commandPending;
-	char			closePending;
-	char			chaseResponsePending;
+	bool			open;
+	bool			openPending;
+	bool			commandPending;
+	bool			closePending;
+	bool			chaseResponsePending;
 
 	wait_queue_head_t	wait_chase;		/* for handling sleeping while waiting for chase to finish */
 	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */
@@ -156,7 +156,7 @@
 	__u8			bulk_in_endpoint;		/* the bulk in endpoint handle */
 	unsigned char *		bulk_in_buffer;			/* the buffer we use for the bulk in endpoint */
 	struct urb *		read_urb;			/* our bulk read urb */
-	int			read_in_progress;
+	bool			read_in_progress;
 	spinlock_t		es_lock;
 
 	__u8			bulk_out_endpoint;		/* the bulk out endpoint handle */
@@ -212,7 +212,7 @@
 
 static int low_latency = 1;	/* tty low latency flag, on by default */
 
-static int CmdUrbs = 0;		/* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs;		/* Number of outstanding Command Write Urbs */
 
 
 /* local function prototypes */
@@ -631,14 +631,14 @@
 				if (edge_serial->rxBytesAvail > 0 &&
 				    !edge_serial->read_in_progress) {
 					dbg("%s - posting a read", __FUNCTION__);
-					edge_serial->read_in_progress = TRUE;
+					edge_serial->read_in_progress = true;
 
 					/* we have pending bytes on the bulk in pipe, send a request */
 					edge_serial->read_urb->dev = edge_serial->serial->dev;
 					result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
 					if (result) {
 						dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result);
-						edge_serial->read_in_progress = FALSE;
+						edge_serial->read_in_progress = false;
 					}
 				}
 				spin_unlock(&edge_serial->es_lock);
@@ -695,13 +695,13 @@
 
 	if (urb->status) {
 		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-		edge_serial->read_in_progress = FALSE;
+		edge_serial->read_in_progress = false;
 		return;
 	}
 
 	if (urb->actual_length == 0) {
 		dbg("%s - read bulk callback with no data", __FUNCTION__);
-		edge_serial->read_in_progress = FALSE;
+		edge_serial->read_in_progress = false;
 		return;
 	}
 
@@ -725,10 +725,10 @@
 		status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
 		if (status) {
 			dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status);
-			edge_serial->read_in_progress = FALSE;
+			edge_serial->read_in_progress = false;
 		}
 	} else {
-		edge_serial->read_in_progress = FALSE;
+		edge_serial->read_in_progress = false;
 	}
 
 	spin_unlock(&edge_serial->es_lock);
@@ -759,7 +759,7 @@
 	}
 
 	// Release the Write URB
-	edge_port->write_in_progress = FALSE;
+	edge_port->write_in_progress = false;
 
 	// Check if more data needs to be sent
 	send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port);
@@ -779,8 +779,8 @@
 
 	dbg("%s", __FUNCTION__);
 
-	CmdUrbs--;
-	dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, CmdUrbs);
+	atomic_dec(&CmdUrbs);
+	dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
 
 
 	/* clean up the transfer buffer */
@@ -802,7 +802,7 @@
 		tty_wakeup(tty);
 
 	/* we have completed the command */
-	edge_port->commandPending = FALSE;
+	edge_port->commandPending = false;
 	wake_up(&edge_port->wait_command);
 }
 
@@ -868,7 +868,7 @@
 				  port0->bulk_in_buffer,
 				  edge_serial->read_urb->transfer_buffer_length,
 				  edge_bulk_in_callback, edge_serial);
-		edge_serial->read_in_progress = FALSE;
+		edge_serial->read_in_progress = false;
 
 		/* start interrupt read for this edgeport
 		 * this interrupt will continue as long as the edgeport is connected */
@@ -890,26 +890,26 @@
 	/* initialize our port settings */
 	edge_port->txCredits            = 0;			/* Can't send any data yet */
 	edge_port->shadowMCR            = MCR_MASTER_IE;	/* Must always set this bit to enable ints! */
-	edge_port->chaseResponsePending = FALSE;
+	edge_port->chaseResponsePending = false;
 
 	/* send a open port command */
-	edge_port->openPending = TRUE;
-	edge_port->open        = FALSE;
+	edge_port->openPending = true;
+	edge_port->open        = false;
 	response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
 
 	if (response < 0) {
 		dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__);
-		edge_port->openPending = FALSE;
+		edge_port->openPending = false;
 		return -ENODEV;
 	}
 
 	/* now wait for the port to be completely opened */
-	wait_event_timeout(edge_port->wait_open, (edge_port->openPending != TRUE), OPEN_TIMEOUT);
+	wait_event_timeout(edge_port->wait_open, !edge_port->openPending, OPEN_TIMEOUT);
 
-	if (edge_port->open == FALSE) {
+	if (!edge_port->open) {
 		/* open timed out */
 		dbg("%s - open timedout", __FUNCTION__);
-		edge_port->openPending = FALSE;
+		edge_port->openPending = false;
 		return -ENODEV;
 	}
 
@@ -928,7 +928,7 @@
 
 	/* Allocate a URB for the write */
 	edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
-	edge_port->write_in_progress = FALSE;
+	edge_port->write_in_progress = false;
 
 	if (!edge_port->write_urb) {
 		dbg("%s - no memory", __FUNCTION__);
@@ -966,7 +966,7 @@
 		lastCredits = edge_port->txCredits;
 
 		// Did we get our Chase response
-		if (edge_port->chaseResponsePending == FALSE) {
+		if (!edge_port->chaseResponsePending) {
 			dbg("%s - Got Chase Response", __FUNCTION__);
 
 			// did we get all of our credit back?
@@ -985,7 +985,7 @@
 			// No activity.. count down.
 			loop--;
 			if (loop == 0) {
-				edge_port->chaseResponsePending = FALSE;
+				edge_port->chaseResponsePending = false;
 				dbg("%s - Chase TIMEOUT", __FUNCTION__);
 				return;
 			}
@@ -1068,13 +1068,13 @@
 	// block until tx is empty
 	block_until_tx_empty(edge_port);
 
-	edge_port->closePending = TRUE;
+	edge_port->closePending = true;
 
 	if ((!edge_serial->is_epic) ||
 	    ((edge_serial->is_epic) &&
 	     (edge_serial->epic_descriptor.Supports.IOSPChase))) {
 		/* flush and chase */
-		edge_port->chaseResponsePending = TRUE;
+		edge_port->chaseResponsePending = true;
 
 		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
 		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
@@ -1082,7 +1082,7 @@
 			// block until chase finished
 			block_until_chase_response(edge_port);
 		} else {
-			edge_port->chaseResponsePending = FALSE;
+			edge_port->chaseResponsePending = false;
 		}
 	}
 
@@ -1094,10 +1094,10 @@
 		send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
 	}
 
-	//port->close = TRUE;
-	edge_port->closePending = FALSE;
-	edge_port->open = FALSE;
-	edge_port->openPending = FALSE;
+	//port->close = true;
+	edge_port->closePending = false;
+	edge_port->open = false;
+	edge_port->openPending = false;
 
 	usb_kill_urb(edge_port->write_urb);
 
@@ -1247,7 +1247,7 @@
 	}
 
 	// lock this write
-	edge_port->write_in_progress = TRUE;
+	edge_port->write_in_progress = true;
 
 	// get a pointer to the write_urb
 	urb = edge_port->write_urb;
@@ -1261,7 +1261,7 @@
 	buffer = kmalloc (count+2, GFP_ATOMIC);
 	if (buffer == NULL) {
 		dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__);
-		edge_port->write_in_progress = FALSE;
+		edge_port->write_in_progress = false;
 		goto exit_send;
 	}
 	buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count);
@@ -1301,7 +1301,7 @@
 	if (status) {
 		/* something went wrong */
 		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status);
-		edge_port->write_in_progress = FALSE;
+		edge_port->write_in_progress = false;
 
 		/* revert the credits as something bad happened. */
 		edge_port->txCredits += count;
@@ -1332,7 +1332,7 @@
 
 	if (edge_port == NULL)
 		return -ENODEV;
-	if (edge_port->closePending == TRUE)
+	if (edge_port->closePending)
 		return -ENODEV;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1371,7 +1371,7 @@
 
 	if (edge_port == NULL)
 		return -ENODEV;
-	if (edge_port->closePending == TRUE)
+	if (edge_port->closePending)
 		return -ENODEV;
 
 	if (!edge_port->open) {
@@ -1762,7 +1762,7 @@
 	    ((edge_serial->is_epic) &&
 	     (edge_serial->epic_descriptor.Supports.IOSPChase))) {
 		/* flush and chase */
-		edge_port->chaseResponsePending = TRUE;
+		edge_port->chaseResponsePending = true;
 
 		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
 		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
@@ -1770,7 +1770,7 @@
 			// block until chase finished
 			block_until_chase_response(edge_port);
 		} else {
-			edge_port->chaseResponsePending = FALSE;
+			edge_port->chaseResponsePending = false;
 		}
 	}
 
@@ -1952,13 +1952,13 @@
 				// Also, we currently clear flag and close the port regardless of content of above's Byte3.
 				// We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
 				// like wait longer in block_until_chase_response, but for now we don't. 
-				edge_port->chaseResponsePending = FALSE;
+				edge_port->chaseResponsePending = false;
 				wake_up (&edge_port->wait_chase);
 				return;
 
 			case IOSP_EXT_STATUS_RX_CHECK_RSP:
 				dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __FUNCTION__, edge_serial->rxPort, byte3 );
-				//Port->RxCheckRsp = TRUE;
+				//Port->RxCheckRsp = true;
 				return;
 		}
 	}
@@ -1974,8 +1974,8 @@
 			change_port_settings (edge_port, edge_port->port->tty->termios);
 
 		/* we have completed the open */
-		edge_port->openPending = FALSE;
-		edge_port->open = TRUE;
+		edge_port->openPending = false;
+		edge_port->open = true;
 		wake_up(&edge_port->wait_open);
 		return;
 	}
@@ -1983,7 +1983,7 @@
 	// If port is closed, silently discard all rcvd status. We can
 	// have cases where buffered status is received AFTER the close
 	// port command is sent to the Edgeport.
-	if ((!edge_port->open ) || (edge_port->closePending)) {
+	if (!edge_port->open || edge_port->closePending) {
 		return;
 	}
 
@@ -1991,14 +1991,14 @@
 		// Not currently sent by Edgeport
 		case IOSP_STATUS_LSR:
 			dbg("%s - Port %u LSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
-			handle_new_lsr (edge_port, FALSE, byte2, 0);
+			handle_new_lsr(edge_port, false, byte2, 0);
 			break;
 
 		case IOSP_STATUS_LSR_DATA:
 			dbg("%s - Port %u LSR Status = %02x, Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
 			// byte2 is LSR Register
 			// byte3 is broken data byte
-			handle_new_lsr (edge_port, TRUE, byte2, byte3);
+			handle_new_lsr(edge_port, true, byte2, byte3);
 			break;
 			//
 			//	case IOSP_EXT_4_STATUS:
@@ -2317,14 +2317,14 @@
 	if (!urb)
 		return -ENOMEM;
 
-	CmdUrbs++;
-	dbg("%s - ALLOCATE URB %p (outstanding %d)", __FUNCTION__, urb, CmdUrbs);
+	atomic_inc(&CmdUrbs);
+	dbg("%s - ALLOCATE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
 
 	usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
 		       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
 		       buffer, length, edge_bulk_out_cmd_callback, edge_port);
 
-	edge_port->commandPending = TRUE;
+	edge_port->commandPending = true;
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 
 	if (status) {
@@ -2332,16 +2332,16 @@
 		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __FUNCTION__, status);
 		usb_kill_urb(urb);
 		usb_free_urb(urb);
-		CmdUrbs--;
+		atomic_dec(&CmdUrbs);
 		return status;
 	}
 
 	// wait for command to finish
 	timeout = COMMAND_TIMEOUT;
 #if 0
-	wait_event (&edge_port->wait_command, (edge_port->commandPending == FALSE));
+	wait_event (&edge_port->wait_command, !edge_port->commandPending);
 
-	if (edge_port->commandPending == TRUE) {
+	if (edge_port->commandPending) {
 		/* command timed out */
 		dbg("%s - command timed out", __FUNCTION__);
 		status = -EINVAL;
@@ -2524,8 +2524,8 @@
 
 	dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
 
-	if ((!edge_port->open) &&
-	    (!edge_port->openPending)) {
+	if (!edge_port->open &&
+	    !edge_port->openPending) {
 		dbg("%s - port not opened", __FUNCTION__);
 		return;
 	}
@@ -2836,9 +2836,9 @@
 	struct usb_device *dev;
 	int i, j;
 	int response;
-	int interrupt_in_found;
-	int bulk_in_found;
-	int bulk_out_found;
+	bool interrupt_in_found;
+	bool bulk_in_found;
+	bool bulk_out_found;
 	static __u32 descriptor[3] = {	EDGE_COMPATIBILITY_MASK0,
 					EDGE_COMPATIBILITY_MASK1,
 					EDGE_COMPATIBILITY_MASK2 };
@@ -2936,14 +2936,14 @@
 	if (edge_serial->is_epic) {
 		/* EPIC thing, set up our interrupt polling now and our read urb, so
 		 * that the device knows it really is connected. */
-		interrupt_in_found = bulk_in_found = bulk_out_found = FALSE;
+		interrupt_in_found = bulk_in_found = bulk_out_found = false;
 		for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) {
 			struct usb_endpoint_descriptor *endpoint;
 			int buffer_size;
 
 			endpoint = &serial->interface->altsetting[0].endpoint[i].desc;
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-			if ((!interrupt_in_found) &&
+			if (!interrupt_in_found &&
 			    (usb_endpoint_is_int_in(endpoint))) {
 				/* we found a interrupt in endpoint */
 				dbg("found interrupt in");
@@ -2972,10 +2972,10 @@
 						 edge_serial,
 						 endpoint->bInterval);
 
-				interrupt_in_found = TRUE;
+				interrupt_in_found = true;
 			}
 
-			if ((!bulk_in_found) &&
+			if (!bulk_in_found &&
 			    (usb_endpoint_is_bulk_in(endpoint))) {
 				/* we found a bulk in endpoint */
 				dbg("found bulk in");
@@ -3001,19 +3001,19 @@
 						  endpoint->wMaxPacketSize,
 						  edge_bulk_in_callback,
 						  edge_serial);
-				bulk_in_found = TRUE;
+				bulk_in_found = true;
 			}
 
-			if ((!bulk_out_found) &&
+			if (!bulk_out_found &&
 			    (usb_endpoint_is_bulk_out(endpoint))) {
 				/* we found a bulk out endpoint */
 				dbg("found bulk out");
 				edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress;
-				bulk_out_found = TRUE;
+				bulk_out_found = true;
 			}
 		}
 
-		if ((!interrupt_in_found) || (!bulk_in_found) || (!bulk_out_found)) {
+		if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
 			err ("Error - the proper endpoints were not found!");
 			return -ENODEV;
 		}
@@ -3083,6 +3083,7 @@
 	retval = usb_register(&io_driver);
 	if (retval) 
 		goto failed_usb_register;
+	atomic_set(&CmdUrbs, 0);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index 29a913a..cb201c1 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -19,12 +19,6 @@
 #define MAX_RS232_PORTS		8	/* Max # of RS-232 ports per device */
 
 /* typedefs that the insideout headers need */
-#ifndef TRUE
-	#define TRUE		(1)
-#endif
-#ifndef FALSE
-	#define FALSE		(0)
-#endif
 #ifndef LOW8
 	#define LOW8(a)		((unsigned char)(a & 0xff))
 #endif
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index a408184..4df0ec7 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -247,12 +247,15 @@
 	{ USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
 	{ USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
 	{ USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+	{ USB_DEVICE(0x04AD, 0x0306) }, /* GPS Pocket PC USB Sync */
+	{ USB_DEVICE(0x04B7, 0x0531) }, /* MyGuide 7000 XL USB Sync */
 	{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
 	{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
 	{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
 	{ USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */
 	{ USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */
 	{ USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */
+	{ USB_DEVICE(0x04DD, 0x9151) }, /* SHARP S01SH USB Modem */
 	{ USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
 	{ USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
 	{ USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index b2097c4..7b085f3 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -238,7 +238,7 @@
 	if (rc < 0)
 		err("Reading line status failed (error = %d)", rc);
 	else {
-		status = status_buf[0] + (status_buf[1]<<8);
+		status = le16_to_cpu(*(u16 *)status_buf);
 
 		info("%s - read status %x %x", __FUNCTION__,
 		     status_buf[0], status_buf[1]);
@@ -257,7 +257,7 @@
 static int klsi_105_startup (struct usb_serial *serial)
 {
 	struct klsi_105_private *priv;
-	int i;
+	int i, j;
 
 	/* check if we support the product id (see keyspan.c)
 	 * FIXME
@@ -265,12 +265,12 @@
 
 	/* allocate the private data structure */
 	for (i=0; i<serial->num_ports; i++) {
-		int j;
 		priv = kmalloc(sizeof(struct klsi_105_private),
 						   GFP_KERNEL);
 		if (!priv) {
 			dbg("%skmalloc for klsi_105_private failed.", __FUNCTION__);
-			return -ENOMEM;
+			i--;
+			goto err_cleanup;
 		}
 		/* set initial values for control structures */
 		priv->cfg.pktlen    = 5;
@@ -292,15 +292,14 @@
 			priv->write_urb_pool[j] = urb;
 			if (urb == NULL) {
 				err("No more urbs???");
-				continue;
+				goto err_cleanup;
 			}
 
-			urb->transfer_buffer = NULL;
 			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
 							GFP_KERNEL);
 			if (!urb->transfer_buffer) {
 				err("%s - out of memory for urb buffers.", __FUNCTION__);
-				continue;
+				goto err_cleanup;
 			}
 		}
 
@@ -308,7 +307,20 @@
 		init_waitqueue_head(&serial->port[i]->write_wait);
 	}
 	
-	return (0);
+	return 0;
+
+err_cleanup:
+	for (; i >= 0; i--) {
+		priv = usb_get_serial_port_data(serial->port[i]);
+		for (j=0; j < NUM_URBS; j++) {
+			if (priv->write_urb_pool[j]) {
+				kfree(priv->write_urb_pool[j]->transfer_buffer);
+				usb_free_urb(priv->write_urb_pool[j]);
+			}
+		}
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+	return -ENOMEM;
 } /* klsi_105_startup */
 
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 4cd839b..3db1adc 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -438,17 +438,21 @@
 	if (retval) {
 		err("usb_submit_urb(read bulk) failed pipe 0x%x err %d",
 		    port->read_urb->pipe, retval);
-		goto exit;
+		goto error;
 	}
 
 	port->interrupt_in_urb->dev = port->serial->dev;
 	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-	if (retval)
+	if (retval) {
+		usb_kill_urb(port->read_urb);
 		err(" usb_submit_urb(read int) failed pipe 0x%x err %d",
 		    port->interrupt_in_urb->pipe, retval);
-
-exit:
+		goto error;
+	}
 	return 0;
+
+error:
+	return retval;
 } /* mct_u232_open */
 
 
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 2d588fb..b563e2a 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -103,11 +103,9 @@
 {
 	int result;
 	int length;
-	__u32 *data;
-	unsigned int status;
+	__u8 *data;
 	__u8 sp1;
 	__u8 sp2;
-	__u8 st;
 
 	dbg("%s"," : Entering\n");
 
@@ -141,18 +139,19 @@
 	 * Byte 2 IIR Port 2 (port.number is 1)
 	 * Byte 3 --------------
 	 * Byte 4 FIFO status for both */
-	if (length && length > 4) {
+
+	/* the above description is inverted
+	 * 	oneukum 2007-03-14 */
+
+	if (unlikely(length != 4)) {
 		dbg("Wrong data !!!");
 		return;
 	}
 
-	status = *data;
+	sp1 = data[3];
+	sp2 = data[2];
 
-	sp1 = (status & 0xff000000)>>24;
-	sp2 = (status & 0x00ff0000)>>16;
-	st = status & 0x000000ff;
-
-	if ((sp1 & 0x01) || (sp2 & 0x01)) {
+	if ((sp1 | sp2) & 0x01) {
 		/* No Interrupt Pending in both the ports */
 		dbg("No Interrupt !!!");
 	} else {
@@ -333,6 +332,7 @@
 	int response;
 	int port_number;
 	char data;
+	int allocated_urbs = 0;
 	int j;
 
 	serial = port->serial;
@@ -353,7 +353,7 @@
 
 	/* Initialising the write urb pool */
 	for (j = 0; j < NUM_URBS; ++j) {
-		urb = usb_alloc_urb(0,GFP_ATOMIC);
+		urb = usb_alloc_urb(0,GFP_KERNEL);
 		mos7720_port->write_urb_pool[j] = urb;
 
 		if (urb == NULL) {
@@ -365,10 +365,16 @@
 					       GFP_KERNEL);
 		if (!urb->transfer_buffer) {
 			err("%s-out of memory for urb buffers.", __FUNCTION__);
+			usb_free_urb(mos7720_port->write_urb_pool[j]);
+			mos7720_port->write_urb_pool[j] = NULL;
 			continue;
 		}
+		allocated_urbs++;
 	}
 
+	if (!allocated_urbs)
+		return -ENOMEM;
+
 	 /* Initialize MCS7720 -- Write Init values to corresponding Registers
 	  *
 	  * Register Index
@@ -526,7 +532,7 @@
 	}
 
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
 			chars += URB_TRANSFER_BUFFER_SIZE;
 	}
 	dbg("%s - returns %d", __FUNCTION__, chars);
@@ -629,7 +635,7 @@
 	}
 
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
 			room += URB_TRANSFER_BUFFER_SIZE;
 	}
 
@@ -664,7 +670,7 @@
 	urb = NULL;
 
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
+		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
 			urb = mos7720_port->write_urb_pool[i];
 			dbg("URB:%d",i);
 			break;
@@ -1628,6 +1634,7 @@
 	.chars_in_buffer	= mos7720_chars_in_buffer,
 	.break_ctl		= mos7720_break,
 	.read_bulk_callback	= mos7720_bulk_in_callback,
+	.read_int_callback	= mos7720_interrupt_callback,
 };
 
 static int __init moschip7720_init(void)
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index c6cca85..2366e7b 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -176,9 +176,12 @@
 	int port_num;		/*Actual port number in the device(1,2,etc) */
 	struct urb *write_urb;	/* write URB for this port */
 	struct urb *read_urb;	/* read URB for this port */
+	struct urb *int_urb;
 	__u8 shadowLCR;		/* last LCR value received */
 	__u8 shadowMCR;		/* last MCR value received */
 	char open;
+	char open_ports;
+	char zombie;
 	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
 	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */
 	int delta_msr_cond;
@@ -191,17 +194,17 @@
 	__u8 DcrRegOffset;
 	//for processing control URBS in interrupt context
 	struct urb *control_urb;
+	struct usb_ctrlrequest *dr;
 	char *ctrl_buf;
 	int MsrLsr;
 
+	spinlock_t pool_lock;
 	struct urb *write_urb_pool[NUM_URBS];
+	char busy[NUM_URBS];
 };
 
 
 static int debug;
-static int mos7840_num_ports;	//this says the number of ports in the device
-static int mos7840_num_open_ports;
-
 
 /*
  * mos7840_set_reg_sync
@@ -254,7 +257,7 @@
 	struct usb_device *dev = port->serial->dev;
 	val = val & 0x00ff;
 	// For the UART control registers, the application number need to be Or'ed
-	if (mos7840_num_ports == 4) {
+	if (port->serial->num_ports == 4) {
 		val |=
 		    (((__u16) port->number - (__u16) (port->serial->minor)) +
 		     1) << 8;
@@ -294,7 +297,7 @@
 
 	//dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
 	/*Wval  is same as application number */
-	if (mos7840_num_ports == 4) {
+	if (port->serial->num_ports == 4) {
 		Wval =
 		    (((__u16) port->number - (__u16) (port->serial->minor)) +
 		     1) << 8;
@@ -352,7 +355,7 @@
 	return (struct moschip_port *)usb_get_serial_port_data(port);
 }
 
-static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
+static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
 {
 	struct moschip_port *mos7840_port;
 	struct async_icount *icount;
@@ -366,22 +369,24 @@
 		/* update input line counters */
 		if (new_msr & MOS_MSR_DELTA_CTS) {
 			icount->cts++;
+			smp_wmb();
 		}
 		if (new_msr & MOS_MSR_DELTA_DSR) {
 			icount->dsr++;
+			smp_wmb();
 		}
 		if (new_msr & MOS_MSR_DELTA_CD) {
 			icount->dcd++;
+			smp_wmb();
 		}
 		if (new_msr & MOS_MSR_DELTA_RI) {
 			icount->rng++;
+			smp_wmb();
 		}
 	}
-
-	return 0;
 }
 
-static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
+static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
 {
 	struct async_icount *icount;
 
@@ -400,18 +405,20 @@
 	icount = &port->icount;
 	if (new_lsr & SERIAL_LSR_BI) {
 		icount->brk++;
+		smp_wmb();
 	}
 	if (new_lsr & SERIAL_LSR_OE) {
 		icount->overrun++;
+		smp_wmb();
 	}
 	if (new_lsr & SERIAL_LSR_PE) {
 		icount->parity++;
+		smp_wmb();
 	}
 	if (new_lsr & SERIAL_LSR_FE) {
 		icount->frame++;
+		smp_wmb();
 	}
-
-	return 0;
 }
 
 /************************************************************************/
@@ -426,12 +433,15 @@
 	unsigned char *data;
 	struct moschip_port *mos7840_port;
 	__u8 regval = 0x0;
+	int result = 0;
 
 	if (!urb) {
 		dbg("%s", "Invalid Pointer !!!!:\n");
 		return;
 	}
 
+	mos7840_port = (struct moschip_port *)urb->context;
+
 	switch (urb->status) {
 	case 0:
 		/* success */
@@ -449,8 +459,6 @@
 		goto exit;
 	}
 
-	mos7840_port = (struct moschip_port *)urb->context;
-
 	dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
 	dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
 	    mos7840_port->MsrLsr, mos7840_port->port_num);
@@ -462,21 +470,26 @@
 	else if (mos7840_port->MsrLsr == 1)
 		mos7840_handle_new_lsr(mos7840_port, regval);
 
-      exit:
-	return;
+exit:
+	spin_lock(&mos7840_port->pool_lock);
+	if (!mos7840_port->zombie)
+		result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
+	spin_unlock(&mos7840_port->pool_lock);
+	if (result) {
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting interrupt urb\n",
+			__FUNCTION__, result);
+	}
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
 			   __u16 * val)
 {
 	struct usb_device *dev = mcs->port->serial->dev;
-	struct usb_ctrlrequest *dr = NULL;
-	unsigned char *buffer = NULL;
-	int ret = 0;
-	buffer = (__u8 *) mcs->ctrl_buf;
+	struct usb_ctrlrequest *dr = mcs->dr;
+	unsigned char *buffer = mcs->ctrl_buf;
+	int ret;
 
-//      dr=(struct usb_ctrlrequest *)(buffer);
-	dr = (void *)(buffer + 2);
 	dr->bRequestType = MCS_RD_RTYPE;
 	dr->bRequest = MCS_RDREQ;
 	dr->wValue = cpu_to_le16(Wval);	//0;
@@ -506,8 +519,8 @@
 	__u16 Data;
 	unsigned char *data;
 	__u8 sp[5], st;
-	int i;
-	__u16 wval;
+	int i, rv = 0;
+	__u16 wval, wreg = 0;
 
 	dbg("%s", " : Entering\n");
 	if (!urb) {
@@ -569,31 +582,34 @@
 					dbg("Serial Port %d: Receiver status error or ", i);
 					dbg("address bit detected in 9-bit mode\n");
 					mos7840_port->MsrLsr = 1;
-					mos7840_get_reg(mos7840_port, wval,
-							LINE_STATUS_REGISTER,
-							&Data);
+					wreg = LINE_STATUS_REGISTER;
 					break;
 				case SERIAL_IIR_MS:
 					dbg("Serial Port %d: Modem status change\n", i);
 					mos7840_port->MsrLsr = 0;
-					mos7840_get_reg(mos7840_port, wval,
-							MODEM_STATUS_REGISTER,
-							&Data);
+					wreg = MODEM_STATUS_REGISTER;
 					break;
 				}
+				spin_lock(&mos7840_port->pool_lock);
+				if (!mos7840_port->zombie) {
+					rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
+				} else {
+					spin_unlock(&mos7840_port->pool_lock);
+					return;
+				}
+				spin_unlock(&mos7840_port->pool_lock);
 			}
 		}
 	}
-      exit:
+	if (!(rv < 0)) /* the completion handler for the control urb will resubmit */
+		return;
+exit:
 	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result) {
 		dev_err(&urb->dev->dev,
 			"%s - Error %d submitting interrupt urb\n",
 			__FUNCTION__, result);
 	}
-
-	return;
-
 }
 
 static int mos7840_port_paranoia_check(struct usb_serial_port *port,
@@ -634,7 +650,8 @@
 	if (!port ||
 	    mos7840_port_paranoia_check(port, function) ||
 	    mos7840_serial_paranoia_check(port->serial, function)) {
-		/* then say that we don't have a valid usb_serial thing, which will                  * end up genrating -ENODEV return values */
+		/* then say that we don't have a valid usb_serial thing, which will
+		 * end up genrating -ENODEV return values */
 		return NULL;
 	}
 
@@ -699,6 +716,7 @@
 			tty_flip_buffer_push(tty);
 		}
 		mos7840_port->icount.rx += urb->actual_length;
+		smp_wmb();
 		dbg("mos7840_port->icount.rx is %d:\n",
 		    mos7840_port->icount.rx);
 	}
@@ -708,15 +726,14 @@
 		return;
 	}
 
-	if (mos7840_port->read_urb->status != -EINPROGRESS) {
-		mos7840_port->read_urb->dev = serial->dev;
 
-		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+	mos7840_port->read_urb->dev = serial->dev;
 
-		if (status) {
-			dbg(" usb_submit_urb(read bulk) failed, status = %d",
-			    status);
-		}
+	status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+	if (status) {
+		dbg(" usb_submit_urb(read bulk) failed, status = %d",
+		 status);
 	}
 }
 
@@ -730,17 +747,28 @@
 {
 	struct moschip_port *mos7840_port;
 	struct tty_struct *tty;
+	int i;
+
 	if (!urb) {
 		dbg("%s", "Invalid Pointer !!!!:\n");
 		return;
 	}
 
+	mos7840_port = (struct moschip_port *)urb->context;
+	spin_lock(&mos7840_port->pool_lock);
+	for (i = 0; i < NUM_URBS; i++) {
+		if (urb == mos7840_port->write_urb_pool[i]) {
+			mos7840_port->busy[i] = 0;
+			break;
+		}
+	}
+	spin_unlock(&mos7840_port->pool_lock);
+
 	if (urb->status) {
 		dbg("nonzero write bulk status received:%d\n", urb->status);
 		return;
 	}
 
-	mos7840_port = (struct moschip_port *)urb->context;
 	if (!mos7840_port) {
 		dbg("%s", "NULL mos7840_port pointer \n");
 		return;
@@ -792,13 +820,13 @@
 	__u16 Data;
 	int status;
 	struct moschip_port *mos7840_port;
+	struct moschip_port *port0;
 
 	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
 		dbg("%s", "Port Paranoia failed \n");
 		return -ENODEV;
 	}
 
-	mos7840_num_open_ports++;
 	serial = port->serial;
 
 	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
@@ -807,16 +835,18 @@
 	}
 
 	mos7840_port = mos7840_get_port_private(port);
+	port0 = mos7840_get_port_private(serial->port[0]);
 
-	if (mos7840_port == NULL)
+	if (mos7840_port == NULL || port0 == NULL)
 		return -ENODEV;
 
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
+	port0->open_ports++;
 
 	/* Initialising the write urb pool */
 	for (j = 0; j < NUM_URBS; ++j) {
-		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		urb = usb_alloc_urb(0, GFP_KERNEL);
 		mos7840_port->write_urb_pool[j] = urb;
 
 		if (urb == NULL) {
@@ -824,10 +854,10 @@
 			continue;
 		}
 
-		urb->transfer_buffer = NULL;
-		urb->transfer_buffer =
-		    kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
 		if (!urb->transfer_buffer) {
+			usb_free_urb(urb);
+			mos7840_port->write_urb_pool[j] = NULL;
 			err("%s-out of memory for urb buffers.", __FUNCTION__);
 			continue;
 		}
@@ -879,9 +909,7 @@
 	}
 	Data |= 0x08;		//Driver done bit
 	Data |= 0x20;		//rx_disable
-	status = 0;
-	status =
-	    mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+	status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
 	if (status < 0) {
 		dbg("writing Controlreg failed\n");
 		return -1;
@@ -893,7 +921,6 @@
 	////////////////////////////////////
 
 	Data = 0x00;
-	status = 0;
 	status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
 	if (status < 0) {
 		dbg("disableing interrupts failed\n");
@@ -901,7 +928,6 @@
 	}
 	// Set FIFO_CONTROL_REGISTER to the default value
 	Data = 0x00;
-	status = 0;
 	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
 	if (status < 0) {
 		dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
@@ -909,7 +935,6 @@
 	}
 
 	Data = 0xcf;
-	status = 0;
 	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
 	if (status < 0) {
 		dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
@@ -917,22 +942,18 @@
 	}
 
 	Data = 0x03;
-	status = 0;
 	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
 	mos7840_port->shadowLCR = Data;
 
 	Data = 0x0b;
-	status = 0;
 	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
 	mos7840_port->shadowMCR = Data;
 
 	Data = 0x00;
-	status = 0;
 	status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
 	mos7840_port->shadowLCR = Data;
 
 	Data |= SERIAL_LCR_DLAB;	//data latch enable in LCR 0x80
-	status = 0;
 	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
 
 	Data = 0x0c;
@@ -999,7 +1020,7 @@
 /* Check to see if we've set up our endpoint info yet    *
      * (can't set it up in mos7840_startup as the structures *
      * were not set up at that time.)                        */
-	if (mos7840_num_open_ports == 1) {
+	if (port0->open_ports == 1) {
 		if (serial->port[0]->interrupt_in_buffer == NULL) {
 
 			/* set up interrupt urb */
@@ -1097,6 +1118,7 @@
 {
 	int i;
 	int chars = 0;
+	unsigned long flags;
 	struct moschip_port *mos7840_port;
 
 	dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
@@ -1112,13 +1134,15 @@
 		return -1;
 	}
 
+	spin_lock_irqsave(&mos7840_port->pool_lock,flags);
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7840_port->write_urb_pool[i]->status == -EINPROGRESS) {
+		if (mos7840_port->busy[i]) {
 			chars += URB_TRANSFER_BUFFER_SIZE;
 		}
 	}
+	spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
 	dbg("%s - returns %d", __FUNCTION__, chars);
-	return (chars);
+	return chars;
 
 }
 
@@ -1172,6 +1196,7 @@
 {
 	struct usb_serial *serial;
 	struct moschip_port *mos7840_port;
+	struct moschip_port *port0;
 	int j;
 	__u16 Data;
 
@@ -1189,10 +1214,10 @@
 	}
 
 	mos7840_port = mos7840_get_port_private(port);
+	port0 = mos7840_get_port_private(serial->port[0]);
 
-	if (mos7840_port == NULL) {
+	if (mos7840_port == NULL || port0 == NULL)
 		return;
-	}
 
 	for (j = 0; j < NUM_URBS; ++j)
 		usb_kill_urb(mos7840_port->write_urb_pool[j]);
@@ -1234,12 +1259,13 @@
 	}
 //              if(mos7840_port->ctrl_buf != NULL)
 //                      kfree(mos7840_port->ctrl_buf);
-	mos7840_num_open_ports--;
+	port0->open_ports--;
 	dbg("mos7840_num_open_ports in close%d:in port%d\n",
-	    mos7840_num_open_ports, port->number);
-	if (mos7840_num_open_ports == 0) {
+	    port0->open_ports, port->number);
+	if (port0->open_ports == 0) {
 		if (serial->port[0]->interrupt_in_urb) {
 			dbg("%s", "Shutdown interrupt_in_urb\n");
+			usb_kill_urb(serial->port[0]->interrupt_in_urb);
 		}
 	}
 
@@ -1368,6 +1394,7 @@
 {
 	int i;
 	int room = 0;
+	unsigned long flags;
 	struct moschip_port *mos7840_port;
 
 	dbg("%s \n", " mos7840_write_room:entering ...........");
@@ -1384,14 +1411,17 @@
 		return -1;
 	}
 
+	spin_lock_irqsave(&mos7840_port->pool_lock, flags);
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+		if (!mos7840_port->busy[i]) {
 			room += URB_TRANSFER_BUFFER_SIZE;
 		}
 	}
+	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 
+	room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
 	dbg("%s - returns %d", __FUNCTION__, room);
-	return (room);
+	return room;
 
 }
 
@@ -1410,6 +1440,7 @@
 	int i;
 	int bytes_sent = 0;
 	int transfer_size;
+	unsigned long flags;
 
 	struct moschip_port *mos7840_port;
 	struct usb_serial *serial;
@@ -1476,13 +1507,16 @@
 	/* try to find a free urb in the list */
 	urb = NULL;
 
+	spin_lock_irqsave(&mos7840_port->pool_lock, flags);
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+		if (!mos7840_port->busy[i]) {
+			mos7840_port->busy[i] = 1;
 			urb = mos7840_port->write_urb_pool[i];
 			dbg("\nURB:%d", i);
 			break;
 		}
 	}
+	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 
 	if (urb == NULL) {
 		dbg("%s - no more free urbs", __FUNCTION__);
@@ -1518,6 +1552,7 @@
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 
 	if (status) {
+		mos7840_port->busy[i] = 0;
 		err("%s - usb_submit_urb(write bulk) failed with status = %d",
 		    __FUNCTION__, status);
 		bytes_sent = status;
@@ -1525,6 +1560,7 @@
 	}
 	bytes_sent = transfer_size;
 	mos7840_port->icount.tx += transfer_size;
+	smp_wmb();
 	dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
       exit:
 
@@ -2490,6 +2526,7 @@
 			if (signal_pending(current))
 				return -ERESTARTSYS;
 			cnow = mos7840_port->icount;
+			smp_rmb();
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
 				return -EIO;	/* no change => error */
@@ -2506,6 +2543,7 @@
 
 	case TIOCGICOUNT:
 		cnow = mos7840_port->icount;
+		smp_rmb();
 		icount.cts = cnow.cts;
 		icount.dsr = cnow.dsr;
 		icount.rng = cnow.rng;
@@ -2535,19 +2573,18 @@
 
 static int mos7840_calc_num_ports(struct usb_serial *serial)
 {
+	int mos7840_num_ports = 0;
 
 	dbg("numberofendpoints: %d \n",
 	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
 	dbg("numberofendpoints: %d \n",
 	    (int)serial->interface->altsetting->desc.bNumEndpoints);
 	if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
-		mos7840_num_ports = 2;
-		serial->type->num_ports = 2;
+		mos7840_num_ports = serial->num_ports = 2;
 	} else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
-		mos7840_num_ports = 4;
-		serial->type->num_bulk_in = 4;
-		serial->type->num_bulk_out = 4;
-		serial->type->num_ports = 4;
+		serial->num_bulk_in = 4;
+		serial->num_bulk_out = 4;
+		mos7840_num_ports = serial->num_ports = 4;
 	}
 
 	return mos7840_num_ports;
@@ -2583,7 +2620,9 @@
 		mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
 		if (mos7840_port == NULL) {
 			err("%s - Out of memory", __FUNCTION__);
-			return -ENOMEM;
+			status = -ENOMEM;
+			i--; /* don't follow NULL pointer cleaning up */
+			goto error;
 		}
 
 		/* Initialize all port interrupt end point to port 0 int endpoint *
@@ -2591,6 +2630,7 @@
 
 		mos7840_port->port = serial->port[i];
 		mos7840_set_port_private(serial->port[i], mos7840_port);
+		spin_lock_init(&mos7840_port->pool_lock);
 
 		mos7840_port->port_num = ((serial->port[i]->number -
 					   (serial->port[i]->serial->minor)) +
@@ -2601,22 +2641,22 @@
 			mos7840_port->ControlRegOffset = 0x1;
 			mos7840_port->DcrRegOffset = 0x4;
 		} else if ((mos7840_port->port_num == 2)
-			   && (mos7840_num_ports == 4)) {
+			   && (serial->num_ports == 4)) {
 			mos7840_port->SpRegOffset = 0x8;
 			mos7840_port->ControlRegOffset = 0x9;
 			mos7840_port->DcrRegOffset = 0x16;
 		} else if ((mos7840_port->port_num == 2)
-			   && (mos7840_num_ports == 2)) {
+			   && (serial->num_ports == 2)) {
 			mos7840_port->SpRegOffset = 0xa;
 			mos7840_port->ControlRegOffset = 0xb;
 			mos7840_port->DcrRegOffset = 0x19;
 		} else if ((mos7840_port->port_num == 3)
-			   && (mos7840_num_ports == 4)) {
+			   && (serial->num_ports == 4)) {
 			mos7840_port->SpRegOffset = 0xa;
 			mos7840_port->ControlRegOffset = 0xb;
 			mos7840_port->DcrRegOffset = 0x19;
 		} else if ((mos7840_port->port_num == 4)
-			   && (mos7840_num_ports == 4)) {
+			   && (serial->num_ports == 4)) {
 			mos7840_port->SpRegOffset = 0xc;
 			mos7840_port->ControlRegOffset = 0xd;
 			mos7840_port->DcrRegOffset = 0x1c;
@@ -2701,21 +2741,19 @@
 			dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
 
 		Data = 0x20;
-		status = 0;
 		status =
 		    mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
 					 Data);
 		if (status < 0) {
 			dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
 			    status);
-			break;
+			goto error;
 		} else
 			dbg("CLK_MULTI_REGISTER Writing success status%d\n",
 			    status);
 
 		//write value 0x0 to scratchpad register
 		Data = 0x00;
-		status = 0;
 		status =
 		    mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
 					 Data);
@@ -2729,7 +2767,7 @@
 
 		//Zero Length flag register
 		if ((mos7840_port->port_num != 1)
-		    && (mos7840_num_ports == 2)) {
+		    && (serial->num_ports == 2)) {
 
 			Data = 0xff;
 			status = 0;
@@ -2770,14 +2808,17 @@
 				    i + 1, status);
 
 		}
-		mos7840_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC);
+		mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
 		mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-
+		mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+		if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) {
+			status = -ENOMEM;
+			goto error;
+		}
 	}
 
 	//Zero Length flag enable
 	Data = 0x0f;
-	status = 0;
 	status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
 	if (status < 0) {
 		dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
@@ -2789,6 +2830,17 @@
 	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ);
 	return 0;
+error:
+	for (/* nothing */; i >= 0; i--) {
+		mos7840_port = mos7840_get_port_private(serial->port[i]);
+
+		kfree(mos7840_port->dr);
+		kfree(mos7840_port->ctrl_buf);
+		usb_free_urb(mos7840_port->control_urb);
+		kfree(mos7840_port);
+		serial->port[i] = NULL;
+	}
+	return status;
 }
 
 /****************************************************************************
@@ -2799,6 +2851,7 @@
 static void mos7840_shutdown(struct usb_serial *serial)
 {
 	int i;
+	unsigned long flags;
 	struct moschip_port *mos7840_port;
 	dbg("%s \n", " shutdown :entering..........");
 
@@ -2814,8 +2867,12 @@
 
 	for (i = 0; i < serial->num_ports; ++i) {
 		mos7840_port = mos7840_get_port_private(serial->port[i]);
-		kfree(mos7840_port->ctrl_buf);
+		spin_lock_irqsave(&mos7840_port->pool_lock, flags);
+		mos7840_port->zombie = 1;
+		spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 		usb_kill_urb(mos7840_port->control_urb);
+		kfree(mos7840_port->ctrl_buf);
+		kfree(mos7840_port->dr);
 		kfree(mos7840_port);
 		mos7840_set_port_private(serial->port[i], NULL);
 	}
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 0216ac1..4adfab9 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -69,6 +69,7 @@
 static int  omninet_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  omninet_write_room		(struct usb_serial_port *port);
 static void omninet_shutdown		(struct usb_serial *serial);
+static int omninet_attach		(struct usb_serial *serial);
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -99,6 +100,7 @@
 	.num_bulk_in =		1,
 	.num_bulk_out =		2,
 	.num_ports =		1,
+	.attach =		omninet_attach,
 	.open =			omninet_open,
 	.close =		omninet_close,
 	.write =		omninet_write,
@@ -145,22 +147,30 @@
 	__u8	od_outseq;	// Sequence number for bulk_out URBs
 };
 
-static int omninet_open (struct usb_serial_port *port, struct file *filp)
+static int omninet_attach (struct usb_serial *serial)
 {
-	struct usb_serial	*serial = port->serial;
-	struct usb_serial_port	*wport;
-	struct omninet_data	*od;
-	int			result = 0;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
+	struct omninet_data *od;
+	struct usb_serial_port *port = serial->port[0];
 
 	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
 	if( !od ) {
 		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data));
 		return -ENOMEM;
 	}
-
 	usb_set_serial_port_data(port, od);
+	return 0;
+}
+
+static int omninet_open (struct usb_serial_port *port, struct file *filp)
+{
+	struct usb_serial	*serial = port->serial;
+	struct usb_serial_port	*wport;
+	struct omninet_data	*od = usb_get_serial_port_data(port);
+	int			result = 0;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
 	wport = serial->port[1];
 	wport->tty = port->tty;
 
@@ -170,24 +180,17 @@
 		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 		      omninet_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-	if (result)
+	if (result) {
 		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+	}
 
 	return result;
 }
 
 static void omninet_close (struct usb_serial_port *port, struct file * filp)
 {
-	struct usb_serial 	*serial = port->serial;
-	struct usb_serial_port 	*wport;
-
 	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	wport = serial->port[1];
-	usb_kill_urb(wport->write_urb);
 	usb_kill_urb(port->read_urb);
-
-	kfree(usb_get_serial_port_data(port));
 }
 
 
@@ -326,7 +329,12 @@
 
 static void omninet_shutdown (struct usb_serial *serial)
 {
+	struct usb_serial_port *wport = serial->port[1];
+	struct usb_serial_port *port = serial->port[0];
 	dbg ("%s", __FUNCTION__);
+
+	usb_kill_urb(wport->write_urb);
+	kfree(usb_get_serial_port_data(port));
 }
 
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index ced9f32..8c3f55b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -67,54 +67,115 @@
 static int  option_send_setup(struct usb_serial_port *port);
 
 /* Vendor and product IDs */
-#define OPTION_VENDOR_ID                0x0AF0
-#define HUAWEI_VENDOR_ID                0x12D1
-#define AUDIOVOX_VENDOR_ID              0x0F3D
-#define NOVATELWIRELESS_VENDOR_ID       0x1410
-#define ANYDATA_VENDOR_ID               0x16d5
+#define OPTION_VENDOR_ID			0x0AF0
+#define OPTION_PRODUCT_COLT			0x5000
+#define OPTION_PRODUCT_RICOLA			0x6000
+#define OPTION_PRODUCT_RICOLA_LIGHT		0x6100
+#define OPTION_PRODUCT_RICOLA_QUAD		0x6200
+#define OPTION_PRODUCT_RICOLA_QUAD_LIGHT	0x6300
+#define OPTION_PRODUCT_RICOLA_NDIS		0x6050
+#define OPTION_PRODUCT_RICOLA_NDIS_LIGHT	0x6150
+#define OPTION_PRODUCT_RICOLA_NDIS_QUAD		0x6250
+#define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT	0x6350
+#define OPTION_PRODUCT_COBRA			0x6500
+#define OPTION_PRODUCT_COBRA_BUS		0x6501
+#define OPTION_PRODUCT_VIPER			0x6600
+#define OPTION_PRODUCT_VIPER_BUS		0x6601
+#define OPTION_PRODUCT_GT_MAX_READY		0x6701
+#define OPTION_PRODUCT_GT_MAX			0x6711
+#define OPTION_PRODUCT_FUJI_MODEM_LIGHT		0x6721
+#define OPTION_PRODUCT_FUJI_MODEM_GT		0x6741
+#define OPTION_PRODUCT_FUJI_MODEM_EX		0x6761
+#define OPTION_PRODUCT_FUJI_NETWORK_LIGHT	0x6731
+#define OPTION_PRODUCT_FUJI_NETWORK_GT		0x6751
+#define OPTION_PRODUCT_FUJI_NETWORK_EX		0x6771
+#define OPTION_PRODUCT_KOI_MODEM		0x6800
+#define OPTION_PRODUCT_KOI_NETWORK		0x6811
+#define OPTION_PRODUCT_SCORPION_MODEM		0x6901
+#define OPTION_PRODUCT_SCORPION_NETWORK		0x6911
+#define OPTION_PRODUCT_ETNA_MODEM		0x7001
+#define OPTION_PRODUCT_ETNA_NETWORK		0x7011
+#define OPTION_PRODUCT_ETNA_MODEM_LITE		0x7021
+#define OPTION_PRODUCT_ETNA_MODEM_GT		0x7041
+#define OPTION_PRODUCT_ETNA_MODEM_EX		0x7061
+#define OPTION_PRODUCT_ETNA_NETWORK_LITE	0x7031
+#define OPTION_PRODUCT_ETNA_NETWORK_GT		0x7051
+#define OPTION_PRODUCT_ETNA_NETWORK_EX		0x7071
+#define OPTION_PRODUCT_ETNA_KOI_MODEM		0x7100
+#define OPTION_PRODUCT_ETNA_KOI_NETWORK		0x7111
 
-#define OPTION_PRODUCT_OLD              0x5000
-#define OPTION_PRODUCT_FUSION           0x6000
-#define OPTION_PRODUCT_FUSION2          0x6300
-#define OPTION_PRODUCT_COBRA            0x6500
-#define OPTION_PRODUCT_COBRA2           0x6600
-#define OPTION_PRODUCT_GTMAX36          0x6701
-#define HUAWEI_PRODUCT_E600             0x1001
-#define HUAWEI_PRODUCT_E220             0x1003
-#define AUDIOVOX_PRODUCT_AIRCARD        0x0112
-#define NOVATELWIRELESS_PRODUCT_U740    0x1400
-#define ANYDATA_PRODUCT_ID              0x6501
+#define HUAWEI_VENDOR_ID			0x12D1
+#define HUAWEI_PRODUCT_E600			0x1001
+#define HUAWEI_PRODUCT_E220			0x1003
+
+#define NOVATELWIRELESS_VENDOR_ID		0x1410
+
+#define ANYDATA_VENDOR_ID			0x16d5
+#define ANYDATA_PRODUCT_ID			0x6501
+
+#define BANDRICH_VENDOR_ID			0x1A8D
+#define BANDRICH_PRODUCT_C100_1			0x1002
+#define BANDRICH_PRODUCT_C100_2			0x1003
+
+#define DELL_VENDOR_ID				0x413C
 
 static struct usb_device_id option_ids[] = {
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel XU870 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
+	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
+	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) },		/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */
 	{ } /* Terminating entry */
 };
-
-static struct usb_device_id option_ids1[] = {
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
-	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
-	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
-	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
-	{ } /* Terminating entry */
-};
-
 MODULE_DEVICE_TABLE(usb, option_ids);
 
 static struct usb_driver option_driver = {
@@ -136,7 +197,7 @@
 	},
 	.description       = "GSM modem (1-port)",
 	.usb_driver        = &option_driver,
-	.id_table          = option_ids1,
+	.id_table          = option_ids,
 	.num_interrupt_in  = NUM_DONT_CARE,
 	.num_bulk_in       = NUM_DONT_CARE,
 	.num_bulk_out      = NUM_DONT_CARE,
@@ -539,12 +600,6 @@
 	return (0);
 }
 
-static inline void stop_urb(struct urb *urb)
-{
-	if (urb && urb->status == -EINPROGRESS)
-		usb_kill_urb(urb);
-}
-
 static void option_close(struct usb_serial_port *port, struct file *filp)
 {
 	int i;
@@ -562,9 +617,9 @@
 
 		/* Stop reading/writing urbs */
 		for (i = 0; i < N_IN_URB; i++)
-			stop_urb(portdata->in_urbs[i]);
+			usb_kill_urb(portdata->in_urbs[i]);
 		for (i = 0; i < N_OUT_URB; i++)
-			stop_urb(portdata->out_urbs[i]);
+			usb_kill_urb(portdata->out_urbs[i]);
 	}
 	port->tty = NULL;
 }
@@ -695,9 +750,9 @@
 		port = serial->port[i];
 		portdata = usb_get_serial_port_data(port);
 		for (j = 0; j < N_IN_URB; j++)
-			stop_urb(portdata->in_urbs[j]);
+			usb_kill_urb(portdata->in_urbs[j]);
 		for (j = 0; j < N_OUT_URB; j++)
-			stop_urb(portdata->out_urbs[j]);
+			usb_kill_urb(portdata->out_urbs[j]);
 	}
 
 	/* Now free them */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 6c083d4..83dfae9 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -83,6 +83,7 @@
 	{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
 	{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
+	{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 65a5039..f9a71d0 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -97,3 +97,8 @@
 /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
 #define HUAWEI_VENDOR_ID	0x12d1
 #define HUAWEI_PRODUCT_ID	0x1001
+
+/* Willcom WS002IN Data Driver (by NetIndex Inc.) */
+#define WS002IN_VENDOR_ID	0x11f6
+#define WS002IN_PRODUCT_ID	0x2001
+
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index ecedd83..644607d 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -456,12 +456,6 @@
 	return (0);
 }
 
-static inline void stop_urb(struct urb *urb)
-{
-	if (urb && urb->status == -EINPROGRESS)
-		usb_kill_urb(urb);
-}
-
 static void sierra_close(struct usb_serial_port *port, struct file *filp)
 {
 	int i;
@@ -479,9 +473,9 @@
 
 		/* Stop reading/writing urbs */
 		for (i = 0; i < N_IN_URB; i++)
-			stop_urb(portdata->in_urbs[i]);
+			usb_unlink_urb(portdata->in_urbs[i]);
 		for (i = 0; i < N_OUT_URB; i++)
-			stop_urb(portdata->out_urbs[i]);
+			usb_unlink_urb(portdata->out_urbs[i]);
 	}
 	port->tty = NULL;
 }
@@ -583,17 +577,26 @@
 	/* Stop reading/writing urbs */
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
+		if (!port)
+			continue;
 		portdata = usb_get_serial_port_data(port);
+		if (!portdata)
+			continue;
+
 		for (j = 0; j < N_IN_URB; j++)
-			stop_urb(portdata->in_urbs[j]);
+			usb_unlink_urb(portdata->in_urbs[j]);
 		for (j = 0; j < N_OUT_URB; j++)
-			stop_urb(portdata->out_urbs[j]);
+			usb_unlink_urb(portdata->out_urbs[j]);
 	}
 
 	/* Now free them */
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
+		if (!port)
+			continue;
 		portdata = usb_get_serial_port_data(port);
+		if (!portdata)
+			continue;
 
 		for (j = 0; j < N_IN_URB; j++) {
 			if (portdata->in_urbs[j]) {
@@ -612,6 +615,8 @@
 	/* Now free per port private data */
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
+		if (!port)
+			continue;
 		kfree(usb_get_serial_port_data(port));
 	}
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 6bf22a2..7639022 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -99,9 +99,12 @@
 			continue;
 
 		*minor = i;
+		j = 0;
 		dbg("%s - minor base = %d", __FUNCTION__, *minor);
-		for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
+		for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
 			serial_table[i] = serial;
+			serial->port[j++]->number = i;
+		}
 		spin_unlock(&table_lock);
 		return serial;
 	}
@@ -826,7 +829,6 @@
 			num_ports = type->num_ports;
 	}
 
-	serial->minor = minor;
 	serial->num_ports = num_ports;
 	serial->num_bulk_in = num_bulk_in;
 	serial->num_bulk_out = num_bulk_out;
@@ -847,7 +849,6 @@
 		port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
 		if (!port)
 			goto probe_error;
-		port->number = i + serial->minor;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
 		mutex_init(&port->mutex);
@@ -980,6 +981,7 @@
 		dev_err(&interface->dev, "No more free serial devices\n");
 		goto probe_error;
 	}
+	serial->minor = minor;
 
 	/* register all of the individual ports with the driver core */
 	for (i = 0; i < num_ports; ++i) {
@@ -1034,9 +1036,6 @@
 		kfree(port->interrupt_out_buffer);
 	}
 
-	/* return the minor range that this device had */
-	return_serial (serial);
-
 	/* free up any memory that we allocated */
 	for (i = 0; i < serial->num_port_pointers; ++i)
 		kfree(serial->port[i]);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 2f59ff2..ffbe601 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -384,19 +384,21 @@
 		dbg("%s - write limit hit\n", __FUNCTION__);
 		return 0;
 	}
+	priv->outstanding_urbs++;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	buffer = kmalloc (count, GFP_ATOMIC);
 	if (!buffer) {
 		dev_err(&port->dev, "out of memory\n");
-		return -ENOMEM;
+		count = -ENOMEM;
+		goto error_no_buffer;
 	}
 
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		dev_err(&port->dev, "no more free urbs\n");
-		kfree (buffer);
-		return -ENOMEM;
+		count = -ENOMEM;
+		goto error_no_urb;
 	}
 
 	memcpy (buffer, buf, count);
@@ -415,19 +417,27 @@
 		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
 			__FUNCTION__, status);
 		count = status;
-		kfree (buffer);
+		goto error;
 	} else {
 		spin_lock_irqsave(&priv->lock, flags);
-		++priv->outstanding_urbs;
 		priv->bytes_out += count;
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
 	/* we are done with this urb, so let the host driver
 	 * really free it when it is finished with it */
-	usb_free_urb (urb);
+	usb_free_urb(urb);
 
 	return count;
+error:
+	usb_free_urb(urb);
+error_no_urb:
+	kfree(buffer);
+error_no_buffer:
+	spin_lock_irqsave(&priv->lock, flags);
+	--priv->outstanding_urbs;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return count;
 }
 
 
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index bf16e9e..27c5f8f 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -1109,7 +1109,7 @@
 	command_port = port->serial->port[COMMAND_PORT];
 	command_info = usb_get_serial_port_data(command_port);
 	spin_lock_irqsave(&command_info->lock, flags);
-	command_info->command_finished = FALSE;
+	command_info->command_finished = false;
 	
 	transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
 	transfer_buffer[0] = command;
@@ -1124,12 +1124,12 @@
 	spin_unlock_irqrestore(&command_info->lock, flags);
 
 	/* wait for the command to complete */
-	wait_event_interruptible_timeout(command_info->wait_command, 
-		(command_info->command_finished != FALSE), COMMAND_TIMEOUT);
+	wait_event_interruptible_timeout(command_info->wait_command,
+		(bool)command_info->command_finished, COMMAND_TIMEOUT);
 
 	spin_lock_irqsave(&command_info->lock, flags);
 
-	if (command_info->command_finished == FALSE) {
+	if (command_info->command_finished == false) {
 		dbg("%s - command timed out.", __FUNCTION__);
 		retval = -ETIMEDOUT;
 		goto exit;
diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h
index d714eff..f160797 100644
--- a/drivers/usb/serial/whiteheat.h
+++ b/drivers/usb/serial/whiteheat.h
@@ -20,10 +20,6 @@
 #define __LINUX_USB_SERIAL_WHITEHEAT_H
 
 
-#define FALSE	0
-#define TRUE	1
-
-
 /* WhiteHEAT commands */
 #define WHITEHEAT_OPEN			1	/* open the port */
 #define WHITEHEAT_CLOSE			2	/* close the port */
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index 599ad10..06d1107 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -117,6 +117,7 @@
 static int usu_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
+	int rc;
 	unsigned long type;
 	struct task_struct* task;
 	unsigned long flags;
@@ -135,7 +136,7 @@
 
 	task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
 	if (IS_ERR(task)) {
-		int rc = PTR_ERR(task);
+		rc = PTR_ERR(task);
 		printk(KERN_WARNING "libusual: "
 		    "Unable to start the thread for %s: %d\n",
 		    bias_names[type], rc);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 70234f5..e227f64 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -153,6 +153,12 @@
 		if (us->flags & US_FL_FIX_CAPACITY)
 			sdev->fix_capacity = 1;
 
+		/* A few disks have two indistinguishable version, one of
+		 * which reports the correct capacity and the other does not.
+		 * The sd driver has to guess which is the case. */
+		if (us->flags & US_FL_CAPACITY_HEURISTICS)
+			sdev->guess_capacity = 1;
+
 		/* Some devices report a SCSI revision level above 2 but are
 		 * unable to handle the REPORT LUNS command (for which
 		 * support is mandatory at level 3).  Since we already have
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f49a62f..8b3145ab 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -146,6 +146,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Andrew Nayenko <relan@bk.ru> */
+UNUSUAL_DEV(  0x0421, 0x0019, 0x0592, 0x0592,
+		"Nokia",
+		"Nokia 6288",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_MAX_SECTORS_64 ),
+
 /* Reported by Mario Rettig <mariorettig@web.de> */
 UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
 		"Nokia",
@@ -320,6 +327,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
+/* Reported by Emil Larsson <emil@swip.net> */
+UNUSUAL_DEV(  0x04b0, 0x0411, 0x0100, 0x0100,
+		"NIKON",
+		"NIKON DSC D80",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY),
+
 /* BENQ DC5330
  * Reported by Manuel Fombuena <mfombuena@ya.com> and
  * Frank Copeland <fjc@thingy.apana.org.au> */
@@ -1101,6 +1115,15 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Submitted by Dylan Taft <d13f00l@gmail.com>
+ * US_FL_IGNORE_RESIDUE Needed
+ */
+UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
+                "AIPTEK",
+                "Aiptek USB Keychain MP3 Player",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
+                US_FL_IGNORE_RESIDUE),
+
 /* Entry needed for flags. Moreover, all devices with this ID use
  * bulk-only transport, but _some_ falsely report Control/Bulk instead.
  * One example is "Trumpion Digital Research MYMP3".
@@ -1311,12 +1334,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT ),
 
-/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+/* Reported by Jan Mate <mate@fiit.stuba.sk>
+ * and by Soeren Sonnenburg <kernel@nn7.de> */
 UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"P990i",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY ),
+		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
@@ -1347,15 +1371,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
-/* This prevents the kernel from detecting the virtual cd-drive with the
- * Windows drivers.  <johann.wilhelm@student.tugraz.at>
-*/
-UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0xffff,
-		"HUAWEI",
-		"E220 USB-UMTS Install",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_IGNORE_DEVICE),
-
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
 UNUSUAL_DEV(  0x132b, 0x000b, 0x0001, 0x0001,
 		"Minolta",
@@ -1394,6 +1409,16 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
+/*
+ * Patch by Pete Zaitcev <zaitcev@redhat.com>
+ * Report by Mark Patton. Red Hat bz#208928.
+ */
+UNUSUAL_DEV(  0x22b8, 0x4810, 0x0001, 0x0001,
+		"Motorola",
+		"RAZR V3i",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY),
+
 /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
 UNUSUAL_DEV(  0x2735, 0x100b, 0x0000, 0x9999,
 		"MPIO",
@@ -1423,7 +1448,7 @@
 		"DataStor",
 		"USB4500 FW1.04",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY),
+		US_FL_CAPACITY_HEURISTICS),
 
 /* Control/Bulk transport for all SubClass values */
 USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 7e7ec29..8e898e3 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -55,7 +55,7 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
-#include <linux/utsrelease.h>
+#include <linux/utsname.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -547,7 +547,7 @@
 				idesc->bInterfaceSubClass,
 				idesc->bInterfaceProtocol,
 				msgs[msg],
-				UTS_RELEASE);
+				utsname()->release);
 	}
 
 	return 0;
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 296b091..8432bf1 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -34,18 +34,25 @@
 };
 MODULE_DEVICE_TABLE(usb, skel_table);
 
+/* to prevent a race between open and disconnect */
+static DEFINE_MUTEX(skel_open_lock);
+
 
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE	192
 
 /* our private defines. if this grows any larger, use your own .h file */
 #define MAX_TRANSFER		(PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+   allocations > PAGE_SIZE and the number of packets in a page
+   is an integer 512 is the largest possible packet on EHCI */
 #define WRITES_IN_FLIGHT	8
+/* arbitrarily chosen */
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-	struct usb_device       *dev;			/* the usb device for this device */
-	struct usb_interface    *interface;		/* the interface for this device */
+	struct usb_device	*udev;			/* the usb device for this device */
+	struct usb_interface	*interface;		/* the interface for this device */
 	struct semaphore	limit_sem;		/* limiting the number of writes in progress */
 	unsigned char           *bulk_in_buffer;	/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
@@ -76,8 +83,10 @@
 
 	subminor = iminor(inode);
 
+	mutex_lock(&skel_open_lock);
 	interface = usb_find_interface(&skel_driver, subminor);
 	if (!interface) {
+		mutex_unlock(&skel_open_lock);
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
 		retval = -ENODEV;
@@ -86,17 +95,22 @@
 
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
+		mutex_unlock(&skel_open_lock);
 		retval = -ENODEV;
 		goto exit;
 	}
 
-	/* prevent the device from being autosuspended */
-	retval = usb_autopm_get_interface(interface);
-	if (retval)
-		goto exit;
-
 	/* increment our usage count for the device */
 	kref_get(&dev->kref);
+	/* now we can drop the lock */
+	mutex_unlock(&skel_open_lock);
+
+	/* prevent the device from being autosuspended */
+	retval = usb_autopm_get_interface(interface);
+	if (retval) {
+		kref_put(&dev->kref, skel_delete);
+		goto exit;
+	}
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
@@ -199,12 +213,6 @@
 		goto exit;
 	}
 
-	mutex_lock(&dev->io_mutex);
-	if (!dev->interface) {		/* disconnect() was called */
-		retval = -ENODEV;
-		goto error;
-	}
-
 	/* create a urb, and a buffer for it, and copy the data to the urb */
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
@@ -223,6 +231,14 @@
 		goto error;
 	}
 
+	/* this lock makes sure we don't submit URBs to gone devices */
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* disconnect() was called */
+		mutex_unlock(&dev->io_mutex);
+		retval = -ENODEV;
+		goto error;
+	}
+
 	/* initialize the urb properly */
 	usb_fill_bulk_urb(urb, dev->udev,
 			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
@@ -231,6 +247,7 @@
 
 	/* send the data out the bulk port */
 	retval = usb_submit_urb(urb, GFP_KERNEL);
+	mutex_unlock(&dev->io_mutex);
 	if (retval) {
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
 		goto error;
@@ -239,7 +256,7 @@
 	/* release our reference to this urb, the USB core will eventually free it entirely */
 	usb_free_urb(urb);
 
-	mutex_unlock(&dev->io_mutex);
+
 	return writesize;
 
 error:
@@ -247,7 +264,6 @@
 		usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
 		usb_free_urb(urb);
 	}
-	mutex_unlock(&dev->io_mutex);
 	up(&dev->limit_sem);
 
 exit:
@@ -342,6 +358,7 @@
 
 error:
 	if (dev)
+		/* this frees allocated memory */
 		kref_put(&dev->kref, skel_delete);
 	return retval;
 }
@@ -352,20 +369,21 @@
 	int minor = interface->minor;
 
 	/* prevent skel_open() from racing skel_disconnect() */
-	lock_kernel();
+	mutex_lock(&skel_open_lock);
 
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
 	/* give back our minor */
 	usb_deregister_dev(interface, &skel_class);
+	mutex_unlock(&skel_open_lock);
 
 	/* prevent more I/O from starting */
 	mutex_lock(&dev->io_mutex);
 	dev->interface = NULL;
 	mutex_unlock(&dev->io_mutex);
 
-	unlock_kernel();
+
 
 	/* decrement our usage count */
 	kref_put(&dev->kref, skel_delete);
@@ -378,6 +396,7 @@
 	.probe =	skel_probe,
 	.disconnect =	skel_disconnect,
 	.id_table =	skel_table,
+	.supports_autosuspend = 1,
 };
 
 static int __init usb_skel_init(void)