Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  [PATCH] fix sysctl_nr_open bugs
  [PATCH] sanitize anon_inode_getfd()
  [PATCH] split linux/file.h
  [PATCH] make osf_select() use core_sys_select()
  [PATCH] remove horrors with irix tty ioctls handling
  [PATCH] fix file and descriptor handling in perfmon
diff --git a/Documentation/hwmon/w83l785ts b/Documentation/hwmon/w83l785ts
index 1841ced..bd1fa9d 100644
--- a/Documentation/hwmon/w83l785ts
+++ b/Documentation/hwmon/w83l785ts
@@ -33,7 +33,8 @@
 ------------
 
 On some systems (Asus), the BIOS is known to interfere with the driver
-and cause read errors. The driver will retry a given number of times
+and cause read errors. Or maybe the W83L785TS-S chip is simply unreliable,
+we don't really know. The driver will retry a given number of times
 (5 by default) and then give up, returning the old value (or 0 if
 there is no old value). It seems to work well enough so that you should
 not notice anything. Thanks to James Bolt for helping test this feature.
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index d0ac72c..b8e52c0 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -245,6 +245,8 @@
     crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
     range=start-[end]
 
+    'start' is inclusive and 'end' is exclusive.
+
 For example:
 
     crashkernel=512M-2G:64M,2G-:128M
@@ -253,10 +255,11 @@
 
     1) if the RAM is smaller than 512M, then don't reserve anything
        (this is the "rescue" case)
-    2) if the RAM size is between 512M and 2G, then reserve 64M
+    2) if the RAM size is between 512M and 2G (exclusive), then reserve 64M
     3) if the RAM size is larger than 2G, then reserve 128M
 
 
+
 Boot into System Kernel
 =======================
 
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 4c1fc65..3be8ab2 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -131,6 +131,9 @@
 	/* Any queues attached to this device */
 	struct virtqueue *vq;
 
+	/* Handle status being finalized (ie. feature bits stable). */
+	void (*ready)(struct device *me);
+
 	/* Device-specific data. */
 	void *priv;
 };
@@ -925,24 +928,40 @@
 	write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
 }
 
-/* When the Guest asks us to reset a device, it's is fairly easy. */
-static void reset_device(struct device *dev)
+/* When the Guest tells us they updated the status field, we handle it. */
+static void update_device_status(struct device *dev)
 {
 	struct virtqueue *vq;
 
-	verbose("Resetting device %s\n", dev->name);
-	/* Clear the status. */
-	dev->desc->status = 0;
+	/* This is a reset. */
+	if (dev->desc->status == 0) {
+		verbose("Resetting device %s\n", dev->name);
 
-	/* Clear any features they've acked. */
-	memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
-	       dev->desc->feature_len);
+		/* Clear any features they've acked. */
+		memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
+		       dev->desc->feature_len);
 
-	/* Zero out the virtqueues. */
-	for (vq = dev->vq; vq; vq = vq->next) {
-		memset(vq->vring.desc, 0,
-		       vring_size(vq->config.num, getpagesize()));
-		vq->last_avail_idx = 0;
+		/* Zero out the virtqueues. */
+		for (vq = dev->vq; vq; vq = vq->next) {
+			memset(vq->vring.desc, 0,
+			       vring_size(vq->config.num, getpagesize()));
+			vq->last_avail_idx = 0;
+		}
+	} else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
+		warnx("Device %s configuration FAILED", dev->name);
+	} else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
+		unsigned int i;
+
+		verbose("Device %s OK: offered", dev->name);
+		for (i = 0; i < dev->desc->feature_len; i++)
+			verbose(" %08x", get_feature_bits(dev)[i]);
+		verbose(", accepted");
+		for (i = 0; i < dev->desc->feature_len; i++)
+			verbose(" %08x", get_feature_bits(dev)
+				[dev->desc->feature_len+i]);
+
+		if (dev->ready)
+			dev->ready(dev);
 	}
 }
 
@@ -954,9 +973,9 @@
 
 	/* Check each device and virtqueue. */
 	for (i = devices.dev; i; i = i->next) {
-		/* Notifications to device descriptors reset the device. */
+		/* Notifications to device descriptors update device status. */
 		if (from_guest_phys(addr) == i->desc) {
-			reset_device(i);
+			update_device_status(i);
 			return;
 		}
 
@@ -1170,6 +1189,7 @@
 	dev->handle_input = handle_input;
 	dev->name = name;
 	dev->vq = NULL;
+	dev->ready = NULL;
 
 	/* Append to device list.  Prepending to a single-linked list is
 	 * easier, but the user expects the devices to be arranged on the bus
@@ -1398,7 +1418,7 @@
 	struct vblk_info *vblk = dev->priv;
 	unsigned int head, out_num, in_num, wlen;
 	int ret;
-	struct virtio_blk_inhdr *in;
+	u8 *in;
 	struct virtio_blk_outhdr *out;
 	struct iovec iov[dev->vq->vring.num];
 	off64_t off;
@@ -1416,7 +1436,7 @@
 		     head, out_num, in_num);
 
 	out = convert(&iov[0], struct virtio_blk_outhdr);
-	in = convert(&iov[out_num+in_num-1], struct virtio_blk_inhdr);
+	in = convert(&iov[out_num+in_num-1], u8);
 	off = out->sector * 512;
 
 	/* The block device implements "barriers", where the Guest indicates
@@ -1430,7 +1450,7 @@
 	 * It'd be nice if we supported eject, for example, but we don't. */
 	if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
 		fprintf(stderr, "Scsi commands unsupported\n");
-		in->status = VIRTIO_BLK_S_UNSUPP;
+		*in = VIRTIO_BLK_S_UNSUPP;
 		wlen = sizeof(*in);
 	} else if (out->type & VIRTIO_BLK_T_OUT) {
 		/* Write */
@@ -1453,7 +1473,7 @@
 			errx(1, "Write past end %llu+%u", off, ret);
 		}
 		wlen = sizeof(*in);
-		in->status = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
+		*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
 	} else {
 		/* Read */
 
@@ -1466,10 +1486,10 @@
 		verbose("READ from sector %llu: %i\n", out->sector, ret);
 		if (ret >= 0) {
 			wlen = sizeof(*in) + ret;
-			in->status = VIRTIO_BLK_S_OK;
+			*in = VIRTIO_BLK_S_OK;
 		} else {
 			wlen = sizeof(*in);
-			in->status = VIRTIO_BLK_S_IOERR;
+			*in = VIRTIO_BLK_S_IOERR;
 		}
 	}
 
diff --git a/MAINTAINERS b/MAINTAINERS
index c3a533d..93547d3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1196,9 +1196,9 @@
 
 CPUSETS
 P:	Paul Jackson
-P:	Simon Derr
+P:	Paul Menage
 M:	pj@sgi.com
-M:	simon.derr@bull.net
+M:	menage@google.com
 L:	linux-kernel@vger.kernel.org
 W:	http://www.bullopensource.org/cpuset/
 S:	Supported
@@ -1557,6 +1557,14 @@
 L:	general@lists.openfabrics.org
 S:	Supported
 
+EMBEDDED LINUX
+P:	Paul Gortmaker
+M:	paul.gortmaker@windriver.com
+P	David Woodhouse
+M:	dwmw2@infradead.org
+L:	linux-embedded@vger.kernel.org
+S:	Maintained
+
 EMULEX LPFC FC SCSI DRIVER
 P:	James Smart
 M:	james.smart@emulex.com
@@ -4043,6 +4051,12 @@
 S:	Maintained
 W:	http://www.kroah.com/linux-usb/
 
+USB CYPRESS C67X00 DRIVER
+P:	Peter Korsgaard
+M:	jacmet@sunsite.dk
+L:	linux-usb@vger.kernel.org
+S:	Maintained
+
 USB DAVICOM DM9601 DRIVER
 P:	Peter Korsgaard
 M:	jacmet@sunsite.dk
diff --git a/Makefile b/Makefile
index d3634cd..5cf8258 100644
--- a/Makefile
+++ b/Makefile
@@ -794,7 +794,7 @@
 quiet_cmd_vmlinux-modpost = LD      $@
       cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@                          \
 	 $(vmlinux-init) --start-group $(vmlinux-main) --end-group             \
-	 $(filter-out $(vmlinux-init) $(vmlinux-main) $(vmlinux-lds) FORCE ,$^)
+	 $(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
 define rule_vmlinux-modpost
 	:
 	+$(call cmd,vmlinux-modpost)
@@ -818,7 +818,9 @@
 ifdef CONFIG_KALLSYMS
 .tmp_vmlinux1: vmlinux.o
 endif
-vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE
+
+modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))
+vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
 	$(call if_changed_rule,vmlinux-modpost)
 
 # The actual objects are generated when descending, 
diff --git a/arch/frv/mm/Makefile b/arch/frv/mm/Makefile
index fb8b1d8..1bca5ab 100644
--- a/arch/frv/mm/Makefile
+++ b/arch/frv/mm/Makefile
@@ -6,4 +6,4 @@
 
 obj-$(CONFIG_MMU) += \
 	pgalloc.o highmem.o fault.o extable.o cache-page.o tlb-flush.o tlb-miss.o \
-	mmu-context.o dma-alloc.o unaligned.o elf-fdpic.o
+	mmu-context.o dma-alloc.o elf-fdpic.o
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 256a7fa..b763ca1 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -463,7 +463,7 @@
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
-	set_thread_flag(TIF_RESTORE_SIGMASK);
+	set_restore_sigmask();
 	return -ERESTARTNOHAND;
 }
 
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index c7467f8..19709a0 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -966,7 +966,7 @@
 fs_initcall(acpi_map_iosapics);
 #endif				/* CONFIG_ACPI_NUMA */
 
-int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
+int __ref acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
 	int err;
 
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 6dee579..7fd18f5 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -183,10 +183,10 @@
 {
 	unsigned int irq;
 	extern void ia64_process_pending_intr(void);
-	extern void ia64_disable_timer(void);
 	extern volatile int time_keeper_id;
 
-	ia64_disable_timer();
+	/* Mask ITV to disable timer */
+	ia64_set_itv(1 << 16);
 
 	/*
 	 * Find a new timesync master
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 396004e..4547a20 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -1053,7 +1053,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block palinfo_cpu_notifier __cpuinitdata =
+static struct notifier_block __refdata palinfo_cpu_notifier =
 {
 	.notifier_call = palinfo_cpu_callback,
 	.priority = 0,
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 5740296c..19c5a78 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -464,7 +464,7 @@
 	if (!user_mode(&scr->pt))
 		return;
 
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
 		oldset = &current->saved_sigmask;
 	else
 		oldset = &current->blocked;
@@ -530,12 +530,13 @@
 		 * continue to iterate in this loop so we can deliver the SIGSEGV...
 		 */
 		if (handle_signal(signr, &ka, &info, oldset, scr)) {
-			/* a signal was successfully delivered; the saved
+			/*
+			 * A signal was successfully delivered; the saved
 			 * sigmask will have been stored in the signal frame,
 			 * and will be restored by sigreturn, so we can simply
-			 * clear the TIF_RESTORE_SIGMASK flag */
-			if (test_thread_flag(TIF_RESTORE_SIGMASK))
-				clear_thread_flag(TIF_RESTORE_SIGMASK);
+			 * clear the TS_RESTORE_SIGMASK flag.
+			 */
+			current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
 			return;
 		}
 	}
@@ -566,8 +567,8 @@
 
 	/* if there's no signal to deliver, we just put the saved sigmask
 	 * back */
-	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
+	if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
 }
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 9a9d4c4..983296f 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -98,8 +98,33 @@
 	spin_unlock_irq(&call_lock);
 }
 
+static inline void
+handle_call_data(void)
+{
+	struct call_data_struct *data;
+	void (*func)(void *info);
+	void *info;
+	int wait;
+
+	/* release the 'pointer lock' */
+	data = (struct call_data_struct *)call_data;
+	func = data->func;
+	info = data->info;
+	wait = data->wait;
+
+	mb();
+	atomic_inc(&data->started);
+	/* At this point the structure may be gone unless wait is true. */
+	(*func)(info);
+
+	/* Notify the sending CPU that the task is done. */
+	mb();
+	if (wait)
+		atomic_inc(&data->finished);
+}
+
 static void
-stop_this_cpu (void)
+stop_this_cpu(void)
 {
 	/*
 	 * Remove this CPU:
@@ -138,44 +163,21 @@
 			ops &= ~(1 << which);
 
 			switch (which) {
-			      case IPI_CALL_FUNC:
-			      {
-				      struct call_data_struct *data;
-				      void (*func)(void *info);
-				      void *info;
-				      int wait;
+			case IPI_CALL_FUNC:
+				handle_call_data();
+				break;
 
-				      /* release the 'pointer lock' */
-				      data = (struct call_data_struct *) call_data;
-				      func = data->func;
-				      info = data->info;
-				      wait = data->wait;
-
-				      mb();
-				      atomic_inc(&data->started);
-				      /*
-				       * At this point the structure may be gone unless
-				       * wait is true.
-				       */
-				      (*func)(info);
-
-				      /* Notify the sending CPU that the task is done.  */
-				      mb();
-				      if (wait)
-					      atomic_inc(&data->finished);
-			      }
-			      break;
-
-			      case IPI_CPU_STOP:
+			case IPI_CPU_STOP:
 				stop_this_cpu();
 				break;
 #ifdef CONFIG_KEXEC
-			      case IPI_KDUMP_CPU_STOP:
+			case IPI_KDUMP_CPU_STOP:
 				unw_init_running(kdump_cpu_freeze, NULL);
 				break;
 #endif
-			      default:
-				printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
+			default:
+				printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
+						this_cpu, which);
 				break;
 			}
 		} while (ops);
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 48e15a5..8c73643 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -379,11 +379,6 @@
 	.name =		"timer"
 };
 
-void __devinit ia64_disable_timer(void)
-{
-	ia64_set_itv(1 << 16);
-}
-
 void __init
 time_init (void)
 {
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index abb17a6..26228e2 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -36,9 +36,11 @@
 }
 EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
 
-int arch_register_cpu(int num)
+
+#ifdef CONFIG_HOTPLUG_CPU
+int __ref arch_register_cpu(int num)
 {
-#if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
+#ifdef CONFIG_ACPI
 	/*
 	 * If CPEI can be re-targetted or if this is not
 	 * CPEI target, then it is hotpluggable
@@ -47,19 +49,21 @@
 		sysfs_cpus[num].cpu.hotpluggable = 1;
 	map_cpu_to_node(num, node_cpuid[num].nid);
 #endif
-
 	return register_cpu(&sysfs_cpus[num].cpu, num);
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
+EXPORT_SYMBOL(arch_register_cpu);
 
 void arch_unregister_cpu(int num)
 {
 	unregister_cpu(&sysfs_cpus[num].cpu);
 	unmap_cpu_from_node(num, cpu_to_node(num));
 }
-EXPORT_SYMBOL(arch_register_cpu);
 EXPORT_SYMBOL(arch_unregister_cpu);
+#else
+static int __init arch_register_cpu(int num)
+{
+	return register_cpu(&sysfs_cpus[num].cpu, num);
+}
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 6df0732..318b811 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1,4 +1,3 @@
-
 /*
  * kvm_ia64.c: Basic KVM suppport On Itanium series processors
  *
@@ -431,7 +430,7 @@
 	if (itc_diff < 0)
 		itc_diff = -itc_diff;
 
-	expires = div64_64(itc_diff, cyc_per_usec);
+	expires = div64_u64(itc_diff, cyc_per_usec);
 	kt = ktime_set(0, 1000 * expires);
 	vcpu->arch.ht_active = 1;
 	hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS);
diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile
index 4072a07..469766b 100644
--- a/arch/m32r/Makefile
+++ b/arch/m32r/Makefile
@@ -5,6 +5,8 @@
 # architecture-specific flags and dependencies.
 #
 
+KBUILD_DEFCONFIG := m32700ut.smp_defconfig
+
 LDFLAGS		:=
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux	:=
diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig
deleted file mode 100644
index af3b981..0000000
--- a/arch/m32r/defconfig
+++ /dev/null
@@ -1,863 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc1
-# Wed Aug  1 17:22:35 2007
-#
-CONFIG_M32R=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_NO_IOPORT=y
-CONFIG_NO_DMA=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_CPUSETS is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-# CONFIG_KALLSYMS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-# CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
-# CONFIG_EPOLL is not set
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-# CONFIG_BLK_DEV_BSG is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-
-#
-# Processor type and features
-#
-# CONFIG_PLAT_MAPPI is not set
-# CONFIG_PLAT_USRV is not set
-CONFIG_PLAT_M32700UT=y
-# CONFIG_PLAT_OPSPUT is not set
-# CONFIG_PLAT_OAKS32R is not set
-# CONFIG_PLAT_MAPPI2 is not set
-# CONFIG_PLAT_MAPPI3 is not set
-# CONFIG_PLAT_M32104UT is not set
-CONFIG_CHIP_M32700=y
-# CONFIG_CHIP_M32102 is not set
-# CONFIG_CHIP_M32104 is not set
-# CONFIG_CHIP_VDEC2 is not set
-# CONFIG_CHIP_OPSP is not set
-CONFIG_MMU=y
-CONFIG_TLB_ENTRIES=32
-CONFIG_ISA_M32R2=y
-CONFIG_ISA_DSP_LEVEL2=y
-CONFIG_ISA_DUAL_ISSUE=y
-CONFIG_BUS_CLOCK=50000000
-CONFIG_TIMER_DIVIDE=128
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_MEMORY_START=0x08000000
-CONFIG_MEMORY_SIZE=0x01000000
-CONFIG_NOHIGHMEM=y
-CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-# CONFIG_FLATMEM_MANUAL is not set
-CONFIG_DISCONTIGMEM_MANUAL=y
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_DISCONTIGMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_IRAM_START=0x00f00000
-CONFIG_IRAM_SIZE=0x00080000
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_PREEMPT=y
-CONFIG_SMP=y
-# CONFIG_CHIP_M32700_TS1 is not set
-CONFIG_NR_CPUS=2
-CONFIG_NODES_SHIFT=1
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-# CONFIG_ISA is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=m
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-# CONFIG_MTD_CFI_NOSWAP is not set
-CONFIG_MTD_CFI_BE_BYTE_SWAP=y
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=m
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=m
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
-CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_PROC_FS=y
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=m
-# CONFIG_SCSI_DMA is not set
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=m
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=m
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-# CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_MD is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_PHYLIB is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_NE2000 is not set
-CONFIG_NETDEV_1000=y
-CONFIG_NETDEV_10000=y
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_M32R_SIO=y
-CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-CONFIG_SERIAL_M32R_PLDSIO=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_RTC is not set
-CONFIG_DS1302=y
-# CONFIG_R3964 is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_SM501 is not set
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_CPIA is not set
-CONFIG_VIDEO_M32R_AR=m
-CONFIG_VIDEO_M32R_AR_M64278=m
-CONFIG_RADIO_ADAPTERS=y
-# CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
-
-#
-# Graphics support
-#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB_DDC is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-
-#
-# Frame buffer hardware drivers
-#
-CONFIG_FB_S1D13XXX=y
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_LOGO_M32R_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-CONFIG_USB_SUPPORT=y
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-# CONFIG_MMC_UNSAFE_RESUME is not set
-
-#
-# MMC/SD Card Drivers
-#
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_BLOCK_BOUNCE=y
-
-#
-# MMC/SD Host Controller Drivers
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
-# CONFIG_UIO is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_FRAME_POINTER is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_HAS_IOMEM=y
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 41b0785..15a6f36 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -60,9 +60,6 @@
   . = ALIGN(4096);
   __nosave_end = .;
 
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index fd0c685..c785d07 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -87,6 +87,7 @@
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 
 	return 0;
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
index 1e7ea6a..f4782d2 100644
--- a/arch/m68knommu/kernel/entry.S
+++ b/arch/m68knommu/kernel/entry.S
@@ -32,6 +32,7 @@
 #include <asm/segment.h>
 #include <asm/asm-offsets.h>
 #include <asm/entry.h>
+#include <asm/unistd.h>
 
 .text
 
@@ -140,3 +141,11 @@
 	RESTORE_SWITCH_STACK
 	rts
 
+ENTRY(ret_from_user_signal)
+	moveq #__NR_sigreturn,%d0
+	trap #0
+
+ENTRY(ret_from_user_rt_signal)
+	move #__NR_rt_sigreturn,%d0
+	trap #0
+
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index d6f0200..03f4fe6 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -162,7 +162,7 @@
 	printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
 #endif
 #ifdef CONFIG_M5235EVB
-	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)");
+	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n");
 #endif
 
 #ifdef DEBUG
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 7037137..bbfcae9 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -51,6 +51,8 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
+void ret_from_user_signal(void);
+void ret_from_user_rt_signal(void);
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 
 /*
@@ -539,10 +541,6 @@
 	return err;
 }
 
-static inline void push_cache (unsigned long vaddr)
-{
-}
-
 static inline void *
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 {
@@ -586,16 +584,11 @@
 	err |= copy_to_user (&frame->sc, &context, sizeof(context));
 
 	/* Set up to return from userspace.  */
-	err |= __put_user(frame->retcode, &frame->pretcode);
-	/* moveq #,d0; trap #0 */
-	err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
-			  (long *)(frame->retcode));
+	err |= __put_user((void *) ret_from_user_signal, &frame->pretcode);
 
 	if (err)
 		goto give_sigsegv;
 
-	push_cache ((unsigned long) &frame->retcode);
-
 	/* Set up registers for signal handler */
 	wrusp ((unsigned long) frame);
 	regs->pc = (unsigned long) ka->sa.sa_handler;
@@ -655,17 +648,11 @@
 	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
 
 	/* Set up to return from userspace.  */
-	err |= __put_user(frame->retcode, &frame->pretcode);
-	/* moveq #,d0; notb d0; trap #0 */
-	err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
-			  (long *)(frame->retcode + 0));
-	err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
+	err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode);
 
 	if (err)
 		goto give_sigsegv;
 
-	push_cache ((unsigned long) &frame->retcode);
-
 	/* Set up registers for signal handler */
 	wrusp ((unsigned long) frame);
 	regs->pc = (unsigned long) ka->sa.sa_handler;
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index 437a061..ec9aea6 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -28,6 +28,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
+#include <linux/kallsyms.h>
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
@@ -102,56 +103,47 @@
 	force_sig(SIGSEGV, current);
 }
 
-
 int kstack_depth_to_print = 48;
 
-void show_stack(struct task_struct *task, unsigned long *stack)
+static void __show_stack(struct task_struct *task, unsigned long *stack)
 {
 	unsigned long *endstack, addr;
-	extern char _start, _etext;
+	unsigned long *last_stack;
 	int i;
 
-	if (!stack) {
-		if (task)
-			stack = (unsigned long *)task->thread.ksp;
-		else
-			stack = (unsigned long *)&stack;
-	}
+	if (!stack)
+		stack = (unsigned long *)task->thread.ksp;
 
 	addr = (unsigned long) stack;
 	endstack = (unsigned long *) PAGE_ALIGN(addr);
 
 	printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
 	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (stack + 1 > endstack)
+		if (stack + 1 + i > endstack)
 			break;
 		if (i % 8 == 0)
 			printk("\n" KERN_EMERG "       ");
-		printk(" %08lx", *stack++);
+		printk(" %08lx", *(stack + i));
 	}
 	printk("\n");
 
-	printk(KERN_EMERG "Call Trace:");
-	i = 0;
-	while (stack + 1 <= endstack) {
-		addr = *stack++;
-		/*
-		 * If the address is either in the text segment of the
-		 * kernel, or in the region which contains vmalloc'ed
-		 * memory, it *may* be the address of a calling
-		 * routine; if so, print it so that someone tracing
-		 * down the cause of the crash will be able to figure
-		 * out the call path that was taken.
-		 */
-		if (((addr >= (unsigned long) &_start) &&
-		     (addr <= (unsigned long) &_etext))) {
-			if (i % 4 == 0)
-				printk("\n" KERN_EMERG "       ");
-			printk(" [<%08lx>]", addr);
-			i++;
-		}
+#ifdef CONFIG_FRAME_POINTER
+	printk(KERN_EMERG "Call Trace:\n");
+
+	last_stack = stack - 1;
+	while (stack <= endstack && stack > last_stack) {
+
+		addr = *(stack + 1);
+		printk(KERN_EMERG " [%08lx] ", addr);
+		print_symbol(KERN_CONT "%s\n", addr);
+
+		last_stack = stack;
+		stack = (unsigned long *)*stack;
 	}
 	printk("\n");
+#else
+	printk(KERN_EMERG "CONFIG_FRAME_POINTER disabled, no symbolic call trace\n");
+#endif
 }
 
 void bad_super_trap(struct frame *fp)
@@ -298,19 +290,47 @@
 	current->thread.esp0 = ssp;
 }
 
-
 /*
  * The architecture-independent backtrace generator
  */
 void dump_stack(void)
 {
-	unsigned long stack;
+	/*
+	 * We need frame pointers for this little trick, which works as follows:
+	 *
+	 * +------------+ 0x00
+	 * | Next SP	|	-> 0x0c
+	 * +------------+ 0x04
+	 * | Caller	|
+	 * +------------+ 0x08
+	 * | Local vars	|	-> our stack var
+	 * +------------+ 0x0c
+	 * | Next SP	|	-> 0x18, that is what we pass to show_stack()
+	 * +------------+ 0x10
+	 * | Caller	|
+	 * +------------+ 0x14
+	 * | Local vars	|
+	 * +------------+ 0x18
+	 * | ...	|
+	 * +------------+
+	 */
 
-	show_stack(current, &stack);
+	unsigned long *stack;
+
+	stack = (unsigned long *)&stack;
+	stack++;
+	__show_stack(current, stack);
 }
-
 EXPORT_SYMBOL(dump_stack);
 
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	if (!stack && !task)
+		dump_stack();
+	else
+		__show_stack(task, stack);
+}
+
 #ifdef CONFIG_M68KFPU_EMU
 asmlinkage void fpemu_signal(int signal, int code, void *addr)
 {
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index b44edb0..5592e0b 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -64,6 +64,7 @@
 		_stext = . ;
 		TEXT_TEXT
 		SCHED_TEXT
+		LOCK_TEXT
         	*(.text.lock)
 
 		. = ALIGN(16);          /* Exception table              */
@@ -73,6 +74,7 @@
 
 		*(.rodata) *(.rodata.*)
 		*(__vermagic)		/* Kernel version magic */
+		*(__markers_strings)
 		*(.rodata1)
 		*(.rodata.str1.1)
 
@@ -182,6 +184,7 @@
 		*(COMMON)
 		. = ALIGN(4) ;
 		_ebss = . ;
+	 	_end = . ;
 	} > BSS
 
 }
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
index a6692e9..d01a5d2 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68knommu/platform/5206e/config.c
@@ -48,7 +48,7 @@
 
 /***************************************************************************/
 
-static void __init m5206_uart_init_line(int line, int irq)
+static void __init m5206e_uart_init_line(int line, int irq)
 {
 	if (line == 0) {
 		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index 2aca599..230bae6 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -139,10 +139,6 @@
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
 	commandp[size-1] = 0;
-#elif defined(CONFIG_MTD_KeyTechnology)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0xffe06000, size);
-	commandp[size-1] = 0;
 #elif defined(CONFIG_CANCam)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0010000, size);
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index 036e1b7..dfdb5c2e 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -26,9 +26,240 @@
 #include <asm/mcfuart.h>
 #include <asm/mcfqspi.h>
 
+#ifdef CONFIG_MTD_PARTITIONS
+#include <linux/mtd/partitions.h>
+#endif
+
 /***************************************************************************/
 
 void coldfire_reset(void);
+static void coldfire_qspi_cs_control(u8 cs, u8 command);
+
+/***************************************************************************/
+
+#if defined(CONFIG_SPI)
+
+#if defined(CONFIG_WILDFIRE)
+#define SPI_NUM_CHIPSELECTS 	0x02
+#define SPI_PAR_VAL		0x07  /* Enable DIN, DOUT, CLK */
+#define SPI_CS_MASK		0x18
+
+#define FLASH_BLOCKSIZE		(1024*64)
+#define FLASH_NUMBLOCKS		16
+#define FLASH_TYPE		"m25p80"
+
+#define M25P80_CS		0
+#define MMC_CS			1
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition stm25p_partitions[] = {
+	/* sflash */
+	[0] = {
+		.name = "stm25p80",
+		.offset = 0x00000000,
+		.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS,
+		.mask_flags = 0
+	}
+};
+
+#endif
+
+#elif defined(CONFIG_WILDFIREMOD)
+
+#define SPI_NUM_CHIPSELECTS	0x08
+#define SPI_PAR_VAL		0x07  /* Enable DIN, DOUT, CLK */
+#define SPI_CS_MASK		0x78
+
+#define FLASH_BLOCKSIZE		(1024*64)
+#define FLASH_NUMBLOCKS		64
+#define FLASH_TYPE		"m25p32"
+/* Reserve 1M for the kernel parition */
+#define FLASH_KERNEL_SIZE   (1024 * 1024)
+
+#define M25P80_CS		5
+#define MMC_CS			6
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition stm25p_partitions[] = {
+	/* sflash */
+	[0] = {
+		.name = "kernel",
+		.offset = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS - FLASH_KERNEL_SIZE,
+		.size = FLASH_KERNEL_SIZE,
+		.mask_flags = 0
+	},
+	[1] = {
+		.name = "image",
+		.offset = 0x00000000,
+		.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS - FLASH_KERNEL_SIZE,
+		.mask_flags = 0
+	},
+	[2] = {
+		.name = "all",
+		.offset = 0x00000000,
+		.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS,
+		.mask_flags = 0
+	}
+};
+#endif
+
+#else
+#define SPI_NUM_CHIPSELECTS 	0x04
+#define SPI_PAR_VAL		0x7F  /* Enable DIN, DOUT, CLK, CS0 - CS4 */
+#endif
+
+#ifdef MMC_CS
+static struct coldfire_spi_chip flash_chip_info = {
+	.mode = SPI_MODE_0,
+	.bits_per_word = 16,
+	.del_cs_to_clk = 17,
+	.del_after_trans = 1,
+	.void_write_data = 0
+};
+
+static struct coldfire_spi_chip mmc_chip_info = {
+	.mode = SPI_MODE_0,
+	.bits_per_word = 16,
+	.del_cs_to_clk = 17,
+	.del_after_trans = 1,
+	.void_write_data = 0xFFFF
+};
+#endif
+
+#ifdef M25P80_CS
+static struct flash_platform_data stm25p80_platform_data = {
+	.name = "ST M25P80 SPI Flash chip",
+#ifdef CONFIG_MTD_PARTITIONS
+	.parts = stm25p_partitions,
+	.nr_parts = sizeof(stm25p_partitions) / sizeof(*stm25p_partitions),
+#endif
+	.type = FLASH_TYPE
+};
+#endif
+
+static struct spi_board_info spi_board_info[] __initdata = {
+#ifdef M25P80_CS
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 16000000,
+		.bus_num = 1,
+		.chip_select = M25P80_CS,
+		.platform_data = &stm25p80_platform_data,
+		.controller_data = &flash_chip_info
+	},
+#endif
+#ifdef MMC_CS
+	{
+		.modalias = "mmc_spi",
+		.max_speed_hz = 16000000,
+		.bus_num = 1,
+		.chip_select = MMC_CS,
+		.controller_data = &mmc_chip_info
+	}
+#endif
+};
+
+static struct coldfire_spi_master coldfire_master_info = {
+	.bus_num = 1,
+	.num_chipselect = SPI_NUM_CHIPSELECTS,
+	.irq_source = MCF5282_QSPI_IRQ_SOURCE,
+	.irq_vector = MCF5282_QSPI_IRQ_VECTOR,
+	.irq_mask = ((0x01 << MCF5282_QSPI_IRQ_SOURCE) | 0x01),
+	.irq_lp = 0x2B,  /* Level 5 and Priority 3 */
+	.par_val = SPI_PAR_VAL,
+	.cs_control = coldfire_qspi_cs_control,
+};
+
+static struct resource coldfire_spi_resources[] = {
+	[0] = {
+		.name = "qspi-par",
+		.start = MCF5282_QSPI_PAR,
+		.end = MCF5282_QSPI_PAR,
+		.flags = IORESOURCE_MEM
+	},
+
+	[1] = {
+		.name = "qspi-module",
+		.start = MCF5282_QSPI_QMR,
+		.end = MCF5282_QSPI_QMR + 0x18,
+		.flags = IORESOURCE_MEM
+	},
+
+	[2] = {
+		.name = "qspi-int-level",
+		.start = MCF5282_INTC0 + MCFINTC_ICR0 + MCF5282_QSPI_IRQ_SOURCE,
+		.end = MCF5282_INTC0 + MCFINTC_ICR0 + MCF5282_QSPI_IRQ_SOURCE,
+		.flags = IORESOURCE_MEM
+	},
+
+	[3] = {
+		.name = "qspi-int-mask",
+		.start = MCF5282_INTC0 + MCFINTC_IMRL,
+		.end = MCF5282_INTC0 + MCFINTC_IMRL,
+		.flags = IORESOURCE_MEM
+	}
+};
+
+static struct platform_device coldfire_spi = {
+	.name = "spi_coldfire",
+	.id = -1,
+	.resource = coldfire_spi_resources,
+	.num_resources = ARRAY_SIZE(coldfire_spi_resources),
+	.dev = {
+		.platform_data = &coldfire_master_info,
+	}
+};
+
+static void coldfire_qspi_cs_control(u8 cs, u8 command)
+{
+	u8 cs_bit = ((0x01 << cs) << 3) & SPI_CS_MASK;
+
+#if defined(CONFIG_WILDFIRE)
+	u8 cs_mask = ~(((0x01 << cs) << 3) & SPI_CS_MASK);
+#endif
+#if defined(CONFIG_WILDFIREMOD)
+	u8 cs_mask = (cs << 3) & SPI_CS_MASK;
+#endif
+
+	/*
+	 * Don't do anything if the chip select is not
+	 * one of the port qs pins.
+	 */
+	if (command & QSPI_CS_INIT) {
+#if defined(CONFIG_WILDFIRE)
+		MCF5282_GPIO_DDRQS  |= cs_bit;
+		MCF5282_GPIO_PQSPAR &= ~cs_bit;
+#endif
+
+#if defined(CONFIG_WILDFIREMOD)
+		MCF5282_GPIO_DDRQS  |= SPI_CS_MASK;
+		MCF5282_GPIO_PQSPAR &= ~SPI_CS_MASK;
+#endif
+	}
+
+	if (command & QSPI_CS_ASSERT) {
+		MCF5282_GPIO_PORTQS &= ~SPI_CS_MASK;
+		MCF5282_GPIO_PORTQS |= cs_mask;
+	} else if (command & QSPI_CS_DROP) {
+		MCF5282_GPIO_PORTQS |= SPI_CS_MASK;
+	}
+}
+
+static int __init spi_dev_init(void)
+{
+	int retval;
+
+	retval = platform_device_register(&coldfire_spi);
+	if (retval < 0)
+		return retval;
+
+	if (ARRAY_SIZE(spi_board_info))
+		retval = spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+	return retval;
+}
+
+#endif /* CONFIG_SPI */
 
 /***************************************************************************/
 
@@ -111,10 +342,43 @@
 
 /***************************************************************************/
 
+#ifdef CONFIG_WILDFIRE
+void wildfire_halt(void)
+{
+	writeb(0, 0x30000007);
+	writeb(0x2, 0x30000007);
+}
+#endif
+
+#ifdef CONFIG_WILDFIREMOD
+void wildfiremod_halt(void)
+{
+	printk(KERN_INFO "WildFireMod hibernating...\n");
+
+	/* Set portE.5 to Digital IO */
+	MCF5282_GPIO_PEPAR &= ~(1 << (5 * 2));
+
+	/* Make portE.5 an output */
+	MCF5282_GPIO_DDRE |= (1 << 5);
+
+	/* Now toggle portE.5 from low to high */
+	MCF5282_GPIO_PORTE &= ~(1 << 5);
+	MCF5282_GPIO_PORTE |= (1 << 5);
+
+	printk(KERN_EMERG "Failed to hibernate. Halting!\n");
+}
+#endif
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_disableall();
-	mach_reset = coldfire_reset;
+
+#ifdef CONFIG_WILDFIRE
+	mach_halt = wildfire_halt;
+#endif
+#ifdef CONFIG_WILDFIREMOD
+	mach_halt = wildfiremod_halt;
+#endif
 }
 
 /***************************************************************************/
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index 92dc862..11cff66 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -124,8 +124,7 @@
 	mcf_setimr(MCFSIM_IMR_MASKALL);
 
 #if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-      defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
-      defined(CONFIG_CLEOPATRA)
+    defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
 	commandp[size-1] = 0;
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index 111b66d..1e3c0dc 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -103,9 +103,26 @@
 	addql	#4,%sp
 
 ret_from_exception:
+	move	#0x2700,%sr		/* disable intrs */
 	btst	#5,%sp@(PT_SR)		/* check if returning to kernel */
 	jeq	Luser_return		/* if so, skip resched, signals */
 
+#ifdef CONFIG_PREEMPT
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
+	movel	%d1,%a0
+	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
+	andl	#_TIF_NEED_RESCHED,%d1
+	jeq	Lkernel_return
+
+	movel	%a0@(TI_PREEMPTCOUNT),%d1
+	cmpl	#0,%d1
+	jne	Lkernel_return
+
+	pea	Lkernel_return
+	jmp	preempt_schedule_irq	/* preempt the kernel */
+#endif
+
 Lkernel_return:
 	moveml	%sp@,%d1-%d5/%a0-%a2
 	lea	%sp@(32),%sp		/* space for 8 regs */
@@ -140,6 +157,7 @@
 
 Lwork_to_do:
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
+	move	#0x2000,%sr		/* enable intrs again */
 	btst	#TIF_NEED_RESCHED,%d1
 	jne	reschedule
 
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
index 77db347..9fdd8bc 100644
--- a/arch/mips/kernel/binfmt_elfn32.c
+++ b/arch/mips/kernel/binfmt_elfn32.c
@@ -54,6 +54,7 @@
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
+#include <linux/math64.h>
 
 #define elf_prstatus elf_prstatus32
 struct elf_prstatus32
@@ -102,8 +103,8 @@
 	 * one divide.
 	 */
 	u64 nsec = (u64)jiffies * TICK_NSEC;
-	long rem;
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &rem);
+	u32 rem;
+	value->tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
 	value->tv_usec = rem / NSEC_PER_USEC;
 }
 
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 08f4cd7..e1333d7 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -56,6 +56,7 @@
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
+#include <linux/math64.h>
 
 #define elf_prstatus elf_prstatus32
 struct elf_prstatus32
@@ -104,8 +105,8 @@
 	 * one divide.
 	 */
 	u64 nsec = (u64)jiffies * TICK_NSEC;
-	long rem;
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &rem);
+	u32 rem;
+	value->tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
 	value->tv_usec = rem / NSEC_PER_USEC;
 }
 
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 3b26fbd6..73401e8 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -149,7 +149,7 @@
 u64 tb_to_xs;
 unsigned tb_to_us;
 
-#define TICKLEN_SCALE	TICK_LENGTH_SHIFT
+#define TICKLEN_SCALE	NTP_SCALE_SHIFT
 u64 last_tick_len;	/* units are ns / 2^TICKLEN_SCALE */
 u64 ticklen_to_xs;	/* 0.64 fraction */
 
@@ -1007,8 +1007,6 @@
 	vdso_data->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
 	vdso_data->tb_to_xs = tb_to_xs;
 
-	time_freq = 0;
-
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	/* Register the clocksource, if we're not running on iSeries */
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 361e316..4c943ea 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -35,7 +35,7 @@
 #include "i8254.h"
 
 #ifndef CONFIG_X86_64
-#define mod_64(x, y) ((x) - (y) * div64_64(x, y))
+#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
 #else
 #define mod_64(x, y) ((x) % (y))
 #endif
@@ -60,8 +60,8 @@
 	rl = (u64)u.l.low * (u64)b;
 	rh = (u64)u.l.high * (u64)b;
 	rh += (rl >> 32);
-	res.l.high = div64_64(rh, c);
-	res.l.low = div64_64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
+	res.l.high = div64_u64(rh, c);
+	res.l.low = div64_u64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
 	return res.ll;
 }
 
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57ac4e4..36809d7 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -25,13 +25,13 @@
 #include <linux/hrtimer.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/math64.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/page.h>
 #include <asm/current.h>
 #include <asm/apicdef.h>
 #include <asm/atomic.h>
-#include <asm/div64.h>
 #include "irq.h"
 
 #define PRId64 "d"
@@ -526,8 +526,8 @@
 	} else
 		passed = ktime_sub(now, apic->timer.last_update);
 
-	counter_passed = div64_64(ktime_to_ns(passed),
-				  (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
+	counter_passed = div64_u64(ktime_to_ns(passed),
+				   (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
 
 	if (counter_passed > tmcct) {
 		if (unlikely(!apic_lvtt_period(apic))) {
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index 66e5528..a09ead1 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -26,8 +26,7 @@
 {
 	if (ordered & (QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH) &&
 	    prepare_flush_fn == NULL) {
-		printk(KERN_ERR "%s: prepare_flush_fn required\n",
-								__FUNCTION__);
+		printk(KERN_ERR "%s: prepare_flush_fn required\n", __func__);
 		return -EINVAL;
 	}
 
diff --git a/block/blk-core.c b/block/blk-core.c
index 5d09f8c..b754a4a 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -136,7 +136,7 @@
 
 		if (unlikely(nbytes > bio->bi_size)) {
 			printk(KERN_ERR "%s: want %u bytes done, %u left\n",
-			       __FUNCTION__, nbytes, bio->bi_size);
+			       __func__, nbytes, bio->bi_size);
 			nbytes = bio->bi_size;
 		}
 
@@ -1566,8 +1566,7 @@
 			if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
 				blk_dump_rq_flags(req, "__end_that");
 				printk(KERN_ERR "%s: bio idx %d >= vcnt %d\n",
-						__FUNCTION__, bio->bi_idx,
-						bio->bi_vcnt);
+				       __func__, bio->bi_idx, bio->bi_vcnt);
 				break;
 			}
 
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 6089384..bb93d4c 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -168,8 +168,8 @@
 {
 	if ((max_sectors << 9) < PAGE_CACHE_SIZE) {
 		max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
-		printk(KERN_INFO "%s: set to minimum %d\n", __FUNCTION__,
-							max_sectors);
+		printk(KERN_INFO "%s: set to minimum %d\n",
+		       __func__, max_sectors);
 	}
 
 	if (BLK_DEF_MAX_SECTORS > max_sectors)
@@ -196,8 +196,8 @@
 {
 	if (!max_segments) {
 		max_segments = 1;
-		printk(KERN_INFO "%s: set to minimum %d\n", __FUNCTION__,
-							max_segments);
+		printk(KERN_INFO "%s: set to minimum %d\n",
+		       __func__, max_segments);
 	}
 
 	q->max_phys_segments = max_segments;
@@ -220,8 +220,8 @@
 {
 	if (!max_segments) {
 		max_segments = 1;
-		printk(KERN_INFO "%s: set to minimum %d\n", __FUNCTION__,
-							max_segments);
+		printk(KERN_INFO "%s: set to minimum %d\n",
+		       __func__, max_segments);
 	}
 
 	q->max_hw_segments = max_segments;
@@ -241,8 +241,8 @@
 {
 	if (max_size < PAGE_CACHE_SIZE) {
 		max_size = PAGE_CACHE_SIZE;
-		printk(KERN_INFO "%s: set to minimum %d\n", __FUNCTION__,
-							max_size);
+		printk(KERN_INFO "%s: set to minimum %d\n",
+		       __func__, max_size);
 	}
 
 	q->max_segment_size = max_size;
@@ -357,8 +357,8 @@
 {
 	if (mask < PAGE_CACHE_SIZE - 1) {
 		mask = PAGE_CACHE_SIZE - 1;
-		printk(KERN_INFO "%s: set to minimum %lx\n", __FUNCTION__,
-							mask);
+		printk(KERN_INFO "%s: set to minimum %lx\n",
+		       __func__, mask);
 	}
 
 	q->seg_boundary_mask = mask;
diff --git a/block/blk-tag.c b/block/blk-tag.c
index e176ddb..de64e04 100644
--- a/block/blk-tag.c
+++ b/block/blk-tag.c
@@ -112,7 +112,7 @@
 	if (q && depth > q->nr_requests * 2) {
 		depth = q->nr_requests * 2;
 		printk(KERN_ERR "%s: adjusted depth to %d\n",
-				__FUNCTION__, depth);
+		       __func__, depth);
 	}
 
 	tag_index = kzalloc(depth * sizeof(struct request *), GFP_ATOMIC);
@@ -296,13 +296,13 @@
 
 	if (unlikely(bqt->tag_index[tag] == NULL))
 		printk(KERN_ERR "%s: tag %d is missing\n",
-		       __FUNCTION__, tag);
+		       __func__, tag);
 
 	bqt->tag_index[tag] = NULL;
 
 	if (unlikely(!test_bit(tag, bqt->tag_map))) {
 		printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
-		       __FUNCTION__, tag);
+		       __func__, tag);
 		return;
 	}
 	/*
@@ -340,7 +340,7 @@
 	if (unlikely((rq->cmd_flags & REQ_QUEUED))) {
 		printk(KERN_ERR
 		       "%s: request %p for device [%s] already tagged %d",
-		       __FUNCTION__, rq,
+		       __func__, rq,
 		       rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
 		BUG();
 	}
diff --git a/block/bsg.c b/block/bsg.c
index 23ea4fd..fa796b6 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -57,7 +57,7 @@
 #undef BSG_DEBUG
 
 #ifdef BSG_DEBUG
-#define dprintk(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ##args)
+#define dprintk(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ##args)
 #else
 #define dprintk(fmt, args...)
 #endif
diff --git a/block/elevator.c b/block/elevator.c
index ac5310e..980f8ae 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -650,7 +650,7 @@
 
 	default:
 		printk(KERN_ERR "%s: bad insertion point %d\n",
-		       __FUNCTION__, where);
+		       __func__, where);
 		BUG();
 	}
 
@@ -808,8 +808,7 @@
 			rq->cmd_flags |= REQ_QUIET;
 			end_queued_request(rq, 0);
 		} else {
-			printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,
-								ret);
+			printk(KERN_ERR "%s: bad return=%d\n", __func__, ret);
 			break;
 		}
 	}
diff --git a/crypto/authenc.c b/crypto/authenc.c
index ed8ac5a..4b22676 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -217,9 +217,10 @@
 					   int err)
 {
 	if (!err) {
-		struct aead_givcrypt_request *greq = req->data;
+		struct aead_request *areq = req->data;
+		struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
 
-		err = crypto_authenc_genicv(&greq->areq, greq->giv, 0);
+		err = crypto_authenc_genicv(areq, greq->giv, 0);
 	}
 
 	aead_request_complete(req->data, err);
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 2504252..b150de5 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -190,8 +190,10 @@
 	int err;
 
 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
-	if (IS_ERR(inst))
+	if (!inst) {
+		inst = ERR_PTR(-ENOMEM);
 		goto out;
+	}
 
 	err = -ENAMETOOLONG;
 	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index b14f14e..881d309 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -136,7 +136,8 @@
 	}
 
 	ablkcipher_request_set_crypt(subreq, reqctx->src, dst,
-				     req->creq.nbytes, req->creq.info);
+				     req->creq.nbytes + ivsize,
+				     req->creq.info);
 
 	memcpy(req->creq.info, ctx->salt, ivsize);
 
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 6fe4174..e38dfed 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -18,7 +18,7 @@
 };
 EXPORT_SYMBOL(cpu_sysdev_class);
 
-static struct sys_device *cpu_sys_devices[NR_CPUS];
+static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
 
 #ifdef CONFIG_HOTPLUG_CPU
 static ssize_t show_online(struct sys_device *dev, char *buf)
@@ -68,7 +68,7 @@
 	sysdev_remove_file(&cpu->sysdev, &attr_online);
 
 	sysdev_unregister(&cpu->sysdev);
-	cpu_sys_devices[logical_cpu] = NULL;
+	per_cpu(cpu_sys_devices, logical_cpu) = NULL;
 	return;
 }
 #else /* ... !CONFIG_HOTPLUG_CPU */
@@ -167,7 +167,7 @@
 	if (!error && cpu->hotpluggable)
 		register_cpu_control(cpu);
 	if (!error)
-		cpu_sys_devices[num] = &cpu->sysdev;
+		per_cpu(cpu_sys_devices, num) = &cpu->sysdev;
 	if (!error)
 		register_cpu_under_node(num, cpu_to_node(num));
 
@@ -180,8 +180,8 @@
 
 struct sys_device *get_cpu_sysdev(unsigned cpu)
 {
-	if (cpu < NR_CPUS)
-		return cpu_sys_devices[cpu];
+	if (cpu < nr_cpu_ids && cpu_possible(cpu))
+		return per_cpu(cpu_sys_devices, cpu);
 	else
 		return NULL;
 }
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index e539be5..e336b05 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -428,13 +428,9 @@
 		proc_cciss = proc_mkdir("driver/cciss", NULL);
 	if (!proc_cciss)
 		return;
-	pde = proc_create(hba[i]->devname, S_IWUSR | S_IRUSR | S_IRGRP |
+	pde = proc_create_data(hba[i]->devname, S_IWUSR | S_IRUSR | S_IRGRP |
 					S_IROTH, proc_cciss,
-					&cciss_proc_fops);
-	if (!pde)
-		return;
-
-	pde->data = hba[i];
+					&cciss_proc_fops, hba[i]);
 }
 #endif				/* CONFIG_PROC_FS */
 
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index e322cce..3a281ef 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -205,6 +205,7 @@
 	unsigned char key, asc, ascq;	/* May be valid if error==-EIO */
 
 	int stat_count;			/* Retries getting status. */
+	unsigned int timeo;		/* jiffies until rq->timeout changes */
 
 	unsigned int len;		/* Requested length */
 	unsigned int current_sg;
@@ -318,6 +319,7 @@
 	int openc;			/* protected by ub_lock! */
 					/* kref is too implicit for our taste */
 	int reset;			/* Reset is running */
+	int bad_resid;
 	unsigned int tagcnt;
 	char name[12];
 	struct usb_device *dev;
@@ -764,6 +766,12 @@
 	cmd->cdb_len = rq->cmd_len;
 
 	cmd->len = rq->data_len;
+
+	/*
+	 * To reapply this to every URB is not as incorrect as it looks.
+	 * In return, we avoid any complicated tracking calculations.
+	 */
+	cmd->timeo = rq->timeout;
 }
 
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
@@ -785,10 +793,6 @@
 			scsi_status = 0;
 		} else {
 			if (cmd->act_len != cmd->len) {
-				if ((cmd->key == MEDIUM_ERROR ||
-				     cmd->key == UNIT_ATTENTION) &&
-				    ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
-					return;
 				scsi_status = SAM_STAT_CHECK_CONDITION;
 			} else {
 				scsi_status = 0;
@@ -804,7 +808,10 @@
 			else
 				scsi_status = DID_ERROR << 16;
 		} else {
-			if (cmd->error == -EIO) {
+			if (cmd->error == -EIO &&
+			    (cmd->key == 0 ||
+			     cmd->key == MEDIUM_ERROR ||
+			     cmd->key == UNIT_ATTENTION)) {
 				if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
 					return;
 			}
@@ -1259,14 +1266,19 @@
 			return;
 		}
 
-		len = le32_to_cpu(bcs->Residue);
-		if (len != cmd->len - cmd->act_len) {
-			/*
-			 * It is all right to transfer less, the caller has
-			 * to check. But it's not all right if the device
-			 * counts disagree with our counts.
-			 */
-			goto Bad_End;
+		if (!sc->bad_resid) {
+			len = le32_to_cpu(bcs->Residue);
+			if (len != cmd->len - cmd->act_len) {
+				/*
+				 * Only start ignoring if this cmd ended well.
+				 */
+				if (cmd->len == cmd->act_len) {
+					printk(KERN_NOTICE "%s: "
+					    "bad residual %d of %d, ignoring\n",
+					    sc->name, len, cmd->len);
+					sc->bad_resid = 1;
+				}
+			}
 		}
 
 		switch (bcs->Status) {
@@ -1297,8 +1309,7 @@
 		ub_state_done(sc, cmd, -EIO);
 
 	} else {
-		printk(KERN_WARNING "%s: "
-		    "wrong command state %d\n",
+		printk(KERN_WARNING "%s: wrong command state %d\n",
 		    sc->name, cmd->state);
 		ub_state_done(sc, cmd, -EINVAL);
 		return;
@@ -1336,7 +1347,10 @@
 		return;
 	}
 
-	sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
+	if (cmd->timeo)
+		sc->work_timer.expires = jiffies + cmd->timeo;
+	else
+		sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
 	add_timer(&sc->work_timer);
 
 	cmd->state = UB_CMDST_DATA;
@@ -1376,7 +1390,10 @@
 		return -1;
 	}
 
-	sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT;
+	if (cmd->timeo)
+		sc->work_timer.expires = jiffies + cmd->timeo;
+	else
+		sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT;
 	add_timer(&sc->work_timer);
 	return 0;
 }
@@ -1515,8 +1532,7 @@
 		return;
 	}
 	if (cmd->state != UB_CMDST_SENSE) {
-		printk(KERN_WARNING "%s: "
-		    "sense done with bad cmd state %d\n",
+		printk(KERN_WARNING "%s: sense done with bad cmd state %d\n",
 		    sc->name, cmd->state);
 		return;
 	}
@@ -1720,7 +1736,7 @@
 }
 
 /*
- * This is called once a new disk was seen by the block layer or by ub_probe().
+ * This is called by check_disk_change if we reported a media change.
  * The main onjective here is to discover the features of the media such as
  * the capacity, read-only status, etc. USB storage generally does not
  * need to be spun up, but if we needed it, this would be the place.
@@ -2136,8 +2152,7 @@
 	}
 
 	if (ep_in == NULL || ep_out == NULL) {
-		printk(KERN_NOTICE "%s: failed endpoint check\n",
-		    sc->name);
+		printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name);
 		return -ENODEV;
 	}
 
@@ -2354,7 +2369,7 @@
 	spin_unlock_irqrestore(&ub_lock, flags);
 
 	/*
-	 * Fence stall clearnings, operations triggered by unlinkings and so on.
+	 * Fence stall clearings, operations triggered by unlinkings and so on.
 	 * We do not attempt to unlink any URBs, because we do not trust the
 	 * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
 	 */
@@ -2417,7 +2432,7 @@
 	spin_unlock_irqrestore(sc->lock, flags);
 
 	/*
-	 * There is virtually no chance that other CPU runs times so long
+	 * There is virtually no chance that other CPU runs a timeout so long
 	 * after ub_urb_complete should have called del_timer, but only if HCD
 	 * didn't forget to deliver a callback on unlink.
 	 */
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 0cfbe8c..84e064f 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -35,7 +35,7 @@
 	struct list_head list;
 	struct request *req;
 	struct virtio_blk_outhdr out_hdr;
-	struct virtio_blk_inhdr in_hdr;
+	u8 status;
 };
 
 static void blk_done(struct virtqueue *vq)
@@ -48,7 +48,7 @@
 	spin_lock_irqsave(&vblk->lock, flags);
 	while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
 		int uptodate;
-		switch (vbr->in_hdr.status) {
+		switch (vbr->status) {
 		case VIRTIO_BLK_S_OK:
 			uptodate = 1;
 			break;
@@ -101,7 +101,7 @@
 	sg_init_table(vblk->sg, VIRTIO_MAX_SG);
 	sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
 	num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
-	sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr));
+	sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status));
 
 	if (rq_data_dir(vbr->req) == WRITE) {
 		vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
@@ -157,10 +157,25 @@
 /* We provide getgeo only to please some old bootloader/partitioning tools */
 static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
 {
-	/* some standard values, similar to sd */
-	geo->heads = 1 << 6;
-	geo->sectors = 1 << 5;
-	geo->cylinders = get_capacity(bd->bd_disk) >> 11;
+	struct virtio_blk *vblk = bd->bd_disk->private_data;
+	struct virtio_blk_geometry vgeo;
+	int err;
+
+	/* see if the host passed in geometry config */
+	err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY,
+				offsetof(struct virtio_blk_config, geometry),
+				&vgeo);
+
+	if (!err) {
+		geo->heads = vgeo.heads;
+		geo->sectors = vgeo.sectors;
+		geo->cylinders = vgeo.cylinders;
+	} else {
+		/* some standard values, similar to sd */
+		geo->heads = 1 << 6;
+		geo->sectors = 1 << 5;
+		geo->cylinders = get_capacity(bd->bd_disk) >> 11;
+	}
 	return 0;
 }
 
@@ -242,12 +257,12 @@
 	index++;
 
 	/* If barriers are supported, tell block layer that queue is ordered */
-	if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER))
+	if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER))
 		blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
 
 	/* Host must always specify the capacity. */
-	__virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity),
-			    &cap);
+	vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
+			  &cap, sizeof(cap));
 
 	/* If capacity is too big, truncate with warning. */
 	if ((sector_t)cap != cap) {
@@ -289,7 +304,6 @@
 static void virtblk_remove(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
-	int major = vblk->disk->major;
 
 	/* Nothing should be pending. */
 	BUG_ON(!list_empty(&vblk->reqs));
@@ -299,7 +313,6 @@
 
 	blk_cleanup_queue(vblk->disk->queue);
 	put_disk(vblk->disk);
-	unregister_blkdev(major, "virtblk");
 	mempool_destroy(vblk->pool);
 	vdev->config->del_vq(vblk->vq);
 	kfree(vblk);
@@ -310,7 +323,14 @@
 	{ 0 },
 };
 
+static unsigned int features[] = {
+	VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
+	VIRTIO_BLK_F_GEOMETRY,
+};
+
 static struct virtio_driver virtio_blk = {
+	.feature_table = features,
+	.feature_table_size = ARRAY_SIZE(features),
 	.driver.name =	KBUILD_MODNAME,
 	.driver.owner =	THIS_MODULE,
 	.id_table =	id_table,
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index f49037b..b60d425 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -77,6 +77,10 @@
 module_param(power_status, bool, 0600);
 MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
 
+static int fan_mult = I8K_FAN_MULT;
+module_param(fan_mult, int, 0);
+MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
+
 static int i8k_open_fs(struct inode *inode, struct file *file);
 static int i8k_ioctl(struct inode *, struct file *, unsigned int,
 		     unsigned long);
@@ -239,7 +243,7 @@
 	struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
 
 	regs.ebx = fan & 0xff;
-	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * I8K_FAN_MULT;
+	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * fan_mult;
 }
 
 /*
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index d83db5d8..192961f 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -30,6 +30,8 @@
 #include <linux/miscdevice.h>
 #include <linux/posix-timers.h>
 #include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/math64.h>
 
 #include <asm/uaccess.h>
 #include <asm/sn/addrs.h>
@@ -472,8 +474,8 @@
 
 	nsec = rtc_time() * sgi_clock_period
 			+ sgi_clock_offset.tv_nsec;
-	tp->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tp->tv_nsec)
-			+ sgi_clock_offset.tv_sec;
+	*tp = ns_to_timespec(nsec);
+	tp->tv_sec += sgi_clock_offset.tv_sec;
 	return 0;
 };
 
@@ -481,11 +483,11 @@
 {
 
 	u64 nsec;
-	u64 rem;
+	u32 rem;
 
 	nsec = rtc_time() * sgi_clock_period;
 
-	sgi_clock_offset.tv_sec = tp->tv_sec - div_long_long_rem(nsec, NSEC_PER_SEC, &rem);
+	sgi_clock_offset.tv_sec = tp->tv_sec - div_u64_rem(nsec, NSEC_PER_SEC, &rem);
 
 	if (rem <= tp->tv_nsec)
 		sgi_clock_offset.tv_nsec = tp->tv_sec - rem;
@@ -644,9 +646,6 @@
 	return 0;
 }
 
-#define timespec_to_ns(x) ((x).tv_nsec + (x).tv_sec * NSEC_PER_SEC)
-#define ns_to_timespec(ts, nsec) (ts).tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &(ts).tv_nsec)
-
 /* Assumption: it_lock is already held with irq's disabled */
 static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 {
@@ -659,9 +658,8 @@
 		return;
 	}
 
-	ns_to_timespec(cur_setting->it_interval, timr->it.mmtimer.incr * sgi_clock_period);
-	ns_to_timespec(cur_setting->it_value, (timr->it.mmtimer.expires - rtc_time())* sgi_clock_period);
-	return;
+	cur_setting->it_interval = ns_to_timespec(timr->it.mmtimer.incr * sgi_clock_period);
+	cur_setting->it_value = ns_to_timespec((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
 }
 
 
@@ -679,8 +677,8 @@
 		sgi_timer_get(timr, old_setting);
 
 	sgi_timer_del(timr);
-	when = timespec_to_ns(new_setting->it_value);
-	period = timespec_to_ns(new_setting->it_interval);
+	when = timespec_to_ns(&new_setting->it_value);
+	period = timespec_to_ns(&new_setting->it_interval);
 
 	if (when == 0)
 		/* Clear timer */
@@ -695,7 +693,7 @@
 		unsigned long now;
 
 		getnstimeofday(&n);
-		now = timespec_to_ns(n);
+		now = timespec_to_ns(&n);
 		if (when > now)
 			when -= now;
 		else
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 513b7c2..ac5080d 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2028,13 +2028,13 @@
  */
 static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+	struct mgsl_struct *info = tty->driver_data;
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
-	if ( debug_level >= DEBUG_LEVEL_INFO ) {
-		printk( "%s(%d):mgsl_put_char(%d) on %s\n",
-			__FILE__,__LINE__,ch,info->device_name);
+	if (debug_level >= DEBUG_LEVEL_INFO) {
+		printk(KERN_DEBUG "%s(%d):mgsl_put_char(%d) on %s\n",
+			__FILE__, __LINE__, ch, info->device_name);
 	}		
 	
 	if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
@@ -2043,9 +2043,9 @@
 	if (!tty || !info->xmit_buf)
 		return 0;
 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
+	spin_lock_irqsave(&info->irq_spinlock, flags);
 	
-	if ( (info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active ) {
+	if ((info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active) {
 		if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
 			info->xmit_buf[info->xmit_head++] = ch;
 			info->xmit_head &= SERIAL_XMIT_SIZE-1;
@@ -2053,7 +2053,7 @@
 			ret = 1;
 		}
 	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
 	return ret;
 	
 }	/* end of mgsl_put_char() */
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 2a999373..62e3c91 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -784,7 +784,7 @@
 		kfree(lu);
 	}
 	scsi_remove_host(shost);
-	fw_notify("released %s\n", tgt->bus_id);
+	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
 
 	fw_unit_put(tgt->unit);
 	scsi_host_put(shost);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 5a99e81..93f9167 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -30,6 +30,8 @@
 	{ "pca9537", 4, },
 	{ "pca9538", 8, },
 	{ "pca9539", 16, },
+	{ "pca9555", 16, },
+	{ "pca9557", 8, },
 	/* REVISIT several pca955x parts should work here too */
 	{ }
 };
@@ -193,7 +195,7 @@
 {
 	struct pca953x_platform_data *pdata;
 	struct pca953x_chip *chip;
-	int ret, i;
+	int ret;
 
 	pdata = client->dev.platform_data;
 	if (pdata == NULL)
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
index 9587869..c1009d6 100644
--- a/drivers/hwmon/adt7473.c
+++ b/drivers/hwmon/adt7473.c
@@ -422,18 +422,14 @@
  * number in the range -128 to 127, or as an unsigned number that must
  * be offset by 64.
  */
-static int decode_temp(struct adt7473_data *data, u8 raw)
+static int decode_temp(u8 twos_complement, u8 raw)
 {
-	if (data->temp_twos_complement)
-		return (s8)raw;
-	return raw - 64;
+	return twos_complement ? (s8)raw : raw - 64;
 }
 
-static u8 encode_temp(struct adt7473_data *data, int cooked)
+static u8 encode_temp(u8 twos_complement, int cooked)
 {
-	if (data->temp_twos_complement)
-		return (cooked & 0xFF);
-	return cooked + 64;
+	return twos_complement ? cooked & 0xFF : cooked + 64;
 }
 
 static ssize_t show_temp_min(struct device *dev,
@@ -442,8 +438,9 @@
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       1000 * decode_temp(data, data->temp_min[attr->index]));
+	return sprintf(buf, "%d\n", 1000 * decode_temp(
+						data->temp_twos_complement,
+						data->temp_min[attr->index]));
 }
 
 static ssize_t set_temp_min(struct device *dev,
@@ -455,7 +452,7 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adt7473_data *data = i2c_get_clientdata(client);
 	int temp = simple_strtol(buf, NULL, 10) / 1000;
-	temp = encode_temp(data, temp);
+	temp = encode_temp(data->temp_twos_complement, temp);
 
 	mutex_lock(&data->lock);
 	data->temp_min[attr->index] = temp;
@@ -472,8 +469,9 @@
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       1000 * decode_temp(data, data->temp_max[attr->index]));
+	return sprintf(buf, "%d\n", 1000 * decode_temp(
+						data->temp_twos_complement,
+						data->temp_max[attr->index]));
 }
 
 static ssize_t set_temp_max(struct device *dev,
@@ -485,7 +483,7 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adt7473_data *data = i2c_get_clientdata(client);
 	int temp = simple_strtol(buf, NULL, 10) / 1000;
-	temp = encode_temp(data, temp);
+	temp = encode_temp(data->temp_twos_complement, temp);
 
 	mutex_lock(&data->lock);
 	data->temp_max[attr->index] = temp;
@@ -501,8 +499,9 @@
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       1000 * decode_temp(data, data->temp[attr->index]));
+	return sprintf(buf, "%d\n", 1000 * decode_temp(
+						data->temp_twos_complement,
+						data->temp[attr->index]));
 }
 
 static ssize_t show_fan_min(struct device *dev,
@@ -671,8 +670,9 @@
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       1000 * decode_temp(data, data->temp_tmax[attr->index]));
+	return sprintf(buf, "%d\n", 1000 * decode_temp(
+						data->temp_twos_complement,
+						data->temp_tmax[attr->index]));
 }
 
 static ssize_t set_temp_tmax(struct device *dev,
@@ -684,7 +684,7 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adt7473_data *data = i2c_get_clientdata(client);
 	int temp = simple_strtol(buf, NULL, 10) / 1000;
-	temp = encode_temp(data, temp);
+	temp = encode_temp(data->temp_twos_complement, temp);
 
 	mutex_lock(&data->lock);
 	data->temp_tmax[attr->index] = temp;
@@ -701,8 +701,9 @@
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       1000 * decode_temp(data, data->temp_tmin[attr->index]));
+	return sprintf(buf, "%d\n", 1000 * decode_temp(
+						data->temp_twos_complement,
+						data->temp_tmin[attr->index]));
 }
 
 static ssize_t set_temp_tmin(struct device *dev,
@@ -714,7 +715,7 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adt7473_data *data = i2c_get_clientdata(client);
 	int temp = simple_strtol(buf, NULL, 10) / 1000;
-	temp = encode_temp(data, temp);
+	temp = encode_temp(data->temp_twos_complement, temp);
 
 	mutex_lock(&data->lock);
 	data->temp_tmin[attr->index] = temp;
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 84712a2..fe2eea4 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -953,12 +953,8 @@
 static void asb100_init_client(struct i2c_client *client)
 {
 	struct asb100_data *data = i2c_get_clientdata(client);
-	int vid = 0;
 
-	vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
-	vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
 	data->vrm = vid_which_vrm();
-	vid = vid_from_reg(vid, data->vrm);
 
 	/* Start monitoring */
 	asb100_write_value(client, ASB100_REG_CONFIG,
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 115f409..fa76969 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -248,7 +248,7 @@
 
 /* All registers are word-sized, except for the configuration register.
    LM75 uses a high-byte first convention, which is exactly opposite to
-   the usual practice. */
+   the SMBus standard. */
 static int lm75_read_value(struct i2c_client *client, u8 reg)
 {
 	if (reg == LM75_REG_CONF)
@@ -257,9 +257,6 @@
 		return swab16(i2c_smbus_read_word_data(client, reg));
 }
 
-/* All registers are word-sized, except for the configuration register.
-   LM75 uses a high-byte first convention, which is exactly opposite to
-   the usual practice. */
 static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if (reg == LM75_REG_CONF)
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index f61d8f4..eb03544 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -335,11 +335,23 @@
 static int __init smsc47b397_find(unsigned short *addr)
 {
 	u8 id, rev;
+	char *name;
 
 	superio_enter();
 	id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
-	if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) {
+	switch(id) {
+	case 0x81:
+		name = "SCH5307-NS";
+		break;
+	case 0x6f:
+		name = "LPC47B397-NC";
+		break;
+	case 0x85:
+	case 0x8c:
+		name = "SCH5317";
+		break;
+	default:
 		superio_exit();
 		return -ENODEV;
 	}
@@ -352,8 +364,7 @@
 
 	printk(KERN_INFO DRVNAME ": found SMSC %s "
 		"(base address 0x%04x, revision %u)\n",
-		id == 0x81 ? "SCH5307-NS" : id == 0x85 ? "SCH5317" :
-	       "LPC47B397-NC", *addr, rev);
+		name, *addr, rev);
 
 	superio_exit();
 	return 0;
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index ee35af9..ed3c019 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -1024,10 +1024,9 @@
 	SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
 	SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
 };
+static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm);
 
 static struct sensor_device_attribute_2 sda_single_files[] = {
-	SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
-		      NOT_USED, NOT_USED),
 	SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
 		      store_chassis_clear, ALARM_STATUS, 30),
 	SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable,
@@ -1080,6 +1079,7 @@
 
 		for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
 			device_remove_file(dev, &w83793_vid[i].dev_attr);
+		device_remove_file(dev, &dev_attr_vrm);
 
 		for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
 			device_remove_file(dev, &w83793_left_fan[i].dev_attr);
@@ -1282,7 +1282,6 @@
 	/* Initialize the chip */
 	w83793_init_client(client);
 
-	data->vrm = vid_which_vrm();
 	/*
 	   Only fan 1-5 has their own input pins,
 	   Pwm 1-3 has their own pins
@@ -1293,7 +1292,9 @@
 	val = w83793_read_value(client, W83793_REG_FANIN_CTRL);
 
 	/* check the function of pins 49-56 */
-	if (!(tmp & 0x80)) {
+	if (tmp & 0x80) {
+		data->has_vid |= 0x2;	/* has VIDB */
+	} else {
 		data->has_pwm |= 0x18;	/* pwm 4,5 */
 		if (val & 0x01) {	/* fan 6 */
 			data->has_fan |= 0x20;
@@ -1309,13 +1310,15 @@
 		}
 	}
 
+	/* check the function of pins 37-40 */
+	if (!(tmp & 0x29))
+		data->has_vid |= 0x1;	/* has VIDA */
 	if (0x08 == (tmp & 0x0c)) {
 		if (val & 0x08)	/* fan 9 */
 			data->has_fan |= 0x100;
 		if (val & 0x10)	/* fan 10 */
 			data->has_fan |= 0x200;
 	}
-
 	if (0x20 == (tmp & 0x30)) {
 		if (val & 0x20)	/* fan 11 */
 			data->has_fan |= 0x400;
@@ -1359,13 +1362,6 @@
 	if (tmp & 0x02)
 		data->has_temp |= 0x20;
 
-	/* Detect the VID usage and ignore unused input */
-	tmp = w83793_read_value(client, W83793_REG_MFC);
-	if (!(tmp & 0x29))
-		data->has_vid |= 0x1;	/* has VIDA */
-	if (tmp & 0x80)
-		data->has_vid |= 0x2;	/* has VIDB */
-
 	/* Register sysfs hooks */
 	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
 		err = device_create_file(dev,
@@ -1381,6 +1377,12 @@
 		if (err)
 			goto exit_remove;
 	}
+	if (data->has_vid) {
+		data->vrm = vid_which_vrm();
+		err = device_create_file(dev, &dev_attr_vrm);
+		if (err)
+			goto exit_remove;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
 		err = device_create_file(dev, &sda_single_files[i].dev_attr);
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 77f2d48..52e268e 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -301,8 +301,8 @@
 		msleep(i);
 	}
 
-	dev_err(&client->dev, "Couldn't read value from register 0x%02x. "
-		"Please report.\n", reg);
+	dev_err(&client->dev, "Couldn't read value from register 0x%02x.\n",
+		reg);
 	return defval;
 }
 
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 099a0fe..591deda 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1347,7 +1347,8 @@
 	    (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
 		hwif->irq = port ? 15 : 14;
 
-	hwif->host_flags = d->host_flags;
+	/* ->host_flags may be set by ->init_iops (or even earlier...) */
+	hwif->host_flags |= d->host_flags;
 	hwif->pio_mask = d->pio_mask;
 
 	/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 29d833e..05710c7 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -520,8 +520,11 @@
 	char *scratch = buf;
 
 	driver = container_of(drv, struct hpsb_protocol_driver, driver);
+	id = driver->id_table;
+	if (!id)
+		return 0;
 
-	for (id = driver->id_table; id->match_flags != 0; id++) {
+	for (; id->match_flags != 0; id++) {
 		int need_coma = 0;
 
 		if (id->match_flags & IEEE1394_MATCH_VENDOR_ID) {
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 877be99..15906d0 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -405,7 +405,8 @@
 		sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
 		if ((card->procconf = (void *) proc_create(conf_name,
 						S_IFREG | S_IRUGO | S_IWUSR,
-						hysdn_proc_entry)) != NULL) {
+						hysdn_proc_entry,
+						&conf_fops)) != NULL) {
 			hysdn_proclog_init(card);	/* init the log file entry */
 		}
 		card = card->next;	/* next entry */
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 2bc9bf7..8080249 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -85,27 +85,34 @@
 		+ desc->config_len;
 }
 
-/* This tests (and acknowleges) a feature bit. */
-static bool lg_feature(struct virtio_device *vdev, unsigned fbit)
+/* This gets the device's feature bits. */
+static u32 lg_get_features(struct virtio_device *vdev)
 {
+	unsigned int i;
+	u32 features = 0;
 	struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
-	u8 *features;
+	u8 *in_features = lg_features(desc);
 
-	/* Obviously if they ask for a feature off the end of our feature
-	 * bitmap, it's not set. */
-	if (fbit / 8 > desc->feature_len)
-		return false;
+	/* We do this the slow but generic way. */
+	for (i = 0; i < min(desc->feature_len * 8, 32); i++)
+		if (in_features[i / 8] & (1 << (i % 8)))
+			features |= (1 << i);
 
-	/* The feature bitmap comes after the virtqueues. */
-	features = lg_features(desc);
-	if (!(features[fbit / 8] & (1 << (fbit % 8))))
-		return false;
+	return features;
+}
 
-	/* We set the matching bit in the other half of the bitmap to tell the
-	 * Host we want to use this feature.  We don't use this yet, but we
-	 * could in future. */
-	features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
-	return true;
+static void lg_set_features(struct virtio_device *vdev, u32 features)
+{
+	unsigned int i;
+	struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+	/* Second half of bitmap is features we accept. */
+	u8 *out_features = lg_features(desc) + desc->feature_len;
+
+	memset(out_features, 0, desc->feature_len);
+	for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
+		if (features & (1 << i))
+			out_features[i / 8] |= (1 << (i % 8));
+	}
 }
 
 /* Once they've found a field, getting a copy of it is easy. */
@@ -137,22 +144,28 @@
 	return to_lgdev(vdev)->desc->status;
 }
 
-static void lg_set_status(struct virtio_device *vdev, u8 status)
-{
-	BUG_ON(!status);
-	to_lgdev(vdev)->desc->status = status;
-}
-
-/* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor
- * address of the device.  The Host will zero the status and all the
- * features. */
-static void lg_reset(struct virtio_device *vdev)
+/* To notify on status updates, we (ab)use the NOTIFY hypercall, with the
+ * descriptor address of the device.  A zero status means "reset". */
+static void set_status(struct virtio_device *vdev, u8 status)
 {
 	unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
 
+	/* We set the status. */
+	to_lgdev(vdev)->desc->status = status;
 	hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0);
 }
 
+static void lg_set_status(struct virtio_device *vdev, u8 status)
+{
+	BUG_ON(!status);
+	set_status(vdev, status);
+}
+
+static void lg_reset(struct virtio_device *vdev)
+{
+	set_status(vdev, 0);
+}
+
 /*
  * Virtqueues
  *
@@ -286,7 +299,8 @@
 
 /* The ops structure which hooks everything together. */
 static struct virtio_config_ops lguest_config_ops = {
-	.feature = lg_feature,
+	.get_features = lg_get_features,
+	.set_features = lg_set_features,
 	.get = lg_get,
 	.set = lg_set,
 	.get_status = lg_get_status,
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 645e6e0..e73a000 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -102,7 +102,7 @@
 static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
 {
 	/* We have a limited number the number of CPUs in the lguest struct. */
-	if (id >= NR_CPUS)
+	if (id >= ARRAY_SIZE(cpu->lg->cpus))
 		return -EINVAL;
 
 	/* Set up this CPU's id, and pointer back to the lguest struct. */
@@ -251,8 +251,6 @@
 		if (!lg || (cpu_id >= lg->nr_cpus))
 			return -EINVAL;
 		cpu = &lg->cpus[cpu_id];
-		if (!cpu)
-			return -EINVAL;
 
 		/* Once the Guest is dead, you can only read() why it died. */
 		if (lg->dead)
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index e812df6..fcd1aec 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -82,9 +82,8 @@
 static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **);
 
 static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
-		     size_t *retlen, u_char **mtdbuf);
-static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
-			size_t len);
+		     size_t *retlen, void **virt, resource_size_t *phys);
+static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
 
 static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
 static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
@@ -1240,7 +1239,8 @@
 	return ret;
 }
 
-static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
+static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, void **virt, resource_size_t *phys)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -1257,8 +1257,10 @@
 	chipnum = (from >> cfi->chipshift);
 	ofs = from - (chipnum << cfi->chipshift);
 
-	*mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
+	*virt = map->virt + cfi->chips[chipnum].start + ofs;
 	*retlen = 0;
+	if (phys)
+		*phys = map->phys + cfi->chips[chipnum].start + ofs;
 
 	while (len) {
 		unsigned long thislen;
@@ -1291,7 +1293,7 @@
 	return 0;
 }
 
-static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
+static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index bf485ff..0399be1 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -48,18 +48,21 @@
 }
 
 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
-		size_t *retlen, u_char **mtdbuf)
+		size_t *retlen, void **virt, resource_size_t *phys)
 {
 	if (from + len > mtd->size)
 		return -EINVAL;
 
-	*mtdbuf = mtd->priv + from;
+	/* can we return a physical address with this driver? */
+	if (phys)
+		return -EINVAL;
+
+	*virt = mtd->priv + from;
 	*retlen = len;
 	return 0;
 }
 
-static void ram_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
-		size_t len)
+static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 }
 
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 5f96018..c7987b1 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -57,20 +57,21 @@
 }
 
 static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
-		size_t *retlen, u_char **mtdbuf)
+		size_t *retlen, void **virt, resource_size_t *phys)
 {
-	u_char *start = mtd->priv;
-
 	if (from + len > mtd->size)
 		return -EINVAL;
 
-	*mtdbuf = start + from;
+	/* can we return a physical address with this driver? */
+	if (phys)
+		return -EINVAL;
+
+	*virt = mtd->priv + from;
 	*retlen = len;
 	return 0;
 }
 
-static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from,
-		size_t len)
+static void phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 }
 
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 7060a08..bc99817 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -134,7 +134,8 @@
 	eoff_lo = end & (priv->asize - 1);
 	soff_lo = instr->addr & (priv->asize - 1);
 
-	pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr);
+	pmc551_point(mtd, instr->addr, instr->len, &retlen,
+		     (void **)&ptr, NULL);
 
 	if (soff_hi == eoff_hi || mtd->size == priv->asize) {
 		/* The whole thing fits within one access, so just one shot
@@ -154,7 +155,8 @@
 			}
 			soff_hi += priv->asize;
 			pmc551_point(mtd, (priv->base_map0 | soff_hi),
-				     priv->asize, &retlen, &ptr);
+				     priv->asize, &retlen,
+				     (void **)&ptr, NULL);
 		}
 		memset(ptr, 0xff, eoff_lo);
 	}
@@ -170,7 +172,7 @@
 }
 
 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
-			size_t * retlen, u_char ** mtdbuf)
+			size_t *retlen, void **virt, resource_size_t *phys)
 {
 	struct mypriv *priv = mtd->priv;
 	u32 soff_hi;
@@ -188,6 +190,10 @@
 		return -EINVAL;
 	}
 
+	/* can we return a physical address with this driver? */
+	if (phys)
+		return -EINVAL;
+
 	soff_hi = from & ~(priv->asize - 1);
 	soff_lo = from & (priv->asize - 1);
 
@@ -198,13 +204,12 @@
 		priv->curr_map0 = soff_hi;
 	}
 
-	*mtdbuf = priv->start + soff_lo;
+	*virt = priv->start + soff_lo;
 	*retlen = len;
 	return 0;
 }
 
-static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
-			   size_t len)
+static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 #ifdef CONFIG_MTD_PMC551_DEBUG
 	printk(KERN_DEBUG "pmc551_unpoint()\n");
@@ -242,7 +247,7 @@
 	soff_lo = from & (priv->asize - 1);
 	eoff_lo = end & (priv->asize - 1);
 
-	pmc551_point(mtd, from, len, retlen, &ptr);
+	pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
 
 	if (soff_hi == eoff_hi) {
 		/* The whole thing fits within one access, so just one shot
@@ -263,7 +268,8 @@
 				goto out;
 			}
 			soff_hi += priv->asize;
-			pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
+			pmc551_point(mtd, soff_hi, priv->asize, retlen,
+				     (void **)&ptr, NULL);
 		}
 		memcpy(copyto, ptr, eoff_lo);
 		copyto += eoff_lo;
@@ -308,7 +314,7 @@
 	soff_lo = to & (priv->asize - 1);
 	eoff_lo = end & (priv->asize - 1);
 
-	pmc551_point(mtd, to, len, retlen, &ptr);
+	pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
 
 	if (soff_hi == eoff_hi) {
 		/* The whole thing fits within one access, so just one shot
@@ -329,7 +335,8 @@
 				goto out;
 			}
 			soff_hi += priv->asize;
-			pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
+			pmc551_point(mtd, soff_hi, priv->asize, retlen,
+				     (void **)&ptr, NULL);
 		}
 		memcpy(ptr, copyfrom, eoff_lo);
 		copyfrom += eoff_lo;
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index d293add..cb86db7 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -76,8 +76,9 @@
 static slram_mtd_list_t *slram_mtdlist = NULL;
 
 static int slram_erase(struct mtd_info *, struct erase_info *);
-static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, u_char **);
-static void slram_unpoint(struct mtd_info *, u_char *, loff_t,	size_t);
+static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **,
+		resource_size_t *);
+static void slram_unpoint(struct mtd_info *, loff_t, size_t);
 static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 
@@ -104,19 +105,23 @@
 }
 
 static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
-		size_t *retlen, u_char **mtdbuf)
+		size_t *retlen, void **virt, resource_size_t *phys)
 {
 	slram_priv_t *priv = mtd->priv;
 
+	/* can we return a physical address with this driver? */
+	if (phys)
+		return -EINVAL;
+
 	if (from + len > mtd->size)
 		return -EINVAL;
 
-	*mtdbuf = priv->start + from;
+	*virt = priv->start + from;
 	*retlen = len;
 	return(0);
 }
 
-static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
+static void slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 }
 
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 14ffb1a..c42f4b8 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -40,10 +40,12 @@
 /****************************************************************************/
 
 int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, u_char **mtdbuf)
+	size_t *retlen, void **virt, resource_size_t *phys)
 {
 	struct map_info *map = mtd->priv;
-	*mtdbuf = (u_char *) (map->virt + ((int) from));
+	*virt = map->virt + from;
+	if (phys)
+		*phys = map->phys + from;
 	*retlen = len;
 	return(0);
 }
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index c66902d..07c7011 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -68,7 +68,7 @@
 }
 
 static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
-			size_t *retlen, u_char **buf)
+			size_t *retlen, void **virt, resource_size_t *phys)
 {
 	struct mtd_part *part = PART(mtd);
 	if (from >= mtd->size)
@@ -76,14 +76,14 @@
 	else if (from + len > mtd->size)
 		len = mtd->size - from;
 	return part->master->point (part->master, from + part->offset,
-				    len, retlen, buf);
+				    len, retlen, virt, phys);
 }
 
-static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
+static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_part *part = PART(mtd);
 
-	part->master->unpoint (part->master, addr, from + part->offset, len);
+	part->master->unpoint(part->master, from + part->offset, len);
 }
 
 static int part_read_oob(struct mtd_info *mtd, loff_t from,
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
index 414ceae..0adb287 100644
--- a/drivers/mtd/nand/at91_nand.c
+++ b/drivers/mtd/nand/at91_nand.c
@@ -94,6 +94,24 @@
 };
 
 /*
+ * Enable NAND.
+ */
+static void at91_nand_enable(struct at91_nand_host *host)
+{
+	if (host->board->enable_pin)
+		at91_set_gpio_value(host->board->enable_pin, 0);
+}
+
+/*
+ * Disable NAND.
+ */
+static void at91_nand_disable(struct at91_nand_host *host)
+{
+	if (host->board->enable_pin)
+		at91_set_gpio_value(host->board->enable_pin, 1);
+}
+
+/*
  * Hardware specific access to control-lines
  */
 static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -101,11 +119,11 @@
 	struct nand_chip *nand_chip = mtd->priv;
 	struct at91_nand_host *host = nand_chip->priv;
 
-	if (host->board->enable_pin && (ctrl & NAND_CTRL_CHANGE)) {
+	if (ctrl & NAND_CTRL_CHANGE) {
 		if (ctrl & NAND_NCE)
-			at91_set_gpio_value(host->board->enable_pin, 0);
+			at91_nand_enable(host);
 		else
-			at91_set_gpio_value(host->board->enable_pin, 1);
+			at91_nand_disable(host);
 	}
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -128,24 +146,6 @@
 }
 
 /*
- * Enable NAND.
- */
-static void at91_nand_enable(struct at91_nand_host *host)
-{
-	if (host->board->enable_pin)
-		at91_set_gpio_value(host->board->enable_pin, 0);
-}
-
-/*
- * Disable NAND.
- */
-static void at91_nand_disable(struct at91_nand_host *host)
-{
-	if (host->board->enable_pin)
-		at91_set_gpio_value(host->board->enable_pin, 1);
-}
-
-/*
  * write oob for small pages
  */
 static int at91_nand_write_oob_512(struct mtd_info *mtd,
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index d7a3ea8..32a4f17 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -67,6 +67,10 @@
 #define	FEC_MAX_PORTS	1
 #endif
 
+#if defined(CONFIG_FADS) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_M5272)
+#define HAVE_mii_link_interrupt
+#endif
+
 /*
  * Define the fixed address of the FEC hardware.
  */
@@ -205,7 +209,10 @@
 	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
 	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
 	uint	tx_full;
-	spinlock_t lock;
+	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
+	spinlock_t hw_lock;
+	/* hold while accessing the mii_list_t() elements */
+	spinlock_t mii_lock;
 
 	uint	phy_id;
 	uint	phy_id_done;
@@ -309,6 +316,7 @@
 	volatile fec_t	*fecp;
 	volatile cbd_t	*bdp;
 	unsigned short	status;
+	unsigned long flags;
 
 	fep = netdev_priv(dev);
 	fecp = (volatile fec_t*)dev->base_addr;
@@ -318,6 +326,7 @@
 		return 1;
 	}
 
+	spin_lock_irqsave(&fep->hw_lock, flags);
 	/* Fill in a Tx ring entry */
 	bdp = fep->cur_tx;
 
@@ -328,6 +337,7 @@
 		 * This should not happen, since dev->tbusy should be set.
 		 */
 		printk("%s: tx queue full!.\n", dev->name);
+		spin_unlock_irqrestore(&fep->hw_lock, flags);
 		return 1;
 	}
 #endif
@@ -366,8 +376,6 @@
 	flush_dcache_range((unsigned long)skb->data,
 			   (unsigned long)skb->data + skb->len);
 
-	spin_lock_irq(&fep->lock);
-
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
 	 */
@@ -396,7 +404,7 @@
 
 	fep->cur_tx = (cbd_t *)bdp;
 
-	spin_unlock_irq(&fep->lock);
+	spin_unlock_irqrestore(&fep->hw_lock, flags);
 
 	return 0;
 }
@@ -454,19 +462,20 @@
 	struct	net_device *dev = dev_id;
 	volatile fec_t	*fecp;
 	uint	int_events;
-	int handled = 0;
+	irqreturn_t ret = IRQ_NONE;
 
 	fecp = (volatile fec_t*)dev->base_addr;
 
 	/* Get the interrupt events that caused us to be here.
 	*/
-	while ((int_events = fecp->fec_ievent) != 0) {
+	do {
+		int_events = fecp->fec_ievent;
 		fecp->fec_ievent = int_events;
 
 		/* Handle receive event in its own function.
 		 */
 		if (int_events & FEC_ENET_RXF) {
-			handled = 1;
+			ret = IRQ_HANDLED;
 			fec_enet_rx(dev);
 		}
 
@@ -475,17 +484,18 @@
 		   them as part of the transmit process.
 		*/
 		if (int_events & FEC_ENET_TXF) {
-			handled = 1;
+			ret = IRQ_HANDLED;
 			fec_enet_tx(dev);
 		}
 
 		if (int_events & FEC_ENET_MII) {
-			handled = 1;
+			ret = IRQ_HANDLED;
 			fec_enet_mii(dev);
 		}
 
-	}
-	return IRQ_RETVAL(handled);
+	} while (int_events);
+
+	return ret;
 }
 
 
@@ -498,7 +508,7 @@
 	struct	sk_buff	*skb;
 
 	fep = netdev_priv(dev);
-	spin_lock(&fep->lock);
+	spin_lock_irq(&fep->hw_lock);
 	bdp = fep->dirty_tx;
 
 	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
@@ -557,7 +567,7 @@
 		}
 	}
 	fep->dirty_tx = (cbd_t *)bdp;
-	spin_unlock(&fep->lock);
+	spin_unlock_irq(&fep->hw_lock);
 }
 
 
@@ -584,6 +594,8 @@
 	fep = netdev_priv(dev);
 	fecp = (volatile fec_t*)dev->base_addr;
 
+	spin_lock_irq(&fep->hw_lock);
+
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
 	 */
@@ -689,6 +701,8 @@
 	 */
 	fecp->fec_r_des_active = 0;
 #endif
+
+	spin_unlock_irq(&fep->hw_lock);
 }
 
 
@@ -702,11 +716,11 @@
 	uint		mii_reg;
 
 	fep = netdev_priv(dev);
+	spin_lock_irq(&fep->mii_lock);
+
 	ep = fep->hwp;
 	mii_reg = ep->fec_mii_data;
 
-	spin_lock(&fep->lock);
-
 	if ((mip = mii_head) == NULL) {
 		printk("MII and no head!\n");
 		goto unlock;
@@ -723,7 +737,7 @@
 		ep->fec_mii_data = mip->mii_regval;
 
 unlock:
-	spin_unlock(&fep->lock);
+	spin_unlock_irq(&fep->mii_lock);
 }
 
 static int
@@ -737,12 +751,11 @@
 	/* Add PHY address to register command.
 	*/
 	fep = netdev_priv(dev);
+	spin_lock_irqsave(&fep->mii_lock, flags);
+
 	regval |= fep->phy_addr << 23;
-
 	retval = 0;
 
-	spin_lock_irqsave(&fep->lock,flags);
-
 	if ((mip = mii_free) != NULL) {
 		mii_free = mip->mii_next;
 		mip->mii_regval = regval;
@@ -759,9 +772,8 @@
 		retval = 1;
 	}
 
-	spin_unlock_irqrestore(&fep->lock,flags);
-
-	return(retval);
+	spin_unlock_irqrestore(&fep->mii_lock, flags);
+	return retval;
 }
 
 static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
@@ -1222,7 +1234,7 @@
 };
 
 /* ------------------------------------------------------------------------- */
-#if !defined(CONFIG_M532x)
+#ifdef HAVE_mii_link_interrupt
 #ifdef CONFIG_RPXCLASSIC
 static void
 mii_link_interrupt(void *dev_id);
@@ -1362,18 +1374,8 @@
 		unsigned short irq;
 	} *idp, id[] = {
 		{ "fec(TXF)", 23 },
-		{ "fec(TXB)", 24 },
-		{ "fec(TXFIFO)", 25 },
-		{ "fec(TXCR)", 26 },
 		{ "fec(RXF)", 27 },
-		{ "fec(RXB)", 28 },
 		{ "fec(MII)", 29 },
-		{ "fec(LC)", 30 },
-		{ "fec(HBERR)", 31 },
-		{ "fec(GRA)", 32 },
-		{ "fec(EBERR)", 33 },
-		{ "fec(BABT)", 34 },
-		{ "fec(BABR)", 35 },
 		{ NULL },
 	};
 
@@ -1533,18 +1535,8 @@
 		unsigned short irq;
 	} *idp, id[] = {
 		{ "fec(TXF)", 23 },
-		{ "fec(TXB)", 24 },
-		{ "fec(TXFIFO)", 25 },
-		{ "fec(TXCR)", 26 },
 		{ "fec(RXF)", 27 },
-		{ "fec(RXB)", 28 },
 		{ "fec(MII)", 29 },
-		{ "fec(LC)", 30 },
-		{ "fec(HBERR)", 31 },
-		{ "fec(GRA)", 32 },
-		{ "fec(EBERR)", 33 },
-		{ "fec(BABT)", 34 },
-		{ "fec(BABR)", 35 },
 		{ NULL },
 	};
 
@@ -1660,18 +1652,8 @@
 		unsigned short irq;
 	} *idp, id[] = {
 	    { "fec(TXF)", 36 },
-	    { "fec(TXB)", 37 },
-	    { "fec(TXFIFO)", 38 },
-	    { "fec(TXCR)", 39 },
 	    { "fec(RXF)", 40 },
-	    { "fec(RXB)", 41 },
 	    { "fec(MII)", 42 },
-	    { "fec(LC)", 43 },
-	    { "fec(HBERR)", 44 },
-	    { "fec(GRA)", 45 },
-	    { "fec(EBERR)", 46 },
-	    { "fec(BABT)", 47 },
-	    { "fec(BABR)", 48 },
 	    { NULL },
 	};
 
@@ -2126,6 +2108,7 @@
 
 /* This interrupt occurs when the PHY detects a link change.
 */
+#ifdef HAVE_mii_link_interrupt
 #ifdef CONFIG_RPXCLASSIC
 static void
 mii_link_interrupt(void *dev_id)
@@ -2148,6 +2131,7 @@
 
 	return IRQ_HANDLED;
 }
+#endif
 
 static int
 fec_enet_open(struct net_device *dev)
@@ -2243,13 +2227,13 @@
 			/* Catch all multicast addresses, so set the
 			 * filter to all 1's.
 			 */
-			ep->fec_hash_table_high = 0xffffffff;
-			ep->fec_hash_table_low = 0xffffffff;
+			ep->fec_grp_hash_table_high = 0xffffffff;
+			ep->fec_grp_hash_table_low = 0xffffffff;
 		} else {
 			/* Clear filter and add the addresses in hash register.
 			*/
-			ep->fec_hash_table_high = 0;
-			ep->fec_hash_table_low = 0;
+			ep->fec_grp_hash_table_high = 0;
+			ep->fec_grp_hash_table_low = 0;
 
 			dmi = dev->mc_list;
 
@@ -2280,9 +2264,9 @@
 				hash = (crc >> (32 - HASH_BITS)) & 0x3f;
 
 				if (hash > 31)
-					ep->fec_hash_table_high |= 1 << (hash - 32);
+					ep->fec_grp_hash_table_high |= 1 << (hash - 32);
 				else
-					ep->fec_hash_table_low |= 1 << hash;
+					ep->fec_grp_hash_table_low |= 1 << hash;
 			}
 		}
 	}
@@ -2332,6 +2316,9 @@
 		return -ENOMEM;
 	}
 
+	spin_lock_init(&fep->hw_lock);
+	spin_lock_init(&fep->mii_lock);
+
 	/* Create an Ethernet device instance.
 	*/
 	fecp = (volatile fec_t *) fec_hw[index];
@@ -2430,11 +2417,15 @@
 	*/
 	fec_request_intrs(dev);
 
-	fecp->fec_hash_table_high = 0;
-	fecp->fec_hash_table_low = 0;
+	fecp->fec_grp_hash_table_high = 0;
+	fecp->fec_grp_hash_table_low = 0;
 	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
 	fecp->fec_ecntrl = 2;
 	fecp->fec_r_des_active = 0;
+#ifndef CONFIG_M5272
+	fecp->fec_hash_table_high = 0;
+	fecp->fec_hash_table_low = 0;
+#endif
 
 	dev->base_addr = (unsigned long)fecp;
 
@@ -2455,8 +2446,7 @@
 
 	/* Clear and enable interrupts */
 	fecp->fec_ievent = 0xffc00000;
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
-		FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
 
 	/* Queue up command to detect the PHY and initialize the
 	 * remainder of the interface.
@@ -2500,8 +2490,8 @@
 
 	/* Reset all multicast.
 	*/
-	fecp->fec_hash_table_high = 0;
-	fecp->fec_hash_table_low = 0;
+	fecp->fec_grp_hash_table_high = 0;
+	fecp->fec_grp_hash_table_low = 0;
 
 	/* Set maximum receive buffer size.
 	*/
@@ -2583,8 +2573,7 @@
 
 	/* Enable interrupts we wish to service.
 	*/
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
-		FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
 }
 
 static void
@@ -2624,7 +2613,7 @@
 static int __init fec_enet_module_init(void)
 {
 	struct net_device *dev;
-	int i, j, err;
+	int i, err;
 	DECLARE_MAC_BUF(mac);
 
 	printk("FEC ENET Version 0.2\n");
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index 1d42160..292719d 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -88,8 +88,8 @@
 	unsigned long	fec_reserved7[158];
 	unsigned long	fec_addr_low;		/* Low 32bits MAC address */
 	unsigned long	fec_addr_high;		/* High 16bits MAC address */
-	unsigned long	fec_hash_table_high;	/* High 32bits hash table */
-	unsigned long	fec_hash_table_low;	/* Low 32bits hash table */
+	unsigned long	fec_grp_hash_table_high;/* High 32bits hash table */
+	unsigned long	fec_grp_hash_table_low;	/* Low 32bits hash table */
 	unsigned long	fec_r_des_start;	/* Receive descriptor ring */
 	unsigned long	fec_x_des_start;	/* Transmit descriptor ring */
 	unsigned long	fec_r_buff_size;	/* Maximum receive buff size */
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 555b70c..f926b5a 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -41,6 +41,9 @@
 	struct net_device *dev;
 	struct napi_struct napi;
 
+	/* The skb we couldn't send because buffers were full. */
+	struct sk_buff *last_xmit_skb;
+
 	/* Number of input buffers, and max we've ever had. */
 	unsigned int num, max;
 
@@ -142,10 +145,10 @@
 static void try_fill_recv(struct virtnet_info *vi)
 {
 	struct sk_buff *skb;
-	struct scatterlist sg[1+MAX_SKB_FRAGS];
+	struct scatterlist sg[2+MAX_SKB_FRAGS];
 	int num, err;
 
-	sg_init_table(sg, 1+MAX_SKB_FRAGS);
+	sg_init_table(sg, 2+MAX_SKB_FRAGS);
 	for (;;) {
 		skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
 		if (unlikely(!skb))
@@ -221,23 +224,22 @@
 	while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) {
 		pr_debug("Sent skb %p\n", skb);
 		__skb_unlink(skb, &vi->send);
-		vi->dev->stats.tx_bytes += len;
+		vi->dev->stats.tx_bytes += skb->len;
 		vi->dev->stats.tx_packets++;
 		kfree_skb(skb);
 	}
 }
 
-static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 {
-	struct virtnet_info *vi = netdev_priv(dev);
-	int num, err;
-	struct scatterlist sg[1+MAX_SKB_FRAGS];
+	int num;
+	struct scatterlist sg[2+MAX_SKB_FRAGS];
 	struct virtio_net_hdr *hdr;
 	const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
 
-	sg_init_table(sg, 1+MAX_SKB_FRAGS);
+	sg_init_table(sg, 2+MAX_SKB_FRAGS);
 
-	pr_debug("%s: xmit %p " MAC_FMT "\n", dev->name, skb,
+	pr_debug("%s: xmit %p " MAC_FMT "\n", vi->dev->name, skb,
 		 dest[0], dest[1], dest[2],
 		 dest[3], dest[4], dest[5]);
 
@@ -272,30 +274,51 @@
 
 	vnet_hdr_to_sg(sg, skb);
 	num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
-	__skb_queue_head(&vi->send, skb);
+
+	return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
+}
+
+static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
 
 again:
 	/* Free up any pending old buffers before queueing new ones. */
 	free_old_xmit_skbs(vi);
-	err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
-	if (err) {
-		pr_debug("%s: virtio not prepared to send\n", dev->name);
-		netif_stop_queue(dev);
 
-		/* Activate callback for using skbs: if this returns false it
-		 * means some were used in the meantime. */
-		if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
-			vi->svq->vq_ops->disable_cb(vi->svq);
-			netif_start_queue(dev);
-			goto again;
+	/* If we has a buffer left over from last time, send it now. */
+	if (vi->last_xmit_skb) {
+		if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
+			/* Drop this skb: we only queue one. */
+			vi->dev->stats.tx_dropped++;
+			kfree_skb(skb);
+			goto stop_queue;
 		}
-		__skb_unlink(skb, &vi->send);
-
-		return NETDEV_TX_BUSY;
+		vi->last_xmit_skb = NULL;
 	}
-	vi->svq->vq_ops->kick(vi->svq);
 
-	return 0;
+	/* Put new one in send queue and do transmit */
+	__skb_queue_head(&vi->send, skb);
+	if (xmit_skb(vi, skb) != 0) {
+		vi->last_xmit_skb = skb;
+		goto stop_queue;
+	}
+done:
+	vi->svq->vq_ops->kick(vi->svq);
+	return NETDEV_TX_OK;
+
+stop_queue:
+	pr_debug("%s: virtio not prepared to send\n", dev->name);
+	netif_stop_queue(dev);
+
+	/* Activate callback for using skbs: if this returns false it
+	 * means some were used in the meantime. */
+	if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
+		vi->svq->vq_ops->disable_cb(vi->svq);
+		netif_start_queue(dev);
+		goto again;
+	}
+	goto done;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -355,17 +378,26 @@
 	SET_NETDEV_DEV(dev, &vdev->dev);
 
 	/* Do we support "hardware" checksums? */
-	if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) {
+	if (csum && virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
 		/* This opens up the world of extra features. */
 		dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
-		if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) {
+		if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
 			dev->features |= NETIF_F_TSO | NETIF_F_UFO
 				| NETIF_F_TSO_ECN | NETIF_F_TSO6;
 		}
+		/* Individual feature bits: what can host handle? */
+		if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4))
+			dev->features |= NETIF_F_TSO;
+		if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6))
+			dev->features |= NETIF_F_TSO6;
+		if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
+			dev->features |= NETIF_F_TSO_ECN;
+		if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
+			dev->features |= NETIF_F_UFO;
 	}
 
 	/* Configuration may specify what MAC to use.  Otherwise random. */
-	if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) {
+	if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
 		vdev->config->get(vdev,
 				  offsetof(struct virtio_net_config, mac),
 				  dev->dev_addr, dev->addr_len);
@@ -454,7 +486,15 @@
 	{ 0 },
 };
 
+static unsigned int features[] = {
+	VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
+	VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
+	VIRTIO_NET_F_HOST_ECN,
+};
+
 static struct virtio_driver virtio_net = {
+	.feature_table = features,
+	.feature_table_size = ARRAY_SIZE(features),
 	.driver.name =	KBUILD_MODNAME,
 	.driver.owner =	THIS_MODULE,
 	.id_table =	id_table,
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c
index 74e0515..c78d77f 100644
--- a/drivers/pcmcia/au1000_db1x00.c
+++ b/drivers/pcmcia/au1000_db1x00.c
@@ -194,7 +194,7 @@
 				default:
 					pwr |= SET_VCC_VPP(0,0,sock);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n",
-							__FUNCTION__,
+							__func__,
 							state->Vcc,
 							state->Vpp);
 					break;
@@ -215,7 +215,7 @@
 				default:
 					pwr |= SET_VCC_VPP(0,0,sock);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n",
-							__FUNCTION__,
+							__func__,
 							state->Vcc,
 							state->Vpp);
 					break;
@@ -224,7 +224,7 @@
 		default: /* what's this ? */
 			pwr |= SET_VCC_VPP(0,0,sock);
 			printk(KERN_ERR "%s: bad Vcc %d\n",
-					__FUNCTION__, state->Vcc);
+					__func__, state->Vcc);
 			break;
 	}
 
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index b693367..75e8f85 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -41,6 +41,7 @@
 #include <linux/notifier.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
@@ -71,7 +72,7 @@
 u32 *pcmcia_base_vaddrs[2];
 extern const unsigned long mips_io_port_base;
 
-DECLARE_MUTEX(pcmcia_sockets_lock);
+static DEFINE_MUTEX(pcmcia_sockets_lock);
 
 static int (*au1x00_pcmcia_hw_init[])(struct device *dev) = {
 	au1x_board_init,
@@ -472,7 +473,7 @@
 	struct skt_dev_info *sinfo = dev_get_drvdata(dev);
 	int i;
 
-	down(&pcmcia_sockets_lock);
+	mutex_lock(&pcmcia_sockets_lock);
 	dev_set_drvdata(dev, NULL);
 
 	for (i = 0; i < sinfo->nskt; i++) {
@@ -488,7 +489,7 @@
 	}
 
 	kfree(sinfo);
-	up(&pcmcia_sockets_lock);
+	mutex_unlock(&pcmcia_sockets_lock);
 	return 0;
 }
 
@@ -501,13 +502,13 @@
 {
 	int i, ret = -ENODEV;
 
-	down(&pcmcia_sockets_lock);
+	mutex_lock(&pcmcia_sockets_lock);
 	for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) {
 		ret = au1x00_pcmcia_hw_init[i](dev);
 		if (ret == 0)
 			break;
 	}
-	up(&pcmcia_sockets_lock);
+	mutex_unlock(&pcmcia_sockets_lock);
 	return ret;
 }
 
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index 86c0808..157e414 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -244,7 +244,7 @@
 					pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
 							configure->sock);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n", 
-							__FUNCTION__, 
+							__func__,
 							configure->vcc, 
 							configure->vpp);
 					break;
@@ -272,7 +272,7 @@
 					pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
 							configure->sock);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n", 
-							__FUNCTION__, 
+							__func__,
 							configure->vcc, 
 							configure->vpp);
 					break;
@@ -300,7 +300,7 @@
 					pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
 							configure->sock);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n", 
-							__FUNCTION__, 
+							__func__,
 							configure->vcc, 
 							configure->vpp);
 					break;
@@ -309,7 +309,7 @@
 		default: /* what's this ? */
 			pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock);
 			printk(KERN_ERR "%s: bad Vcc %d\n", 
-					__FUNCTION__, configure->vcc);
+					__func__, configure->vcc);
 			break;
 	}
 
@@ -353,7 +353,7 @@
 				default:
 					pcr |= SET_VCC_VPP(0,0);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n", 
-							__FUNCTION__, 
+							__func__,
 							configure->vcc, 
 							configure->vpp);
 					break;
@@ -374,7 +374,7 @@
 				default:
 					pcr |= SET_VCC_VPP(0,0);
 					printk("%s: bad Vcc/Vpp (%d:%d)\n", 
-							__FUNCTION__, 
+							__func__,
 							configure->vcc, 
 							configure->vpp);
 					break;
@@ -383,7 +383,7 @@
 		default: /* what's this ? */
 			pcr |= SET_VCC_VPP(0,0);
 			printk(KERN_ERR "%s: bad Vcc %d\n", 
-					__FUNCTION__, configure->vcc);
+					__func__, configure->vcc);
 			break;
 	}
 
diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c
index ce9d5c4..c78ed53 100644
--- a/drivers/pcmcia/au1000_xxs1500.c
+++ b/drivers/pcmcia/au1000_xxs1500.c
@@ -56,7 +56,7 @@
 #define PCMCIA_IRQ		AU1000_GPIO_4
 
 #if 0
-#define DEBUG(x,args...)	printk(__FUNCTION__ ": " x,##args)
+#define DEBUG(x, args...)	printk(__func__ ": " x, ##args)
 #else
 #define DEBUG(x,args...)
 #endif
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 714baae..fb2f38d 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -209,7 +209,7 @@
 	}
 }
 
-int cb_alloc(struct pcmcia_socket * s)
+int __ref cb_alloc(struct pcmcia_socket * s)
 {
 	struct pci_bus *bus = s->cb_dev->subordinate;
 	struct pci_dev *dev;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 5a85871..e407754 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1520,7 +1520,7 @@
 
 
 /* the pcmcia_bus_interface is used to handle pcmcia socket devices */
-static struct class_interface pcmcia_bus_interface = {
+static struct class_interface pcmcia_bus_interface __refdata = {
 	.class = &pcmcia_socket_class,
 	.add_dev = &pcmcia_bus_add_socket,
 	.remove_dev = &pcmcia_bus_remove_socket,
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index e54ecc5..e136186 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -53,7 +53,7 @@
 }
 #endif
 
-static struct pci_driver i82092aa_pci_drv = {
+static struct pci_driver i82092aa_pci_driver = {
 	.name           = "i82092aa",
 	.id_table       = i82092aa_pci_ids,
 	.probe          = i82092aa_pci_probe,
@@ -714,13 +714,13 @@
 
 static int i82092aa_module_init(void)
 {
-	return pci_register_driver(&i82092aa_pci_drv);
+	return pci_register_driver(&i82092aa_pci_driver);
 }
 
 static void i82092aa_module_exit(void)
 {
 	enter("i82092aa_module_exit");
-	pci_unregister_driver(&i82092aa_pci_drv);
+	pci_unregister_driver(&i82092aa_pci_driver);
 	if (sockets[0].io_base>0)
 			 release_region(sockets[0].io_base, 2);
 	leave("i82092aa_module_exit");
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index bb6db3a..46314b4 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -153,7 +153,7 @@
 
 static int omap_cf_ss_suspend(struct pcmcia_socket *s)
 {
-	pr_debug("%s: %s\n", driver_name, __FUNCTION__);
+	pr_debug("%s: %s\n", driver_name, __func__);
 	return omap_cf_set_socket(s, &dead_socket);
 }
 
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index abc10fe..8bed1da 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -778,7 +778,7 @@
 };
 MODULE_DEVICE_TABLE(pci, pd6729_pci_ids);
 
-static struct pci_driver pd6729_pci_drv = {
+static struct pci_driver pd6729_pci_driver = {
 	.name		= "pd6729",
 	.id_table	= pd6729_pci_ids,
 	.probe		= pd6729_pci_probe,
@@ -791,12 +791,12 @@
 
 static int pd6729_module_init(void)
 {
-	return pci_register_driver(&pd6729_pci_drv);
+	return pci_register_driver(&pd6729_pci_driver);
 }
 
 static void pd6729_module_exit(void)
 {
-	pci_unregister_driver(&pd6729_pci_drv);
+	pci_unregister_driver(&pd6729_pci_driver);
 }
 
 module_init(pd6729_module_init);
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
index 4a05802..881ec8a 100644
--- a/drivers/pcmcia/pxa2xx_lubbock.c
+++ b/drivers/pcmcia/pxa2xx_lubbock.c
@@ -87,7 +87,7 @@
 
 		default:
 			printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-			       __FUNCTION__, state->Vcc);
+			       __func__, state->Vcc);
 			ret = -1;
 		}
 
@@ -104,7 +104,7 @@
 				pa_dwr_set |= GPIO_A0;
 			else {
 				printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-				       __FUNCTION__, state->Vpp);
+				       __func__, state->Vpp);
 				ret = -1;
 				break;
 			}
@@ -128,14 +128,14 @@
 
 		default:
 			printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-			       __FUNCTION__, state->Vcc);
+			       __func__, state->Vcc);
 			ret = -1;
 			break;
 		}
 
 		if (state->Vpp != state->Vcc && state->Vpp != 0) {
 			printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
-			       __FUNCTION__, state->Vpp);
+			       __func__, state->Vpp);
 			ret = -1;
 			break;
 		}
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 6fa5eaa..145b85e 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -99,7 +99,7 @@
 	case 50: power |= MST_PCMCIA_PWR_VCC_50; break;
 	default:
 		 printk(KERN_ERR "%s(): bad Vcc %u\n",
-				 __FUNCTION__, state->Vcc);
+				 __func__, state->Vcc);
 		 ret = -1;
 	}
 
@@ -111,7 +111,7 @@
 			  power |= MST_PCMCIA_PWR_VPP_VCC;
 		  } else {
 			  printk(KERN_ERR "%s(): bad Vpp %u\n",
-					  __FUNCTION__, state->Vpp);
+					  __func__, state->Vpp);
 			  ret = -1;
 		  }
 	}
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index a8d1007..0fcf763 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -1045,7 +1045,7 @@
 		device_remove_file(dev, *attr);
 }
 
-static struct class_interface pccard_rsrc_interface = {
+static struct class_interface pccard_rsrc_interface __refdata = {
 	.class = &pcmcia_socket_class,
 	.add_dev = &pccard_sysfs_add_rsrc,
 	.remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index 7c57fdd..ce133ce 100644
--- a/drivers/pcmcia/sa1100_assabet.c
+++ b/drivers/pcmcia/sa1100_assabet.c
@@ -66,14 +66,14 @@
 
 	case 50:
 		printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
-			__FUNCTION__);
+			__func__);
 
 	case 33:  /* Can only apply 3.3V to the CF slot. */
 		mask = ASSABET_BCR_CF_PWR;
 		break;
 
 	default:
-		printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+		printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __func__,
 			state->Vcc);
 		return -1;
 	}
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
index 62bfc75..607c3f3 100644
--- a/drivers/pcmcia/sa1100_badge4.c
+++ b/drivers/pcmcia/sa1100_badge4.c
@@ -82,14 +82,14 @@
 	case 0:
 		if ((state->Vcc != 0) &&
 		    (state->Vcc != badge4_pcmvcc)) {
-			complain_about_jumpering(__FUNCTION__, "pcmvcc",
+			complain_about_jumpering(__func__, "pcmvcc",
 						 badge4_pcmvcc, state->Vcc);
 			// Apply power regardless of the jumpering.
 			// return -1;
 		}
 		if ((state->Vpp != 0) &&
 		    (state->Vpp != badge4_pcmvpp)) {
-			complain_about_jumpering(__FUNCTION__, "pcmvpp",
+			complain_about_jumpering(__func__, "pcmvpp",
 						 badge4_pcmvpp, state->Vpp);
 			return -1;
 		}
@@ -98,7 +98,7 @@
 	case 1:
 		if ((state->Vcc != 0) &&
 		    (state->Vcc != badge4_cfvcc)) {
-			complain_about_jumpering(__FUNCTION__, "cfvcc",
+			complain_about_jumpering(__func__, "cfvcc",
 						 badge4_cfvcc, state->Vcc);
 			return -1;
 		}
@@ -143,7 +143,7 @@
 	if (machine_is_badge4()) {
 		printk(KERN_INFO
 		       "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
-		       __FUNCTION__,
+		       __func__,
 		       badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
 
 		ret = sa11xx_drv_pcmcia_probe(dev, &badge4_pcmcia_ops, 0, 2);
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index 549a152..7c3951a 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -63,7 +63,7 @@
 
 	default:
 		printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-			__FUNCTION__, state->Vcc);
+			__func__, state->Vcc);
 		return -1;
 	}
 
diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c
index 6284c35..2167e67 100644
--- a/drivers/pcmcia/sa1100_jornada720.c
+++ b/drivers/pcmcia/sa1100_jornada720.c
@@ -42,7 +42,7 @@
   unsigned int pa_dwr_mask, pa_dwr_set;
   int ret;
 
-printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
+printk("%s(): config socket %d vcc %d vpp %d\n", __func__,
 	skt->nr, state->Vcc, state->Vpp);
 
   switch (skt->nr) {
@@ -74,7 +74,7 @@
 
   if (state->Vpp != state->Vcc && state->Vpp != 0) {
     printk(KERN_ERR "%s(): slot cannot support VPP %u\n",
-	   __FUNCTION__, state->Vpp);
+	   __func__, state->Vpp);
     return -1;
   }
 
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c
index 5bc9e95..687492f 100644
--- a/drivers/pcmcia/sa1100_neponset.c
+++ b/drivers/pcmcia/sa1100_neponset.c
@@ -59,7 +59,7 @@
 			ncr_set = NCR_A0VPP;
 		else {
 			printk(KERN_ERR "%s(): unrecognized VPP %u\n",
-			       __FUNCTION__, state->Vpp);
+			       __func__, state->Vpp);
 			return -1;
 		}
 		break;
@@ -71,7 +71,7 @@
 
 		if (state->Vpp != state->Vcc && state->Vpp != 0) {
 			printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
-			       __FUNCTION__, state->Vpp);
+			       __func__, state->Vpp);
 			return -1;
 		}
 		break;
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
index 9456f54..494912f 100644
--- a/drivers/pcmcia/sa1100_shannon.c
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -73,19 +73,19 @@
 {
 	switch (state->Vcc) {
 	case 0:	/* power off */
-		printk(KERN_WARNING "%s(): CS asked for 0V, still applying 3.3V..\n", __FUNCTION__);
+		printk(KERN_WARNING "%s(): CS asked for 0V, still applying 3.3V..\n", __func__);
 		break;
 	case 50:
-		printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V..\n", __FUNCTION__);
+		printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V..\n", __func__);
 	case 33:
 		break;
 	default:
 		printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-		       __FUNCTION__, state->Vcc);
+		       __func__, state->Vcc);
 		return -1;
 	}
 
-	printk(KERN_WARNING "%s(): Warning, Can't perform reset\n", __FUNCTION__);
+	printk(KERN_WARNING "%s(): Warning, Can't perform reset\n", __func__);
 	
 	/* Silently ignore Vpp, output enable, speaker enable. */
 
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index 04d6f7f..42567de 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -90,7 +90,7 @@
 
 	default:
 		printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-			__FUNCTION__, state->Vcc);
+			__func__, state->Vcc);
 		clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
 		local_irq_restore(flags);
 		return -1;
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index aa7779d..420a775 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/spinlock.h>
@@ -353,7 +354,7 @@
 		(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
 
 	if (map->map >= MAX_IO_WIN) {
-		printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+		printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
 		       map->map);
 		return -1;
 	}
@@ -578,7 +579,7 @@
 
 
 LIST_HEAD(soc_pcmcia_sockets);
-DECLARE_MUTEX(soc_pcmcia_sockets_lock);
+static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
 
 static const char *skt_names[] = {
 	"PCMCIA socket 0",
@@ -601,11 +602,11 @@
 	struct cpufreq_freqs *freqs = data;
 	int ret = 0;
 
-	down(&soc_pcmcia_sockets_lock);
+	mutex_lock(&soc_pcmcia_sockets_lock);
 	list_for_each_entry(skt, &soc_pcmcia_sockets, node)
 		if ( skt->ops->frequency_change )
 			ret += skt->ops->frequency_change(skt, val, freqs);
-	up(&soc_pcmcia_sockets_lock);
+	mutex_unlock(&soc_pcmcia_sockets_lock);
 
 	return ret;
 }
@@ -642,7 +643,7 @@
 	struct soc_pcmcia_socket *skt;
 	int ret, i;
 
-	down(&soc_pcmcia_sockets_lock);
+	mutex_lock(&soc_pcmcia_sockets_lock);
 
 	sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
 	if (!sinfo) {
@@ -782,7 +783,7 @@
 	kfree(sinfo);
 
  out:
-	up(&soc_pcmcia_sockets_lock);
+	mutex_unlock(&soc_pcmcia_sockets_lock);
 	return ret;
 }
 
@@ -793,7 +794,7 @@
 
 	dev_set_drvdata(dev, NULL);
 
-	down(&soc_pcmcia_sockets_lock);
+	mutex_lock(&soc_pcmcia_sockets_lock);
 	for (i = 0; i < sinfo->nskt; i++) {
 		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
 
@@ -818,7 +819,7 @@
 	if (list_empty(&soc_pcmcia_sockets))
 		soc_pcmcia_cpufreq_unregister();
 
-	up(&soc_pcmcia_sockets_lock);
+	mutex_unlock(&soc_pcmcia_sockets_lock);
 
 	kfree(sinfo);
 
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index 6f14126..1edc1da 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -133,7 +133,6 @@
 
 
 extern struct list_head soc_pcmcia_sockets;
-extern struct semaphore soc_pcmcia_sockets_lock;
 
 extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
 extern int soc_common_drv_pcmcia_remove(struct device *dev);
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index 2e2c457..5ff9a4c 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -591,7 +591,8 @@
 	p[1] = map & 0xff;
 	p[2] = (map >> 8) & 0xff;
 
-	dev_dbg(&dev->dev, "  encode irq %d\n", res->start);
+	dev_dbg(&dev->dev, "  encode irq %llu\n",
+		(unsigned long long)res->start);
 }
 
 static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
@@ -602,7 +603,8 @@
 	map = 1 << res->start;
 	p[1] = map & 0xff;
 
-	dev_dbg(&dev->dev, "  encode dma %d\n", res->start);
+	dev_dbg(&dev->dev, "  encode dma %llu\n",
+		(unsigned long long)res->start);
 }
 
 static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c
index e55b903..1dd70d7 100644
--- a/drivers/scsi/mvsas.c
+++ b/drivers/scsi/mvsas.c
@@ -2822,7 +2822,9 @@
 		dev_printk(KERN_DEBUG, &pdev->dev,
 			"phy[%d] Get Attached Address 0x%llX ,"
 			" SAS Address 0x%llX\n",
-			i, phy->att_dev_sas_addr, phy->dev_sas_addr);
+			i,
+			(unsigned long long)phy->att_dev_sas_addr,
+			(unsigned long long)phy->dev_sas_addr);
 		dev_printk(KERN_DEBUG, &pdev->dev,
 			"Rate = %x , type = %d\n",
 			sas_phy->linkrate, phy->phy_type);
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index ceab4f73..c57c94c 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -8222,7 +8222,7 @@
 #ifdef DEBUG_WAITING_LIST
 	if (waiting_list) printk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts);
 #endif
-	while (wcmd = waiting_list) {
+	while ((wcmd = waiting_list) != NULL) {
 		waiting_list = (struct scsi_cmnd *) wcmd->next_wcmd;
 		wcmd->next_wcmd = NULL;
 		if (sts == DID_OK) {
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ea41f26..a1ca9b7 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2271,7 +2271,8 @@
 		}
 
 		if (up->port.flags & UPF_IOREMAP) {
-			up->port.membase = ioremap(up->port.mapbase, size);
+			up->port.membase = ioremap_nocache(up->port.mapbase,
+									size);
 			if (!up->port.membase) {
 				release_mem_region(up->port.mapbase, size);
 				ret = -ENOMEM;
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index cd89870..f279745 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -153,7 +153,7 @@
 			(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
 		port->membase += port->mapbase & ~PAGE_MASK;
 #else
-		port->membase = ioremap(port->mapbase, 64);
+		port->membase = ioremap_nocache(port->mapbase, 64);
 		if (!port->membase) {
 			printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
 				__func__,
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 6e57382..53fa19c 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -86,7 +86,7 @@
 		len =  pci_resource_len(dev, bar);
 
 		if (!priv->remapped_bar[bar])
-			priv->remapped_bar[bar] = ioremap(base, len);
+			priv->remapped_bar[bar] = ioremap_nocache(base, len);
 		if (!priv->remapped_bar[bar])
 			return -ENOMEM;
 
@@ -270,7 +270,7 @@
 	/*
 	 * enable/disable interrupts
 	 */
-	p = ioremap(pci_resource_start(dev, 0), 0x80);
+	p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
 	if (p == NULL)
 		return -ENOMEM;
 	writel(irq_config, p + 0x4c);
@@ -294,7 +294,7 @@
 	/*
 	 * disable interrupts
 	 */
-	p = ioremap(pci_resource_start(dev, 0), 0x80);
+	p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
 	if (p != NULL) {
 		writel(0, p + 0x4c);
 
@@ -341,7 +341,8 @@
 {
 	u8 __iomem *p;
 
-	p = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0));
+	p = ioremap_nocache(pci_resource_start(dev, 0),
+						pci_resource_len(dev, 0));
 
 	if (p == NULL)
 		return -ENOMEM;
@@ -365,7 +366,8 @@
 {
 	u8 __iomem *p;
 
-	p = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0));
+	p = ioremap_nocache(pci_resource_start(dev, 0),
+					pci_resource_len(dev, 0));
 	/* FIXME: What if resource_len < OCT_REG_CR_OFF */
 	if (p != NULL)
 		writeb(0, p + OCT_REG_CR_OFF);
@@ -419,7 +421,7 @@
 		break;
 	}
 
-	p = ioremap(pci_resource_start(dev, 0), 0x80);
+	p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
 	if (p == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index 12c934a..8871aaa 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -373,6 +373,7 @@
 #define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME		"Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
 #define PCI_DEVICE_NEO_2RJ45_PCI_NAME		"Neo 2 - RJ45 Universal PCI"
 #define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME	"Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
+#define PCIE_DEVICE_NEO_IBM_PCI_NAME		"Neo 4 - PCI Express - IBM"
 
 /*
  * Our Global Variables.
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 6767ee3..338cf8a 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -82,7 +82,10 @@
 	/* store the info for the board we've found */
 	brd->boardnum = adapter_count++;
 	brd->pci_dev = pdev;
-	brd->maxports = 2;
+	if (pdev->device == PCIE_DEVICE_ID_NEO_4_IBM)
+		brd->maxports = 4;
+	else
+		brd->maxports = 2;
 
 	spin_lock_init(&brd->bd_lock);
 	spin_lock_init(&brd->bd_intr_lock);
@@ -208,6 +211,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4_IBM), 0, 0, 4 },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index a9ac1fd..7fea3cf 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -608,6 +608,7 @@
 	u8 width;
 	u16 cr, dma_width, dma_config;
 	u32 tranf_success = 1;
+	u8 full_duplex = 0;
 
 	/* Get current state information */
 	message = drv_data->cur_msg;
@@ -658,6 +659,7 @@
 	}
 
 	if (transfer->rx_buf != NULL) {
+		full_duplex = transfer->tx_buf != NULL;
 		drv_data->rx = transfer->rx_buf;
 		drv_data->rx_end = drv_data->rx + transfer->len;
 		dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n",
@@ -740,7 +742,8 @@
 	 * successful use different way to r/w according to
 	 * drv_data->cur_chip->enable_dma
 	 */
-	if (drv_data->cur_chip->enable_dma && drv_data->len > 6) {
+	if (!full_duplex && drv_data->cur_chip->enable_dma
+				&& drv_data->len > 6) {
 
 		disable_dma(drv_data->dma_channel);
 		clear_dma_irqstat(drv_data->dma_channel);
@@ -828,7 +831,7 @@
 		/* IO mode write then read */
 		dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
 
-		if (drv_data->tx != NULL && drv_data->rx != NULL) {
+		if (full_duplex) {
 			/* full duplex mode */
 			BUG_ON((drv_data->tx_end - drv_data->tx) !=
 			       (drv_data->rx_end - drv_data->rx));
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 34bfb7d..0885cc3 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -125,10 +125,10 @@
 	/* is clk = pclk / (2 * (pre+1)), or is it
 	 *    clk = (pclk * 2) / ( pre + 1) */
 
-	div = (div / 2) - 1;
+	div /= 2;
 
-	if (div < 0)
-		div = 1;
+	if (div > 0)
+		div -= 1;
 
 	if (div > 255)
 		div = 255;
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 516a640..a419c42 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -17,6 +17,8 @@
 obj-$(CONFIG_USB_U132_HCD)	+= host/
 obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
 
+obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/
+
 obj-$(CONFIG_USB_ACM)		+= class/
 obj-$(CONFIG_USB_PRINTER)	+= class/
 
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index 86e6403..be0b8da 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -19,7 +19,6 @@
 
 config USB_SPEEDTOUCH
 	tristate "Speedtouch USB support"
-	depends on USB_ATM
 	select FW_LOADER
 	help
 	  Say Y here if you have an SpeedTouch USB or SpeedTouch 330
@@ -32,7 +31,6 @@
 
 config USB_CXACRU
 	tristate "Conexant AccessRunner USB support"
-	depends on USB_ATM
 	select FW_LOADER
 	help
 	  Say Y here if you have an ADSL USB modem based on the Conexant
@@ -45,7 +43,6 @@
 
 config USB_UEAGLEATM
 	tristate "ADI 930 and eagle USB DSL modem"
-	depends on USB_ATM
 	select FW_LOADER
 	help
 	  Say Y here if you have an ADSL USB modem based on the ADI 930
@@ -58,7 +55,6 @@
 
 config USB_XUSBATM
 	tristate "Other USB DSL modem support"
-	depends on USB_ATM
 	help
 	  Say Y here if you have a DSL USB modem not explicitly supported by
 	  another USB DSL drivers.  In order to use your modem you will need to
diff --git a/drivers/usb/c67x00/Makefile b/drivers/usb/c67x00/Makefile
new file mode 100644
index 0000000..868bc41
--- /dev/null
+++ b/drivers/usb/c67x00/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for Cypress C67X00 USB Controller
+#
+
+ccflags-$(CONFIG_USB_DEBUG)		+= -DDEBUG
+
+obj-$(CONFIG_USB_C67X00_HCD)		+= c67x00.o
+
+c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
new file mode 100644
index 0000000..5633bc5
--- /dev/null
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -0,0 +1,243 @@
+/*
+ * c67x00-drv.c: Cypress C67X00 USB Common infrastructure
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ *    based on multiple host controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+/*
+ * This file implements the common infrastructure for using the c67x00.
+ * It is both the link between the platform configuration and subdrivers and
+ * the link between the common hardware parts and the subdrivers (e.g.
+ * interrupt handling).
+ *
+ * The c67x00 has 2 SIE's (serial interface engine) wich can be configured
+ * to be host, device or OTG (with some limitations, E.G. only SIE1 can be OTG).
+ *
+ * Depending on the platform configuration, the SIE's are created and
+ * the corresponding subdriver is initialized (c67x00_probe_sie).
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/usb/c67x00.h>
+
+#include "c67x00.h"
+#include "c67x00-hcd.h"
+
+static void c67x00_probe_sie(struct c67x00_sie *sie,
+			     struct c67x00_device *dev, int sie_num)
+{
+	spin_lock_init(&sie->lock);
+	sie->dev = dev;
+	sie->sie_num = sie_num;
+	sie->mode = c67x00_sie_config(dev->pdata->sie_config, sie_num);
+
+	switch (sie->mode) {
+	case C67X00_SIE_HOST:
+		c67x00_hcd_probe(sie);
+		break;
+
+	case C67X00_SIE_UNUSED:
+		dev_info(sie_dev(sie),
+			 "Not using SIE %d as requested\n", sie->sie_num);
+		break;
+
+	default:
+		dev_err(sie_dev(sie),
+			"Unsupported configuration: 0x%x for SIE %d\n",
+			sie->mode, sie->sie_num);
+		break;
+	}
+}
+
+static void c67x00_remove_sie(struct c67x00_sie *sie)
+{
+	switch (sie->mode) {
+	case C67X00_SIE_HOST:
+		c67x00_hcd_remove(sie);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static irqreturn_t c67x00_irq(int irq, void *__dev)
+{
+	struct c67x00_device *c67x00 = __dev;
+	struct c67x00_sie *sie;
+	u16 msg, int_status;
+	int i, count = 8;
+
+	int_status = c67x00_ll_hpi_status(c67x00);
+	if (!int_status)
+		return IRQ_NONE;
+
+	while (int_status != 0 && (count-- >= 0)) {
+		c67x00_ll_irq(c67x00, int_status);
+		for (i = 0; i < C67X00_SIES; i++) {
+			sie = &c67x00->sie[i];
+			msg = 0;
+			if (int_status & SIEMSG_FLG(i))
+				msg = c67x00_ll_fetch_siemsg(c67x00, i);
+			if (sie->irq)
+				sie->irq(sie, int_status, msg);
+		}
+		int_status = c67x00_ll_hpi_status(c67x00);
+	}
+
+	if (int_status)
+		dev_warn(&c67x00->pdev->dev, "Not all interrupts handled! "
+			 "status = 0x%04x\n", int_status);
+
+	return IRQ_HANDLED;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit c67x00_drv_probe(struct platform_device *pdev)
+{
+	struct c67x00_device *c67x00;
+	struct c67x00_platform_data *pdata;
+	struct resource *res, *res2;
+	int ret, i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res2)
+		return -ENODEV;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENODEV;
+
+	c67x00 = kzalloc(sizeof(*c67x00), GFP_KERNEL);
+	if (!c67x00)
+		return -ENOMEM;
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				pdev->name)) {
+		dev_err(&pdev->dev, "Memory region busy\n");
+		ret = -EBUSY;
+		goto request_mem_failed;
+	}
+	c67x00->hpi.base = ioremap(res->start, res->end - res->start + 1);
+	if (!c67x00->hpi.base) {
+		dev_err(&pdev->dev, "Unable to map HPI registers\n");
+		ret = -EIO;
+		goto map_failed;
+	}
+
+	spin_lock_init(&c67x00->hpi.lock);
+	c67x00->hpi.regstep = pdata->hpi_regstep;
+	c67x00->pdata = pdev->dev.platform_data;
+	c67x00->pdev = pdev;
+
+	c67x00_ll_init(c67x00);
+	c67x00_ll_hpi_reg_init(c67x00);
+
+	ret = request_irq(res2->start, c67x00_irq, 0, pdev->name, c67x00);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		goto request_irq_failed;
+	}
+
+	ret = c67x00_ll_reset(c67x00);
+	if (ret) {
+		dev_err(&pdev->dev, "Device reset failed\n");
+		goto reset_failed;
+	}
+
+	for (i = 0; i < C67X00_SIES; i++)
+		c67x00_probe_sie(&c67x00->sie[i], c67x00, i);
+
+	platform_set_drvdata(pdev, c67x00);
+
+	return 0;
+
+ reset_failed:
+	free_irq(res2->start, c67x00);
+ request_irq_failed:
+	iounmap(c67x00->hpi.base);
+ map_failed:
+	release_mem_region(res->start, res->end - res->start + 1);
+ request_mem_failed:
+	kfree(c67x00);
+
+	return ret;
+}
+
+static int __devexit c67x00_drv_remove(struct platform_device *pdev)
+{
+	struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
+	struct resource *res;
+	int i;
+
+	for (i = 0; i < C67X00_SIES; i++)
+		c67x00_remove_sie(&c67x00->sie[i]);
+
+	c67x00_ll_release(c67x00);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res)
+		free_irq(res->start, c67x00);
+
+	iounmap(c67x00->hpi.base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		release_mem_region(res->start, res->end - res->start + 1);
+
+	kfree(c67x00);
+
+	return 0;
+}
+
+static struct platform_driver c67x00_driver = {
+	.probe	= c67x00_drv_probe,
+	.remove	= __devexit_p(c67x00_drv_remove),
+	.driver	= {
+		.owner = THIS_MODULE,
+		.name = "c67x00",
+	},
+};
+MODULE_ALIAS("platform:c67x00");
+
+static int __init c67x00_init(void)
+{
+	return platform_driver_register(&c67x00_driver);
+}
+
+static void __exit c67x00_exit(void)
+{
+	platform_driver_unregister(&c67x00_driver);
+}
+
+module_init(c67x00_init);
+module_exit(c67x00_exit);
+
+MODULE_AUTHOR("Peter Korsgaard, Jan Veldeman, Grant Likely");
+MODULE_DESCRIPTION("Cypress C67X00 USB Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c
new file mode 100644
index 0000000..a22b887
--- /dev/null
+++ b/drivers/usb/c67x00/c67x00-hcd.c
@@ -0,0 +1,412 @@
+/*
+ * c67x00-hcd.c: Cypress C67X00 USB Host Controller Driver
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ *    based on multiple host controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+
+#include "c67x00.h"
+#include "c67x00-hcd.h"
+
+/* --------------------------------------------------------------------------
+ * Root Hub Support
+ */
+
+static __u8 c67x00_hub_des[] = {
+	0x09,			/*  __u8  bLength; */
+	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
+	0x02,			/*  __u8  bNbrPorts; */
+	0x00,			/* __u16  wHubCharacteristics; */
+	0x00,			/*   (per-port OC, no power switching) */
+	0x32,			/*  __u8  bPwrOn2pwrGood; 2ms */
+	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
+	0x00,			/*  __u8  DeviceRemovable; ** 7 Ports max ** */
+	0xff,			/*  __u8  PortPwrCtrlMask; ** 7 ports max ** */
+};
+
+static void c67x00_hub_reset_host_port(struct c67x00_sie *sie, int port)
+{
+	struct c67x00_hcd *c67x00 = sie->private_data;
+	unsigned long flags;
+
+	c67x00_ll_husb_reset(sie, port);
+
+	spin_lock_irqsave(&c67x00->lock, flags);
+	c67x00_ll_husb_reset_port(sie, port);
+	spin_unlock_irqrestore(&c67x00->lock, flags);
+
+	c67x00_ll_set_husb_eot(sie->dev, DEFAULT_EOT);
+}
+
+static int c67x00_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
+	struct c67x00_sie *sie = c67x00->sie;
+	u16 status;
+	int i;
+
+	*buf = 0;
+	status = c67x00_ll_usb_get_status(sie);
+	for (i = 0; i < C67X00_PORTS; i++)
+		if (status & PORT_CONNECT_CHANGE(i))
+			*buf |= (1 << i);
+
+	/* bit 0 denotes hub change, b1..n port change */
+	*buf <<= 1;
+
+	return !!*buf;
+}
+
+static int c67x00_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+			      u16 wIndex, char *buf, u16 wLength)
+{
+	struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
+	struct c67x00_sie *sie = c67x00->sie;
+	u16 status, usb_status;
+	int len = 0;
+	unsigned int port = wIndex-1;
+	u16 wPortChange, wPortStatus;
+
+	switch (typeReq) {
+
+	case GetHubStatus:
+		*(__le32 *) buf = cpu_to_le32(0);
+		len = 4;		/* hub power */
+		break;
+
+	case GetPortStatus:
+		if (wIndex > C67X00_PORTS)
+			return -EPIPE;
+
+		status = c67x00_ll_usb_get_status(sie);
+		usb_status = c67x00_ll_get_usb_ctl(sie);
+
+		wPortChange = 0;
+		if (status & PORT_CONNECT_CHANGE(port))
+			wPortChange |= USB_PORT_STAT_C_CONNECTION;
+
+		wPortStatus = USB_PORT_STAT_POWER;
+		if (!(status & PORT_SE0_STATUS(port)))
+			wPortStatus |= USB_PORT_STAT_CONNECTION;
+		if (usb_status & LOW_SPEED_PORT(port)) {
+			wPortStatus |= USB_PORT_STAT_LOW_SPEED;
+			c67x00->low_speed_ports |= (1 << port);
+		} else
+			c67x00->low_speed_ports &= ~(1 << port);
+
+		if (usb_status & SOF_EOP_EN(port))
+			wPortStatus |= USB_PORT_STAT_ENABLE;
+
+		*(__le16 *) buf = cpu_to_le16(wPortStatus);
+		*(__le16 *) (buf + 2) = cpu_to_le16(wPortChange);
+		len = 4;
+		break;
+
+	case SetHubFeature:	/* We don't implement these */
+	case ClearHubFeature:
+		switch (wValue) {
+		case C_HUB_OVER_CURRENT:
+		case C_HUB_LOCAL_POWER:
+			len = 0;
+			break;
+
+		default:
+			return -EPIPE;
+		}
+		break;
+
+	case SetPortFeature:
+		if (wIndex > C67X00_PORTS)
+			return -EPIPE;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"SetPortFeature %d (SUSPEND)\n", port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_RESET:
+			c67x00_hub_reset_host_port(sie, port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_POWER:
+			/* Power always enabled */
+			len = 0;
+			break;
+
+		default:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"%s: SetPortFeature %d (0x%04x) Error!\n",
+				__func__, port, wValue);
+			return -EPIPE;
+		}
+		break;
+
+	case ClearPortFeature:
+		if (wIndex > C67X00_PORTS)
+			return -EPIPE;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			/* Reset the port so that the c67x00 also notices the
+			 * disconnect */
+			c67x00_hub_reset_host_port(sie, port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_C_ENABLE:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"ClearPortFeature (%d): C_ENABLE\n", port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_SUSPEND:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"ClearPortFeature (%d): SUSPEND\n", port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_C_SUSPEND:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"ClearPortFeature (%d): C_SUSPEND\n", port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"ClearPortFeature (%d): POWER\n", port);
+			return -EPIPE;
+
+		case USB_PORT_FEAT_C_CONNECTION:
+			c67x00_ll_usb_clear_status(sie,
+						   PORT_CONNECT_CHANGE(port));
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"ClearPortFeature (%d): OVER_CURRENT\n", port);
+			len = 0;
+			break;
+
+		case USB_PORT_FEAT_C_RESET:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"ClearPortFeature (%d): C_RESET\n", port);
+			len = 0;
+			break;
+
+		default:
+			dev_dbg(c67x00_hcd_dev(c67x00),
+				"%s: ClearPortFeature %d (0x%04x) Error!\n",
+				__func__, port, wValue);
+			return -EPIPE;
+		}
+		break;
+
+	case GetHubDescriptor:
+		len = min_t(unsigned int, sizeof(c67x00_hub_des), wLength);
+		memcpy(buf, c67x00_hub_des, len);
+		break;
+
+	default:
+		dev_dbg(c67x00_hcd_dev(c67x00), "%s: unknown\n", __func__);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * Main part of host controller driver
+ */
+
+/**
+ * c67x00_hcd_irq
+ *
+ * This function is called from the interrupt handler in c67x00-drv.c
+ */
+static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
+{
+	struct c67x00_hcd *c67x00 = sie->private_data;
+	struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00);
+
+	/* Handle sie message flags */
+	if (msg) {
+		if (msg & HUSB_TDListDone)
+			c67x00_sched_kick(c67x00);
+		else
+			dev_warn(c67x00_hcd_dev(c67x00),
+				 "Unknown SIE msg flag(s): 0x%04x\n", msg);
+	}
+
+	if (unlikely(hcd->state == HC_STATE_HALT))
+		return;
+
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+		return;
+
+	/* Handle Start of frame events */
+	if (int_status & SOFEOP_FLG(sie->sie_num)) {
+		c67x00_ll_usb_clear_status(sie, SOF_EOP_IRQ_FLG);
+		c67x00_sched_kick(c67x00);
+		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+	}
+}
+
+/**
+ * c67x00_hcd_start: Host controller start hook
+ */
+static int c67x00_hcd_start(struct usb_hcd *hcd)
+{
+	hcd->uses_new_polling = 1;
+	hcd->state = HC_STATE_RUNNING;
+	hcd->poll_rh = 1;
+
+	return 0;
+}
+
+/**
+ * c67x00_hcd_stop: Host controller stop hook
+ */
+static void c67x00_hcd_stop(struct usb_hcd *hcd)
+{
+	/* Nothing to do */
+}
+
+static int c67x00_hcd_get_frame(struct usb_hcd *hcd)
+{
+	struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
+	u16 temp_val;
+
+	dev_dbg(c67x00_hcd_dev(c67x00), "%s\n", __func__);
+	temp_val = c67x00_ll_husb_get_frame(c67x00->sie);
+	temp_val &= HOST_FRAME_MASK;
+	return temp_val ? (temp_val - 1) : HOST_FRAME_MASK;
+}
+
+static struct hc_driver c67x00_hc_driver = {
+	.description	= "c67x00-hcd",
+	.product_desc	= "Cypress C67X00 Host Controller",
+	.hcd_priv_size	= sizeof(struct c67x00_hcd),
+	.flags		= HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start		= c67x00_hcd_start,
+	.stop		= c67x00_hcd_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue	= c67x00_urb_enqueue,
+	.urb_dequeue	= c67x00_urb_dequeue,
+	.endpoint_disable = c67x00_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = c67x00_hcd_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = c67x00_hub_status_data,
+	.hub_control	= c67x00_hub_control,
+};
+
+/* ---------------------------------------------------------------------
+ * Setup/Teardown routines
+ */
+
+int c67x00_hcd_probe(struct c67x00_sie *sie)
+{
+	struct c67x00_hcd *c67x00;
+	struct usb_hcd *hcd;
+	unsigned long flags;
+	int retval;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	hcd = usb_create_hcd(&c67x00_hc_driver, sie_dev(sie), "c67x00_sie");
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto err0;
+	}
+	c67x00 = hcd_to_c67x00_hcd(hcd);
+
+	spin_lock_init(&c67x00->lock);
+	c67x00->sie = sie;
+
+	INIT_LIST_HEAD(&c67x00->list[PIPE_ISOCHRONOUS]);
+	INIT_LIST_HEAD(&c67x00->list[PIPE_INTERRUPT]);
+	INIT_LIST_HEAD(&c67x00->list[PIPE_CONTROL]);
+	INIT_LIST_HEAD(&c67x00->list[PIPE_BULK]);
+	c67x00->urb_count = 0;
+	INIT_LIST_HEAD(&c67x00->td_list);
+	c67x00->td_base_addr = CY_HCD_BUF_ADDR + SIE_TD_OFFSET(sie->sie_num);
+	c67x00->buf_base_addr = CY_HCD_BUF_ADDR + SIE_BUF_OFFSET(sie->sie_num);
+	c67x00->max_frame_bw = MAX_FRAME_BW_STD;
+
+	c67x00_ll_husb_init_host_port(sie);
+
+	init_completion(&c67x00->endpoint_disable);
+	retval = c67x00_sched_start_scheduler(c67x00);
+	if (retval)
+		goto err1;
+
+	retval = usb_add_hcd(hcd, 0, 0);
+	if (retval) {
+		dev_dbg(sie_dev(sie), "%s: usb_add_hcd returned %d\n",
+			__func__, retval);
+		goto err2;
+	}
+
+	spin_lock_irqsave(&sie->lock, flags);
+	sie->private_data = c67x00;
+	sie->irq = c67x00_hcd_irq;
+	spin_unlock_irqrestore(&sie->lock, flags);
+
+	return retval;
+
+ err2:
+	c67x00_sched_stop_scheduler(c67x00);
+ err1:
+	usb_put_hcd(hcd);
+ err0:
+	return retval;
+}
+
+/* may be called with controller, bus, and devices active */
+void c67x00_hcd_remove(struct c67x00_sie *sie)
+{
+	struct c67x00_hcd *c67x00 = sie->private_data;
+	struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00);
+
+	c67x00_sched_stop_scheduler(c67x00);
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+}
diff --git a/drivers/usb/c67x00/c67x00-hcd.h b/drivers/usb/c67x00/c67x00-hcd.h
new file mode 100644
index 0000000..e8c6d94
--- /dev/null
+++ b/drivers/usb/c67x00/c67x00-hcd.h
@@ -0,0 +1,133 @@
+/*
+ * c67x00-hcd.h: Cypress C67X00 USB HCD
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ *    based on multiple host controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+#ifndef _USB_C67X00_HCD_H
+#define _USB_C67X00_HCD_H
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include "../core/hcd.h"
+#include "c67x00.h"
+
+/*
+ * The following parameters depend on the CPU speed, bus speed, ...
+ * These can be tuned for specific use cases, e.g. if isochronous transfers
+ * are very important, bandwith can be sacrificed to guarantee that the
+ * 1ms deadline will be met.
+ * If bulk transfers are important, the MAX_FRAME_BW can be increased,
+ * but some (or many) isochronous deadlines might not be met.
+ *
+ * The values are specified in bittime.
+ */
+
+/*
+ * The current implementation switches between _STD (default) and _ISO (when
+ * isochronous transfers are scheduled), in order to optimize the throughput
+ * in normal cicrumstances, but also provide good isochronous behaviour.
+ *
+ * Bandwidth is described in bit time so with a 12MHz USB clock and 1ms
+ * frames; there are 12000 bit times per frame.
+ */
+
+#define TOTAL_FRAME_BW		12000
+#define DEFAULT_EOT		2250
+
+#define MAX_FRAME_BW_STD	(TOTAL_FRAME_BW - DEFAULT_EOT)
+#define MAX_FRAME_BW_ISO	2400
+
+/*
+ * Periodic transfers may only use 90% of the full frame, but as
+ * we currently don't even use 90% of the full frame, we may
+ * use the full usable time for periodic transfers.
+ */
+#define MAX_PERIODIC_BW(full_bw)	full_bw
+
+/* -------------------------------------------------------------------------- */
+
+struct c67x00_hcd {
+	spinlock_t lock;
+	struct c67x00_sie *sie;
+	unsigned int low_speed_ports;	/* bitmask of low speed ports */
+	unsigned int urb_count;
+	unsigned int urb_iso_count;
+
+	struct list_head list[4];	/* iso, int, ctrl, bulk */
+#if PIPE_BULK != 3
+#error "Sanity check failed, this code presumes PIPE_... to range from 0 to 3"
+#endif
+
+	/* USB bandwidth allocated to td_list */
+	int bandwidth_allocated;
+	/* USB bandwidth allocated for isoc/int transfer */
+	int periodic_bw_allocated;
+	struct list_head td_list;
+	int max_frame_bw;
+
+	u16 td_base_addr;
+	u16 buf_base_addr;
+	u16 next_td_addr;
+	u16 next_buf_addr;
+
+	struct tasklet_struct tasklet;
+
+	struct completion endpoint_disable;
+
+	u16 current_frame;
+	u16 last_frame;
+};
+
+static inline struct c67x00_hcd *hcd_to_c67x00_hcd(struct usb_hcd *hcd)
+{
+	return (struct c67x00_hcd *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *c67x00_hcd_to_hcd(struct c67x00_hcd *c67x00)
+{
+	return container_of((void *)c67x00, struct usb_hcd, hcd_priv);
+}
+
+/* ---------------------------------------------------------------------
+ * Functions used by c67x00-drv
+ */
+
+int c67x00_hcd_probe(struct c67x00_sie *sie);
+void c67x00_hcd_remove(struct c67x00_sie *sie);
+
+/* ---------------------------------------------------------------------
+ * Transfer Descriptor scheduling functions
+ */
+int c67x00_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
+int c67x00_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
+void c67x00_endpoint_disable(struct usb_hcd *hcd,
+			     struct usb_host_endpoint *ep);
+
+void c67x00_hcd_msg_received(struct c67x00_sie *sie, u16 msg);
+void c67x00_sched_kick(struct c67x00_hcd *c67x00);
+int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00);
+void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00);
+
+#define c67x00_hcd_dev(x)	(c67x00_hcd_to_hcd(x)->self.controller)
+
+#endif				/* _USB_C67X00_HCD_H */
diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c b/drivers/usb/c67x00/c67x00-ll-hpi.c
new file mode 100644
index 0000000..f3430b3
--- /dev/null
+++ b/drivers/usb/c67x00/c67x00-ll-hpi.c
@@ -0,0 +1,480 @@
+/*
+ * c67x00-ll-hpi.c: Cypress C67X00 USB Low level interface using HPI
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ *    based on multiple host controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/usb/c67x00.h>
+#include "c67x00.h"
+
+#define COMM_REGS 14
+
+struct c67x00_lcp_int_data {
+	u16 regs[COMM_REGS];
+};
+
+/* -------------------------------------------------------------------------- */
+/* Interface definitions */
+
+#define COMM_ACK			0x0FED
+#define COMM_NAK			0xDEAD
+
+#define COMM_RESET			0xFA50
+#define COMM_EXEC_INT			0xCE01
+#define COMM_INT_NUM			0x01C2
+
+/* Registers 0 to COMM_REGS-1 */
+#define COMM_R(x)			(0x01C4 + 2 * (x))
+
+#define HUSB_SIE_pCurrentTDPtr(x)	((x) ? 0x01B2 : 0x01B0)
+#define HUSB_SIE_pTDListDone_Sem(x)	((x) ? 0x01B8 : 0x01B6)
+#define HUSB_pEOT			0x01B4
+
+/* Software interrupts */
+/* 114, 115: */
+#define HUSB_SIE_INIT_INT(x)		((x) ? 0x0073 : 0x0072)
+#define HUSB_RESET_INT			0x0074
+
+#define SUSB_INIT_INT			0x0071
+#define SUSB_INIT_INT_LOC		(SUSB_INIT_INT * 2)
+
+/* -----------------------------------------------------------------------
+ * HPI implementation
+ *
+ * The c67x00 chip also support control via SPI or HSS serial
+ * interfaces.  However, this driver assumes that register access can
+ * be performed from IRQ context.  While this is a safe assuption with
+ * the HPI interface, it is not true for the serial interfaces.
+ */
+
+/* HPI registers */
+#define HPI_DATA	0
+#define HPI_MAILBOX	1
+#define HPI_ADDR	2
+#define HPI_STATUS	3
+
+static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg)
+{
+	return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep);
+}
+
+static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value)
+{
+	__raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep);
+}
+
+static inline u16 hpi_read_word_nolock(struct c67x00_device *dev, u16 reg)
+{
+	hpi_write_reg(dev, HPI_ADDR, reg);
+	return hpi_read_reg(dev, HPI_DATA);
+}
+
+static u16 hpi_read_word(struct c67x00_device *dev, u16 reg)
+{
+	u16 value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	value = hpi_read_word_nolock(dev, reg);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+
+	return value;
+}
+
+static void hpi_write_word_nolock(struct c67x00_device *dev, u16 reg, u16 value)
+{
+	hpi_write_reg(dev, HPI_ADDR, reg);
+	hpi_write_reg(dev, HPI_DATA, value);
+}
+
+static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	hpi_write_word_nolock(dev, reg, value);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+}
+
+/*
+ * Only data is little endian, addr has cpu endianess
+ */
+static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr,
+				 u16 *data, u16 count)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+
+	hpi_write_reg(dev, HPI_ADDR, addr);
+	for (i = 0; i < count; i++)
+		hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++));
+
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+}
+
+/*
+ * Only data is little endian, addr has cpu endianess
+ */
+static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr,
+				u16 *data, u16 count)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	hpi_write_reg(dev, HPI_ADDR, addr);
+	for (i = 0; i < count; i++)
+		*data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA));
+
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+}
+
+static void hpi_set_bits(struct c67x00_device *dev, u16 reg, u16 mask)
+{
+	u16 value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	value = hpi_read_word_nolock(dev, reg);
+	hpi_write_word_nolock(dev, reg, value | mask);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+}
+
+static void hpi_clear_bits(struct c67x00_device *dev, u16 reg, u16 mask)
+{
+	u16 value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	value = hpi_read_word_nolock(dev, reg);
+	hpi_write_word_nolock(dev, reg, value & ~mask);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+}
+
+static u16 hpi_recv_mbox(struct c67x00_device *dev)
+{
+	u16 value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	value = hpi_read_reg(dev, HPI_MAILBOX);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+
+	return value;
+}
+
+static u16 hpi_send_mbox(struct c67x00_device *dev, u16 value)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	hpi_write_reg(dev, HPI_MAILBOX, value);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+
+	return value;
+}
+
+u16 c67x00_ll_hpi_status(struct c67x00_device *dev)
+{
+	u16 value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hpi.lock, flags);
+	value = hpi_read_reg(dev, HPI_STATUS);
+	spin_unlock_irqrestore(&dev->hpi.lock, flags);
+
+	return value;
+}
+
+void c67x00_ll_hpi_reg_init(struct c67x00_device *dev)
+{
+	int i;
+
+	hpi_recv_mbox(dev);
+	c67x00_ll_hpi_status(dev);
+	hpi_write_word(dev, HPI_IRQ_ROUTING_REG, 0);
+
+	for (i = 0; i < C67X00_SIES; i++) {
+		hpi_write_word(dev, SIEMSG_REG(i), 0);
+		hpi_read_word(dev, SIEMSG_REG(i));
+	}
+}
+
+void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie)
+{
+	hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG,
+		     SOFEOP_TO_HPI_EN(sie->sie_num));
+}
+
+void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie)
+{
+	hpi_clear_bits(sie->dev, HPI_IRQ_ROUTING_REG,
+		       SOFEOP_TO_HPI_EN(sie->sie_num));
+}
+
+/* -------------------------------------------------------------------------- */
+/* Transactions */
+
+static inline u16 ll_recv_msg(struct c67x00_device *dev)
+{
+	u16 res;
+
+	res = wait_for_completion_timeout(&dev->hpi.lcp.msg_received, 5 * HZ);
+	WARN_ON(!res);
+
+	return (res == 0) ? -EIO : 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* General functions */
+
+u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num)
+{
+	u16 val;
+
+	val = hpi_read_word(dev, SIEMSG_REG(sie_num));
+	/* clear register to allow next message */
+	hpi_write_word(dev, SIEMSG_REG(sie_num), 0);
+
+	return val;
+}
+
+u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie)
+{
+	return hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num));
+}
+
+/**
+ * c67x00_ll_usb_clear_status - clear the USB status bits
+ */
+void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits)
+{
+	hpi_write_word(sie->dev, USB_STAT_REG(sie->sie_num), bits);
+}
+
+u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie)
+{
+	return hpi_read_word(sie->dev, USB_STAT_REG(sie->sie_num));
+}
+
+/* -------------------------------------------------------------------------- */
+
+static int c67x00_comm_exec_int(struct c67x00_device *dev, u16 nr,
+				struct c67x00_lcp_int_data *data)
+{
+	int i, rc;
+
+	mutex_lock(&dev->hpi.lcp.mutex);
+	hpi_write_word(dev, COMM_INT_NUM, nr);
+	for (i = 0; i < COMM_REGS; i++)
+		hpi_write_word(dev, COMM_R(i), data->regs[i]);
+	hpi_send_mbox(dev, COMM_EXEC_INT);
+	rc = ll_recv_msg(dev);
+	mutex_unlock(&dev->hpi.lcp.mutex);
+
+	return rc;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Host specific functions */
+
+void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value)
+{
+	mutex_lock(&dev->hpi.lcp.mutex);
+	hpi_write_word(dev, HUSB_pEOT, value);
+	mutex_unlock(&dev->hpi.lcp.mutex);
+}
+
+static inline void c67x00_ll_husb_sie_init(struct c67x00_sie *sie)
+{
+	struct c67x00_device *dev = sie->dev;
+	struct c67x00_lcp_int_data data;
+	int rc;
+
+	rc = c67x00_comm_exec_int(dev, HUSB_SIE_INIT_INT(sie->sie_num), &data);
+	BUG_ON(rc); /* No return path for error code; crash spectacularly */
+}
+
+void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port)
+{
+	struct c67x00_device *dev = sie->dev;
+	struct c67x00_lcp_int_data data;
+	int rc;
+
+	data.regs[0] = 50;	/* Reset USB port for 50ms */
+	data.regs[1] = port | (sie->sie_num << 1);
+	rc = c67x00_comm_exec_int(dev, HUSB_RESET_INT, &data);
+	BUG_ON(rc); /* No return path for error code; crash spectacularly */
+}
+
+void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr)
+{
+	hpi_write_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num), addr);
+}
+
+u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie)
+{
+	return hpi_read_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num));
+}
+
+u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie)
+{
+	return hpi_read_word(sie->dev, HOST_FRAME_REG(sie->sie_num));
+}
+
+void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie)
+{
+	/* Set port into host mode */
+	hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), HOST_MODE);
+	c67x00_ll_husb_sie_init(sie);
+	/* Clear interrupts */
+	c67x00_ll_usb_clear_status(sie, HOST_STAT_MASK);
+	/* Check */
+	if (!(hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)) & HOST_MODE))
+		dev_warn(sie_dev(sie),
+			 "SIE %d not set to host mode\n", sie->sie_num);
+}
+
+void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port)
+{
+	/* Clear connect change */
+	c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port));
+
+	/* Enable interrupts */
+	hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG,
+		     SOFEOP_TO_CPU_EN(sie->sie_num));
+	hpi_set_bits(sie->dev, HOST_IRQ_EN_REG(sie->sie_num),
+		     SOF_EOP_IRQ_EN | DONE_IRQ_EN);
+
+	/* Enable pull down transistors */
+	hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), PORT_RES_EN(port));
+}
+
+/* -------------------------------------------------------------------------- */
+
+void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status)
+{
+	if ((int_status & MBX_OUT_FLG) == 0)
+		return;
+
+	dev->hpi.lcp.last_msg = hpi_recv_mbox(dev);
+	complete(&dev->hpi.lcp.msg_received);
+}
+
+/* -------------------------------------------------------------------------- */
+
+int c67x00_ll_reset(struct c67x00_device *dev)
+{
+	int rc;
+
+	mutex_lock(&dev->hpi.lcp.mutex);
+	hpi_send_mbox(dev, COMM_RESET);
+	rc = ll_recv_msg(dev);
+	mutex_unlock(&dev->hpi.lcp.mutex);
+
+	return rc;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * c67x00_ll_write_mem_le16 - write into c67x00 memory
+ * Only data is little endian, addr has cpu endianess.
+ */
+void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
+			      void *data, int len)
+{
+	u8 *buf = data;
+
+	/* Sanity check */
+	if (addr + len > 0xffff) {
+		dev_err(&dev->pdev->dev,
+			"Trying to write beyond writable region!\n");
+		return;
+	}
+
+	if (addr & 0x01) {
+		/* unaligned access */
+		u16 tmp;
+		tmp = hpi_read_word(dev, addr - 1);
+		tmp = (tmp & 0x00ff) | (*buf++ << 8);
+		hpi_write_word(dev, addr - 1, tmp);
+		addr++;
+		len--;
+	}
+
+	hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2);
+	buf += len & ~0x01;
+	addr += len & ~0x01;
+	len &= 0x01;
+
+	if (len) {
+		u16 tmp;
+		tmp = hpi_read_word(dev, addr);
+		tmp = (tmp & 0xff00) | *buf;
+		hpi_write_word(dev, addr, tmp);
+	}
+}
+
+/**
+ * c67x00_ll_read_mem_le16 - read from c67x00 memory
+ * Only data is little endian, addr has cpu endianess.
+ */
+void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
+			     void *data, int len)
+{
+	u8 *buf = data;
+
+	if (addr & 0x01) {
+		/* unaligned access */
+		u16 tmp;
+		tmp = hpi_read_word(dev, addr - 1);
+		*buf++ = (tmp >> 8) & 0x00ff;
+		addr++;
+		len--;
+	}
+
+	hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2);
+	buf += len & ~0x01;
+	addr += len & ~0x01;
+	len &= 0x01;
+
+	if (len) {
+		u16 tmp;
+		tmp = hpi_read_word(dev, addr);
+		*buf = tmp & 0x00ff;
+	}
+}
+
+/* -------------------------------------------------------------------------- */
+
+void c67x00_ll_init(struct c67x00_device *dev)
+{
+	mutex_init(&dev->hpi.lcp.mutex);
+	init_completion(&dev->hpi.lcp.msg_received);
+}
+
+void c67x00_ll_release(struct c67x00_device *dev)
+{
+}
diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c
new file mode 100644
index 0000000..85dfe29
--- /dev/null
+++ b/drivers/usb/c67x00/c67x00-sched.c
@@ -0,0 +1,1170 @@
+/*
+ * c67x00-sched.c: Cypress C67X00 USB Host Controller Driver - TD scheduling
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ *    based on multiple host controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+#include <linux/kthread.h>
+
+#include "c67x00.h"
+#include "c67x00-hcd.h"
+
+/*
+ * These are the stages for a control urb, they are kept
+ * in both urb->interval and td->privdata.
+ */
+#define SETUP_STAGE		0
+#define DATA_STAGE		1
+#define STATUS_STAGE		2
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * struct c67x00_ep_data: Host endpoint data structure
+ */
+struct c67x00_ep_data {
+	struct list_head queue;
+	struct list_head node;
+	struct usb_host_endpoint *hep;
+	struct usb_device *dev;
+	u16 next_frame;		/* For int/isoc transactions */
+};
+
+/**
+ * struct c67x00_td
+ *
+ * Hardware parts are little endiannes, SW in CPU endianess.
+ */
+struct c67x00_td {
+	/* HW specific part */
+	__le16 ly_base_addr;	/* Bytes 0-1 */
+	__le16 port_length;	/* Bytes 2-3 */
+	u8 pid_ep;		/* Byte 4 */
+	u8 dev_addr;		/* Byte 5 */
+	u8 ctrl_reg;		/* Byte 6 */
+	u8 status;		/* Byte 7 */
+	u8 retry_cnt;		/* Byte 8 */
+#define TT_OFFSET		2
+#define TT_CONTROL		0
+#define TT_ISOCHRONOUS		1
+#define TT_BULK			2
+#define TT_INTERRUPT		3
+	u8 residue;		/* Byte 9 */
+	__le16 next_td_addr;	/* Bytes 10-11 */
+	/* SW part */
+	struct list_head td_list;
+	u16 td_addr;
+	void *data;
+	struct urb *urb;
+	unsigned long privdata;
+
+	/* These are needed for handling the toggle bits:
+	 * an urb can be dequeued while a td is in progress
+	 * after checking the td, the toggle bit might need to
+	 * be fixed */
+	struct c67x00_ep_data *ep_data;
+	unsigned int pipe;
+};
+
+struct c67x00_urb_priv {
+	struct list_head hep_node;
+	struct urb *urb;
+	int port;
+	int cnt;		/* packet number for isoc */
+	int status;
+	struct c67x00_ep_data *ep_data;
+};
+
+#define td_udev(td)	((td)->ep_data->dev)
+
+#define CY_TD_SIZE		12
+
+#define TD_PIDEP_OFFSET		0x04
+#define TD_PIDEPMASK_PID	0xF0
+#define TD_PIDEPMASK_EP		0x0F
+#define TD_PORTLENMASK_DL	0x02FF
+#define TD_PORTLENMASK_PN	0xC000
+
+#define TD_STATUS_OFFSET	0x07
+#define TD_STATUSMASK_ACK	0x01
+#define TD_STATUSMASK_ERR	0x02
+#define TD_STATUSMASK_TMOUT	0x04
+#define TD_STATUSMASK_SEQ	0x08
+#define TD_STATUSMASK_SETUP	0x10
+#define TD_STATUSMASK_OVF	0x20
+#define TD_STATUSMASK_NAK	0x40
+#define TD_STATUSMASK_STALL	0x80
+
+#define TD_ERROR_MASK		(TD_STATUSMASK_ERR | TD_STATUSMASK_TMOUT | \
+				 TD_STATUSMASK_STALL)
+
+#define TD_RETRYCNT_OFFSET	0x08
+#define TD_RETRYCNTMASK_ACT_FLG	0x10
+#define TD_RETRYCNTMASK_TX_TYPE	0x0C
+#define TD_RETRYCNTMASK_RTY_CNT	0x03
+
+#define TD_RESIDUE_OVERFLOW	0x80
+
+#define TD_PID_IN		0x90
+
+/* Residue: signed 8bits, neg -> OVERFLOW, pos -> UNDERFLOW */
+#define td_residue(td)		((__s8)(td->residue))
+#define td_ly_base_addr(td)	(__le16_to_cpu((td)->ly_base_addr))
+#define td_port_length(td)	(__le16_to_cpu((td)->port_length))
+#define td_next_td_addr(td)	(__le16_to_cpu((td)->next_td_addr))
+
+#define td_active(td)		((td)->retry_cnt & TD_RETRYCNTMASK_ACT_FLG)
+#define td_length(td)		(td_port_length(td) & TD_PORTLENMASK_DL)
+
+#define td_sequence_ok(td)	(!td->status || \
+				 (!(td->status & TD_STATUSMASK_SEQ) ==	\
+				  !(td->ctrl_reg & SEQ_SEL)))
+
+#define td_acked(td)		(!td->status || \
+				 (td->status & TD_STATUSMASK_ACK))
+#define td_actual_bytes(td)	(td_length(td) - td_residue(td))
+
+/* -------------------------------------------------------------------------- */
+
+#ifdef DEBUG
+
+/**
+ * dbg_td - Dump the contents of the TD
+ */
+static void dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg)
+{
+	struct device *dev = c67x00_hcd_dev(c67x00);
+
+	dev_dbg(dev, "### %s at 0x%04x\n", msg, td->td_addr);
+	dev_dbg(dev, "urb:      0x%p\n", td->urb);
+	dev_dbg(dev, "endpoint:   %4d\n", usb_pipeendpoint(td->pipe));
+	dev_dbg(dev, "pipeout:    %4d\n", usb_pipeout(td->pipe));
+	dev_dbg(dev, "ly_base_addr: 0x%04x\n", td_ly_base_addr(td));
+	dev_dbg(dev, "port_length:  0x%04x\n", td_port_length(td));
+	dev_dbg(dev, "pid_ep:         0x%02x\n", td->pid_ep);
+	dev_dbg(dev, "dev_addr:       0x%02x\n", td->dev_addr);
+	dev_dbg(dev, "ctrl_reg:       0x%02x\n", td->ctrl_reg);
+	dev_dbg(dev, "status:         0x%02x\n", td->status);
+	dev_dbg(dev, "retry_cnt:      0x%02x\n", td->retry_cnt);
+	dev_dbg(dev, "residue:        0x%02x\n", td->residue);
+	dev_dbg(dev, "next_td_addr: 0x%04x\n", td_next_td_addr(td));
+	dev_dbg(dev, "data:");
+	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
+		       td->data, td_length(td), 1);
+}
+#else				/* DEBUG */
+
+static inline void
+dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg) { }
+
+#endif				/* DEBUG */
+
+/* -------------------------------------------------------------------------- */
+/* Helper functions */
+
+static inline u16 c67x00_get_current_frame_number(struct c67x00_hcd *c67x00)
+{
+	return c67x00_ll_husb_get_frame(c67x00->sie) & HOST_FRAME_MASK;
+}
+
+/**
+ * frame_add
+ * Software wraparound for framenumbers.
+ */
+static inline u16 frame_add(u16 a, u16 b)
+{
+	return (a + b) & HOST_FRAME_MASK;
+}
+
+/**
+ * frame_after - is frame a after frame b
+ */
+static inline int frame_after(u16 a, u16 b)
+{
+	return ((HOST_FRAME_MASK + a - b) & HOST_FRAME_MASK) <
+	    (HOST_FRAME_MASK / 2);
+}
+
+/**
+ * frame_after_eq - is frame a after or equal to frame b
+ */
+static inline int frame_after_eq(u16 a, u16 b)
+{
+	return ((HOST_FRAME_MASK + 1 + a - b) & HOST_FRAME_MASK) <
+	    (HOST_FRAME_MASK / 2);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * c67x00_release_urb - remove link from all tds to this urb
+ * Disconnects the urb from it's tds, so that it can be given back.
+ * pre: urb->hcpriv != NULL
+ */
+static void c67x00_release_urb(struct c67x00_hcd *c67x00, struct urb *urb)
+{
+	struct c67x00_td *td;
+	struct c67x00_urb_priv *urbp;
+
+	BUG_ON(!urb);
+
+	c67x00->urb_count--;
+
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+		c67x00->urb_iso_count--;
+		if (c67x00->urb_iso_count == 0)
+			c67x00->max_frame_bw = MAX_FRAME_BW_STD;
+	}
+
+	/* TODO this might be not so efficient when we've got many urbs!
+	 * Alternatives:
+	 *   * only clear when needed
+	 *   * keep a list of tds with each urbp
+	 */
+	list_for_each_entry(td, &c67x00->td_list, td_list)
+		if (urb == td->urb)
+			td->urb = NULL;
+
+	urbp = urb->hcpriv;
+	urb->hcpriv = NULL;
+	list_del(&urbp->hep_node);
+	kfree(urbp);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static struct c67x00_ep_data *
+c67x00_ep_data_alloc(struct c67x00_hcd *c67x00, struct urb *urb)
+{
+	struct usb_host_endpoint *hep = urb->ep;
+	struct c67x00_ep_data *ep_data;
+	int type;
+
+	c67x00->current_frame = c67x00_get_current_frame_number(c67x00);
+
+	/* Check if endpoint already has a c67x00_ep_data struct allocated */
+	if (hep->hcpriv) {
+		ep_data = hep->hcpriv;
+		if (frame_after(c67x00->current_frame, ep_data->next_frame))
+			ep_data->next_frame =
+			    frame_add(c67x00->current_frame, 1);
+		return hep->hcpriv;
+	}
+
+	/* Allocate and initialize a new c67x00 endpoint data structure */
+	ep_data = kzalloc(sizeof(*ep_data), GFP_ATOMIC);
+	if (!ep_data)
+		return NULL;
+
+	INIT_LIST_HEAD(&ep_data->queue);
+	INIT_LIST_HEAD(&ep_data->node);
+	ep_data->hep = hep;
+
+	/* hold a reference to udev as long as this endpoint lives,
+	 * this is needed to possibly fix the data toggle */
+	ep_data->dev = usb_get_dev(urb->dev);
+	hep->hcpriv = ep_data;
+
+	/* For ISOC and INT endpoints, start ASAP: */
+	ep_data->next_frame = frame_add(c67x00->current_frame, 1);
+
+	/* Add the endpoint data to one of the pipe lists; must be added
+	   in order of endpoint address */
+	type = usb_pipetype(urb->pipe);
+	if (list_empty(&ep_data->node)) {
+		list_add(&ep_data->node, &c67x00->list[type]);
+	} else {
+		struct c67x00_ep_data *prev;
+
+		list_for_each_entry(prev, &c67x00->list[type], node) {
+			if (prev->hep->desc.bEndpointAddress >
+			    hep->desc.bEndpointAddress) {
+				list_add(&ep_data->node, prev->node.prev);
+				break;
+			}
+		}
+	}
+
+	return ep_data;
+}
+
+static int c67x00_ep_data_free(struct usb_host_endpoint *hep)
+{
+	struct c67x00_ep_data *ep_data = hep->hcpriv;
+
+	if (!ep_data)
+		return 0;
+
+	if (!list_empty(&ep_data->queue))
+		return -EBUSY;
+
+	usb_put_dev(ep_data->dev);
+	list_del(&ep_data->queue);
+	list_del(&ep_data->node);
+
+	kfree(ep_data);
+	hep->hcpriv = NULL;
+
+	return 0;
+}
+
+void c67x00_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+{
+	struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
+	unsigned long flags;
+
+	if (!list_empty(&ep->urb_list))
+		dev_warn(c67x00_hcd_dev(c67x00), "error: urb list not empty\n");
+
+	spin_lock_irqsave(&c67x00->lock, flags);
+
+	/* loop waiting for all transfers in the endpoint queue to complete */
+	while (c67x00_ep_data_free(ep)) {
+		/* Drop the lock so we can sleep waiting for the hardware */
+		spin_unlock_irqrestore(&c67x00->lock, flags);
+
+		/* it could happen that we reinitialize this completion, while
+		 * somebody was waiting for that completion.  The timeout and
+		 * while loop handle such cases, but this might be improved */
+		INIT_COMPLETION(c67x00->endpoint_disable);
+		c67x00_sched_kick(c67x00);
+		wait_for_completion_timeout(&c67x00->endpoint_disable, 1 * HZ);
+
+		spin_lock_irqsave(&c67x00->lock, flags);
+	}
+
+	spin_unlock_irqrestore(&c67x00->lock, flags);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static inline int get_root_port(struct usb_device *dev)
+{
+	while (dev->parent->parent)
+		dev = dev->parent;
+	return dev->portnum;
+}
+
+int c67x00_urb_enqueue(struct usb_hcd *hcd,
+		       struct urb *urb, gfp_t mem_flags)
+{
+	int ret;
+	unsigned long flags;
+	struct c67x00_urb_priv *urbp;
+	struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
+	int port = get_root_port(urb->dev)-1;
+
+	spin_lock_irqsave(&c67x00->lock, flags);
+
+	/* Make sure host controller is running */
+	if (!HC_IS_RUNNING(hcd->state)) {
+		ret = -ENODEV;
+		goto err_not_linked;
+	}
+
+	ret = usb_hcd_link_urb_to_ep(hcd, urb);
+	if (ret)
+		goto err_not_linked;
+
+	/* Allocate and initialize urb private data */
+	urbp = kzalloc(sizeof(*urbp), mem_flags);
+	if (!urbp) {
+		ret = -ENOMEM;
+		goto err_urbp;
+	}
+
+	INIT_LIST_HEAD(&urbp->hep_node);
+	urbp->urb = urb;
+	urbp->port = port;
+
+	urbp->ep_data = c67x00_ep_data_alloc(c67x00, urb);
+
+	if (!urbp->ep_data) {
+		ret = -ENOMEM;
+		goto err_epdata;
+	}
+
+	/* TODO claim bandwidth with usb_claim_bandwidth?
+	 * also release it somewhere! */
+
+	urb->hcpriv = urbp;
+
+	urb->actual_length = 0;	/* Nothing received/transmitted yet */
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		urb->interval = SETUP_STAGE;
+		break;
+	case PIPE_INTERRUPT:
+		break;
+	case PIPE_BULK:
+		break;
+	case PIPE_ISOCHRONOUS:
+		if (c67x00->urb_iso_count == 0)
+			c67x00->max_frame_bw = MAX_FRAME_BW_ISO;
+		c67x00->urb_iso_count++;
+		/* Assume always URB_ISO_ASAP, FIXME */
+		if (list_empty(&urbp->ep_data->queue))
+			urb->start_frame = urbp->ep_data->next_frame;
+		else {
+			/* Go right after the last one */
+			struct urb *last_urb;
+
+			last_urb = list_entry(urbp->ep_data->queue.prev,
+					      struct c67x00_urb_priv,
+					      hep_node)->urb;
+			urb->start_frame =
+			    frame_add(last_urb->start_frame,
+				      last_urb->number_of_packets *
+				      last_urb->interval);
+		}
+		urbp->cnt = 0;
+		break;
+	}
+
+	/* Add the URB to the endpoint queue */
+	list_add_tail(&urbp->hep_node, &urbp->ep_data->queue);
+
+	/* If this is the only URB, kick start the controller */
+	if (!c67x00->urb_count++)
+		c67x00_ll_hpi_enable_sofeop(c67x00->sie);
+
+	c67x00_sched_kick(c67x00);
+	spin_unlock_irqrestore(&c67x00->lock, flags);
+
+	return 0;
+
+err_epdata:
+	kfree(urbp);
+err_urbp:
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+err_not_linked:
+	spin_unlock_irqrestore(&c67x00->lock, flags);
+
+	return ret;
+}
+
+int c67x00_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+	struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&c67x00->lock, flags);
+	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+	if (rc)
+		goto done;
+
+	c67x00_release_urb(c67x00, urb);
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+	spin_unlock(&c67x00->lock);
+	usb_hcd_giveback_urb(hcd, urb, status);
+	spin_lock(&c67x00->lock);
+
+	spin_unlock_irqrestore(&c67x00->lock, flags);
+
+	return 0;
+
+ done:
+	spin_unlock_irqrestore(&c67x00->lock, flags);
+	return rc;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * pre: c67x00 locked, urb unlocked
+ */
+static void
+c67x00_giveback_urb(struct c67x00_hcd *c67x00, struct urb *urb, int status)
+{
+	struct c67x00_urb_priv *urbp;
+
+	if (!urb)
+		return;
+
+	urbp = urb->hcpriv;
+	urbp->status = status;
+
+	list_del_init(&urbp->hep_node);
+
+	c67x00_release_urb(c67x00, urb);
+	usb_hcd_unlink_urb_from_ep(c67x00_hcd_to_hcd(c67x00), urb);
+	spin_unlock(&c67x00->lock);
+	usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, urbp->status);
+	spin_lock(&c67x00->lock);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static int c67x00_claim_frame_bw(struct c67x00_hcd *c67x00, struct urb *urb,
+				 int len, int periodic)
+{
+	struct c67x00_urb_priv *urbp = urb->hcpriv;
+	int bit_time;
+
+	/* According to the C67x00 BIOS user manual, page 3-18,19, the
+	 * following calculations provide the full speed bit times for
+	 * a transaction.
+	 *
+	 * FS(in)	= 112.5 +  9.36*BC + HOST_DELAY
+	 * FS(in,iso)	=  90.5 +  9.36*BC + HOST_DELAY
+	 * FS(out)	= 112.5 +  9.36*BC + HOST_DELAY
+	 * FS(out,iso)	=  78.4 +  9.36*BC + HOST_DELAY
+	 * LS(in)	= 802.4 + 75.78*BC + HOST_DELAY
+	 * LS(out)	= 802.6 + 74.67*BC + HOST_DELAY
+	 *
+	 * HOST_DELAY == 106 for the c67200 and c67300.
+	 */
+
+	/* make calculations in 1/100 bit times to maintain resolution */
+	if (urbp->ep_data->dev->speed == USB_SPEED_LOW) {
+		/* Low speed pipe */
+		if (usb_pipein(urb->pipe))
+			bit_time = 80240 + 7578*len;
+		else
+			bit_time = 80260 + 7467*len;
+	} else {
+		/* FS pipes */
+		if (usb_pipeisoc(urb->pipe))
+			bit_time = usb_pipein(urb->pipe) ? 9050 : 7840;
+		else
+			bit_time = 11250;
+		bit_time += 936*len;
+	}
+
+	/* Scale back down to integer bit times.  Use a host delay of 106.
+	 * (this is the only place it is used) */
+	bit_time = ((bit_time+50) / 100) + 106;
+
+	if (unlikely(bit_time + c67x00->bandwidth_allocated >=
+		     c67x00->max_frame_bw))
+		return -EMSGSIZE;
+
+	if (unlikely(c67x00->next_td_addr + CY_TD_SIZE >=
+		     c67x00->td_base_addr + SIE_TD_SIZE))
+		return -EMSGSIZE;
+
+	if (unlikely(c67x00->next_buf_addr + len >=
+		     c67x00->buf_base_addr + SIE_TD_BUF_SIZE))
+		return -EMSGSIZE;
+
+	if (periodic) {
+		if (unlikely(bit_time + c67x00->periodic_bw_allocated >=
+			     MAX_PERIODIC_BW(c67x00->max_frame_bw)))
+			return -EMSGSIZE;
+		c67x00->periodic_bw_allocated += bit_time;
+	}
+
+	c67x00->bandwidth_allocated += bit_time;
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * td_addr and buf_addr must be word aligned
+ */
+static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb,
+			    void *data, int len, int pid, int toggle,
+			    unsigned long privdata)
+{
+	struct c67x00_td *td;
+	struct c67x00_urb_priv *urbp = urb->hcpriv;
+	const __u8 active_flag = 1, retry_cnt = 1;
+	__u8 cmd = 0;
+	int tt = 0;
+
+	if (c67x00_claim_frame_bw(c67x00, urb, len, usb_pipeisoc(urb->pipe)
+				  || usb_pipeint(urb->pipe)))
+		return -EMSGSIZE;	/* Not really an error, but expected */
+
+	td = kzalloc(sizeof(*td), GFP_ATOMIC);
+	if (!td)
+		return -ENOMEM;
+
+	td->pipe = urb->pipe;
+	td->ep_data = urbp->ep_data;
+
+	if ((td_udev(td)->speed == USB_SPEED_LOW) &&
+	    !(c67x00->low_speed_ports & (1 << urbp->port)))
+		cmd |= PREAMBLE_EN;
+
+	switch (usb_pipetype(td->pipe)) {
+	case PIPE_ISOCHRONOUS:
+		tt = TT_ISOCHRONOUS;
+		cmd |= ISO_EN;
+		break;
+	case PIPE_CONTROL:
+		tt = TT_CONTROL;
+		break;
+	case PIPE_BULK:
+		tt = TT_BULK;
+		break;
+	case PIPE_INTERRUPT:
+		tt = TT_INTERRUPT;
+		break;
+	}
+
+	if (toggle)
+		cmd |= SEQ_SEL;
+
+	cmd |= ARM_EN;
+
+	/* SW part */
+	td->td_addr = c67x00->next_td_addr;
+	c67x00->next_td_addr = c67x00->next_td_addr + CY_TD_SIZE;
+
+	/* HW part */
+	td->ly_base_addr = __cpu_to_le16(c67x00->next_buf_addr);
+	td->port_length = __cpu_to_le16((c67x00->sie->sie_num << 15) |
+					(urbp->port << 14) | (len & 0x3FF));
+	td->pid_ep = ((pid & 0xF) << TD_PIDEP_OFFSET) |
+	    (usb_pipeendpoint(td->pipe) & 0xF);
+	td->dev_addr = usb_pipedevice(td->pipe) & 0x7F;
+	td->ctrl_reg = cmd;
+	td->status = 0;
+	td->retry_cnt = (tt << TT_OFFSET) | (active_flag << 4) | retry_cnt;
+	td->residue = 0;
+	td->next_td_addr = __cpu_to_le16(c67x00->next_td_addr);
+
+	/* SW part */
+	td->data = data;
+	td->urb = urb;
+	td->privdata = privdata;
+
+	c67x00->next_buf_addr += (len + 1) & ~0x01;	/* properly align */
+
+	list_add_tail(&td->td_list, &c67x00->td_list);
+	return 0;
+}
+
+static inline void c67x00_release_td(struct c67x00_td *td)
+{
+	list_del_init(&td->td_list);
+	kfree(td);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static int c67x00_add_data_urb(struct c67x00_hcd *c67x00, struct urb *urb)
+{
+	int remaining;
+	int toggle;
+	int pid;
+	int ret = 0;
+	int maxps;
+	int need_empty;
+
+	toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			       usb_pipeout(urb->pipe));
+	remaining = urb->transfer_buffer_length - urb->actual_length;
+
+	maxps = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+
+	need_empty = (urb->transfer_flags & URB_ZERO_PACKET) &&
+	    usb_pipeout(urb->pipe) && !(remaining % maxps);
+
+	while (remaining || need_empty) {
+		int len;
+		char *td_buf;
+
+		len = (remaining > maxps) ? maxps : remaining;
+		if (!len)
+			need_empty = 0;
+
+		pid = usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN;
+		td_buf = urb->transfer_buffer + urb->transfer_buffer_length -
+		    remaining;
+		ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, toggle,
+				       DATA_STAGE);
+		if (ret)
+			return ret;	/* td wasn't created */
+
+		toggle ^= 1;
+		remaining -= len;
+		if (usb_pipecontrol(urb->pipe))
+			break;
+	}
+
+	return 0;
+}
+
+/**
+ * return 0 in case more bandwidth is available, else errorcode
+ */
+static int c67x00_add_ctrl_urb(struct c67x00_hcd *c67x00, struct urb *urb)
+{
+	int ret;
+	int pid;
+
+	switch (urb->interval) {
+	default:
+	case SETUP_STAGE:
+		ret = c67x00_create_td(c67x00, urb, urb->setup_packet,
+				       8, USB_PID_SETUP, 0, SETUP_STAGE);
+		if (ret)
+			return ret;
+		urb->interval = SETUP_STAGE;
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			      usb_pipeout(urb->pipe), 1);
+		break;
+	case DATA_STAGE:
+		if (urb->transfer_buffer_length) {
+			ret = c67x00_add_data_urb(c67x00, urb);
+			if (ret)
+				return ret;
+			break;
+		}		/* else fallthrough */
+	case STATUS_STAGE:
+		pid = !usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN;
+		ret = c67x00_create_td(c67x00, urb, NULL, 0, pid, 1,
+				       STATUS_STAGE);
+		if (ret)
+			return ret;
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * return 0 in case more bandwidth is available, else errorcode
+ */
+static int c67x00_add_int_urb(struct c67x00_hcd *c67x00, struct urb *urb)
+{
+	struct c67x00_urb_priv *urbp = urb->hcpriv;
+
+	if (frame_after_eq(c67x00->current_frame, urbp->ep_data->next_frame)) {
+		urbp->ep_data->next_frame =
+		    frame_add(urbp->ep_data->next_frame, urb->interval);
+		return c67x00_add_data_urb(c67x00, urb);
+	}
+	return 0;
+}
+
+static int c67x00_add_iso_urb(struct c67x00_hcd *c67x00, struct urb *urb)
+{
+	struct c67x00_urb_priv *urbp = urb->hcpriv;
+
+	if (frame_after_eq(c67x00->current_frame, urbp->ep_data->next_frame)) {
+		char *td_buf;
+		int len, pid, ret;
+
+		BUG_ON(urbp->cnt >= urb->number_of_packets);
+
+		td_buf = urb->transfer_buffer +
+		    urb->iso_frame_desc[urbp->cnt].offset;
+		len = urb->iso_frame_desc[urbp->cnt].length;
+		pid = usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN;
+
+		ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, 0,
+				       urbp->cnt);
+		if (ret) {
+			printk(KERN_DEBUG "create failed: %d\n", ret);
+			urb->iso_frame_desc[urbp->cnt].actual_length = 0;
+			urb->iso_frame_desc[urbp->cnt].status = ret;
+			if (urbp->cnt + 1 == urb->number_of_packets)
+				c67x00_giveback_urb(c67x00, urb, 0);
+		}
+
+		urbp->ep_data->next_frame =
+		    frame_add(urbp->ep_data->next_frame, urb->interval);
+		urbp->cnt++;
+	}
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void c67x00_fill_from_list(struct c67x00_hcd *c67x00, int type,
+				  int (*add)(struct c67x00_hcd *, struct urb *))
+{
+	struct c67x00_ep_data *ep_data;
+	struct urb *urb;
+
+	/* traverse every endpoint on the list */
+	list_for_each_entry(ep_data, &c67x00->list[type], node) {
+		if (!list_empty(&ep_data->queue)) {
+			/* and add the first urb */
+			/* isochronous transfer rely on this */
+			urb = list_entry(ep_data->queue.next,
+					 struct c67x00_urb_priv,
+					 hep_node)->urb;
+			add(c67x00, urb);
+		}
+	}
+}
+
+static void c67x00_fill_frame(struct c67x00_hcd *c67x00)
+{
+	struct c67x00_td *td, *ttd;
+
+	/* Check if we can proceed */
+	if (!list_empty(&c67x00->td_list)) {
+		dev_warn(c67x00_hcd_dev(c67x00),
+			 "TD list not empty! This should not happen!\n");
+		list_for_each_entry_safe(td, ttd, &c67x00->td_list, td_list) {
+			dbg_td(c67x00, td, "Unprocessed td");
+			c67x00_release_td(td);
+		}
+	}
+
+	/* Reinitialize variables */
+	c67x00->bandwidth_allocated = 0;
+	c67x00->periodic_bw_allocated = 0;
+
+	c67x00->next_td_addr = c67x00->td_base_addr;
+	c67x00->next_buf_addr = c67x00->buf_base_addr;
+
+	/* Fill the list */
+	c67x00_fill_from_list(c67x00, PIPE_ISOCHRONOUS, c67x00_add_iso_urb);
+	c67x00_fill_from_list(c67x00, PIPE_INTERRUPT, c67x00_add_int_urb);
+	c67x00_fill_from_list(c67x00, PIPE_CONTROL, c67x00_add_ctrl_urb);
+	c67x00_fill_from_list(c67x00, PIPE_BULK, c67x00_add_data_urb);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * Get TD from C67X00
+ */
+static inline void
+c67x00_parse_td(struct c67x00_hcd *c67x00, struct c67x00_td *td)
+{
+	c67x00_ll_read_mem_le16(c67x00->sie->dev,
+				td->td_addr, td, CY_TD_SIZE);
+
+	if (usb_pipein(td->pipe) && td_actual_bytes(td))
+		c67x00_ll_read_mem_le16(c67x00->sie->dev, td_ly_base_addr(td),
+					td->data, td_actual_bytes(td));
+}
+
+static int c67x00_td_to_error(struct c67x00_hcd *c67x00, struct c67x00_td *td)
+{
+	if (td->status & TD_STATUSMASK_ERR) {
+		dbg_td(c67x00, td, "ERROR_FLAG");
+		return -EILSEQ;
+	}
+	if (td->status & TD_STATUSMASK_STALL) {
+		/* dbg_td(c67x00, td, "STALL"); */
+		return -EPIPE;
+	}
+	if (td->status & TD_STATUSMASK_TMOUT) {
+		dbg_td(c67x00, td, "TIMEOUT");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static inline int c67x00_end_of_data(struct c67x00_td *td)
+{
+	int maxps, need_empty, remaining;
+	struct urb *urb = td->urb;
+	int act_bytes;
+
+	act_bytes = td_actual_bytes(td);
+
+	if (unlikely(!act_bytes))
+		return 1;	/* This was an empty packet */
+
+	maxps = usb_maxpacket(td_udev(td), td->pipe, usb_pipeout(td->pipe));
+
+	if (unlikely(act_bytes < maxps))
+		return 1;	/* Smaller then full packet */
+
+	remaining = urb->transfer_buffer_length - urb->actual_length;
+	need_empty = (urb->transfer_flags & URB_ZERO_PACKET) &&
+	    usb_pipeout(urb->pipe) && !(remaining % maxps);
+
+	if (unlikely(!remaining && !need_empty))
+		return 1;
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Remove all td's from the list which come
+ * after last_td and are meant for the same pipe.
+ * This is used when a short packet has occured */
+static inline void c67x00_clear_pipe(struct c67x00_hcd *c67x00,
+				     struct c67x00_td *last_td)
+{
+	struct c67x00_td *td, *tmp;
+	td = last_td;
+	tmp = last_td;
+	while (td->td_list.next != &c67x00->td_list) {
+		td = list_entry(td->td_list.next, struct c67x00_td, td_list);
+		if (td->pipe == last_td->pipe) {
+			c67x00_release_td(td);
+			td = tmp;
+		}
+		tmp = td;
+	}
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void c67x00_handle_successful_td(struct c67x00_hcd *c67x00,
+					struct c67x00_td *td)
+{
+	struct urb *urb = td->urb;
+
+	if (!urb)
+		return;
+
+	urb->actual_length += td_actual_bytes(td);
+
+	switch (usb_pipetype(td->pipe)) {
+		/* isochronous tds are handled separately */
+	case PIPE_CONTROL:
+		switch (td->privdata) {
+		case SETUP_STAGE:
+			urb->interval =
+			    urb->transfer_buffer_length ?
+			    DATA_STAGE : STATUS_STAGE;
+			/* Don't count setup_packet with normal data: */
+			urb->actual_length = 0;
+			break;
+
+		case DATA_STAGE:
+			if (c67x00_end_of_data(td)) {
+				urb->interval = STATUS_STAGE;
+				c67x00_clear_pipe(c67x00, td);
+			}
+			break;
+
+		case STATUS_STAGE:
+			urb->interval = 0;
+			c67x00_giveback_urb(c67x00, urb, 0);
+			break;
+		}
+		break;
+
+	case PIPE_INTERRUPT:
+	case PIPE_BULK:
+		if (unlikely(c67x00_end_of_data(td))) {
+			c67x00_clear_pipe(c67x00, td);
+			c67x00_giveback_urb(c67x00, urb, 0);
+		}
+		break;
+	}
+}
+
+static void c67x00_handle_isoc(struct c67x00_hcd *c67x00, struct c67x00_td *td)
+{
+	struct urb *urb = td->urb;
+	struct c67x00_urb_priv *urbp;
+	int cnt;
+
+	if (!urb)
+		return;
+
+	urbp = urb->hcpriv;
+	cnt = td->privdata;
+
+	if (td->status & TD_ERROR_MASK)
+		urb->error_count++;
+
+	urb->iso_frame_desc[cnt].actual_length = td_actual_bytes(td);
+	urb->iso_frame_desc[cnt].status = c67x00_td_to_error(c67x00, td);
+	if (cnt + 1 == urb->number_of_packets)	/* Last packet */
+		c67x00_giveback_urb(c67x00, urb, 0);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * c67x00_check_td_list - handle tds which have been processed by the c67x00
+ * pre: current_td == 0
+ */
+static inline void c67x00_check_td_list(struct c67x00_hcd *c67x00)
+{
+	struct c67x00_td *td, *tmp;
+	struct urb *urb;
+	int ack_ok;
+	int clear_endpoint;
+
+	list_for_each_entry_safe(td, tmp, &c67x00->td_list, td_list) {
+		/* get the TD */
+		c67x00_parse_td(c67x00, td);
+		urb = td->urb;	/* urb can be NULL! */
+		ack_ok = 0;
+		clear_endpoint = 1;
+
+		/* Handle isochronous transfers separately */
+		if (usb_pipeisoc(td->pipe)) {
+			clear_endpoint = 0;
+			c67x00_handle_isoc(c67x00, td);
+			goto cont;
+		}
+
+		/* When an error occurs, all td's for that pipe go into an
+		 * inactive state. This state matches successful transfers so
+		 * we must make sure not to service them. */
+		if (td->status & TD_ERROR_MASK) {
+			c67x00_giveback_urb(c67x00, urb,
+					    c67x00_td_to_error(c67x00, td));
+			goto cont;
+		}
+
+		if ((td->status & TD_STATUSMASK_NAK) || !td_sequence_ok(td) ||
+		    !td_acked(td))
+			goto cont;
+
+		/* Sequence ok and acked, don't need to fix toggle */
+		ack_ok = 1;
+
+		if (unlikely(td->status & TD_STATUSMASK_OVF)) {
+			if (td_residue(td) & TD_RESIDUE_OVERFLOW) {
+				/* Overflow */
+				c67x00_giveback_urb(c67x00, urb, -EOVERFLOW);
+				goto cont;
+			}
+		}
+
+		clear_endpoint = 0;
+		c67x00_handle_successful_td(c67x00, td);
+
+cont:
+		if (clear_endpoint)
+			c67x00_clear_pipe(c67x00, td);
+		if (ack_ok)
+			usb_settoggle(td_udev(td), usb_pipeendpoint(td->pipe),
+				      usb_pipeout(td->pipe),
+				      !(td->ctrl_reg & SEQ_SEL));
+		/* next in list could have been removed, due to clear_pipe! */
+		tmp = list_entry(td->td_list.next, typeof(*td), td_list);
+		c67x00_release_td(td);
+	}
+}
+
+/* -------------------------------------------------------------------------- */
+
+static inline int c67x00_all_tds_processed(struct c67x00_hcd *c67x00)
+{
+	/* If all tds are processed, we can check the previous frame (if
+	 * there was any) and start our next frame.
+	 */
+	return !c67x00_ll_husb_get_current_td(c67x00->sie);
+}
+
+/**
+ * Send td to C67X00
+ */
+static void c67x00_send_td(struct c67x00_hcd *c67x00, struct c67x00_td *td)
+{
+	int len = td_length(td);
+
+	if (len && ((td->pid_ep & TD_PIDEPMASK_PID) != TD_PID_IN))
+		c67x00_ll_write_mem_le16(c67x00->sie->dev, td_ly_base_addr(td),
+					 td->data, len);
+
+	c67x00_ll_write_mem_le16(c67x00->sie->dev,
+				 td->td_addr, td, CY_TD_SIZE);
+}
+
+static void c67x00_send_frame(struct c67x00_hcd *c67x00)
+{
+	struct c67x00_td *td;
+
+	if (list_empty(&c67x00->td_list))
+		dev_warn(c67x00_hcd_dev(c67x00),
+			 "%s: td list should not be empty here!\n",
+			 __func__);
+
+	list_for_each_entry(td, &c67x00->td_list, td_list) {
+		if (td->td_list.next == &c67x00->td_list)
+			td->next_td_addr = 0;	/* Last td in list */
+
+		c67x00_send_td(c67x00, td);
+	}
+
+	c67x00_ll_husb_set_current_td(c67x00->sie, c67x00->td_base_addr);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * c67x00_do_work - Schedulers state machine
+ */
+static void c67x00_do_work(struct c67x00_hcd *c67x00)
+{
+	spin_lock(&c67x00->lock);
+	/* Make sure all tds are processed */
+	if (!c67x00_all_tds_processed(c67x00))
+		goto out;
+
+	c67x00_check_td_list(c67x00);
+
+	/* no td's are being processed (current == 0)
+	 * and all have been "checked" */
+	complete(&c67x00->endpoint_disable);
+
+	if (!list_empty(&c67x00->td_list))
+		goto out;
+
+	c67x00->current_frame = c67x00_get_current_frame_number(c67x00);
+	if (c67x00->current_frame == c67x00->last_frame)
+		goto out;	/* Don't send tds in same frame */
+	c67x00->last_frame = c67x00->current_frame;
+
+	/* If no urbs are scheduled, our work is done */
+	if (!c67x00->urb_count) {
+		c67x00_ll_hpi_disable_sofeop(c67x00->sie);
+		goto out;
+	}
+
+	c67x00_fill_frame(c67x00);
+	if (!list_empty(&c67x00->td_list))
+		/* TD's have been added to the frame */
+		c67x00_send_frame(c67x00);
+
+ out:
+	spin_unlock(&c67x00->lock);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void c67x00_sched_tasklet(unsigned long __c67x00)
+{
+	struct c67x00_hcd *c67x00 = (struct c67x00_hcd *)__c67x00;
+	c67x00_do_work(c67x00);
+}
+
+void c67x00_sched_kick(struct c67x00_hcd *c67x00)
+{
+	tasklet_hi_schedule(&c67x00->tasklet);
+}
+
+int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00)
+{
+	tasklet_init(&c67x00->tasklet, c67x00_sched_tasklet,
+		     (unsigned long)c67x00);
+	return 0;
+}
+
+void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00)
+{
+	tasklet_kill(&c67x00->tasklet);
+}
diff --git a/drivers/usb/c67x00/c67x00.h b/drivers/usb/c67x00/c67x00.h
new file mode 100644
index 0000000..a26e9de
--- /dev/null
+++ b/drivers/usb/c67x00/c67x00.h
@@ -0,0 +1,294 @@
+/*
+ * c67x00.h: Cypress C67X00 USB register and field definitions
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ *    based on multiple host controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+#ifndef _USB_C67X00_H
+#define _USB_C67X00_H
+
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+
+/* ---------------------------------------------------------------------
+ * Cypress C67x00 register definitions
+ */
+
+/* Hardware Revision Register */
+#define HW_REV_REG		0xC004
+
+/* General USB registers */
+/* ===================== */
+
+/* USB Control Register */
+#define USB_CTL_REG(x)		((x) ? 0xC0AA : 0xC08A)
+
+#define LOW_SPEED_PORT(x)	((x) ? 0x0800 : 0x0400)
+#define HOST_MODE		0x0200
+#define PORT_RES_EN(x)		((x) ? 0x0100 : 0x0080)
+#define SOF_EOP_EN(x)		((x) ? 0x0002 : 0x0001)
+
+/* USB status register - Notice it has different content in hcd/udc mode */
+#define USB_STAT_REG(x)		((x) ? 0xC0B0 : 0xC090)
+
+#define EP0_IRQ_FLG		0x0001
+#define EP1_IRQ_FLG		0x0002
+#define EP2_IRQ_FLG		0x0004
+#define EP3_IRQ_FLG		0x0008
+#define EP4_IRQ_FLG		0x0010
+#define EP5_IRQ_FLG		0x0020
+#define EP6_IRQ_FLG		0x0040
+#define EP7_IRQ_FLG		0x0080
+#define RESET_IRQ_FLG		0x0100
+#define SOF_EOP_IRQ_FLG		0x0200
+#define ID_IRQ_FLG		0x4000
+#define VBUS_IRQ_FLG		0x8000
+
+/* USB Host only registers */
+/* ======================= */
+
+/* Host n Control Register */
+#define HOST_CTL_REG(x)		((x) ? 0xC0A0 : 0xC080)
+
+#define PREAMBLE_EN		0x0080	/* Preamble enable */
+#define SEQ_SEL			0x0040	/* Data Toggle Sequence Bit Select */
+#define ISO_EN			0x0010	/* Isochronous enable  */
+#define ARM_EN			0x0001	/* Arm operation */
+
+/* Host n Interrupt Enable Register */
+#define HOST_IRQ_EN_REG(x)	((x) ? 0xC0AC : 0xC08C)
+
+#define SOF_EOP_IRQ_EN		0x0200	/* SOF/EOP Interrupt Enable  */
+#define SOF_EOP_TMOUT_IRQ_EN	0x0800	/* SOF/EOP Timeout Interrupt Enable  */
+#define ID_IRQ_EN		0x4000	/* ID interrupt enable */
+#define VBUS_IRQ_EN		0x8000	/* VBUS interrupt enable */
+#define DONE_IRQ_EN		0x0001	/* Done Interrupt Enable  */
+
+/* USB status register */
+#define HOST_STAT_MASK		0x02FD
+#define PORT_CONNECT_CHANGE(x)	((x) ? 0x0020 : 0x0010)
+#define PORT_SE0_STATUS(x)	((x) ? 0x0008 : 0x0004)
+
+/* Host Frame Register */
+#define HOST_FRAME_REG(x)	((x) ? 0xC0B6 : 0xC096)
+
+#define HOST_FRAME_MASK		0x07FF
+
+/* USB Peripheral only registers */
+/* ============================= */
+
+/* Device n Port Sel reg */
+#define DEVICE_N_PORT_SEL(x)	((x) ? 0xC0A4 : 0xC084)
+
+/* Device n Interrupt Enable Register */
+#define DEVICE_N_IRQ_EN_REG(x)	((x) ? 0xC0AC : 0xC08C)
+
+#define DEVICE_N_ENDPOINT_N_CTL_REG(dev, ep)	((dev)  		\
+						 ? (0x0280 + (ep << 4)) \
+						 : (0x0200 + (ep << 4)))
+#define DEVICE_N_ENDPOINT_N_STAT_REG(dev, ep)	((dev)			\
+						 ? (0x0286 + (ep << 4)) \
+						 : (0x0206 + (ep << 4)))
+
+#define DEVICE_N_ADDRESS(dev)	((dev) ? (0xC0AE) : (0xC08E))
+
+/* HPI registers */
+/* ============= */
+
+/* HPI Status register */
+#define SOFEOP_FLG(x)		(1 << ((x) ? 12 : 10))
+#define SIEMSG_FLG(x)		(1 << (4 + (x)))
+#define RESET_FLG(x)		((x) ? 0x0200 : 0x0002)
+#define DONE_FLG(x)		(1 << (2 + (x)))
+#define RESUME_FLG(x)		(1 << (6 + (x)))
+#define MBX_OUT_FLG		0x0001	/* Message out available */
+#define MBX_IN_FLG		0x0100
+#define ID_FLG			0x4000
+#define VBUS_FLG		0x8000
+
+/* Interrupt routing register */
+#define HPI_IRQ_ROUTING_REG	0x0142
+
+#define HPI_SWAP_ENABLE(x)	((x) ? 0x0100 : 0x0001)
+#define RESET_TO_HPI_ENABLE(x)	((x) ? 0x0200 : 0x0002)
+#define DONE_TO_HPI_ENABLE(x)	((x) ? 0x0008 : 0x0004)
+#define RESUME_TO_HPI_ENABLE(x)	((x) ? 0x0080 : 0x0040)
+#define SOFEOP_TO_HPI_EN(x)	((x) ? 0x2000 : 0x0800)
+#define SOFEOP_TO_CPU_EN(x)	((x) ? 0x1000 : 0x0400)
+#define ID_TO_HPI_ENABLE	0x4000
+#define VBUS_TO_HPI_ENABLE	0x8000
+
+/* SIE msg registers */
+#define SIEMSG_REG(x)		((x) ? 0x0148 : 0x0144)
+
+#define HUSB_TDListDone		0x1000
+
+#define SUSB_EP0_MSG		0x0001
+#define SUSB_EP1_MSG		0x0002
+#define SUSB_EP2_MSG		0x0004
+#define SUSB_EP3_MSG		0x0008
+#define SUSB_EP4_MSG		0x0010
+#define SUSB_EP5_MSG		0x0020
+#define SUSB_EP6_MSG		0x0040
+#define SUSB_EP7_MSG		0x0080
+#define SUSB_RST_MSG		0x0100
+#define SUSB_SOF_MSG		0x0200
+#define SUSB_CFG_MSG		0x0400
+#define SUSB_SUS_MSG		0x0800
+#define SUSB_ID_MSG	       	0x4000
+#define SUSB_VBUS_MSG		0x8000
+
+/* BIOS interrupt routines */
+
+#define SUSBx_RECEIVE_INT(x)	((x) ? 97 : 81)
+#define SUSBx_SEND_INT(x)	((x) ? 96 : 80)
+
+#define SUSBx_DEV_DESC_VEC(x)	((x) ? 0x00D4 : 0x00B4)
+#define SUSBx_CONF_DESC_VEC(x)	((x) ? 0x00D6 : 0x00B6)
+#define SUSBx_STRING_DESC_VEC(x) ((x) ? 0x00D8 : 0x00B8)
+
+#define CY_HCD_BUF_ADDR		0x500	/* Base address for host */
+#define SIE_TD_SIZE		0x200	/* size of the td list */
+#define SIE_TD_BUF_SIZE		0x400	/* size of the data buffer */
+
+#define SIE_TD_OFFSET(host)	((host) ? (SIE_TD_SIZE+SIE_TD_BUF_SIZE) : 0)
+#define SIE_BUF_OFFSET(host)	(SIE_TD_OFFSET(host) + SIE_TD_SIZE)
+
+/* Base address of HCD + 2 x TD_SIZE + 2 x TD_BUF_SIZE */
+#define CY_UDC_REQ_HEADER_BASE	0x1100
+/* 8- byte request headers for IN/OUT transfers */
+#define CY_UDC_REQ_HEADER_SIZE	8
+
+#define CY_UDC_REQ_HEADER_ADDR(ep_num)	(CY_UDC_REQ_HEADER_BASE + \
+					 ((ep_num) * CY_UDC_REQ_HEADER_SIZE))
+#define CY_UDC_DESC_BASE_ADDRESS	(CY_UDC_REQ_HEADER_ADDR(8))
+
+#define CY_UDC_BIOS_REPLACE_BASE	0x1800
+#define CY_UDC_REQ_BUFFER_BASE		0x2000
+#define CY_UDC_REQ_BUFFER_SIZE		0x0400
+#define CY_UDC_REQ_BUFFER_ADDR(ep_num)	(CY_UDC_REQ_BUFFER_BASE + \
+					 ((ep_num) * CY_UDC_REQ_BUFFER_SIZE))
+
+/* ---------------------------------------------------------------------
+ * Driver data structures
+ */
+
+struct c67x00_device;
+
+/**
+ * struct c67x00_sie - Common data associated with a SIE
+ * @lock: lock to protect this struct and the associated chip registers
+ * @private_data: subdriver dependent data
+ * @irq: subdriver dependent irq handler, set NULL when not used
+ * @dev: link to common driver structure
+ * @sie_num: SIE number on chip, starting from 0
+ * @mode: SIE mode (host/peripheral/otg/not used)
+ */
+struct c67x00_sie {
+	/* Entries to be used by the subdrivers */
+	spinlock_t lock;	/* protect this structure */
+	void *private_data;
+	void (*irq) (struct c67x00_sie *sie, u16 int_status, u16 msg);
+
+	/* Read only: */
+	struct c67x00_device *dev;
+	int sie_num;
+	int mode;
+};
+
+#define sie_dev(s)	(&(s)->dev->pdev->dev)
+
+/**
+ * struct c67x00_lcp
+ */
+struct c67x00_lcp {
+	/* Internal use only */
+	struct mutex mutex;
+	struct completion msg_received;
+	u16 last_msg;
+};
+
+/*
+ * struct c67x00_hpi
+ */
+struct c67x00_hpi {
+	void __iomem *base;
+	int regstep;
+	spinlock_t lock;
+	struct c67x00_lcp lcp;
+};
+
+#define C67X00_SIES	2
+#define C67X00_PORTS	2
+
+/**
+ * struct c67x00_device - Common data associated with a c67x00 instance
+ * @hpi: hpi addresses
+ * @sie: array of sie's on this chip
+ * @pdev: platform device of instance
+ * @pdata: configuration provided by the platform
+ */
+struct c67x00_device {
+	struct c67x00_hpi hpi;
+	struct c67x00_sie sie[C67X00_SIES];
+	struct platform_device *pdev;
+	struct c67x00_platform_data *pdata;
+};
+
+/* ---------------------------------------------------------------------
+ * Low level interface functions
+ */
+
+/* Host Port Interface (HPI) functions */
+u16 c67x00_ll_hpi_status(struct c67x00_device *dev);
+void c67x00_ll_hpi_reg_init(struct c67x00_device *dev);
+void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie);
+void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie);
+
+/* General functions */
+u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num);
+u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie);
+void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits);
+u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie);
+void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
+			      void *data, int len);
+void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
+			     void *data, int len);
+
+/* Host specific functions */
+void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value);
+void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port);
+void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr);
+u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie);
+u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie);
+void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie);
+void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port);
+
+/* Called by c67x00_irq to handle lcp interrupts */
+void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status);
+
+/* Setup and teardown */
+void c67x00_ll_init(struct c67x00_device *dev);
+void c67x00_ll_release(struct c67x00_device *dev);
+int c67x00_ll_reset(struct c67x00_device *dev);
+
+#endif				/* _USB_C67X00_H */
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e819e53..3e69266 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -394,7 +394,9 @@
 	if (!io->urbs)
 		goto nomem;
 
-	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
+	urb_flags = URB_NO_INTERRUPT;
+	if (dma)
+		urb_flags |= URB_NO_TRANSFER_DMA_MAP;
 	if (usb_pipein(pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index f7b5465..6e784d2 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -231,6 +231,26 @@
 	   However, this problem is improved if change a value of
 	   NET_IP_ALIGN to 4.
 
+config USB_GADGET_PXA27X
+	boolean "PXA 27x"
+	depends on ARCH_PXA && PXA27x
+	help
+	   Intel's PXA 27x series XScale ARM v5TE processors include
+	   an integrated full speed USB 1.1 device controller.
+
+	   It has up to 23 endpoints, as well as endpoint zero (for
+	   control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "pxa27x_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_PXA27X
+	tristate
+	depends on USB_GADGET_PXA27X
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
 config USB_GADGET_GOKU
 	boolean "Toshiba TC86C001 'Goku-S'"
 	depends on PCI
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index c3aab80..1235725 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
 obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
+obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
 obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index bb93bdd..8d61ea6 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -235,10 +235,6 @@
 #define	DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA27X
-#define DEV_CONFIG_CDC
-#endif
-
 #ifdef CONFIG_USB_GADGET_S3C2410
 #define DEV_CONFIG_CDC
 #endif
@@ -270,6 +266,10 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
+#ifdef CONFIG_USB_GADGET_PXA27X
+#define	DEV_CONFIG_SUBSET
+#endif
+
 #ifdef CONFIG_USB_GADGET_SUPERH
 #define	DEV_CONFIG_SUBSET
 #endif
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index bf3f946..47bb9f0 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -2307,6 +2307,29 @@
 	return rc;
 }
 
+static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
+{
+	int	rc;
+
+	DBG(fsg, "bulk-in set wedge\n");
+	rc = usb_ep_set_wedge(fsg->bulk_in);
+	if (rc == -EAGAIN)
+		VDBG(fsg, "delayed bulk-in endpoint wedge\n");
+	while (rc != 0) {
+		if (rc != -EAGAIN) {
+			WARN(fsg, "usb_ep_set_wedge -> %d\n", rc);
+			rc = 0;
+			break;
+		}
+
+		/* Wait for a short time and then try again */
+		if (msleep_interruptible(100) != 0)
+			return -EINTR;
+		rc = usb_ep_set_wedge(fsg->bulk_in);
+	}
+	return rc;
+}
+
 static int pad_with_zeros(struct fsg_dev *fsg)
 {
 	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
@@ -2957,7 +2980,7 @@
 		 * We aren't required to halt the OUT endpoint; instead
 		 * we can simply accept and discard any data received
 		 * until the next reset. */
-		halt_bulk_in_endpoint(fsg);
+		wedge_bulk_in_endpoint(fsg);
 		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 		return -EINVAL;
 	}
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
new file mode 100644
index 0000000..75eba20
--- /dev/null
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -0,0 +1,2404 @@
+/*
+ * Handles the Intel 27x USB Device Controller (UDC)
+ *
+ * Inspired by original driver by Frank Becker, David Brownell, and others.
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+
+#include <asm/byteorder.h>
+#include <asm/hardware.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include <asm/arch/udc.h>
+
+#include "pxa27x_udc.h"
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x
+ * series processors.
+ *
+ * Such controller drivers work with a gadget driver.  The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * 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. The
+ * biggest issues are:  that the endpoints have to be set up before the
+ * controller can be enabled (minor, and not uncommon); and each endpoint
+ * can only have one configuration, interface and alternative interface
+ * number (major, and very unusual). Once set up, these cannot be changed
+ * without a controller reset.
+ *
+ * The workaround is to setup all combinations necessary for the gadgets which
+ * will work with this driver. This is done in pxa_udc structure, statically.
+ * See pxa_udc, udc_usb_ep versus pxa_ep, and matching function find_pxa_ep.
+ * (You could modify this if needed.  Some drivers have a "fifo_mode" module
+ * parameter to facilitate such changes.)
+ *
+ * The combinations have been tested with these gadgets :
+ *  - zero gadget
+ *  - file storage gadget
+ *  - ether gadget
+ *
+ * The driver doesn't use DMA, only IO access and IRQ callbacks. No use is
+ * made of UDC's double buffering either. USB "On-The-Go" is not implemented.
+ *
+ * All the requests are handled the same way :
+ *  - the drivers tries to handle the request directly to the IO
+ *  - if the IO fifo is not big enough, the remaining is send/received in
+ *    interrupt handling.
+ */
+
+#define	DRIVER_VERSION	"2008-04-18"
+#define	DRIVER_DESC	"PXA 27x USB Device Controller driver"
+
+static const char driver_name[] = "pxa27x_udc";
+static struct pxa_udc *the_controller;
+
+static void handle_ep(struct pxa_ep *ep);
+
+/*
+ * Debug filesystem
+ */
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+
+static int state_dbg_show(struct seq_file *s, void *p)
+{
+	struct pxa_udc *udc = s->private;
+	int pos = 0, ret;
+	u32 tmp;
+
+	ret = -ENODEV;
+	if (!udc->driver)
+		goto out;
+
+	/* basic device status */
+	pos += seq_printf(s, DRIVER_DESC "\n"
+			 "%s version: %s\nGadget driver: %s\n",
+			 driver_name, DRIVER_VERSION,
+			 udc->driver ? udc->driver->driver.name : "(none)");
+
+	tmp = udc_readl(udc, UDCCR);
+	pos += seq_printf(s,
+			 "udccr=0x%0x(%s%s%s%s%s%s%s%s%s%s), "
+			 "con=%d,inter=%d,altinter=%d\n", tmp,
+			 (tmp & UDCCR_OEN) ? " oen":"",
+			 (tmp & UDCCR_AALTHNP) ? " aalthnp":"",
+			 (tmp & UDCCR_AHNP) ? " rem" : "",
+			 (tmp & UDCCR_BHNP) ? " rstir" : "",
+			 (tmp & UDCCR_DWRE) ? " dwre" : "",
+			 (tmp & UDCCR_SMAC) ? " smac" : "",
+			 (tmp & UDCCR_EMCE) ? " emce" : "",
+			 (tmp & UDCCR_UDR) ? " udr" : "",
+			 (tmp & UDCCR_UDA) ? " uda" : "",
+			 (tmp & UDCCR_UDE) ? " ude" : "",
+			 (tmp & UDCCR_ACN) >> UDCCR_ACN_S,
+			 (tmp & UDCCR_AIN) >> UDCCR_AIN_S,
+			 (tmp & UDCCR_AAISN) >> UDCCR_AAISN_S);
+	/* registers for device and ep0 */
+	pos += seq_printf(s, "udcicr0=0x%08x udcicr1=0x%08x\n",
+			udc_readl(udc, UDCICR0), udc_readl(udc, UDCICR1));
+	pos += seq_printf(s, "udcisr0=0x%08x udcisr1=0x%08x\n",
+			udc_readl(udc, UDCISR0), udc_readl(udc, UDCISR1));
+	pos += seq_printf(s, "udcfnr=%d\n", udc_readl(udc, UDCFNR));
+	pos += seq_printf(s, "irqs: reset=%lu, suspend=%lu, resume=%lu, "
+			"reconfig=%lu\n",
+			udc->stats.irqs_reset, udc->stats.irqs_suspend,
+			udc->stats.irqs_resume, udc->stats.irqs_reconfig);
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int queues_dbg_show(struct seq_file *s, void *p)
+{
+	struct pxa_udc *udc = s->private;
+	struct pxa_ep *ep;
+	struct pxa27x_request *req;
+	int pos = 0, i, maxpkt, ret;
+
+	ret = -ENODEV;
+	if (!udc->driver)
+		goto out;
+
+	/* dump endpoint queues */
+	for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+		ep = &udc->pxa_ep[i];
+		maxpkt = ep->fifo_size;
+		pos += seq_printf(s,  "%-12s max_pkt=%d %s\n",
+				EPNAME(ep), maxpkt, "pio");
+
+		if (list_empty(&ep->queue)) {
+			pos += seq_printf(s, "\t(nothing queued)\n");
+			continue;
+		}
+
+		list_for_each_entry(req, &ep->queue, queue) {
+			pos += seq_printf(s,  "\treq %p len %d/%d buf %p\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf);
+		}
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int eps_dbg_show(struct seq_file *s, void *p)
+{
+	struct pxa_udc *udc = s->private;
+	struct pxa_ep *ep;
+	int pos = 0, i, ret;
+	u32 tmp;
+
+	ret = -ENODEV;
+	if (!udc->driver)
+		goto out;
+
+	ep = &udc->pxa_ep[0];
+	tmp = udc_ep_readl(ep, UDCCSR);
+	pos += seq_printf(s, "udccsr0=0x%03x(%s%s%s%s%s%s%s)\n", tmp,
+			 (tmp & UDCCSR0_SA) ? " sa" : "",
+			 (tmp & UDCCSR0_RNE) ? " rne" : "",
+			 (tmp & UDCCSR0_FST) ? " fst" : "",
+			 (tmp & UDCCSR0_SST) ? " sst" : "",
+			 (tmp & UDCCSR0_DME) ? " dme" : "",
+			 (tmp & UDCCSR0_IPR) ? " ipr" : "",
+			 (tmp & UDCCSR0_OPC) ? " opc" : "");
+	for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+		ep = &udc->pxa_ep[i];
+		tmp = i? udc_ep_readl(ep, UDCCR) : udc_readl(udc, UDCCR);
+		pos += seq_printf(s, "%-12s: "
+				"IN %lu(%lu reqs), OUT %lu(%lu reqs), "
+				"irqs=%lu, udccr=0x%08x, udccsr=0x%03x, "
+				"udcbcr=%d\n",
+				EPNAME(ep),
+				ep->stats.in_bytes, ep->stats.in_ops,
+				ep->stats.out_bytes, ep->stats.out_ops,
+				ep->stats.irqs,
+				tmp, udc_ep_readl(ep, UDCCSR),
+				udc_ep_readl(ep, UDCBCR));
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int eps_dbg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, eps_dbg_show, inode->i_private);
+}
+
+static int queues_dbg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, queues_dbg_show, inode->i_private);
+}
+
+static int state_dbg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, state_dbg_show, inode->i_private);
+}
+
+static const struct file_operations state_dbg_fops = {
+	.owner		= THIS_MODULE,
+	.open		= state_dbg_open,
+	.llseek		= seq_lseek,
+	.read		= seq_read,
+	.release	= single_release,
+};
+
+static const struct file_operations queues_dbg_fops = {
+	.owner		= THIS_MODULE,
+	.open		= queues_dbg_open,
+	.llseek		= seq_lseek,
+	.read		= seq_read,
+	.release	= single_release,
+};
+
+static const struct file_operations eps_dbg_fops = {
+	.owner		= THIS_MODULE,
+	.open		= eps_dbg_open,
+	.llseek		= seq_lseek,
+	.read		= seq_read,
+	.release	= single_release,
+};
+
+static void pxa_init_debugfs(struct pxa_udc *udc)
+{
+	struct dentry *root, *state, *queues, *eps;
+
+	root = debugfs_create_dir(udc->gadget.name, NULL);
+	if (IS_ERR(root) || !root)
+		goto err_root;
+
+	state = debugfs_create_file("udcstate", 0400, root, udc,
+			&state_dbg_fops);
+	if (!state)
+		goto err_state;
+	queues = debugfs_create_file("queues", 0400, root, udc,
+			&queues_dbg_fops);
+	if (!queues)
+		goto err_queues;
+	eps = debugfs_create_file("epstate", 0400, root, udc,
+			&eps_dbg_fops);
+	if (!queues)
+		goto err_eps;
+
+	udc->debugfs_root = root;
+	udc->debugfs_state = state;
+	udc->debugfs_queues = queues;
+	udc->debugfs_eps = eps;
+	return;
+err_eps:
+	debugfs_remove(eps);
+err_queues:
+	debugfs_remove(queues);
+err_state:
+	debugfs_remove(root);
+err_root:
+	dev_err(udc->dev, "debugfs is not available\n");
+}
+
+static void pxa_cleanup_debugfs(struct pxa_udc *udc)
+{
+	debugfs_remove(udc->debugfs_eps);
+	debugfs_remove(udc->debugfs_queues);
+	debugfs_remove(udc->debugfs_state);
+	debugfs_remove(udc->debugfs_root);
+	udc->debugfs_eps = NULL;
+	udc->debugfs_queues = NULL;
+	udc->debugfs_state = NULL;
+	udc->debugfs_root = NULL;
+}
+
+#else
+static inline void pxa_init_debugfs(struct pxa_udc *udc)
+{
+}
+
+static inline void pxa_cleanup_debugfs(struct pxa_udc *udc)
+{
+}
+#endif
+
+/**
+ * is_match_usb_pxa - check if usb_ep and pxa_ep match
+ * @udc_usb_ep: usb endpoint
+ * @ep: pxa endpoint
+ * @config: configuration required in pxa_ep
+ * @interface: interface required in pxa_ep
+ * @altsetting: altsetting required in pxa_ep
+ *
+ * Returns 1 if all criteria match between pxa and usb endpoint, 0 otherwise
+ */
+static int is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep,
+		int config, int interface, int altsetting)
+{
+	if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr)
+		return 0;
+	if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in)
+		return 0;
+	if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type)
+		return 0;
+	if ((ep->config != config) || (ep->interface != interface)
+			|| (ep->alternate != altsetting))
+		return 0;
+	return 1;
+}
+
+/**
+ * find_pxa_ep - find pxa_ep structure matching udc_usb_ep
+ * @udc: pxa udc
+ * @udc_usb_ep: udc_usb_ep structure
+ *
+ * Match udc_usb_ep and all pxa_ep available, to see if one matches.
+ * This is necessary because of the strong pxa hardware restriction requiring
+ * that once pxa endpoints are initialized, their configuration is freezed, and
+ * no change can be made to their address, direction, or in which configuration,
+ * interface or altsetting they are active ... which differs from more usual
+ * models which have endpoints be roughly just addressable fifos, and leave
+ * configuration events up to gadget drivers (like all control messages).
+ *
+ * Note that there is still a blurred point here :
+ *   - we rely on UDCCR register "active interface" and "active altsetting".
+ *     This is a nonsense in regard of USB spec, where multiple interfaces are
+ *     active at the same time.
+ *   - if we knew for sure that the pxa can handle multiple interface at the
+ *     same time, assuming Intel's Developer Guide is wrong, this function
+ *     should be reviewed, and a cache of couples (iface, altsetting) should
+ *     be kept in the pxa_udc structure. In this case this function would match
+ *     against the cache of couples instead of the "last altsetting" set up.
+ *
+ * Returns the matched pxa_ep structure or NULL if none found
+ */
+static struct pxa_ep *find_pxa_ep(struct pxa_udc *udc,
+		struct udc_usb_ep *udc_usb_ep)
+{
+	int i;
+	struct pxa_ep *ep;
+	int cfg = udc->config;
+	int iface = udc->last_interface;
+	int alt = udc->last_alternate;
+
+	if (udc_usb_ep == &udc->udc_usb_ep[0])
+		return &udc->pxa_ep[0];
+
+	for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+		ep = &udc->pxa_ep[i];
+		if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt))
+			return ep;
+	}
+	return NULL;
+}
+
+/**
+ * update_pxa_ep_matches - update pxa_ep cached values in all udc_usb_ep
+ * @udc: pxa udc
+ *
+ * Context: in_interrupt()
+ *
+ * Updates all pxa_ep fields in udc_usb_ep structures, if this field was
+ * previously set up (and is not NULL). The update is necessary is a
+ * configuration change or altsetting change was issued by the USB host.
+ */
+static void update_pxa_ep_matches(struct pxa_udc *udc)
+{
+	int i;
+	struct udc_usb_ep *udc_usb_ep;
+
+	for (i = 1; i < NR_USB_ENDPOINTS; i++) {
+		udc_usb_ep = &udc->udc_usb_ep[i];
+		if (udc_usb_ep->pxa_ep)
+			udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep);
+	}
+}
+
+/**
+ * pio_irq_enable - Enables irq generation for one endpoint
+ * @ep: udc endpoint
+ */
+static void pio_irq_enable(struct pxa_ep *ep)
+{
+	struct pxa_udc *udc = ep->dev;
+	int index = EPIDX(ep);
+	u32 udcicr0 = udc_readl(udc, UDCICR0);
+	u32 udcicr1 = udc_readl(udc, UDCICR1);
+
+	if (index < 16)
+		udc_writel(udc, UDCICR0, udcicr0 | (3 << (index * 2)));
+	else
+		udc_writel(udc, UDCICR1, udcicr1 | (3 << ((index - 16) * 2)));
+}
+
+/**
+ * pio_irq_disable - Disables irq generation for one endpoint
+ * @ep: udc endpoint
+ * @index: endpoint number
+ */
+static void pio_irq_disable(struct pxa_ep *ep)
+{
+	struct pxa_udc *udc = ep->dev;
+	int index = EPIDX(ep);
+	u32 udcicr0 = udc_readl(udc, UDCICR0);
+	u32 udcicr1 = udc_readl(udc, UDCICR1);
+
+	if (index < 16)
+		udc_writel(udc, UDCICR0, udcicr0 & ~(3 << (index * 2)));
+	else
+		udc_writel(udc, UDCICR1, udcicr1 & ~(3 << ((index - 16) * 2)));
+}
+
+/**
+ * udc_set_mask_UDCCR - set bits in UDCCR
+ * @udc: udc device
+ * @mask: bits to set in UDCCR
+ *
+ * Sets bits in UDCCR, leaving DME and FST bits as they were.
+ */
+static inline void udc_set_mask_UDCCR(struct pxa_udc *udc, int mask)
+{
+	u32 udccr = udc_readl(udc, UDCCR);
+	udc_writel(udc, UDCCR,
+			(udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS));
+}
+
+/**
+ * udc_clear_mask_UDCCR - clears bits in UDCCR
+ * @udc: udc device
+ * @mask: bit to clear in UDCCR
+ *
+ * Clears bits in UDCCR, leaving DME and FST bits as they were.
+ */
+static inline void udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask)
+{
+	u32 udccr = udc_readl(udc, UDCCR);
+	udc_writel(udc, UDCCR,
+			(udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS));
+}
+
+/**
+ * ep_count_bytes_remain - get how many bytes in udc endpoint
+ * @ep: udc endpoint
+ *
+ * Returns number of bytes in OUT fifos. Broken for IN fifos (-EOPNOTSUPP)
+ */
+static int ep_count_bytes_remain(struct pxa_ep *ep)
+{
+	if (ep->dir_in)
+		return -EOPNOTSUPP;
+	return udc_ep_readl(ep, UDCBCR) & 0x3ff;
+}
+
+/**
+ * ep_is_empty - checks if ep has byte ready for reading
+ * @ep: udc endpoint
+ *
+ * If endpoint is the control endpoint, checks if there are bytes in the
+ * control endpoint fifo. If endpoint is a data endpoint, checks if bytes
+ * are ready for reading on OUT endpoint.
+ *
+ * Returns 0 if ep not empty, 1 if ep empty, -EOPNOTSUPP if IN endpoint
+ */
+static int ep_is_empty(struct pxa_ep *ep)
+{
+	int ret;
+
+	if (!is_ep0(ep) && ep->dir_in)
+		return -EOPNOTSUPP;
+	if (is_ep0(ep))
+		ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE);
+	else
+		ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE);
+	return ret;
+}
+
+/**
+ * ep_is_full - checks if ep has place to write bytes
+ * @ep: udc endpoint
+ *
+ * If endpoint is not the control endpoint and is an IN endpoint, checks if
+ * there is place to write bytes into the endpoint.
+ *
+ * Returns 0 if ep not full, 1 if ep full, -EOPNOTSUPP if OUT endpoint
+ */
+static int ep_is_full(struct pxa_ep *ep)
+{
+	if (is_ep0(ep))
+		return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR);
+	if (!ep->dir_in)
+		return -EOPNOTSUPP;
+	return (!(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF));
+}
+
+/**
+ * epout_has_pkt - checks if OUT endpoint fifo has a packet available
+ * @ep: pxa endpoint
+ *
+ * Returns 1 if a complete packet is available, 0 if not, -EOPNOTSUPP for IN ep.
+ */
+static int epout_has_pkt(struct pxa_ep *ep)
+{
+	if (!is_ep0(ep) && ep->dir_in)
+		return -EOPNOTSUPP;
+	if (is_ep0(ep))
+		return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC);
+	return (udc_ep_readl(ep, UDCCSR) & UDCCSR_PC);
+}
+
+/**
+ * set_ep0state - Set ep0 automata state
+ * @dev: udc device
+ * @state: state
+ */
+static void set_ep0state(struct pxa_udc *udc, int state)
+{
+	struct pxa_ep *ep = &udc->pxa_ep[0];
+	char *old_stname = EP0_STNAME(udc);
+
+	udc->ep0state = state;
+	ep_dbg(ep, "state=%s->%s, udccsr0=0x%03x, udcbcr=%d\n", old_stname,
+		EP0_STNAME(udc), udc_ep_readl(ep, UDCCSR),
+		udc_ep_readl(ep, UDCBCR));
+}
+
+/**
+ * ep0_idle - Put control endpoint into idle state
+ * @dev: udc device
+ */
+static void ep0_idle(struct pxa_udc *dev)
+{
+	set_ep0state(dev, WAIT_FOR_SETUP);
+}
+
+/**
+ * inc_ep_stats_reqs - Update ep stats counts
+ * @ep: physical endpoint
+ * @req: usb request
+ * @is_in: ep direction (USB_DIR_IN or 0)
+ *
+ */
+static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in)
+{
+	if (is_in)
+		ep->stats.in_ops++;
+	else
+		ep->stats.out_ops++;
+}
+
+/**
+ * inc_ep_stats_bytes - Update ep stats counts
+ * @ep: physical endpoint
+ * @count: bytes transfered on endpoint
+ * @req: usb request
+ * @is_in: ep direction (USB_DIR_IN or 0)
+ */
+static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
+{
+	if (is_in)
+		ep->stats.in_bytes += count;
+	else
+		ep->stats.out_bytes += count;
+}
+
+/**
+ * pxa_ep_setup - Sets up an usb physical endpoint
+ * @ep: pxa27x physical endpoint
+ *
+ * Find the physical pxa27x ep, and setup its UDCCR
+ */
+static __init void pxa_ep_setup(struct pxa_ep *ep)
+{
+	u32 new_udccr;
+
+	new_udccr = ((ep->config << UDCCONR_CN_S) & UDCCONR_CN)
+		| ((ep->interface << UDCCONR_IN_S) & UDCCONR_IN)
+		| ((ep->alternate << UDCCONR_AISN_S) & UDCCONR_AISN)
+		| ((EPADDR(ep) << UDCCONR_EN_S) & UDCCONR_EN)
+		| ((EPXFERTYPE(ep) << UDCCONR_ET_S) & UDCCONR_ET)
+		| ((ep->dir_in) ? UDCCONR_ED : 0)
+		| ((ep->fifo_size << UDCCONR_MPS_S) & UDCCONR_MPS)
+		| UDCCONR_EE;
+
+	udc_ep_writel(ep, UDCCR, new_udccr);
+}
+
+/**
+ * pxa_eps_setup - Sets up all usb physical endpoints
+ * @dev: udc device
+ *
+ * Setup all pxa physical endpoints, except ep0
+ */
+static __init void pxa_eps_setup(struct pxa_udc *dev)
+{
+	unsigned int i;
+
+	dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev);
+
+	for (i = 1; i < NR_PXA_ENDPOINTS; i++)
+		pxa_ep_setup(&dev->pxa_ep[i]);
+}
+
+/**
+ * pxa_ep_alloc_request - Allocate usb request
+ * @_ep: usb endpoint
+ * @gfp_flags:
+ *
+ * For the pxa27x, these can just wrap kmalloc/kfree.  gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+  */
+static struct usb_request *
+pxa_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct pxa27x_request *req;
+
+	req = kzalloc(sizeof *req, gfp_flags);
+	if (!req || !_ep)
+		return NULL;
+
+	INIT_LIST_HEAD(&req->queue);
+	req->in_use = 0;
+	req->udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+
+	return &req->req;
+}
+
+/**
+ * pxa_ep_free_request - Free usb request
+ * @_ep: usb endpoint
+ * @_req: usb request
+ *
+ * Wrapper around kfree to free _req
+ */
+static void pxa_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct pxa27x_request *req;
+
+	req = container_of(_req, struct pxa27x_request, req);
+	WARN_ON(!list_empty(&req->queue));
+	kfree(req);
+}
+
+/**
+ * ep_add_request - add a request to the endpoint's queue
+ * @ep: usb endpoint
+ * @req: usb request
+ *
+ * Context: ep->lock held
+ *
+ * Queues the request in the endpoint's queue, and enables the interrupts
+ * on the endpoint.
+ */
+static void ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	if (unlikely(!req))
+		return;
+	ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
+		req->req.length, udc_ep_readl(ep, UDCCSR));
+
+	req->in_use = 1;
+	list_add_tail(&req->queue, &ep->queue);
+	pio_irq_enable(ep);
+}
+
+/**
+ * ep_del_request - removes a request from the endpoint's queue
+ * @ep: usb endpoint
+ * @req: usb request
+ *
+ * Context: ep->lock held
+ *
+ * Unqueue the request from the endpoint's queue. If there are no more requests
+ * on the endpoint, and if it's not the control endpoint, interrupts are
+ * disabled on the endpoint.
+ */
+static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	if (unlikely(!req))
+		return;
+	ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
+		req->req.length, udc_ep_readl(ep, UDCCSR));
+
+	list_del_init(&req->queue);
+	req->in_use = 0;
+	if (!is_ep0(ep) && list_empty(&ep->queue))
+		pio_irq_disable(ep);
+}
+
+/**
+ * req_done - Complete an usb request
+ * @ep: pxa physical endpoint
+ * @req: pxa request
+ * @status: usb request status sent to gadget API
+ *
+ * Context: ep->lock held
+ *
+ * Retire a pxa27x usb request. Endpoint must be locked.
+ */
+static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status)
+{
+	ep_del_request(ep, req);
+	if (likely(req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (status && status != -ESHUTDOWN)
+		ep_dbg(ep, "complete req %p stat %d len %u/%u\n",
+			&req->req, status,
+			req->req.actual, req->req.length);
+
+	req->req.complete(&req->udc_usb_ep->usb_ep, &req->req);
+}
+
+/**
+ * ep_end_out_req - Ends control endpoint in request
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends endpoint in request (completes usb request).
+ */
+static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	inc_ep_stats_reqs(ep, !USB_DIR_IN);
+	req_done(ep, req, 0);
+}
+
+/**
+ * ep0_end_out_req - Ends control endpoint in request (ends data stage)
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends control endpoint in request (completes usb request), and puts
+ * control endpoint into idle state
+ */
+static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	set_ep0state(ep->dev, OUT_STATUS_STAGE);
+	ep_end_out_req(ep, req);
+	ep0_idle(ep->dev);
+}
+
+/**
+ * ep_end_in_req - Ends endpoint out request
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends endpoint out request (completes usb request).
+ */
+static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	inc_ep_stats_reqs(ep, USB_DIR_IN);
+	req_done(ep, req, 0);
+}
+
+/**
+ * ep0_end_in_req - Ends control endpoint out request (ends data stage)
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends control endpoint out request (completes usb request), and puts
+ * control endpoint into status state
+ */
+static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	struct pxa_udc *udc = ep->dev;
+
+	set_ep0state(udc, IN_STATUS_STAGE);
+	ep_end_in_req(ep, req);
+}
+
+/**
+ * nuke - Dequeue all requests
+ * @ep: pxa endpoint
+ * @status: usb request status
+ *
+ * Context: ep->lock held
+ *
+ * Dequeues all requests on an endpoint. As a side effect, interrupts will be
+ * disabled on that endpoint (because no more requests).
+ */
+static void nuke(struct pxa_ep *ep, int status)
+{
+	struct pxa27x_request *req;
+
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+		req_done(ep, req, status);
+	}
+}
+
+/**
+ * read_packet - transfer 1 packet from an OUT endpoint into request
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ *
+ * Takes bytes from OUT endpoint and transfers them info the usb request.
+ * If there is less space in request than bytes received in OUT endpoint,
+ * bytes are left in the OUT endpoint.
+ *
+ * Returns how many bytes were actually transfered
+ */
+static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	u32 *buf;
+	int bytes_ep, bufferspace, count, i;
+
+	bytes_ep = ep_count_bytes_remain(ep);
+	bufferspace = req->req.length - req->req.actual;
+
+	buf = (u32 *)(req->req.buf + req->req.actual);
+	prefetchw(buf);
+
+	if (likely(!ep_is_empty(ep)))
+		count = min(bytes_ep, bufferspace);
+	else /* zlp */
+		count = 0;
+
+	for (i = count; i > 0; i -= 4)
+		*buf++ = udc_ep_readl(ep, UDCDR);
+	req->req.actual += count;
+
+	udc_ep_writel(ep, UDCCSR, UDCCSR_PC);
+
+	return count;
+}
+
+/**
+ * write_packet - transfer 1 packet from request into an IN endpoint
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ * @max: max bytes that fit into endpoint
+ *
+ * Takes bytes from usb request, and transfers them into the physical
+ * endpoint. If there are no bytes to transfer, doesn't write anything
+ * to physical endpoint.
+ *
+ * Returns how many bytes were actually transfered.
+ */
+static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req,
+			unsigned int max)
+{
+	int length, count, remain, i;
+	u32 *buf;
+	u8 *buf_8;
+
+	buf = (u32 *)(req->req.buf + req->req.actual);
+	prefetch(buf);
+
+	length = min(req->req.length - req->req.actual, max);
+	req->req.actual += length;
+
+	remain = length & 0x3;
+	count = length & ~(0x3);
+	for (i = count; i > 0 ; i -= 4)
+		udc_ep_writel(ep, UDCDR, *buf++);
+
+	buf_8 = (u8 *)buf;
+	for (i = remain; i > 0; i--)
+		udc_ep_writeb(ep, UDCDR, *buf_8++);
+
+	ep_vdbg(ep, "length=%d+%d, udccsr=0x%03x\n", count, remain,
+		udc_ep_readl(ep, UDCCSR));
+
+	return length;
+}
+
+/**
+ * read_fifo - Transfer packets from OUT endpoint into usb request
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ *
+ * Context: callable when in_interrupt()
+ *
+ * Unload as many packets as possible from the fifo we use for usb OUT
+ * transfers and put them into the request. Caller should have made sure
+ * there's at least one packet ready.
+ * Doesn't complete the request, that's the caller's job
+ *
+ * Returns 1 if the request completed, 0 otherwise
+ */
+static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	int count, is_short, completed = 0;
+
+	while (epout_has_pkt(ep)) {
+		count = read_packet(ep, req);
+		inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
+
+		is_short = (count < ep->fifo_size);
+		ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
+			udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
+			&req->req, req->req.actual, req->req.length);
+
+		/* completion */
+		if (is_short || req->req.actual == req->req.length) {
+			completed = 1;
+			break;
+		}
+		/* finished that packet.  the next one may be waiting... */
+	}
+	return completed;
+}
+
+/**
+ * write_fifo - transfer packets from usb request into an IN endpoint
+ * @ep: pxa physical endpoint
+ * @req: pxa usb request
+ *
+ * Write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ * Doesn't complete the request, that's the caller's job
+ *
+ * Returns 1 if request fully transfered, 0 if partial transfer
+ */
+static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	unsigned max;
+	int count, is_short, is_last = 0, completed = 0, totcount = 0;
+	u32 udccsr;
+
+	max = ep->fifo_size;
+	do {
+		is_short = 0;
+
+		udccsr = udc_ep_readl(ep, UDCCSR);
+		if (udccsr & UDCCSR_PC) {
+			ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
+				udccsr);
+			udc_ep_writel(ep, UDCCSR, UDCCSR_PC);
+		}
+		if (udccsr & UDCCSR_TRN) {
+			ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n",
+				udccsr);
+			udc_ep_writel(ep, UDCCSR, UDCCSR_TRN);
+		}
+
+		count = write_packet(ep, req, max);
+		inc_ep_stats_bytes(ep, count, USB_DIR_IN);
+		totcount += count;
+
+		/* last packet is usually short (or a zlp) */
+		if (unlikely(count < max)) {
+			is_last = 1;
+			is_short = 1;
+		} else {
+			if (likely(req->req.length > req->req.actual)
+					|| req->req.zero)
+				is_last = 0;
+			else
+				is_last = 1;
+			/* interrupt/iso maxpacket may not fill the fifo */
+			is_short = unlikely(max < ep->fifo_size);
+		}
+
+		if (is_short)
+			udc_ep_writel(ep, UDCCSR, UDCCSR_SP);
+
+		/* requests complete when all IN data is in the FIFO */
+		if (is_last) {
+			completed = 1;
+			break;
+		}
+	} while (!ep_is_full(ep));
+
+	ep_dbg(ep, "wrote count:%d bytes%s%s, left:%d req=%p\n",
+			totcount, is_last ? "/L" : "", is_short ? "/S" : "",
+			req->req.length - req->req.actual, &req->req);
+
+	return completed;
+}
+
+/**
+ * read_ep0_fifo - Transfer packets from control endpoint into usb request
+ * @ep: control endpoint
+ * @req: pxa usb request
+ *
+ * Special ep0 version of the above read_fifo. Reads as many bytes from control
+ * endpoint as can be read, and stores them into usb request (limited by request
+ * maximum length).
+ *
+ * Returns 0 if usb request only partially filled, 1 if fully filled
+ */
+static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	int count, is_short, completed = 0;
+
+	while (epout_has_pkt(ep)) {
+		count = read_packet(ep, req);
+		udc_ep_writel(ep, UDCCSR, UDCCSR0_OPC);
+		inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
+
+		is_short = (count < ep->fifo_size);
+		ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
+			udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
+			&req->req, req->req.actual, req->req.length);
+
+		if (is_short || req->req.actual >= req->req.length) {
+			completed = 1;
+			break;
+		}
+	}
+
+	return completed;
+}
+
+/**
+ * write_ep0_fifo - Send a request to control endpoint (ep0 in)
+ * @ep: control endpoint
+ * @req: request
+ *
+ * Context: callable when in_interrupt()
+ *
+ * Sends a request (or a part of the request) to the control endpoint (ep0 in).
+ * If the request doesn't fit, the remaining part will be sent from irq.
+ * The request is considered fully written only if either :
+ *   - last write transfered all remaining bytes, but fifo was not fully filled
+ *   - last write was a 0 length write
+ *
+ * Returns 1 if request fully written, 0 if request only partially sent
+ */
+static int write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+	unsigned	count;
+	int		is_last, is_short;
+
+	count = write_packet(ep, req, EP0_FIFO_SIZE);
+	inc_ep_stats_bytes(ep, count, USB_DIR_IN);
+
+	is_short = (count < EP0_FIFO_SIZE);
+	is_last = ((count == 0) || (count < EP0_FIFO_SIZE));
+
+	/* Sends either a short packet or a 0 length packet */
+	if (unlikely(is_short))
+		udc_ep_writel(ep, UDCCSR, UDCCSR0_IPR);
+
+	ep_dbg(ep, "in %d bytes%s%s, %d left, req=%p, udccsr0=0x%03x\n",
+		count, is_short ? "/S" : "", is_last ? "/L" : "",
+		req->req.length - req->req.actual,
+		&req->req, udc_ep_readl(ep, UDCCSR));
+
+	return is_last;
+}
+
+/**
+ * pxa_ep_queue - Queue a request into an IN endpoint
+ * @_ep: usb endpoint
+ * @_req: usb request
+ * @gfp_flags: flags
+ *
+ * Context: normally called when !in_interrupt, but callable when in_interrupt()
+ * in the special case of ep0 setup :
+ *   (irq->handle_ep0_ctrl_req->gadget_setup->pxa_ep_queue)
+ *
+ * Returns 0 if succedeed, error otherwise
+ */
+static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+			gfp_t gfp_flags)
+{
+	struct udc_usb_ep	*udc_usb_ep;
+	struct pxa_ep		*ep;
+	struct pxa27x_request	*req;
+	struct pxa_udc		*dev;
+	unsigned long		flags;
+	int			rc = 0;
+	int			is_first_req;
+	unsigned		length;
+
+	req = container_of(_req, struct pxa27x_request, req);
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+
+	if (unlikely(!_req || !_req->complete || !_req->buf))
+		return -EINVAL;
+
+	if (unlikely(!_ep))
+		return -EINVAL;
+
+	dev = udc_usb_ep->dev;
+	ep = udc_usb_ep->pxa_ep;
+	if (unlikely(!ep))
+		return -EINVAL;
+
+	dev = ep->dev;
+	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		ep_dbg(ep, "bogus device state\n");
+		return -ESHUTDOWN;
+	}
+
+	/* iso is always one packet per request, that's the only way
+	 * we can report per-packet status.  that also helps with dma.
+	 */
+	if (unlikely(EPXFERTYPE_is_ISO(ep)
+			&& req->req.length > ep->fifo_size))
+		return -EMSGSIZE;
+
+	spin_lock_irqsave(&ep->lock, flags);
+
+	is_first_req = list_empty(&ep->queue);
+	ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
+			_req, is_first_req ? "yes" : "no",
+			_req->length, _req->buf);
+
+	if (!ep->enabled) {
+		_req->status = -ESHUTDOWN;
+		rc = -ESHUTDOWN;
+		goto out;
+	}
+
+	if (req->in_use) {
+		ep_err(ep, "refusing to queue req %p (already queued)\n", req);
+		goto out;
+	}
+
+	length = _req->length;
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	ep_add_request(ep, req);
+
+	if (is_ep0(ep)) {
+		switch (dev->ep0state) {
+		case WAIT_ACK_SET_CONF_INTERF:
+			if (length == 0) {
+				ep_end_in_req(ep, req);
+			} else {
+				ep_err(ep, "got a request of %d bytes while"
+					"in state WATI_ACK_SET_CONF_INTERF\n",
+					length);
+				ep_del_request(ep, req);
+				rc = -EL2HLT;
+			}
+			ep0_idle(ep->dev);
+			break;
+		case IN_DATA_STAGE:
+			if (!ep_is_full(ep))
+				if (write_ep0_fifo(ep, req))
+					ep0_end_in_req(ep, req);
+			break;
+		case OUT_DATA_STAGE:
+			if ((length == 0) || !epout_has_pkt(ep))
+				if (read_ep0_fifo(ep, req))
+					ep0_end_out_req(ep, req);
+			break;
+		default:
+			ep_err(ep, "odd state %s to send me a request\n",
+				EP0_STNAME(ep->dev));
+			ep_del_request(ep, req);
+			rc = -EL2HLT;
+			break;
+		}
+	} else {
+		handle_ep(ep);
+	}
+
+out:
+	spin_unlock_irqrestore(&ep->lock, flags);
+	return rc;
+}
+
+/**
+ * pxa_ep_dequeue - Dequeue one request
+ * @_ep: usb endpoint
+ * @_req: usb request
+ *
+ * Return 0 if no error, -EINVAL or -ECONNRESET otherwise
+ */
+static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct pxa_ep		*ep;
+	struct udc_usb_ep	*udc_usb_ep;
+	struct pxa27x_request	*req;
+	unsigned long		flags;
+	int			rc;
+
+	if (!_ep)
+		return -EINVAL;
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+	ep = udc_usb_ep->pxa_ep;
+	if (!ep || is_ep0(ep))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->lock, flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+
+	rc = -EINVAL;
+	if (&req->req != _req)
+		goto out;
+
+	rc = 0;
+	req_done(ep, req, -ECONNRESET);
+out:
+	spin_unlock_irqrestore(&ep->lock, flags);
+	return rc;
+}
+
+/**
+ * pxa_ep_set_halt - Halts operations on one endpoint
+ * @_ep: usb endpoint
+ * @value:
+ *
+ * Returns 0 if no error, -EINVAL, -EROFS, -EAGAIN otherwise
+ */
+static int pxa_ep_set_halt(struct usb_ep *_ep, int value)
+{
+	struct pxa_ep		*ep;
+	struct udc_usb_ep	*udc_usb_ep;
+	unsigned long flags;
+	int rc;
+
+
+	if (!_ep)
+		return -EINVAL;
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+	ep = udc_usb_ep->pxa_ep;
+	if (!ep || is_ep0(ep))
+		return -EINVAL;
+
+	if (value == 0) {
+		/*
+		 * This path (reset toggle+halt) is needed to implement
+		 * SET_INTERFACE on normal hardware.  but it can't be
+		 * done from software on the PXA UDC, and the hardware
+		 * forgets to do it as part of SET_INTERFACE automagic.
+		 */
+		ep_dbg(ep, "only host can clear halt\n");
+		return -EROFS;
+	}
+
+	spin_lock_irqsave(&ep->lock, flags);
+
+	rc = -EAGAIN;
+	if (ep->dir_in	&& (ep_is_full(ep) || !list_empty(&ep->queue)))
+		goto out;
+
+	/* FST, FEF bits are the same for control and non control endpoints */
+	rc = 0;
+	udc_ep_writel(ep, UDCCSR, UDCCSR_FST | UDCCSR_FEF);
+	if (is_ep0(ep))
+		set_ep0state(ep->dev, STALL);
+
+out:
+	spin_unlock_irqrestore(&ep->lock, flags);
+	return rc;
+}
+
+/**
+ * pxa_ep_fifo_status - Get how many bytes in physical endpoint
+ * @_ep: usb endpoint
+ *
+ * Returns number of bytes in OUT fifos. Broken for IN fifos.
+ */
+static int pxa_ep_fifo_status(struct usb_ep *_ep)
+{
+	struct pxa_ep		*ep;
+	struct udc_usb_ep	*udc_usb_ep;
+
+	if (!_ep)
+		return -ENODEV;
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+	ep = udc_usb_ep->pxa_ep;
+	if (!ep || is_ep0(ep))
+		return -ENODEV;
+
+	if (ep->dir_in)
+		return -EOPNOTSUPP;
+	if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep))
+		return 0;
+	else
+		return ep_count_bytes_remain(ep) + 1;
+}
+
+/**
+ * pxa_ep_fifo_flush - Flushes one endpoint
+ * @_ep: usb endpoint
+ *
+ * Discards all data in one endpoint(IN or OUT), except control endpoint.
+ */
+static void pxa_ep_fifo_flush(struct usb_ep *_ep)
+{
+	struct pxa_ep		*ep;
+	struct udc_usb_ep	*udc_usb_ep;
+	unsigned long		flags;
+
+	if (!_ep)
+		return;
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+	ep = udc_usb_ep->pxa_ep;
+	if (!ep || is_ep0(ep))
+		return;
+
+	spin_lock_irqsave(&ep->lock, flags);
+
+	if (unlikely(!list_empty(&ep->queue)))
+		ep_dbg(ep, "called while queue list not empty\n");
+	ep_dbg(ep, "called\n");
+
+	/* for OUT, just read and discard the FIFO contents. */
+	if (!ep->dir_in) {
+		while (!ep_is_empty(ep))
+			udc_ep_readl(ep, UDCDR);
+	} else {
+		/* most IN status is the same, but ISO can't stall */
+		udc_ep_writel(ep, UDCCSR,
+				UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN
+				| (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST));
+	}
+
+	spin_unlock_irqrestore(&ep->lock, flags);
+
+	return;
+}
+
+/**
+ * pxa_ep_enable - Enables usb endpoint
+ * @_ep: usb endpoint
+ * @desc: usb endpoint descriptor
+ *
+ * Nothing much to do here, as ep configuration is done once and for all
+ * before udc is enabled. After udc enable, no physical endpoint configuration
+ * can be changed.
+ * Function makes sanity checks and flushes the endpoint.
+ */
+static int pxa_ep_enable(struct usb_ep *_ep,
+	const struct usb_endpoint_descriptor *desc)
+{
+	struct pxa_ep		*ep;
+	struct udc_usb_ep	*udc_usb_ep;
+	struct pxa_udc		*udc;
+
+	if (!_ep || !desc)
+		return -EINVAL;
+
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+	if (udc_usb_ep->pxa_ep) {
+		ep = udc_usb_ep->pxa_ep;
+		ep_warn(ep, "usb_ep %s already enabled, doing nothing\n",
+			_ep->name);
+	} else {
+		ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep);
+	}
+
+	if (!ep || is_ep0(ep)) {
+		dev_err(udc_usb_ep->dev->dev,
+			"unable to match pxa_ep for ep %s\n",
+			_ep->name);
+		return -EINVAL;
+	}
+
+	if ((desc->bDescriptorType != USB_DT_ENDPOINT)
+			|| (ep->type != usb_endpoint_type(desc))) {
+		ep_err(ep, "type mismatch\n");
+		return -EINVAL;
+	}
+
+	if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) {
+		ep_err(ep, "bad maxpacket\n");
+		return -ERANGE;
+	}
+
+	udc_usb_ep->pxa_ep = ep;
+	udc = ep->dev;
+
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+		ep_err(ep, "bogus device state\n");
+		return -ESHUTDOWN;
+	}
+
+	ep->enabled = 1;
+
+	/* flush fifo (mostly for OUT buffers) */
+	pxa_ep_fifo_flush(_ep);
+
+	ep_dbg(ep, "enabled\n");
+	return 0;
+}
+
+/**
+ * pxa_ep_disable - Disable usb endpoint
+ * @_ep: usb endpoint
+ *
+ * Same as for pxa_ep_enable, no physical endpoint configuration can be
+ * changed.
+ * Function flushes the endpoint and related requests.
+ */
+static int pxa_ep_disable(struct usb_ep *_ep)
+{
+	struct pxa_ep		*ep;
+	struct udc_usb_ep	*udc_usb_ep;
+	unsigned long		flags;
+
+	if (!_ep)
+		return -EINVAL;
+
+	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+	ep = udc_usb_ep->pxa_ep;
+	if (!ep || is_ep0(ep) || !list_empty(&ep->queue))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	ep->enabled = 0;
+	nuke(ep, -ESHUTDOWN);
+	spin_unlock_irqrestore(&ep->lock, flags);
+
+	pxa_ep_fifo_flush(_ep);
+	udc_usb_ep->pxa_ep = NULL;
+
+	ep_dbg(ep, "disabled\n");
+	return 0;
+}
+
+static struct usb_ep_ops pxa_ep_ops = {
+	.enable		= pxa_ep_enable,
+	.disable	= pxa_ep_disable,
+
+	.alloc_request	= pxa_ep_alloc_request,
+	.free_request	= pxa_ep_free_request,
+
+	.queue		= pxa_ep_queue,
+	.dequeue	= pxa_ep_dequeue,
+
+	.set_halt	= pxa_ep_set_halt,
+	.fifo_status	= pxa_ep_fifo_status,
+	.fifo_flush	= pxa_ep_fifo_flush,
+};
+
+
+/**
+ * pxa_udc_get_frame - Returns usb frame number
+ * @_gadget: usb gadget
+ */
+static int pxa_udc_get_frame(struct usb_gadget *_gadget)
+{
+	struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+	return (udc_readl(udc, UDCFNR) & 0x7ff);
+}
+
+/**
+ * pxa_udc_wakeup - Force udc device out of suspend
+ * @_gadget: usb gadget
+ *
+ * Returns 0 if succesfull, error code otherwise
+ */
+static int pxa_udc_wakeup(struct usb_gadget *_gadget)
+{
+	struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+	/* host may not have enabled remote wakeup */
+	if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0)
+		return -EHOSTUNREACH;
+	udc_set_mask_UDCCR(udc, UDCCR_UDR);
+	return 0;
+}
+
+static const struct usb_gadget_ops pxa_udc_ops = {
+	.get_frame	= pxa_udc_get_frame,
+	.wakeup		= pxa_udc_wakeup,
+	/* current versions must always be self-powered */
+};
+
+/**
+ * udc_disable - disable udc device controller
+ * @udc: udc device
+ *
+ * Disables the udc device : disables clocks, udc interrupts, control endpoint
+ * interrupts.
+ */
+static void udc_disable(struct pxa_udc *udc)
+{
+	udc_writel(udc, UDCICR0, 0);
+	udc_writel(udc, UDCICR1, 0);
+
+	udc_clear_mask_UDCCR(udc, UDCCR_UDE);
+	clk_disable(udc->clk);
+
+	ep0_idle(udc);
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+/**
+ * udc_init_data - Initialize udc device data structures
+ * @dev: udc device
+ *
+ * Initializes gadget endpoint list, endpoints locks. No action is taken
+ * on the hardware.
+ */
+static __init void udc_init_data(struct pxa_udc *dev)
+{
+	int i;
+	struct pxa_ep *ep;
+
+	/* device/ep0 records init */
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+	dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+	ep0_idle(dev);
+	strcpy(dev->dev->bus_id, "");
+
+	/* PXA endpoints init */
+	for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+		ep = &dev->pxa_ep[i];
+
+		ep->enabled = is_ep0(ep);
+		INIT_LIST_HEAD(&ep->queue);
+		spin_lock_init(&ep->lock);
+	}
+
+	/* USB endpoints init */
+	for (i = 0; i < NR_USB_ENDPOINTS; i++)
+		if (i != 0)
+			list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
+					&dev->gadget.ep_list);
+}
+
+/**
+ * udc_enable - Enables the udc device
+ * @dev: udc device
+ *
+ * Enables the udc device : enables clocks, udc interrupts, control endpoint
+ * interrupts, sets usb as UDC client and setups endpoints.
+ */
+static void udc_enable(struct pxa_udc *udc)
+{
+	udc_writel(udc, UDCICR0, 0);
+	udc_writel(udc, UDCICR1, 0);
+	udc_writel(udc, UP2OCR, UP2OCR_HXOE);
+	udc_clear_mask_UDCCR(udc, UDCCR_UDE);
+
+	clk_enable(udc->clk);
+
+	ep0_idle(udc);
+	udc->gadget.speed = USB_SPEED_FULL;
+	memset(&udc->stats, 0, sizeof(udc->stats));
+
+	udc_set_mask_UDCCR(udc, UDCCR_UDE);
+	udelay(2);
+	if (udc_readl(udc, UDCCR) & UDCCR_EMCE)
+		dev_err(udc->dev, "Configuration errors, udc disabled\n");
+
+	/*
+	 * Caller must be able to sleep in order to cope with startup transients
+	 */
+	msleep(100);
+
+	/* enable suspend/resume and reset irqs */
+	udc_writel(udc, UDCICR1,
+			UDCICR1_IECC | UDCICR1_IERU
+			| UDCICR1_IESU | UDCICR1_IERS);
+
+	/* enable ep0 irqs */
+	pio_irq_enable(&udc->pxa_ep[0]);
+
+	dev_info(udc->dev, "UDC connecting\n");
+	if (udc->mach->udc_command)
+		udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
+/**
+ * usb_gadget_register_driver - Register gadget driver
+ * @driver: gadget driver
+ *
+ * When a driver is successfully registered, it will receive control requests
+ * including set_configuration(), which enables non-control requests.  Then
+ * usb traffic follows until a disconnect is reported.  Then a host may connect
+ * again, or the driver might get unbound.
+ *
+ * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct pxa_udc *udc = the_controller;
+	int retval;
+
+	if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind
+			|| !driver->disconnect || !driver->setup)
+		return -EINVAL;
+	if (!udc)
+		return -ENODEV;
+	if (udc->driver)
+		return -EBUSY;
+
+	/* first hook up the driver ... */
+	udc->driver = driver;
+	udc->gadget.dev.driver = &driver->driver;
+
+	retval = device_add(&udc->gadget.dev);
+	if (retval) {
+		dev_err(udc->dev, "device_add error %d\n", retval);
+		goto add_fail;
+	}
+	retval = driver->bind(&udc->gadget);
+	if (retval) {
+		dev_err(udc->dev, "bind to driver %s --> error %d\n",
+			driver->driver.name, retval);
+		goto bind_fail;
+	}
+	dev_dbg(udc->dev, "registered gadget driver '%s'\n",
+		driver->driver.name);
+
+	udc_enable(udc);
+	return 0;
+
+bind_fail:
+	device_del(&udc->gadget.dev);
+add_fail:
+	udc->driver = NULL;
+	udc->gadget.dev.driver = NULL;
+	return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+
+/**
+ * stop_activity - Stops udc endpoints
+ * @udc: udc device
+ * @driver: gadget driver
+ *
+ * Disables all udc endpoints (even control endpoint), report disconnect to
+ * the gadget user.
+ */
+static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
+{
+	int i;
+
+	/* don't disconnect drivers more than once */
+	if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+		driver = NULL;
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+
+	for (i = 0; i < NR_USB_ENDPOINTS; i++)
+		pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
+
+	if (driver)
+		driver->disconnect(&udc->gadget);
+}
+
+/**
+ * usb_gadget_unregister_driver - Unregister the gadget driver
+ * @driver: gadget driver
+ *
+ * Returns 0 if no error, -ENODEV, -EINVAL otherwise
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct pxa_udc *udc = the_controller;
+
+	if (!udc)
+		return -ENODEV;
+	if (!driver || driver != udc->driver || !driver->unbind)
+		return -EINVAL;
+
+	stop_activity(udc, driver);
+	udc_disable(udc);
+
+	driver->unbind(&udc->gadget);
+	udc->driver = NULL;
+
+	device_del(&udc->gadget.dev);
+
+	dev_info(udc->dev, "unregistered gadget driver '%s'\n",
+		 driver->driver.name);
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/**
+ * handle_ep0_ctrl_req - handle control endpoint control request
+ * @udc: udc device
+ * @req: control request
+ */
+static void handle_ep0_ctrl_req(struct pxa_udc *udc,
+				struct pxa27x_request *req)
+{
+	struct pxa_ep *ep = &udc->pxa_ep[0];
+	union {
+		struct usb_ctrlrequest	r;
+		u32			word[2];
+	} u;
+	int i;
+	int have_extrabytes = 0;
+
+	nuke(ep, -EPROTO);
+
+	/* read SETUP packet */
+	for (i = 0; i < 2; i++) {
+		if (unlikely(ep_is_empty(ep)))
+			goto stall;
+		u.word[i] = udc_ep_readl(ep, UDCDR);
+	}
+
+	have_extrabytes = !ep_is_empty(ep);
+	while (!ep_is_empty(ep)) {
+		i = udc_ep_readl(ep, UDCDR);
+		ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
+	}
+
+	le16_to_cpus(&u.r.wValue);
+	le16_to_cpus(&u.r.wIndex);
+	le16_to_cpus(&u.r.wLength);
+
+	ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+		u.r.bRequestType, u.r.bRequest,
+		u.r.wValue, u.r.wIndex, u.r.wLength);
+	if (unlikely(have_extrabytes))
+		goto stall;
+
+	if (u.r.bRequestType & USB_DIR_IN)
+		set_ep0state(udc, IN_DATA_STAGE);
+	else
+		set_ep0state(udc, OUT_DATA_STAGE);
+
+	/* Tell UDC to enter Data Stage */
+	udc_ep_writel(ep, UDCCSR, UDCCSR0_SA | UDCCSR0_OPC);
+
+	i = udc->driver->setup(&udc->gadget, &u.r);
+	if (i < 0)
+		goto stall;
+out:
+	return;
+stall:
+	ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n",
+		udc_ep_readl(ep, UDCCSR), i);
+	udc_ep_writel(ep, UDCCSR, UDCCSR0_FST | UDCCSR0_FTF);
+	set_ep0state(udc, STALL);
+	goto out;
+}
+
+/**
+ * handle_ep0 - Handle control endpoint data transfers
+ * @udc: udc device
+ * @fifo_irq: 1 if triggered by fifo service type irq
+ * @opc_irq: 1 if triggered by output packet complete type irq
+ *
+ * Context : when in_interrupt() or with ep->lock held
+ *
+ * Tries to transfer all pending request data into the endpoint and/or
+ * transfer all pending data in the endpoint into usb requests.
+ * Handles states of ep0 automata.
+ *
+ * PXA27x hardware handles several standard usb control requests without
+ * driver notification.  The requests fully handled by hardware are :
+ *  SET_ADDRESS, SET_FEATURE, CLEAR_FEATURE, GET_CONFIGURATION, GET_INTERFACE,
+ *  GET_STATUS
+ * The requests handled by hardware, but with irq notification are :
+ *  SYNCH_FRAME, SET_CONFIGURATION, SET_INTERFACE
+ * The remaining standard requests really handled by handle_ep0 are :
+ *  GET_DESCRIPTOR, SET_DESCRIPTOR, specific requests.
+ * Requests standardized outside of USB 2.0 chapter 9 are handled more
+ * uniformly, by gadget drivers.
+ *
+ * The control endpoint state machine is _not_ USB spec compliant, it's even
+ * hardly compliant with Intel PXA270 developers guide.
+ * The key points which inferred this state machine are :
+ *   - on every setup token, bit UDCCSR0_SA is raised and held until cleared by
+ *     software.
+ *   - on every OUT packet received, UDCCSR0_OPC is raised and held until
+ *     cleared by software.
+ *   - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it
+ *     before reading ep0.
+ *   - irq can be called on a "packet complete" event (opc_irq=1), while
+ *     UDCCSR0_OPC is not yet raised (delta can be as big as 100ms
+ *     from experimentation).
+ *   - as UDCCSR0_SA can be activated while in irq handling, and clearing
+ *     UDCCSR0_OPC would flush the setup data, we almost never clear UDCCSR0_OPC
+ *     => we never actually read the "status stage" packet of an IN data stage
+ *     => this is not documented in Intel documentation
+ *   - hardware as no idea of STATUS STAGE, it only handle SETUP STAGE and DATA
+ *     STAGE. The driver add STATUS STAGE to send last zero length packet in
+ *     OUT_STATUS_STAGE.
+ *   - special attention was needed for IN_STATUS_STAGE. If a packet complete
+ *     event is detected, we terminate the status stage without ackowledging the
+ *     packet (not to risk to loose a potential SETUP packet)
+ */
+static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
+{
+	u32			udccsr0;
+	struct pxa_ep		*ep = &udc->pxa_ep[0];
+	struct pxa27x_request	*req = NULL;
+	int			completed = 0;
+
+	udccsr0 = udc_ep_readl(ep, UDCCSR);
+	ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
+		EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
+		(fifo_irq << 1 | opc_irq));
+
+	if (!list_empty(&ep->queue))
+		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+
+	if (udccsr0 & UDCCSR0_SST) {
+		ep_dbg(ep, "clearing stall status\n");
+		nuke(ep, -EPIPE);
+		udc_ep_writel(ep, UDCCSR, UDCCSR0_SST);
+		ep0_idle(udc);
+	}
+
+	if (udccsr0 & UDCCSR0_SA) {
+		nuke(ep, 0);
+		set_ep0state(udc, SETUP_STAGE);
+	}
+
+	switch (udc->ep0state) {
+	case WAIT_FOR_SETUP:
+		/*
+		 * Hardware bug : beware, we cannot clear OPC, since we would
+		 * miss a potential OPC irq for a setup packet.
+		 * So, we only do ... nothing, and hope for a next irq with
+		 * UDCCSR0_SA set.
+		 */
+		break;
+	case SETUP_STAGE:
+		udccsr0 &= UDCCSR0_CTRL_REQ_MASK;
+		if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK))
+			handle_ep0_ctrl_req(udc, req);
+		break;
+	case IN_DATA_STAGE:			/* GET_DESCRIPTOR */
+		if (epout_has_pkt(ep))
+			udc_ep_writel(ep, UDCCSR, UDCCSR0_OPC);
+		if (req && !ep_is_full(ep))
+			completed = write_ep0_fifo(ep, req);
+		if (completed)
+			ep0_end_in_req(ep, req);
+		break;
+	case OUT_DATA_STAGE:			/* SET_DESCRIPTOR */
+		if (epout_has_pkt(ep) && req)
+			completed = read_ep0_fifo(ep, req);
+		if (completed)
+			ep0_end_out_req(ep, req);
+		break;
+	case STALL:
+		udc_ep_writel(ep, UDCCSR, UDCCSR0_FST);
+		break;
+	case IN_STATUS_STAGE:
+		/*
+		 * Hardware bug : beware, we cannot clear OPC, since we would
+		 * miss a potential PC irq for a setup packet.
+		 * So, we only put the ep0 into WAIT_FOR_SETUP state.
+		 */
+		if (opc_irq)
+			ep0_idle(udc);
+		break;
+	case OUT_STATUS_STAGE:
+	case WAIT_ACK_SET_CONF_INTERF:
+		ep_warn(ep, "should never get in %s state here!!!\n",
+				EP0_STNAME(ep->dev));
+		ep0_idle(udc);
+		break;
+	}
+}
+
+/**
+ * handle_ep - Handle endpoint data tranfers
+ * @ep: pxa physical endpoint
+ *
+ * Tries to transfer all pending request data into the endpoint and/or
+ * transfer all pending data in the endpoint into usb requests.
+ *
+ * Is always called when in_interrupt() or with ep->lock held.
+ */
+static void handle_ep(struct pxa_ep *ep)
+{
+	struct pxa27x_request	*req;
+	int completed;
+	u32 udccsr;
+	int is_in = ep->dir_in;
+	int loop = 0;
+
+	do {
+		completed = 0;
+		udccsr = udc_ep_readl(ep, UDCCSR);
+		if (likely(!list_empty(&ep->queue)))
+			req = list_entry(ep->queue.next,
+					struct pxa27x_request, queue);
+		else
+			req = NULL;
+
+		ep_dbg(ep, "req:%p, udccsr 0x%03x loop=%d\n",
+				req, udccsr, loop++);
+
+		if (unlikely(udccsr & (UDCCSR_SST | UDCCSR_TRN)))
+			udc_ep_writel(ep, UDCCSR,
+					udccsr & (UDCCSR_SST | UDCCSR_TRN));
+		if (!req)
+			break;
+
+		if (unlikely(is_in)) {
+			if (likely(!ep_is_full(ep)))
+				completed = write_fifo(ep, req);
+			if (completed)
+				ep_end_in_req(ep, req);
+		} else {
+			if (likely(epout_has_pkt(ep)))
+				completed = read_fifo(ep, req);
+			if (completed)
+				ep_end_out_req(ep, req);
+		}
+	} while (completed);
+}
+
+/**
+ * pxa27x_change_configuration - Handle SET_CONF usb request notification
+ * @udc: udc device
+ * @config: usb configuration
+ *
+ * Post the request to upper level.
+ * Don't use any pxa specific harware configuration capabilities
+ */
+static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
+{
+	struct usb_ctrlrequest req ;
+
+	dev_dbg(udc->dev, "config=%d\n", config);
+
+	udc->config = config;
+	udc->last_interface = 0;
+	udc->last_alternate = 0;
+
+	req.bRequestType = 0;
+	req.bRequest = USB_REQ_SET_CONFIGURATION;
+	req.wValue = config;
+	req.wIndex = 0;
+	req.wLength = 0;
+
+	set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
+	udc->driver->setup(&udc->gadget, &req);
+}
+
+/**
+ * pxa27x_change_interface - Handle SET_INTERF usb request notification
+ * @udc: udc device
+ * @iface: interface number
+ * @alt: alternate setting number
+ *
+ * Post the request to upper level.
+ * Don't use any pxa specific harware configuration capabilities
+ */
+static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
+{
+	struct usb_ctrlrequest  req;
+
+	dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt);
+
+	udc->last_interface = iface;
+	udc->last_alternate = alt;
+
+	req.bRequestType = USB_RECIP_INTERFACE;
+	req.bRequest = USB_REQ_SET_INTERFACE;
+	req.wValue = alt;
+	req.wIndex = iface;
+	req.wLength = 0;
+
+	set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
+	udc->driver->setup(&udc->gadget, &req);
+}
+
+/*
+ * irq_handle_data - Handle data transfer
+ * @irq: irq IRQ number
+ * @udc: dev pxa_udc device structure
+ *
+ * Called from irq handler, transferts data to or from endpoint to queue
+ */
+static void irq_handle_data(int irq, struct pxa_udc *udc)
+{
+	int i;
+	struct pxa_ep *ep;
+	u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK;
+	u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK;
+
+	if (udcisr0 & UDCISR_INT_MASK) {
+		udc->pxa_ep[0].stats.irqs++;
+		udc_writel(udc, UDCISR0, UDCISR_INT(0, UDCISR_INT_MASK));
+		handle_ep0(udc, !!(udcisr0 & UDCICR_FIFOERR),
+				!!(udcisr0 & UDCICR_PKTCOMPL));
+	}
+
+	udcisr0 >>= 2;
+	for (i = 1; udcisr0 != 0 && i < 16; udcisr0 >>= 2, i++) {
+		if (!(udcisr0 & UDCISR_INT_MASK))
+			continue;
+
+		udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK));
+		ep = &udc->pxa_ep[i];
+		ep->stats.irqs++;
+		handle_ep(ep);
+	}
+
+	for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) {
+		udc_writel(udc, UDCISR1, UDCISR_INT(i - 16, UDCISR_INT_MASK));
+		if (!(udcisr1 & UDCISR_INT_MASK))
+			continue;
+
+		ep = &udc->pxa_ep[i];
+		ep->stats.irqs++;
+		handle_ep(ep);
+	}
+
+}
+
+/**
+ * irq_udc_suspend - Handle IRQ "UDC Suspend"
+ * @udc: udc device
+ */
+static void irq_udc_suspend(struct pxa_udc *udc)
+{
+	udc_writel(udc, UDCISR1, UDCISR1_IRSU);
+	udc->stats.irqs_suspend++;
+
+	if (udc->gadget.speed != USB_SPEED_UNKNOWN
+			&& udc->driver && udc->driver->suspend)
+		udc->driver->suspend(&udc->gadget);
+	ep0_idle(udc);
+}
+
+/**
+  * irq_udc_resume - Handle IRQ "UDC Resume"
+  * @udc: udc device
+  */
+static void irq_udc_resume(struct pxa_udc *udc)
+{
+	udc_writel(udc, UDCISR1, UDCISR1_IRRU);
+	udc->stats.irqs_resume++;
+
+	if (udc->gadget.speed != USB_SPEED_UNKNOWN
+			&& udc->driver && udc->driver->resume)
+		udc->driver->resume(&udc->gadget);
+}
+
+/**
+ * irq_udc_reconfig - Handle IRQ "UDC Change Configuration"
+ * @udc: udc device
+ */
+static void irq_udc_reconfig(struct pxa_udc *udc)
+{
+	unsigned config, interface, alternate, config_change;
+	u32 udccr = udc_readl(udc, UDCCR);
+
+	udc_writel(udc, UDCISR1, UDCISR1_IRCC);
+	udc->stats.irqs_reconfig++;
+
+	config = (udccr & UDCCR_ACN) >> UDCCR_ACN_S;
+	config_change = (config != udc->config);
+	pxa27x_change_configuration(udc, config);
+
+	interface = (udccr & UDCCR_AIN) >> UDCCR_AIN_S;
+	alternate = (udccr & UDCCR_AAISN) >> UDCCR_AAISN_S;
+	pxa27x_change_interface(udc, interface, alternate);
+
+	if (config_change)
+		update_pxa_ep_matches(udc);
+	udc_set_mask_UDCCR(udc, UDCCR_SMAC);
+}
+
+/**
+ * irq_udc_reset - Handle IRQ "UDC Reset"
+ * @udc: udc device
+ */
+static void irq_udc_reset(struct pxa_udc *udc)
+{
+	u32 udccr = udc_readl(udc, UDCCR);
+	struct pxa_ep *ep = &udc->pxa_ep[0];
+
+	dev_info(udc->dev, "USB reset\n");
+	udc_writel(udc, UDCISR1, UDCISR1_IRRS);
+	udc->stats.irqs_reset++;
+
+	if ((udccr & UDCCR_UDA) == 0) {
+		dev_dbg(udc->dev, "USB reset start\n");
+		stop_activity(udc, udc->driver);
+	}
+	udc->gadget.speed = USB_SPEED_FULL;
+	memset(&udc->stats, 0, sizeof udc->stats);
+
+	nuke(ep, -EPROTO);
+	udc_ep_writel(ep, UDCCSR, UDCCSR0_FTF | UDCCSR0_OPC);
+	ep0_idle(udc);
+}
+
+/**
+ * pxa_udc_irq - Main irq handler
+ * @irq: irq number
+ * @_dev: udc device
+ *
+ * Handles all udc interrupts
+ */
+static irqreturn_t pxa_udc_irq(int irq, void *_dev)
+{
+	struct pxa_udc *udc = _dev;
+	u32 udcisr0 = udc_readl(udc, UDCISR0);
+	u32 udcisr1 = udc_readl(udc, UDCISR1);
+	u32 udccr = udc_readl(udc, UDCCR);
+	u32 udcisr1_spec;
+
+	dev_vdbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
+		 "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr);
+
+	udcisr1_spec = udcisr1 & 0xf8000000;
+	if (unlikely(udcisr1_spec & UDCISR1_IRSU))
+		irq_udc_suspend(udc);
+	if (unlikely(udcisr1_spec & UDCISR1_IRRU))
+		irq_udc_resume(udc);
+	if (unlikely(udcisr1_spec & UDCISR1_IRCC))
+		irq_udc_reconfig(udc);
+	if (unlikely(udcisr1_spec & UDCISR1_IRRS))
+		irq_udc_reset(udc);
+
+	if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK))
+		irq_handle_data(irq, udc);
+
+	return IRQ_HANDLED;
+}
+
+static struct pxa_udc memory = {
+	.gadget = {
+		.ops		= &pxa_udc_ops,
+		.ep0		= &memory.udc_usb_ep[0].usb_ep,
+		.name		= driver_name,
+		.dev = {
+			.bus_id		= "gadget",
+		},
+	},
+
+	.udc_usb_ep = {
+		USB_EP_CTRL,
+		USB_EP_OUT_BULK(1),
+		USB_EP_IN_BULK(2),
+		USB_EP_IN_ISO(3),
+		USB_EP_OUT_ISO(4),
+		USB_EP_IN_INT(5),
+	},
+
+	.pxa_ep = {
+		PXA_EP_CTRL,
+		/* Endpoints for gadget zero */
+		PXA_EP_OUT_BULK(1, 1, 3, 0, 0),
+		PXA_EP_IN_BULK(2,  2, 3, 0, 0),
+		/* Endpoints for ether gadget, file storage gadget */
+		PXA_EP_OUT_BULK(3, 1, 1, 0, 0),
+		PXA_EP_IN_BULK(4,  2, 1, 0, 0),
+		PXA_EP_IN_ISO(5,   3, 1, 0, 0),
+		PXA_EP_OUT_ISO(6,  4, 1, 0, 0),
+		PXA_EP_IN_INT(7,   5, 1, 0, 0),
+		/* Endpoints for RNDIS, serial */
+		PXA_EP_OUT_BULK(8, 1, 2, 0, 0),
+		PXA_EP_IN_BULK(9,  2, 2, 0, 0),
+		PXA_EP_IN_INT(10,  5, 2, 0, 0),
+		/*
+		 * All the following endpoints are only for completion.  They
+		 * won't never work, as multiple interfaces are really broken on
+		 * the pxa.
+		*/
+		PXA_EP_OUT_BULK(11, 1, 2, 1, 0),
+		PXA_EP_IN_BULK(12,  2, 2, 1, 0),
+		/* Endpoint for CDC Ether */
+		PXA_EP_OUT_BULK(13, 1, 1, 1, 1),
+		PXA_EP_IN_BULK(14,  2, 1, 1, 1),
+	}
+};
+
+/**
+ * pxa_udc_probe - probes the udc device
+ * @_dev: platform device
+ *
+ * Perform basic init : allocates udc clock, creates sysfs files, requests
+ * irq.
+ */
+static int __init pxa_udc_probe(struct platform_device *pdev)
+{
+	struct resource *regs;
+	struct pxa_udc *udc = &memory;
+	int retval;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+	udc->irq = platform_get_irq(pdev, 0);
+	if (udc->irq < 0)
+		return udc->irq;
+
+	udc->dev = &pdev->dev;
+	udc->mach = pdev->dev.platform_data;
+
+	udc->clk = clk_get(&pdev->dev, "UDCCLK");
+	if (IS_ERR(udc->clk)) {
+		retval = PTR_ERR(udc->clk);
+		goto err_clk;
+	}
+
+	retval = -ENOMEM;
+	udc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!udc->regs) {
+		dev_err(&pdev->dev, "Unable to map UDC I/O memory\n");
+		goto err_map;
+	}
+
+	device_initialize(&udc->gadget.dev);
+	udc->gadget.dev.parent = &pdev->dev;
+	udc->gadget.dev.dma_mask = NULL;
+
+	the_controller = udc;
+	platform_set_drvdata(pdev, udc);
+	udc_init_data(udc);
+	pxa_eps_setup(udc);
+
+	/* irq setup after old hardware state is cleaned up */
+	retval = request_irq(udc->irq, pxa_udc_irq,
+			IRQF_SHARED, driver_name, udc);
+	if (retval != 0) {
+		dev_err(udc->dev, "%s: can't get irq %i, err %d\n",
+			driver_name, IRQ_USB, retval);
+		goto err_irq;
+	}
+
+	pxa_init_debugfs(udc);
+	return 0;
+err_irq:
+	iounmap(udc->regs);
+err_map:
+	clk_put(udc->clk);
+	udc->clk = NULL;
+err_clk:
+	return retval;
+}
+
+/**
+ * pxa_udc_remove - removes the udc device driver
+ * @_dev: platform device
+ */
+static int __exit pxa_udc_remove(struct platform_device *_dev)
+{
+	struct pxa_udc *udc = platform_get_drvdata(_dev);
+
+	usb_gadget_unregister_driver(udc->driver);
+	free_irq(udc->irq, udc);
+	pxa_cleanup_debugfs(udc);
+
+	platform_set_drvdata(_dev, NULL);
+	the_controller = NULL;
+	clk_put(udc->clk);
+
+	return 0;
+}
+
+static void pxa_udc_shutdown(struct platform_device *_dev)
+{
+	struct pxa_udc *udc = platform_get_drvdata(_dev);
+
+	udc_disable(udc);
+}
+
+#ifdef CONFIG_PM
+/**
+ * pxa_udc_suspend - Suspend udc device
+ * @_dev: platform device
+ * @state: suspend state
+ *
+ * Suspends udc : saves configuration registers (UDCCR*), then disables the udc
+ * device.
+ */
+static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
+{
+	int i;
+	struct pxa_udc *udc = platform_get_drvdata(_dev);
+	struct pxa_ep *ep;
+
+	ep = &udc->pxa_ep[0];
+	udc->udccsr0 = udc_ep_readl(ep, UDCCSR);
+	for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+		ep = &udc->pxa_ep[i];
+		ep->udccsr_value = udc_ep_readl(ep, UDCCSR);
+		ep->udccr_value  = udc_ep_readl(ep, UDCCR);
+		ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
+				ep->udccsr_value, ep->udccr_value);
+	}
+
+	udc_disable(udc);
+
+	return 0;
+}
+
+/**
+ * pxa_udc_resume - Resume udc device
+ * @_dev: platform device
+ *
+ * Resumes udc : restores configuration registers (UDCCR*), then enables the udc
+ * device.
+ */
+static int pxa_udc_resume(struct platform_device *_dev)
+{
+	int i;
+	struct pxa_udc *udc = platform_get_drvdata(_dev);
+	struct pxa_ep *ep;
+
+	ep = &udc->pxa_ep[0];
+	udc_ep_writel(ep, UDCCSR, udc->udccsr0 & (UDCCSR0_FST | UDCCSR0_DME));
+	for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+		ep = &udc->pxa_ep[i];
+		udc_ep_writel(ep, UDCCSR, ep->udccsr_value);
+		udc_ep_writel(ep, UDCCR,  ep->udccr_value);
+		ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
+				ep->udccsr_value, ep->udccr_value);
+	}
+
+	udc_enable(udc);
+	/*
+	 * We do not handle OTG yet.
+	 *
+	 * OTGPH bit is set when sleep mode is entered.
+	 * it indicates that OTG pad is retaining its state.
+	 * Upon exit from sleep mode and before clearing OTGPH,
+	 * Software must configure the USB OTG pad, UDC, and UHC
+	 * to the state they were in before entering sleep mode.
+	 *
+	 * Should be : PSSR |= PSSR_OTGPH;
+	 */
+
+	return 0;
+}
+#endif
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:pxa2xx-udc");
+
+static struct platform_driver udc_driver = {
+	.driver		= {
+		.name	= "pxa2xx-udc",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(pxa_udc_remove),
+	.shutdown	= pxa_udc_shutdown,
+#ifdef CONFIG_PM
+	.suspend	= pxa_udc_suspend,
+	.resume		= pxa_udc_resume
+#endif
+};
+
+static int __init udc_init(void)
+{
+	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+	return platform_driver_probe(&udc_driver, pxa_udc_probe);
+}
+module_init(udc_init);
+
+
+static void __exit udc_exit(void)
+{
+	platform_driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
new file mode 100644
index 0000000..1d1b7936
--- /dev/null
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -0,0 +1,487 @@
+/*
+ * linux/drivers/usb/gadget/pxa27x_udc.h
+ * Intel PXA27x on-chip full speed USB device controller
+ *
+ * Inspired by original driver by Frank Becker, David Brownell, and others.
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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
+ */
+
+#ifndef __LINUX_USB_GADGET_PXA27X_H
+#define __LINUX_USB_GADGET_PXA27X_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+/*
+ * Register definitions
+ */
+/* Offsets */
+#define UDCCR		0x0000		/* UDC Control Register */
+#define UDCICR0		0x0004		/* UDC Interrupt Control Register0 */
+#define UDCICR1		0x0008		/* UDC Interrupt Control Register1 */
+#define UDCISR0		0x000C		/* UDC Interrupt Status Register 0 */
+#define UDCISR1		0x0010		/* UDC Interrupt Status Register 1 */
+#define UDCFNR		0x0014		/* UDC Frame Number Register */
+#define UDCOTGICR	0x0018		/* UDC On-The-Go interrupt control */
+#define UP2OCR		0x0020		/* USB Port 2 Output Control register */
+#define UP3OCR		0x0024		/* USB Port 3 Output Control register */
+#define UDCCSRn(x)	(0x0100 + ((x)<<2)) /* UDC Control/Status register */
+#define UDCBCRn(x)	(0x0200 + ((x)<<2)) /* UDC Byte Count Register */
+#define UDCDRn(x)	(0x0300 + ((x)<<2)) /* UDC Data Register  */
+#define UDCCRn(x)	(0x0400 + ((x)<<2)) /* UDC Control Register */
+
+#define UDCCR_OEN	(1 << 31)	/* On-the-Go Enable */
+#define UDCCR_AALTHNP	(1 << 30)	/* A-device Alternate Host Negotiation
+					   Protocol Port Support */
+#define UDCCR_AHNP	(1 << 29)	/* A-device Host Negotiation Protocol
+					   Support */
+#define UDCCR_BHNP	(1 << 28)	/* B-device Host Negotiation Protocol
+					   Enable */
+#define UDCCR_DWRE	(1 << 16)	/* Device Remote Wake-up Enable */
+#define UDCCR_ACN	(0x03 << 11)	/* Active UDC configuration Number */
+#define UDCCR_ACN_S	11
+#define UDCCR_AIN	(0x07 << 8)	/* Active UDC interface Number */
+#define UDCCR_AIN_S	8
+#define UDCCR_AAISN	(0x07 << 5)	/* Active UDC Alternate Interface
+					   Setting Number */
+#define UDCCR_AAISN_S	5
+#define UDCCR_SMAC	(1 << 4)	/* Switch Endpoint Memory to Active
+					   Configuration */
+#define UDCCR_EMCE	(1 << 3)	/* Endpoint Memory Configuration
+					   Error */
+#define UDCCR_UDR	(1 << 2)	/* UDC Resume */
+#define UDCCR_UDA	(1 << 1)	/* UDC Active */
+#define UDCCR_UDE	(1 << 0)	/* UDC Enable */
+
+#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCICR1_IECC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCICR1_IESOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCICR1_IERU	(1 << 29)	/* IntEn - Resume */
+#define UDCICR1_IESU	(1 << 28)	/* IntEn - Suspend */
+#define UDCICR1_IERS	(1 << 27)	/* IntEn - Reset */
+#define UDCICR_FIFOERR	(1 << 1)	/* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL	(1 << 0)	/* Packet Complete interrupt for EP */
+#define UDCICR_INT_MASK	(UDCICR_FIFOERR | UDCICR_PKTCOMPL)
+
+#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC	(1 << 31)	/* IntReq - Configuration Change */
+#define UDCISR1_IRSOF	(1 << 30)	/* IntReq - Start of Frame */
+#define UDCISR1_IRRU	(1 << 29)	/* IntReq - Resume */
+#define UDCISR1_IRSU	(1 << 28)	/* IntReq - Suspend */
+#define UDCISR1_IRRS	(1 << 27)	/* IntReq - Reset */
+#define UDCISR_INT_MASK	(UDCICR_FIFOERR | UDCICR_PKTCOMPL)
+
+#define UDCOTGICR_IESF	(1 << 24)	/* OTG SET_FEATURE command recvd */
+#define UDCOTGICR_IEXR	(1 << 17)	/* Extra Transciever Interrupt
+					   Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEXF	(1 << 16)	/* Extra Transciever Interrupt
+					   Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40R (1 << 9)	/* OTG Vbus Valid 4.0V Rising Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IEVV40F (1 << 8)	/* OTG Vbus Valid 4.0V Falling Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IEVV44R (1 << 7)	/* OTG Vbus Valid 4.4V Rising Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IEVV44F (1 << 6)	/* OTG Vbus Valid 4.4V Falling Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IESVR	(1 << 5)	/* OTG Session Valid Rising Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IESVF	(1 << 4)	/* OTG Session Valid Falling Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IESDR	(1 << 3)	/* OTG A-Device SRP Detect Rising
+					   Edge Interrupt Enable */
+#define UDCOTGICR_IESDF	(1 << 2)	/* OTG A-Device SRP Detect Falling
+					   Edge Interrupt Enable */
+#define UDCOTGICR_IEIDR	(1 << 1)	/* OTG ID Change Rising Edge
+					   Interrupt Enable */
+#define UDCOTGICR_IEIDF	(1 << 0)	/* OTG ID Change Falling Edge
+					   Interrupt Enable */
+
+/* Host Port 2 field bits */
+#define UP2OCR_CPVEN	(1 << 0)	/* Charge Pump Vbus Enable */
+#define UP2OCR_CPVPE	(1 << 1)	/* Charge Pump Vbus Pulse Enable */
+					/* Transceiver enablers */
+#define UP2OCR_DPPDE	(1 << 2)	/*   D+ Pull Down Enable */
+#define UP2OCR_DMPDE	(1 << 3)	/*   D- Pull Down Enable */
+#define UP2OCR_DPPUE	(1 << 4)	/*   D+ Pull Up Enable */
+#define UP2OCR_DMPUE	(1 << 5)	/*   D- Pull Up Enable */
+#define UP2OCR_DPPUBE	(1 << 6)	/*   D+ Pull Up Bypass Enable */
+#define UP2OCR_DMPUBE	(1 << 7)	/*   D- Pull Up Bypass Enable */
+#define UP2OCR_EXSP	(1 << 8)	/* External Transceiver Speed Control */
+#define UP2OCR_EXSUS	(1 << 9)	/* External Transceiver Speed Enable */
+#define UP2OCR_IDON	(1 << 10)	/* OTG ID Read Enable */
+#define UP2OCR_HXS	(1 << 16)	/* Transceiver Output Select */
+#define UP2OCR_HXOE	(1 << 17)	/* Transceiver Output Enable */
+#define UP2OCR_SEOS	(1 << 24)	/* Single-Ended Output Select */
+
+#define UDCCSR0_SA	(1 << 7)	/* Setup Active */
+#define UDCCSR0_RNE	(1 << 6)	/* Receive FIFO Not Empty */
+#define UDCCSR0_FST	(1 << 5)	/* Force Stall */
+#define UDCCSR0_SST	(1 << 4)	/* Sent Stall */
+#define UDCCSR0_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR0_FTF	(1 << 2)	/* Flush Transmit FIFO */
+#define UDCCSR0_IPR	(1 << 1)	/* IN Packet Ready */
+#define UDCCSR0_OPC	(1 << 0)	/* OUT Packet Complete */
+
+#define UDCCSR_DPE	(1 << 9)	/* Data Packet Error */
+#define UDCCSR_FEF	(1 << 8)	/* Flush Endpoint FIFO */
+#define UDCCSR_SP	(1 << 7)	/* Short Packet Control/Status */
+#define UDCCSR_BNE	(1 << 6)	/* Buffer Not Empty (IN endpoints) */
+#define UDCCSR_BNF	(1 << 6)	/* Buffer Not Full (OUT endpoints) */
+#define UDCCSR_FST	(1 << 5)	/* Force STALL */
+#define UDCCSR_SST	(1 << 4)	/* Sent STALL */
+#define UDCCSR_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR_TRN	(1 << 2)	/* Tx/Rx NAK */
+#define UDCCSR_PC	(1 << 1)	/* Packet Complete */
+#define UDCCSR_FS	(1 << 0)	/* FIFO needs service */
+
+#define UDCCONR_CN	(0x03 << 25)	/* Configuration Number */
+#define UDCCONR_CN_S	25
+#define UDCCONR_IN	(0x07 << 22)	/* Interface Number */
+#define UDCCONR_IN_S	22
+#define UDCCONR_AISN	(0x07 << 19)	/* Alternate Interface Number */
+#define UDCCONR_AISN_S	19
+#define UDCCONR_EN	(0x0f << 15)	/* Endpoint Number */
+#define UDCCONR_EN_S	15
+#define UDCCONR_ET	(0x03 << 13)	/* Endpoint Type: */
+#define UDCCONR_ET_S	13
+#define UDCCONR_ET_INT	(0x03 << 13)	/*   Interrupt */
+#define UDCCONR_ET_BULK	(0x02 << 13)	/*   Bulk */
+#define UDCCONR_ET_ISO	(0x01 << 13)	/*   Isochronous */
+#define UDCCONR_ET_NU	(0x00 << 13)	/*   Not used */
+#define UDCCONR_ED	(1 << 12)	/* Endpoint Direction */
+#define UDCCONR_MPS	(0x3ff << 2)	/* Maximum Packet Size */
+#define UDCCONR_MPS_S	2
+#define UDCCONR_DE	(1 << 1)	/* Double Buffering Enable */
+#define UDCCONR_EE	(1 << 0)	/* Endpoint Enable */
+
+#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE)
+#define UDCCSR_WR_MASK	(UDCCSR_DME | UDCCSR_FST)
+#define UDC_FNR_MASK	(0x7ff)
+#define UDC_BCR_MASK	(0x3ff)
+
+/*
+ * UDCCR = UDC Endpoint Configuration Registers
+ * UDCCSR = UDC Control/Status Register for this EP
+ * UDCBCR = UDC Byte Count Remaining (contents of OUT fifo)
+ * UDCDR = UDC Endpoint Data Register (the fifo)
+ */
+#define ofs_UDCCR(ep)	(UDCCRn(ep->idx))
+#define ofs_UDCCSR(ep)	(UDCCSRn(ep->idx))
+#define ofs_UDCBCR(ep)	(UDCBCRn(ep->idx))
+#define ofs_UDCDR(ep)	(UDCDRn(ep->idx))
+
+/* Register access macros */
+#define udc_ep_readl(ep, reg)	\
+	__raw_readl((ep)->dev->regs + ofs_##reg(ep))
+#define udc_ep_writel(ep, reg, value)	\
+	__raw_writel((value), ep->dev->regs + ofs_##reg(ep))
+#define udc_ep_readb(ep, reg)	\
+	__raw_readb((ep)->dev->regs + ofs_##reg(ep))
+#define udc_ep_writeb(ep, reg, value)	\
+	__raw_writeb((value), ep->dev->regs + ofs_##reg(ep))
+#define udc_readl(dev, reg)	\
+	__raw_readl((dev)->regs + (reg))
+#define udc_writel(udc, reg, value)	\
+	__raw_writel((value), (udc)->regs + (reg))
+
+#define UDCCSR_MASK		(UDCCSR_FST | UDCCSR_DME)
+#define UDCCISR0_EP_MASK	~0
+#define UDCCISR1_EP_MASK	0xffff
+#define UDCCSR0_CTRL_REQ_MASK	(UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)
+
+#define EPIDX(ep)	(ep->idx)
+#define EPADDR(ep)	(ep->addr)
+#define EPXFERTYPE(ep)	(ep->type)
+#define EPNAME(ep)	(ep->name)
+#define is_ep0(ep)	(!ep->idx)
+#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC)
+
+/*
+ * Endpoint definitions
+ *
+ * Once enabled, pxa endpoint configuration is freezed, and cannot change
+ * unless a reset happens or the udc is disabled.
+ * Therefore, we must define all pxa potential endpoint definitions needed for
+ * all gadget and set them up before the udc is enabled.
+ *
+ * As the architecture chosen is fully static, meaning the pxa endpoint
+ * configurations are set up once and for all, we must provide a way to match
+ * one usb endpoint (usb_ep) to several pxa endpoints. The reason is that gadget
+ * layer autoconf doesn't choose the usb_ep endpoint on (config, interface, alt)
+ * criteria, while the pxa architecture requires that.
+ *
+ * The solution is to define several pxa endpoints matching one usb_ep. Ex:
+ *   - "ep1-in" matches pxa endpoint EPA (which is an IN ep at addr 1, when
+ *     the udc talks on (config=3, interface=0, alt=0)
+ *   - "ep1-in" matches pxa endpoint EPB (which is an IN ep at addr 1, when
+ *     the udc talks on (config=3, interface=0, alt=1)
+ *   - "ep1-in" matches pxa endpoint EPC (which is an IN ep at addr 1, when
+ *     the udc talks on (config=2, interface=0, alt=0)
+ *
+ * We'll define the pxa endpoint by its index (EPA => idx=1, EPB => idx=2, ...)
+ */
+
+/*
+ * Endpoint definition helpers
+ */
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
+{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+  .desc = {	.bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
+		.bmAttributes = type, \
+		.wMaxPacketSize = maxpkt, }, \
+  .dev = &memory \
+}
+#define USB_EP_BULK(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
+#define USB_EP_ISO(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
+#define USB_EP_INT(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
+#define USB_EP_IN_BULK(n)	USB_EP_BULK(n, "ep" #n "in-bulk", 1)
+#define USB_EP_OUT_BULK(n)	USB_EP_BULK(n, "ep" #n "out-bulk", 0)
+#define USB_EP_IN_ISO(n)	USB_EP_ISO(n,  "ep" #n "in-iso", 1)
+#define USB_EP_OUT_ISO(n)	USB_EP_ISO(n,  "ep" #n "out-iso", 0)
+#define USB_EP_IN_INT(n)	USB_EP_INT(n,  "ep" #n "in-int", 1)
+#define USB_EP_CTRL		USB_EP_DEF(0,  "ep0", 0, 0, EP0_FIFO_SIZE)
+
+#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
+{ \
+	.dev = &memory, \
+	.name = "ep" #_idx, \
+	.idx = _idx, .enabled = 0, \
+	.dir_in = dir, .addr = _addr, \
+	.config = _config, .interface = iface, .alternate = altset, \
+	.type = _type, .fifo_size = maxpkt, \
+}
+#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \
+		config, iface, alt)
+#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \
+		config, iface, alt)
+#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \
+		config, iface, alt)
+#define PXA_EP_IN_BULK(i, adr, c, f, a)		PXA_EP_BULK(i, adr, 1, c, f, a)
+#define PXA_EP_OUT_BULK(i, adr, c, f, a)	PXA_EP_BULK(i, adr, 0, c, f, a)
+#define PXA_EP_IN_ISO(i, adr, c, f, a)		PXA_EP_ISO(i, adr, 1, c, f, a)
+#define PXA_EP_OUT_ISO(i, adr, c, f, a)		PXA_EP_ISO(i, adr, 0, c, f, a)
+#define PXA_EP_IN_INT(i, adr, c, f, a)		PXA_EP_INT(i, adr, 1, c, f, a)
+#define PXA_EP_CTRL	PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0)
+
+struct pxa27x_udc;
+
+struct stats {
+	unsigned long in_ops;
+	unsigned long out_ops;
+	unsigned long in_bytes;
+	unsigned long out_bytes;
+	unsigned long irqs;
+};
+
+/**
+ * struct udc_usb_ep - container of each usb_ep structure
+ * @usb_ep: usb endpoint
+ * @desc: usb descriptor, especially type and address
+ * @dev: udc managing this endpoint
+ * @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call)
+ */
+struct udc_usb_ep {
+	struct usb_ep usb_ep;
+	struct usb_endpoint_descriptor desc;
+	struct pxa_udc *dev;
+	struct pxa_ep *pxa_ep;
+};
+
+/**
+ * struct pxa_ep - pxa endpoint
+ * @dev: udc device
+ * @queue: requests queue
+ * @lock: lock to pxa_ep data (queues and stats)
+ * @enabled: true when endpoint enabled (not stopped by gadget layer)
+ * @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
+ * @name: endpoint name (for trace/debug purpose)
+ * @dir_in: 1 if IN endpoint, 0 if OUT endpoint
+ * @addr: usb endpoint number
+ * @config: configuration in which this endpoint is active
+ * @interface: interface in which this endpoint is active
+ * @alternate: altsetting in which this endpoitn is active
+ * @fifo_size: max packet size in the endpoint fifo
+ * @type: endpoint type (bulk, iso, int, ...)
+ * @udccsr_value: save register of UDCCSR0 for suspend/resume
+ * @udccr_value: save register of UDCCR for suspend/resume
+ * @stats: endpoint statistics
+ *
+ * The *PROBLEM* is that pxa's endpoint configuration scheme is both misdesigned
+ * (cares about config/interface/altsetting, thus placing needless limits on
+ * device capability) and full of implementation bugs forcing it to be set up
+ * for use more or less like a pxa255.
+ *
+ * As we define the pxa_ep statically, we must guess all needed pxa_ep for all
+ * gadget which may work with this udc driver.
+ */
+struct pxa_ep {
+	struct pxa_udc		*dev;
+
+	struct list_head	queue;
+	spinlock_t		lock;		/* Protects this structure */
+						/* (queues, stats) */
+	unsigned		enabled:1;
+
+	unsigned		idx:5;
+	char			*name;
+
+	/*
+	 * Specific pxa endpoint data, needed for hardware initialization
+	 */
+	unsigned		dir_in:1;
+	unsigned		addr:3;
+	unsigned		config:2;
+	unsigned		interface:3;
+	unsigned		alternate:3;
+	unsigned		fifo_size;
+	unsigned		type;
+
+#ifdef CONFIG_PM
+	u32			udccsr_value;
+	u32			udccr_value;
+#endif
+	struct stats		stats;
+};
+
+/**
+ * struct pxa27x_request - container of each usb_request structure
+ * @req: usb request
+ * @udc_usb_ep: usb endpoint the request was submitted on
+ * @in_use: sanity check if request already queued on an pxa_ep
+ * @queue: linked list of requests, linked on pxa_ep->queue
+ */
+struct pxa27x_request {
+	struct usb_request			req;
+	struct udc_usb_ep			*udc_usb_ep;
+	unsigned				in_use:1;
+	struct list_head			queue;
+};
+
+enum ep0_state {
+	WAIT_FOR_SETUP,
+	SETUP_STAGE,
+	IN_DATA_STAGE,
+	OUT_DATA_STAGE,
+	IN_STATUS_STAGE,
+	OUT_STATUS_STAGE,
+	STALL,
+	WAIT_ACK_SET_CONF_INTERF
+};
+
+static char *ep0_state_name[] = {
+	"WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE",
+	"IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL",
+	"WAIT_ACK_SET_CONF_INTERF"
+};
+#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state]
+
+#define EP0_FIFO_SIZE	16U
+#define BULK_FIFO_SIZE	64U
+#define ISO_FIFO_SIZE	256U
+#define INT_FIFO_SIZE	16U
+
+struct udc_stats {
+	unsigned long	irqs_reset;
+	unsigned long	irqs_suspend;
+	unsigned long	irqs_resume;
+	unsigned long	irqs_reconfig;
+};
+
+#define NR_USB_ENDPOINTS (1 + 5)	/* ep0 + ep1in-bulk + .. + ep3in-iso */
+#define NR_PXA_ENDPOINTS (1 + 14)	/* ep0 + epA + epB + .. + epX */
+
+/**
+ * struct pxa_udc - udc structure
+ * @regs: mapped IO space
+ * @irq: udc irq
+ * @clk: udc clock
+ * @usb_gadget: udc gadget structure
+ * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
+ * @dev: device
+ * @mach: machine info, used to activate specific GPIO
+ * @ep0state: control endpoint state machine state
+ * @stats: statistics on udc usage
+ * @udc_usb_ep: array of usb endpoints offered by the gadget
+ * @pxa_ep: array of pxa available endpoints
+ * @config: UDC active configuration
+ * @last_interface: UDC interface of the last SET_INTERFACE host request
+ * @last_alternate: UDC altsetting of the last SET_INTERFACE host request
+ * @udccsr0: save of udccsr0 in case of suspend
+ * @debugfs_root: root entry of debug filesystem
+ * @debugfs_state: debugfs entry for "udcstate"
+ * @debugfs_queues: debugfs entry for "queues"
+ * @debugfs_eps: debugfs entry for "epstate"
+ */
+struct pxa_udc {
+	void __iomem				*regs;
+	int					irq;
+	struct clk				*clk;
+
+	struct usb_gadget			gadget;
+	struct usb_gadget_driver		*driver;
+	struct device				*dev;
+	struct pxa2xx_udc_mach_info		*mach;
+
+	enum ep0_state				ep0state;
+	struct udc_stats			stats;
+
+	struct udc_usb_ep			udc_usb_ep[NR_USB_ENDPOINTS];
+	struct pxa_ep				pxa_ep[NR_PXA_ENDPOINTS];
+
+	unsigned				config:2;
+	unsigned				last_interface:3;
+	unsigned				last_alternate:3;
+
+#ifdef CONFIG_PM
+	unsigned				udccsr0;
+#endif
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+	struct dentry				*debugfs_root;
+	struct dentry				*debugfs_state;
+	struct dentry				*debugfs_queues;
+	struct dentry				*debugfs_eps;
+#endif
+};
+
+static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
+{
+	return container_of(gadget, struct pxa_udc, gadget);
+}
+
+/*
+ * Debugging/message support
+ */
+#define ep_dbg(ep, fmt, arg...) \
+	dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_vdbg(ep, fmt, arg...) \
+	dev_vdbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_err(ep, fmt, arg...) \
+	dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_info(ep, fmt, arg...) \
+	dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_warn(ep, fmt, arg...) \
+	dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
+
+#endif /* __LINUX_USB_GADGET_PXA27X_H */
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 8d158e5..54cdd6f 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -135,7 +135,10 @@
 	int			port_in_use;	/* open/close in progress */
 	wait_queue_head_t	port_write_wait;/* waiting to write */
 	struct gs_buf		*port_write_buf;
-	struct usb_cdc_line_coding	port_line_coding;
+	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
+	u16			port_handshake_bits;
+#define RS232_RTS	(1 << 1)
+#define RS232_DTE	(1 << 0)
 };
 
 /* the device structure holds info for the USB device */
@@ -199,6 +202,8 @@
 static int gs_setup_class(struct usb_gadget *gadget,
 	const struct usb_ctrlrequest *ctrl);
 static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req);
+static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
+	struct usb_request *req);
 static void gs_disconnect(struct usb_gadget *gadget);
 static int gs_set_config(struct gs_dev *dev, unsigned config);
 static void gs_reset_config(struct gs_dev *dev);
@@ -406,7 +411,7 @@
 	.bLength =		sizeof(gs_acm_descriptor),
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-	.bmCapabilities =	0,
+	.bmCapabilities =	(1 << 1),
 };
 
 static const struct usb_cdc_union_desc gs_union_desc = {
@@ -1502,6 +1507,8 @@
 	u16 wValue = le16_to_cpu(ctrl->wValue);
 	u16 wLength = le16_to_cpu(ctrl->wLength);
 
+	req->complete = gs_setup_complete;
+
 	switch (ctrl->bRequestType & USB_TYPE_MASK) {
 	case USB_TYPE_STANDARD:
 		ret = gs_setup_standard(gadget,ctrl);
@@ -1679,18 +1686,14 @@
 
 	switch (ctrl->bRequest) {
 	case USB_CDC_REQ_SET_LINE_CODING:
-		/* FIXME Submit req to read the data; have its completion
-		 * handler copy that data to port->port_line_coding (iff
-		 * it's valid) and maybe pass it on.  Until then, fail.
-		 */
-		pr_warning("gs_setup: set_line_coding "
-				"unuspported\n");
+		if (wLength != sizeof(struct usb_cdc_line_coding))
+			break;
+		ret = wLength;
+		req->complete = gs_setup_complete_set_line_coding;
 		break;
 
 	case USB_CDC_REQ_GET_LINE_CODING:
-		port = dev->dev_port[0];	/* ACM only has one port */
-		ret = min(wLength,
-			(u16)sizeof(struct usb_cdc_line_coding));
+		ret = min_t(int, wLength, sizeof(struct usb_cdc_line_coding));
 		if (port) {
 			spin_lock(&port->port_lock);
 			memcpy(req->buf, &port->port_line_coding, ret);
@@ -1699,15 +1702,27 @@
 		break;
 
 	case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
-		/* FIXME Submit req to read the data; have its completion
-		 * handler use that to set the state (iff it's valid) and
-		 * maybe pass it on.  Until then, fail.
-		 */
-		pr_warning("gs_setup: set_control_line_state "
-				"unuspported\n");
+		if (wLength != 0)
+			break;
+		ret = 0;
+		if (port) {
+			/* REVISIT:  we currently just remember this data.
+			 * If we change that, update whatever hardware needs
+			 * updating.
+			 */
+			spin_lock(&port->port_lock);
+			port->port_handshake_bits = wValue;
+			spin_unlock(&port->port_lock);
+		}
 		break;
 
 	default:
+		/* NOTE:  strictly speaking, we should accept AT-commands
+		 * using SEND_ENCPSULATED_COMMAND/GET_ENCAPSULATED_RESPONSE.
+		 * But our call management descriptor says we don't handle
+		 * call management, so we should be able to get by without
+		 * handling those "required" commands (except by stalling).
+		 */
 		pr_err("gs_setup: unknown class request, "
 				"type=%02x, request=%02x, value=%04x, "
 				"index=%04x, length=%d\n",
@@ -1719,6 +1734,42 @@
 	return ret;
 }
 
+static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
+		struct usb_request *req)
+{
+	struct gs_dev *dev = ep->driver_data;
+	struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
+
+	switch (req->status) {
+	case 0:
+		/* normal completion */
+		if (req->actual != sizeof(port->port_line_coding))
+			usb_ep_set_halt(ep);
+		else if (port) {
+			struct usb_cdc_line_coding	*value = req->buf;
+
+			/* REVISIT:  we currently just remember this data.
+			 * If we change that, (a) validate it first, then
+			 * (b) update whatever hardware needs updating.
+			 */
+			spin_lock(&port->port_lock);
+			port->port_line_coding = *value;
+			spin_unlock(&port->port_lock);
+		}
+		break;
+
+	case -ESHUTDOWN:
+		/* disconnect */
+		gs_free_req(ep, req);
+		break;
+
+	default:
+		/* unexpected */
+		break;
+	}
+	return;
+}
+
 /*
  * gs_setup_complete
  */
@@ -1906,6 +1957,11 @@
 		}
 	}
 
+	/* REVISIT the ACM mode should be able to actually *issue* some
+	 * notifications, for at least serial state change events if
+	 * not also for network connection; say so in bmCapabilities.
+	 */
+
 	pr_info("gs_set_config: %s configured, %s speed %s config\n",
 		GS_LONG_NAME,
 		gadget->speed == USB_SPEED_HIGH ? "high" : "full",
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index d3d4f40..fce4924 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -23,9 +23,7 @@
 /*
  * Gadget Zero only needs two bulk endpoints, and is an example of how you
  * can write a hardware-agnostic gadget driver running inside a USB device.
- *
- * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
- * affect most of the driver.
+ * Some hardware details are visible, but don't affect most of the driver.
  *
  * Use it with the Linux host/master side "usbtest" driver to get a basic
  * functional test of your device-side usb stack, or with "usb-skeleton".
@@ -37,6 +35,7 @@
  *   buflen=N		default N=4096, buffer size used
  *   qlen=N		default N=32, how many buffers in the loopback queue
  *   loopdefault	default false, list loopback config first
+ *   autoresume=N	default N=0, seconds before triggering remote wakeup
  *
  * Many drivers will only have one configuration, letting them be much
  * simpler if they also don't support high speed operation (like this
@@ -62,13 +61,13 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define DRIVER_VERSION		"Lughnasadh, 2007"
+#define DRIVER_VERSION		"Earth Day 2008"
 
-static const char shortname [] = "zero";
-static const char longname [] = "Gadget Zero";
+static const char shortname[] = "zero";
+static const char longname[] = "Gadget Zero";
 
-static const char source_sink [] = "source and sink data";
-static const char loopback [] = "loop input to output";
+static const char source_sink[] = "source and sink data";
+static const char loopback[] = "loop input to output";
 
 /*-------------------------------------------------------------------------*/
 
@@ -120,16 +119,16 @@
 static unsigned qlen = 32;
 static unsigned pattern = 0;
 
-module_param (buflen, uint, S_IRUGO);
-module_param (qlen, uint, S_IRUGO);
-module_param (pattern, uint, S_IRUGO|S_IWUSR);
+module_param(buflen, uint, S_IRUGO);
+module_param(qlen, uint, S_IRUGO);
+module_param(pattern, uint, S_IRUGO|S_IWUSR);
 
 /*
  * if it's nonzero, autoresume says how many seconds to wait
  * before trying to wake up the host after suspend.
  */
 static unsigned autoresume = 0;
-module_param (autoresume, uint, 0);
+module_param(autoresume, uint, 0);
 
 /*
  * Normally the "loopback" configuration is second (index 1) so
@@ -138,8 +137,7 @@
  * Or controllers (like superh) that only support one config.
  */
 static int loopdefault = 0;
-
-module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
+module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
 
 /*-------------------------------------------------------------------------*/
 
@@ -176,24 +174,22 @@
 #define	CONFIG_SOURCE_SINK	3
 #define	CONFIG_LOOPBACK		2
 
-static struct usb_device_descriptor
-device_desc = {
+static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 
-	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
+	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.iSerialNumber =	STRING_SERIAL,
 	.bNumConfigurations =	2,
 };
 
-static struct usb_config_descriptor
-source_sink_config = {
+static struct usb_config_descriptor source_sink_config = {
 	.bLength =		sizeof source_sink_config,
 	.bDescriptorType =	USB_DT_CONFIG,
 
@@ -205,8 +201,7 @@
 	.bMaxPower =		1,	/* self-powered */
 };
 
-static struct usb_config_descriptor
-loopback_config = {
+static struct usb_config_descriptor loopback_config = {
 	.bLength =		sizeof loopback_config,
 	.bDescriptorType =	USB_DT_CONFIG,
 
@@ -218,8 +213,7 @@
 	.bMaxPower =		1,	/* self-powered */
 };
 
-static struct usb_otg_descriptor
-otg_descriptor = {
+static struct usb_otg_descriptor otg_descriptor = {
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
@@ -228,8 +222,7 @@
 
 /* one interface in each configuration */
 
-static const struct usb_interface_descriptor
-source_sink_intf = {
+static const struct usb_interface_descriptor source_sink_intf = {
 	.bLength =		sizeof source_sink_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
@@ -238,8 +231,7 @@
 	.iInterface =		STRING_SOURCE_SINK,
 };
 
-static const struct usb_interface_descriptor
-loopback_intf = {
+static const struct usb_interface_descriptor loopback_intf = {
 	.bLength =		sizeof loopback_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
@@ -250,8 +242,7 @@
 
 /* two full speed bulk endpoints; their use is config-dependent */
 
-static struct usb_endpoint_descriptor
-fs_source_desc = {
+static struct usb_endpoint_descriptor fs_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -259,8 +250,7 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor
-fs_sink_desc = {
+static struct usb_endpoint_descriptor fs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -268,7 +258,7 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static const struct usb_descriptor_header *fs_source_sink_function [] = {
+static const struct usb_descriptor_header *fs_source_sink_function[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
 	(struct usb_descriptor_header *) &source_sink_intf,
 	(struct usb_descriptor_header *) &fs_sink_desc,
@@ -276,7 +266,7 @@
 	NULL,
 };
 
-static const struct usb_descriptor_header *fs_loopback_function [] = {
+static const struct usb_descriptor_header *fs_loopback_function[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
 	(struct usb_descriptor_header *) &loopback_intf,
 	(struct usb_descriptor_header *) &fs_sink_desc,
@@ -293,36 +283,33 @@
  * for the config descriptor.
  */
 
-static struct usb_endpoint_descriptor
-hs_source_desc = {
+static struct usb_endpoint_descriptor hs_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor
-hs_sink_desc = {
+static struct usb_endpoint_descriptor hs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static struct usb_qualifier_descriptor
-dev_qualifier = {
+static struct usb_qualifier_descriptor dev_qualifier = {
 	.bLength =		sizeof dev_qualifier,
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 
 	.bNumConfigurations =	2,
 };
 
-static const struct usb_descriptor_header *hs_source_sink_function [] = {
+static const struct usb_descriptor_header *hs_source_sink_function[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
 	(struct usb_descriptor_header *) &source_sink_intf,
 	(struct usb_descriptor_header *) &hs_source_desc,
@@ -330,7 +317,7 @@
 	NULL,
 };
 
-static const struct usb_descriptor_header *hs_loopback_function [] = {
+static const struct usb_descriptor_header *hs_loopback_function[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
 	(struct usb_descriptor_header *) &loopback_intf,
 	(struct usb_descriptor_header *) &hs_source_desc,
@@ -355,7 +342,7 @@
 
 
 /* static strings, in UTF-8 */
-static struct usb_string		strings [] = {
+static struct usb_string strings[] = {
 	{ STRING_MANUFACTURER, manufacturer, },
 	{ STRING_PRODUCT, longname, },
 	{ STRING_SERIAL, serial, },
@@ -364,7 +351,7 @@
 	{  }			/* end of list */
 };
 
-static struct usb_gadget_strings	stringtab = {
+static struct usb_gadget_strings stringtab = {
 	.language	= 0x0409,	/* en-us */
 	.strings	= strings,
 };
@@ -387,8 +374,7 @@
  * high bandwidth modes at high speed.  (Maybe work like Intel's test
  * device?)
  */
-static int
-config_buf (struct usb_gadget *gadget,
+static int config_buf(struct usb_gadget *gadget,
 		u8 *buf, u8 type, unsigned index)
 {
 	int				is_source_sink;
@@ -419,7 +405,7 @@
 	if (!gadget_is_otg(gadget))
 		function++;
 
-	len = usb_gadget_config_buf (is_source_sink
+	len = usb_gadget_config_buf(is_source_sink
 					? &source_sink_config
 					: &loopback_config,
 			buf, USB_BUFSIZ, function);
@@ -431,27 +417,26 @@
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_request *
-alloc_ep_req (struct usb_ep *ep, unsigned length)
+static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
 {
 	struct usb_request	*req;
 
-	req = usb_ep_alloc_request (ep, GFP_ATOMIC);
+	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
 	if (req) {
 		req->length = length;
 		req->buf = kmalloc(length, GFP_ATOMIC);
 		if (!req->buf) {
-			usb_ep_free_request (ep, req);
+			usb_ep_free_request(ep, req);
 			req = NULL;
 		}
 	}
 	return req;
 }
 
-static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
+static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
 {
 	kfree(req->buf);
-	usb_ep_free_request (ep, req);
+	usb_ep_free_request(ep, req);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -472,7 +457,7 @@
 /* optionally require specific source/sink data patterns  */
 
 static int
-check_read_data (
+check_read_data(
 	struct zero_dev		*dev,
 	struct usb_ep		*ep,
 	struct usb_request	*req
@@ -498,8 +483,8 @@
 				continue;
 			break;
 		}
-		ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
-		usb_ep_set_halt (ep);
+		ERROR(dev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
+		usb_ep_set_halt(ep);
 		return -EINVAL;
 	}
 	return 0;
@@ -512,7 +497,7 @@
 
 	switch (pattern) {
 	case 0:
-		memset (req->buf, 0, req->length);
+		memset(req->buf, 0, req->length);
 		break;
 	case 1:
 		for  (i = 0; i < req->length; i++)
@@ -525,7 +510,7 @@
  * irq delay between end of one request and start of the next.
  * that prevents using hardware dma queues.
  */
-static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
+static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct zero_dev	*dev = ep->driver_data;
 	int		status = req->status;
@@ -534,8 +519,8 @@
 
 	case 0:				/* normal completion? */
 		if (ep == dev->out_ep) {
-			check_read_data (dev, ep, req);
-			memset (req->buf, 0x55, req->length);
+			check_read_data(dev, ep, req);
+			memset(req->buf, 0x55, req->length);
 		} else
 			reinit_write_data(ep, req);
 		break;
@@ -544,11 +529,11 @@
 	case -ECONNABORTED:		/* hardware forced ep reset */
 	case -ECONNRESET:		/* request dequeued */
 	case -ESHUTDOWN:		/* disconnect from host */
-		VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
+		VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
 				req->actual, req->length);
 		if (ep == dev->out_ep)
-			check_read_data (dev, ep, req);
-		free_ep_req (ep, req);
+			check_read_data(dev, ep, req);
+		free_ep_req(ep, req);
 		return;
 
 	case -EOVERFLOW:		/* buffer overrun on read means that
@@ -557,18 +542,18 @@
 					 */
 	default:
 #if 1
-		DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
+		DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
 				status, req->actual, req->length);
 #endif
 	case -EREMOTEIO:		/* short read */
 		break;
 	}
 
-	status = usb_ep_queue (ep, req, GFP_ATOMIC);
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
 	if (status) {
-		ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
+		ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n",
 				ep->name, req->length, status);
-		usb_ep_set_halt (ep);
+		usb_ep_set_halt(ep);
 		/* FIXME recover later ... somehow */
 	}
 }
@@ -578,24 +563,24 @@
 	struct usb_request	*req;
 	int			status;
 
-	req = alloc_ep_req (ep, buflen);
+	req = alloc_ep_req(ep, buflen);
 	if (!req)
 		return NULL;
 
-	memset (req->buf, 0, req->length);
+	memset(req->buf, 0, req->length);
 	req->complete = source_sink_complete;
 
-	if (strcmp (ep->name, EP_IN_NAME) == 0)
+	if (strcmp(ep->name, EP_IN_NAME) == 0)
 		reinit_write_data(ep, req);
 	else
-		memset (req->buf, 0x55, req->length);
+		memset(req->buf, 0x55, req->length);
 
 	status = usb_ep_queue(ep, req, GFP_ATOMIC);
 	if (status) {
 		struct zero_dev	*dev = ep->driver_data;
 
-		ERROR (dev, "start %s --> %d\n", ep->name, status);
-		free_ep_req (ep, req);
+		ERROR(dev, "start %s --> %d\n", ep->name, status);
+		free_ep_req(ep, req);
 		req = NULL;
 	}
 
@@ -608,34 +593,34 @@
 	struct usb_ep		*ep;
 	struct usb_gadget	*gadget = dev->gadget;
 
-	gadget_for_each_ep (ep, gadget) {
+	gadget_for_each_ep(ep, gadget) {
 		const struct usb_endpoint_descriptor	*d;
 
 		/* one endpoint writes (sources) zeroes in (to the host) */
-		if (strcmp (ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable (ep, d);
+		if (strcmp(ep->name, EP_IN_NAME) == 0) {
+			d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
+			result = usb_ep_enable(ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
 				if (source_sink_start_ep(ep) != NULL) {
 					dev->in_ep = ep;
 					continue;
 				}
-				usb_ep_disable (ep);
+				usb_ep_disable(ep);
 				result = -EIO;
 			}
 
 		/* one endpoint reads (sinks) anything out (from the host) */
-		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable (ep, d);
+		} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
+			d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
+			result = usb_ep_enable(ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
 				if (source_sink_start_ep(ep) != NULL) {
 					dev->out_ep = ep;
 					continue;
 				}
-				usb_ep_disable (ep);
+				usb_ep_disable(ep);
 				result = -EIO;
 			}
 
@@ -644,11 +629,11 @@
 			continue;
 
 		/* stop on error */
-		ERROR (dev, "can't start %s, result %d\n", ep->name, result);
+		ERROR(dev, "can't start %s, result %d\n", ep->name, result);
 		break;
 	}
 	if (result == 0)
-		DBG (dev, "buflen %d\n", buflen);
+		DBG(dev, "buflen %d\n", buflen);
 
 	/* caller is responsible for cleanup on error */
 	return result;
@@ -656,7 +641,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
+static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct zero_dev	*dev = ep->driver_data;
 	int		status = req->status;
@@ -668,19 +653,19 @@
 			/* loop this OUT packet back IN to the host */
 			req->zero = (req->actual < req->length);
 			req->length = req->actual;
-			status = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
+			status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
 			if (status == 0)
 				return;
 
 			/* "should never get here" */
-			ERROR (dev, "can't loop %s to %s: %d\n",
+			ERROR(dev, "can't loop %s to %s: %d\n",
 				ep->name, dev->in_ep->name,
 				status);
 		}
 
 		/* queue the buffer for some later OUT packet */
 		req->length = buflen;
-		status = usb_ep_queue (dev->out_ep, req, GFP_ATOMIC);
+		status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
 		if (status == 0)
 			return;
 
@@ -688,7 +673,7 @@
 		/* FALLTHROUGH */
 
 	default:
-		ERROR (dev, "%s loop complete --> %d, %d/%d\n", ep->name,
+		ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name,
 				status, req->actual, req->length);
 		/* FALLTHROUGH */
 
@@ -700,7 +685,7 @@
 	case -ECONNABORTED:		/* hardware forced ep reset */
 	case -ECONNRESET:		/* request dequeued */
 	case -ESHUTDOWN:		/* disconnect from host */
-		free_ep_req (ep, req);
+		free_ep_req(ep, req);
 		return;
 	}
 }
@@ -711,13 +696,13 @@
 	struct usb_ep		*ep;
 	struct usb_gadget	*gadget = dev->gadget;
 
-	gadget_for_each_ep (ep, gadget) {
+	gadget_for_each_ep(ep, gadget) {
 		const struct usb_endpoint_descriptor	*d;
 
 		/* one endpoint writes data back IN to the host */
-		if (strcmp (ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable (ep, d);
+		if (strcmp(ep->name, EP_IN_NAME) == 0) {
+			d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
+			result = usb_ep_enable(ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
 				dev->in_ep = ep;
@@ -725,9 +710,9 @@
 			}
 
 		/* one endpoint just reads OUT packets */
-		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable (ep, d);
+		} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
+			d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
+			result = usb_ep_enable(ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
 				dev->out_ep = ep;
@@ -739,7 +724,7 @@
 			continue;
 
 		/* stop on error */
-		ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
+		ERROR(dev, "can't enable %s, result %d\n", ep->name, result);
 		break;
 	}
 
@@ -753,19 +738,19 @@
 
 		ep = dev->out_ep;
 		for (i = 0; i < qlen && result == 0; i++) {
-			req = alloc_ep_req (ep, buflen);
+			req = alloc_ep_req(ep, buflen);
 			if (req) {
 				req->complete = loopback_complete;
-				result = usb_ep_queue (ep, req, GFP_ATOMIC);
+				result = usb_ep_queue(ep, req, GFP_ATOMIC);
 				if (result)
-					DBG (dev, "%s queue req --> %d\n",
+					DBG(dev, "%s queue req --> %d\n",
 							ep->name, result);
 			} else
 				result = -ENOMEM;
 		}
 	}
 	if (result == 0)
-		DBG (dev, "qlen %d, buflen %d\n", qlen, buflen);
+		DBG(dev, "qlen %d, buflen %d\n", qlen, buflen);
 
 	/* caller is responsible for cleanup on error */
 	return result;
@@ -773,26 +758,26 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void zero_reset_config (struct zero_dev *dev)
+static void zero_reset_config(struct zero_dev *dev)
 {
 	if (dev->config == 0)
 		return;
 
-	DBG (dev, "reset config\n");
+	DBG(dev, "reset config\n");
 
 	/* just disable endpoints, forcing completion of pending i/o.
 	 * all our completion handlers free their requests in this case.
 	 */
 	if (dev->in_ep) {
-		usb_ep_disable (dev->in_ep);
+		usb_ep_disable(dev->in_ep);
 		dev->in_ep = NULL;
 	}
 	if (dev->out_ep) {
-		usb_ep_disable (dev->out_ep);
+		usb_ep_disable(dev->out_ep);
 		dev->out_ep = NULL;
 	}
 	dev->config = 0;
-	del_timer (&dev->resume);
+	del_timer(&dev->resume);
 }
 
 /* change our operational config.  this code must agree with the code
@@ -813,12 +798,12 @@
 	if (number == dev->config)
 		return 0;
 
-	if (gadget_is_sa1100 (gadget) && dev->config) {
+	if (gadget_is_sa1100(gadget) && dev->config) {
 		/* tx fifo is full, but we can't clear it...*/
 		ERROR(dev, "can't change configurations\n");
 		return -ESPIPE;
 	}
-	zero_reset_config (dev);
+	zero_reset_config(dev);
 
 	switch (number) {
 	case CONFIG_SOURCE_SINK:
@@ -837,7 +822,7 @@
 	if (!result && (!dev->in_ep || !dev->out_ep))
 		result = -ENODEV;
 	if (result)
-		zero_reset_config (dev);
+		zero_reset_config(dev);
 	else {
 		char *speed;
 
@@ -849,7 +834,7 @@
 		}
 
 		dev->config = number;
-		INFO (dev, "%s speed config #%d: %s\n", speed, number,
+		INFO(dev, "%s speed config #%d: %s\n", speed, number,
 				(number == CONFIG_SOURCE_SINK)
 					? source_sink : loopback);
 	}
@@ -858,10 +843,10 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
+static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	if (req->status || req->actual != req->length)
-		DBG ((struct zero_dev *) ep->driver_data,
+		DBG((struct zero_dev *) ep->driver_data,
 				"setup complete --> %d, %d/%d\n",
 				req->status, req->actual, req->length);
 }
@@ -874,9 +859,9 @@
  * the work is in config-specific setup.
  */
 static int
-zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 {
-	struct zero_dev		*dev = get_gadget_data (gadget);
+	struct zero_dev		*dev = get_gadget_data(gadget);
 	struct usb_request	*req = dev->req;
 	int			value = -EOPNOTSUPP;
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
@@ -895,14 +880,14 @@
 		switch (w_value >> 8) {
 
 		case USB_DT_DEVICE:
-			value = min (w_length, (u16) sizeof device_desc);
-			memcpy (req->buf, &device_desc, value);
+			value = min(w_length, (u16) sizeof device_desc);
+			memcpy(req->buf, &device_desc, value);
 			break;
 		case USB_DT_DEVICE_QUALIFIER:
 			if (!gadget_is_dualspeed(gadget))
 				break;
-			value = min (w_length, (u16) sizeof dev_qualifier);
-			memcpy (req->buf, &dev_qualifier, value);
+			value = min(w_length, (u16) sizeof dev_qualifier);
+			memcpy(req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
@@ -910,11 +895,11 @@
 				break;
 			// FALLTHROUGH
 		case USB_DT_CONFIG:
-			value = config_buf (gadget, req->buf,
+			value = config_buf(gadget, req->buf,
 					w_value >> 8,
 					w_value & 0xff);
 			if (value >= 0)
-				value = min (w_length, (u16) value);
+				value = min(w_length, (u16) value);
 			break;
 
 		case USB_DT_STRING:
@@ -923,10 +908,10 @@
 			 * add string tables for other languages, using
 			 * any UTF-8 characters
 			 */
-			value = usb_gadget_get_string (&stringtab,
+			value = usb_gadget_get_string(&stringtab,
 					w_value & 0xff, req->buf);
 			if (value >= 0)
-				value = min (w_length, (u16) value);
+				value = min(w_length, (u16) value);
 			break;
 		}
 		break;
@@ -936,20 +921,20 @@
 		if (ctrl->bRequestType != 0)
 			goto unknown;
 		if (gadget->a_hnp_support)
-			DBG (dev, "HNP available\n");
+			DBG(dev, "HNP available\n");
 		else if (gadget->a_alt_hnp_support)
-			DBG (dev, "HNP needs a different root port\n");
+			DBG(dev, "HNP needs a different root port\n");
 		else
-			VDBG (dev, "HNP inactive\n");
-		spin_lock (&dev->lock);
+			VDBG(dev, "HNP inactive\n");
+		spin_lock(&dev->lock);
 		value = zero_set_config(dev, w_value);
-		spin_unlock (&dev->lock);
+		spin_unlock(&dev->lock);
 		break;
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			goto unknown;
 		*(u8 *)req->buf = dev->config;
-		value = min (w_length, (u16) 1);
+		value = min(w_length, (u16) 1);
 		break;
 
 	/* until we add altsetting support, or other interfaces,
@@ -959,7 +944,7 @@
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
 			goto unknown;
-		spin_lock (&dev->lock);
+		spin_lock(&dev->lock);
 		if (dev->config && w_index == 0 && w_value == 0) {
 			u8		config = dev->config;
 
@@ -970,11 +955,11 @@
 			 * if we had more than one interface we couldn't
 			 * use this "reset the config" shortcut.
 			 */
-			zero_reset_config (dev);
+			zero_reset_config(dev);
 			zero_set_config(dev, config);
 			value = 0;
 		}
-		spin_unlock (&dev->lock);
+		spin_unlock(&dev->lock);
 		break;
 	case USB_REQ_GET_INTERFACE:
 		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
@@ -986,7 +971,7 @@
 			break;
 		}
 		*(u8 *)req->buf = 0;
-		value = min (w_length, (u16) 1);
+		value = min(w_length, (u16) 1);
 		break;
 
 	/*
@@ -1018,7 +1003,7 @@
 
 	default:
 unknown:
-		VDBG (dev,
+		VDBG(dev,
 			"unknown control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			w_value, w_index, w_length);
@@ -1028,11 +1013,11 @@
 	if (value >= 0) {
 		req->length = value;
 		req->zero = value < w_length;
-		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
+		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0) {
-			DBG (dev, "ep_queue --> %d\n", value);
+			DBG(dev, "ep_queue --> %d\n", value);
 			req->status = 0;
-			zero_setup_complete (gadget->ep0, req);
+			zero_setup_complete(gadget->ep0, req);
 		}
 	}
 
@@ -1040,28 +1025,26 @@
 	return value;
 }
 
-static void
-zero_disconnect (struct usb_gadget *gadget)
+static void zero_disconnect(struct usb_gadget *gadget)
 {
-	struct zero_dev		*dev = get_gadget_data (gadget);
+	struct zero_dev		*dev = get_gadget_data(gadget);
 	unsigned long		flags;
 
-	spin_lock_irqsave (&dev->lock, flags);
-	zero_reset_config (dev);
+	spin_lock_irqsave(&dev->lock, flags);
+	zero_reset_config(dev);
 
 	/* a more significant application might have some non-usb
 	 * activities to quiesce here, saving resources like power
 	 * or pushing the notification up a network stack.
 	 */
-	spin_unlock_irqrestore (&dev->lock, flags);
+	spin_unlock_irqrestore(&dev->lock, flags);
 
 	/* next we may get setup() calls to enumerate new connections;
 	 * or an unbind() during shutdown (including removing module).
 	 */
 }
 
-static void
-zero_autoresume (unsigned long _dev)
+static void zero_autoresume(unsigned long _dev)
 {
 	struct zero_dev	*dev = (struct zero_dev *) _dev;
 	int		status;
@@ -1070,32 +1053,30 @@
 	 * more significant than just a timer firing...
 	 */
 	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
-		status = usb_gadget_wakeup (dev->gadget);
-		DBG (dev, "wakeup --> %d\n", status);
+		status = usb_gadget_wakeup(dev->gadget);
+		DBG(dev, "wakeup --> %d\n", status);
 	}
 }
 
 /*-------------------------------------------------------------------------*/
 
-static void /* __init_or_exit */
-zero_unbind (struct usb_gadget *gadget)
+static void zero_unbind(struct usb_gadget *gadget)
 {
-	struct zero_dev		*dev = get_gadget_data (gadget);
+	struct zero_dev		*dev = get_gadget_data(gadget);
 
-	DBG (dev, "unbind\n");
+	DBG(dev, "unbind\n");
 
 	/* we've already been disconnected ... no i/o is active */
 	if (dev->req) {
 		dev->req->length = USB_BUFSIZ;
-		free_ep_req (gadget->ep0, dev->req);
+		free_ep_req(gadget->ep0, dev->req);
 	}
-	del_timer_sync (&dev->resume);
-	kfree (dev);
-	set_gadget_data (gadget, NULL);
+	del_timer_sync(&dev->resume);
+	kfree(dev);
+	set_gadget_data(gadget, NULL);
 }
 
-static int __init
-zero_bind (struct usb_gadget *gadget)
+static int __init zero_bind(struct usb_gadget *gadget)
 {
 	struct zero_dev		*dev;
 	struct usb_ep		*ep;
@@ -1111,8 +1092,8 @@
 	 * autoconfigure on any sane usb controller driver,
 	 * but there may also be important quirks to address.
 	 */
-	usb_ep_autoconfig_reset (gadget);
-	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+	usb_ep_autoconfig_reset(gadget);
+	ep = usb_ep_autoconfig(gadget, &fs_source_desc);
 	if (!ep) {
 autoconf_fail:
 		pr_err("%s: can't autoconfigure on %s\n",
@@ -1122,15 +1103,15 @@
 	EP_IN_NAME = ep->name;
 	ep->driver_data = ep;	/* claim */
 
-	ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+	ep = usb_ep_autoconfig(gadget, &fs_sink_desc);
 	if (!ep)
 		goto autoconf_fail;
 	EP_OUT_NAME = ep->name;
 	ep->driver_data = ep;	/* claim */
 
-	gcnum = usb_gadget_controller_number (gadget);
+	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
-		device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
 	else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
@@ -1141,7 +1122,7 @@
 		 */
 		pr_warning("%s: controller '%s' not recognized\n",
 			shortname, gadget->name);
-		device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
 
 
@@ -1149,12 +1130,16 @@
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return -ENOMEM;
-	spin_lock_init (&dev->lock);
+	spin_lock_init(&dev->lock);
 	dev->gadget = gadget;
-	set_gadget_data (gadget, dev);
+	set_gadget_data(gadget, dev);
+
+	init_timer(&dev->resume);
+	dev->resume.function = zero_autoresume;
+	dev->resume.data = (unsigned long) dev;
 
 	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
+	dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
 	if (!dev->req)
 		goto enomem;
 	dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
@@ -1182,11 +1167,8 @@
 		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	usb_gadget_set_selfpowered (gadget);
+	usb_gadget_set_selfpowered(gadget);
 
-	init_timer (&dev->resume);
-	dev->resume.function = zero_autoresume;
-	dev->resume.data = (unsigned long) dev;
 	if (autoresume) {
 		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
@@ -1194,45 +1176,43 @@
 
 	gadget->ep0->driver_data = dev;
 
-	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
-	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
+	INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
+	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
 		EP_OUT_NAME, EP_IN_NAME);
 
-	snprintf (manufacturer, sizeof manufacturer, "%s %s with %s",
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
 
 	return 0;
 
 enomem:
-	zero_unbind (gadget);
+	zero_unbind(gadget);
 	return -ENOMEM;
 }
 
 /*-------------------------------------------------------------------------*/
 
-static void
-zero_suspend (struct usb_gadget *gadget)
+static void zero_suspend(struct usb_gadget *gadget)
 {
-	struct zero_dev		*dev = get_gadget_data (gadget);
+	struct zero_dev		*dev = get_gadget_data(gadget);
 
 	if (gadget->speed == USB_SPEED_UNKNOWN)
 		return;
 
 	if (autoresume) {
-		mod_timer (&dev->resume, jiffies + (HZ * autoresume));
-		DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
+		mod_timer(&dev->resume, jiffies + (HZ * autoresume));
+		DBG(dev, "suspend, wakeup in %d seconds\n", autoresume);
 	} else
-		DBG (dev, "suspend\n");
+		DBG(dev, "suspend\n");
 }
 
-static void
-zero_resume (struct usb_gadget *gadget)
+static void zero_resume(struct usb_gadget *gadget)
 {
-	struct zero_dev		*dev = get_gadget_data (gadget);
+	struct zero_dev		*dev = get_gadget_data(gadget);
 
-	DBG (dev, "resume\n");
-	del_timer (&dev->resume);
+	DBG(dev, "resume\n");
+	del_timer(&dev->resume);
 }
 
 
@@ -1264,15 +1244,15 @@
 MODULE_LICENSE("GPL");
 
 
-static int __init init (void)
+static int __init init(void)
 {
-	return usb_gadget_register_driver (&zero_driver);
+	return usb_gadget_register_driver(&zero_driver);
 }
-module_init (init);
+module_init(init);
 
-static void __exit cleanup (void)
+static void __exit cleanup(void)
 {
-	usb_gadget_unregister_driver (&zero_driver);
+	usb_gadget_unregister_driver(&zero_driver);
 }
-module_exit (cleanup);
+module_exit(cleanup);
 
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0b87480..33b467a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -4,6 +4,19 @@
 comment "USB Host Controller Drivers"
 	depends on USB
 
+config USB_C67X00_HCD
+	tristate "Cypress C67x00 HCD support"
+	depends on USB
+	help
+	  The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role
+	  host/peripheral/OTG USB controllers.
+
+	  Enable this option to support this chip in host controller mode.
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called c67x00.
+
 config USB_EHCI_HCD
 	tristate "EHCI HCD (USB 2.0) support"
 	depends on USB && USB_ARCH_HAS_EHCI
@@ -95,6 +108,32 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called isp116x-hcd.
 
+config USB_ISP1760_HCD
+	tristate "ISP 1760 HCD support"
+	depends on USB && EXPERIMENTAL
+	---help---
+	  The ISP1760 chip is a USB 2.0 host controller.
+
+	  This driver does not support isochronous transfers or OTG.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called isp1760-hcd.
+
+config USB_ISP1760_PCI
+	bool "Support for the PCI bus"
+	depends on USB_ISP1760_HCD && PCI
+	---help---
+	  Enables support for the device present on the PCI bus.
+	  This should only be required if you happen to have the eval kit from
+	  NXP and you are going to test it.
+
+config USB_ISP1760_OF
+	bool "Support for the OF platform bus"
+	depends on USB_ISP1760_HCD && OF
+	---help---
+	  Enables support for the device present on the PowerPC
+	  OpenFirmware platform bus.
+
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	depends on USB && USB_ARCH_HAS_OHCI
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index bb8e9d4..f1edda2 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -6,6 +6,8 @@
 	EXTRA_CFLAGS		+= -DDEBUG
 endif
 
+isp1760-objs := isp1760-hcd.o isp1760-if.o
+
 obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
@@ -16,4 +18,4 @@
 obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o
 obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o
 obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o
-
+obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
new file mode 100644
index 0000000..4ba96c1
--- /dev/null
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -0,0 +1,2231 @@
+/*
+ * Driver for the NXP ISP1760 chip
+ *
+ * However, the code might contain some bugs. What doesn't work for sure is:
+ * - ISO
+ * - OTG
+ e The interrupt line is configured as active low, level.
+ *
+ * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/unaligned.h>
+
+#include "../core/hcd.h"
+#include "isp1760-hcd.h"
+
+static struct kmem_cache *qtd_cachep;
+static struct kmem_cache *qh_cachep;
+
+struct isp1760_hcd {
+	u32 hcs_params;
+	spinlock_t		lock;
+	struct inter_packet_info atl_ints[32];
+	struct inter_packet_info int_ints[32];
+	struct memory_chunk memory_pool[BLOCKS];
+
+	/* periodic schedule support */
+#define	DEFAULT_I_TDPS		1024
+	unsigned		periodic_size;
+	unsigned		i_thresh;
+	unsigned long		reset_done;
+	unsigned long		next_statechange;
+};
+
+static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
+{
+	return (struct isp1760_hcd *) (hcd->hcd_priv);
+}
+static inline struct usb_hcd *priv_to_hcd(struct isp1760_hcd *priv)
+{
+	return container_of((void *) priv, struct usb_hcd, hcd_priv);
+}
+
+/* Section 2.2 Host Controller Capability Registers */
+#define HC_LENGTH(p)		(((p)>>00)&0x00ff)	/* bits 7:0 */
+#define HC_VERSION(p)		(((p)>>16)&0xffff)	/* bits 31:16 */
+#define HCS_INDICATOR(p)	((p)&(1 << 16))	/* true: has port indicators */
+#define HCS_PPC(p)		((p)&(1 << 4))	/* true: port power control */
+#define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
+#define HCC_ISOC_CACHE(p)       ((p)&(1 << 7))  /* true: can cache isoc frame */
+#define HCC_ISOC_THRES(p)       (((p)>>4)&0x7)  /* bits 6:4, uframes cached */
+
+/* Section 2.3 Host Controller Operational Registers */
+#define CMD_LRESET	(1<<7)		/* partial reset (no ports, etc) */
+#define CMD_RESET	(1<<1)		/* reset HC not bus */
+#define CMD_RUN		(1<<0)		/* start/stop HC */
+#define STS_PCD		(1<<2)		/* port change detect */
+#define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
+
+#define PORT_OWNER	(1<<13)		/* true: companion hc owns this port */
+#define PORT_POWER	(1<<12)		/* true: has power (see PPC) */
+#define PORT_USB11(x) (((x) & (3 << 10)) == (1 << 10))	/* USB 1.1 device */
+#define PORT_RESET	(1<<8)		/* reset port */
+#define PORT_SUSPEND	(1<<7)		/* suspend port */
+#define PORT_RESUME	(1<<6)		/* resume it */
+#define PORT_PE		(1<<2)		/* port enable */
+#define PORT_CSC	(1<<1)		/* connect status change */
+#define PORT_CONNECT	(1<<0)		/* device connected */
+#define PORT_RWC_BITS   (PORT_CSC)
+
+struct isp1760_qtd {
+	struct isp1760_qtd *hw_next;
+	u8 packet_type;
+	u8 toggle;
+
+	void *data_buffer;
+	/* the rest is HCD-private */
+	struct list_head qtd_list;
+	struct urb *urb;
+	size_t length;
+
+	/* isp special*/
+	u32 status;
+#define URB_COMPLETE_NOTIFY	(1 << 0)
+#define URB_ENQUEUED		(1 << 1)
+#define URB_TYPE_ATL		(1 << 2)
+#define URB_TYPE_INT		(1 << 3)
+};
+
+struct isp1760_qh {
+	/* first part defined by EHCI spec */
+	struct list_head qtd_list;
+	struct isp1760_hcd *priv;
+
+	/* periodic schedule info */
+	unsigned short period;		/* polling interval */
+	struct usb_device *dev;
+
+	u32 toggle;
+	u32 ping;
+};
+
+#define ehci_port_speed(priv, portsc) (1 << USB_PORT_FEAT_HIGHSPEED)
+
+static unsigned int isp1760_readl(__u32 __iomem *regs)
+{
+	return readl(regs);
+}
+
+static void isp1760_writel(const unsigned int val, __u32 __iomem *regs)
+{
+	writel(val, regs);
+}
+
+/*
+ * The next two copy via MMIO data to/from the device. memcpy_{to|from}io()
+ * doesn't quite work because some people have to enforce 32-bit access
+ */
+static void priv_read_copy(struct isp1760_hcd *priv, u32 *src,
+		__u32 __iomem *dst, u32 offset, u32 len)
+{
+	struct usb_hcd *hcd = priv_to_hcd(priv);
+	u32 val;
+	u8 *buff8;
+
+	if (!src) {
+		printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len);
+		return;
+	}
+	isp1760_writel(offset,  hcd->regs + HC_MEMORY_REG);
+	/* XXX
+	 * 90nsec delay, the spec says something how this could be avoided.
+	 */
+	mdelay(1);
+
+	while (len >= 4) {
+		*src = __raw_readl(dst);
+		len -= 4;
+		src++;
+		dst++;
+	}
+
+	if (!len)
+		return;
+
+	/* in case we have 3, 2 or 1 by left. The dst buffer may not be fully
+	 * allocated.
+	 */
+	val = isp1760_readl(dst);
+
+	buff8 = (u8 *)src;
+	while (len) {
+
+		*buff8 = val;
+		val >>= 8;
+		len--;
+		buff8++;
+	}
+}
+
+static void priv_write_copy(const struct isp1760_hcd *priv, const u32 *src,
+		__u32 __iomem *dst, u32 len)
+{
+	while (len >= 4) {
+		__raw_writel(*src, dst);
+		len -= 4;
+		src++;
+		dst++;
+	}
+
+	if (!len)
+		return;
+	/* in case we have 3, 2 or 1 by left. The buffer is allocated and the
+	 * extra bytes should not be read by the HW
+	 */
+
+	__raw_writel(*src, dst);
+}
+
+/* memory management of the 60kb on the chip from 0x1000 to 0xffff */
+static void init_memory(struct isp1760_hcd *priv)
+{
+	int i;
+	u32 payload;
+
+	payload = 0x1000;
+	for (i = 0; i < BLOCK_1_NUM; i++) {
+		priv->memory_pool[i].start = payload;
+		priv->memory_pool[i].size = BLOCK_1_SIZE;
+		priv->memory_pool[i].free = 1;
+		payload += priv->memory_pool[i].size;
+	}
+
+
+	for (i = BLOCK_1_NUM; i < BLOCK_1_NUM + BLOCK_2_NUM; i++) {
+		priv->memory_pool[i].start = payload;
+		priv->memory_pool[i].size = BLOCK_2_SIZE;
+		priv->memory_pool[i].free = 1;
+		payload += priv->memory_pool[i].size;
+	}
+
+
+	for (i = BLOCK_1_NUM + BLOCK_2_NUM; i < BLOCKS; i++) {
+		priv->memory_pool[i].start = payload;
+		priv->memory_pool[i].size = BLOCK_3_SIZE;
+		priv->memory_pool[i].free = 1;
+		payload += priv->memory_pool[i].size;
+	}
+
+	BUG_ON(payload - priv->memory_pool[i - 1].size > PAYLOAD_SIZE);
+}
+
+static u32 alloc_mem(struct isp1760_hcd *priv, u32 size)
+{
+	int i;
+
+	if (!size)
+		return ISP1760_NULL_POINTER;
+
+	for (i = 0; i < BLOCKS; i++) {
+		if (priv->memory_pool[i].size >= size &&
+				priv->memory_pool[i].free) {
+
+			priv->memory_pool[i].free = 0;
+			return priv->memory_pool[i].start;
+		}
+	}
+
+	printk(KERN_ERR "ISP1760 MEM: can not allocate %d bytes of memory\n",
+			size);
+	printk(KERN_ERR "Current memory map:\n");
+	for (i = 0; i < BLOCKS; i++) {
+		printk(KERN_ERR "Pool %2d size %4d status: %d\n",
+				i, priv->memory_pool[i].size,
+				priv->memory_pool[i].free);
+	}
+	/* XXX maybe -ENOMEM could be possible */
+	BUG();
+	return 0;
+}
+
+static void free_mem(struct isp1760_hcd *priv, u32 mem)
+{
+	int i;
+
+	if (mem == ISP1760_NULL_POINTER)
+		return;
+
+	for (i = 0; i < BLOCKS; i++) {
+		if (priv->memory_pool[i].start == mem) {
+
+			BUG_ON(priv->memory_pool[i].free);
+
+			priv->memory_pool[i].free = 1;
+			return ;
+		}
+	}
+
+	printk(KERN_ERR "Trying to free not-here-allocated memory :%08x\n",
+			mem);
+	BUG();
+}
+
+static void isp1760_init_regs(struct usb_hcd *hcd)
+{
+	isp1760_writel(0, hcd->regs + HC_BUFFER_STATUS_REG);
+	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
+			HC_ATL_PTD_SKIPMAP_REG);
+	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
+			HC_INT_PTD_SKIPMAP_REG);
+	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
+			HC_ISO_PTD_SKIPMAP_REG);
+
+	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
+			HC_ATL_PTD_DONEMAP_REG);
+	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
+			HC_INT_PTD_DONEMAP_REG);
+	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
+			HC_ISO_PTD_DONEMAP_REG);
+}
+
+static int handshake(struct isp1760_hcd *priv, void __iomem *ptr,
+		      u32 mask, u32 done, int usec)
+{
+	u32 result;
+
+	do {
+		result = isp1760_readl(ptr);
+		if (result == ~0)
+			return -ENODEV;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -ETIMEDOUT;
+}
+
+/* reset a non-running (STS_HALT == 1) controller */
+static int ehci_reset(struct isp1760_hcd *priv)
+{
+	int retval;
+	struct usb_hcd *hcd = priv_to_hcd(priv);
+	u32 command = isp1760_readl(hcd->regs + HC_USBCMD);
+
+	command |= CMD_RESET;
+	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	hcd->state = HC_STATE_HALT;
+	priv->next_statechange = jiffies;
+	retval = handshake(priv, hcd->regs + HC_USBCMD,
+			    CMD_RESET, 0, 250 * 1000);
+	return retval;
+}
+
+static void qh_destroy(struct isp1760_qh *qh)
+{
+	BUG_ON(!list_empty(&qh->qtd_list));
+	kmem_cache_free(qh_cachep, qh);
+}
+
+static struct isp1760_qh *isp1760_qh_alloc(struct isp1760_hcd *priv,
+		gfp_t flags)
+{
+	struct isp1760_qh *qh;
+
+	qh = kmem_cache_zalloc(qh_cachep, flags);
+	if (!qh)
+		return qh;
+
+	INIT_LIST_HEAD(&qh->qtd_list);
+	qh->priv = priv;
+	return qh;
+}
+
+/* magic numbers that can affect system performance */
+#define	EHCI_TUNE_CERR		3	/* 0-3 qtd retries; 0 == don't stop */
+#define	EHCI_TUNE_RL_HS		4	/* nak throttle; see 4.9 */
+#define	EHCI_TUNE_RL_TT		0
+#define	EHCI_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
+#define	EHCI_TUNE_MULT_TT	1
+#define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
+
+/* one-time init, only for memory state */
+static int priv_init(struct usb_hcd *hcd)
+{
+	struct isp1760_hcd		*priv = hcd_to_priv(hcd);
+	u32			hcc_params;
+
+	spin_lock_init(&priv->lock);
+
+	/*
+	 * hw default: 1K periodic list heads, one per frame.
+	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+	 */
+	priv->periodic_size = DEFAULT_I_TDPS;
+
+	/* controllers may cache some of the periodic schedule ... */
+	hcc_params = isp1760_readl(hcd->regs + HC_HCCPARAMS);
+	/* full frame cache */
+	if (HCC_ISOC_CACHE(hcc_params))
+		priv->i_thresh = 8;
+	else /* N microframes cached */
+		priv->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
+
+	return 0;
+}
+
+static int isp1760_hc_setup(struct usb_hcd *hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	int result;
+	u32 scratch;
+
+	isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
+	scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
+	if (scratch != 0xdeadbabe) {
+		printk(KERN_ERR "ISP1760: Scratch test failed.\n");
+		return -ENODEV;
+	}
+
+	/* pre reset */
+	isp1760_init_regs(hcd);
+
+	/* reset */
+	isp1760_writel(SW_RESET_RESET_ALL, hcd->regs + HC_RESET_REG);
+	mdelay(100);
+
+	isp1760_writel(SW_RESET_RESET_HC, hcd->regs + HC_RESET_REG);
+	mdelay(100);
+
+	result = ehci_reset(priv);
+	if (result)
+		return result;
+
+	/* Step 11 passed */
+
+	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
+	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+
+	/* ATL reset */
+	scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+	isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
+	mdelay(10);
+	isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL);
+
+	isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL);
+	mdelay(10);
+
+	priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
+
+	return priv_init(hcd);
+}
+
+static void isp1760_init_maps(struct usb_hcd *hcd)
+{
+	/*set last maps, for iso its only 1, else 32 tds bitmap*/
+	isp1760_writel(0x80000000, hcd->regs + HC_ATL_PTD_LASTPTD_REG);
+	isp1760_writel(0x80000000, hcd->regs + HC_INT_PTD_LASTPTD_REG);
+	isp1760_writel(0x00000001, hcd->regs + HC_ISO_PTD_LASTPTD_REG);
+}
+
+static void isp1760_enable_interrupts(struct usb_hcd *hcd)
+{
+	isp1760_writel(0, hcd->regs + HC_ATL_IRQ_MASK_AND_REG);
+	isp1760_writel(0, hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	isp1760_writel(0, hcd->regs + HC_INT_IRQ_MASK_AND_REG);
+	isp1760_writel(0, hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	isp1760_writel(0, hcd->regs + HC_ISO_IRQ_MASK_AND_REG);
+	isp1760_writel(0xffffffff, hcd->regs + HC_ISO_IRQ_MASK_OR_REG);
+	/* step 23 passed */
+}
+
+static int isp1760_run(struct usb_hcd *hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	int retval;
+	u32 temp;
+	u32 command;
+	u32 chipid;
+
+	hcd->uses_new_polling = 1;
+	hcd->poll_rh = 0;
+
+	hcd->state = HC_STATE_RUNNING;
+	isp1760_enable_interrupts(hcd);
+	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+	temp |= FINAL_HW_CONFIG;
+	isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL);
+
+	command = isp1760_readl(hcd->regs + HC_USBCMD);
+	command &= ~(CMD_LRESET|CMD_RESET);
+	command |= CMD_RUN;
+	isp1760_writel(command, hcd->regs + HC_USBCMD);
+
+	retval = handshake(priv, hcd->regs + HC_USBCMD,	CMD_RUN, CMD_RUN,
+			250 * 1000);
+	if (retval)
+		return retval;
+
+	/*
+	 * XXX
+	 * Spec says to write FLAG_CF as last config action, priv code grabs
+	 * the semaphore while doing so.
+	 */
+	down_write(&ehci_cf_port_reset_rwsem);
+	isp1760_writel(FLAG_CF, hcd->regs + HC_CONFIGFLAG);
+
+	retval = handshake(priv, hcd->regs + HC_CONFIGFLAG, FLAG_CF, FLAG_CF,
+			250 * 1000);
+	up_write(&ehci_cf_port_reset_rwsem);
+	if (retval)
+		return retval;
+
+	chipid = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
+	isp1760_info(priv, "USB ISP %04x HW rev. %d started\n",	chipid & 0xffff,
+			chipid >> 16);
+
+	/* PTD Register Init Part 2, Step 28 */
+	/* enable INTs */
+	isp1760_init_maps(hcd);
+
+	/* GRR this is run-once init(), being done every time the HC starts.
+	 * So long as they're part of class devices, we can't do it init()
+	 * since the class device isn't created that early.
+	 */
+	return 0;
+}
+
+static u32 base_to_chip(u32 base)
+{
+	return ((base - 0x400) >> 3);
+}
+
+static void transform_into_atl(struct isp1760_hcd *priv, struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct urb *urb,
+			u32 payload, struct ptd *ptd)
+{
+	u32 dw0;
+	u32 dw1;
+	u32 dw2;
+	u32 dw3;
+	u32 maxpacket;
+	u32 multi;
+	u32 pid_code;
+	u32 rl = RL_COUNTER;
+	u32 nak = NAK_COUNTER;
+
+	/* according to 3.6.2, max packet len can not be > 0x400 */
+	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	multi =  1 + ((maxpacket >> 11) & 0x3);
+	maxpacket &= 0x7ff;
+
+	/* DW0 */
+	dw0 = PTD_VALID;
+	dw0 |= PTD_LENGTH(qtd->length);
+	dw0 |= PTD_MAXPACKET(maxpacket);
+	dw0 |= PTD_ENDPOINT(usb_pipeendpoint(urb->pipe));
+	dw1 = usb_pipeendpoint(urb->pipe) >> 1;
+
+	/* DW1 */
+	dw1 |= PTD_DEVICE_ADDR(usb_pipedevice(urb->pipe));
+
+	pid_code = qtd->packet_type;
+	dw1 |= PTD_PID_TOKEN(pid_code);
+
+	if (usb_pipebulk(urb->pipe))
+		dw1 |= PTD_TRANS_BULK;
+	else if  (usb_pipeint(urb->pipe))
+		dw1 |= PTD_TRANS_INT;
+
+	if (urb->dev->speed != USB_SPEED_HIGH) {
+		/* split transaction */
+
+		dw1 |= PTD_TRANS_SPLIT;
+		if (urb->dev->speed == USB_SPEED_LOW)
+			dw1 |= PTD_SE_USB_LOSPEED;
+
+		dw1 |= PTD_PORT_NUM(urb->dev->ttport);
+		dw1 |= PTD_HUB_NUM(urb->dev->tt->hub->devnum);
+
+		/* SE bit for Split INT transfers */
+		if (usb_pipeint(urb->pipe) &&
+				(urb->dev->speed == USB_SPEED_LOW))
+			dw1 |= 2 << 16;
+
+		dw3 = 0;
+		rl = 0;
+		nak = 0;
+	} else {
+		dw0 |= PTD_MULTI(multi);
+		if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe))
+			dw3 = qh->ping;
+		else
+			dw3 = 0;
+	}
+	/* DW2 */
+	dw2 = 0;
+	dw2 |= PTD_DATA_START_ADDR(base_to_chip(payload));
+	dw2 |= PTD_RL_CNT(rl);
+	dw3 |= PTD_NAC_CNT(nak);
+
+	/* DW3 */
+	if (usb_pipecontrol(urb->pipe))
+		dw3 |= PTD_DATA_TOGGLE(qtd->toggle);
+	else
+		dw3 |= qh->toggle;
+
+
+	dw3 |= PTD_ACTIVE;
+	/* Cerr */
+	dw3 |= PTD_CERR(ERR_COUNTER);
+
+	memset(ptd, 0, sizeof(*ptd));
+
+	ptd->dw0 = cpu_to_le32(dw0);
+	ptd->dw1 = cpu_to_le32(dw1);
+	ptd->dw2 = cpu_to_le32(dw2);
+	ptd->dw3 = cpu_to_le32(dw3);
+}
+
+static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct urb *urb,
+			u32 payload, struct ptd *ptd)
+{
+	u32 maxpacket;
+	u32 multi;
+	u32 numberofusofs;
+	u32 i;
+	u32 usofmask, usof;
+	u32 period;
+
+	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	multi =  1 + ((maxpacket >> 11) & 0x3);
+	maxpacket &= 0x7ff;
+	/* length of the data per uframe */
+	maxpacket = multi * maxpacket;
+
+	numberofusofs = urb->transfer_buffer_length / maxpacket;
+	if (urb->transfer_buffer_length % maxpacket)
+		numberofusofs += 1;
+
+	usofmask = 1;
+	usof = 0;
+	for (i = 0; i < numberofusofs; i++) {
+		usof |= usofmask;
+		usofmask <<= 1;
+	}
+
+	if (urb->dev->speed != USB_SPEED_HIGH) {
+		/* split */
+		ptd->dw5 = __constant_cpu_to_le32(0x1c);
+
+		if (qh->period >= 32)
+			period = qh->period / 2;
+		else
+			period = qh->period;
+
+	} else {
+
+		if (qh->period >= 8)
+			period = qh->period/8;
+		else
+			period = qh->period;
+
+		if (period >= 32)
+			period  = 16;
+
+		if (qh->period >= 8) {
+			/* millisecond period */
+			period = (period << 3);
+		} else {
+			/* usof based tranmsfers */
+			/* minimum 4 usofs */
+			usof = 0x11;
+		}
+	}
+
+	ptd->dw2 |= cpu_to_le32(period);
+	ptd->dw4 = cpu_to_le32(usof);
+}
+
+static void transform_into_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct urb *urb,
+			u32 payload, struct ptd *ptd)
+{
+	transform_into_atl(priv, qh, qtd, urb, payload, ptd);
+	transform_add_int(priv, qh, qtd, urb,  payload, ptd);
+}
+
+static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
+		u32 token)
+{
+	int count;
+
+	qtd->data_buffer = databuffer;
+	qtd->packet_type = GET_QTD_TOKEN_TYPE(token);
+	qtd->toggle = GET_DATA_TOGGLE(token);
+
+	if (len > HC_ATL_PL_SIZE)
+		count = HC_ATL_PL_SIZE;
+	else
+		count = len;
+
+	qtd->length = count;
+	return count;
+}
+
+static int check_error(struct ptd *ptd)
+{
+	int error = 0;
+	u32 dw3;
+
+	dw3 = le32_to_cpu(ptd->dw3);
+	if (dw3 & DW3_HALT_BIT)
+		error = -EPIPE;
+
+	if (dw3 & DW3_ERROR_BIT) {
+		printk(KERN_ERR "error bit is set in DW3\n");
+		error = -EPIPE;
+	}
+
+	if (dw3 & DW3_QTD_ACTIVE) {
+		printk(KERN_ERR "transfer active bit is set DW3\n");
+		printk(KERN_ERR "nak counter: %d, rl: %d\n", (dw3 >> 19) & 0xf,
+				(le32_to_cpu(ptd->dw2) >> 25) & 0xf);
+	}
+
+	return error;
+}
+
+static void check_int_err_status(u32 dw4)
+{
+	u32 i;
+
+	dw4 >>= 8;
+
+	for (i = 0; i < 8; i++) {
+		switch (dw4 & 0x7) {
+		case INT_UNDERRUN:
+			printk(KERN_ERR "ERROR: under run , %d\n", i);
+			break;
+
+		case INT_EXACT:
+			printk(KERN_ERR "ERROR: transaction error, %d\n", i);
+			break;
+
+		case INT_BABBLE:
+			printk(KERN_ERR "ERROR: babble error, %d\n", i);
+			break;
+		}
+		dw4 >>= 3;
+	}
+}
+
+static void enqueue_one_qtd(struct isp1760_qtd *qtd, struct isp1760_hcd *priv,
+		u32 payload)
+{
+	u32 token;
+	struct usb_hcd *hcd = priv_to_hcd(priv);
+
+	token = qtd->packet_type;
+
+	if (qtd->length && (qtd->length <= HC_ATL_PL_SIZE)) {
+		switch (token) {
+		case IN_PID:
+			break;
+		case OUT_PID:
+		case SETUP_PID:
+			priv_write_copy(priv, qtd->data_buffer,
+					hcd->regs + payload,
+					qtd->length);
+		}
+	}
+}
+
+static void enqueue_one_atl_qtd(u32 atl_regs, u32 payload,
+		struct isp1760_hcd *priv, struct isp1760_qh *qh,
+		struct urb *urb, u32 slot, struct isp1760_qtd *qtd)
+{
+	struct ptd ptd;
+	struct usb_hcd *hcd = priv_to_hcd(priv);
+
+	transform_into_atl(priv, qh, qtd, urb, payload, &ptd);
+	priv_write_copy(priv, (u32 *)&ptd, hcd->regs + atl_regs, sizeof(ptd));
+	enqueue_one_qtd(qtd, priv, payload);
+
+	priv->atl_ints[slot].urb = urb;
+	priv->atl_ints[slot].qh = qh;
+	priv->atl_ints[slot].qtd = qtd;
+	priv->atl_ints[slot].data_buffer = qtd->data_buffer;
+	priv->atl_ints[slot].payload = payload;
+	qtd->status |= URB_ENQUEUED | URB_TYPE_ATL;
+	qtd->status |= slot << 16;
+}
+
+static void enqueue_one_int_qtd(u32 int_regs, u32 payload,
+		struct isp1760_hcd *priv, struct isp1760_qh *qh,
+		struct urb *urb, u32 slot,  struct isp1760_qtd *qtd)
+{
+	struct ptd ptd;
+	struct usb_hcd *hcd = priv_to_hcd(priv);
+
+	transform_into_int(priv, qh, qtd, urb, payload, &ptd);
+	priv_write_copy(priv, (u32 *)&ptd, hcd->regs + int_regs, sizeof(ptd));
+	enqueue_one_qtd(qtd, priv, payload);
+
+	priv->int_ints[slot].urb = urb;
+	priv->int_ints[slot].qh = qh;
+	priv->int_ints[slot].qtd = qtd;
+	priv->int_ints[slot].data_buffer = qtd->data_buffer;
+	priv->int_ints[slot].payload = payload;
+	qtd->status |= URB_ENQUEUED | URB_TYPE_INT;
+	qtd->status |= slot << 16;
+}
+
+void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
+		struct isp1760_qtd *qtd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	u32 skip_map, or_map;
+	u32 queue_entry;
+	u32 slot;
+	u32 atl_regs, payload;
+	u32 buffstatus;
+
+	skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
+
+	BUG_ON(!skip_map);
+	slot = __ffs(skip_map);
+	queue_entry = 1 << slot;
+
+	atl_regs = ATL_REGS_OFFSET + slot * sizeof(struct ptd);
+
+	payload = alloc_mem(priv, qtd->length);
+
+	enqueue_one_atl_qtd(atl_regs, payload, priv, qh, qtd->urb, slot, qtd);
+
+	or_map = isp1760_readl(hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	or_map |= queue_entry;
+	isp1760_writel(or_map, hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+
+	skip_map &= ~queue_entry;
+	isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
+
+	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
+	buffstatus |= ATL_BUFFER;
+	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
+}
+
+void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
+		struct isp1760_qtd *qtd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	u32 skip_map, or_map;
+	u32 queue_entry;
+	u32 slot;
+	u32 int_regs, payload;
+	u32 buffstatus;
+
+	skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG);
+
+	BUG_ON(!skip_map);
+	slot = __ffs(skip_map);
+	queue_entry = 1 << slot;
+
+	int_regs = INT_REGS_OFFSET + slot * sizeof(struct ptd);
+
+	payload = alloc_mem(priv, qtd->length);
+
+	enqueue_one_int_qtd(int_regs, payload, priv, qh, qtd->urb, slot, qtd);
+
+	or_map = isp1760_readl(hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	or_map |= queue_entry;
+	isp1760_writel(or_map, hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+
+	skip_map &= ~queue_entry;
+	isp1760_writel(skip_map, hcd->regs + HC_INT_PTD_SKIPMAP_REG);
+
+	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
+	buffstatus |= INT_BUFFER;
+	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
+}
+
+static void isp1760_urb_done(struct isp1760_hcd *priv, struct urb *urb, int status)
+__releases(priv->lock)
+__acquires(priv->lock)
+{
+	if (!urb->unlinked) {
+		if (status == -EINPROGRESS)
+			status = 0;
+	}
+
+	/* complete() can reenter this HCD */
+	usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
+	spin_unlock(&priv->lock);
+	usb_hcd_giveback_urb(priv_to_hcd(priv), urb, status);
+	spin_lock(&priv->lock);
+}
+
+static void isp1760_qtd_free(struct isp1760_qtd *qtd)
+{
+	kmem_cache_free(qtd_cachep, qtd);
+}
+
+static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd)
+{
+	struct isp1760_qtd *tmp_qtd;
+
+	tmp_qtd = qtd->hw_next;
+	list_del(&qtd->qtd_list);
+	isp1760_qtd_free(qtd);
+	return tmp_qtd;
+}
+
+/*
+ * Remove this QTD from the QH list and free its memory. If this QTD
+ * isn't the last one than remove also his successor(s).
+ * Returns the QTD which is part of an new URB and should be enqueued.
+ */
+static struct isp1760_qtd *clean_up_qtdlist(struct isp1760_qtd *qtd)
+{
+	struct isp1760_qtd *tmp_qtd;
+	int last_one;
+
+	do {
+		tmp_qtd = qtd->hw_next;
+		last_one = qtd->status & URB_COMPLETE_NOTIFY;
+		list_del(&qtd->qtd_list);
+		isp1760_qtd_free(qtd);
+		qtd = tmp_qtd;
+	} while (!last_one && qtd);
+
+	return qtd;
+}
+
+static void do_atl_int(struct usb_hcd *usb_hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	u32 done_map, skip_map;
+	struct ptd ptd;
+	struct urb *urb = NULL;
+	u32 atl_regs_base;
+	u32 atl_regs;
+	u32 queue_entry;
+	u32 payload;
+	u32 length;
+	u32 or_map;
+	u32 status = -EINVAL;
+	int error;
+	struct isp1760_qtd *qtd;
+	struct isp1760_qh *qh;
+	u32 rl;
+	u32 nakcount;
+
+	done_map = isp1760_readl(usb_hcd->regs +
+			HC_ATL_PTD_DONEMAP_REG);
+	skip_map = isp1760_readl(usb_hcd->regs +
+			HC_ATL_PTD_SKIPMAP_REG);
+
+	or_map = isp1760_readl(usb_hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	or_map &= ~done_map;
+	isp1760_writel(or_map, usb_hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+
+	atl_regs_base = ATL_REGS_OFFSET;
+	while (done_map) {
+		u32 dw1;
+		u32 dw2;
+		u32 dw3;
+
+		status = 0;
+
+		queue_entry = __ffs(done_map);
+		done_map &= ~(1 << queue_entry);
+		skip_map |= 1 << queue_entry;
+
+		atl_regs = atl_regs_base + queue_entry * sizeof(struct ptd);
+
+		urb = priv->atl_ints[queue_entry].urb;
+		qtd = priv->atl_ints[queue_entry].qtd;
+		qh = priv->atl_ints[queue_entry].qh;
+		payload = priv->atl_ints[queue_entry].payload;
+
+		if (!qh) {
+			printk(KERN_ERR "qh is 0\n");
+			continue;
+		}
+		priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs,
+				atl_regs, sizeof(ptd));
+
+		dw1 = le32_to_cpu(ptd.dw1);
+		dw2 = le32_to_cpu(ptd.dw2);
+		dw3 = le32_to_cpu(ptd.dw3);
+		rl = (dw2 >> 25) & 0x0f;
+		nakcount = (dw3 >> 19) & 0xf;
+
+		/* Transfer Error, *but* active and no HALT -> reload */
+		if ((dw3 & DW3_ERROR_BIT) && (dw3 & DW3_QTD_ACTIVE) &&
+				!(dw3 & DW3_HALT_BIT)) {
+
+			/* according to ppriv code, we have to
+			 * reload this one if trasfered bytes != requested bytes
+			 * else act like everything went smooth..
+			 * XXX This just doesn't feel right and hasn't
+			 * triggered so far.
+			 */
+
+			length = PTD_XFERRED_LENGTH(dw3);
+			printk(KERN_ERR "Should reload now.... transfered %d "
+					"of %zu\n", length, qtd->length);
+			BUG();
+		}
+
+		if (!nakcount && (dw3 & DW3_QTD_ACTIVE)) {
+			u32 buffstatus;
+
+			/* XXX
+			 * NAKs are handled in HW by the chip. Usually if the
+			 * device is not able to send data fast enough.
+			 * This did not trigger for a long time now.
+			 */
+			printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: "
+					"%d of %d done: %08x cur: %08x\n", qtd,
+					urb, qh, PTD_XFERRED_LENGTH(dw3),
+					qtd->length, done_map,
+					(1 << queue_entry));
+
+			/* RL counter = ERR counter */
+			dw3 &= ~(0xf << 19);
+			dw3 |= rl << 19;
+			dw3 &= ~(3 << (55 - 32));
+			dw3 |= ERR_COUNTER << (55 - 32);
+
+			/*
+			 * It is not needed to write skip map back because it
+			 * is unchanged. Just make sure that this entry is
+			 * unskipped once it gets written to the HW.
+			 */
+			skip_map &= ~(1 << queue_entry);
+			or_map = isp1760_readl(usb_hcd->regs +
+					HC_ATL_IRQ_MASK_OR_REG);
+			or_map |= 1 << queue_entry;
+			isp1760_writel(or_map, usb_hcd->regs +
+					HC_ATL_IRQ_MASK_OR_REG);
+
+			ptd.dw3 = cpu_to_le32(dw3);
+			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
+					atl_regs, sizeof(ptd));
+
+			ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID);
+			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
+					atl_regs, sizeof(ptd));
+
+			buffstatus = isp1760_readl(usb_hcd->regs +
+					HC_BUFFER_STATUS_REG);
+			buffstatus |= ATL_BUFFER;
+			isp1760_writel(buffstatus, usb_hcd->regs +
+					HC_BUFFER_STATUS_REG);
+			continue;
+		}
+
+		error = check_error(&ptd);
+		if (error) {
+			status = error;
+			priv->atl_ints[queue_entry].qh->toggle = 0;
+			priv->atl_ints[queue_entry].qh->ping = 0;
+			urb->status = -EPIPE;
+
+#if 0
+			printk(KERN_ERR "Error in %s().\n", __func__);
+			printk(KERN_ERR "IN dw0: %08x dw1: %08x dw2: %08x "
+					"dw3: %08x dw4: %08x dw5: %08x dw6: "
+					"%08x dw7: %08x\n",
+					ptd.dw0, ptd.dw1, ptd.dw2, ptd.dw3,
+					ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7);
+#endif
+		} else {
+			if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+				priv->atl_ints[queue_entry].qh->toggle = dw3 &
+					(1 << 25);
+				priv->atl_ints[queue_entry].qh->ping = dw3 &
+					(1 << 26);
+			}
+		}
+
+		length = PTD_XFERRED_LENGTH(dw3);
+		if (length) {
+			switch (DW1_GET_PID(dw1)) {
+			case IN_PID:
+				priv_read_copy(priv,
+					priv->atl_ints[queue_entry].data_buffer,
+					usb_hcd->regs + payload, payload,
+					length);
+
+			case OUT_PID:
+
+				urb->actual_length += length;
+
+			case SETUP_PID:
+				break;
+			}
+		}
+
+		priv->atl_ints[queue_entry].data_buffer = NULL;
+		priv->atl_ints[queue_entry].urb = NULL;
+		priv->atl_ints[queue_entry].qtd = NULL;
+		priv->atl_ints[queue_entry].qh = NULL;
+
+		free_mem(priv, payload);
+
+		isp1760_writel(skip_map, usb_hcd->regs +
+				HC_ATL_PTD_SKIPMAP_REG);
+
+		if (urb->status == -EPIPE) {
+			/* HALT was received */
+
+			qtd = clean_up_qtdlist(qtd);
+			isp1760_urb_done(priv, urb, urb->status);
+
+		} else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) {
+			/* short BULK received */
+
+			printk(KERN_ERR "short bulk, %d instead %d\n", length,
+					qtd->length);
+			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+				urb->status = -EREMOTEIO;
+				printk(KERN_ERR "not okey\n");
+			}
+
+			if (urb->status == -EINPROGRESS)
+				urb->status = 0;
+
+			qtd = clean_up_qtdlist(qtd);
+
+			isp1760_urb_done(priv, urb, urb->status);
+
+		} else if (qtd->status & URB_COMPLETE_NOTIFY) {
+			/* that was the last qtd of that URB */
+
+			if (urb->status == -EINPROGRESS)
+				urb->status = 0;
+
+			qtd = clean_this_qtd(qtd);
+			isp1760_urb_done(priv, urb, urb->status);
+
+		} else {
+			/* next QTD of this URB */
+
+			qtd = clean_this_qtd(qtd);
+			BUG_ON(!qtd);
+		}
+
+		if (qtd)
+			enqueue_an_ATL_packet(usb_hcd, qh, qtd);
+
+		skip_map = isp1760_readl(usb_hcd->regs +
+				HC_ATL_PTD_SKIPMAP_REG);
+	}
+}
+
+static void do_intl_int(struct usb_hcd *usb_hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	u32 done_map, skip_map;
+	struct ptd ptd;
+	struct urb *urb = NULL;
+	u32 int_regs;
+	u32 int_regs_base;
+	u32 payload;
+	u32 length;
+	u32 or_map;
+	int error;
+	u32 queue_entry;
+	struct isp1760_qtd *qtd;
+	struct isp1760_qh *qh;
+
+	done_map = isp1760_readl(usb_hcd->regs +
+			HC_INT_PTD_DONEMAP_REG);
+	skip_map = isp1760_readl(usb_hcd->regs +
+			HC_INT_PTD_SKIPMAP_REG);
+
+	or_map = isp1760_readl(usb_hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	or_map &= ~done_map;
+	isp1760_writel(or_map, usb_hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+
+	int_regs_base = INT_REGS_OFFSET;
+
+	while (done_map) {
+		u32 dw1;
+		u32 dw3;
+
+		queue_entry = __ffs(done_map);
+		done_map &= ~(1 << queue_entry);
+		skip_map |= 1 << queue_entry;
+
+		int_regs = int_regs_base + queue_entry * sizeof(struct ptd);
+		urb = priv->int_ints[queue_entry].urb;
+		qtd = priv->int_ints[queue_entry].qtd;
+		qh = priv->int_ints[queue_entry].qh;
+		payload = priv->int_ints[queue_entry].payload;
+
+		if (!qh) {
+			printk(KERN_ERR "(INT) qh is 0\n");
+			continue;
+		}
+
+		priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs,
+				int_regs, sizeof(ptd));
+		dw1 = le32_to_cpu(ptd.dw1);
+		dw3 = le32_to_cpu(ptd.dw3);
+		check_int_err_status(le32_to_cpu(ptd.dw4));
+
+		error = check_error(&ptd);
+		if (error) {
+#if 0
+			printk(KERN_ERR "Error in %s().\n", __func__);
+			printk(KERN_ERR "IN dw0: %08x dw1: %08x dw2: %08x "
+					"dw3: %08x dw4: %08x dw5: %08x dw6: "
+					"%08x dw7: %08x\n",
+					ptd.dw0, ptd.dw1, ptd.dw2, ptd.dw3,
+					ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7);
+#endif
+			urb->status = -EPIPE;
+			priv->int_ints[queue_entry].qh->toggle = 0;
+			priv->int_ints[queue_entry].qh->ping = 0;
+
+		} else {
+			priv->int_ints[queue_entry].qh->toggle =
+				dw3 & (1 << 25);
+			priv->int_ints[queue_entry].qh->ping = dw3 & (1 << 26);
+		}
+
+		if (urb->dev->speed != USB_SPEED_HIGH)
+			length = PTD_XFERRED_LENGTH_LO(dw3);
+		else
+			length = PTD_XFERRED_LENGTH(dw3);
+
+		if (length) {
+			switch (DW1_GET_PID(dw1)) {
+			case IN_PID:
+				priv_read_copy(priv,
+					priv->int_ints[queue_entry].data_buffer,
+					usb_hcd->regs + payload , payload,
+					length);
+			case OUT_PID:
+
+				urb->actual_length += length;
+
+			case SETUP_PID:
+				break;
+			}
+		}
+
+		priv->int_ints[queue_entry].data_buffer = NULL;
+		priv->int_ints[queue_entry].urb = NULL;
+		priv->int_ints[queue_entry].qtd = NULL;
+		priv->int_ints[queue_entry].qh = NULL;
+
+		isp1760_writel(skip_map, usb_hcd->regs +
+				HC_INT_PTD_SKIPMAP_REG);
+		free_mem(priv, payload);
+
+		if (urb->status == -EPIPE) {
+			/* HALT received */
+
+			 qtd = clean_up_qtdlist(qtd);
+			 isp1760_urb_done(priv, urb, urb->status);
+
+		} else if (qtd->status & URB_COMPLETE_NOTIFY) {
+
+			if (urb->status == -EINPROGRESS)
+				urb->status = 0;
+
+			qtd = clean_this_qtd(qtd);
+			isp1760_urb_done(priv, urb, urb->status);
+
+		} else {
+			/* next QTD of this URB */
+
+			qtd = clean_this_qtd(qtd);
+			BUG_ON(!qtd);
+		}
+
+		if (qtd)
+			enqueue_an_INT_packet(usb_hcd, qh, qtd);
+
+		skip_map = isp1760_readl(usb_hcd->regs +
+				HC_INT_PTD_SKIPMAP_REG);
+	}
+}
+
+#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
+static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
+		gfp_t flags)
+{
+	struct isp1760_qh *qh;
+	int is_input, type;
+
+	qh = isp1760_qh_alloc(priv, flags);
+	if (!qh)
+		return qh;
+
+	/*
+	 * init endpoint/device data for this QH
+	 */
+	is_input = usb_pipein(urb->pipe);
+	type = usb_pipetype(urb->pipe);
+
+	if (type == PIPE_INTERRUPT) {
+
+		if (urb->dev->speed == USB_SPEED_HIGH) {
+
+			qh->period = urb->interval >> 3;
+			if (qh->period == 0 && urb->interval != 1) {
+				/* NOTE interval 2 or 4 uframes could work.
+				 * But interval 1 scheduling is simpler, and
+				 * includes high bandwidth.
+				 */
+				printk(KERN_ERR "intr period %d uframes, NYET!",
+						urb->interval);
+				qh_destroy(qh);
+				return NULL;
+			}
+		} else {
+			qh->period = urb->interval;
+		}
+	}
+
+	/* support for tt scheduling, and access to toggles */
+	qh->dev = urb->dev;
+
+	if (!usb_pipecontrol(urb->pipe))
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input,
+				1);
+	return qh;
+}
+
+/*
+ * For control/bulk/interrupt, return QH with these TDs appended.
+ * Allocates and initializes the QH if necessary.
+ * Returns null if it can't allocate a QH it needs to.
+ * If the QH has TDs (urbs) already, that's great.
+ */
+static struct isp1760_qh *qh_append_tds(struct isp1760_hcd *priv,
+		struct urb *urb, struct list_head *qtd_list, int epnum,
+		void **ptr)
+{
+	struct isp1760_qh *qh;
+	struct isp1760_qtd *qtd;
+	struct isp1760_qtd *prev_qtd;
+
+	qh = (struct isp1760_qh *)*ptr;
+	if (!qh) {
+		/* can't sleep here, we have priv->lock... */
+		qh = qh_make(priv, urb, GFP_ATOMIC);
+		if (!qh)
+			return qh;
+		*ptr = qh;
+	}
+
+	qtd = list_entry(qtd_list->next, struct isp1760_qtd,
+			qtd_list);
+	if (!list_empty(&qh->qtd_list))
+		prev_qtd = list_entry(qh->qtd_list.prev,
+				struct isp1760_qtd, qtd_list);
+	else
+		prev_qtd = NULL;
+
+	list_splice(qtd_list, qh->qtd_list.prev);
+	if (prev_qtd) {
+		BUG_ON(prev_qtd->hw_next);
+		prev_qtd->hw_next = qtd;
+	}
+
+	urb->hcpriv = qh;
+	return qh;
+}
+
+static void qtd_list_free(struct isp1760_hcd *priv, struct urb *urb,
+		struct list_head *qtd_list)
+{
+	struct list_head *entry, *temp;
+
+	list_for_each_safe(entry, temp, qtd_list) {
+		struct isp1760_qtd	*qtd;
+
+		qtd = list_entry(entry, struct isp1760_qtd, qtd_list);
+		list_del(&qtd->qtd_list);
+		isp1760_qtd_free(qtd);
+	}
+}
+
+static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
+		struct list_head *qtd_list, gfp_t mem_flags, packet_enqueue *p)
+{
+	struct isp1760_qtd         *qtd;
+	int                     epnum;
+	unsigned long           flags;
+	struct isp1760_qh          *qh = NULL;
+	int                     rc;
+	int qh_busy;
+
+	qtd = list_entry(qtd_list->next, struct isp1760_qtd, qtd_list);
+	epnum = urb->ep->desc.bEndpointAddress;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &priv_to_hcd(priv)->flags)) {
+		rc = -ESHUTDOWN;
+		goto done;
+	}
+	rc = usb_hcd_link_urb_to_ep(priv_to_hcd(priv), urb);
+	if (rc)
+		goto done;
+
+	qh = urb->ep->hcpriv;
+	if (qh)
+		qh_busy = !list_empty(&qh->qtd_list);
+	else
+		qh_busy = 0;
+
+	qh = qh_append_tds(priv, urb, qtd_list, epnum, &urb->ep->hcpriv);
+	if (!qh) {
+		usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
+		rc = -ENOMEM;
+		goto done;
+	}
+
+	if (!qh_busy)
+		p(priv_to_hcd(priv), qh, qtd);
+
+done:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	if (!qh)
+		qtd_list_free(priv, urb, qtd_list);
+	return rc;
+}
+
+static struct isp1760_qtd *isp1760_qtd_alloc(struct isp1760_hcd *priv,
+		gfp_t flags)
+{
+	struct isp1760_qtd *qtd;
+
+	qtd = kmem_cache_zalloc(qtd_cachep, flags);
+	if (qtd)
+		INIT_LIST_HEAD(&qtd->qtd_list);
+
+	return qtd;
+}
+
+/*
+ * create a list of filled qtds for this URB; won't link into qh.
+ */
+static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
+		struct urb *urb, struct list_head *head, gfp_t flags)
+{
+	struct isp1760_qtd *qtd, *qtd_prev;
+	void *buf;
+	int len, maxpacket;
+	int is_input;
+	u32 token;
+
+	/*
+	 * URBs map to sequences of QTDs:  one logical transaction
+	 */
+	qtd = isp1760_qtd_alloc(priv, flags);
+	if (!qtd)
+		return NULL;
+
+	list_add_tail(&qtd->qtd_list, head);
+	qtd->urb = urb;
+	urb->status = -EINPROGRESS;
+
+	token = 0;
+	/* for split transactions, SplitXState initialized to zero */
+
+	len = urb->transfer_buffer_length;
+	is_input = usb_pipein(urb->pipe);
+	if (usb_pipecontrol(urb->pipe)) {
+		/* SETUP pid */
+		qtd_fill(qtd, urb->setup_packet,
+				sizeof(struct usb_ctrlrequest),
+				token | SETUP_PID);
+
+		/* ... and always at least one more pid */
+		token ^= DATA_TOGGLE;
+		qtd_prev = qtd;
+		qtd = isp1760_qtd_alloc(priv, flags);
+		if (!qtd)
+			goto cleanup;
+		qtd->urb = urb;
+		qtd_prev->hw_next = qtd;
+		list_add_tail(&qtd->qtd_list, head);
+
+		/* for zero length DATA stages, STATUS is always IN */
+		if (len == 0)
+			token |= IN_PID;
+	}
+
+	/*
+	 * data transfer stage:  buffer setup
+	 */
+	buf = urb->transfer_buffer;
+
+	if (is_input)
+		token |= IN_PID;
+	else
+		token |= OUT_PID;
+
+	maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
+
+	/*
+	 * buffer gets wrapped in one or more qtds;
+	 * last one may be "short" (including zero len)
+	 * and may serve as a control status ack
+	 */
+	for (;;) {
+		int this_qtd_len;
+
+		if (!buf && len) {
+			/* XXX This looks like usb storage / SCSI bug */
+			printk(KERN_ERR "buf is null, dma is %08lx len is %d\n",
+					(long unsigned)urb->transfer_dma, len);
+			WARN_ON(1);
+		}
+
+		this_qtd_len = qtd_fill(qtd, buf, len, token);
+		len -= this_qtd_len;
+		buf += this_qtd_len;
+
+		/* qh makes control packets use qtd toggle; maybe switch it */
+		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
+			token ^= DATA_TOGGLE;
+
+		if (len <= 0)
+			break;
+
+		qtd_prev = qtd;
+		qtd = isp1760_qtd_alloc(priv, flags);
+		if (!qtd)
+			goto cleanup;
+		qtd->urb = urb;
+		qtd_prev->hw_next = qtd;
+		list_add_tail(&qtd->qtd_list, head);
+	}
+
+	/*
+	 * control requests may need a terminating data "status" ack;
+	 * bulk ones may need a terminating short packet (zero length).
+	 */
+	if (urb->transfer_buffer_length != 0) {
+		int one_more = 0;
+
+		if (usb_pipecontrol(urb->pipe)) {
+			one_more = 1;
+			/* "in" <--> "out"  */
+			token ^= IN_PID;
+			/* force DATA1 */
+			token |= DATA_TOGGLE;
+		} else if (usb_pipebulk(urb->pipe)
+				&& (urb->transfer_flags & URB_ZERO_PACKET)
+				&& !(urb->transfer_buffer_length % maxpacket)) {
+			one_more = 1;
+		}
+		if (one_more) {
+			qtd_prev = qtd;
+			qtd = isp1760_qtd_alloc(priv, flags);
+			if (!qtd)
+				goto cleanup;
+			qtd->urb = urb;
+			qtd_prev->hw_next = qtd;
+			list_add_tail(&qtd->qtd_list, head);
+
+			/* never any data in such packets */
+			qtd_fill(qtd, NULL, 0, token);
+		}
+	}
+
+	qtd->status = URB_COMPLETE_NOTIFY;
+	return head;
+
+cleanup:
+	qtd_list_free(priv, urb, head);
+	return NULL;
+}
+
+static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+		gfp_t mem_flags)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	struct list_head qtd_list;
+	packet_enqueue *pe;
+
+	INIT_LIST_HEAD(&qtd_list);
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+
+		if (!qh_urb_transaction(priv, urb, &qtd_list, mem_flags))
+			return -ENOMEM;
+		pe =  enqueue_an_ATL_packet;
+		break;
+
+	case PIPE_INTERRUPT:
+		if (!qh_urb_transaction(priv, urb, &qtd_list, mem_flags))
+			return -ENOMEM;
+		pe = enqueue_an_INT_packet;
+		break;
+
+	case PIPE_ISOCHRONOUS:
+		printk(KERN_ERR "PIPE_ISOCHRONOUS ain't supported\n");
+	default:
+		return -EPIPE;
+	}
+
+	isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe);
+	return 0;
+}
+
+static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+		int status)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	struct inter_packet_info *ints;
+	u32 i;
+	u32 reg_base, or_reg, skip_reg;
+	int flags;
+	struct ptd ptd;
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_ISOCHRONOUS:
+		return -EPIPE;
+		break;
+
+	case PIPE_INTERRUPT:
+		ints = priv->int_ints;
+		reg_base = INT_REGS_OFFSET;
+		or_reg = HC_INT_IRQ_MASK_OR_REG;
+		skip_reg = HC_INT_PTD_SKIPMAP_REG;
+		break;
+
+	default:
+		ints = priv->atl_ints;
+		reg_base = ATL_REGS_OFFSET;
+		or_reg = HC_ATL_IRQ_MASK_OR_REG;
+		skip_reg = HC_ATL_PTD_SKIPMAP_REG;
+		break;
+	}
+
+	memset(&ptd, 0, sizeof(ptd));
+	spin_lock_irqsave(&priv->lock, flags);
+
+	for (i = 0; i < 32; i++) {
+		if (ints->urb == urb) {
+			u32 skip_map;
+			u32 or_map;
+			struct isp1760_qtd *qtd;
+
+			skip_map = isp1760_readl(hcd->regs + skip_reg);
+			skip_map |= 1 << i;
+			isp1760_writel(skip_map, hcd->regs + skip_reg);
+
+			or_map = isp1760_readl(hcd->regs + or_reg);
+			or_map &= ~(1 << i);
+			isp1760_writel(or_map, hcd->regs + or_reg);
+
+			priv_write_copy(priv, (u32 *)&ptd, hcd->regs + reg_base
+					+ i * sizeof(ptd), sizeof(ptd));
+			qtd = ints->qtd;
+
+			clean_up_qtdlist(qtd);
+
+			free_mem(priv, ints->payload);
+
+			ints->urb = NULL;
+			ints->qh = NULL;
+			ints->qtd = NULL;
+			ints->data_buffer = NULL;
+			ints->payload = 0;
+
+			isp1760_urb_done(priv, urb, status);
+			break;
+		}
+		ints++;
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return 0;
+}
+
+static irqreturn_t isp1760_irq(struct usb_hcd *usb_hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	u32 imask;
+	irqreturn_t irqret = IRQ_NONE;
+
+	spin_lock(&priv->lock);
+
+	if (!(usb_hcd->state & HC_STATE_RUNNING))
+		goto leave;
+
+	imask = isp1760_readl(usb_hcd->regs + HC_INTERRUPT_REG);
+	if (unlikely(!imask))
+		goto leave;
+
+	isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG);
+	if (imask & HC_ATL_INT)
+		do_atl_int(usb_hcd);
+
+	if (imask & HC_INTL_INT)
+		do_intl_int(usb_hcd);
+
+	irqret = IRQ_HANDLED;
+leave:
+	spin_unlock(&priv->lock);
+	return irqret;
+}
+
+static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	u32 temp, status = 0;
+	u32 mask;
+	int retval = 1;
+	unsigned long flags;
+
+	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
+	if (!HC_IS_RUNNING(hcd->state))
+		return 0;
+
+	/* init status to no-changes */
+	buf[0] = 0;
+	mask = PORT_CSC;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	temp = isp1760_readl(hcd->regs + HC_PORTSC1);
+
+	if (temp & PORT_OWNER) {
+		if (temp & PORT_CSC) {
+			temp &= ~PORT_CSC;
+			isp1760_writel(temp, hcd->regs + HC_PORTSC1);
+			goto done;
+		}
+	}
+
+	/*
+	 * Return status information even for ports with OWNER set.
+	 * Otherwise khubd wouldn't see the disconnect event when a
+	 * high-speed device is switched over to the companion
+	 * controller by the user.
+	 */
+
+	if ((temp & mask) != 0
+			|| ((temp & PORT_RESUME) != 0
+				&& time_after_eq(jiffies,
+					priv->reset_done))) {
+		buf [0] |= 1 << (0 + 1);
+		status = STS_PCD;
+	}
+	/* FIXME autosuspend idle root hubs */
+done:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return status ? retval : 0;
+}
+
+static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
+		struct usb_hub_descriptor *desc)
+{
+	int ports = HCS_N_PORTS(priv->hcs_params);
+	u16 temp;
+
+	desc->bDescriptorType = 0x29;
+	/* priv 1.0, 2.3.9 says 20ms max */
+	desc->bPwrOn2PwrGood = 10;
+	desc->bHubContrCurrent = 0;
+
+	desc->bNbrPorts = ports;
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset(&desc->bitmap[0], 0, temp);
+	memset(&desc->bitmap[temp], 0xff, temp);
+
+	/* per-port overcurrent reporting */
+	temp = 0x0008;
+	if (HCS_PPC(priv->hcs_params))
+		/* per-port power control */
+		temp |= 0x0001;
+	else
+		/* no power switching */
+		temp |= 0x0002;
+	desc->wHubCharacteristics = cpu_to_le16(temp);
+}
+
+#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+
+static int check_reset_complete(struct isp1760_hcd *priv, int index,
+		u32 __iomem *status_reg, int port_status)
+{
+	if (!(port_status & PORT_CONNECT))
+		return port_status;
+
+	/* if reset finished and it's still not enabled -- handoff */
+	if (!(port_status & PORT_PE)) {
+
+		printk(KERN_ERR "port %d full speed --> companion\n",
+			index + 1);
+
+		port_status |= PORT_OWNER;
+		port_status &= ~PORT_RWC_BITS;
+		isp1760_writel(port_status, status_reg);
+
+	} else
+		printk(KERN_ERR "port %d high speed\n", index + 1);
+
+	return port_status;
+}
+
+static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
+		u16 wValue, u16 wIndex, char *buf, u16 wLength)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	int ports = HCS_N_PORTS(priv->hcs_params);
+	u32 __iomem *status_reg = hcd->regs + HC_PORTSC1;
+	u32 temp, status;
+	unsigned long flags;
+	int retval = 0;
+	unsigned selector;
+
+	/*
+	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
+	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
+	 * (track current state ourselves) ... blink for diagnostics,
+	 * power, "this is the one", etc.  EHCI spec supports this.
+	 */
+
+	spin_lock_irqsave(&priv->lock, flags);
+	switch (typeReq) {
+	case ClearHubFeature:
+		switch (wValue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* no hub-wide feature/status flags */
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case ClearPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = isp1760_readl(status_reg);
+
+		/*
+		 * Even if OWNER is set, so the port is owned by the
+		 * companion controller, khubd needs to be able to clear
+		 * the port-change status bits (especially
+		 * USB_PORT_FEAT_C_CONNECTION).
+		 */
+
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			isp1760_writel(temp & ~PORT_PE, status_reg);
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+			/* XXX error? */
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			if (temp & PORT_RESET)
+				goto error;
+
+			if (temp & PORT_SUSPEND) {
+				if ((temp & PORT_PE) == 0)
+					goto error;
+				/* resume signaling for 20 msec */
+				temp &= ~(PORT_RWC_BITS);
+				isp1760_writel(temp | PORT_RESUME,
+						status_reg);
+				priv->reset_done = jiffies +
+					msecs_to_jiffies(20);
+			}
+			break;
+		case USB_PORT_FEAT_C_SUSPEND:
+			/* we auto-clear this feature */
+			break;
+		case USB_PORT_FEAT_POWER:
+			if (HCS_PPC(priv->hcs_params))
+				isp1760_writel(temp & ~PORT_POWER, status_reg);
+			break;
+		case USB_PORT_FEAT_C_CONNECTION:
+			isp1760_writel(temp | PORT_CSC,
+					status_reg);
+			break;
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			/* XXX error ?*/
+			break;
+		case USB_PORT_FEAT_C_RESET:
+			/* GetPortStatus clears reset */
+			break;
+		default:
+			goto error;
+		}
+		isp1760_readl(hcd->regs + HC_USBCMD);
+		break;
+	case GetHubDescriptor:
+		isp1760_hub_descriptor(priv, (struct usb_hub_descriptor *)
+			buf);
+		break;
+	case GetHubStatus:
+		/* no hub-wide feature/status flags */
+		memset(buf, 0, 4);
+		break;
+	case GetPortStatus:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		status = 0;
+		temp = isp1760_readl(status_reg);
+
+		/* wPortChange bits */
+		if (temp & PORT_CSC)
+			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
+
+
+		/* whoever resumes must GetPortStatus to complete it!! */
+		if (temp & PORT_RESUME) {
+			printk(KERN_ERR "Port resume should be skipped.\n");
+
+			/* Remote Wakeup received? */
+			if (!priv->reset_done) {
+				/* resume signaling for 20 msec */
+				priv->reset_done = jiffies
+						+ msecs_to_jiffies(20);
+				/* check the port again */
+				mod_timer(&priv_to_hcd(priv)->rh_timer,
+						priv->reset_done);
+			}
+
+			/* resume completed? */
+			else if (time_after_eq(jiffies,
+					priv->reset_done)) {
+				status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+				priv->reset_done = 0;
+
+				/* stop resume signaling */
+				temp = isp1760_readl(status_reg);
+				isp1760_writel(
+					temp & ~(PORT_RWC_BITS | PORT_RESUME),
+					status_reg);
+				retval = handshake(priv, status_reg,
+					   PORT_RESUME, 0, 2000 /* 2msec */);
+				if (retval != 0) {
+					isp1760_err(priv,
+						"port %d resume error %d\n",
+						wIndex + 1, retval);
+					goto error;
+				}
+				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+			}
+		}
+
+		/* whoever resets must GetPortStatus to complete it!! */
+		if ((temp & PORT_RESET)
+				&& time_after_eq(jiffies,
+					priv->reset_done)) {
+			status |= 1 << USB_PORT_FEAT_C_RESET;
+			priv->reset_done = 0;
+
+			/* force reset to complete */
+			isp1760_writel(temp & ~PORT_RESET,
+					status_reg);
+			/* REVISIT:  some hardware needs 550+ usec to clear
+			 * this bit; seems too long to spin routinely...
+			 */
+			retval = handshake(priv, status_reg,
+					PORT_RESET, 0, 750);
+			if (retval != 0) {
+				isp1760_err(priv, "port %d reset error %d\n",
+						wIndex + 1, retval);
+				goto error;
+			}
+
+			/* see what we found out */
+			temp = check_reset_complete(priv, wIndex, status_reg,
+					isp1760_readl(status_reg));
+		}
+		/*
+		 * Even if OWNER is set, there's no harm letting khubd
+		 * see the wPortStatus values (they should all be 0 except
+		 * for PORT_POWER anyway).
+		 */
+
+		if (temp & PORT_OWNER)
+			printk(KERN_ERR "Warning: PORT_OWNER is set\n");
+
+		if (temp & PORT_CONNECT) {
+			status |= 1 << USB_PORT_FEAT_CONNECTION;
+			/* status may be from integrated TT */
+			status |= ehci_port_speed(priv, temp);
+		}
+		if (temp & PORT_PE)
+			status |= 1 << USB_PORT_FEAT_ENABLE;
+		if (temp & (PORT_SUSPEND|PORT_RESUME))
+			status |= 1 << USB_PORT_FEAT_SUSPEND;
+		if (temp & PORT_RESET)
+			status |= 1 << USB_PORT_FEAT_RESET;
+		if (temp & PORT_POWER)
+			status |= 1 << USB_PORT_FEAT_POWER;
+
+		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
+		break;
+	case SetHubFeature:
+		switch (wValue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* no hub-wide feature/status flags */
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case SetPortFeature:
+		selector = wIndex >> 8;
+		wIndex &= 0xff;
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = isp1760_readl(status_reg);
+		if (temp & PORT_OWNER)
+			break;
+
+/*		temp &= ~PORT_RWC_BITS; */
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			isp1760_writel(temp | PORT_PE, status_reg);
+			break;
+
+		case USB_PORT_FEAT_SUSPEND:
+			if ((temp & PORT_PE) == 0
+					|| (temp & PORT_RESET) != 0)
+				goto error;
+
+			isp1760_writel(temp | PORT_SUSPEND, status_reg);
+			break;
+		case USB_PORT_FEAT_POWER:
+			if (HCS_PPC(priv->hcs_params))
+				isp1760_writel(temp | PORT_POWER,
+						status_reg);
+			break;
+		case USB_PORT_FEAT_RESET:
+			if (temp & PORT_RESUME)
+				goto error;
+			/* line status bits may report this as low speed,
+			 * which can be fine if this root hub has a
+			 * transaction translator built in.
+			 */
+			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
+					&& PORT_USB11(temp)) {
+				temp |= PORT_OWNER;
+			} else {
+				temp |= PORT_RESET;
+				temp &= ~PORT_PE;
+
+				/*
+				 * caller must wait, then call GetPortStatus
+				 * usb 2.0 spec says 50 ms resets on root
+				 */
+				priv->reset_done = jiffies +
+					msecs_to_jiffies(50);
+			}
+			isp1760_writel(temp, status_reg);
+			break;
+		default:
+			goto error;
+		}
+		isp1760_readl(hcd->regs + HC_USBCMD);
+		break;
+
+	default:
+error:
+		/* "stall" on error */
+		retval = -EPIPE;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return retval;
+}
+
+static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd,
+		struct usb_host_endpoint *ep)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_qh *qh;
+	struct isp1760_qtd *qtd;
+	u32 flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	qh = ep->hcpriv;
+	if (!qh)
+		goto out;
+
+	ep->hcpriv = NULL;
+	do {
+		/* more than entry might get removed */
+		if (list_empty(&qh->qtd_list))
+			break;
+
+		qtd = list_first_entry(&qh->qtd_list, struct isp1760_qtd,
+				qtd_list);
+
+		if (qtd->status & URB_ENQUEUED) {
+
+			spin_unlock_irqrestore(&priv->lock, flags);
+			isp1760_urb_dequeue(usb_hcd, qtd->urb, -ECONNRESET);
+			spin_lock_irqsave(&priv->lock, flags);
+		} else {
+			struct urb *urb;
+
+			urb = qtd->urb;
+			clean_up_qtdlist(qtd);
+			isp1760_urb_done(priv, urb, -ECONNRESET);
+		}
+	} while (1);
+
+	qh_destroy(qh);
+	/* remove requests and leak them.
+	 * ATL are pretty fast done, INT could take a while...
+	 * The latter shoule be removed
+	 */
+out:
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int isp1760_get_frame(struct usb_hcd *hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	u32 fr;
+
+	fr = isp1760_readl(hcd->regs + HC_FRINDEX);
+	return (fr >> 3) % priv->periodic_size;
+}
+
+static void isp1760_stop(struct usb_hcd *hcd)
+{
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
+	isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER,	1,
+			NULL, 0);
+	mdelay(20);
+
+	spin_lock_irq(&priv->lock);
+	ehci_reset(priv);
+	/* Disable IRQ */
+	isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+	spin_unlock_irq(&priv->lock);
+
+	isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
+}
+
+static void isp1760_shutdown(struct usb_hcd *hcd)
+{
+	u32 command;
+
+	isp1760_stop(hcd);
+	isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+
+	command = isp1760_readl(hcd->regs + HC_USBCMD);
+	command &= ~CMD_RUN;
+	isp1760_writel(command, hcd->regs + HC_USBCMD);
+}
+
+static const struct hc_driver isp1760_hc_driver = {
+	.description		= "isp1760-hcd",
+	.product_desc		= "NXP ISP1760 USB Host Controller",
+	.hcd_priv_size		= sizeof(struct isp1760_hcd),
+	.irq			= isp1760_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+	.reset			= isp1760_hc_setup,
+	.start			= isp1760_run,
+	.stop			= isp1760_stop,
+	.shutdown		= isp1760_shutdown,
+	.urb_enqueue		= isp1760_urb_enqueue,
+	.urb_dequeue		= isp1760_urb_dequeue,
+	.endpoint_disable	= isp1760_endpoint_disable,
+	.get_frame_number	= isp1760_get_frame,
+	.hub_status_data	= isp1760_hub_status_data,
+	.hub_control		= isp1760_hub_control,
+};
+
+int __init init_kmem_once(void)
+{
+	qtd_cachep = kmem_cache_create("isp1760_qtd",
+			sizeof(struct isp1760_qtd), 0, SLAB_TEMPORARY |
+			SLAB_MEM_SPREAD, NULL);
+
+	if (!qtd_cachep)
+		return -ENOMEM;
+
+	qh_cachep = kmem_cache_create("isp1760_qh", sizeof(struct isp1760_qh),
+			0, SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
+
+	if (!qh_cachep) {
+		kmem_cache_destroy(qtd_cachep);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void deinit_kmem_cache(void)
+{
+	kmem_cache_destroy(qtd_cachep);
+	kmem_cache_destroy(qh_cachep);
+}
+
+struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
+		u64 irqflags, struct device *dev, const char *busname)
+{
+	struct usb_hcd *hcd;
+	struct isp1760_hcd *priv;
+	int ret;
+
+	if (usb_disabled())
+		return ERR_PTR(-ENODEV);
+
+	/* prevent usb-core allocating DMA pages */
+	dev->dma_mask = NULL;
+
+	hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev->bus_id);
+	if (!hcd)
+		return ERR_PTR(-ENOMEM);
+
+	priv = hcd_to_priv(hcd);
+	init_memory(priv);
+	hcd->regs = ioremap(res_start, res_len);
+	if (!hcd->regs) {
+		ret = -EIO;
+		goto err_put;
+	}
+
+	ret = usb_add_hcd(hcd, irq, irqflags);
+	if (ret)
+		goto err_unmap;
+
+	hcd->irq = irq;
+	hcd->rsrc_start = res_start;
+	hcd->rsrc_len = res_len;
+
+	return hcd;
+
+err_unmap:
+	 iounmap(hcd->regs);
+
+err_put:
+	 usb_put_hcd(hcd);
+
+	 return ERR_PTR(ret);
+}
+
+MODULE_DESCRIPTION("Driver for the ISP1760 USB-controller from NXP");
+MODULE_AUTHOR("Sebastian Siewior <bigeasy@linuxtronix.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
new file mode 100644
index 0000000..3d86d0f
--- /dev/null
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -0,0 +1,206 @@
+#ifndef _ISP1760_HCD_H_
+#define _ISP1760_HCD_H_
+
+/* exports for if */
+struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
+		u64 irqflags, struct device *dev, const char *busname);
+int init_kmem_once(void);
+void deinit_kmem_cache(void);
+
+/* EHCI capability registers */
+#define HC_CAPLENGTH		0x00
+#define HC_HCSPARAMS		0x04
+#define HC_HCCPARAMS		0x08
+
+/* EHCI operational registers */
+#define HC_USBCMD		0x20
+#define HC_USBSTS		0x24
+#define HC_FRINDEX		0x2c
+#define HC_CONFIGFLAG		0x60
+#define HC_PORTSC1		0x64
+#define HC_ISO_PTD_DONEMAP_REG	0x130
+#define HC_ISO_PTD_SKIPMAP_REG	0x134
+#define HC_ISO_PTD_LASTPTD_REG	0x138
+#define HC_INT_PTD_DONEMAP_REG	0x140
+#define HC_INT_PTD_SKIPMAP_REG	0x144
+#define HC_INT_PTD_LASTPTD_REG	0x148
+#define HC_ATL_PTD_DONEMAP_REG	0x150
+#define HC_ATL_PTD_SKIPMAP_REG	0x154
+#define HC_ATL_PTD_LASTPTD_REG	0x158
+
+/* Configuration Register */
+#define HC_HW_MODE_CTRL		0x300
+#define ALL_ATX_RESET		(1 << 31)
+#define HW_DATA_BUS_32BIT	(1 << 8)
+#define HW_DACK_POL_HIGH	(1 << 6)
+#define HW_DREQ_POL_HIGH	(1 << 5)
+#define HW_INTR_HIGH_ACT	(1 << 2)
+#define HW_INTR_EDGE_TRIG	(1 << 1)
+#define HW_GLOBAL_INTR_EN	(1 << 0)
+
+#define HC_CHIP_ID_REG		0x304
+#define HC_SCRATCH_REG		0x308
+
+#define HC_RESET_REG		0x30c
+#define SW_RESET_RESET_HC	(1 << 1)
+#define SW_RESET_RESET_ALL	(1 << 0)
+
+#define HC_BUFFER_STATUS_REG	0x334
+#define ATL_BUFFER		0x1
+#define INT_BUFFER		0x2
+#define ISO_BUFFER		0x4
+#define BUFFER_MAP		0x7
+
+#define HC_MEMORY_REG		0x33c
+#define HC_PORT1_CTRL		0x374
+#define PORT1_POWER		(3 << 3)
+#define PORT1_INIT1		(1 << 7)
+#define PORT1_INIT2		(1 << 23)
+
+/* Interrupt Register */
+#define HC_INTERRUPT_REG	0x310
+
+#define HC_INTERRUPT_ENABLE	0x314
+#define INTERRUPT_ENABLE_MASK	(HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
+#define FINAL_HW_CONFIG	(HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT)
+
+#define HC_ISO_INT		(1 << 9)
+#define HC_ATL_INT		(1 << 8)
+#define HC_INTL_INT		(1 << 7)
+#define HC_EOT_INT		(1 << 3)
+#define HC_SOT_INT		(1 << 1)
+
+#define HC_ISO_IRQ_MASK_OR_REG	0x318
+#define HC_INT_IRQ_MASK_OR_REG	0x31C
+#define HC_ATL_IRQ_MASK_OR_REG	0x320
+#define HC_ISO_IRQ_MASK_AND_REG	0x324
+#define HC_INT_IRQ_MASK_AND_REG	0x328
+#define HC_ATL_IRQ_MASK_AND_REG	0x32C
+
+/* Register sets */
+#define HC_BEGIN_OF_ATL		0x0c00
+#define HC_BEGIN_OF_INT		0x0800
+#define HC_BEGIN_OF_ISO		0x0400
+#define HC_BEGIN_OF_PAYLOAD	0x1000
+
+/* urb state*/
+#define DELETE_URB		(0x0008)
+#define NO_TRANSFER_ACTIVE	(0xffffffff)
+
+#define ATL_REGS_OFFSET		(0xc00)
+#define INT_REGS_OFFSET		(0x800)
+
+/* Philips Transfer Descriptor (PTD) */
+struct ptd {
+	__le32 dw0;
+	__le32 dw1;
+	__le32 dw2;
+	__le32 dw3;
+	__le32 dw4;
+	__le32 dw5;
+	__le32 dw6;
+	__le32 dw7;
+};
+
+struct inter_packet_info {
+	void *data_buffer;
+	u32 payload;
+#define PTD_FIRE_NEXT		(1 << 0)
+#define PTD_URB_FINISHED	(1 << 1)
+	struct urb *urb;
+	struct isp1760_qh *qh;
+	struct isp1760_qtd *qtd;
+};
+
+
+typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
+		struct isp1760_qtd *qtd);
+
+#define isp1760_info(priv, fmt, args...) \
+	dev_info(priv_to_hcd(priv)->self.controller, fmt, ##args)
+
+#define isp1760_err(priv, fmt, args...) \
+	dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
+
+/* chip memory management */
+struct memory_chunk {
+	unsigned int start;
+	unsigned int size;
+	unsigned int free;
+};
+
+/*
+ * 60kb divided in:
+ * - 32 blocks @ 256  bytes
+ * - 20 blocks @ 1024 bytes
+ * -  4 blocks @ 8192 bytes
+ */
+
+#define BLOCK_1_NUM 32
+#define BLOCK_2_NUM 20
+#define BLOCK_3_NUM 4
+
+#define BLOCK_1_SIZE 256
+#define BLOCK_2_SIZE 1024
+#define BLOCK_3_SIZE 8192
+#define BLOCKS (BLOCK_1_NUM + BLOCK_2_NUM + BLOCK_3_NUM)
+#define PAYLOAD_SIZE 0xf000
+
+/* I saw if some reloads if the pointer was negative */
+#define ISP1760_NULL_POINTER	(0x400)
+
+/* ATL */
+/* DW0 */
+#define PTD_VALID			1
+#define PTD_LENGTH(x)			(((u32) x) << 3)
+#define PTD_MAXPACKET(x)		(((u32) x) << 18)
+#define PTD_MULTI(x)			(((u32) x) << 29)
+#define PTD_ENDPOINT(x)			(((u32)	x) << 31)
+/* DW1 */
+#define PTD_DEVICE_ADDR(x)		(((u32) x) << 3)
+#define PTD_PID_TOKEN(x)		(((u32) x) << 10)
+#define PTD_TRANS_BULK			((u32) 2 << 12)
+#define PTD_TRANS_INT			((u32) 3 << 12)
+#define PTD_TRANS_SPLIT			((u32) 1 << 14)
+#define PTD_SE_USB_LOSPEED		((u32) 2 << 16)
+#define PTD_PORT_NUM(x)			(((u32) x) << 18)
+#define PTD_HUB_NUM(x)			(((u32) x) << 25)
+#define PTD_PING(x)			(((u32) x) << 26)
+/* DW2 */
+#define PTD_RL_CNT(x)			(((u32) x) << 25)
+#define PTD_DATA_START_ADDR(x)		(((u32) x) << 8)
+#define BASE_ADDR			0x1000
+/* DW3 */
+#define PTD_CERR(x)			(((u32) x) << 23)
+#define PTD_NAC_CNT(x)			(((u32) x) << 19)
+#define PTD_ACTIVE			((u32) 1 << 31)
+#define PTD_DATA_TOGGLE(x)		(((u32) x) << 25)
+
+#define DW3_HALT_BIT			(1 << 30)
+#define DW3_ERROR_BIT			(1 << 28)
+#define DW3_QTD_ACTIVE			(1 << 31)
+
+#define INT_UNDERRUN			(1 << 2)
+#define INT_BABBLE			(1 << 1)
+#define INT_EXACT			(1 << 0)
+
+#define DW1_GET_PID(x)			(((x) >> 10) & 0x3)
+#define PTD_XFERRED_LENGTH(x)		((x) & 0x7fff)
+#define PTD_XFERRED_LENGTH_LO(x)	((x) & 0x7ff)
+
+#define SETUP_PID	(2)
+#define IN_PID		(1)
+#define OUT_PID		(0)
+#define GET_QTD_TOKEN_TYPE(x)	((x) & 0x3)
+
+#define DATA_TOGGLE		(1 << 31)
+#define GET_DATA_TOGGLE(x)	((x) >> 31)
+
+/* Errata 1 */
+#define RL_COUNTER	(0)
+#define NAK_COUNTER	(0)
+#define ERR_COUNTER	(2)
+
+#define HC_ATL_PL_SIZE	(8192)
+
+#endif
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
new file mode 100644
index 0000000..73fb2a3
--- /dev/null
+++ b/drivers/usb/host/isp1760-if.c
@@ -0,0 +1,298 @@
+/*
+ * Glue code for the ISP1760 driver and bus
+ * Currently there is support for
+ * - OpenFirmware
+ * - PCI
+ *
+ * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/io.h>
+
+#include "../core/hcd.h"
+#include "isp1760-hcd.h"
+
+#ifdef CONFIG_USB_ISP1760_OF
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#endif
+
+#ifdef CONFIG_USB_ISP1760_PCI
+#include <linux/pci.h>
+#endif
+
+#ifdef CONFIG_USB_ISP1760_OF
+static int of_isp1760_probe(struct of_device *dev,
+		const struct of_device_id *match)
+{
+	struct usb_hcd *hcd;
+	struct device_node *dp = dev->node;
+	struct resource *res;
+	struct resource memory;
+	struct of_irq oirq;
+	int virq;
+	u64 res_len;
+	int ret;
+
+	ret = of_address_to_resource(dp, 0, &memory);
+	if (ret)
+		return -ENXIO;
+
+	res = request_mem_region(memory.start, memory.end - memory.start + 1,
+			dev->dev.bus_id);
+	if (!res)
+		return -EBUSY;
+
+	res_len = memory.end - memory.start + 1;
+
+	if (of_irq_map_one(dp, 0, &oirq)) {
+		ret = -ENODEV;
+		goto release_reg;
+	}
+
+	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+			oirq.size);
+
+	hcd = isp1760_register(memory.start, res_len, virq,
+		IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
+	if (IS_ERR(hcd)) {
+		ret = PTR_ERR(hcd);
+		goto release_reg;
+	}
+
+	dev_set_drvdata(&dev->dev, hcd);
+	return ret;
+
+release_reg:
+	release_mem_region(memory.start, memory.end - memory.start + 1);
+	return ret;
+}
+
+static int of_isp1760_remove(struct of_device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&dev->dev);
+
+	dev_set_drvdata(&dev->dev, NULL);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	return 0;
+}
+
+static struct of_device_id of_isp1760_match[] = {
+	{
+		.compatible = "nxp,usb-isp1760",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_isp1760_match);
+
+static struct of_platform_driver isp1760_of_driver = {
+	.name           = "nxp-isp1760",
+	.match_table    = of_isp1760_match,
+	.probe          = of_isp1760_probe,
+	.remove         = of_isp1760_remove,
+};
+#endif
+
+#ifdef CONFIG_USB_ISP1760_PCI
+static u32 nxp_pci_io_base;
+static u32 iolength;
+static u32 pci_mem_phy0;
+static u32 length;
+static u8 *chip_addr;
+static u8 *iobase;
+
+static int __devinit isp1761_pci_probe(struct pci_dev *dev,
+		const struct pci_device_id *id)
+{
+	u8 latency, limit;
+	__u32 reg_data;
+	int retry_count;
+	int length;
+	int status = 1;
+	struct usb_hcd *hcd;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	if (pci_enable_device(dev) < 0)
+		return -ENODEV;
+
+	if (!dev->irq)
+		return -ENODEV;
+
+	/* Grab the PLX PCI mem maped port start address we need  */
+	nxp_pci_io_base = pci_resource_start(dev, 0);
+	iolength = pci_resource_len(dev, 0);
+
+	if (!request_mem_region(nxp_pci_io_base, iolength, "ISP1761 IO MEM")) {
+		printk(KERN_ERR "request region #1\n");
+		return -EBUSY;
+	}
+
+	iobase = ioremap_nocache(nxp_pci_io_base, iolength);
+	if (!iobase) {
+		printk(KERN_ERR "ioremap #1\n");
+		release_mem_region(nxp_pci_io_base, iolength);
+		return -ENOMEM;
+	}
+	/* Grab the PLX PCI shared memory of the ISP 1761 we need  */
+	pci_mem_phy0 = pci_resource_start(dev, 3);
+	length = pci_resource_len(dev, 3);
+
+	if (length < 0xffff) {
+		printk(KERN_ERR "memory length for this resource is less than "
+				"required\n");
+		release_mem_region(nxp_pci_io_base, iolength);
+		iounmap(iobase);
+		return  -ENOMEM;
+	}
+
+	if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) {
+		printk(KERN_ERR "host controller already in use\n");
+		release_mem_region(nxp_pci_io_base, iolength);
+		iounmap(iobase);
+		return -EBUSY;
+	}
+
+	/* bad pci latencies can contribute to overruns */
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
+	if (latency) {
+		pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
+		if (limit && limit < latency)
+			pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
+	}
+
+	/* Try to check whether we can access Scratch Register of
+	 * Host Controller or not. The initial PCI access is retried until
+	 * local init for the PCI bridge is completed
+	 */
+	retry_count = 20;
+	reg_data = 0;
+	while ((reg_data != 0xFACE) && retry_count) {
+		/*by default host is in 16bit mode, so
+		 * io operations at this stage must be 16 bit
+		 * */
+		writel(0xface, chip_addr + HC_SCRATCH_REG);
+		udelay(100);
+		reg_data = readl(chip_addr + HC_SCRATCH_REG);
+		retry_count--;
+	}
+
+	/* Host Controller presence is detected by writing to scratch register
+	 * and reading back and checking the contents are same or not
+	 */
+	if (reg_data != 0xFACE) {
+		err("scratch register mismatch %x", reg_data);
+		goto clean;
+	}
+
+	pci_set_master(dev);
+
+	status = readl(iobase + 0x68);
+	status |= 0x900;
+	writel(status, iobase + 0x68);
+
+	dev->dev.dma_mask = NULL;
+	hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
+		IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
+	pci_set_drvdata(dev, hcd);
+	if (!hcd)
+		return 0;
+clean:
+	status = -ENODEV;
+	iounmap(iobase);
+	release_mem_region(pci_mem_phy0, length);
+	release_mem_region(nxp_pci_io_base, iolength);
+	return status;
+}
+static void isp1761_pci_remove(struct pci_dev *dev)
+{
+	struct usb_hcd *hcd;
+
+	hcd = pci_get_drvdata(dev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	pci_disable_device(dev);
+
+	iounmap(iobase);
+	iounmap(chip_addr);
+
+	release_mem_region(nxp_pci_io_base, iolength);
+	release_mem_region(pci_mem_phy0, length);
+}
+
+static void isp1761_pci_shutdown(struct pci_dev *dev)
+{
+	printk(KERN_ERR "ips1761_pci_shutdown\n");
+}
+
+static const struct pci_device_id isp1760_plx [] = { {
+	/* handle any USB 2.0 EHCI controller */
+	PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)), ~0),
+		.driver_data = 0,
+},
+{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, isp1760_plx);
+
+static struct pci_driver isp1761_pci_driver = {
+	.name =         "isp1760",
+	.id_table =     isp1760_plx,
+	.probe =        isp1761_pci_probe,
+	.remove =       isp1761_pci_remove,
+	.shutdown =     isp1761_pci_shutdown,
+};
+#endif
+
+static int __init isp1760_init(void)
+{
+	int ret;
+
+	init_kmem_once();
+
+#ifdef CONFIG_USB_ISP1760_OF
+	ret = of_register_platform_driver(&isp1760_of_driver);
+	if (ret) {
+		deinit_kmem_cache();
+		return ret;
+	}
+#endif
+#ifdef CONFIG_USB_ISP1760_PCI
+	ret = pci_register_driver(&isp1761_pci_driver);
+	if (ret)
+		goto unreg_of;
+#endif
+	return ret;
+
+#ifdef CONFIG_USB_ISP1760_PCI
+unreg_of:
+#endif
+#ifdef CONFIG_USB_ISP1760_OF
+	of_unregister_platform_driver(&isp1760_of_driver);
+#endif
+	deinit_kmem_cache();
+	return ret;
+}
+module_init(isp1760_init);
+
+static void __exit isp1760_exit(void)
+{
+#ifdef CONFIG_USB_ISP1760_OF
+	of_unregister_platform_driver(&isp1760_of_driver);
+#endif
+#ifdef CONFIG_USB_ISP1760_PCI
+	pci_unregister_driver(&isp1761_pci_driver);
+#endif
+	deinit_kmem_cache();
+}
+module_exit(isp1760_exit);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 17dc2ec..79a7802 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -613,7 +613,7 @@
 static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
 {
 	__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
-	u32	temp;
+	u32	temp = 0;
 	u16	now = ohci_readl(ohci, &ohci->regs->fmnumber);
 	u16	reset_done = now + PORT_RESET_MSEC;
 	int	limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index d3e0d8a..3a7bfe7 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -234,7 +234,7 @@
 	return 0;
 }
 
-static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
+static int global_suspend_mode_is_broken(struct uhci_hcd *uhci)
 {
 	int port;
 	const char *sys_info;
@@ -261,27 +261,60 @@
 __acquires(uhci->lock)
 {
 	int auto_stop;
-	int int_enable, egsm_enable;
+	int int_enable, egsm_enable, wakeup_enable;
 	struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
 
 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
 	dev_dbg(&rhdev->dev, "%s%s\n", __func__,
 			(auto_stop ? " (auto-stop)" : ""));
 
-	/* Enable resume-detect interrupts if they work.
-	 * Then enter Global Suspend mode if _it_ works, still configured.
+	/* Start off by assuming Resume-Detect interrupts and EGSM work
+	 * and that remote wakeups should be enabled.
 	 */
 	egsm_enable = USBCMD_EGSM;
-	uhci->working_RD = 1;
+	uhci->RD_enable = 1;
 	int_enable = USBINTR_RESUME;
-	if (remote_wakeup_is_broken(uhci))
-		egsm_enable = 0;
-	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
+	wakeup_enable = 1;
+
+	/* In auto-stop mode wakeups must always be detected, but
+	 * Resume-Detect interrupts may be prohibited.  (In the absence
+	 * of CONFIG_PM, they are always disallowed.)
+	 */
+	if (auto_stop) {
+		if (!device_may_wakeup(&rhdev->dev))
+			int_enable = 0;
+
+	/* In bus-suspend mode wakeups may be disabled, but if they are
+	 * allowed then so are Resume-Detect interrupts.
+	 */
+	} else {
 #ifdef CONFIG_PM
-			(!auto_stop && !rhdev->do_remote_wakeup) ||
+		if (!rhdev->do_remote_wakeup)
+			wakeup_enable = 0;
 #endif
-			(auto_stop && !device_may_wakeup(&rhdev->dev)))
-		uhci->working_RD = int_enable = 0;
+	}
+
+	/* EGSM causes the root hub to echo a 'K' signal (resume) out any
+	 * port which requests a remote wakeup.  According to the USB spec,
+	 * every hub is supposed to do this.  But if we are ignoring
+	 * remote-wakeup requests anyway then there's no point to it.
+	 * We also shouldn't enable EGSM if it's broken.
+	 */
+	if (!wakeup_enable || global_suspend_mode_is_broken(uhci))
+		egsm_enable = 0;
+
+	/* If we're ignoring wakeup events then there's no reason to
+	 * enable Resume-Detect interrupts.  We also shouldn't enable
+	 * them if they are broken or disallowed.
+	 *
+	 * This logic may lead us to enabling RD but not EGSM.  The UHCI
+	 * spec foolishly says that RD works only when EGSM is on, but
+	 * there's no harm in enabling it anyway -- perhaps some chips
+	 * will implement it!
+	 */
+	if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) ||
+			!int_enable)
+		uhci->RD_enable = int_enable = 0;
 
 	outw(int_enable, uhci->io_addr + USBINTR);
 	outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
@@ -308,7 +341,11 @@
 
 	uhci->rh_state = new_state;
 	uhci->is_stopped = UHCI_IS_STOPPED;
-	uhci_to_hcd(uhci)->poll_rh = !int_enable;
+
+	/* If interrupts don't work and remote wakeup is enabled then
+	 * the suspended root hub needs to be polled.
+	 */
+	uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable);
 
 	uhci_scan_schedule(uhci);
 	uhci_fsbr_off(uhci);
@@ -344,9 +381,12 @@
 	 * for 20 ms.
 	 */
 	if (uhci->rh_state == UHCI_RH_SUSPENDED) {
+		unsigned egsm;
+
+		/* Keep EGSM on if it was set before */
+		egsm = inw(uhci->io_addr + USBCMD) & USBCMD_EGSM;
 		uhci->rh_state = UHCI_RH_RESUMING;
-		outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF,
-				uhci->io_addr + USBCMD);
+		outw(USBCMD_FGR | USBCMD_CF | egsm, uhci->io_addr + USBCMD);
 		spin_unlock_irq(&uhci->lock);
 		msleep(20);
 		spin_lock_irq(&uhci->lock);
@@ -801,8 +841,10 @@
 
 	spin_unlock_irq(&uhci->lock);
 
-	if (!uhci->working_RD) {
-		/* Suspended root hub needs to be polled */
+	/* If interrupts don't work and remote wakeup is enabled then
+	 * the suspended root hub needs to be polled.
+	 */
+	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
 		hcd->poll_rh = 1;
 		usb_hcd_poll_rh_status(hcd);
 	}
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 340d6ed..7d01c56 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -400,8 +400,9 @@
 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
 	unsigned int need_rescan:1;		/* Redo the schedule scan */
 	unsigned int dead:1;			/* Controller has died */
-	unsigned int working_RD:1;		/* Suspended root hub doesn't
-						   need to be polled */
+	unsigned int RD_enable:1;		/* Suspended root hub with
+						   Resume-Detect interrupts
+						   enabled */
 	unsigned int is_initialized:1;		/* Data structure is usable */
 	unsigned int fsbr_is_on:1;		/* FSBR is turned on */
 	unsigned int fsbr_is_wanted:1;		/* Does any URB want FSBR? */
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 11580e8..7aafd53 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -148,7 +148,7 @@
 
 /* Structure to hold all of our device specific stuff */
 struct ld_usb {
-	struct semaphore	sem;		/* locks this structure */
+	struct mutex		mutex;		/* locks this structure */
 	struct usb_interface*	intf;		/* save off the usb interface pointer */
 
 	int			open_count;	/* number of times this port has been opened */
@@ -319,7 +319,7 @@
 		return -ENODEV;
 
 	/* lock this device */
-	if (down_interruptible(&dev->sem))
+	if (mutex_lock_interruptible(&dev->mutex))
 		return -ERESTARTSYS;
 
 	/* allow opening only once */
@@ -358,7 +358,7 @@
 	file->private_data = dev;
 
 unlock_exit:
-	up(&dev->sem);
+	mutex_unlock(&dev->mutex);
 
 	return retval;
 }
@@ -378,7 +378,7 @@
 		goto exit;
 	}
 
-	if (down_interruptible(&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->mutex)) {
 		retval = -ERESTARTSYS;
 		goto exit;
 	}
@@ -389,7 +389,7 @@
 	}
 	if (dev->intf == NULL) {
 		/* the device was unplugged before the file was released */
-		up(&dev->sem);
+		mutex_unlock(&dev->mutex);
 		/* unlock here as ld_usb_delete frees dev */
 		ld_usb_delete(dev);
 		goto exit;
@@ -402,7 +402,7 @@
 	dev->open_count = 0;
 
 unlock_exit:
-	up(&dev->sem);
+	mutex_unlock(&dev->mutex);
 
 exit:
 	return retval;
@@ -448,7 +448,7 @@
 		goto exit;
 
 	/* lock this object */
-	if (down_interruptible(&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->mutex)) {
 		retval = -ERESTARTSYS;
 		goto exit;
 	}
@@ -505,7 +505,7 @@
 
 unlock_exit:
 	/* unlock the device */
-	up(&dev->sem);
+	mutex_unlock(&dev->mutex);
 
 exit:
 	return retval;
@@ -528,7 +528,7 @@
 		goto exit;
 
 	/* lock this object */
-	if (down_interruptible(&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->mutex)) {
 		retval = -ERESTARTSYS;
 		goto exit;
 	}
@@ -602,7 +602,7 @@
 
 unlock_exit:
 	/* unlock the device */
-	up(&dev->sem);
+	mutex_unlock(&dev->mutex);
 
 exit:
 	return retval;
@@ -651,7 +651,7 @@
 		dev_err(&intf->dev, "Out of memory\n");
 		goto exit;
 	}
-	init_MUTEX(&dev->sem);
+	mutex_init(&dev->mutex);
 	spin_lock_init(&dev->rbsl);
 	dev->intf = intf;
 	init_waitqueue_head(&dev->read_wait);
@@ -765,15 +765,15 @@
 	/* give back our minor */
 	usb_deregister_dev(intf, &ld_usb_class);
 
-	down(&dev->sem);
+	mutex_lock(&dev->mutex);
 
 	/* if the device is not opened, then we clean up right now */
 	if (!dev->open_count) {
-		up(&dev->sem);
+		mutex_unlock(&dev->mutex);
 		ld_usb_delete(dev);
 	} else {
 		dev->intf = NULL;
-		up(&dev->sem);
+		mutex_unlock(&dev->mutex);
 	}
 
 	dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index a519838..742be3c 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -79,30 +79,10 @@
 /* set up all urbs so they can be used with either bulk or interrupt */
 #define	INTERRUPT_RATE		1	/* msec/transfer */
 
-#define xprintk(tdev,level,fmt,args...) \
-	dev_printk(level ,  &(tdev)->intf->dev ,  fmt ,  ## args)
-
-#ifdef DEBUG
-#define DBG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DBG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDBG DBG
-#else
-#define VDBG(dev,fmt,args...) \
-	do { } while (0)
-#endif	/* VERBOSE */
-
-#define ERROR(dev,fmt,args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
+#define ERROR(tdev, fmt, args...) \
+	dev_err(&(tdev)->intf->dev , fmt , ## args)
+#define WARN(tdev, fmt, args...) \
+	dev_warn(&(tdev)->intf->dev , fmt , ## args)
 
 /*-------------------------------------------------------------------------*/
 
@@ -236,7 +216,7 @@
 
 static unsigned pattern = 0;
 module_param (pattern, uint, S_IRUGO);
-// MODULE_PARM_DESC (pattern, "i/o pattern (0 == zeroes)");
+MODULE_PARM_DESC(pattern, "i/o pattern (0 == zeroes)");
 
 static inline void simple_fill_buf (struct urb *urb)
 {
@@ -257,7 +237,7 @@
 	}
 }
 
-static inline int simple_check_buf (struct urb *urb)
+static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
 {
 	unsigned	i;
 	u8		expected;
@@ -285,7 +265,7 @@
 		}
 		if (*buf == expected)
 			continue;
-		dbg ("buf[%d] = %d (not %d)", i, *buf, expected);
+		ERROR(tdev, "buf[%d] = %d (not %d)\n", i, *buf, expected);
 		return -EINVAL;
 	}
 	return 0;
@@ -299,6 +279,7 @@
 }
 
 static int simple_io (
+	struct usbtest_dev	*tdev,
 	struct urb		*urb,
 	int			iterations,
 	int			vary,
@@ -324,7 +305,7 @@
 		retval = urb->status;
 		urb->dev = udev;
 		if (retval == 0 && usb_pipein (urb->pipe))
-			retval = simple_check_buf (urb);
+			retval = simple_check_buf(tdev, urb);
 
 		if (vary) {
 			int	len = urb->transfer_buffer_length;
@@ -341,7 +322,7 @@
 	urb->transfer_buffer_length = max;
 
 	if (expected != retval)
-		dev_dbg (&udev->dev,
+		dev_err(&udev->dev,
 			"%s failed, iterations left %d, status %d (not %d)\n",
 				label, iterations, retval, expected);
 	return retval;
@@ -357,7 +338,7 @@
 static void free_sglist (struct scatterlist *sg, int nents)
 {
 	unsigned		i;
-	
+
 	if (!sg)
 		return;
 	for (i = 0; i < nents; i++) {
@@ -415,7 +396,7 @@
 }
 
 static int perform_sglist (
-	struct usb_device	*udev,
+	struct usbtest_dev	*tdev,
 	unsigned		iterations,
 	int			pipe,
 	struct usb_sg_request	*req,
@@ -423,6 +404,7 @@
 	int			nents
 )
 {
+	struct usb_device	*udev = testdev_to_usbdev(tdev);
 	int			retval = 0;
 
 	while (retval == 0 && iterations-- > 0) {
@@ -431,7 +413,7 @@
 					? (INTERRUPT_RATE << 3)
 					: INTERRUPT_RATE,
 				sg, nents, 0, GFP_KERNEL);
-		
+
 		if (retval)
 			break;
 		usb_sg_wait (req);
@@ -446,7 +428,8 @@
 	// failure if retval is as we expected ...
 
 	if (retval)
-		dbg ("perform_sglist failed, iterations left %d, status %d",
+		ERROR(tdev, "perform_sglist failed, "
+				"iterations left %d, status %d\n",
 				iterations, retval);
 	return retval;
 }
@@ -505,28 +488,28 @@
 			alternate);
 }
 
-static int is_good_config (char *buf, int len)
+static int is_good_config(struct usbtest_dev *tdev, int len)
 {
 	struct usb_config_descriptor	*config;
-	
+
 	if (len < sizeof *config)
 		return 0;
-	config = (struct usb_config_descriptor *) buf;
+	config = (struct usb_config_descriptor *) tdev->buf;
 
 	switch (config->bDescriptorType) {
 	case USB_DT_CONFIG:
 	case USB_DT_OTHER_SPEED_CONFIG:
 		if (config->bLength != 9) {
-			dbg ("bogus config descriptor length");
+			ERROR(tdev, "bogus config descriptor length\n");
 			return 0;
 		}
 		/* this bit 'must be 1' but often isn't */
 		if (!realworld && !(config->bmAttributes & 0x80)) {
-			dbg ("high bit of config attributes not set");
+			ERROR(tdev, "high bit of config attributes not set\n");
 			return 0;
 		}
 		if (config->bmAttributes & 0x1f) {	/* reserved == 0 */
-			dbg ("reserved config bits set");
+			ERROR(tdev, "reserved config bits set\n");
 			return 0;
 		}
 		break;
@@ -538,7 +521,7 @@
 		return 1;
 	if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE)		/* max partial read */
 		return 1;
-	dbg ("bogus config descriptor read size");
+	ERROR(tdev, "bogus config descriptor read size\n");
 	return 0;
 }
 
@@ -571,7 +554,7 @@
 		/* 9.2.3 constrains the range here */
 		alt = iface->altsetting [i].desc.bAlternateSetting;
 		if (alt < 0 || alt >= iface->num_altsetting) {
-			dev_dbg (&iface->dev,
+			dev_err(&iface->dev,
 					"invalid alt [%d].bAltSetting = %d\n",
 					i, alt);
 		}
@@ -583,7 +566,7 @@
 		/* [9.4.10] set_interface */
 		retval = set_altsetting (dev, alt);
 		if (retval) {
-			dev_dbg (&iface->dev, "can't set_interface = %d, %d\n",
+			dev_err(&iface->dev, "can't set_interface = %d, %d\n",
 					alt, retval);
 			return retval;
 		}
@@ -591,7 +574,7 @@
 		/* [9.4.4] get_interface always works */
 		retval = get_altsetting (dev);
 		if (retval != alt) {
-			dev_dbg (&iface->dev, "get alt should be %d, was %d\n",
+			dev_err(&iface->dev, "get alt should be %d, was %d\n",
 					alt, retval);
 			return (retval < 0) ? retval : -EDOM;
 		}
@@ -611,7 +594,7 @@
 				USB_DIR_IN | USB_RECIP_DEVICE,
 				0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
 		if (retval != 1 || dev->buf [0] != expected) {
-			dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n",
+			dev_err(&iface->dev, "get config --> %d %d (1 %d)\n",
 				retval, dev->buf[0], expected);
 			return (retval < 0) ? retval : -EDOM;
 		}
@@ -621,7 +604,7 @@
 	retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0,
 			dev->buf, sizeof udev->descriptor);
 	if (retval != sizeof udev->descriptor) {
-		dev_dbg (&iface->dev, "dev descriptor --> %d\n", retval);
+		dev_err(&iface->dev, "dev descriptor --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
@@ -629,8 +612,8 @@
 	for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
 		retval = usb_get_descriptor (udev, USB_DT_CONFIG, i,
 				dev->buf, TBUF_SIZE);
-		if (!is_good_config (dev->buf, retval)) {
-			dev_dbg (&iface->dev,
+		if (!is_good_config(dev, retval)) {
+			dev_err(&iface->dev,
 					"config [%d] descriptor --> %d\n",
 					i, retval);
 			return (retval < 0) ? retval : -EDOM;
@@ -650,14 +633,14 @@
 				sizeof (struct usb_qualifier_descriptor));
 		if (retval == -EPIPE) {
 			if (udev->speed == USB_SPEED_HIGH) {
-				dev_dbg (&iface->dev,
+				dev_err(&iface->dev,
 						"hs dev qualifier --> %d\n",
 						retval);
 				return (retval < 0) ? retval : -EDOM;
 			}
 			/* usb2.0 but not high-speed capable; fine */
 		} else if (retval != sizeof (struct usb_qualifier_descriptor)) {
-			dev_dbg (&iface->dev, "dev qualifier --> %d\n", retval);
+			dev_err(&iface->dev, "dev qualifier --> %d\n", retval);
 			return (retval < 0) ? retval : -EDOM;
 		} else
 			d = (struct usb_qualifier_descriptor *) dev->buf;
@@ -669,8 +652,8 @@
 				retval = usb_get_descriptor (udev,
 					USB_DT_OTHER_SPEED_CONFIG, i,
 					dev->buf, TBUF_SIZE);
-				if (!is_good_config (dev->buf, retval)) {
-					dev_dbg (&iface->dev,
+				if (!is_good_config(dev, retval)) {
+					dev_err(&iface->dev,
 						"other speed config --> %d\n",
 						retval);
 					return (retval < 0) ? retval : -EDOM;
@@ -683,7 +666,7 @@
 	/* [9.4.5] get_status always works */
 	retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf);
 	if (retval != 2) {
-		dev_dbg (&iface->dev, "get dev status --> %d\n", retval);
+		dev_err(&iface->dev, "get dev status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
@@ -693,11 +676,11 @@
 	retval = usb_get_status (udev, USB_RECIP_INTERFACE,
 			iface->altsetting [0].desc.bInterfaceNumber, dev->buf);
 	if (retval != 2) {
-		dev_dbg (&iface->dev, "get interface status --> %d\n", retval);
+		dev_err(&iface->dev, "get interface status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 	// FIXME get status for each endpoint in the interface
-	
+
 	return 0;
 }
 
@@ -752,8 +735,9 @@
 	 */
 	if (subcase->number > 0) {
 		if ((subcase->number - ctx->last) != 1) {
-			dbg ("subcase %d completed out of order, last %d",
-					subcase->number, ctx->last);
+			ERROR(ctx->dev,
+				"subcase %d completed out of order, last %d\n",
+				subcase->number, ctx->last);
 			status = -EDOM;
 			ctx->last = subcase->number;
 			goto error;
@@ -777,7 +761,7 @@
 		else if (subcase->number == 12 && status == -EPIPE)
 			status = 0;
 		else
-			dbg ("subtest %d error, status %d",
+			ERROR(ctx->dev, "subtest %d error, status %d\n",
 					subcase->number, status);
 	}
 
@@ -788,9 +772,12 @@
 			int		i;
 
 			ctx->status = status;
-			info ("control queue %02x.%02x, err %d, %d left",
+			ERROR(ctx->dev, "control queue %02x.%02x, err %d, "
+					"%d left, subcase %d, len %d/%d\n",
 					reqp->bRequestType, reqp->bRequest,
-					status, ctx->count);
+					status, ctx->count, subcase->number,
+					urb->actual_length,
+					urb->transfer_buffer_length);
 
 			/* FIXME this "unlink everything" exit route should
 			 * be a separate test case.
@@ -799,7 +786,8 @@
 			/* unlink whatever's still pending */
 			for (i = 1; i < ctx->param->sglen; i++) {
 				struct urb	*u = ctx->urb [
-	(i + subcase->number) % ctx->param->sglen];
+						(i + subcase->number)
+						% ctx->param->sglen];
 
 				if (u == urb || !u->dev)
 					continue;
@@ -812,7 +800,8 @@
 				case -EIDRM:
 					continue;
 				default:
-					dbg ("urb unlink --> %d", status);
+					ERROR(ctx->dev, "urb unlink --> %d\n",
+							status);
 				}
 			}
 			status = ctx->status;
@@ -822,14 +811,15 @@
 	/* resubmit if we need to, else mark this as done */
 	if ((status == 0) && (ctx->pending < ctx->count)) {
 		if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
-			dbg ("can't resubmit ctrl %02x.%02x, err %d",
+			ERROR(ctx->dev,
+				"can't resubmit ctrl %02x.%02x, err %d\n",
 				reqp->bRequestType, reqp->bRequest, status);
 			urb->dev = NULL;
 		} else
 			ctx->pending++;
 	} else
 		urb->dev = NULL;
-	
+
 	/* signal completion when nothing's queued */
 	if (ctx->pending == 0)
 		complete (&ctx->complete);
@@ -918,11 +908,11 @@
 			req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
 			// interface == 0
 			len = sizeof (struct usb_interface_descriptor);
-			expected = EPIPE;
+			expected = -EPIPE;
 			break;
 		// NOTE: two consecutive stalls in the queue here.
 		// that tests fault recovery a bit more aggressively.
-		case 8:		// clear endpoint halt (USUALLY STALLS)
+		case 8:		// clear endpoint halt (MAY STALL)
 			req.bRequest = USB_REQ_CLEAR_FEATURE;
 			req.bRequestType = USB_RECIP_ENDPOINT;
 			// wValue 0 == ep halt
@@ -965,7 +955,7 @@
 			break;
 		case 14:	// short read; try to fill the last packet
 			req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0);
-			// device descriptor size == 18 bytes 
+			/* device descriptor size == 18 bytes */
 			len = udev->descriptor.bMaxPacketSize0;
 			switch (len) {
 			case 8:		len = 24; break;
@@ -974,7 +964,7 @@
 			expected = -EREMOTEIO;
 			break;
 		default:
-			err ("bogus number of ctrl queue testcases!");
+			ERROR(dev, "bogus number of ctrl queue testcases!\n");
 			context.status = -EINVAL;
 			goto cleanup;
 		}
@@ -1003,7 +993,7 @@
 	for (i = 0; i < param->sglen; i++) {
 		context.status = usb_submit_urb (urb [i], GFP_ATOMIC);
 		if (context.status != 0) {
-			dbg ("can't submit urb[%d], status %d",
+			ERROR(dev, "can't submit urb[%d], status %d\n",
 					i, context.status);
 			context.count = context.pending;
 			break;
@@ -1070,7 +1060,7 @@
 	 * due to errors, or is just NAKing requests.
 	 */
 	if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) {
-		dev_dbg (&dev->intf->dev, "submit fail %d\n", retval);
+		dev_err(&dev->intf->dev, "submit fail %d\n", retval);
 		return retval;
 	}
 
@@ -1087,13 +1077,13 @@
 			 * "normal" drivers would prevent resubmission, but
 			 * since we're testing unlink paths, we can't.
 			 */
-			dev_dbg (&dev->intf->dev, "unlink retry\n");
+			ERROR(dev,  "unlink retry\n");
 			goto retry;
 		}
 	} else
 		usb_kill_urb (urb);
 	if (!(retval == 0 || retval == -EINPROGRESS)) {
-		dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval);
+		dev_err(&dev->intf->dev, "unlink fail %d\n", retval);
 		return retval;
 	}
 
@@ -1121,7 +1111,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int verify_not_halted (int ep, struct urb *urb)
+static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
 {
 	int	retval;
 	u16	status;
@@ -1129,20 +1119,21 @@
 	/* shouldn't look or act halted */
 	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
 	if (retval < 0) {
-		dbg ("ep %02x couldn't get no-halt status, %d", ep, retval);
+		ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n",
+				ep, retval);
 		return retval;
 	}
 	if (status != 0) {
-		dbg ("ep %02x bogus status: %04x != 0", ep, status);
+		ERROR(tdev, "ep %02x bogus status: %04x != 0\n", ep, status);
 		return -EINVAL;
 	}
-	retval = simple_io (urb, 1, 0, 0, __func__);
+	retval = simple_io(tdev, urb, 1, 0, 0, __func__);
 	if (retval != 0)
 		return -EINVAL;
 	return 0;
 }
 
-static int verify_halted (int ep, struct urb *urb)
+static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
 {
 	int	retval;
 	u16	status;
@@ -1150,29 +1141,30 @@
 	/* should look and act halted */
 	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
 	if (retval < 0) {
-		dbg ("ep %02x couldn't get halt status, %d", ep, retval);
+		ERROR(tdev, "ep %02x couldn't get halt status, %d\n",
+				ep, retval);
 		return retval;
 	}
 	le16_to_cpus(&status);
 	if (status != 1) {
-		dbg ("ep %02x bogus status: %04x != 1", ep, status);
+		ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status);
 		return -EINVAL;
 	}
-	retval = simple_io (urb, 1, 0, -EPIPE, __func__);
+	retval = simple_io(tdev, urb, 1, 0, -EPIPE, __func__);
 	if (retval != -EPIPE)
 		return -EINVAL;
-	retval = simple_io (urb, 1, 0, -EPIPE, "verify_still_halted");
+	retval = simple_io(tdev, urb, 1, 0, -EPIPE, "verify_still_halted");
 	if (retval != -EPIPE)
 		return -EINVAL;
 	return 0;
 }
 
-static int test_halt (int ep, struct urb *urb)
+static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb)
 {
 	int	retval;
 
 	/* shouldn't look or act halted now */
-	retval = verify_not_halted (ep, urb);
+	retval = verify_not_halted(tdev, ep, urb);
 	if (retval < 0)
 		return retval;
 
@@ -1182,20 +1174,20 @@
 			USB_ENDPOINT_HALT, ep,
 			NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval < 0) {
-		dbg ("ep %02x couldn't set halt, %d", ep, retval);
+		ERROR(tdev, "ep %02x couldn't set halt, %d\n", ep, retval);
 		return retval;
 	}
-	retval = verify_halted (ep, urb);
+	retval = verify_halted(tdev, ep, urb);
 	if (retval < 0)
 		return retval;
 
 	/* clear halt (tests API + protocol), verify it worked */
 	retval = usb_clear_halt (urb->dev, urb->pipe);
 	if (retval < 0) {
-		dbg ("ep %02x couldn't clear halt, %d", ep, retval);
+		ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval);
 		return retval;
 	}
-	retval = verify_not_halted (ep, urb);
+	retval = verify_not_halted(tdev, ep, urb);
 	if (retval < 0)
 		return retval;
 
@@ -1217,7 +1209,7 @@
 	if (dev->in_pipe) {
 		ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN;
 		urb->pipe = dev->in_pipe;
-		retval = test_halt (ep, urb);
+		retval = test_halt(dev, ep, urb);
 		if (retval < 0)
 			goto done;
 	}
@@ -1225,7 +1217,7 @@
 	if (dev->out_pipe) {
 		ep = usb_pipeendpoint (dev->out_pipe);
 		urb->pipe = dev->out_pipe;
-		retval = test_halt (ep, urb);
+		retval = test_halt(dev, ep, urb);
 	}
 done:
 	simple_free_urb (urb);
@@ -1275,7 +1267,7 @@
 		if (retval != len) {
 			what = "write";
 			if (retval >= 0) {
-				INFO(dev, "ctrl_out, wlen %d (expected %d)\n",
+				ERROR(dev, "ctrl_out, wlen %d (expected %d)\n",
 						retval, len);
 				retval = -EBADMSG;
 			}
@@ -1289,7 +1281,7 @@
 		if (retval != len) {
 			what = "read";
 			if (retval >= 0) {
-				INFO(dev, "ctrl_out, rlen %d (expected %d)\n",
+				ERROR(dev, "ctrl_out, rlen %d (expected %d)\n",
 						retval, len);
 				retval = -EBADMSG;
 			}
@@ -1299,7 +1291,7 @@
 		/* fail if we can't verify */
 		for (j = 0; j < len; j++) {
 			if (buf [j] != (u8) (i + j)) {
-				INFO (dev, "ctrl_out, byte %d is %d not %d\n",
+				ERROR(dev, "ctrl_out, byte %d is %d not %d\n",
 					j, buf [j], (u8) i + j);
 				retval = -EBADMSG;
 				break;
@@ -1321,7 +1313,7 @@
 	}
 
 	if (retval < 0)
-		INFO (dev, "ctrl_out %s failed, code %d, count %d\n",
+		ERROR (dev, "ctrl_out %s failed, code %d, count %d\n",
 			what, retval, i);
 
 	kfree (buf);
@@ -1366,7 +1358,7 @@
 		case 0:
 			goto done;
 		default:
-			dev_dbg (&ctx->dev->intf->dev,
+			dev_err(&ctx->dev->intf->dev,
 					"iso resubmit err %d\n",
 					status);
 			/* FALLTHROUGH */
@@ -1381,7 +1373,7 @@
 	ctx->pending--;
 	if (ctx->pending == 0) {
 		if (ctx->errors)
-			dev_dbg (&ctx->dev->intf->dev,
+			dev_err(&ctx->dev->intf->dev,
 				"iso test, %lu errors out of %lu\n",
 				ctx->errors, ctx->packet_count);
 		complete (&ctx->done);
@@ -1458,7 +1450,7 @@
 
 	memset (urbs, 0, sizeof urbs);
 	udev = testdev_to_usbdev (dev);
-	dev_dbg (&dev->intf->dev,
+	dev_info(&dev->intf->dev,
 		"... iso period %d %sframes, wMaxPacket %04x\n",
 		1 << (desc->bInterval - 1),
 		(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
@@ -1475,7 +1467,7 @@
 		urbs [i]->context = &context;
 	}
 	packets *= param->iterations;
-	dev_dbg (&dev->intf->dev,
+	dev_info(&dev->intf->dev,
 		"... total %lu msec (%lu packets)\n",
 		(packets * (1 << (desc->bInterval - 1)))
 			/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
@@ -1537,6 +1529,13 @@
  * except indirectly by consuming USB bandwidth and CPU resources for test
  * threads and request completion.  But the only way to know that for sure
  * is to test when HC queues are in use by many devices.
+ *
+ * WARNING:  Because usbfs grabs udev->dev.sem before calling this ioctl(),
+ * it locks out usbcore in certain code paths.  Notably, if you disconnect
+ * the device-under-test, khubd will wait block forever waiting for the
+ * ioctl to complete ... so that usb_disconnect() can abort the pending
+ * urbs and then call usbtest_disconnect().  To abort a test, you're best
+ * off just killing the userspace task and waiting for it to exit.
  */
 
 static int
@@ -1575,7 +1574,7 @@
 	 * altsettings; force a default so most tests don't need to check.
 	 */
 	if (dev->info->alt >= 0) {
-	    	int	res;
+		int	res;
 
 		if (intf->altsetting->desc.bInterfaceNumber) {
 			mutex_unlock(&dev->lock);
@@ -1604,7 +1603,7 @@
 	switch (param->test_num) {
 
 	case 0:
-		dev_dbg (&intf->dev, "TEST 0:  NOP\n");
+		dev_info(&intf->dev, "TEST 0:  NOP\n");
 		retval = 0;
 		break;
 
@@ -1612,7 +1611,7 @@
 	case 1:
 		if (dev->out_pipe == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 				"TEST 1:  write %d bytes %u times\n",
 				param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
@@ -1621,13 +1620,13 @@
 			break;
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
-		retval = simple_io (urb, param->iterations, 0, 0, "test1");
+		retval = simple_io(dev, urb, param->iterations, 0, 0, "test1");
 		simple_free_urb (urb);
 		break;
 	case 2:
 		if (dev->in_pipe == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 				"TEST 2:  read %d bytes %u times\n",
 				param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
@@ -1636,13 +1635,13 @@
 			break;
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
-		retval = simple_io (urb, param->iterations, 0, 0, "test2");
+		retval = simple_io(dev, urb, param->iterations, 0, 0, "test2");
 		simple_free_urb (urb);
 		break;
 	case 3:
 		if (dev->out_pipe == 0 || param->vary == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 				"TEST 3:  write/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
@@ -1651,14 +1650,14 @@
 			break;
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
-		retval = simple_io (urb, param->iterations, param->vary,
+		retval = simple_io(dev, urb, param->iterations, param->vary,
 					0, "test3");
 		simple_free_urb (urb);
 		break;
 	case 4:
 		if (dev->in_pipe == 0 || param->vary == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 				"TEST 4:  read/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
@@ -1667,7 +1666,7 @@
 			break;
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
-		retval = simple_io (urb, param->iterations, param->vary,
+		retval = simple_io(dev, urb, param->iterations, param->vary,
 					0, "test4");
 		simple_free_urb (urb);
 		break;
@@ -1676,7 +1675,7 @@
 	case 5:
 		if (dev->out_pipe == 0 || param->sglen == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 			"TEST 5:  write %d sglists %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
@@ -1686,7 +1685,7 @@
 			break;
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
-		retval = perform_sglist (udev, param->iterations, dev->out_pipe,
+		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
 				&req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
@@ -1694,7 +1693,7 @@
 	case 6:
 		if (dev->in_pipe == 0 || param->sglen == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 			"TEST 6:  read %d sglists %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
@@ -1704,14 +1703,14 @@
 			break;
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
-		retval = perform_sglist (udev, param->iterations, dev->in_pipe,
+		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
 				&req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
 	case 7:
 		if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 			"TEST 7:  write/%d %d sglists %d entries 0..%d bytes\n",
 				param->vary, param->iterations,
 				param->sglen, param->length);
@@ -1721,14 +1720,14 @@
 			break;
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
-		retval = perform_sglist (udev, param->iterations, dev->out_pipe,
+		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
 				&req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
 	case 8:
 		if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 			"TEST 8:  read/%d %d sglists %d entries 0..%d bytes\n",
 				param->vary, param->iterations,
 				param->sglen, param->length);
@@ -1738,7 +1737,7 @@
 			break;
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
-		retval = perform_sglist (udev, param->iterations, dev->in_pipe,
+		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
 				&req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
@@ -1746,13 +1745,14 @@
 	/* non-queued sanity tests for control (chapter 9 subset) */
 	case 9:
 		retval = 0;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 			"TEST 9:  ch9 (subset) control tests, %d times\n",
 				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
 			retval = ch9_postconfig (dev);
 		if (retval)
-			dbg ("ch9 subset failed, iterations left %d", i);
+			dev_err(&intf->dev, "ch9 subset failed, "
+					"iterations left %d\n", i);
 		break;
 
 	/* queued control messaging */
@@ -1760,7 +1760,7 @@
 		if (param->sglen == 0)
 			break;
 		retval = 0;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 				"TEST 10:  queue %d control calls, %d times\n",
 				param->sglen,
 				param->iterations);
@@ -1772,26 +1772,26 @@
 		if (dev->in_pipe == 0 || !param->length)
 			break;
 		retval = 0;
-		dev_dbg (&intf->dev, "TEST 11:  unlink %d reads of %d\n",
+		dev_info(&intf->dev, "TEST 11:  unlink %d reads of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
 			retval = unlink_simple (dev, dev->in_pipe,
 						param->length);
 		if (retval)
-			dev_dbg (&intf->dev, "unlink reads failed %d, "
+			dev_err(&intf->dev, "unlink reads failed %d, "
 				"iterations left %d\n", retval, i);
 		break;
 	case 12:
 		if (dev->out_pipe == 0 || !param->length)
 			break;
 		retval = 0;
-		dev_dbg (&intf->dev, "TEST 12:  unlink %d writes of %d\n",
+		dev_info(&intf->dev, "TEST 12:  unlink %d writes of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
 			retval = unlink_simple (dev, dev->out_pipe,
 						param->length);
 		if (retval)
-			dev_dbg (&intf->dev, "unlink writes failed %d, "
+			dev_err(&intf->dev, "unlink writes failed %d, "
 				"iterations left %d\n", retval, i);
 		break;
 
@@ -1800,24 +1800,24 @@
 		if (dev->out_pipe == 0 && dev->in_pipe == 0)
 			break;
 		retval = 0;
-		dev_dbg (&intf->dev, "TEST 13:  set/clear %d halts\n",
+		dev_info(&intf->dev, "TEST 13:  set/clear %d halts\n",
 				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
 			retval = halt_simple (dev);
-		
+
 		if (retval)
-			DBG (dev, "halts failed, iterations left %d\n", i);
+			ERROR(dev, "halts failed, iterations left %d\n", i);
 		break;
 
 	/* control write tests */
 	case 14:
 		if (!dev->info->ctrl_out)
 			break;
-		dev_dbg (&intf->dev, "TEST 14:  %d ep0out, %d..%d vary %d\n",
+		dev_info(&intf->dev, "TEST 14:  %d ep0out, %d..%d vary %d\n",
 				param->iterations,
 				realworld ? 1 : 0, param->length,
 				param->vary);
-		retval = ctrl_out (dev, param->iterations, 
+		retval = ctrl_out(dev, param->iterations,
 				param->length, param->vary);
 		break;
 
@@ -1825,7 +1825,7 @@
 	case 15:
 		if (dev->out_iso_pipe == 0 || param->sglen == 0)
 			break;
-		dev_dbg (&intf->dev, 
+		dev_info(&intf->dev,
 			"TEST 15:  write %d iso, %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
@@ -1838,7 +1838,7 @@
 	case 16:
 		if (dev->in_iso_pipe == 0 || param->sglen == 0)
 			break;
-		dev_dbg (&intf->dev,
+		dev_info(&intf->dev,
 			"TEST 16:  read %d iso, %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
@@ -1898,7 +1898,8 @@
 			return -ENODEV;
 		if (product && le16_to_cpu(udev->descriptor.idProduct) != (u16)product)
 			return -ENODEV;
-		dbg ("matched module params, vend=0x%04x prod=0x%04x",
+		dev_info(&intf->dev, "matched module params, "
+					"vend=0x%04x prod=0x%04x\n",
 				le16_to_cpu(udev->descriptor.idVendor),
 				le16_to_cpu(udev->descriptor.idProduct));
 	}
@@ -1940,7 +1941,8 @@
 
 			status = get_endpoints (dev, intf);
 			if (status < 0) {
-				dbg ("couldn't get endpoints, %d\n", status);
+				WARN(dev, "couldn't get endpoints, %d\n",
+						status);
 				return status;
 			}
 			/* may find bulk or ISO pipes */
@@ -2082,21 +2084,9 @@
 };
 #endif
 
-// FIXME remove this 
-static struct usbtest_info hact_info = {
-	.name		= "FX2/hact",
-	//.ep_in		= 6,
-	.ep_out		= 2,
-	.alt		= -1,
-};
-
 
 static struct usb_device_id id_table [] = {
 
-	{ USB_DEVICE (0x0547, 0x1002),
-		.driver_info = (unsigned long) &hact_info,
-		},
-
 	/*-------------------------------------------------------------*/
 
 	/* EZ-USB devices which download firmware to replace (or in our
@@ -2185,7 +2175,7 @@
 {
 #ifdef GENERIC
 	if (vendor)
-		dbg ("params: vend=0x%04x prod=0x%04x", vendor, product);
+		pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product);
 #endif
 	return usb_register (&usbtest_driver);
 }
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 9b1bb34..db6f97a 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -147,7 +147,7 @@
  */
 static int serial_buf_data_avail(struct circ_buf *cb)
 {
-	return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE);
+	return CIRC_CNT(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
 }
 
 /*
@@ -171,7 +171,7 @@
 		cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1);
 		buf += c;
 		count -= c;
-		ret= c;
+		ret = c;
 	}
 	return ret;
 }
@@ -197,7 +197,7 @@
 		cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1);
 		buf += c;
 		count -= c;
-		ret= c;
+		ret = c;
 	}
 	return ret;
 }
@@ -208,7 +208,7 @@
 {
 	int count, result;
 	struct aircable_private *priv = usb_get_serial_port_data(port);
-	unsigned char* buf;
+	unsigned char *buf;
 	__le16 *dbuf;
 	dbg("%s - port %d", __func__, port->number);
 	if (port->write_urb_busy)
@@ -229,7 +229,8 @@
 	buf[1] = TX_HEADER_1;
 	dbuf = (__le16 *)&buf[2];
 	*dbuf = cpu_to_le16((u16)count);
-	serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
+	serial_buf_get(priv->tx_buf, buf + HCI_HEADER_LENGTH,
+							MAX_HCI_FRAMESIZE);
 
 	memcpy(port->write_urb->transfer_buffer, buf,
 	       count + HCI_HEADER_LENGTH);
@@ -261,7 +262,7 @@
 	struct tty_struct *tty;
 	unsigned char *data;
 	int count;
-	if (priv->rx_flags & THROTTLED){
+	if (priv->rx_flags & THROTTLED) {
 		if (priv->rx_flags & ACTUALLY_THROTTLED)
 			schedule_work(&priv->rx_work);
 		return;
@@ -282,10 +283,10 @@
 	count = min(64, serial_buf_data_avail(priv->rx_buf));
 
 	if (count <= 0)
-		return; //We have finished sending everything.
+		return; /* We have finished sending everything. */
 
 	tty_prepare_flip_string(tty, &data, count);
-	if (!data){
+	if (!data) {
 		err("%s- kzalloc(%d) failed.", __func__, count);
 		return;
 	}
@@ -304,9 +305,10 @@
 static int aircable_probe(struct usb_serial *serial,
 			  const struct usb_device_id *id)
 {
-	struct usb_host_interface *iface_desc = serial->interface->cur_altsetting;
+	struct usb_host_interface *iface_desc = serial->interface->
+								cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
-	int num_bulk_out=0;
+	int num_bulk_out = 0;
 	int i;
 
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
@@ -325,13 +327,13 @@
 	return 0;
 }
 
-static int aircable_attach (struct usb_serial *serial)
+static int aircable_attach(struct usb_serial *serial)
 {
 	struct usb_serial_port *port = serial->port[0];
 	struct aircable_private *priv;
 
 	priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
-	if (!priv){
+	if (!priv) {
 		err("%s- kmalloc(%Zd) failed.", __func__,
 			sizeof(struct aircable_private));
 		return -ENOMEM;
@@ -392,7 +394,7 @@
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, source);
 
-	if (!count){
+	if (!count) {
 		dbg("%s - write request of 0 bytes", __func__);
 		return count;
 	}
@@ -418,31 +420,31 @@
 
 	/* This has been taken from cypress_m8.c cypress_write_int_callback */
 	switch (status) {
-		case 0:
-			/* success */
-			break;
-		case -ECONNRESET:
-		case -ENOENT:
-		case -ESHUTDOWN:
-			/* this urb is terminated, clean up */
-			dbg("%s - urb shutting down with status: %d",
-			    __func__, status);
-			port->write_urb_busy = 0;
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+		    __func__, status);
+		port->write_urb_busy = 0;
+		return;
+	default:
+		/* error in the urb, so we have to resubmit it */
+		dbg("%s - Overflow in write", __func__);
+		dbg("%s - nonzero write bulk status received: %d",
+		    __func__, status);
+		port->write_urb->transfer_buffer_length = 1;
+		port->write_urb->dev = port->serial->dev;
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result)
+			dev_err(&urb->dev->dev,
+			    "%s - failed resubmitting write urb, error %d\n",
+							__func__, result);
+		else
 			return;
-		default:
-			/* error in the urb, so we have to resubmit it */
-			dbg("%s - Overflow in write", __func__);
-			dbg("%s - nonzero write bulk status received: %d",
-			    __func__, status);
-			port->write_urb->transfer_buffer_length = 1;
-			port->write_urb->dev = port->serial->dev;
-			result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-			if (result)
-				dev_err(&urb->dev->dev,
-					"%s - failed resubmitting write urb, error %d\n",
-					__func__, result);
-			else
-				return;
 	}
 
 	port->write_urb_busy = 0;
@@ -472,11 +474,11 @@
 			dbg("%s - caught -EPROTO, resubmitting the urb",
 			    __func__);
 			usb_fill_bulk_urb(port->read_urb, port->serial->dev,
-					  usb_rcvbulkpipe(port->serial->dev,
-					  		  port->bulk_in_endpointAddress),
-					  port->read_urb->transfer_buffer,
-					  port->read_urb->transfer_buffer_length,
-					  aircable_read_bulk_callback, port);
+				usb_rcvbulkpipe(port->serial->dev,
+					port->bulk_in_endpointAddress),
+				port->read_urb->transfer_buffer,
+				port->read_urb->transfer_buffer_length,
+				aircable_read_bulk_callback, port);
 
 			result = usb_submit_urb(urb, GFP_ATOMIC);
 			if (result)
@@ -490,7 +492,7 @@
 	}
 
 	usb_serial_debug_data(debug, &port->dev, __func__,
-				urb->actual_length,urb->transfer_buffer);
+				urb->actual_length, urb->transfer_buffer);
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
@@ -507,9 +509,9 @@
 			no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
 
 			if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
-				no_packages+=1;
+				no_packages++;
 
-			for (i = 0; i < no_packages ;i++) {
+			for (i = 0; i < no_packages; i++) {
 				if (remaining > (HCI_COMPLETE_FRAME))
 					package_length = HCI_COMPLETE_FRAME;
 				else
@@ -529,7 +531,7 @@
 	if (port->open_count) {
 		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
 				  usb_rcvbulkpipe(port->serial->dev,
-				  		  port->bulk_in_endpointAddress),
+					  port->bulk_in_endpointAddress),
 				  port->read_urb->transfer_buffer,
 				  port->read_urb->transfer_buffer_length,
 				  aircable_read_bulk_callback, port);
@@ -602,7 +604,7 @@
 	.unthrottle =		aircable_unthrottle,
 };
 
-static int __init aircable_init (void)
+static int __init aircable_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&aircable_device);
@@ -619,7 +621,7 @@
 	return retval;
 }
 
-static void __exit aircable_exit (void)
+static void __exit aircable_exit(void)
 {
 	usb_deregister(&aircable_driver);
 	usb_serial_deregister(&aircable_device);
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 725b6b9..0798c14 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -68,8 +68,9 @@
 			val |= 0x02;
 
 		return usb_control_msg(serial->dev,
-				usb_rcvctrlpipe(serial->dev, 0),
-				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+					usb_rcvctrlpipe(serial->dev, 0),
+					0x22, 0x21, val, 0, NULL, 0,
+					USB_CTRL_SET_TIMEOUT);
 	}
 
 	return 0;
@@ -90,17 +91,19 @@
 		    __func__, status);
 		return;
 	}
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
-		tty_insert_flip_string (tty, data, urb->actual_length);
-		tty_flip_buffer_push (tty);
+		tty_insert_flip_string(tty, data, urb->actual_length);
+		tty_flip_buffer_push(tty);
 	}
 
-	result = usb_submit_urb (urb, GFP_ATOMIC);
+	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result)
-		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+		dev_err(&port->dev,
+			"%s - failed resubmitting read urb, error %d\n",
 			__func__, result);
 	return;
 }
@@ -115,7 +118,7 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree (urb->transfer_buffer);
+	kfree(urb->transfer_buffer);
 
 	if (status)
 		dbg("%s - nonzero write bulk status received: %d",
@@ -171,7 +174,7 @@
 		}
 		usb_fill_bulk_urb(urb, serial->dev,
 				  usb_rcvbulkpipe(serial->dev,
-						  port->bulk_out_endpointAddress),
+					  port->bulk_out_endpointAddress),
 				  buffer, buffer_size,
 				  airprime_read_bulk_callback, port);
 		result = usb_submit_urb(urb, GFP_KERNEL);
@@ -183,7 +186,8 @@
 				__func__, i, port->number, result);
 			goto errout;
 		}
-		/* remember this urb so we can kill it when the port is closed */
+		/* remember this urb so we can kill it when the
+		   port is closed */
 		priv->read_urbp[i] = urb;
 	}
 
@@ -192,22 +196,22 @@
 	goto out;
 
  errout:
-	/* some error happened, cancel any submitted urbs and clean up anything that
-	   got allocated successfully */
+	/* some error happened, cancel any submitted urbs and clean up
+	   anything that got allocated successfully */
 
 	while (i-- != 0) {
 		urb = priv->read_urbp[i];
 		buffer = urb->transfer_buffer;
-		usb_kill_urb (urb);
-		usb_free_urb (urb);
-		kfree (buffer);
+		usb_kill_urb(urb);
+		usb_free_urb(urb);
+		kfree(buffer);
 	}
 
  out:
 	return result;
 }
 
-static void airprime_close(struct usb_serial_port *port, struct file * filp)
+static void airprime_close(struct usb_serial_port *port, struct file *filp)
 {
 	struct airprime_private *priv = usb_get_serial_port_data(port);
 	int i;
@@ -220,16 +224,16 @@
 	mutex_lock(&port->serial->disc_mutex);
 	if (!port->serial->disconnected)
 		airprime_send_setup(port);
-	mutex_lock(&port->serial->disc_mutex);
+	mutex_unlock(&port->serial->disc_mutex);
 
 	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]);
+		usb_kill_urb(priv->read_urbp[i]);
+		kfree(priv->read_urbp[i]->transfer_buffer);
+		usb_free_urb(priv->read_urbp[i]);
 	}
 
 	/* free up private structure */
-	kfree (priv);
+	kfree(priv);
 	usb_set_serial_port_data(port, NULL);
 }
 
@@ -259,10 +263,10 @@
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		dev_err(&port->dev, "no more free urbs\n");
-		kfree (buffer);
+		kfree(buffer);
 		return -ENOMEM;
 	}
-	memcpy (buffer, buf, count);
+	memcpy(buffer, buf, count);
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
@@ -279,7 +283,7 @@
 			"%s - usb_submit_urb(write bulk) failed with status = %d\n",
 			__func__, status);
 		count = status;
-		kfree (buffer);
+		kfree(buffer);
 	} else {
 		spin_lock_irqsave(&priv->lock, flags);
 		++priv->outstanding_urbs;
@@ -287,7 +291,7 @@
 	}
 	/* 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;
 }
 
@@ -315,8 +319,10 @@
 {
 	int retval;
 
-	airprime_device.num_ports =
-		(endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS;
+	airprime_device.num_ports = endpoints;
+	if (endpoints < 0 || endpoints >= MAX_BULK_EPS)
+		airprime_device.num_ports = NUM_BULK_EPS;
+
 	retval = usb_serial_register(&airprime_device);
 	if (retval)
 		return retval;
@@ -341,6 +347,7 @@
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled");
 module_param(buffer_size, int, 0);
-MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)");
+MODULE_PARM_DESC(buffer_size,
+		"Size of the transfer buffers in bytes (default 4096)");
 module_param(endpoints, int, 0);
 MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 599ab2e..77895c8 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -24,7 +24,7 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include <linux/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 static int debug;
@@ -246,29 +246,29 @@
 	baud = tty_get_baud_rate(port->tty);
 
 	switch (baud) {
-		case 75:
-		case 150:
-		case 300:
-		case 600:
-		case 1200:
-		case 1800:
-		case 2400:
-		case 4800:
-		case 9600:
-		case 19200:
-		case 38400:
-		case 57600:
-		case 115200:
-		case 230400:
-		case 460800:
-			/* Report the resulting rate back to the caller */
-			tty_encode_baud_rate(port->tty, baud, baud);
-			break;
-		/* set 9600 as default (if given baudrate is invalid for example) */
-		default:
-			tty_encode_baud_rate(port->tty, 9600, 9600);
-		case 0:
-			baud = 9600;
+	case 75:
+	case 150:
+	case 300:
+	case 600:
+	case 1200:
+	case 1800:
+	case 2400:
+	case 4800:
+	case 9600:
+	case 19200:
+	case 38400:
+	case 57600:
+	case 115200:
+	case 230400:
+	case 460800:
+		/* Report the resulting rate back to the caller */
+		tty_encode_baud_rate(port->tty, baud, baud);
+		break;
+	/* set 9600 as default (if given baudrate is invalid for example) */
+	default:
+		tty_encode_baud_rate(port->tty, 9600, 9600);
+	case 0:
+		baud = 9600;
 	}
 
 	/*
@@ -380,19 +380,19 @@
 	switch (cmd) {
 	case TIOCGSERIAL:
 		/* XXX: Some of these values are probably wrong. */
-		memset(&serstruct, 0, sizeof (serstruct));
+		memset(&serstruct, 0, sizeof(serstruct));
 		serstruct.type = PORT_16654;
 		serstruct.line = port->serial->minor;
 		serstruct.port = port->number;
 		serstruct.custom_divisor = 0;
 		serstruct.baud_base = 460800;
 
-		if (copy_to_user(user_arg, &serstruct, sizeof (serstruct)))
+		if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
 			return -EFAULT;
 
 		return 0;
 	case TIOCSSERIAL:
-		if (copy_from_user(&serstruct, user_arg, sizeof (serstruct)))
+		if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
 			return -EFAULT;
 		return 0;
 	default:
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index d947d95..ba28fdc 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -130,7 +130,7 @@
 		return -ENOMEM;
 
 	r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size);
-	if ( r < 0)
+	if (r < 0)
 		goto out;
 
 	/* Not having the datasheet for the CH341, we ignore the bytes returned
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c7329f4..5b349ec 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -133,6 +133,14 @@
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 6da539e..504edf8 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -40,6 +40,17 @@
 /* AlphaMicro Components AMC-232USB01 device */
 #define FTDI_AMC232_PID 0xFF00 /* Product Id */
 
+/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
+/* the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
+#define FTDI_SCS_DEVICE_1_PID 0xD011    /* SCS Tracker / DSP TNC */
+#define FTDI_SCS_DEVICE_2_PID 0xD012
+#define FTDI_SCS_DEVICE_3_PID 0xD013
+#define FTDI_SCS_DEVICE_4_PID 0xD014
+#define FTDI_SCS_DEVICE_5_PID 0xD015
+#define FTDI_SCS_DEVICE_6_PID 0xD016
+#define FTDI_SCS_DEVICE_7_PID 0xD017
+
 /* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
 #define FTDI_ACTZWAVE_PID	0xF2D0
 
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 6bcb82d..78f2f6d 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1713,7 +1713,7 @@
 {
 	struct moschip_port *mos7840_port;
 	unsigned int mcr;
-	unsigned int status;
+	int status;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -1740,11 +1740,10 @@
 
 	mos7840_port->shadowMCR = mcr;
 
-	status = 0;
 	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
 	if (status < 0) {
 		dbg("setting MODEM_CONTROL_REGISTER Failed\n");
-		return -1;
+		return status;
 	}
 
 	return 0;
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 0f6d234..3d92496 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -123,7 +123,8 @@
 
 config USB_STORAGE_ONETOUCH
 	bool "Support OneTouch Button on Maxtor Hard Drives"
-	depends on USB_STORAGE && INPUT_EVDEV
+	depends on USB_STORAGE
+	depends on INPUT=y || INPUT=USB_STORAGE
 	help
 	  Say Y here to include additional code to support the Maxtor OneTouch
 	  USB hard drive's onetouch button.
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index a28d491..d617e8a 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -135,7 +135,7 @@
 	stat[type].fls |= USU_MOD_FL_THREAD;
 	spin_unlock_irqrestore(&usu_lock, flags);
 
-	task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
+	task = kthread_run(usu_probe_thread, (void*)type, "libusual_%ld", type);
 	if (IS_ERR(task)) {
 		rc = PTR_ERR(task);
 		printk(KERN_WARNING "libusual: "
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index dfd42fe..98b89ea 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -38,7 +38,7 @@
 #include "onetouch.h"
 #include "debug.h"
 
-void onetouch_release_input(void *onetouch_);
+static void onetouch_release_input(void *onetouch_);
 
 struct usb_onetouch {
 	char name[128];
@@ -223,7 +223,7 @@
 	return error;
 }
 
-void onetouch_release_input(void *onetouch_)
+static void onetouch_release_input(void *onetouch_)
 {
 	struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_;
 
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 732bf52..a0ed889 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -44,7 +44,8 @@
  *	  running with this patch.
  * Send your submission to either Phil Dibowitz <phil@ipom.com> or
  * Alan Stern <stern@rowland.harvard.edu>, and don't forget to CC: the
- * USB development list <linux-usb-devel@lists.sourceforge.net>.
+ * USB development list <linux-usb@vger.kernel.org> and the USB storage list
+ * <usb-storage@lists.one-eyed-alien.net>
  */
 
 /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
@@ -557,6 +558,13 @@
 		US_FL_SINGLE_LUN),
 #endif
 
+/* Reported by Dmitry Khlystov <adminimus@gmail.com> */
+UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
+		"Samsung",
+		"YP-U3",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_MAX_SECTORS_64),
+
 /* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
 UNUSUAL_DEV(  0x050d, 0x0115, 0x0133, 0x0133,
 		"Belkin",
@@ -1200,6 +1208,17 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
+/* Andrew Lunn <andrew@lunn.ch>
+ * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
+ * on LUN 4.
+ * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera"
+*/
+UNUSUAL_DEV(  0x0851, 0x1543, 0x0200, 0x0200,
+		"PanDigital",
+		"Photo Frame",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_NOT_LOCKABLE),
+
 /* Submitted by Jan De Luyck <lkml@kcore.org> */
 UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
 		"CITIZEN",
@@ -1342,6 +1361,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY),
 
+/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
+UNUSUAL_DEV(  0x2770, 0x915d, 0x0010, 0x0010,
+		"INTOVA",
+		"Pixtreme",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /*
  * Entry for Jenoptik JD 5200z3
  *
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index a856eff..e268aac 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -539,7 +539,8 @@
 				" has %s in unusual_devs.h (kernel"
 				" %s)\n"
 				"   Please send a copy of this message to "
-				"<linux-usb-devel@lists.sourceforge.net>\n",
+				"<linux-usb@vger.kernel.org> and "
+				"<usb-storage@lists.one-eyed-alien.net>\n",
 				le16_to_cpu(ddesc->idVendor),
 				le16_to_cpu(ddesc->idProduct),
 				le16_to_cpu(ddesc->bcdDevice),
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index b535483..1386678 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -80,19 +80,51 @@
 	dev->config->set_status(dev, dev->config->get_status(dev) | status);
 }
 
+void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
+					 unsigned int fbit)
+{
+	unsigned int i;
+	struct virtio_driver *drv = container_of(vdev->dev.driver,
+						 struct virtio_driver, driver);
+
+	for (i = 0; i < drv->feature_table_size; i++)
+		if (drv->feature_table[i] == fbit)
+			return;
+	BUG();
+}
+EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
+
 static int virtio_dev_probe(struct device *_d)
 {
-	int err;
+	int err, i;
 	struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
 	struct virtio_driver *drv = container_of(dev->dev.driver,
 						 struct virtio_driver, driver);
+	u32 device_features;
 
+	/* We have a driver! */
 	add_status(dev, VIRTIO_CONFIG_S_DRIVER);
+
+	/* Figure out what features the device supports. */
+	device_features = dev->config->get_features(dev);
+
+	/* Features supported by both device and driver into dev->features. */
+	memset(dev->features, 0, sizeof(dev->features));
+	for (i = 0; i < drv->feature_table_size; i++) {
+		unsigned int f = drv->feature_table[i];
+		BUG_ON(f >= 32);
+		if (device_features & (1 << f))
+			set_bit(f, dev->features);
+	}
+
 	err = drv->probe(dev);
 	if (err)
 		add_status(dev, VIRTIO_CONFIG_S_FAILED);
-	else
+	else {
 		add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
+		/* They should never have set feature bits beyond 32 */
+		dev->config->set_features(dev, dev->features[0]);
+	}
 	return err;
 }
 
@@ -114,6 +146,8 @@
 
 int register_virtio_driver(struct virtio_driver *driver)
 {
+	/* Catch this early. */
+	BUG_ON(driver->feature_table_size && !driver->feature_table);
 	driver->driver.bus = &virtio_bus;
 	driver->driver.probe = virtio_dev_probe;
 	driver->driver.remove = virtio_dev_remove;
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 0b3efc3..bfef604 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -155,9 +155,9 @@
 static inline s64 towards_target(struct virtio_balloon *vb)
 {
 	u32 v;
-	__virtio_config_val(vb->vdev,
-			    offsetof(struct virtio_balloon_config, num_pages),
-			    &v);
+	vb->vdev->config->get(vb->vdev,
+			      offsetof(struct virtio_balloon_config, num_pages),
+			      &v, sizeof(v));
 	return v - vb->num_pages;
 }
 
@@ -227,7 +227,7 @@
 	}
 
 	vb->tell_host_first
-		= vdev->config->feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
+		= virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
 
 	return 0;
 
@@ -259,7 +259,11 @@
 	kfree(vb);
 }
 
+static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST };
+
 static struct virtio_driver virtio_balloon = {
+	.feature_table = features,
+	.feature_table_size = ARRAY_SIZE(features),
 	.driver.name =	KBUILD_MODNAME,
 	.driver.owner =	THIS_MODULE,
 	.id_table =	id_table,
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index c0df924..27e9fc9 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -87,23 +87,22 @@
 	return container_of(vdev, struct virtio_pci_device, vdev);
 }
 
-/* virtio config->feature() implementation */
-static bool vp_feature(struct virtio_device *vdev, unsigned bit)
+/* virtio config->get_features() implementation */
+static u32 vp_get_features(struct virtio_device *vdev)
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-	u32 mask;
 
-	/* Since this function is supposed to have the side effect of
-	 * enabling a queried feature, we simulate that by doing a read
-	 * from the host feature bitmask and then writing to the guest
-	 * feature bitmask */
-	mask = ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
-	if (mask & (1 << bit)) {
-		mask |= (1 << bit);
-		iowrite32(mask, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
-	}
+	/* When someone needs more than 32 feature bits, we'll need to
+	 * steal a bit to indicate that the rest are somewhere else. */
+	return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
+}
 
-	return !!(mask & (1 << bit));
+/* virtio config->set_features() implementation */
+static void vp_set_features(struct virtio_device *vdev, u32 features)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+
+	iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
 }
 
 /* virtio config->get() implementation */
@@ -145,14 +144,14 @@
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	/* We should never be setting status to 0. */
 	BUG_ON(status == 0);
-	return iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+	iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
 }
 
 static void vp_reset(struct virtio_device *vdev)
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	/* 0 status means a reset. */
-	return iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+	iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
 }
 
 /* the notify function used when creating a virt queue */
@@ -293,7 +292,6 @@
 }
 
 static struct virtio_config_ops virtio_pci_config_ops = {
-	.feature	= vp_feature,
 	.get		= vp_get,
 	.set		= vp_set,
 	.get_status	= vp_get_status,
@@ -301,6 +299,8 @@
 	.reset		= vp_reset,
 	.find_vq	= vp_find_vq,
 	.del_vq		= vp_del_vq,
+	.get_features	= vp_get_features,
+	.set_features	= vp_set_features,
 };
 
 /* the PCI probing function */
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index c2fa5c6..937a49d 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -184,6 +184,11 @@
 
 	START_USE(vq);
 
+	if (unlikely(vq->broken)) {
+		END_USE(vq);
+		return NULL;
+	}
+
 	if (!more_used(vq)) {
 		pr_debug("No more buffers in queue\n");
 		END_USE(vq);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index d96e5c1..894fee5 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -73,8 +73,8 @@
 	status = 0;
 done:
 	DPRINTK("returning = %d", status);
-	mntput(mnt);
 	dput(dentry);
+	mntput(mnt);
 	return status;
 }
 
@@ -333,7 +333,7 @@
 			/* Can we expire this guy */
 			if (autofs4_can_expire(dentry, timeout, do_now)) {
 				expired = dentry;
-				break;
+				goto found;
 			}
 			goto next;
 		}
@@ -352,7 +352,7 @@
 				inf->flags |= AUTOFS_INF_EXPIRING;
 				spin_unlock(&sbi->fs_lock);
 				expired = dentry;
-				break;
+				goto found;
 			}
 			spin_unlock(&sbi->fs_lock);
 		/*
@@ -363,7 +363,7 @@
 			expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
 			if (expired) {
 				dput(dentry);
-				break;
+				goto found;
 			}
 		}
 next:
@@ -371,18 +371,16 @@
 		spin_lock(&dcache_lock);
 		next = next->next;
 	}
-
-	if (expired) {
-		DPRINTK("returning %p %.*s",
-			expired, (int)expired->d_name.len, expired->d_name.name);
-		spin_lock(&dcache_lock);
-		list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
-		spin_unlock(&dcache_lock);
-		return expired;
-	}
 	spin_unlock(&dcache_lock);
-
 	return NULL;
+
+found:
+	DPRINTK("returning %p %.*s",
+		expired, (int)expired->d_name.len, expired->d_name.name);
+	spin_lock(&dcache_lock);
+	list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
+	spin_unlock(&dcache_lock);
+	return expired;
 }
 
 /* Perform an expiry operation */
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index aa4c5ff..edf5b6b 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -146,17 +146,17 @@
 
 	if (d_mountpoint(dentry)) {
 		struct file *fp = NULL;
-		struct vfsmount *fp_mnt = mntget(mnt);
-		struct dentry *fp_dentry = dget(dentry);
+		struct path fp_path = { .dentry = dentry, .mnt = mnt };
 
-		if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
-			dput(fp_dentry);
-			mntput(fp_mnt);
+		path_get(&fp_path);
+
+		if (!autofs4_follow_mount(&fp_path.mnt, &fp_path.dentry)) {
+			path_put(&fp_path);
 			dcache_dir_close(inode, file);
 			goto out;
 		}
 
-		fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
+		fp = dentry_open(fp_path.dentry, fp_path.mnt, file->f_flags);
 		status = PTR_ERR(fp);
 		if (IS_ERR(fp)) {
 			dcache_dir_close(inode, file);
@@ -242,7 +242,8 @@
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
-	int status = 0;
+	struct dentry *new;
+	int status;
 
 	/* Block on any pending expiry here; invalidate the dentry
            when expiration is done to trigger mount request with a new
@@ -318,7 +319,28 @@
 	spin_lock(&dentry->d_lock);
 	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
 	spin_unlock(&dentry->d_lock);
-	return status;
+
+	/*
+	 * The dentry that is passed in from lookup may not be the one
+	 * we end up using, as mkdir can create a new one.  If this
+	 * happens, and another process tries the lookup at the same time,
+	 * it will set the PENDING flag on this new dentry, but add itself
+	 * to our waitq.  Then, if after the lookup succeeds, the first
+	 * process that requested the mount performs another lookup of the
+	 * same directory, it will show up as still pending!  So, we need
+	 * to redo the lookup here and clear pending on that dentry.
+	 */
+	if (d_unhashed(dentry)) {
+		new = d_lookup(dentry->d_parent, &dentry->d_name);
+		if (new) {
+			spin_lock(&new->d_lock);
+			new->d_flags &= ~DCACHE_AUTOFS_PENDING;
+			spin_unlock(&new->d_lock);
+			dput(new);
+		}
+	}
+
+	return 0;
 }
 
 /* For autofs direct mounts the follow link triggers the mount */
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 1fe28e4..75e5955 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -171,7 +171,7 @@
 	for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
 		len += tmp->d_name.len + 1;
 
-	if (--len > NAME_MAX) {
+	if (!len || --len > NAME_MAX) {
 		spin_unlock(&dcache_lock);
 		return 0;
 	}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 9ced35b..f28cf8b 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -934,7 +934,7 @@
 
 	nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
 	npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	npages = min(max(npages, 1), FUSE_MAX_PAGES_PER_REQ);
+	npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ);
 	down_read(&current->mm->mmap_sem);
 	npages = get_user_pages(current, current->mm, user_addr, npages, write,
 				0, req->pages, NULL);
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index d58f845..c5e1450 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -46,7 +46,7 @@
 
 
 static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
-					struct jffs2_inode_cache *ic)
+				    struct jffs2_inode_cache *ic)
 {
 	struct jffs2_full_dirent *fd;
 
@@ -68,11 +68,17 @@
 			continue;
 		}
 
-		if (child_ic->nlink++ && fd->type == DT_DIR) {
-			JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
-				fd->name, fd->ino, ic->ino);
-			/* TODO: What do we do about it? */
-		}
+		if (fd->type == DT_DIR) {
+			if (child_ic->pino_nlink) {
+				JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
+					    fd->name, fd->ino, ic->ino);
+				/* TODO: What do we do about it? */
+			} else {
+				child_ic->pino_nlink = ic->ino;
+			}
+		} else
+			child_ic->pino_nlink++;
+
 		dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
 		/* Can't free scan_dents so far. We might need them in pass 2 */
 	}
@@ -125,7 +131,7 @@
 	dbg_fsbuild("pass 2 starting\n");
 
 	for_each_inode(i, c, ic) {
-		if (ic->nlink)
+		if (ic->pino_nlink)
 			continue;
 
 		jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
@@ -232,16 +238,19 @@
 			/* Reduce nlink of the child. If it's now zero, stick it on the
 			   dead_fds list to be cleaned up later. Else just free the fd */
 
-			child_ic->nlink--;
+			if (fd->type == DT_DIR)
+				child_ic->pino_nlink = 0;
+			else
+				child_ic->pino_nlink--;
 
-			if (!child_ic->nlink) {
-				dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n",
+			if (!child_ic->pino_nlink) {
+				dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
 					  fd->ino, fd->name);
 				fd->next = *dead_fds;
 				*dead_fds = fd;
 			} else {
 				dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
-					  fd->ino, fd->name, child_ic->nlink);
+					  fd->ino, fd->name, child_ic->pino_nlink);
 				jffs2_free_full_dirent(fd);
 			}
 		}
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index c63e7a9..c0c141f 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -208,6 +208,13 @@
 	f = JFFS2_INODE_INFO(inode);
 	dir_f = JFFS2_INODE_INFO(dir_i);
 
+	/* jffs2_do_create() will want to lock it, _after_ reserving
+	   space and taking c-alloc_sem. If we keep it locked here,
+	   lockdep gets unhappy (although it's a false positive;
+	   nothing else will be looking at this inode yet so there's
+	   no chance of AB-BA deadlock involving its f->sem). */
+	mutex_unlock(&f->sem);
+
 	ret = jffs2_do_create(c, dir_f, f, ri,
 			      dentry->d_name.name, dentry->d_name.len);
 	if (ret)
@@ -219,7 +226,8 @@
 	d_instantiate(dentry, inode);
 
 	D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
-		  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
+		  inode->i_ino, inode->i_mode, inode->i_nlink,
+		  f->inocache->pino_nlink, inode->i_mapping->nrpages));
 	return 0;
 
  fail:
@@ -243,7 +251,7 @@
 	ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
 			      dentry->d_name.len, dead_f, now);
 	if (dead_f->inocache)
-		dentry->d_inode->i_nlink = dead_f->inocache->nlink;
+		dentry->d_inode->i_nlink = dead_f->inocache->pino_nlink;
 	if (!ret)
 		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
 	return ret;
@@ -276,7 +284,7 @@
 
 	if (!ret) {
 		mutex_lock(&f->sem);
-		old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
+		old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink;
 		mutex_unlock(&f->sem);
 		d_instantiate(dentry, old_dentry->d_inode);
 		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
@@ -493,11 +501,14 @@
 
 	inode->i_op = &jffs2_dir_inode_operations;
 	inode->i_fop = &jffs2_dir_operations;
-	/* Directories get nlink 2 at start */
-	inode->i_nlink = 2;
 
 	f = JFFS2_INODE_INFO(inode);
 
+	/* Directories get nlink 2 at start */
+	inode->i_nlink = 2;
+	/* but ic->pino_nlink is the parent ino# */
+	f->inocache->pino_nlink = dir_i->i_ino;
+
 	ri->data_crc = cpu_to_je32(0);
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
@@ -594,17 +605,25 @@
 
 static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
 {
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
+	struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
 	struct jffs2_full_dirent *fd;
 	int ret;
+	uint32_t now = get_seconds();
 
 	for (fd = f->dents ; fd; fd = fd->next) {
 		if (fd->ino)
 			return -ENOTEMPTY;
 	}
-	ret = jffs2_unlink(dir_i, dentry);
-	if (!ret)
+
+	ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
+			      dentry->d_name.len, f, now);
+	if (!ret) {
+		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+		clear_nlink(dentry->d_inode);
 		drop_nlink(dir_i);
+	}
 	return ret;
 }
 
@@ -817,7 +836,10 @@
 		   inode which didn't exist. */
 		if (victim_f->inocache) {
 			mutex_lock(&victim_f->sem);
-			victim_f->inocache->nlink--;
+			if (S_ISDIR(new_dentry->d_inode->i_mode))
+				victim_f->inocache->pino_nlink = 0;
+			else
+				victim_f->inocache->pino_nlink--;
 			mutex_unlock(&victim_f->sem);
 		}
 	}
@@ -838,8 +860,8 @@
 		struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
 		mutex_lock(&f->sem);
 		inc_nlink(old_dentry->d_inode);
-		if (f->inocache)
-			f->inocache->nlink++;
+		if (f->inocache && !S_ISDIR(old_dentry->d_inode->i_mode))
+			f->inocache->pino_nlink++;
 		mutex_unlock(&f->sem);
 
 		printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 25a640e..dddb2a6 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -294,7 +294,7 @@
 			break;
 #endif
 		default:
-			if (ic->nodes == (void *)ic && ic->nlink == 0)
+			if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
 				jffs2_del_ino_cache(c, ic);
 	}
 }
@@ -332,7 +332,8 @@
 	if (c->mtd->point) {
 		unsigned long *wordebuf;
 
-		ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
+		ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size,
+				    &retlen, &ebuf, NULL);
 		if (ret) {
 			D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
 			goto do_flash_read;
@@ -340,7 +341,7 @@
 		if (retlen < c->sector_size) {
 			/* Don't muck about if it won't let us point to the whole erase sector */
 			D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
-			c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen);
+			c->mtd->unpoint(c->mtd, jeb->offset, retlen);
 			goto do_flash_read;
 		}
 		wordebuf = ebuf-sizeof(*wordebuf);
@@ -349,7 +350,7 @@
 		   if (*++wordebuf != ~0)
 			   break;
 		} while(--retlen);
-		c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
+		c->mtd->unpoint(c->mtd, jeb->offset, c->sector_size);
 		if (retlen) {
 			printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
 			       *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 3eb1c84..086c438 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -273,7 +273,7 @@
 	inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
 	inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
 
-	inode->i_nlink = f->inocache->nlink;
+	inode->i_nlink = f->inocache->pino_nlink;
 
 	inode->i_blocks = (inode->i_size + 511) >> 9;
 
@@ -286,13 +286,12 @@
 	case S_IFDIR:
 	{
 		struct jffs2_full_dirent *fd;
+		inode->i_nlink = 2; /* parent and '.' */
 
 		for (fd=f->dents; fd; fd = fd->next) {
 			if (fd->type == DT_DIR && fd->ino)
 				inc_nlink(inode);
 		}
-		/* and '..' */
-		inc_nlink(inode);
 		/* Root dir gets i_nlink 3 for some reason */
 		if (inode->i_ino == 1)
 			inc_nlink(inode);
@@ -586,11 +585,12 @@
 }
 
 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
-						     int inum, int nlink)
+					      int inum, int unlinked)
 {
 	struct inode *inode;
 	struct jffs2_inode_cache *ic;
-	if (!nlink) {
+
+	if (unlinked) {
 		/* The inode has zero nlink but its nodes weren't yet marked
 		   obsolete. This has to be because we're still waiting for
 		   the final (close() and) iput() to happen.
@@ -638,8 +638,8 @@
 			return ERR_CAST(inode);
 	}
 	if (is_bad_inode(inode)) {
-		printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n",
-		       inum, nlink);
+		printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. unlinked %d\n",
+		       inum, unlinked);
 		/* NB. This will happen again. We need to do something appropriate here. */
 		iput(inode);
 		return ERR_PTR(-EIO);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index bad0056..090c556 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -161,8 +161,8 @@
 			continue;
 		}
 
-		if (!ic->nlink) {
-			D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
+		if (!ic->pino_nlink) {
+			D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink/pino zero\n",
 				  ic->ino));
 			spin_unlock(&c->inocache_lock);
 			jffs2_xattr_delete_inode(c, ic);
@@ -398,10 +398,10 @@
 	   it's vaguely possible. */
 
 	inum = ic->ino;
-	nlink = ic->nlink;
+	nlink = ic->pino_nlink;
 	spin_unlock(&c->inocache_lock);
 
-	f = jffs2_gc_fetch_inode(c, inum, nlink);
+	f = jffs2_gc_fetch_inode(c, inum, !nlink);
 	if (IS_ERR(f)) {
 		ret = PTR_ERR(f);
 		goto release_sem;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 8219df6..1750445 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -177,7 +177,10 @@
 #ifdef CONFIG_JFFS2_FS_XATTR
 	struct jffs2_xattr_ref *xref;
 #endif
-	int nlink;
+	uint32_t pino_nlink;	/* Directories store parent inode
+				   here; other inodes store nlink.
+				   Zero always means that it's
+				   completely unlinked. */
 };
 
 /* Inode states for 'state' above. We need the 'GC' state to prevent
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 9df8f3e..a9bf960 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -709,7 +709,7 @@
 				break;
 #endif
 			default:
-				if (ic->nodes == (void *)ic && ic->nlink == 0)
+				if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
 					jffs2_del_ino_cache(c, ic);
 				break;
 		}
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 1b10d25..2cc866c 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -187,7 +187,7 @@
 void jffs2_gc_release_inode(struct jffs2_sb_info *c,
 			    struct jffs2_inode_info *f);
 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
-					      int inum, int nlink);
+					      int inum, int unlinked);
 
 unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
 				   struct jffs2_inode_info *f,
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 4cb4d76..6ca08ad 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -63,10 +63,11 @@
 	/* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
 	 * adding and jffs2_flash_read_end() interface. */
 	if (c->mtd->point) {
-		err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
+		err = c->mtd->point(c->mtd, ofs, len, &retlen,
+				    (void **)&buffer, NULL);
 		if (!err && retlen < len) {
 			JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
-			c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
+			c->mtd->unpoint(c->mtd, ofs, retlen);
 		} else if (err)
 			JFFS2_WARNING("MTD point failed: error code %d.\n", err);
 		else
@@ -100,7 +101,7 @@
 		kfree(buffer);
 #ifndef __ECOS
 	else
-		c->mtd->unpoint(c->mtd, buffer, ofs, len);
+		c->mtd->unpoint(c->mtd, ofs, len);
 #endif
 
 	if (crc != tn->data_crc) {
@@ -136,7 +137,7 @@
 		kfree(buffer);
 #ifndef __ECOS
 	else
-		c->mtd->unpoint(c->mtd, buffer, ofs, len);
+		c->mtd->unpoint(c->mtd, ofs, len);
 #endif
 	return err;
 }
@@ -1123,7 +1124,8 @@
 	size_t retlen;
 	int ret;
 
-	dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
+	dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino,
+		      f->inocache->pino_nlink);
 
 	memset(&rii, 0, sizeof(rii));
 
@@ -1358,7 +1360,7 @@
 		}
 		dbg_readinode("creating inocache for root inode\n");
 		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
-		f->inocache->ino = f->inocache->nlink = 1;
+		f->inocache->ino = f->inocache->pino_nlink = 1;
 		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
 		f->inocache->state = INO_STATE_READING;
 		jffs2_add_ino_cache(c, f->inocache);
@@ -1401,7 +1403,7 @@
 	jffs2_clear_acl(f);
 	jffs2_xattr_delete_inode(c, f->inocache);
 	mutex_lock(&f->sem);
-	deleted = f->inocache && !f->inocache->nlink;
+	deleted = f->inocache && !f->inocache->pino_nlink;
 
 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 272872d..1d437de 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -97,11 +97,12 @@
 	size_t pointlen;
 
 	if (c->mtd->point) {
-		ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf);
+		ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen,
+				    (void **)&flashbuf, NULL);
 		if (!ret && pointlen < c->mtd->size) {
 			/* Don't muck about if it won't let us point to the whole flash */
 			D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
-			c->mtd->unpoint(c->mtd, flashbuf, 0, pointlen);
+			c->mtd->unpoint(c->mtd, 0, pointlen);
 			flashbuf = NULL;
 		}
 		if (ret)
@@ -267,7 +268,7 @@
 		kfree(flashbuf);
 #ifndef __ECOS
 	else
-		c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
+		c->mtd->unpoint(c->mtd, 0, c->mtd->size);
 #endif
 	if (s)
 		kfree(s);
@@ -940,7 +941,7 @@
 	ic->nodes = (void *)ic;
 	jffs2_add_ino_cache(c, ic);
 	if (ino == 1)
-		ic->nlink = 1;
+		ic->pino_nlink = 1;
 	return ic;
 }
 
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index f3353df..7da69ea 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -31,11 +31,12 @@
 
 static struct inode *jffs2_alloc_inode(struct super_block *sb)
 {
-	struct jffs2_inode_info *ei;
-	ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
-	if (!ei)
+	struct jffs2_inode_info *f;
+
+	f = kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
+	if (!f)
 		return NULL;
-	return &ei->vfs_inode;
+	return &f->vfs_inode;
 }
 
 static void jffs2_destroy_inode(struct inode *inode)
@@ -45,10 +46,10 @@
 
 static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
 {
-	struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
+	struct jffs2_inode_info *f = foo;
 
-	mutex_init(&ei->sem);
-	inode_init_once(&ei->vfs_inode);
+	mutex_init(&f->sem);
+	inode_init_once(&f->vfs_inode);
 }
 
 static int jffs2_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 8de52b6..0e78b00 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -494,7 +494,7 @@
 				/* If it's an in-core inode, then we have to adjust any
 				   full_dirent or full_dnode structure to point to the
 				   new version instead of the old */
-				f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink);
+				f = jffs2_gc_fetch_inode(c, ic->ino, !ic->pino_nlink);
 				if (IS_ERR(f)) {
 					/* Should never happen; it _must_ be present */
 					JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 665fce9..ca29440 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -19,7 +19,8 @@
 #include "compr.h"
 
 
-int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri)
+int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+		       uint32_t mode, struct jffs2_raw_inode *ri)
 {
 	struct jffs2_inode_cache *ic;
 
@@ -31,7 +32,7 @@
 	memset(ic, 0, sizeof(*ic));
 
 	f->inocache = ic;
-	f->inocache->nlink = 1;
+	f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
 	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
 	f->inocache->state = INO_STATE_PRESENT;
 
@@ -438,10 +439,10 @@
 	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
 				JFFS2_SUMMARY_INODE_SIZE);
 	D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
-	if (ret) {
-		mutex_unlock(&f->sem);
+	if (ret)
 		return ret;
-	}
+
+	mutex_lock(&f->sem);
 
 	ri->data_crc = cpu_to_je32(0);
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
@@ -635,9 +636,9 @@
 					jffs2_mark_node_obsolete(c, fd->raw);
 				jffs2_free_full_dirent(fd);
 			}
-		}
-
-		dead_f->inocache->nlink--;
+			dead_f->inocache->pino_nlink = 0;
+		} else
+			dead_f->inocache->pino_nlink--;
 		/* NB: Caller must set inode nlink if appropriate */
 		mutex_unlock(&dead_f->sem);
 	}
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 574cb75..082e844 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -592,7 +592,7 @@
 	   When an inode with XATTR is removed, those XATTRs must be removed. */
 	struct jffs2_xattr_ref *ref, *_ref;
 
-	if (!ic || ic->nlink > 0)
+	if (!ic || ic->pino_nlink > 0)
 		return;
 
 	down_write(&c->xattr_sem);
@@ -829,7 +829,7 @@
 			   ref->xd and ref->ic are not valid yet. */
 			xd = jffs2_find_xattr_datum(c, ref->xid);
 			ic = jffs2_get_ino_cache(c, ref->ino);
-			if (!xd || !ic || !ic->nlink) {
+			if (!xd || !ic || !ic->pino_nlink) {
 				dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
 					  ref->ino, ref->xid, ref->xseqno);
 				ref->xseqno |= XREF_DELETE_MARKER;
diff --git a/fs/utimes.c b/fs/utimes.c
index a2bef77..af059d5 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -40,9 +40,14 @@
 
 #endif
 
+static bool nsec_special(long nsec)
+{
+	return nsec == UTIME_OMIT || nsec == UTIME_NOW;
+}
+
 static bool nsec_valid(long nsec)
 {
-	if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
+	if (nsec_special(nsec))
 		return true;
 
 	return nsec >= 0 && nsec <= 999999999;
@@ -119,7 +124,15 @@
 			newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
 			newattrs.ia_valid |= ATTR_MTIME_SET;
 		}
-	} else {
+	}
+
+	/*
+	 * If times is NULL or both times are either UTIME_OMIT or
+	 * UTIME_NOW, then need to check permissions, because
+	 * inode_change_ok() won't do it.
+	 */
+	if (!times || (nsec_special(times[0].tv_nsec) &&
+		       nsec_special(times[1].tv_nsec))) {
 		error = -EACCES;
                 if (IS_IMMUTABLE(inode))
 			goto mnt_drop_write_and_out;
diff --git a/include/asm-arm/div64.h b/include/asm-arm/div64.h
index 0b5f881..5001390 100644
--- a/include/asm-arm/div64.h
+++ b/include/asm-arm/div64.h
@@ -224,6 +224,4 @@
 
 #endif
 
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
-
 #endif
diff --git a/include/asm-frv/unaligned.h b/include/asm-frv/unaligned.h
index 64ccc73..839a2fb 100644
--- a/include/asm-frv/unaligned.h
+++ b/include/asm-frv/unaligned.h
@@ -9,8 +9,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifndef _ASM_FRV_UNALIGNED_H
-#define _ASM_FRV_UNALIGNED_H
+#ifndef _ASM_UNALIGNED_H
+#define _ASM_UNALIGNED_H
 
 #include <linux/unaligned/le_byteshift.h>
 #include <linux/unaligned/be_byteshift.h>
@@ -19,4 +19,4 @@
 #define get_unaligned	__get_unaligned_be
 #define put_unaligned	__put_unaligned_be
 
-#endif /* _ASM_FRV_UNALIGNED_H */
+#endif /* _ASM_UNALIGNED_H */
diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h
index a4a4937..8f4e319 100644
--- a/include/asm-generic/div64.h
+++ b/include/asm-generic/div64.h
@@ -30,11 +30,6 @@
 	__rem;							\
  })
 
-static inline uint64_t div64_64(uint64_t dividend, uint64_t divisor)
-{
-	return dividend / divisor;
-}
-
 #elif BITS_PER_LONG == 32
 
 extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
@@ -54,8 +49,6 @@
 	__rem;						\
  })
 
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
-
 #else /* BITS_PER_LONG == ?? */
 
 # error do_div() does not yet support the C64
diff --git a/include/asm-ia64/cpu.h b/include/asm-ia64/cpu.h
index e87fa32..fcca30b 100644
--- a/include/asm-ia64/cpu.h
+++ b/include/asm-ia64/cpu.h
@@ -14,8 +14,8 @@
 
 DECLARE_PER_CPU(int, cpu_state);
 
-extern int arch_register_cpu(int num);
 #ifdef CONFIG_HOTPLUG_CPU
+extern int arch_register_cpu(int num);
 extern void arch_unregister_cpu(int);
 #endif
 
diff --git a/include/asm-ia64/dmi.h b/include/asm-ia64/dmi.h
index f3efaa2..00eb1b1 100644
--- a/include/asm-ia64/dmi.h
+++ b/include/asm-ia64/dmi.h
@@ -3,4 +3,9 @@
 
 #include <asm/io.h>
 
+/* Use normal IO mappings for DMI */
+#define dmi_ioremap ioremap
+#define dmi_iounmap(x,l) iounmap(x)
+#define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
+
 #endif
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index 4ebed77..260a85a 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -423,11 +423,6 @@
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap (volatile void __iomem *addr);
 
-/* Use normal IO mappings for DMI */
-#define dmi_ioremap ioremap
-#define dmi_iounmap(x,l) iounmap(x)
-#define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
-
 /*
  * String version of IO memory access ops:
  */
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index f30e055..2422ac6 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -108,13 +108,11 @@
 #define TIF_DB_DISABLED		19	/* debug trap disabled for fsyscall */
 #define TIF_FREEZE		20	/* is freezing for suspend */
 #define TIF_RESTORE_RSE		21	/* user RBS is newer than kernel RBS */
-#define TIF_RESTORE_SIGMASK	22	/* restore signal mask in do_signal() */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
@@ -131,7 +129,18 @@
 #define TIF_WORK_MASK		(TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
 
 #define TS_POLLING		1 	/* true if in idle loop and not sleeping */
+#define TS_RESTORE_SIGMASK	2	/* restore signal mask in do_signal() */
 
 #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK	1
+static inline void set_restore_sigmask(void)
+{
+	struct thread_info *ti = current_thread_info();
+	ti->status |= TS_RESTORE_SIGMASK;
+	set_bit(TIF_SIGPENDING, &ti->flags);
+}
+#endif	/* !__ASSEMBLY__ */
+
 #endif /* _ASM_IA64_THREAD_INFO_H */
diff --git a/include/asm-m68k/div64.h b/include/asm-m68k/div64.h
index 33caad1..8243c93 100644
--- a/include/asm-m68k/div64.h
+++ b/include/asm-m68k/div64.h
@@ -25,5 +25,4 @@
 	__rem;							\
 })
 
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
 #endif /* _M68K_DIV64_H */
diff --git a/include/asm-m68knommu/dma.h b/include/asm-m68knommu/dma.h
index 3f20419..939a020 100644
--- a/include/asm-m68knommu/dma.h
+++ b/include/asm-m68knommu/dma.h
@@ -35,7 +35,8 @@
 /*
  * Set number of channels of DMA on ColdFire for different implementations.
  */
-#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
+#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) || \
+	defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define MAX_M68K_DMA_CHANNELS 4
 #elif defined(CONFIG_M5272)
 #define MAX_M68K_DMA_CHANNELS 1
diff --git a/include/asm-m68knommu/param.h b/include/asm-m68knommu/param.h
index 96c4510..6044397 100644
--- a/include/asm-m68knommu/param.h
+++ b/include/asm-m68knommu/param.h
@@ -1,13 +1,16 @@
 #ifndef _M68KNOMMU_PARAM_H
 #define _M68KNOMMU_PARAM_H
 
-#define HZ CONFIG_HZ
-
 #ifdef __KERNEL__
+#define HZ CONFIG_HZ
 #define	USER_HZ		HZ
 #define	CLOCKS_PER_SEC	(USER_HZ)
 #endif
 
+#ifndef HZ
+#define HZ	100
+#endif
+
 #define EXEC_PAGESIZE	4096
 
 #ifndef NOGROUP
diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h
index 716371b..d1d6991 100644
--- a/include/asm-mips/div64.h
+++ b/include/asm-mips/div64.h
@@ -82,7 +82,6 @@
 	(n) = __quot; \
 	__mod; })
 
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
 #endif /* (_MIPS_SZLONG == 32) */
 
 #if (_MIPS_SZLONG == 64)
@@ -106,11 +105,6 @@
 	(n) = __quot; \
 	__mod; })
 
-static inline uint64_t div64_64(uint64_t dividend, uint64_t divisor)
-{
-	return dividend / divisor;
-}
-
 #endif /* (_MIPS_SZLONG == 64) */
 
 #endif /* _ASM_DIV64_H */
diff --git a/include/asm-mn10300/div64.h b/include/asm-mn10300/div64.h
index bf9c515..3a8329b 100644
--- a/include/asm-mn10300/div64.h
+++ b/include/asm-mn10300/div64.h
@@ -97,7 +97,4 @@
 	return result;
 }
 
-extern __attribute__((const))
-uint64_t div64_64(uint64_t dividend, uint64_t divisor);
-
 #endif /* _ASM_DIV64 */
diff --git a/include/asm-um/div64.h b/include/asm-um/div64.h
index 7b73b2c..1e17f74 100644
--- a/include/asm-um/div64.h
+++ b/include/asm-um/div64.h
@@ -3,5 +3,4 @@
 
 #include "asm/arch/div64.h"
 
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
 #endif
diff --git a/include/asm-x86/div64.h b/include/asm-x86/div64.h
index 0dbf8bf..9a2d644 100644
--- a/include/asm-x86/div64.h
+++ b/include/asm-x86/div64.h
@@ -33,25 +33,25 @@
 	__mod;							\
 })
 
-/*
- * (long)X = ((long long)divs) / (long)div
- * (long)rem = ((long long)divs) % (long)div
- *
- * Warning, this will do an exception if X overflows.
- */
-#define div_long_long_rem(a, b, c) div_ll_X_l_rem(a, b, c)
-
-static inline long div_ll_X_l_rem(long long divs, long div, long *rem)
+static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 {
-	long dum2;
-	asm("divl %2":"=a"(dum2), "=d"(*rem)
-	    : "rm"(div), "A"(divs));
+	union {
+		u64 v64;
+		u32 v32[2];
+	} d = { dividend };
+	u32 upper;
 
-	return dum2;
-
+	upper = d.v32[1];
+	d.v32[1] = 0;
+	if (upper >= divisor) {
+		d.v32[1] = upper / divisor;
+		upper %= divisor;
+	}
+	asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) :
+		"rm" (divisor), "0" (d.v32[0]), "1" (upper));
+	return d.v64;
 }
-
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
+#define div_u64_rem	div_u64_rem
 
 #else
 # include <asm-generic/div64.h>
diff --git a/include/asm-x86/dmi.h b/include/asm-x86/dmi.h
index 1241e6a..4edf751 100644
--- a/include/asm-x86/dmi.h
+++ b/include/asm-x86/dmi.h
@@ -27,6 +27,7 @@
 
 #endif
 
+/* Use early IO mappings for DMI because it's initialized early */
 #define dmi_ioremap early_ioremap
 #define dmi_iounmap early_iounmap
 
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index 6e73467..049e81e 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -133,11 +133,6 @@
 extern void early_iounmap(void *addr, unsigned long size);
 extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
-/* Use early IO mappings for DMI because it's initialized early */
-#define dmi_ioremap early_ioremap
-#define dmi_iounmap early_iounmap
-#define dmi_alloc alloc_bootmem
-
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
  */
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 224658b..833d208 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -57,10 +57,14 @@
 					struct scatterlist *sg2)
 {
 	sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0);
+	sg1[num - 1].page_link &= ~0x02;
 }
 
 static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
 {
+	if (sg_is_last(sg))
+		return NULL;
+
 	return (++sg)->length ? sg : (void *)sg_page(sg);
 }
 
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 78fade0..b7d81b2 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -346,6 +346,11 @@
 unifdef-y += virtio_config.h
 unifdef-y += virtio_blk.h
 unifdef-y += virtio_net.h
+unifdef-y += virtio_9p.h
+unifdef-y += virtio_balloon.h
+unifdef-y += virtio_console.h
+unifdef-y += virtio_pci.h
+unifdef-y += virtio_ring.h
 unifdef-y += vt.h
 unifdef-y += wait.h
 unifdef-y += wanrouter.h
diff --git a/include/linux/calc64.h b/include/linux/calc64.h
deleted file mode 100644
index ebf4b8f..0000000
--- a/include/linux/calc64.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _LINUX_CALC64_H
-#define _LINUX_CALC64_H
-
-#include <linux/types.h>
-#include <asm/div64.h>
-
-/*
- * This is a generic macro which is used when the architecture
- * specific div64.h does not provide a optimized one.
- *
- * The 64bit dividend is divided by the divisor (data type long), the
- * result is returned and the remainder stored in the variable
- * referenced by remainder (data type long *). In contrast to the
- * do_div macro the dividend is kept intact.
- */
-#ifndef div_long_long_rem
-#define div_long_long_rem(dividend, divisor, remainder)	\
-	do_div_llr((dividend), divisor, remainder)
-
-static inline unsigned long do_div_llr(const long long dividend,
-				       const long divisor, long *remainder)
-{
-	u64 result = dividend;
-
-	*(remainder) = do_div(result, divisor);
-	return (unsigned long) result;
-}
-#endif
-
-/*
- * Sign aware variation of the above. On some architectures a
- * negative dividend leads to an divide overflow exception, which
- * is avoided by the sign check.
- */
-static inline long div_long_long_rem_signed(const long long dividend,
-					    const long divisor, long *remainder)
-{
-	long res;
-
-	if (unlikely(dividend < 0)) {
-		res = -div_long_long_rem(-dividend, divisor, remainder);
-		*remainder = -(*remainder);
-	} else
-		res = div_long_long_rem(dividend, divisor, remainder);
-
-	return res;
-}
-
-#endif
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 3509447..55e434f 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -93,6 +93,8 @@
 #endif
 };
 
+extern struct clocksource *clock;	/* current clocksource */
+
 /*
  * Clock source flags bits::
  */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 8fa7857..cf8d11c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -65,10 +65,11 @@
 	compat_long_t calcnt;
 	compat_long_t errcnt;
 	compat_long_t stbcnt;
+	compat_int_t tai;
 
 	compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
 	compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
-	compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
+	compat_int_t :32; compat_int_t :32; compat_int_t :32;
 };
 
 #define _COMPAT_NSIG_WORDS	(_COMPAT_NSIG / _COMPAT_NSIG_BPW)
diff --git a/include/linux/device.h b/include/linux/device.h
index 832fb0e..8c23e3d 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -380,6 +380,12 @@
 /* Get the wakeup routines, which depend on struct device */
 #include <linux/pm_wakeup.h>
 
+static inline const char *dev_name(struct device *dev)
+{
+	/* will be changed into kobject_name(&dev->kobj) in the near future */
+	return dev->bus_id;
+}
+
 #ifdef CONFIG_NUMA
 static inline int dev_to_node(struct device *dev)
 {
@@ -478,7 +484,7 @@
 extern const char *dev_driver_string(struct device *dev);
 #define dev_printk(level, dev, format, arg...)	\
 	printk(level "%s %s: " format , dev_driver_string(dev) , \
-	       (dev)->bus_id , ## arg)
+	       dev_name(dev) , ## arg)
 
 #define dev_emerg(dev, format, arg...)		\
 	dev_printk(KERN_EMERG , dev , format , ## arg)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1883a85..552e0ec 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -61,6 +61,7 @@
 #define IRQ_WAKEUP		0x00100000	/* IRQ triggers system wakeup */
 #define IRQ_MOVE_PENDING	0x00200000	/* need to re-target IRQ destination */
 #define IRQ_NO_BALANCING	0x00400000	/* IRQ is excluded from balancing */
+#define IRQ_SPURIOUS_DISABLED	0x00800000	/* IRQ was disabled by the spurious trap */
 
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 33ef710..abb6ac6 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -1,7 +1,7 @@
 #ifndef _LINUX_JIFFIES_H
 #define _LINUX_JIFFIES_H
 
-#include <linux/calc64.h>
+#include <linux/math64.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/time.h>
diff --git a/include/linux/math64.h b/include/linux/math64.h
new file mode 100644
index 0000000..c1a5f81
--- /dev/null
+++ b/include/linux/math64.h
@@ -0,0 +1,84 @@
+#ifndef _LINUX_MATH64_H
+#define _LINUX_MATH64_H
+
+#include <linux/types.h>
+#include <asm/div64.h>
+
+#if BITS_PER_LONG == 64
+
+/**
+ * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
+ *
+ * This is commonly provided by 32bit archs to provide an optimized 64bit
+ * divide.
+ */
+static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
+{
+	*remainder = dividend % divisor;
+	return dividend / divisor;
+}
+
+/**
+ * div_s64_rem - signed 64bit divide with 32bit divisor with remainder
+ */
+static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
+{
+	*remainder = dividend % divisor;
+	return dividend / divisor;
+}
+
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ */
+static inline u64 div64_u64(u64 dividend, u64 divisor)
+{
+	return dividend / divisor;
+}
+
+#elif BITS_PER_LONG == 32
+
+#ifndef div_u64_rem
+static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
+{
+	*remainder = do_div(dividend, divisor);
+	return dividend;
+}
+#endif
+
+#ifndef div_s64_rem
+extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
+#endif
+
+#ifndef div64_u64
+extern u64 div64_u64(u64 dividend, u64 divisor);
+#endif
+
+#endif /* BITS_PER_LONG */
+
+/**
+ * div_u64 - unsigned 64bit divide with 32bit divisor
+ *
+ * This is the most common 64bit divide and should be used if possible,
+ * as many 32bit archs can optimize this variant better than a full 64bit
+ * divide.
+ */
+#ifndef div_u64
+static inline u64 div_u64(u64 dividend, u32 divisor)
+{
+	u32 remainder;
+	return div_u64_rem(dividend, divisor, &remainder);
+}
+#endif
+
+/**
+ * div_s64 - signed 64bit divide with 32bit divisor
+ */
+#ifndef div_s64
+static inline s64 div_s64(s64 dividend, s32 divisor)
+{
+	s32 remainder;
+	return div_s64_rem(dividend, divisor, &remainder);
+}
+#endif
+
+#endif /* _LINUX_MATH64_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index 819c4e8..3e03b1a 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -190,7 +190,7 @@
 	extern typeof(sym) sym;					\
 	__CRC_SYMBOL(sym, sec)					\
 	static const char __kstrtab_##sym[]			\
-	__attribute__((section("__ksymtab_strings")))		\
+	__attribute__((section("__ksymtab_strings"), aligned(1))) \
 	= MODULE_SYMBOL_PREFIX #sym;                    	\
 	static const struct kernel_symbol __ksymtab_##sym	\
 	__used							\
@@ -229,23 +229,6 @@
 	MODULE_STATE_GOING,
 };
 
-/* Similar stuff for section attributes. */
-struct module_sect_attr
-{
-	struct module_attribute mattr;
-	char *name;
-	unsigned long address;
-};
-
-struct module_sect_attrs
-{
-	struct attribute_group grp;
-	int nsections;
-	struct module_sect_attr attrs[0];
-};
-
-struct module_param_attrs;
-
 struct module
 {
 	enum module_state state;
diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h
deleted file mode 100644
index 9006feb..0000000
--- a/include/linux/mtd/jedec.h
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/* JEDEC Flash Interface.
- * This is an older type of interface for self programming flash. It is
- * commonly use in older AMD chips and is obsolete compared with CFI.
- * It is called JEDEC because the JEDEC association distributes the ID codes
- * for the chips.
- *
- * See the AMD flash databook for information on how to operate the interface.
- *
- * $Id: jedec.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $
- */
-
-#ifndef __LINUX_MTD_JEDEC_H__
-#define __LINUX_MTD_JEDEC_H__
-
-#include <linux/types.h>
-
-#define MAX_JEDEC_CHIPS 16
-
-// Listing of all supported chips and their information
-struct JEDECTable
-{
-   __u16 jedec;
-   char *name;
-   unsigned long size;
-   unsigned long sectorsize;
-   __u32 capabilities;
-};
-
-// JEDEC being 0 is the end of the chip array
-struct jedec_flash_chip
-{
-   __u16 jedec;
-   unsigned long size;
-   unsigned long sectorsize;
-
-   // *(__u8*)(base + (adder << addrshift)) = data << datashift
-   // Address size = size << addrshift
-   unsigned long base;           // Byte 0 of the flash, will be unaligned
-   unsigned int datashift;       // Useful for 32bit/16bit accesses
-   unsigned int addrshift;
-   unsigned long offset;         // linerized start. base==offset for unbanked, uninterleaved flash
-
-   __u32 capabilities;
-
-   // These markers are filled in by the flash_chip_scan function
-   unsigned long start;
-   unsigned long length;
-};
-
-struct jedec_private
-{
-   unsigned long size;         // Total size of all the devices
-
-   /* Bank handling. If sum(bank_fill) == size then this is linear flash.
-      Otherwise the mapping has holes in it. bank_fill may be used to
-      find the holes, but in the common symetric case
-      bank_fill[0] == bank_fill[*], thus addresses may be computed
-      mathmatically. bank_fill must be powers of two */
-   unsigned is_banked;
-   unsigned long bank_fill[MAX_JEDEC_CHIPS];
-
-   struct jedec_flash_chip chips[MAX_JEDEC_CHIPS];
-};
-
-#endif
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 0a13bb3..245f909 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -143,10 +143,12 @@
 	int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
 
 	/* This stuff for eXecute-In-Place */
-	int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
+	/* phys is optional and may be set to NULL */
+	int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, void **virt, resource_size_t *phys);
 
 	/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
-	void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
+	void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
 
 
 	int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h
index a7f6d20..5cc070c 100644
--- a/include/linux/mtd/pmc551.h
+++ b/include/linux/mtd/pmc551.h
@@ -36,8 +36,9 @@
  * Function Prototypes
  */
 static int pmc551_erase(struct mtd_info *, struct erase_info *);
-static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
-static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
+static void pmc551_unpoint(struct mtd_info *, loff_t, size_t);
+static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, void **virt, resource_size_t *phys);
 static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index e5a53da..cf6dbd75 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1429,6 +1429,7 @@
 #define PCI_DEVICE_ID_NEO_2DB9PRI       0x00C9
 #define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
 #define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
+#define PCIE_DEVICE_ID_NEO_4_IBM        0x00F4
 
 #define PCI_VENDOR_ID_XIRCOM		0x115d
 #define PCI_DEVICE_ID_XIRCOM_RBM56G	0x0101
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 52e49dc..dcddfb2 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -347,6 +347,9 @@
 	((type) == USRQUOTA ? (sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED) : \
 			      (sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED))
 
+#define sb_any_quota_suspended(sb) (sb_has_quota_suspended(sb, USRQUOTA) | \
+				  sb_has_quota_suspended(sb, GRPQUOTA))
+
 int register_quota_format(struct quota_format_type *fmt);
 void unregister_quota_format(struct quota_format_type *fmt);
 
diff --git a/include/linux/string.h b/include/linux/string.h
index c5d3fca..efdc445 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -109,5 +109,7 @@
 extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
 extern void argv_free(char **argv);
 
+extern bool sysfs_streq(const char *s1, const char *s2);
+
 #endif
 #endif /* _LINUX_STRING_H_ */
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 7858eac..27bad59 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -196,6 +196,12 @@
 	return 0;
 }
 
+static inline int sysfs_update_group(struct kobject *kobj,
+				const struct attribute_group *grp)
+{
+	return 0;
+}
+
 static inline void sysfs_remove_group(struct kobject *kobj,
 				      const struct attribute_group *grp)
 {
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 8ea3e71..fc6035d 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -58,6 +58,8 @@
 
 #include <asm/param.h>
 
+#define NTP_API		4	/* NTP API version */
+
 /*
  * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen
  * for a slightly underdamped convergence characteristic. SHIFT_KH
@@ -74,24 +76,22 @@
 #define MAXTC		10	/* maximum time constant (shift) */
 
 /*
- * The SHIFT_UPDATE define establishes the decimal point of the
- * time_offset variable which represents the current offset with
- * respect to standard time.
- *
  * SHIFT_USEC defines the scaling (shift) of the time_freq and
  * time_tolerance variables, which represent the current frequency
  * offset and maximum frequency tolerance.
  */
-#define SHIFT_UPDATE (SHIFT_HZ + 1) /* time offset scale (shift) */
 #define SHIFT_USEC 16		/* frequency offset scale (shift) */
-#define SHIFT_NSEC 12		/* kernel frequency offset scale */
+#define PPM_SCALE (NSEC_PER_USEC << (NTP_SCALE_SHIFT - SHIFT_USEC))
+#define PPM_SCALE_INV_SHIFT 20
+#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + NTP_SCALE_SHIFT)) / \
+		       PPM_SCALE + 1)
 
-#define MAXPHASE 512000L        /* max phase error (us) */
-#define MAXFREQ (512L << SHIFT_USEC)  /* max frequency error (ppm) */
-#define MAXFREQ_NSEC (512000L << SHIFT_NSEC) /* max frequency error (ppb) */
+#define MAXPHASE 500000000l	/* max phase error (ns) */
+#define MAXFREQ 500000		/* max frequency error (ns/s) */
+#define MAXFREQ_SCALED ((s64)MAXFREQ << NTP_SCALE_SHIFT)
 #define MINSEC 256		/* min interval between updates (s) */
 #define MAXSEC 2048		/* max interval between updates (s) */
-#define	NTP_PHASE_LIMIT	(MAXPHASE << 5)	/* beyond max. dispersion */
+#define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */
 
 /*
  * syscall interface - used (mainly by NTP daemon)
@@ -121,9 +121,11 @@
 	long errcnt;            /* calibration errors (ro) */
 	long stbcnt;            /* stability limit exceeded (ro) */
 
+	int tai;		/* TAI offset (ro) */
+
 	int  :32; int  :32; int  :32; int  :32;
 	int  :32; int  :32; int  :32; int  :32;
-	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32;
 };
 
 /*
@@ -135,6 +137,9 @@
 #define ADJ_ESTERROR		0x0008	/* estimated time error */
 #define ADJ_STATUS		0x0010	/* clock status */
 #define ADJ_TIMECONST		0x0020	/* pll time constant */
+#define ADJ_TAI			0x0080	/* set TAI offset */
+#define ADJ_MICRO		0x1000	/* select microsecond resolution */
+#define ADJ_NANO		0x2000	/* select nanosecond resolution */
 #define ADJ_TICK		0x4000	/* tick value */
 #define ADJ_OFFSET_SINGLESHOT	0x8001	/* old-fashioned adjtime */
 #define ADJ_OFFSET_SS_READ	0xa001  /* read-only adjtime */
@@ -146,8 +151,6 @@
 #define MOD_ESTERROR	ADJ_ESTERROR
 #define MOD_STATUS	ADJ_STATUS
 #define MOD_TIMECONST	ADJ_TIMECONST
-#define MOD_CLKB	ADJ_TICK
-#define MOD_CLKA	ADJ_OFFSET_SINGLESHOT /* 0x8000 in original */
 
 
 /*
@@ -169,9 +172,13 @@
 #define STA_PPSERROR	0x0800	/* PPS signal calibration error (ro) */
 
 #define STA_CLOCKERR	0x1000	/* clock hardware fault (ro) */
+#define STA_NANO	0x2000	/* resolution (0 = us, 1 = ns) (ro) */
+#define STA_MODE	0x4000	/* mode (0 = PLL, 1 = FLL) (ro) */
+#define STA_CLK		0x8000	/* clock source (0 = A, 1 = B) (ro) */
 
+/* read-only bits */
 #define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \
-    STA_PPSERROR | STA_CLOCKERR) /* read-only bits */
+	STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK)
 
 /*
  * Clock states (time_state)
@@ -203,10 +210,9 @@
 extern long time_maxerror;	/* maximum error */
 extern long time_esterror;	/* estimated error */
 
-extern long time_freq;		/* frequency offset (scaled ppm) */
-
 extern long time_adjust;	/* The amount of adjtime left */
 
+extern void ntp_init(void);
 extern void ntp_clear(void);
 
 /**
@@ -225,7 +231,7 @@
 	__x < 0 ? -(-__x >> __s) : __x >> __s;	\
 })
 
-#define TICK_LENGTH_SHIFT	32
+#define NTP_SCALE_SHIFT		32
 
 #ifdef CONFIG_NO_HZ
 #define NTP_INTERVAL_FREQ  (2)
@@ -234,8 +240,8 @@
 #endif
 #define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
 
-/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
-extern u64 current_tick_length(void);
+/* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
+extern u64 tick_length;
 
 extern void second_overflow(void);
 extern void update_ntp_one_tick(void);
diff --git a/include/linux/usb/c67x00.h b/include/linux/usb/c67x00.h
new file mode 100644
index 0000000..83c6b45
--- /dev/null
+++ b/include/linux/usb/c67x00.h
@@ -0,0 +1,48 @@
+/*
+ * usb_c67x00.h: platform definitions for the Cypress C67X00 USB chip
+ *
+ * Copyright (C) 2006-2008 Barco N.V.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301  USA.
+ */
+
+#ifndef _LINUX_USB_C67X00_H
+#define _LINUX_USB_C67X00_H
+
+/* SIE configuration */
+#define C67X00_SIE_UNUSED	0
+#define C67X00_SIE_HOST		1
+#define C67X00_SIE_PERIPHERAL_A	2	/* peripheral on A port */
+#define C67X00_SIE_PERIPHERAL_B	3	/* peripheral on B port */
+
+#define c67x00_sie_config(config, n)  (((config)>>(4*(n)))&0x3)
+
+#define C67X00_SIE1_UNUSED	        (C67X00_SIE_UNUSED		<< 0)
+#define C67X00_SIE1_HOST	        (C67X00_SIE_HOST		<< 0)
+#define C67X00_SIE1_PERIPHERAL_A	(C67X00_SIE_PERIPHERAL_A	<< 0)
+#define C67X00_SIE1_PERIPHERAL_B	(C67X00_SIE_PERIPHERAL_B	<< 0)
+
+#define C67X00_SIE2_UNUSED		(C67X00_SIE_UNUSED		<< 4)
+#define C67X00_SIE2_HOST		(C67X00_SIE_HOST		<< 4)
+#define C67X00_SIE2_PERIPHERAL_A	(C67X00_SIE_PERIPHERAL_A	<< 4)
+#define C67X00_SIE2_PERIPHERAL_B	(C67X00_SIE_PERIPHERAL_B	<< 4)
+
+struct c67x00_platform_data {
+	int sie_config;			/* SIEs config (C67X00_SIEx_*) */
+	unsigned long hpi_regstep;	/* Step between HPI registers  */
+};
+
+#endif /* _LINUX_USB_C67X00_H */
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 7e0d308..73a2f4e 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -455,7 +455,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* USB_DT_BOS:  group of wireless capabilities */
+/* USB_DT_BOS:  group of device-level capabilities */
 struct usb_bos_descriptor {
 	__u8  bLength;
 	__u8  bDescriptorType;
@@ -501,6 +501,16 @@
 	__u8  bReserved;
 } __attribute__((packed));
 
+#define	USB_CAP_TYPE_EXT		2
+
+struct usb_ext_cap_descriptor {		/* Link Power Management */
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bDevCapabilityType;
+	__u8  bmAttributes;
+#define USB_LPM_SUPPORT			(1 << 1)	/* supports LPM */
+} __attribute__((packed));
+
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index d8128f7..cf468fb 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -114,6 +114,8 @@
 	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
 
 	int (*set_halt) (struct usb_ep *ep, int value);
+	int (*set_wedge) (struct usb_ep *ep);
+
 	int (*fifo_status) (struct usb_ep *ep);
 	void (*fifo_flush) (struct usb_ep *ep);
 };
@@ -349,6 +351,25 @@
 }
 
 /**
+ * usb_ep_set_wedge - sets the halt feature and ignores clear requests
+ * @ep: the endpoint being wedged
+ *
+ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
+ * requests. If the gadget driver clears the halt status, it will
+ * automatically unwedge the endpoint.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_ep_set_wedge(struct usb_ep *ep)
+{
+	if (ep->ops->set_wedge)
+		return ep->ops->set_wedge(ep);
+	else
+		return ep->ops->set_halt(ep, 1);
+}
+
+/**
  * usb_ep_fifo_status - returns number of bytes in fifo, or error
  * @ep: the endpoint whose fifo status is being checked.
  *
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index e7d1084..06005fa 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -76,6 +76,7 @@
  * @dev: underlying device.
  * @id: the device type identification (used to match it with a driver).
  * @config: the configuration ops for this device.
+ * @features: the features supported by both driver and device.
  * @priv: private pointer for the driver's use.
  */
 struct virtio_device
@@ -84,6 +85,8 @@
 	struct device dev;
 	struct virtio_device_id id;
 	struct virtio_config_ops *config;
+	/* Note that this is a Linux set_bit-style bitmap. */
+	unsigned long features[1];
 	void *priv;
 };
 
@@ -94,6 +97,8 @@
  * virtio_driver - operations for a virtio I/O driver
  * @driver: underlying device driver (populate name and owner).
  * @id_table: the ids serviced by this driver.
+ * @feature_table: an array of feature numbers supported by this device.
+ * @feature_table_size: number of entries in the feature table array.
  * @probe: the function to call when a device is found.  Returns a token for
  *    remove, or PTR_ERR().
  * @remove: the function when a device is removed.
@@ -103,6 +108,8 @@
 struct virtio_driver {
 	struct device_driver driver;
 	const struct virtio_device_id *id_table;
+	const unsigned int *feature_table;
+	unsigned int feature_table_size;
 	int (*probe)(struct virtio_device *dev);
 	void (*remove)(struct virtio_device *dev);
 	void (*config_changed)(struct virtio_device *dev);
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
index bca0b10..d4695a3 100644
--- a/include/linux/virtio_blk.h
+++ b/include/linux/virtio_blk.h
@@ -9,6 +9,7 @@
 #define VIRTIO_BLK_F_BARRIER	0	/* Does host support barriers? */
 #define VIRTIO_BLK_F_SIZE_MAX	1	/* Indicates maximum segment size */
 #define VIRTIO_BLK_F_SEG_MAX	2	/* Indicates maximum # of segments */
+#define VIRTIO_BLK_F_GEOMETRY	4	/* Legacy geometry available  */
 
 struct virtio_blk_config
 {
@@ -18,6 +19,12 @@
 	__le32 size_max;
 	/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
 	__le32 seg_max;
+	/* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
+	struct virtio_blk_geometry {
+		__le16 cylinders;
+		__u8 heads;
+		__u8 sectors;
+	} geometry;
 } __attribute__((packed));
 
 /* These two define direction. */
@@ -41,13 +48,8 @@
 	__u64 sector;
 };
 
+/* And this is the final byte of the write scatter-gather list. */
 #define VIRTIO_BLK_S_OK		0
 #define VIRTIO_BLK_S_IOERR	1
 #define VIRTIO_BLK_S_UNSUPP	2
-
-/* This is the first element of the write scatter-gather list */
-struct virtio_blk_inhdr
-{
-	unsigned char status;
-};
 #endif /* _LINUX_VIRTIO_BLK_H */
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index d581b29..50db245 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -16,27 +16,20 @@
 #define VIRTIO_CONFIG_S_FAILED		0x80
 
 #ifdef __KERNEL__
-struct virtio_device;
+#include <linux/virtio.h>
 
 /**
  * virtio_config_ops - operations for configuring a virtio device
- * @feature: search for a feature in this config
- *	vdev: the virtio_device
- *	bit: the feature bit
- *	Returns true if the feature is supported.  Acknowledges the feature
- *	so the host can see it.
  * @get: read the value of a configuration field
  *	vdev: the virtio_device
  *	offset: the offset of the configuration field
  *	buf: the buffer to write the field value into.
  *	len: the length of the buffer
- *	Note that contents are conventionally little-endian.
  * @set: write the value of a configuration field
  *	vdev: the virtio_device
  *	offset: the offset of the configuration field
  *	buf: the buffer to read the field value from.
  *	len: the length of the buffer
- *	Note that contents are conventionally little-endian.
  * @get_status: read the status byte
  *	vdev: the virtio_device
  *	Returns the status byte
@@ -52,10 +45,15 @@
  *	callback: the virqtueue callback
  *	Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
  * @del_vq: free a virtqueue found by find_vq().
+ * @get_features: get the array of feature bits for this device.
+ *	vdev: the virtio_device
+ *	Returns the first 32 feature bits (all we currently need).
+ * @set_features: confirm what device features we'll be using.
+ *	vdev: the virtio_device
+ *	feature: the first 32 feature bits
  */
 struct virtio_config_ops
 {
-	bool (*feature)(struct virtio_device *vdev, unsigned bit);
 	void (*get)(struct virtio_device *vdev, unsigned offset,
 		    void *buf, unsigned len);
 	void (*set)(struct virtio_device *vdev, unsigned offset,
@@ -67,43 +65,52 @@
 				     unsigned index,
 				     void (*callback)(struct virtqueue *));
 	void (*del_vq)(struct virtqueue *vq);
+	u32 (*get_features)(struct virtio_device *vdev);
+	void (*set_features)(struct virtio_device *vdev, u32 features);
 };
 
+/* If driver didn't advertise the feature, it will never appear. */
+void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
+					 unsigned int fbit);
+
 /**
- * virtio_config_val - look for a feature and get a single virtio config.
+ * virtio_has_feature - helper to determine if this device has this feature.
+ * @vdev: the device
+ * @fbit: the feature bit
+ */
+static inline bool virtio_has_feature(const struct virtio_device *vdev,
+				      unsigned int fbit)
+{
+	/* Did you forget to fix assumptions on max features? */
+	if (__builtin_constant_p(fbit))
+		BUILD_BUG_ON(fbit >= 32);
+
+	virtio_check_driver_offered_feature(vdev, fbit);
+	return test_bit(fbit, vdev->features);
+}
+
+/**
+ * virtio_config_val - look for a feature and get a virtio config entry.
  * @vdev: the virtio device
  * @fbit: the feature bit
  * @offset: the type to search for.
  * @val: a pointer to the value to fill in.
  *
  * The return value is -ENOENT if the feature doesn't exist.  Otherwise
- * the value is endian-corrected and returned in v. */
-#define virtio_config_val(vdev, fbit, offset, v) ({			\
-	int _err;							\
-	if ((vdev)->config->feature((vdev), (fbit))) {			\
-		__virtio_config_val((vdev), (offset), (v));		\
-		_err = 0;						\
-	} else								\
-		_err = -ENOENT;						\
-	_err;								\
-})
+ * the config value is copied into whatever is pointed to by v. */
+#define virtio_config_val(vdev, fbit, offset, v) \
+	virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(v))
 
-/**
- * __virtio_config_val - get a single virtio config without feature check.
- * @vdev: the virtio device
- * @offset: the type to search for.
- * @val: a pointer to the value to fill in.
- *
- * The value is endian-corrected and returned in v. */
-#define __virtio_config_val(vdev, offset, v) do {			\
-	BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2		\
-		     && sizeof(*(v)) != 4 && sizeof(*(v)) != 8);	\
-	(vdev)->config->get((vdev), (offset), (v), sizeof(*(v)));	\
-	switch (sizeof(*(v))) {						\
-	case 2: le16_to_cpus((__u16 *) v); break;			\
-	case 4: le32_to_cpus((__u32 *) v); break;			\
-	case 8: le64_to_cpus((__u64 *) v); break;			\
-	}								\
-} while(0)
+static inline int virtio_config_buf(struct virtio_device *vdev,
+				    unsigned int fbit,
+				    unsigned int offset,
+				    void *buf, unsigned len)
+{
+	if (!virtio_has_feature(vdev, fbit))
+		return -ENOENT;
+
+	vdev->config->get(vdev, offset, buf, len);
+	return 0;
+}
 #endif /* __KERNEL__ */
 #endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 1ea3351..9405aa6 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -6,9 +6,18 @@
 #define VIRTIO_ID_NET	1
 
 /* The feature bitmap for virtio net */
-#define VIRTIO_NET_F_CSUM	0	/* Can handle pkts w/ partial csum */
+#define VIRTIO_NET_F_CSUM	0	/* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM	1	/* Guest handles pkts w/ partial csum */
 #define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */
-#define VIRTIO_NET_F_GSO	6	/* Can handle pkts w/ any GSO type */
+#define VIRTIO_NET_F_GSO	6	/* Host handles pkts w/ any GSO type */
+#define VIRTIO_NET_F_GUEST_TSO4	7	/* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6	8	/* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN	9	/* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO	10	/* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4	11	/* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6	12	/* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN	13	/* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO	14	/* Host can handle UFO in. */
 
 struct virtio_net_config
 {
diff --git a/kernel/compat.c b/kernel/compat.c
index 4a856a3..32c254a 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -955,7 +955,8 @@
 			__put_user(txc.jitcnt, &utp->jitcnt) ||
 			__put_user(txc.calcnt, &utp->calcnt) ||
 			__put_user(txc.errcnt, &utp->errcnt) ||
-			__put_user(txc.stbcnt, &utp->stbcnt))
+			__put_user(txc.stbcnt, &utp->stbcnt) ||
+			__put_user(txc.tai, &utp->tai))
 		ret = -EFAULT;
 
 	return ret;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 46e4ad1..46d6611 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -150,6 +150,26 @@
 }
 EXPORT_SYMBOL(disable_irq);
 
+static void __enable_irq(struct irq_desc *desc, unsigned int irq)
+{
+	switch (desc->depth) {
+	case 0:
+		printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
+		WARN_ON(1);
+		break;
+	case 1: {
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+
+		/* Prevent probing on this irq: */
+		desc->status = status | IRQ_NOPROBE;
+		check_irq_resend(desc, irq);
+		/* fall-through */
+	}
+	default:
+		desc->depth--;
+	}
+}
+
 /**
  *	enable_irq - enable handling of an irq
  *	@irq: Interrupt to enable
@@ -169,22 +189,7 @@
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	switch (desc->depth) {
-	case 0:
-		printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
-		WARN_ON(1);
-		break;
-	case 1: {
-		unsigned int status = desc->status & ~IRQ_DISABLED;
-
-		/* Prevent probing on this irq: */
-		desc->status = status | IRQ_NOPROBE;
-		check_irq_resend(desc, irq);
-		/* fall-through */
-	}
-	default:
-		desc->depth--;
-	}
+	__enable_irq(desc, irq);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 EXPORT_SYMBOL(enable_irq);
@@ -365,7 +370,7 @@
 			compat_irq_chip_set_default_handler(desc);
 
 		desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
-				  IRQ_INPROGRESS);
+				  IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
 
 		if (!(desc->status & IRQ_NOAUTOEN)) {
 			desc->depth = 0;
@@ -381,6 +386,16 @@
 	/* Reset broken irq detection when installing new handler */
 	desc->irq_count = 0;
 	desc->irqs_unhandled = 0;
+
+	/*
+	 * Check whether we disabled the irq via the spurious handler
+	 * before. Reenable it and give it another chance.
+	 */
+	if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
+		desc->status &= ~IRQ_SPURIOUS_DISABLED;
+		__enable_irq(desc, irq);
+	}
+
 	spin_unlock_irqrestore(&desc->lock, flags);
 
 	new->irq = irq;
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 088dabb..c66d3f1 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -209,8 +209,8 @@
 		 * Now kill the IRQ
 		 */
 		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
-		desc->status |= IRQ_DISABLED;
-		desc->depth = 1;
+		desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
+		desc->depth++;
 		desc->chip->disable(irq);
 	}
 	desc->irqs_unhandled = 0;
diff --git a/kernel/kexec.c b/kernel/kexec.c
index cb85c79..1c5fcac 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1217,7 +1217,7 @@
 		}
 
 		/* match ? */
-		if (system_ram >= start && system_ram <= end) {
+		if (system_ram >= start && system_ram < end) {
 			*crash_size = size;
 			break;
 		}
diff --git a/kernel/module.c b/kernel/module.c
index 8d6cccc..8674a39 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -164,131 +164,140 @@
 	return NULL;
 }
 
-static void printk_unused_warning(const char *name)
+static bool always_ok(bool gplok, bool warn, const char *name)
 {
-	printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
-		"however this module is using it.\n", name);
-	printk(KERN_WARNING "This symbol will go away in the future.\n");
-	printk(KERN_WARNING "Please evalute if this is the right api to use, "
-		"and if it really is, submit a report the linux kernel "
-		"mailinglist together with submitting your code for "
-		"inclusion.\n");
+	return true;
 }
 
-/* Find a symbol, return value, crc and module which owns it */
-static unsigned long __find_symbol(const char *name,
-				   struct module **owner,
-				   const unsigned long **crc,
-				   int gplok)
+static bool printk_unused_warning(bool gplok, bool warn, const char *name)
+{
+	if (warn) {
+		printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
+		       "however this module is using it.\n", name);
+		printk(KERN_WARNING
+		       "This symbol will go away in the future.\n");
+		printk(KERN_WARNING
+		       "Please evalute if this is the right api to use and if "
+		       "it really is, submit a report the linux kernel "
+		       "mailinglist together with submitting your code for "
+		       "inclusion.\n");
+	}
+	return true;
+}
+
+static bool gpl_only_unused_warning(bool gplok, bool warn, const char *name)
+{
+	if (!gplok)
+		return false;
+	return printk_unused_warning(gplok, warn, name);
+}
+
+static bool gpl_only(bool gplok, bool warn, const char *name)
+{
+	return gplok;
+}
+
+static bool warn_if_not_gpl(bool gplok, bool warn, const char *name)
+{
+	if (!gplok && warn) {
+		printk(KERN_WARNING "Symbol %s is being used "
+		       "by a non-GPL module, which will not "
+		       "be allowed in the future\n", name);
+		printk(KERN_WARNING "Please see the file "
+		       "Documentation/feature-removal-schedule.txt "
+		       "in the kernel source tree for more details.\n");
+	}
+	return true;
+}
+
+struct symsearch {
+	const struct kernel_symbol *start, *stop;
+	const unsigned long *crcs;
+	bool (*check)(bool gplok, bool warn, const char *name);
+};
+
+/* Look through this array of symbol tables for a symbol match which
+ * passes the check function. */
+static const struct kernel_symbol *search_symarrays(const struct symsearch *arr,
+						    unsigned int num,
+						    const char *name,
+						    bool gplok,
+						    bool warn,
+						    const unsigned long **crc)
+{
+	unsigned int i;
+	const struct kernel_symbol *ks;
+
+	for (i = 0; i < num; i++) {
+		ks = lookup_symbol(name, arr[i].start, arr[i].stop);
+		if (!ks || !arr[i].check(gplok, warn, name))
+			continue;
+
+		if (crc)
+			*crc = symversion(arr[i].crcs, ks - arr[i].start);
+		return ks;
+	}
+	return NULL;
+}
+
+/* Find a symbol, return value, (optional) crc and (optional) module
+ * which owns it */
+static unsigned long find_symbol(const char *name,
+				 struct module **owner,
+				 const unsigned long **crc,
+				 bool gplok,
+				 bool warn)
 {
 	struct module *mod;
 	const struct kernel_symbol *ks;
+	const struct symsearch arr[] = {
+		{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
+		  always_ok },
+		{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
+		  __start___kcrctab_gpl, gpl_only },
+		{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,
+		  __start___kcrctab_gpl_future, warn_if_not_gpl },
+		{ __start___ksymtab_unused, __stop___ksymtab_unused,
+		  __start___kcrctab_unused, printk_unused_warning },
+		{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,
+		  __start___kcrctab_unused_gpl, gpl_only_unused_warning },
+	};
 
 	/* Core kernel first. */
-	*owner = NULL;
-	ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
+	ks = search_symarrays(arr, ARRAY_SIZE(arr), name, gplok, warn, crc);
 	if (ks) {
-		*crc = symversion(__start___kcrctab, (ks - __start___ksymtab));
-		return ks->value;
-	}
-	if (gplok) {
-		ks = lookup_symbol(name, __start___ksymtab_gpl,
-					 __stop___ksymtab_gpl);
-		if (ks) {
-			*crc = symversion(__start___kcrctab_gpl,
-					  (ks - __start___ksymtab_gpl));
-			return ks->value;
-		}
-	}
-	ks = lookup_symbol(name, __start___ksymtab_gpl_future,
-				 __stop___ksymtab_gpl_future);
-	if (ks) {
-		if (!gplok) {
-			printk(KERN_WARNING "Symbol %s is being used "
-			       "by a non-GPL module, which will not "
-			       "be allowed in the future\n", name);
-			printk(KERN_WARNING "Please see the file "
-			       "Documentation/feature-removal-schedule.txt "
-			       "in the kernel source tree for more "
-			       "details.\n");
-		}
-		*crc = symversion(__start___kcrctab_gpl_future,
-				  (ks - __start___ksymtab_gpl_future));
-		return ks->value;
-	}
-
-	ks = lookup_symbol(name, __start___ksymtab_unused,
-				 __stop___ksymtab_unused);
-	if (ks) {
-		printk_unused_warning(name);
-		*crc = symversion(__start___kcrctab_unused,
-				  (ks - __start___ksymtab_unused));
-		return ks->value;
-	}
-
-	if (gplok)
-		ks = lookup_symbol(name, __start___ksymtab_unused_gpl,
-				 __stop___ksymtab_unused_gpl);
-	if (ks) {
-		printk_unused_warning(name);
-		*crc = symversion(__start___kcrctab_unused_gpl,
-				  (ks - __start___ksymtab_unused_gpl));
+		if (owner)
+			*owner = NULL;
 		return ks->value;
 	}
 
 	/* Now try modules. */
 	list_for_each_entry(mod, &modules, list) {
-		*owner = mod;
-		ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
-		if (ks) {
-			*crc = symversion(mod->crcs, (ks - mod->syms));
-			return ks->value;
-		}
+		struct symsearch arr[] = {
+			{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
+			  always_ok },
+			{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
+			  mod->gpl_crcs, gpl_only },
+			{ mod->gpl_future_syms,
+			  mod->gpl_future_syms + mod->num_gpl_future_syms,
+			  mod->gpl_future_crcs, warn_if_not_gpl },
+			{ mod->unused_syms,
+			  mod->unused_syms + mod->num_unused_syms,
+			  mod->unused_crcs, printk_unused_warning },
+			{ mod->unused_gpl_syms,
+			  mod->unused_gpl_syms + mod->num_unused_gpl_syms,
+			  mod->unused_gpl_crcs, gpl_only_unused_warning },
+		};
 
-		if (gplok) {
-			ks = lookup_symbol(name, mod->gpl_syms,
-					   mod->gpl_syms + mod->num_gpl_syms);
-			if (ks) {
-				*crc = symversion(mod->gpl_crcs,
-						  (ks - mod->gpl_syms));
-				return ks->value;
-			}
-		}
-		ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms);
+		ks = search_symarrays(arr, ARRAY_SIZE(arr),
+				      name, gplok, warn, crc);
 		if (ks) {
-			printk_unused_warning(name);
-			*crc = symversion(mod->unused_crcs, (ks - mod->unused_syms));
-			return ks->value;
-		}
-
-		if (gplok) {
-			ks = lookup_symbol(name, mod->unused_gpl_syms,
-					   mod->unused_gpl_syms + mod->num_unused_gpl_syms);
-			if (ks) {
-				printk_unused_warning(name);
-				*crc = symversion(mod->unused_gpl_crcs,
-						  (ks - mod->unused_gpl_syms));
-				return ks->value;
-			}
-		}
-		ks = lookup_symbol(name, mod->gpl_future_syms,
-				   (mod->gpl_future_syms +
-				    mod->num_gpl_future_syms));
-		if (ks) {
-			if (!gplok) {
-				printk(KERN_WARNING "Symbol %s is being used "
-				       "by a non-GPL module, which will not "
-				       "be allowed in the future\n", name);
-				printk(KERN_WARNING "Please see the file "
-				       "Documentation/feature-removal-schedule.txt "
-				       "in the kernel source tree for more "
-				       "details.\n");
-			}
-			*crc = symversion(mod->gpl_future_crcs,
-					  (ks - mod->gpl_future_syms));
+			if (owner)
+				*owner = mod;
 			return ks->value;
 		}
 	}
+
 	DEBUGP("Failed to find symbol %s\n", name);
 	return -ENOENT;
 }
@@ -736,12 +745,13 @@
 	if (!forced && module_refcount(mod) != 0)
 		wait_for_zero_refcount(mod);
 
+	mutex_unlock(&module_mutex);
 	/* Final destruction now noone is using it. */
-	if (mod->exit != NULL) {
-		mutex_unlock(&module_mutex);
+	if (mod->exit != NULL)
 		mod->exit();
-		mutex_lock(&module_mutex);
-	}
+	blocking_notifier_call_chain(&module_notify_list,
+				     MODULE_STATE_GOING, mod);
+	mutex_lock(&module_mutex);
 	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
 	free_module(mod);
@@ -777,10 +787,9 @@
 void __symbol_put(const char *symbol)
 {
 	struct module *owner;
-	const unsigned long *crc;
 
 	preempt_disable();
-	if (IS_ERR_VALUE(__find_symbol(symbol, &owner, &crc, 1)))
+	if (IS_ERR_VALUE(find_symbol(symbol, &owner, NULL, true, false)))
 		BUG();
 	module_put(owner);
 	preempt_enable();
@@ -924,13 +933,10 @@
 					  struct module *mod)
 {
 	const unsigned long *crc;
-	struct module *owner;
 
-	if (IS_ERR_VALUE(__find_symbol("struct_module",
-						&owner, &crc, 1)))
+	if (IS_ERR_VALUE(find_symbol("struct_module", NULL, &crc, true, false)))
 		BUG();
-	return check_version(sechdrs, versindex, "struct_module", mod,
-			     crc);
+	return check_version(sechdrs, versindex, "struct_module", mod, crc);
 }
 
 /* First part is kernel version, which we ignore. */
@@ -974,8 +980,8 @@
 	unsigned long ret;
 	const unsigned long *crc;
 
-	ret = __find_symbol(name, &owner, &crc,
-			!(mod->taints & TAINT_PROPRIETARY_MODULE));
+	ret = find_symbol(name, &owner, &crc,
+			  !(mod->taints & TAINT_PROPRIETARY_MODULE), true);
 	if (!IS_ERR_VALUE(ret)) {
 		/* use_module can fail due to OOM,
 		   or module initialization or unloading */
@@ -991,6 +997,20 @@
  * J. Corbet <corbet@lwn.net>
  */
 #if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS)
+struct module_sect_attr
+{
+	struct module_attribute mattr;
+	char *name;
+	unsigned long address;
+};
+
+struct module_sect_attrs
+{
+	struct attribute_group grp;
+	unsigned int nsections;
+	struct module_sect_attr attrs[0];
+};
+
 static ssize_t module_sect_show(struct module_attribute *mattr,
 				struct module *mod, char *buf)
 {
@@ -1001,7 +1021,7 @@
 
 static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
 {
-	int section;
+	unsigned int section;
 
 	for (section = 0; section < sect_attrs->nsections; section++)
 		kfree(sect_attrs->attrs[section].name);
@@ -1362,10 +1382,9 @@
 {
 	struct module *owner;
 	unsigned long value;
-	const unsigned long *crc;
 
 	preempt_disable();
-	value = __find_symbol(symbol, &owner, &crc, 1);
+	value = find_symbol(symbol, &owner, NULL, true, true);
 	if (IS_ERR_VALUE(value))
 		value = 0;
 	else if (strong_try_module_get(owner))
@@ -1382,33 +1401,33 @@
  */
 static int verify_export_symbols(struct module *mod)
 {
-	const char *name = NULL;
-	unsigned long i, ret = 0;
+	unsigned int i;
 	struct module *owner;
-	const unsigned long *crc;
+	const struct kernel_symbol *s;
+	struct {
+		const struct kernel_symbol *sym;
+		unsigned int num;
+	} arr[] = {
+		{ mod->syms, mod->num_syms },
+		{ mod->gpl_syms, mod->num_gpl_syms },
+		{ mod->gpl_future_syms, mod->num_gpl_future_syms },
+		{ mod->unused_syms, mod->num_unused_syms },
+		{ mod->unused_gpl_syms, mod->num_unused_gpl_syms },
+	};
 
-	for (i = 0; i < mod->num_syms; i++)
-		if (!IS_ERR_VALUE(__find_symbol(mod->syms[i].name,
-							&owner, &crc, 1))) {
-			name = mod->syms[i].name;
-			ret = -ENOEXEC;
-			goto dup;
+	for (i = 0; i < ARRAY_SIZE(arr); i++) {
+		for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
+			if (!IS_ERR_VALUE(find_symbol(s->name, &owner,
+						      NULL, true, false))) {
+				printk(KERN_ERR
+				       "%s: exports duplicate symbol %s"
+				       " (owned by %s)\n",
+				       mod->name, s->name, module_name(owner));
+				return -ENOEXEC;
+			}
 		}
-
-	for (i = 0; i < mod->num_gpl_syms; i++)
-		if (!IS_ERR_VALUE(__find_symbol(mod->gpl_syms[i].name,
-							&owner, &crc, 1))) {
-			name = mod->gpl_syms[i].name;
-			ret = -ENOEXEC;
-			goto dup;
-		}
-
-dup:
-	if (ret)
-		printk(KERN_ERR "%s: exports duplicate symbol %s (owned by %s)\n",
-			mod->name, name, module_name(owner));
-
-	return ret;
+	}
+	return 0;
 }
 
 /* Change all symbols so that st_value encodes the pointer directly. */
@@ -1814,8 +1833,9 @@
 	unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME);
 #endif
 
-	/* Don't keep modinfo section */
+	/* Don't keep modinfo and version sections. */
 	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
+	sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
 #ifdef CONFIG_KALLSYMS
 	/* Keep symbol and string tables for decoding later. */
 	sechdrs[symindex].sh_flags |= SHF_ALLOC;
@@ -1977,7 +1997,8 @@
 		mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
 	mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;
 	if (unusedgplcrcindex)
-		mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;
+		mod->unused_gpl_crcs
+			= (void *)sechdrs[unusedgplcrcindex].sh_addr;
 
 #ifdef CONFIG_MODVERSIONS
 	if ((mod->num_syms && !crcindex) ||
@@ -2171,6 +2192,8 @@
 		mod->state = MODULE_STATE_GOING;
 		synchronize_sched();
 		module_put(mod);
+		blocking_notifier_call_chain(&module_notify_list,
+					     MODULE_STATE_GOING, mod);
 		mutex_lock(&module_mutex);
 		free_module(mod);
 		mutex_unlock(&module_mutex);
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index ae5c6c1..f1525ad 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -4,8 +4,9 @@
 
 #include <linux/sched.h>
 #include <linux/posix-timers.h>
-#include <asm/uaccess.h>
 #include <linux/errno.h>
+#include <linux/math64.h>
+#include <asm/uaccess.h>
 
 static int check_clock(const clockid_t which_clock)
 {
@@ -47,12 +48,10 @@
 			       union cpu_time_count cpu,
 			       struct timespec *tp)
 {
-	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
-		tp->tv_sec = div_long_long_rem(cpu.sched,
-					       NSEC_PER_SEC, &tp->tv_nsec);
-	} else {
+	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED)
+		*tp = ns_to_timespec(cpu.sched);
+	else
 		cputime_to_timespec(cpu.cpu, tp);
-	}
 }
 
 static inline int cpu_time_before(const clockid_t which_clock,
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index dcc199c..6c19e94 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -534,7 +534,6 @@
 #define arch_ptrace_attach(child)	do { } while (0)
 #endif
 
-#ifndef __ARCH_SYS_PTRACE
 asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -582,7 +581,6 @@
 	unlock_kernel();
 	return ret;
 }
-#endif /* __ARCH_SYS_PTRACE */
 
 int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
 {
diff --git a/kernel/sched.c b/kernel/sched.c
index e2f7f5ac..34bcc5b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -8025,7 +8025,7 @@
 
 	se->my_q = cfs_rq;
 	se->load.weight = tg->shares;
-	se->load.inv_weight = div64_64(1ULL<<32, se->load.weight);
+	se->load.inv_weight = div64_u64(1ULL<<32, se->load.weight);
 	se->parent = parent;
 }
 #endif
@@ -8692,7 +8692,7 @@
 		dequeue_entity(cfs_rq, se, 0);
 
 	se->load.weight = shares;
-	se->load.inv_weight = div64_64((1ULL<<32), shares);
+	se->load.inv_weight = div64_u64((1ULL<<32), shares);
 
 	if (on_rq)
 		enqueue_entity(cfs_rq, se, 0);
@@ -8787,7 +8787,7 @@
 	if (runtime == RUNTIME_INF)
 		return 1ULL << 16;
 
-	return div64_64(runtime << 16, period);
+	return div64_u64(runtime << 16, period);
 }
 
 #ifdef CONFIG_CGROUP_SCHED
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index 8a9498e..6b4a125 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -357,8 +357,8 @@
 
 		avg_per_cpu = p->se.sum_exec_runtime;
 		if (p->se.nr_migrations) {
-			avg_per_cpu = div64_64(avg_per_cpu,
-					       p->se.nr_migrations);
+			avg_per_cpu = div64_u64(avg_per_cpu,
+						p->se.nr_migrations);
 		} else {
 			avg_per_cpu = -1LL;
 		}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 3c44956..36e0617 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -589,16 +589,20 @@
 	local_irq_disable();
 
 	/* Find end, append list for that CPU. */
-	*__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).head;
-	__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
-	per_cpu(tasklet_vec, cpu).head = NULL;
-	per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
+	if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) {
+		*(__get_cpu_var(tasklet_vec).tail) = per_cpu(tasklet_vec, cpu).head;
+		__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
+		per_cpu(tasklet_vec, cpu).head = NULL;
+		per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
+	}
 	raise_softirq_irqoff(TASKLET_SOFTIRQ);
 
-	*__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
-	__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
-	per_cpu(tasklet_hi_vec, cpu).head = NULL;
-	per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
+	if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) {
+		*__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
+		__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
+		per_cpu(tasklet_hi_vec, cpu).head = NULL;
+		per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
+	}
 	raise_softirq_irqoff(HI_SOFTIRQ);
 
 	local_irq_enable();
diff --git a/kernel/time.c b/kernel/time.c
index 8672904..cbe0d5a 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -36,6 +36,7 @@
 #include <linux/security.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/math64.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -391,13 +392,17 @@
 struct timespec ns_to_timespec(const s64 nsec)
 {
 	struct timespec ts;
+	s32 rem;
 
 	if (!nsec)
 		return (struct timespec) {0, 0};
 
-	ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC, &ts.tv_nsec);
-	if (unlikely(nsec < 0))
-		set_normalized_timespec(&ts, ts.tv_sec, ts.tv_nsec);
+	ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
+	if (unlikely(rem < 0)) {
+		ts.tv_sec--;
+		rem += NSEC_PER_SEC;
+	}
+	ts.tv_nsec = rem;
 
 	return ts;
 }
@@ -527,8 +532,10 @@
 	 * Convert jiffies to nanoseconds and separate with
 	 * one divide.
 	 */
-	u64 nsec = (u64)jiffies * TICK_NSEC;
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_nsec);
+	u32 rem;
+	value->tv_sec = div_u64_rem((u64)jiffies * TICK_NSEC,
+				    NSEC_PER_SEC, &rem);
+	value->tv_nsec = rem;
 }
 EXPORT_SYMBOL(jiffies_to_timespec);
 
@@ -566,12 +573,11 @@
 	 * Convert jiffies to nanoseconds and separate with
 	 * one divide.
 	 */
-	u64 nsec = (u64)jiffies * TICK_NSEC;
-	long tv_usec;
+	u32 rem;
 
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
-	tv_usec /= NSEC_PER_USEC;
-	value->tv_usec = tv_usec;
+	value->tv_sec = div_u64_rem((u64)jiffies * TICK_NSEC,
+				    NSEC_PER_SEC, &rem);
+	value->tv_usec = rem / NSEC_PER_USEC;
 }
 EXPORT_SYMBOL(jiffies_to_timeval);
 
@@ -587,9 +593,7 @@
 	return x / (HZ / USER_HZ);
 # endif
 #else
-	u64 tmp = (u64)x * TICK_NSEC;
-	do_div(tmp, (NSEC_PER_SEC / USER_HZ));
-	return (long)tmp;
+	return div_u64((u64)x * TICK_NSEC, NSEC_PER_SEC / USER_HZ);
 #endif
 }
 EXPORT_SYMBOL(jiffies_to_clock_t);
@@ -601,16 +605,12 @@
 		return ~0UL;
 	return x * (HZ / USER_HZ);
 #else
-	u64 jif;
-
 	/* Don't worry about loss of precision here .. */
 	if (x >= ~0UL / HZ * USER_HZ)
 		return ~0UL;
 
 	/* .. but do try to contain it here */
-	jif = x * (u64) HZ;
-	do_div(jif, USER_HZ);
-	return jif;
+	return div_u64((u64)x * HZ, USER_HZ);
 #endif
 }
 EXPORT_SYMBOL(clock_t_to_jiffies);
@@ -619,10 +619,9 @@
 {
 #if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
 # if HZ < USER_HZ
-	x *= USER_HZ;
-	do_div(x, HZ);
+	x = div_u64(x * USER_HZ, HZ);
 # elif HZ > USER_HZ
-	do_div(x, HZ / USER_HZ);
+	x = div_u64(x, HZ / USER_HZ);
 # else
 	/* Nothing to do */
 # endif
@@ -632,8 +631,7 @@
 	 * but even this doesn't overflow in hundreds of years
 	 * in 64 bits, so..
 	 */
-	x *= TICK_NSEC;
-	do_div(x, (NSEC_PER_SEC / USER_HZ));
+	x = div_u64(x * TICK_NSEC, (NSEC_PER_SEC / USER_HZ));
 #endif
 	return x;
 }
@@ -642,21 +640,17 @@
 u64 nsec_to_clock_t(u64 x)
 {
 #if (NSEC_PER_SEC % USER_HZ) == 0
-	do_div(x, (NSEC_PER_SEC / USER_HZ));
+	return div_u64(x, NSEC_PER_SEC / USER_HZ);
 #elif (USER_HZ % 512) == 0
-	x *= USER_HZ/512;
-	do_div(x, (NSEC_PER_SEC / 512));
+	return div_u64(x * USER_HZ / 512, NSEC_PER_SEC / 512);
 #else
 	/*
          * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
          * overflow after 64.99 years.
          * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
          */
-	x *= 9;
-	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2)) /
-				  USER_HZ));
+	return div_u64(x * 9, (9ull * NSEC_PER_SEC + (USER_HZ / 2)) / USER_HZ);
 #endif
-	return x;
 }
 
 #if (BITS_PER_LONG < 64)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 5fd9b94..5125ddd 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -15,7 +15,8 @@
 #include <linux/jiffies.h>
 #include <linux/hrtimer.h>
 #include <linux/capability.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
+#include <linux/clocksource.h>
 #include <asm/timex.h>
 
 /*
@@ -23,11 +24,14 @@
  */
 unsigned long tick_usec = TICK_USEC; 		/* USER_HZ period (usec) */
 unsigned long tick_nsec;			/* ACTHZ period (nsec) */
-static u64 tick_length, tick_length_base;
+u64 tick_length;
+static u64 tick_length_base;
+
+static struct hrtimer leap_timer;
 
 #define MAX_TICKADJ		500		/* microsecs */
 #define MAX_TICKADJ_SCALED	(((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
-				  TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
+				  NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
 
 /*
  * phase-lock loop variables
@@ -35,11 +39,12 @@
 /* TIME_ERROR prevents overwriting the CMOS clock */
 static int time_state = TIME_OK;	/* clock synchronization status	*/
 int time_status = STA_UNSYNC;		/* clock status bits		*/
-static s64 time_offset;		/* time adjustment (ns)		*/
+static long time_tai;			/* TAI offset (s)		*/
+static s64 time_offset;			/* time adjustment (ns)		*/
 static long time_constant = 2;		/* pll time constant		*/
 long time_maxerror = NTP_PHASE_LIMIT;	/* maximum error (us)		*/
 long time_esterror = NTP_PHASE_LIMIT;	/* estimated error (us)		*/
-long time_freq;				/* frequency offset (scaled ppm)*/
+static s64 time_freq;			/* frequency offset (scaled ns/s)*/
 static long time_reftime;		/* time at last adjustment (s)	*/
 long time_adjust;
 static long ntp_tick_adj;
@@ -47,16 +52,56 @@
 static void ntp_update_frequency(void)
 {
 	u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
-				<< TICK_LENGTH_SHIFT;
-	second_length += (s64)ntp_tick_adj << TICK_LENGTH_SHIFT;
-	second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+				<< NTP_SCALE_SHIFT;
+	second_length += (s64)ntp_tick_adj << NTP_SCALE_SHIFT;
+	second_length += time_freq;
 
 	tick_length_base = second_length;
 
-	do_div(second_length, HZ);
-	tick_nsec = second_length >> TICK_LENGTH_SHIFT;
+	tick_nsec = div_u64(second_length, HZ) >> NTP_SCALE_SHIFT;
+	tick_length_base = div_u64(tick_length_base, NTP_INTERVAL_FREQ);
+}
 
-	do_div(tick_length_base, NTP_INTERVAL_FREQ);
+static void ntp_update_offset(long offset)
+{
+	long mtemp;
+	s64 freq_adj;
+
+	if (!(time_status & STA_PLL))
+		return;
+
+	if (!(time_status & STA_NANO))
+		offset *= NSEC_PER_USEC;
+
+	/*
+	 * Scale the phase adjustment and
+	 * clamp to the operating range.
+	 */
+	offset = min(offset, MAXPHASE);
+	offset = max(offset, -MAXPHASE);
+
+	/*
+	 * Select how the frequency is to be controlled
+	 * and in which mode (PLL or FLL).
+	 */
+	if (time_status & STA_FREQHOLD || time_reftime == 0)
+		time_reftime = xtime.tv_sec;
+	mtemp = xtime.tv_sec - time_reftime;
+	time_reftime = xtime.tv_sec;
+
+	freq_adj = (s64)offset * mtemp;
+	freq_adj <<= NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant);
+	time_status &= ~STA_MODE;
+	if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
+		freq_adj += div_s64((s64)offset << (NTP_SCALE_SHIFT - SHIFT_FLL),
+				    mtemp);
+		time_status |= STA_MODE;
+	}
+	freq_adj += time_freq;
+	freq_adj = min(freq_adj, MAXFREQ_SCALED);
+	time_freq = max(freq_adj, -MAXFREQ_SCALED);
+
+	time_offset = div_s64((s64)offset << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
 }
 
 /**
@@ -78,6 +123,54 @@
 }
 
 /*
+ * Leap second processing. If in leap-insert state at the end of the
+ * day, the system clock is set back one second; if in leap-delete
+ * state, the system clock is set ahead one second.
+ */
+static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
+{
+	enum hrtimer_restart res = HRTIMER_NORESTART;
+
+	write_seqlock_irq(&xtime_lock);
+
+	switch (time_state) {
+	case TIME_OK:
+		break;
+	case TIME_INS:
+		xtime.tv_sec--;
+		wall_to_monotonic.tv_sec++;
+		time_state = TIME_OOP;
+		printk(KERN_NOTICE "Clock: "
+		       "inserting leap second 23:59:60 UTC\n");
+		leap_timer.expires = ktime_add_ns(leap_timer.expires,
+						  NSEC_PER_SEC);
+		res = HRTIMER_RESTART;
+		break;
+	case TIME_DEL:
+		xtime.tv_sec++;
+		time_tai--;
+		wall_to_monotonic.tv_sec--;
+		time_state = TIME_WAIT;
+		printk(KERN_NOTICE "Clock: "
+		       "deleting leap second 23:59:59 UTC\n");
+		break;
+	case TIME_OOP:
+		time_tai++;
+		time_state = TIME_WAIT;
+		/* fall through */
+	case TIME_WAIT:
+		if (!(time_status & (STA_INS | STA_DEL)))
+			time_state = TIME_OK;
+		break;
+	}
+	update_vsyscall(&xtime, clock);
+
+	write_sequnlock_irq(&xtime_lock);
+
+	return res;
+}
+
+/*
  * this routine handles the overflow of the microsecond field
  *
  * The tricky bits of code to handle the accurate clock support
@@ -87,63 +180,23 @@
  */
 void second_overflow(void)
 {
-	long time_adj;
+	s64 time_adj;
 
 	/* Bump the maxerror field */
-	time_maxerror += MAXFREQ >> SHIFT_USEC;
+	time_maxerror += MAXFREQ / NSEC_PER_USEC;
 	if (time_maxerror > NTP_PHASE_LIMIT) {
 		time_maxerror = NTP_PHASE_LIMIT;
 		time_status |= STA_UNSYNC;
 	}
 
 	/*
-	 * Leap second processing. If in leap-insert state at the end of the
-	 * day, the system clock is set back one second; if in leap-delete
-	 * state, the system clock is set ahead one second. The microtime()
-	 * routine or external clock driver will insure that reported time is
-	 * always monotonic. The ugly divides should be replaced.
-	 */
-	switch (time_state) {
-	case TIME_OK:
-		if (time_status & STA_INS)
-			time_state = TIME_INS;
-		else if (time_status & STA_DEL)
-			time_state = TIME_DEL;
-		break;
-	case TIME_INS:
-		if (xtime.tv_sec % 86400 == 0) {
-			xtime.tv_sec--;
-			wall_to_monotonic.tv_sec++;
-			time_state = TIME_OOP;
-			printk(KERN_NOTICE "Clock: inserting leap second "
-					"23:59:60 UTC\n");
-		}
-		break;
-	case TIME_DEL:
-		if ((xtime.tv_sec + 1) % 86400 == 0) {
-			xtime.tv_sec++;
-			wall_to_monotonic.tv_sec--;
-			time_state = TIME_WAIT;
-			printk(KERN_NOTICE "Clock: deleting leap second "
-					"23:59:59 UTC\n");
-		}
-		break;
-	case TIME_OOP:
-		time_state = TIME_WAIT;
-		break;
-	case TIME_WAIT:
-		if (!(time_status & (STA_INS | STA_DEL)))
-		time_state = TIME_OK;
-	}
-
-	/*
 	 * Compute the phase adjustment for the next second. The offset is
 	 * reduced by a fixed factor times the time constant.
 	 */
 	tick_length = tick_length_base;
 	time_adj = shift_right(time_offset, SHIFT_PLL + time_constant);
 	time_offset -= time_adj;
-	tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
+	tick_length += time_adj;
 
 	if (unlikely(time_adjust)) {
 		if (time_adjust > MAX_TICKADJ) {
@@ -154,25 +207,12 @@
 			tick_length -= MAX_TICKADJ_SCALED;
 		} else {
 			tick_length += (s64)(time_adjust * NSEC_PER_USEC /
-					NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
+					NTP_INTERVAL_FREQ) << NTP_SCALE_SHIFT;
 			time_adjust = 0;
 		}
 	}
 }
 
-/*
- * Return how long ticks are at the moment, that is, how much time
- * update_wall_time_one_tick will add to xtime next time we call it
- * (assuming no calls to do_adjtimex in the meantime).
- * The return value is in fixed-point nanoseconds shifted by the
- * specified number of bits to the right of the binary point.
- * This function has no side-effects.
- */
-u64 current_tick_length(void)
-{
-	return tick_length;
-}
-
 #ifdef CONFIG_GENERIC_CMOS_UPDATE
 
 /* Disable the cmos update - used by virtualization and embedded */
@@ -236,8 +276,8 @@
  */
 int do_adjtimex(struct timex *txc)
 {
-	long mtemp, save_adjust, rem;
-	s64 freq_adj, temp64;
+	struct timespec ts;
+	long save_adjust, sec;
 	int result;
 
 	/* In order to modify anything, you gotta be super-user! */
@@ -247,147 +287,132 @@
 	/* Now we validate the data before disabling interrupts */
 
 	if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) {
-	  /* singleshot must not be used with any other mode bits */
-		if (txc->modes != ADJ_OFFSET_SINGLESHOT &&
-					txc->modes != ADJ_OFFSET_SS_READ)
+		/* singleshot must not be used with any other mode bits */
+		if (txc->modes & ~ADJ_OFFSET_SS_READ)
 			return -EINVAL;
 	}
 
-	if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
-	  /* adjustment Offset limited to +- .512 seconds */
-		if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
-			return -EINVAL;
-
 	/* if the quartz is off by more than 10% something is VERY wrong ! */
 	if (txc->modes & ADJ_TICK)
 		if (txc->tick <  900000/USER_HZ ||
 		    txc->tick > 1100000/USER_HZ)
 			return -EINVAL;
 
+	if (time_state != TIME_OK && txc->modes & ADJ_STATUS)
+		hrtimer_cancel(&leap_timer);
+	getnstimeofday(&ts);
+
 	write_seqlock_irq(&xtime_lock);
-	result = time_state;	/* mostly `TIME_OK' */
 
 	/* Save for later - semantics of adjtime is to return old value */
 	save_adjust = time_adjust;
 
-#if 0	/* STA_CLOCKERR is never set yet */
-	time_status &= ~STA_CLOCKERR;		/* reset STA_CLOCKERR */
-#endif
 	/* If there are input parameters, then process them */
-	if (txc->modes)
-	{
-	    if (txc->modes & ADJ_STATUS)	/* only set allowed bits */
-		time_status =  (txc->status & ~STA_RONLY) |
-			      (time_status & STA_RONLY);
-
-	    if (txc->modes & ADJ_FREQUENCY) {	/* p. 22 */
-		if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
-		    result = -EINVAL;
-		    goto leave;
-		}
-		time_freq = ((s64)txc->freq * NSEC_PER_USEC)
-				>> (SHIFT_USEC - SHIFT_NSEC);
-	    }
-
-	    if (txc->modes & ADJ_MAXERROR) {
-		if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
-		    result = -EINVAL;
-		    goto leave;
-		}
-		time_maxerror = txc->maxerror;
-	    }
-
-	    if (txc->modes & ADJ_ESTERROR) {
-		if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
-		    result = -EINVAL;
-		    goto leave;
-		}
-		time_esterror = txc->esterror;
-	    }
-
-	    if (txc->modes & ADJ_TIMECONST) {	/* p. 24 */
-		if (txc->constant < 0) {	/* NTP v4 uses values > 6 */
-		    result = -EINVAL;
-		    goto leave;
-		}
-		time_constant = min(txc->constant + 4, (long)MAXTC);
-	    }
-
-	    if (txc->modes & ADJ_OFFSET) {	/* values checked earlier */
-		if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
-		    /* adjtime() is independent from ntp_adjtime() */
-		    time_adjust = txc->offset;
-		}
-		else if (time_status & STA_PLL) {
-		    time_offset = txc->offset * NSEC_PER_USEC;
-
-		    /*
-		     * Scale the phase adjustment and
-		     * clamp to the operating range.
-		     */
-		    time_offset = min(time_offset, (s64)MAXPHASE * NSEC_PER_USEC);
-		    time_offset = max(time_offset, (s64)-MAXPHASE * NSEC_PER_USEC);
-
-		    /*
-		     * Select whether the frequency is to be controlled
-		     * and in which mode (PLL or FLL). Clamp to the operating
-		     * range. Ugly multiply/divide should be replaced someday.
-		     */
-
-		    if (time_status & STA_FREQHOLD || time_reftime == 0)
-		        time_reftime = xtime.tv_sec;
-		    mtemp = xtime.tv_sec - time_reftime;
-		    time_reftime = xtime.tv_sec;
-
-		    freq_adj = time_offset * mtemp;
-		    freq_adj = shift_right(freq_adj, time_constant * 2 +
-					   (SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
-		    if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
-			u64 utemp64;
-			temp64 = time_offset << (SHIFT_NSEC - SHIFT_FLL);
-			if (time_offset < 0) {
-			    utemp64 = -temp64;
-			    do_div(utemp64, mtemp);
-			    freq_adj -= utemp64;
-			} else {
-			    utemp64 = temp64;
-			    do_div(utemp64, mtemp);
-			    freq_adj += utemp64;
+	if (txc->modes) {
+		if (txc->modes & ADJ_STATUS) {
+			if ((time_status & STA_PLL) &&
+			    !(txc->status & STA_PLL)) {
+				time_state = TIME_OK;
+				time_status = STA_UNSYNC;
 			}
-		    }
-		    freq_adj += time_freq;
-		    freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
-		    time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
-		    time_offset = div_long_long_rem_signed(time_offset,
-							   NTP_INTERVAL_FREQ,
-							   &rem);
-		    time_offset <<= SHIFT_UPDATE;
-		} /* STA_PLL */
-	    } /* txc->modes & ADJ_OFFSET */
-	    if (txc->modes & ADJ_TICK)
-		tick_usec = txc->tick;
+			/* only set allowed bits */
+			time_status &= STA_RONLY;
+			time_status |= txc->status & ~STA_RONLY;
 
-	    if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
-		    ntp_update_frequency();
-	} /* txc->modes */
-leave:	if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
+			switch (time_state) {
+			case TIME_OK:
+			start_timer:
+				sec = ts.tv_sec;
+				if (time_status & STA_INS) {
+					time_state = TIME_INS;
+					sec += 86400 - sec % 86400;
+					hrtimer_start(&leap_timer, ktime_set(sec, 0), HRTIMER_MODE_ABS);
+				} else if (time_status & STA_DEL) {
+					time_state = TIME_DEL;
+					sec += 86400 - (sec + 1) % 86400;
+					hrtimer_start(&leap_timer, ktime_set(sec, 0), HRTIMER_MODE_ABS);
+				}
+				break;
+			case TIME_INS:
+			case TIME_DEL:
+				time_state = TIME_OK;
+				goto start_timer;
+				break;
+			case TIME_WAIT:
+				if (!(time_status & (STA_INS | STA_DEL)))
+					time_state = TIME_OK;
+				break;
+			case TIME_OOP:
+				hrtimer_restart(&leap_timer);
+				break;
+			}
+		}
+
+		if (txc->modes & ADJ_NANO)
+			time_status |= STA_NANO;
+		if (txc->modes & ADJ_MICRO)
+			time_status &= ~STA_NANO;
+
+		if (txc->modes & ADJ_FREQUENCY) {
+			time_freq = (s64)txc->freq * PPM_SCALE;
+			time_freq = min(time_freq, MAXFREQ_SCALED);
+			time_freq = max(time_freq, -MAXFREQ_SCALED);
+		}
+
+		if (txc->modes & ADJ_MAXERROR)
+			time_maxerror = txc->maxerror;
+		if (txc->modes & ADJ_ESTERROR)
+			time_esterror = txc->esterror;
+
+		if (txc->modes & ADJ_TIMECONST) {
+			time_constant = txc->constant;
+			if (!(time_status & STA_NANO))
+				time_constant += 4;
+			time_constant = min(time_constant, (long)MAXTC);
+			time_constant = max(time_constant, 0l);
+		}
+
+		if (txc->modes & ADJ_TAI && txc->constant > 0)
+			time_tai = txc->constant;
+
+		if (txc->modes & ADJ_OFFSET) {
+			if (txc->modes == ADJ_OFFSET_SINGLESHOT)
+				/* adjtime() is independent from ntp_adjtime() */
+				time_adjust = txc->offset;
+			else
+				ntp_update_offset(txc->offset);
+		}
+		if (txc->modes & ADJ_TICK)
+			tick_usec = txc->tick;
+
+		if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
+			ntp_update_frequency();
+	}
+
+	result = time_state;	/* mostly `TIME_OK' */
+	if (time_status & (STA_UNSYNC|STA_CLOCKERR))
 		result = TIME_ERROR;
 
 	if ((txc->modes == ADJ_OFFSET_SINGLESHOT) ||
-			(txc->modes == ADJ_OFFSET_SS_READ))
+	    (txc->modes == ADJ_OFFSET_SS_READ))
 		txc->offset = save_adjust;
-	else
-		txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) *
-	    			NTP_INTERVAL_FREQ / 1000;
-	txc->freq	   = (time_freq / NSEC_PER_USEC) <<
-				(SHIFT_USEC - SHIFT_NSEC);
+	else {
+		txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
+					  NTP_SCALE_SHIFT);
+		if (!(time_status & STA_NANO))
+			txc->offset /= NSEC_PER_USEC;
+	}
+	txc->freq	   = shift_right((s32)(time_freq >> PPM_SCALE_INV_SHIFT) *
+					 (s64)PPM_SCALE_INV,
+					 NTP_SCALE_SHIFT);
 	txc->maxerror	   = time_maxerror;
 	txc->esterror	   = time_esterror;
 	txc->status	   = time_status;
 	txc->constant	   = time_constant;
 	txc->precision	   = 1;
-	txc->tolerance	   = MAXFREQ;
+	txc->tolerance	   = MAXFREQ_SCALED / PPM_SCALE;
 	txc->tick	   = tick_usec;
+	txc->tai	   = time_tai;
 
 	/* PPS is not implemented, so these are zero */
 	txc->ppsfreq	   = 0;
@@ -399,9 +424,15 @@
 	txc->errcnt	   = 0;
 	txc->stbcnt	   = 0;
 	write_sequnlock_irq(&xtime_lock);
-	do_gettimeofday(&txc->time);
+
+	txc->time.tv_sec = ts.tv_sec;
+	txc->time.tv_usec = ts.tv_nsec;
+	if (!(time_status & STA_NANO))
+		txc->time.tv_usec /= NSEC_PER_USEC;
+
 	notify_cmos_timer();
-	return(result);
+
+	return result;
 }
 
 static int __init ntp_tick_adj_setup(char *str)
@@ -411,3 +442,10 @@
 }
 
 __setup("ntp_tick_adj=", ntp_tick_adj_setup);
+
+void __init ntp_init(void)
+{
+	ntp_clear();
+	hrtimer_init(&leap_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+	leap_timer.function = ntp_leap_second;
+}
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 2d6087c..e91c29f 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -53,7 +53,7 @@
 	timespec_add_ns(&xtime_cache, nsec);
 }
 
-static struct clocksource *clock; /* pointer to current clocksource */
+struct clocksource *clock;
 
 
 #ifdef CONFIG_GENERIC_TIME
@@ -246,7 +246,7 @@
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 
-	ntp_clear();
+	ntp_init();
 
 	clock = clocksource_get_next();
 	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
@@ -371,7 +371,7 @@
 	 * here.  This is tuned so that an error of about 1 msec is adjusted
 	 * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
 	 */
-	error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
+	error2 = clock->error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ);
 	error2 = abs(error2);
 	for (look_ahead = 0; error2 > 0; look_ahead++)
 		error2 >>= 2;
@@ -380,8 +380,7 @@
 	 * Now calculate the error in (1 << look_ahead) ticks, but first
 	 * remove the single look ahead already included in the error.
 	 */
-	tick_error = current_tick_length() >>
-		(TICK_LENGTH_SHIFT - clock->shift + 1);
+	tick_error = tick_length >> (NTP_SCALE_SHIFT - clock->shift + 1);
 	tick_error -= clock->xtime_interval >> 1;
 	error = ((error - tick_error) >> look_ahead) + tick_error;
 
@@ -412,7 +411,7 @@
 	s64 error, interval = clock->cycle_interval;
 	int adj;
 
-	error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
+	error = clock->error >> (NTP_SCALE_SHIFT - clock->shift - 1);
 	if (error > interval) {
 		error >>= 2;
 		if (likely(error <= interval))
@@ -434,7 +433,7 @@
 	clock->xtime_interval += interval;
 	clock->xtime_nsec -= offset;
 	clock->error -= (interval - offset) <<
-			(TICK_LENGTH_SHIFT - clock->shift);
+			(NTP_SCALE_SHIFT - clock->shift);
 }
 
 /**
@@ -473,8 +472,8 @@
 		}
 
 		/* accumulate error between NTP and clock interval */
-		clock->error += current_tick_length();
-		clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
+		clock->error += tick_length;
+		clock->error -= clock->xtime_interval << (NTP_SCALE_SHIFT - clock->shift);
 	}
 
 	/* correct the clock when NTP error is too big */
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 721093a..29fc39f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -195,7 +195,6 @@
 int queue_delayed_work(struct workqueue_struct *wq,
 			struct delayed_work *dwork, unsigned long delay)
 {
-	timer_stats_timer_set_start_info(&dwork->timer);
 	if (delay == 0)
 		return queue_work(wq, &dwork->work);
 
@@ -219,11 +218,12 @@
 	struct timer_list *timer = &dwork->timer;
 	struct work_struct *work = &dwork->work;
 
-	timer_stats_timer_set_start_info(&dwork->timer);
 	if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
 		BUG_ON(timer_pending(timer));
 		BUG_ON(!list_empty(&work->entry));
 
+		timer_stats_timer_set_start_info(&dwork->timer);
+
 		/* This stores cwq for the moment, for the timer_fn */
 		set_wq_data(work, wq_per_cpu(wq, raw_smp_processor_id()));
 		timer->expires = jiffies + delay;
@@ -564,7 +564,6 @@
 int schedule_delayed_work(struct delayed_work *dwork,
 					unsigned long delay)
 {
-	timer_stats_timer_set_start_info(&dwork->timer);
 	return queue_delayed_work(keventd_wq, dwork, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work);
@@ -581,7 +580,6 @@
 int schedule_delayed_work_on(int cpu,
 			struct delayed_work *dwork, unsigned long delay)
 {
-	timer_stats_timer_set_start_info(&dwork->timer);
 	return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work_on);
diff --git a/lib/div64.c b/lib/div64.c
index b71cf93..bb5bd0c 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -16,9 +16,8 @@
  * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
  */
 
-#include <linux/types.h>
 #include <linux/module.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
 
 /* Not needed on 64bit architectures */
 #if BITS_PER_LONG == 32
@@ -58,10 +57,31 @@
 
 EXPORT_SYMBOL(__div64_32);
 
-/* 64bit divisor, dividend and result. dynamic precision */
-uint64_t div64_64(uint64_t dividend, uint64_t divisor)
+#ifndef div_s64_rem
+s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
 {
-	uint32_t high, d;
+	u64 quotient;
+
+	if (dividend < 0) {
+		quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
+		*remainder = -*remainder;
+		if (divisor > 0)
+			quotient = -quotient;
+	} else {
+		quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
+		if (divisor < 0)
+			quotient = -quotient;
+	}
+	return quotient;
+}
+EXPORT_SYMBOL(div_s64_rem);
+#endif
+
+/* 64bit divisor, dividend and result. dynamic precision */
+#ifndef div64_u64
+u64 div64_u64(u64 dividend, u64 divisor)
+{
+	u32 high, d;
 
 	high = divisor >> 32;
 	if (high) {
@@ -72,10 +92,9 @@
 	} else
 		d = divisor;
 
-	do_div(dividend, d);
-
-	return dividend;
+	return div_u64(dividend, d);
 }
-EXPORT_SYMBOL(div64_64);
+EXPORT_SYMBOL(div64_u64);
+#endif
 
 #endif /* BITS_PER_LONG == 32 */
diff --git a/lib/idr.c b/lib/idr.c
index 8368c81..7a02e17 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -385,8 +385,8 @@
 	while (idp->id_free_cnt >= IDR_FREE_MAX) {
 		p = alloc_layer(idp);
 		kmem_cache_free(idr_layer_cache, p);
-		return;
 	}
+	return;
 }
 EXPORT_SYMBOL(idr_remove);
 
diff --git a/lib/string.c b/lib/string.c
index 5efafed..b19b87a 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -493,6 +493,33 @@
 EXPORT_SYMBOL(strsep);
 #endif
 
+/**
+ * sysfs_streq - return true if strings are equal, modulo trailing newline
+ * @s1: one string
+ * @s2: another string
+ *
+ * This routine returns true iff two strings are equal, treating both
+ * NUL and newline-then-NUL as equivalent string terminations.  It's
+ * geared for use with sysfs input strings, which generally terminate
+ * with newlines but are compared against values without newlines.
+ */
+bool sysfs_streq(const char *s1, const char *s2)
+{
+	while (*s1 && *s1 == *s2) {
+		s1++;
+		s2++;
+	}
+
+	if (*s1 == *s2)
+		return true;
+	if (!*s1 && *s2 == '\n' && !s2[1])
+		return true;
+	if (*s1 == '\n' && !s1[1] && !*s2)
+		return true;
+	return false;
+}
+EXPORT_SYMBOL(sysfs_streq);
+
 #ifndef __HAVE_ARCH_MEMSET
 /**
  * memset - Fill a region of memory with the given value
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 33add96..e46451e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -48,6 +48,8 @@
 	 */
 	MEM_CGROUP_STAT_CACHE, 	   /* # of pages charged as cache */
 	MEM_CGROUP_STAT_RSS,	   /* # of pages charged as rss */
+	MEM_CGROUP_STAT_PGPGIN_COUNT,	/* # of pages paged in */
+	MEM_CGROUP_STAT_PGPGOUT_COUNT,	/* # of pages paged out */
 
 	MEM_CGROUP_STAT_NSTATS,
 };
@@ -199,6 +201,13 @@
 		__mem_cgroup_stat_add_safe(stat, MEM_CGROUP_STAT_CACHE, val);
 	else
 		__mem_cgroup_stat_add_safe(stat, MEM_CGROUP_STAT_RSS, val);
+
+	if (charge)
+		__mem_cgroup_stat_add_safe(stat,
+				MEM_CGROUP_STAT_PGPGIN_COUNT, 1);
+	else
+		__mem_cgroup_stat_add_safe(stat,
+				MEM_CGROUP_STAT_PGPGOUT_COUNT, 1);
 }
 
 static struct mem_cgroup_per_zone *
@@ -884,6 +893,8 @@
 } mem_cgroup_stat_desc[] = {
 	[MEM_CGROUP_STAT_CACHE] = { "cache", PAGE_SIZE, },
 	[MEM_CGROUP_STAT_RSS] = { "rss", PAGE_SIZE, },
+	[MEM_CGROUP_STAT_PGPGIN_COUNT] = {"pgpgin", 1, },
+	[MEM_CGROUP_STAT_PGPGOUT_COUNT] = {"pgpgout", 1, },
 };
 
 static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
diff --git a/mm/slub.c b/mm/slub.c
index 70db289..32b6262 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -22,6 +22,7 @@
 #include <linux/debugobjects.h>
 #include <linux/kallsyms.h>
 #include <linux/memory.h>
+#include <linux/math64.h>
 
 /*
  * Lock order:
@@ -3621,12 +3622,10 @@
 			len += sprintf(buf + len, "<not-available>");
 
 		if (l->sum_time != l->min_time) {
-			unsigned long remainder;
-
 			len += sprintf(buf + len, " age=%ld/%ld/%ld",
-			l->min_time,
-			div_long_long_rem(l->sum_time, l->count, &remainder),
-			l->max_time);
+				l->min_time,
+				(long)div_u64(l->sum_time, l->count),
+				l->max_time);
 		} else
 			len += sprintf(buf + len, " age=%ld",
 				l->min_time);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 2a39cf1..6e45b0f 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -547,6 +547,7 @@
  *	@gfp_mask:	flags for the page level allocator
  *	@prot:		protection mask for the allocated pages
  *	@node:		node to use for allocation or -1
+ *	@caller:	caller's return address
  *
  *	Allocate enough pages to cover @size from the page level
  *	allocator with @gfp_mask flags.  Map them into contiguous
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index eb5b985..4a1221e 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -15,8 +15,8 @@
 
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/math64.h>
 #include <net/tcp.h>
-#include <asm/div64.h>
 
 #define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
 					 * max_cwnd = snd_cwnd * beta
@@ -128,7 +128,7 @@
 	 * x    = ( 2 * x  +  a / x  ) / 3
 	 *  k+1          k         k
 	 */
-	x = (2 * x + (u32)div64_64(a, (u64)x * (u64)(x - 1)));
+	x = (2 * x + (u32)div64_u64(a, (u64)x * (u64)(x - 1)));
 	x = ((x * 341) >> 10);
 	return x;
 }
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index b15e7e2..d7e8983 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -4,12 +4,11 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/skbuff.h>
+#include <linux/math64.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_connbytes.h>
 #include <net/netfilter/nf_conntrack.h>
 
-#include <asm/div64.h>
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
@@ -82,7 +81,7 @@
 			break;
 		}
 		if (pkts != 0)
-			what = div64_64(bytes, pkts);
+			what = div64_u64(bytes, pkts);
 		break;
 	}
 
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index 62e1e02..5552154 100644
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -36,8 +36,10 @@
 
 # Check if we can link to ncurses
 check() {
-	echo -e " #include CURSES_LOC \n main() {}" |
-	    $cc -xc - -o $tmp 2> /dev/null
+        $cc -xc - -o $tmp 2>/dev/null <<'EOF'
+#include CURSES_LOC
+main() {}
+EOF
 	if [ $? != 0 ]; then
 	    echo " *** Unable to find the ncurses libraries or the"       1>&2
 	    echo " *** required header files."                            1>&2