aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-04-07 11:36:05 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-07 11:36:05 -0700
commitdf2e2ae323420a682d025d4a636ecff274d96504 (patch)
tree13da938dde22fe8ec09cf16eeb85ecf0a3d33e1e
parent8ed491e1d162e90f33cfcd12b8017e739234aad9 (diff)
downloadpatches-df2e2ae323420a682d025d4a636ecff274d96504.tar.gz
bugfixes for usb and staging
-rw-r--r--series23
-rw-r--r--staging/revert-staging-slicoss-use-gfp_kernel-where-possible.patch38
-rw-r--r--staging/staging-aten2011-clean-up-some-tty-bits.patch70
-rw-r--r--staging/staging-binder-add-more-offset-validation.patch54
-rw-r--r--staging/staging-binder-cast-to-uintptr_t-instead-of-size_t-when-aligning-pointers.patch113
-rw-r--r--staging/staging-binder-defer-flush-and-release-operations-to-avoid-deadlocks.patch257
-rw-r--r--staging/staging-binder-don-t-create-two-proc-entries-with-the-same-name-if-the-driver-is-opened-twice-in-one-process.patch26
-rw-r--r--staging/staging-binder-keep-a-reference-to-the-files_struct-while-the-driver-is-mmapped.patch235
-rw-r--r--staging/staging-binder-mmap-fixes.patch49
-rw-r--r--staging/staging-binder-prevent-the-wrong-thread-from-adding-a-transaction-to-the-stack.patch39
-rw-r--r--staging/staging-binder-remove-vm_exec-check.patch32
-rw-r--r--staging/staging-stlc45xx-should-depend-on-generic_hardirqs.patch31
-rw-r--r--usb.current/usb-fix-oops-in-cdc-wdm-in-case-of-malformed-descriptors.patch31
-rw-r--r--usb.current/usb-musb-bugfixes-for-multi-packet-txdma-support.patch206
-rw-r--r--usb.current/usb-musb-fix-isochronous-txdma.patch424
-rw-r--r--usb.current/usb-musb-fix-possible-panic-while-resuming.patch64
-rw-r--r--usb.current/usb-musb-sanitize-clearing-txcsr-dma-bits.patch360
-rw-r--r--usb.current/usb-musb_host-fix-ep0-fifo-flushing.patch116
-rw-r--r--usb.current/usb-musb_host-minor-enqueue-locking-fix.patch64
-rw-r--r--usb.current/usb-option-add-ids-for-d-link-dwm-652-3.5g-modem.patch66
-rw-r--r--usb.current/usb-qcserial-add-extra-device-ids.patch52
-rw-r--r--usb.current/usb-usb-storage-augment-unusual_devs-entry-for-simple-tech-datafab.patch41
-rw-r--r--version2
23 files changed, 2392 insertions, 1 deletions
diff --git a/series b/series
index e5988fb5641014..5f9f7a177cbacd 100644
--- a/series
+++ b/series
@@ -19,6 +19,17 @@ driver-core.current/driver-core-allow-non-root-users-to-listen-to-uevents.patch
#################################
usb.current/usb-gadget-fix-ethernet-link-reports-to-ethtool.patch
usb.current/usb-ftdi_sio-add-vendor-project-id-for-jeti-specbos-1201-spectrometer.patch
+usb.current/usb-option-add-ids-for-d-link-dwm-652-3.5g-modem.patch
+usb.current/usb-qcserial-add-extra-device-ids.patch
+usb.current/usb-fix-oops-in-cdc-wdm-in-case-of-malformed-descriptors.patch
+usb.current/usb-musb_host-minor-enqueue-locking-fix.patch
+usb.current/usb-usb-storage-augment-unusual_devs-entry-for-simple-tech-datafab.patch
+usb.current/usb-musb_host-fix-ep0-fifo-flushing.patch
+usb.current/usb-musb-bugfixes-for-multi-packet-txdma-support.patch
+usb.current/usb-musb-sanitize-clearing-txcsr-dma-bits.patch
+usb.current/usb-musb-fix-isochronous-txdma.patch
+usb.current/usb-musb-fix-possible-panic-while-resuming.patch
+
#####################################################################
# Stuff to be merged after 2.6.30 is out
@@ -54,6 +65,17 @@ staging/staging-sxg-convert-to-netdev_ops.patch
staging/staging-wlan-ng-convert-to-netdev_ops.patch
staging/staging-line6-convert-to-snd_card_create.patch
staging/staging-rt2870-add-id-for-sitecom-wl-315.patch
+staging/staging-aten2011-clean-up-some-tty-bits.patch
+staging/staging-binder-remove-vm_exec-check.patch
+staging/staging-binder-don-t-create-two-proc-entries-with-the-same-name-if-the-driver-is-opened-twice-in-one-process.patch
+staging/staging-binder-mmap-fixes.patch
+staging/staging-binder-add-more-offset-validation.patch
+staging/staging-binder-keep-a-reference-to-the-files_struct-while-the-driver-is-mmapped.patch
+staging/staging-binder-cast-to-uintptr_t-instead-of-size_t-when-aligning-pointers.patch
+staging/staging-binder-prevent-the-wrong-thread-from-adding-a-transaction-to-the-stack.patch
+staging/staging-binder-defer-flush-and-release-operations-to-avoid-deadlocks.patch
+staging/staging-stlc45xx-should-depend-on-generic_hardirqs.patch
+staging/revert-staging-slicoss-use-gfp_kernel-where-possible.patch
# for after .30:
@@ -66,3 +88,4 @@ staging/staging-rt2870-add-id-for-sitecom-wl-315.patch
#staging/staging-add-intel-poulsbo-morrestown-drm-driver.patch
+
diff --git a/staging/revert-staging-slicoss-use-gfp_kernel-where-possible.patch b/staging/revert-staging-slicoss-use-gfp_kernel-where-possible.patch
new file mode 100644
index 00000000000000..f22c4e9a34f391
--- /dev/null
+++ b/staging/revert-staging-slicoss-use-gfp_kernel-where-possible.patch
@@ -0,0 +1,38 @@
+From 2bb347361e2c19799431f56488a3f64de40a3aa6 Mon Sep 17 00:00:00 2001
+From: Lior Dotan <liodot@gmail.com>
+Date: Wed, 11 Feb 2009 13:35:10 +0200
+Subject: Revert Staging: SLICOSS: use gfp_kernel where possible
+
+Revert commit 2bb347361e2c19799431f56488a3f64de40a3aa6
+
+This commit has been reported to cause problems:
+ Mar 24 11:50:31 linuxdev kernel: BUG: sleeping function called from invalid context at mm/slub.c:1599 Mar 24 11:50:31 linuxdev kernel: in_atomic(): 1, irqs_disabled(): 0, pid: 3251, name: avahi-daemon
+
+Cc: Lior Dotan <liodot@gmail.com>
+Cc: Christopher Harrer <charrer@alacritech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/slicoss/slicoss.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/slicoss/slicoss.c
++++ b/drivers/staging/slicoss/slicoss.c
+@@ -1267,7 +1267,7 @@ static int slic_mcast_add_list(struct ad
+ }
+
+ /* Doesn't already exist. Allocate a structure to hold it */
+- mcaddr = kmalloc(sizeof(struct mcast_address), GFP_KERNEL);
++ mcaddr = kmalloc(sizeof(struct mcast_address), GFP_ATOMIC);
+ if (mcaddr == NULL)
+ return 1;
+
+@@ -2291,7 +2291,7 @@ static u32 slic_card_locate(struct adapt
+ }
+ if (!physcard) {
+ /* no structure allocated for this physical card yet */
+- physcard = kzalloc(sizeof(struct physcard), GFP_KERNEL);
++ physcard = kzalloc(sizeof(struct physcard), GFP_ATOMIC);
+ ASSERT(physcard);
+
+ physcard->next = slic_global.phys_card;
diff --git a/staging/staging-aten2011-clean-up-some-tty-bits.patch b/staging/staging-aten2011-clean-up-some-tty-bits.patch
new file mode 100644
index 00000000000000..0a951efb9ba48a
--- /dev/null
+++ b/staging/staging-aten2011-clean-up-some-tty-bits.patch
@@ -0,0 +1,70 @@
+From alan@lxorguk.ukuu.org.uk Tue Apr 7 11:10:30 2009
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Date: Tue, 07 Apr 2009 18:43:43 +0100
+Subject: Staging: aten2011: Clean up some tty bits
+To: greg@kroah.com, linux-usb@vger.kernel.org
+Message-ID: <20090407174342.19104.65668.stgit@t61.ukuu.org.uk>
+
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+Minor fixes for tty layer stuff in this driver
+
+Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/uc2322/aten2011.c | 28 +++-------------------------
+ 1 file changed, 3 insertions(+), 25 deletions(-)
+
+--- a/drivers/staging/uc2322/aten2011.c
++++ b/drivers/staging/uc2322/aten2011.c
+@@ -603,10 +603,9 @@ static void ATEN2011_bulk_out_data_callb
+
+ tty = tty_port_tty_get(&ATEN2011_port->port->port);
+
+- if (tty && ATEN2011_port->open) {
++ if (tty && ATEN2011_port->open)
+ /* tell the tty driver that something has changed */
+- wake_up_interruptible(&tty->write_wait);
+- }
++ tty_wakeup(tty);
+
+ /* schedule_work(&ATEN2011_port->port->work); */
+ tty_kref_put(tty);
+@@ -825,12 +824,6 @@ static int ATEN2011_open(struct tty_stru
+ status = 0;
+ status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data);
+
+- /* force low_latency on so that our tty_push actually forces *
+- * the data through,otherwise it is scheduled, and with *
+- * high data rates (like with OHCI) data can get lost. */
+-
+- if (tty)
+- tty->low_latency = 1;
+ /*
+ * Check to see if we've set up our endpoint info yet
+ * (can't set it up in ATEN2011_startup as the structures
+@@ -1473,22 +1466,7 @@ static void ATEN2011_set_termios(struct
+
+ cflag = tty->termios->c_cflag;
+
+- if (!cflag) {
+- dbg("%s %s", __func__, "cflag is NULL");
+- return;
+- }
+-
+- /* check that they really want us to change something */
+- if (old_termios) {
+- if ((cflag == old_termios->c_cflag) &&
+- (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+- RELEVANT_IFLAG(old_termios->c_iflag))) {
+- dbg("%s", "Nothing to change");
+- return;
+- }
+- }
+-
+- dbg("%s - clfag %08x iflag %08x", __func__,
++ dbg("%s - cflag %08x iflag %08x", __func__,
+ tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
+
+ if (old_termios) {
diff --git a/staging/staging-binder-add-more-offset-validation.patch b/staging/staging-binder-add-more-offset-validation.patch
new file mode 100644
index 00000000000000..e1e77d038cabb0
--- /dev/null
+++ b/staging/staging-binder-add-more-offset-validation.patch
@@ -0,0 +1,54 @@
+From arve@android.com Tue Apr 7 11:15:56 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:56 -0700
+Subject: Staging: binder: Add more offset validation.
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-4-git-send-email-arve@android.com>
+
+
+Check that datasize is not smaller than one flat_binder_object.
+Check that offsets are aligned.
+Check that offsets_size is aligned.
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -1430,10 +1430,19 @@ binder_transaction(struct binder_proc *p
+ return_error = BR_FAILED_REPLY;
+ goto err_copy_data_failed;
+ }
++ if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
++ binder_user_error("binder: %d:%d got transaction with "
++ "invalid offsets size, %zd\n",
++ proc->pid, thread->pid, tr->offsets_size);
++ return_error = BR_FAILED_REPLY;
++ goto err_bad_offset;
++ }
+ off_end = (void *)offp + tr->offsets_size;
+ for (; offp < off_end; offp++) {
+ struct flat_binder_object *fp;
+- if (*offp > t->buffer->data_size - sizeof(*fp)) {
++ if (*offp > t->buffer->data_size - sizeof(*fp) ||
++ t->buffer->data_size < sizeof(*fp) ||
++ !IS_ALIGNED(*offp, sizeof(void *))) {
+ binder_user_error("binder: %d:%d got transaction with "
+ "invalid offset, %zd\n",
+ proc->pid, thread->pid, *offp);
+@@ -1651,7 +1660,9 @@ binder_transaction_buffer_release(struct
+ off_end = (void *)offp + buffer->offsets_size;
+ for (; offp < off_end; offp++) {
+ struct flat_binder_object *fp;
+- if (*offp > buffer->data_size - sizeof(*fp)) {
++ if (*offp > buffer->data_size - sizeof(*fp) ||
++ buffer->data_size < sizeof(*fp) ||
++ !IS_ALIGNED(*offp, sizeof(void *))) {
+ printk(KERN_ERR "binder: transaction release %d bad"
+ "offset %zd, size %zd\n", debug_id, *offp, buffer->data_size);
+ continue;
diff --git a/staging/staging-binder-cast-to-uintptr_t-instead-of-size_t-when-aligning-pointers.patch b/staging/staging-binder-cast-to-uintptr_t-instead-of-size_t-when-aligning-pointers.patch
new file mode 100644
index 00000000000000..fe1df85cf1f7ae
--- /dev/null
+++ b/staging/staging-binder-cast-to-uintptr_t-instead-of-size_t-when-aligning-pointers.patch
@@ -0,0 +1,113 @@
+From arve@android.com Tue Apr 7 11:17:15 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:58 -0700
+Subject: Staging: binder: Cast to uintptr_t instead of size_t when aligning pointers
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-6-git-send-email-arve@android.com>
+
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -246,7 +246,7 @@ struct binder_proc {
+ struct files_struct *files;
+ struct hlist_node release_files_node;
+ void *buffer;
+- size_t user_buffer_offset;
++ ptrdiff_t user_buffer_offset;
+
+ struct list_head buffers;
+ struct rb_root free_buffers;
+@@ -614,7 +614,8 @@ static int binder_update_page_range(stru
+ proc->pid, page_addr);
+ goto err_map_kernel_failed;
+ }
+- user_page_addr = (size_t)page_addr + proc->user_buffer_offset;
++ user_page_addr =
++ (uintptr_t)page_addr + proc->user_buffer_offset;
+ ret = vm_insert_page(vma, user_page_addr, page[0]);
+ if (ret) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+@@ -635,7 +636,7 @@ free_range:
+ page_addr -= PAGE_SIZE) {
+ page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
+ if (vma)
+- zap_page_range(vma, (size_t)page_addr +
++ zap_page_range(vma, (uintptr_t)page_addr +
+ proc->user_buffer_offset, PAGE_SIZE, NULL);
+ err_vm_insert_page_failed:
+ unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+@@ -716,18 +717,19 @@ static struct binder_buffer *binder_allo
+ "er %p size %zd\n", proc->pid, size, buffer, buffer_size);
+
+ has_page_addr =
+- (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK);
++ (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
+ if (n == NULL) {
+ if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
+ buffer_size = size; /* no room for other buffers */
+ else
+ buffer_size = size + sizeof(struct binder_buffer);
+ }
+- end_page_addr = (void *)PAGE_ALIGN((size_t)buffer->data + buffer_size);
++ end_page_addr =
++ (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
+ if (end_page_addr > has_page_addr)
+ end_page_addr = has_page_addr;
+ if (binder_update_page_range(proc, 1,
+- (void *)PAGE_ALIGN((size_t)buffer->data), end_page_addr, NULL))
++ (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
+ return NULL;
+
+ rb_erase(best_fit, &proc->free_buffers);
+@@ -758,12 +760,12 @@ static struct binder_buffer *binder_allo
+
+ static void *buffer_start_page(struct binder_buffer *buffer)
+ {
+- return (void *)((size_t)buffer & PAGE_MASK);
++ return (void *)((uintptr_t)buffer & PAGE_MASK);
+ }
+
+ static void *buffer_end_page(struct binder_buffer *buffer)
+ {
+- return (void *)(((size_t)(buffer + 1) - 1) & PAGE_MASK);
++ return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
+ }
+
+ static void binder_delete_free_buffer(
+@@ -841,8 +843,8 @@ static void binder_free_buf(
+ }
+
+ binder_update_page_range(proc, 0,
+- (void *)PAGE_ALIGN((size_t)buffer->data),
+- (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK),
++ (void *)PAGE_ALIGN((uintptr_t)buffer->data),
++ (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
+ NULL);
+ rb_erase(&buffer->rb_node, &proc->allocated_buffers);
+ buffer->free = 1;
+@@ -2347,7 +2349,7 @@ retry:
+
+ tr.data_size = t->buffer->data_size;
+ tr.offsets_size = t->buffer->offsets_size;
+- tr.data.ptr.buffer = (void *)((void *)t->buffer->data + proc->user_buffer_offset);
++ tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset;
+ tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));
+
+ if (put_user(cmd, (uint32_t __user *)ptr))
+@@ -2753,7 +2755,7 @@ static int binder_mmap(struct file *filp
+ goto err_get_vm_area_failed;
+ }
+ proc->buffer = area->addr;
+- proc->user_buffer_offset = vma->vm_start - (size_t)proc->buffer;
++ proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
+
+ #ifdef CONFIG_CPU_CACHE_VIPT
+ if (cache_is_vipt_aliasing()) {
diff --git a/staging/staging-binder-defer-flush-and-release-operations-to-avoid-deadlocks.patch b/staging/staging-binder-defer-flush-and-release-operations-to-avoid-deadlocks.patch
new file mode 100644
index 00000000000000..919343f3b80946
--- /dev/null
+++ b/staging/staging-binder-defer-flush-and-release-operations-to-avoid-deadlocks.patch
@@ -0,0 +1,257 @@
+From arve@android.com Tue Apr 7 11:18:11 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:13:00 -0700
+Subject: Staging: binder: Defer flush and release operations to avoid deadlocks.
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-8-git-send-email-arve@android.com>
+
+
+If a transaction that contains a file descriptor fails on a later object,
+the new file descriptor needs to be closed. If this is a binder file
+descriptor we would deadlock in flush. If there were no other references to
+the file at this point release would also be called.
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 149 +++++++++++++++++++++++----------------
+ 1 file changed, 88 insertions(+), 61 deletions(-)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -41,8 +41,8 @@ static int binder_last_id;
+ static struct proc_dir_entry *binder_proc_dir_entry_root;
+ static struct proc_dir_entry *binder_proc_dir_entry_proc;
+ static struct hlist_head binder_dead_nodes;
+-static HLIST_HEAD(binder_release_files_list);
+-static DEFINE_MUTEX(binder_release_files_lock);
++static HLIST_HEAD(binder_deferred_list);
++static DEFINE_MUTEX(binder_deferred_lock);
+
+ static int binder_read_proc_proc(
+ char *page, char **start, off_t off, int count, int *eof, void *data);
+@@ -234,6 +234,12 @@ struct binder_buffer {
+ uint8_t data[0];
+ };
+
++enum {
++ BINDER_DEFERRED_PUT_FILES = 0x01,
++ BINDER_DEFERRED_FLUSH = 0x02,
++ BINDER_DEFERRED_RELEASE = 0x04,
++};
++
+ struct binder_proc {
+ struct hlist_node proc_node;
+ struct rb_root threads;
+@@ -244,7 +250,8 @@ struct binder_proc {
+ struct vm_area_struct *vma;
+ struct task_struct *tsk;
+ struct files_struct *files;
+- struct hlist_node release_files_node;
++ struct hlist_node deferred_work_node;
++ int deferred_work;
+ void *buffer;
+ ptrdiff_t user_buffer_offset;
+
+@@ -310,6 +317,8 @@ struct binder_transaction {
+ uid_t sender_euid;
+ };
+
++static void binder_defer_work(struct binder_proc *proc, int defer);
++
+ /*
+ * copied from get_unused_fd_flags
+ */
+@@ -2677,33 +2686,6 @@ static void binder_vma_open(struct vm_ar
+ dump_stack();
+ }
+
+-static void binder_release_files(struct work_struct *work)
+-{
+- struct binder_proc *proc;
+- struct files_struct *files;
+- do {
+- mutex_lock(&binder_lock);
+- mutex_lock(&binder_release_files_lock);
+- if (!hlist_empty(&binder_release_files_list)) {
+- proc = hlist_entry(binder_release_files_list.first,
+- struct binder_proc, release_files_node);
+- hlist_del_init(&proc->release_files_node);
+- files = proc->files;
+- if (files)
+- proc->files = NULL;
+- } else {
+- proc = NULL;
+- files = NULL;
+- }
+- mutex_unlock(&binder_release_files_lock);
+- mutex_unlock(&binder_lock);
+- if (files)
+- put_files_struct(files);
+- } while (proc);
+-}
+-
+-static DECLARE_WORK(binder_release_files_work, binder_release_files);
+-
+ static void binder_vma_close(struct vm_area_struct *vma)
+ {
+ struct binder_proc *proc = vma->vm_private_data;
+@@ -2714,13 +2696,7 @@ static void binder_vma_close(struct vm_a
+ (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
+ (unsigned long)pgprot_val(vma->vm_page_prot));
+ proc->vma = NULL;
+- mutex_lock(&binder_release_files_lock);
+- if (proc->files) {
+- hlist_add_head(&proc->release_files_node,
+- &binder_release_files_list);
+- schedule_work(&binder_release_files_work);
+- }
+- mutex_unlock(&binder_release_files_lock);
++ binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
+ }
+
+ static struct vm_operations_struct binder_vm_ops = {
+@@ -2853,11 +2829,17 @@ static int binder_open(struct inode *nod
+
+ static int binder_flush(struct file *filp, fl_owner_t id)
+ {
+- struct rb_node *n;
+ struct binder_proc *proc = filp->private_data;
+- int wake_count = 0;
+
+- mutex_lock(&binder_lock);
++ binder_defer_work(proc, BINDER_DEFERRED_FLUSH);
++
++ return 0;
++}
++
++static void binder_deferred_flush(struct binder_proc *proc)
++{
++ struct rb_node *n;
++ int wake_count = 0;
+ for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
+ struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+ thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+@@ -2867,36 +2849,34 @@ static int binder_flush(struct file *fil
+ }
+ }
+ wake_up_interruptible_all(&proc->wait);
+- mutex_unlock(&binder_lock);
+
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder_flush: %d woke %d threads\n", proc->pid, wake_count);
+-
+- return 0;
+ }
+
+ static int binder_release(struct inode *nodp, struct file *filp)
+ {
+- struct hlist_node *pos;
+- struct binder_transaction *t;
+- struct rb_node *n;
+- struct files_struct *files;
+ struct binder_proc *proc = filp->private_data;
+- int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
+-
+ if (binder_proc_dir_entry_proc) {
+ char strbuf[11];
+ snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+ remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
+ }
+- mutex_lock(&binder_lock);
+- mutex_lock(&binder_release_files_lock);
+- if (!hlist_unhashed(&proc->release_files_node))
+- hlist_del(&proc->release_files_node);
+- files = proc->files;
+- if (files)
+- proc->files = NULL;
+- mutex_unlock(&binder_release_files_lock);
++
++ binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
++
++ return 0;
++}
++
++static void binder_deferred_release(struct binder_proc *proc)
++{
++ struct hlist_node *pos;
++ struct binder_transaction *t;
++ struct rb_node *n;
++ int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
++
++ BUG_ON(proc->vma);
++ BUG_ON(proc->files);
+
+ hlist_del(&proc->proc_node);
+ if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
+@@ -2971,7 +2951,6 @@ static int binder_release(struct inode *
+ }
+
+ binder_stats.obj_deleted[BINDER_STAT_PROC]++;
+- mutex_unlock(&binder_lock);
+
+ page_count = 0;
+ if (proc->pages) {
+@@ -2995,9 +2974,57 @@ static int binder_release(struct inode *
+ proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);
+
+ kfree(proc);
+- if (files)
+- put_files_struct(files);
+- return 0;
++}
++
++static void binder_deferred_func(struct work_struct *work)
++{
++ struct binder_proc *proc;
++ struct files_struct *files;
++
++ int defer;
++ do {
++ mutex_lock(&binder_lock);
++ mutex_lock(&binder_deferred_lock);
++ if (!hlist_empty(&binder_deferred_list)) {
++ proc = hlist_entry(binder_deferred_list.first,
++ struct binder_proc, deferred_work_node);
++ hlist_del_init(&proc->deferred_work_node);
++ defer = proc->deferred_work;
++ proc->deferred_work = 0;
++ } else {
++ proc = NULL;
++ defer = 0;
++ }
++ mutex_unlock(&binder_deferred_lock);
++
++ files = NULL;
++ if (defer & BINDER_DEFERRED_PUT_FILES)
++ if ((files = proc->files))
++ proc->files = NULL;
++
++ if (defer & BINDER_DEFERRED_FLUSH)
++ binder_deferred_flush(proc);
++
++ if (defer & BINDER_DEFERRED_RELEASE)
++ binder_deferred_release(proc); /* frees proc */
++
++ mutex_unlock(&binder_lock);
++ if (files)
++ put_files_struct(files);
++ } while (proc);
++}
++static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
++
++static void binder_defer_work(struct binder_proc *proc, int defer)
++{
++ mutex_lock(&binder_deferred_lock);
++ proc->deferred_work |= defer;
++ if (hlist_unhashed(&proc->deferred_work_node)) {
++ hlist_add_head(&proc->deferred_work_node,
++ &binder_deferred_list);
++ schedule_work(&binder_deferred_work);
++ }
++ mutex_unlock(&binder_deferred_lock);
+ }
+
+ static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t)
diff --git a/staging/staging-binder-don-t-create-two-proc-entries-with-the-same-name-if-the-driver-is-opened-twice-in-one-process.patch b/staging/staging-binder-don-t-create-two-proc-entries-with-the-same-name-if-the-driver-is-opened-twice-in-one-process.patch
new file mode 100644
index 00000000000000..78cef07a893fe7
--- /dev/null
+++ b/staging/staging-binder-don-t-create-two-proc-entries-with-the-same-name-if-the-driver-is-opened-twice-in-one-process.patch
@@ -0,0 +1,26 @@
+From arve@android.com Tue Apr 7 11:14:55 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:54 -0700
+Subject: Staging: binder: Don't create two proc entries with the same name if the driver is opened twice in one process.
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-2-git-send-email-arve@android.com>
+
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -2776,6 +2776,7 @@ static int binder_open(struct inode *nod
+ if (binder_proc_dir_entry_proc) {
+ char strbuf[11];
+ snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
++ remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
+ create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);
+ }
+
diff --git a/staging/staging-binder-keep-a-reference-to-the-files_struct-while-the-driver-is-mmapped.patch b/staging/staging-binder-keep-a-reference-to-the-files_struct-while-the-driver-is-mmapped.patch
new file mode 100644
index 00000000000000..0b816e8806bc7b
--- /dev/null
+++ b/staging/staging-binder-keep-a-reference-to-the-files_struct-while-the-driver-is-mmapped.patch
@@ -0,0 +1,235 @@
+From arve@android.com Tue Apr 7 11:16:36 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:57 -0700
+Subject: Staging: binder: Keep a reference to the files_struct while the driver is mmapped
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-5-git-send-email-arve@android.com>
+
+
+This prevents breaking fget_light if a single threaded application
+allows incoming file descriptors (in replies or on nodes).
+Should also prevent inserting a file in the wrong files_struct if the
+receving process execs in the middle of a transaction (between
+task_get_unused_fd_flags and task_fd_install).
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 79 +++++++++++++++++++++++++++++++--------
+ 1 file changed, 63 insertions(+), 16 deletions(-)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -41,6 +41,8 @@ static int binder_last_id;
+ static struct proc_dir_entry *binder_proc_dir_entry_root;
+ static struct proc_dir_entry *binder_proc_dir_entry_proc;
+ static struct hlist_head binder_dead_nodes;
++static HLIST_HEAD(binder_release_files_list);
++static DEFINE_MUTEX(binder_release_files_lock);
+
+ static int binder_read_proc_proc(
+ char *page, char **start, off_t off, int count, int *eof, void *data);
+@@ -241,6 +243,8 @@ struct binder_proc {
+ int pid;
+ struct vm_area_struct *vma;
+ struct task_struct *tsk;
++ struct files_struct *files;
++ struct hlist_node release_files_node;
+ void *buffer;
+ size_t user_buffer_offset;
+
+@@ -309,9 +313,9 @@ struct binder_transaction {
+ /*
+ * copied from get_unused_fd_flags
+ */
+-int task_get_unused_fd_flags(struct task_struct *tsk, int flags)
++int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
+ {
+- struct files_struct *files = get_files_struct(tsk);
++ struct files_struct *files = proc->files;
+ int fd, error;
+ struct fdtable *fdt;
+ unsigned long rlim_cur;
+@@ -333,9 +337,9 @@ repeat:
+ * will limit the total number of files that can be opened.
+ */
+ rlim_cur = 0;
+- if (lock_task_sighand(tsk, &irqs)) {
+- rlim_cur = tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+- unlock_task_sighand(tsk, &irqs);
++ if (lock_task_sighand(proc->tsk, &irqs)) {
++ rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
++ unlock_task_sighand(proc->tsk, &irqs);
+ }
+ if (fd >= rlim_cur)
+ goto out;
+@@ -371,7 +375,6 @@ repeat:
+
+ out:
+ spin_unlock(&files->file_lock);
+- put_files_struct(files);
+ return error;
+ }
+
+@@ -379,9 +382,9 @@ out:
+ * copied from fd_install
+ */
+ static void task_fd_install(
+- struct task_struct *tsk, unsigned int fd, struct file *file)
++ struct binder_proc *proc, unsigned int fd, struct file *file)
+ {
+- struct files_struct *files = get_files_struct(tsk);
++ struct files_struct *files = proc->files;
+ struct fdtable *fdt;
+
+ if (files == NULL)
+@@ -392,7 +395,6 @@ static void task_fd_install(
+ BUG_ON(fdt->fd[fd] != NULL);
+ rcu_assign_pointer(fdt->fd[fd], file);
+ spin_unlock(&files->file_lock);
+- put_files_struct(files);
+ }
+
+ /*
+@@ -409,10 +411,10 @@ static void __put_unused_fd(struct files
+ /*
+ * copied from sys_close
+ */
+-static long task_close_fd(struct task_struct *tsk, unsigned int fd)
++static long task_close_fd(struct binder_proc *proc, unsigned int fd)
+ {
+ struct file *filp;
+- struct files_struct *files = get_files_struct(tsk);
++ struct files_struct *files = proc->files;
+ struct fdtable *fdt;
+ int retval;
+
+@@ -439,12 +441,10 @@ static long task_close_fd(struct task_st
+ retval == -ERESTART_RESTARTBLOCK))
+ retval = -EINTR;
+
+- put_files_struct(files);
+ return retval;
+
+ out_unlock:
+ spin_unlock(&files->file_lock);
+- put_files_struct(files);
+ return -EBADF;
+ }
+
+@@ -1549,13 +1549,13 @@ binder_transaction(struct binder_proc *p
+ return_error = BR_FAILED_REPLY;
+ goto err_fget_failed;
+ }
+- target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC);
++ target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+ if (target_fd < 0) {
+ fput(file);
+ return_error = BR_FAILED_REPLY;
+ goto err_get_unused_fd_failed;
+ }
+- task_fd_install(target_proc->tsk, target_fd, file);
++ task_fd_install(target_proc, target_fd, file);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd);
+ /* TODO: fput? */
+@@ -1698,7 +1698,7 @@ binder_transaction_buffer_release(struct
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " fd %ld\n", fp->handle);
+ if (failed_at)
+- task_close_fd(proc->tsk, fp->handle);
++ task_close_fd(proc, fp->handle);
+ break;
+
+ default:
+@@ -2663,6 +2663,34 @@ static void binder_vma_open(struct vm_ar
+ (unsigned long)pgprot_val(vma->vm_page_prot));
+ dump_stack();
+ }
++
++static void binder_release_files(struct work_struct *work)
++{
++ struct binder_proc *proc;
++ struct files_struct *files;
++ do {
++ mutex_lock(&binder_lock);
++ mutex_lock(&binder_release_files_lock);
++ if (!hlist_empty(&binder_release_files_list)) {
++ proc = hlist_entry(binder_release_files_list.first,
++ struct binder_proc, release_files_node);
++ hlist_del_init(&proc->release_files_node);
++ files = proc->files;
++ if (files)
++ proc->files = NULL;
++ } else {
++ proc = NULL;
++ files = NULL;
++ }
++ mutex_unlock(&binder_release_files_lock);
++ mutex_unlock(&binder_lock);
++ if (files)
++ put_files_struct(files);
++ } while (proc);
++}
++
++static DECLARE_WORK(binder_release_files_work, binder_release_files);
++
+ static void binder_vma_close(struct vm_area_struct *vma)
+ {
+ struct binder_proc *proc = vma->vm_private_data;
+@@ -2673,6 +2701,13 @@ static void binder_vma_close(struct vm_a
+ (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
+ (unsigned long)pgprot_val(vma->vm_page_prot));
+ proc->vma = NULL;
++ mutex_lock(&binder_release_files_lock);
++ if (proc->files) {
++ hlist_add_head(&proc->release_files_node,
++ &binder_release_files_list);
++ schedule_work(&binder_release_files_work);
++ }
++ mutex_unlock(&binder_release_files_lock);
+ }
+
+ static struct vm_operations_struct binder_vm_ops = {
+@@ -2751,6 +2786,7 @@ static int binder_mmap(struct file *filp
+ binder_insert_free_buffer(proc, buffer);
+ proc->free_async_space = proc->buffer_size / 2;
+ barrier();
++ proc->files = get_files_struct(current);
+ proc->vma = vma;
+
+ /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
+@@ -2831,6 +2867,7 @@ static int binder_release(struct inode *
+ struct hlist_node *pos;
+ struct binder_transaction *t;
+ struct rb_node *n;
++ struct files_struct *files;
+ struct binder_proc *proc = filp->private_data;
+ int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
+
+@@ -2840,6 +2877,14 @@ static int binder_release(struct inode *
+ remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
+ }
+ mutex_lock(&binder_lock);
++ mutex_lock(&binder_release_files_lock);
++ if (!hlist_unhashed(&proc->release_files_node))
++ hlist_del(&proc->release_files_node);
++ files = proc->files;
++ if (files)
++ proc->files = NULL;
++ mutex_unlock(&binder_release_files_lock);
++
+ hlist_del(&proc->proc_node);
+ if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+@@ -2937,6 +2982,8 @@ static int binder_release(struct inode *
+ proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);
+
+ kfree(proc);
++ if (files)
++ put_files_struct(files);
+ return 0;
+ }
+
diff --git a/staging/staging-binder-mmap-fixes.patch b/staging/staging-binder-mmap-fixes.patch
new file mode 100644
index 00000000000000..4e7bc31b1afd78
--- /dev/null
+++ b/staging/staging-binder-mmap-fixes.patch
@@ -0,0 +1,49 @@
+From arve@android.com Tue Apr 7 11:15:28 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:55 -0700
+Subject: Staging: binder: mmap fixes.
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-3-git-send-email-arve@android.com>
+
+
+Only allow a binder file pointer to be mmapped once. The buffer management
+code cannot deal with more then one area.
+Also remove leftover mutex_unlock if mmap fails.
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -2694,6 +2694,12 @@ static int binder_mmap(struct file *filp
+ }
+ vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
+
++ if (proc->buffer) {
++ ret = -EBUSY;
++ failure_string = "already mapped";
++ goto err_already_mapped;
++ }
++
+ area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
+ if (area == NULL) {
+ ret = -ENOMEM;
+@@ -2741,10 +2747,12 @@ static int binder_mmap(struct file *filp
+
+ err_alloc_small_buf_failed:
+ kfree(proc->pages);
++ proc->pages = NULL;
+ err_alloc_pages_failed:
+ vfree(proc->buffer);
++ proc->buffer = NULL;
+ err_get_vm_area_failed:
+- mutex_unlock(&binder_lock);
++err_already_mapped:
+ err_bad_arg:
+ printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
+ return ret;
diff --git a/staging/staging-binder-prevent-the-wrong-thread-from-adding-a-transaction-to-the-stack.patch b/staging/staging-binder-prevent-the-wrong-thread-from-adding-a-transaction-to-the-stack.patch
new file mode 100644
index 00000000000000..7baa939283c24d
--- /dev/null
+++ b/staging/staging-binder-prevent-the-wrong-thread-from-adding-a-transaction-to-the-stack.patch
@@ -0,0 +1,39 @@
+From arve@android.com Tue Apr 7 11:17:44 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:59 -0700
+Subject: Staging: binder: Prevent the wrong thread from adding a transaction to the stack.
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-7-git-send-email-arve@android.com>
+
+
+If a thread is part of a transaction stack, it is only allowed to make
+another call if it was the target of the top transaction on the stack.
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -1343,6 +1343,17 @@ binder_transaction(struct binder_proc *p
+ if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
+ struct binder_transaction *tmp;
+ tmp = thread->transaction_stack;
++ if (tmp->to_thread != thread) {
++ binder_user_error("binder: %d:%d got new "
++ "transaction with bad transaction stack"
++ ", transaction %d has target %d:%d\n",
++ proc->pid, thread->pid, tmp->debug_id,
++ tmp->to_proc ? tmp->to_proc->pid : 0,
++ tmp->to_thread ?
++ tmp->to_thread->pid : 0);
++ return_error = BR_FAILED_REPLY;
++ goto err_bad_call_stack;
++ }
+ while (tmp) {
+ if (tmp->from && tmp->from->proc == target_proc)
+ target_thread = tmp->from;
diff --git a/staging/staging-binder-remove-vm_exec-check.patch b/staging/staging-binder-remove-vm_exec-check.patch
new file mode 100644
index 00000000000000..892660780062fe
--- /dev/null
+++ b/staging/staging-binder-remove-vm_exec-check.patch
@@ -0,0 +1,32 @@
+From arve@android.com Tue Apr 7 11:14:11 2009
+From: Arve Hj�nnev�g <arve@android.com>
+Date: Mon, 6 Apr 2009 15:12:53 -0700
+Subject: Staging: binder: Remove VM_EXEC check.
+To: gregkh@suse.de
+Cc: swetland@google.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, hugh@veritas.com, Arve Hj�nnev�g <arve@android.com>
+Message-ID: <1239055980-24607-1-git-send-email-arve@android.com>
+
+
+Many platforms do not support mappings without VM_EXEC.
+
+Signed-off-by: Arve Hj�nnev�g <arve@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/android/binder.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/staging/android/binder.c
++++ b/drivers/staging/android/binder.c
+@@ -54,11 +54,7 @@ static int binder_read_proc_proc(
+ #define SZ_4M 0x400000
+ #endif
+
+-#ifndef __i386__
+-#define FORBIDDEN_MMAP_FLAGS (VM_WRITE | VM_EXEC)
+-#else
+ #define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
+-#endif
+
+ #define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64)
+
diff --git a/staging/staging-stlc45xx-should-depend-on-generic_hardirqs.patch b/staging/staging-stlc45xx-should-depend-on-generic_hardirqs.patch
new file mode 100644
index 00000000000000..6fdfd0cebdd17b
--- /dev/null
+++ b/staging/staging-stlc45xx-should-depend-on-generic_hardirqs.patch
@@ -0,0 +1,31 @@
+From geert@linux-m68k.org Tue Apr 7 11:18:56 2009
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+Date: Mon, 6 Apr 2009 15:15:55 +0200 (CEST)
+Subject: Staging: STLC45XX should depend on GENERIC_HARDIRQS
+To: Kalle Valo <kalle.valo@nokia.com>, Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Linux Kernel Development <linux-kernel@vger.kernel.org>
+Message-ID: <Pine.LNX.4.64.0904061515001.13923@anakin>
+
+
+m68k allmodconfig:
+| drivers/staging/stlc45xx/stlc45xx.c: In function 'stlc45xx_probe':
+| drivers/staging/stlc45xx/stlc45xx.c:2456: error: implicit declaration of function 'set_irq_type'
+| make[6]: *** [drivers/staging/stlc45xx/stlc45xx.o] Error 1
+
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/stlc45xx/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/stlc45xx/Kconfig
++++ b/drivers/staging/stlc45xx/Kconfig
+@@ -1,6 +1,6 @@
+ config STLC45XX
+ tristate "stlc4550/4560 support"
+- depends on MAC80211 && WLAN_80211 && SPI_MASTER
++ depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS
+ ---help---
+ This is a driver for stlc4550 and stlc4560 chipsets.
+
diff --git a/usb.current/usb-fix-oops-in-cdc-wdm-in-case-of-malformed-descriptors.patch b/usb.current/usb-fix-oops-in-cdc-wdm-in-case-of-malformed-descriptors.patch
new file mode 100644
index 00000000000000..0104a231a80bf9
--- /dev/null
+++ b/usb.current/usb-fix-oops-in-cdc-wdm-in-case-of-malformed-descriptors.patch
@@ -0,0 +1,31 @@
+From oliver@neukum.org Tue Apr 7 11:12:23 2009
+From: Oliver Neukum <oliver@neukum.org>
+Date: Sat, 4 Apr 2009 09:25:15 +0200
+Subject: USB: fix oops in cdc-wdm in case of malformed descriptors
+To: greg@kroah.com, Chuck Ebbert <cebbert@redhat.com>
+Message-ID: <200904040925.23539.oliver@neukum.org>
+Content-Disposition: inline
+
+
+cdc-wdm needs to ignore extremely malformed descriptors.
+
+Signed-off-by: Oliver Neukum <oliver@neukum.org>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/class/cdc-wdm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -652,7 +652,7 @@ next_desc:
+
+ iface = &intf->altsetting[0];
+ ep = &iface->endpoint[0].desc;
+- if (!usb_endpoint_is_int_in(ep)) {
++ if (!ep || !usb_endpoint_is_int_in(ep)) {
+ rv = -EINVAL;
+ goto err;
+ }
diff --git a/usb.current/usb-musb-bugfixes-for-multi-packet-txdma-support.patch b/usb.current/usb-musb-bugfixes-for-multi-packet-txdma-support.patch
new file mode 100644
index 00000000000000..5566b494406c9e
--- /dev/null
+++ b/usb.current/usb-musb-bugfixes-for-multi-packet-txdma-support.patch
@@ -0,0 +1,206 @@
+From david-b@pacbell.net Tue Apr 7 11:30:22 2009
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Date: Thu, 26 Mar 2009 18:26:40 -0700
+Subject: USB: musb: bugfixes for multi-packet TXDMA support
+To: Greg KH <greg@kroah.com>
+Cc: felipe.balbi@nokia.com, Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Message-ID: <200903261826.40856.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+We really want to use DMA mode 1 for all multi-packet transfers;
+that's one IRQ on DMA completion, instead of one per packet.
+
+There is an important issue with such transfers, especially on
+the host side: when such transfers end with a full-size packet,
+we must defer musb_dma_completion() calls until the FIFO empties.
+Else we report URB completions too soon, and may clobber data in
+the FIFO fifo when writing the next packet (losing data).
+
+The Inventra DMA support uses DMA mode 1, but it ignores that
+issue. The CPPI DMA support uses mode 0, but doesn't handle
+its TXPKTRDY interrupts quite right either; it can get stale
+"packet ready" interrupts, and report transfer completion too
+early using slightly different code paths, also losing data.
+
+So I'm solving it in a generic way -- by adding a sort of the
+"interrupt filter" into musb_host_tx(), catching these cases
+where a DMA completion IRQ doesn't suffice and removing some
+needlessly controller-specific logic. When a TXDMA interrupt
+happens and DMA request mode 1 is active, that filter resets
+to mode 0 and defers URB completion processing until TXPKTRDY,
+unless the FIFO is already empty. Related filtering logic in
+Inventra and CPPI code gets removed.
+
+Since it should be competely safe now to use the DMA request
+mode 1 for host side transfers with the CPPI DMA controller,
+set it in musb_h_tx_dma_start() ... now renamed (and shared).
+
+[ dbrownell@users.sourceforge.net: don't introduce more
+CamElCase; use more concise explanations ]
+
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Cc: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/cppi_dma.c | 22 -------------
+ drivers/usb/musb/musb_host.c | 68 +++++++++++++++++++++++++++++++++++++++++--
+ drivers/usb/musb/musbhsdma.c | 7 +---
+ 3 files changed, 69 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/musb/cppi_dma.c
++++ b/drivers/usb/musb/cppi_dma.c
+@@ -1228,27 +1228,7 @@ void cppi_completion(struct musb *musb,
+
+ hw_ep = tx_ch->hw_ep;
+
+- /* Peripheral role never repurposes the
+- * endpoint, so immediate completion is
+- * safe. Host role waits for the fifo
+- * to empty (TXPKTRDY irq) before going
+- * to the next queued bulk transfer.
+- */
+- if (is_host_active(cppi->musb)) {
+-#if 0
+- /* WORKAROUND because we may
+- * not always get TXKPTRDY ...
+- */
+- int csr;
+-
+- csr = musb_readw(hw_ep->regs,
+- MUSB_TXCSR);
+- if (csr & MUSB_TXCSR_TXPKTRDY)
+-#endif
+- completed = false;
+- }
+- if (completed)
+- musb_dma_completion(musb, index + 1, 1);
++ musb_dma_completion(musb, index + 1, 1);
+
+ } else {
+ /* Bigger transfer than we could fit in
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -4,6 +4,7 @@
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
++ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+@@ -168,13 +169,15 @@ static inline void musb_h_tx_start(struc
+
+ }
+
+-static inline void cppi_host_txdma_start(struct musb_hw_ep *ep)
++static inline void musb_h_tx_dma_start(struct musb_hw_ep *ep)
+ {
+ u16 txcsr;
+
+ /* NOTE: no locks here; caller should lock and select EP */
+ txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+ txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS;
++ if (is_cppi_enabled())
++ txcsr |= MUSB_TXCSR_DMAMODE;
+ musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+ }
+
+@@ -279,7 +282,7 @@ start:
+ if (!hw_ep->tx_channel)
+ musb_h_tx_start(hw_ep);
+ else if (is_cppi_enabled() || tusb_dma_omap())
+- cppi_host_txdma_start(hw_ep);
++ musb_h_tx_dma_start(hw_ep);
+ }
+ }
+
+@@ -1250,6 +1253,67 @@ void musb_host_tx(struct musb *musb, u8
+
+ }
+
++ if (is_dma_capable() && dma && !status) {
++ /*
++ * DMA has completed. But if we're using DMA mode 1 (multi
++ * packet DMA), we need a terminal TXPKTRDY interrupt before
++ * we can consider this transfer completed, lest we trash
++ * its last packet when writing the next URB's data. So we
++ * switch back to mode 0 to get that interrupt; we'll come
++ * back here once it happens.
++ */
++ if (tx_csr & MUSB_TXCSR_DMAMODE) {
++ /*
++ * We shouldn't clear DMAMODE with DMAENAB set; so
++ * clear them in a safe order. That should be OK
++ * once TXPKTRDY has been set (and I've never seen
++ * it being 0 at this moment -- DMA interrupt latency
++ * is significant) but if it hasn't been then we have
++ * no choice but to stop being polite and ignore the
++ * programmer's guide... :-)
++ *
++ * Note that we must write TXCSR with TXPKTRDY cleared
++ * in order not to re-trigger the packet send (this bit
++ * can't be cleared by CPU), and there's another caveat:
++ * TXPKTRDY may be set shortly and then cleared in the
++ * double-buffered FIFO mode, so we do an extra TXCSR
++ * read for debouncing...
++ */
++ tx_csr &= musb_readw(epio, MUSB_TXCSR);
++ if (tx_csr & MUSB_TXCSR_TXPKTRDY) {
++ tx_csr &= ~(MUSB_TXCSR_DMAENAB |
++ MUSB_TXCSR_TXPKTRDY);
++ musb_writew(epio, MUSB_TXCSR,
++ tx_csr | MUSB_TXCSR_H_WZC_BITS);
++ }
++ tx_csr &= ~(MUSB_TXCSR_DMAMODE |
++ MUSB_TXCSR_TXPKTRDY);
++ musb_writew(epio, MUSB_TXCSR,
++ tx_csr | MUSB_TXCSR_H_WZC_BITS);
++
++ /*
++ * There is no guarantee that we'll get an interrupt
++ * after clearing DMAMODE as we might have done this
++ * too late (after TXPKTRDY was cleared by controller).
++ * Re-read TXCSR as we have spoiled its previous value.
++ */
++ tx_csr = musb_readw(epio, MUSB_TXCSR);
++ }
++
++ /*
++ * We may get here from a DMA completion or TXPKTRDY interrupt.
++ * In any case, we must check the FIFO status here and bail out
++ * only if the FIFO still has data -- that should prevent the
++ * "missed" TXPKTRDY interrupts and deal with double-buffered
++ * FIFO mode too...
++ */
++ if (tx_csr & (MUSB_TXCSR_FIFONOTEMPTY | MUSB_TXCSR_TXPKTRDY)) {
++ DBG(2, "DMA complete but packet still in FIFO, "
++ "CSR %04x\n", tx_csr);
++ return;
++ }
++ }
++
+ /* REVISIT this looks wrong... */
+ if (!status || dma || usb_pipeisoc(pipe)) {
+ if (dma)
+--- a/drivers/usb/musb/musbhsdma.c
++++ b/drivers/usb/musb/musbhsdma.c
+@@ -304,12 +304,9 @@ static irqreturn_t dma_controller_irq(in
+ musb_channel->epnum,
+ MUSB_TXCSR),
+ MUSB_TXCSR_TXPKTRDY);
+- } else {
+- musb_dma_completion(
+- musb,
+- musb_channel->epnum,
+- musb_channel->transmit);
+ }
++ musb_dma_completion(musb, musb_channel->epnum,
++ musb_channel->transmit);
+ }
+ }
+ }
diff --git a/usb.current/usb-musb-fix-isochronous-txdma.patch b/usb.current/usb-musb-fix-isochronous-txdma.patch
new file mode 100644
index 00000000000000..b790b16dc8b061
--- /dev/null
+++ b/usb.current/usb-musb-fix-isochronous-txdma.patch
@@ -0,0 +1,424 @@
+From david-b@pacbell.net Tue Apr 7 11:31:07 2009
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Date: Thu, 26 Mar 2009 18:29:19 -0700
+Subject: USB: musb: fix isochronous TXDMA (take 2)
+To: Greg KH <greg@kroah.com>
+Cc: felipe.balbi@nokia.com, Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Message-ID: <200903261829.19682.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+Multi-frame isochronous TX URBs transfers in DMA mode never
+complete with CPPI DMA because musb_host_tx() doesn't restart
+DMA on the second frame, only emitting a debug message.
+With Inventra DMA they complete, but in PIO mode. To fix:
+
+ - Factor out programming of the DMA transfer from
+ musb_ep_program() into musb_tx_dma_program();
+
+ - Reorder the code at the end of musb_host_tx() to
+ facilitate the fallback to PIO iff DMA fails;
+
+ - Handle the buffer offset consistently for both
+ PIO and DMA modes;
+
+ - Add an argument to musb_ep_program() for the same
+ reason (it only worked correctly with non-zero
+ offset of the first frame in PIO mode);
+
+ - Set the completed isochronous frame descriptor's
+ 'actual_length' and 'status' fields correctly in
+ DMA mode.
+
+Also, since CPPI reportedly doesn't like sending isochronous
+packets in the RNDIS mode, change the criterion for this
+mode to be used only for multi-packet transfers. (There's
+no need for that mode in the single-packet case anyway.)
+
+[ dbrownell@users.sourceforge.net: split comment paragraph
+into bullet list, shrink patch delta, style tweaks ]
+
+Signed-off-by: Pavel Kiryukhin <pkiryukhin@ru.mvista.com>
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/cppi_dma.c | 1
+ drivers/usb/musb/musb_host.c | 227 +++++++++++++++++++------------------------
+ 2 files changed, 105 insertions(+), 123 deletions(-)
+
+--- a/drivers/usb/musb/cppi_dma.c
++++ b/drivers/usb/musb/cppi_dma.c
+@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb,
+ * trigger the "send a ZLP?" confusion.
+ */
+ rndis = (maxpacket & 0x3f) == 0
++ && length > maxpacket
+ && length < 0xffff
+ && (length % maxpacket) != 0;
+
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -97,8 +97,8 @@
+
+
+ static void musb_ep_program(struct musb *musb, u8 epnum,
+- struct urb *urb, unsigned int nOut,
+- u8 *buf, u32 len);
++ struct urb *urb, int is_out,
++ u8 *buf, u32 offset, u32 len);
+
+ /*
+ * Clear TX fifo. Needed to avoid BABBLE errors.
+@@ -192,9 +192,10 @@ musb_start_urb(struct musb *musb, int is
+ {
+ u16 frame;
+ u32 len;
+- void *buf;
+ void __iomem *mbase = musb->mregs;
+ struct urb *urb = next_urb(qh);
++ void *buf = urb->transfer_buffer;
++ u32 offset = 0;
+ struct musb_hw_ep *hw_ep = qh->hw_ep;
+ unsigned pipe = urb->pipe;
+ u8 address = usb_pipedevice(pipe);
+@@ -217,7 +218,7 @@ musb_start_urb(struct musb *musb, int is
+ case USB_ENDPOINT_XFER_ISOC:
+ qh->iso_idx = 0;
+ qh->frame = 0;
+- buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset;
++ offset = urb->iso_frame_desc[0].offset;
+ len = urb->iso_frame_desc[0].length;
+ break;
+ default: /* bulk, interrupt */
+@@ -235,14 +236,14 @@ musb_start_urb(struct musb *musb, int is
+ case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
+ default: s = "-intr"; break;
+ }; s; }),
+- epnum, buf, len);
++ epnum, buf + offset, len);
+
+ /* Configure endpoint */
+ if (is_in || hw_ep->is_shared_fifo)
+ hw_ep->in_qh = qh;
+ else
+ hw_ep->out_qh = qh;
+- musb_ep_program(musb, epnum, urb, !is_in, buf, len);
++ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
+
+ /* transmit may have more work: start it when it is time */
+ if (is_in)
+@@ -253,7 +254,6 @@ musb_start_urb(struct musb *musb, int is
+ case USB_ENDPOINT_XFER_ISOC:
+ case USB_ENDPOINT_XFER_INT:
+ DBG(3, "check whether there's still time for periodic Tx\n");
+- qh->iso_idx = 0;
+ frame = musb_readw(mbase, MUSB_FRAME);
+ /* FIXME this doesn't implement that scheduling policy ...
+ * or handle framecounter wrapping
+@@ -634,14 +634,68 @@ musb_rx_reinit(struct musb *musb, struct
+ ep->rx_reinit = 0;
+ }
+
++static bool musb_tx_dma_program(struct dma_controller *dma,
++ struct musb_hw_ep *hw_ep, struct musb_qh *qh,
++ struct urb *urb, u32 offset, u32 length)
++{
++ struct dma_channel *channel = hw_ep->tx_channel;
++ void __iomem *epio = hw_ep->regs;
++ u16 pkt_size = qh->maxpacket;
++ u16 csr;
++ u8 mode;
++
++#ifdef CONFIG_USB_INVENTRA_DMA
++ if (length > channel->max_len)
++ length = channel->max_len;
++
++ csr = musb_readw(epio, MUSB_TXCSR);
++ if (length > pkt_size) {
++ mode = 1;
++ csr |= MUSB_TXCSR_AUTOSET
++ | MUSB_TXCSR_DMAMODE
++ | MUSB_TXCSR_DMAENAB;
++ } else {
++ mode = 0;
++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
++ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
++ }
++ channel->desired_mode = mode;
++ musb_writew(epio, MUSB_TXCSR, csr);
++#else
++ if (!is_cppi_enabled() && !tusb_dma_omap())
++ return false;
++
++ channel->actual_len = 0;
++
++ /*
++ * TX uses "RNDIS" mode automatically but needs help
++ * to identify the zero-length-final-packet case.
++ */
++ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
++#endif
++
++ qh->segsize = length;
++
++ if (!dma->channel_program(channel, pkt_size, mode,
++ urb->transfer_dma + offset, length)) {
++ dma->channel_release(channel);
++ hw_ep->tx_channel = NULL;
++
++ csr = musb_readw(epio, MUSB_TXCSR);
++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
++ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
++ return false;
++ }
++ return true;
++}
+
+ /*
+ * Program an HDRC endpoint as per the given URB
+ * Context: irqs blocked, controller lock held
+ */
+ static void musb_ep_program(struct musb *musb, u8 epnum,
+- struct urb *urb, unsigned int is_out,
+- u8 *buf, u32 len)
++ struct urb *urb, int is_out,
++ u8 *buf, u32 offset, u32 len)
+ {
+ struct dma_controller *dma_controller;
+ struct dma_channel *dma_channel;
+@@ -768,82 +822,9 @@ static void musb_ep_program(struct musb
+ else
+ load_count = min((u32) packet_sz, len);
+
+-#ifdef CONFIG_USB_INVENTRA_DMA
+- if (dma_channel) {
+- qh->segsize = min(len, dma_channel->max_len);
+- if (qh->segsize <= packet_sz)
+- dma_channel->desired_mode = 0;
+- else
+- dma_channel->desired_mode = 1;
+-
+- if (dma_channel->desired_mode == 0) {
+- /* Against the programming guide */
+- csr |= (MUSB_TXCSR_DMAENAB);
+- } else
+- csr |= (MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAENAB
+- | MUSB_TXCSR_DMAMODE);
+- musb_writew(epio, MUSB_TXCSR, csr);
+-
+- dma_ok = dma_controller->channel_program(
+- dma_channel, packet_sz,
+- dma_channel->desired_mode,
+- urb->transfer_dma,
+- qh->segsize);
+- if (dma_ok) {
+- load_count = 0;
+- } else {
+- dma_controller->channel_release(dma_channel);
+- if (is_out)
+- hw_ep->tx_channel = NULL;
+- else
+- hw_ep->rx_channel = NULL;
+- dma_channel = NULL;
+-
+- /*
+- * The programming guide says that we must
+- * clear the DMAENAB bit before DMAMODE...
+- */
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_DMAENAB
+- | MUSB_TXCSR_AUTOSET);
+- musb_writew(epio, MUSB_TXCSR, csr);
+- csr &= ~MUSB_TXCSR_DMAMODE;
+- musb_writew(epio, MUSB_TXCSR, csr);
+- }
+- }
+-#endif
+-
+- /* candidate for DMA */
+- if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+-
+- /* Defer enabling DMA */
+- dma_channel->actual_len = 0L;
+- qh->segsize = len;
+-
+- /* TX uses "rndis" mode automatically, but needs help
+- * to identify the zero-length-final-packet case.
+- */
+- dma_ok = dma_controller->channel_program(
+- dma_channel, packet_sz,
+- (urb->transfer_flags
+- & URB_ZERO_PACKET)
+- == URB_ZERO_PACKET,
+- urb->transfer_dma,
+- qh->segsize);
+- if (dma_ok) {
+- load_count = 0;
+- } else {
+- dma_controller->channel_release(dma_channel);
+- hw_ep->tx_channel = NULL;
+- dma_channel = NULL;
+-
+- /* REVISIT there's an error path here that
+- * needs handling: can't do dma, but
+- * there's no pio buffer address...
+- */
+- }
+- }
++ if (dma_channel && musb_tx_dma_program(dma_controller,
++ hw_ep, qh, urb, offset, len))
++ load_count = 0;
+
+ if (load_count) {
+ /* PIO to load FIFO */
+@@ -903,7 +884,7 @@ static void musb_ep_program(struct musb
+ dma_channel, packet_sz,
+ !(urb->transfer_flags
+ & URB_SHORT_NOT_OK),
+- urb->transfer_dma,
++ urb->transfer_dma + offset,
+ qh->segsize);
+ if (!dma_ok) {
+ dma_controller->channel_release(
+@@ -1146,8 +1127,8 @@ void musb_host_tx(struct musb *musb, u8
+ int pipe;
+ bool done = false;
+ u16 tx_csr;
+- size_t wLength = 0;
+- u8 *buf = NULL;
++ size_t length = 0;
++ size_t offset = 0;
+ struct urb *urb;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+@@ -1165,7 +1146,7 @@ void musb_host_tx(struct musb *musb, u8
+ /* with CPPI, DMA sometimes triggers "extra" irqs */
+ if (!urb) {
+ DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+- goto finish;
++ return;
+ }
+
+ pipe = urb->pipe;
+@@ -1202,7 +1183,7 @@ void musb_host_tx(struct musb *musb, u8
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS
+ | MUSB_TXCSR_TXPKTRDY);
+- goto finish;
++ return;
+ }
+
+ if (status) {
+@@ -1234,8 +1215,7 @@ void musb_host_tx(struct musb *musb, u8
+ /* second cppi case */
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+- goto finish;
+-
++ return;
+ }
+
+ if (is_dma_capable() && dma && !status) {
+@@ -1299,25 +1279,25 @@ void musb_host_tx(struct musb *musb, u8
+ }
+ }
+
+- /* REVISIT this looks wrong... */
+ if (!status || dma || usb_pipeisoc(pipe)) {
+ if (dma)
+- wLength = dma->actual_len;
++ length = dma->actual_len;
+ else
+- wLength = qh->segsize;
+- qh->offset += wLength;
++ length = qh->segsize;
++ qh->offset += length;
+
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+- d->actual_length = qh->segsize;
++ d->actual_length = length;
++ d->status = status;
+ if (++qh->iso_idx >= urb->number_of_packets) {
+ done = true;
+ } else {
+ d++;
+- buf = urb->transfer_buffer + d->offset;
+- wLength = d->length;
++ offset = d->offset;
++ length = d->length;
+ }
+ } else if (dma) {
+ done = true;
+@@ -1330,10 +1310,8 @@ void musb_host_tx(struct musb *musb, u8
+ & URB_ZERO_PACKET))
+ done = true;
+ if (!done) {
+- buf = urb->transfer_buffer
+- + qh->offset;
+- wLength = urb->transfer_buffer_length
+- - qh->offset;
++ offset = qh->offset;
++ length = urb->transfer_buffer_length - offset;
+ }
+ }
+ }
+@@ -1352,28 +1330,31 @@ void musb_host_tx(struct musb *musb, u8
+ urb->status = status;
+ urb->actual_length = qh->offset;
+ musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
++ return;
++ } else if (usb_pipeisoc(pipe) && dma) {
++ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
++ offset, length))
++ return;
++ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
++ DBG(1, "not complete, but DMA enabled?\n");
++ return;
++ }
+
+- } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) {
+- /* WARN_ON(!buf); */
+-
+- /* REVISIT: some docs say that when hw_ep->tx_double_buffered,
+- * (and presumably, fifo is not half-full) we should write TWO
+- * packets before updating TXCSR ... other docs disagree ...
+- */
+- /* PIO: start next packet in this URB */
+- if (wLength > qh->maxpacket)
+- wLength = qh->maxpacket;
+- musb_write_fifo(hw_ep, wLength, buf);
+- qh->segsize = wLength;
+-
+- musb_ep_select(mbase, epnum);
+- musb_writew(epio, MUSB_TXCSR,
+- MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+- } else
+- DBG(1, "not complete, but dma enabled?\n");
++ /*
++ * PIO: start next packet in this URB.
++ *
++ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
++ * (and presumably, FIFO is not half-full) we should write *two*
++ * packets before updating TXCSR; other docs disagree...
++ */
++ if (length > qh->maxpacket)
++ length = qh->maxpacket;
++ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
++ qh->segsize = length;
+
+-finish:
+- return;
++ musb_ep_select(mbase, epnum);
++ musb_writew(epio, MUSB_TXCSR,
++ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+ }
+
+
diff --git a/usb.current/usb-musb-fix-possible-panic-while-resuming.patch b/usb.current/usb-musb-fix-possible-panic-while-resuming.patch
new file mode 100644
index 00000000000000..eee27b0e6f048e
--- /dev/null
+++ b/usb.current/usb-musb-fix-possible-panic-while-resuming.patch
@@ -0,0 +1,64 @@
+From david-b@pacbell.net Tue Apr 7 11:31:35 2009
+From: Kim Kyuwon <q1.kim@samsung.com>
+Date: Thu, 26 Mar 2009 18:56:51 -0700
+Subject: USB: musb: fix possible panic while resuming
+To: Greg KH <greg@kroah.com>
+Cc: felipe.balbi@nokia.com, Kim Kyuwon <q1.kim@samsung.com>
+Message-ID: <200903261856.52215.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: Kim Kyuwon <q1.kim@samsung.com>
+
+During driver resume processing, musb could cause a kernel panic.
+Fix by enabling the clock earlier, with the resume_early method.
+
+Signed-off-by: Kim Kyuwon <q1.kim@samsung.com>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_core.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2170,26 +2170,22 @@ static int musb_suspend(struct platform_
+ return 0;
+ }
+
+-static int musb_resume(struct platform_device *pdev)
++static int musb_resume_early(struct platform_device *pdev)
+ {
+- unsigned long flags;
+ struct musb *musb = dev_to_musb(&pdev->dev);
+
+ if (!musb->clock)
+ return 0;
+
+- spin_lock_irqsave(&musb->lock, flags);
+-
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 1);
+ else
+ clk_enable(musb->clock);
+
+ /* for static cmos like DaVinci, register values were preserved
+- * unless for some reason the whole soc powered down and we're
+- * not treating that as a whole-system restart (e.g. swsusp)
++ * unless for some reason the whole soc powered down or the USB
++ * module got reset through the PSC (vs just being disabled).
+ */
+- spin_unlock_irqrestore(&musb->lock, flags);
+ return 0;
+ }
+
+@@ -2207,7 +2203,7 @@ static struct platform_driver musb_drive
+ .remove = __devexit_p(musb_remove),
+ .shutdown = musb_shutdown,
+ .suspend = musb_suspend,
+- .resume = musb_resume,
++ .resume_early = musb_resume_early,
+ };
+
+ /*-------------------------------------------------------------------------*/
diff --git a/usb.current/usb-musb-sanitize-clearing-txcsr-dma-bits.patch b/usb.current/usb-musb-sanitize-clearing-txcsr-dma-bits.patch
new file mode 100644
index 00000000000000..a857ba87c96d52
--- /dev/null
+++ b/usb.current/usb-musb-sanitize-clearing-txcsr-dma-bits.patch
@@ -0,0 +1,360 @@
+From david-b@pacbell.net Tue Apr 7 11:30:45 2009
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Date: Thu, 26 Mar 2009 18:27:47 -0700
+Subject: USB: musb: sanitize clearing TXCSR DMA bits (take 2)
+To: Greg KH <greg@kroah.com>
+Cc: felipe.balbi@nokia.com, Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Message-ID: <200903261827.47294.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+The MUSB code clears TXCSR_DMAMODE incorrectly in several
+places, either asserting that TXCSR_DMAENAB is clear (when
+sometimes it isn't) or clearing both bits together. Recent
+versions of the programmer's guide require DMAENAB to be
+cleared first, although some older ones didn't.
+
+Fix this and while at it:
+
+ - In musb_gadget::txstate(), stop clearing the AUTOSET
+ and DMAMODE bits for the CPPI case since they never
+ get set anyway (the former bit is reserved on DaVinci);
+ but do clear the DMAENAB bit on the DMA error path.
+
+ - In musb_host::musb_ep_program(), remove the duplicate
+ DMA controller specific code code clearing the TXCSR
+ previous state, add the code to clear TXCSR DMA bits
+ on the Inventra DMA error path, to replace such code
+ (executed late) on the PIO path.
+
+ - In musbhsdma::dma_channel_abort()/dma_controller_irq(),
+ add/use the 'offset' variable to avoid MUSB_EP_OFFSET()
+ invocations on every RXCSR/TXCSR access.
+
+[dbrownell@users.sourceforge.net: don't introduce CamelCase,
+shrink diff]
+
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_gadget.c | 33 +++++++++++------
+ drivers/usb/musb/musb_host.c | 79 ++++++++++++++++-------------------------
+ drivers/usb/musb/musbhsdma.c | 57 ++++++++++++++++++-----------
+ 3 files changed, 89 insertions(+), 80 deletions(-)
+
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, con
+ if (is_dma_capable() && ep->dma) {
+ struct dma_controller *c = ep->musb->dma_controller;
+ int value;
++
+ if (ep->is_in) {
++ /*
++ * The programming guide says that we must not clear
++ * the DMAMODE bit before DMAENAB, so we only
++ * clear it in the second write...
++ */
+ musb_writew(epio, MUSB_TXCSR,
+- 0 | MUSB_TXCSR_FLUSHFIFO);
++ MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
+ musb_writew(epio, MUSB_TXCSR,
+ 0 | MUSB_TXCSR_FLUSHFIFO);
+ } else {
+@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struc
+ | IN token(s) are recd from Host.
+ | -> DMA interrupt on completion
+ | calls TxAvail.
+- | -> stop DMA, ~DmaEenab,
++ | -> stop DMA, ~DMAENAB,
+ | -> set TxPktRdy for last short pkt or zlp
+ | -> Complete Request
+ | -> Continue next request (call txstate)
+@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, s
+ request->dma, request_size);
+ if (use_dma) {
+ if (musb_ep->dma->desired_mode == 0) {
+- /* ASSERT: DMAENAB is clear */
+- csr &= ~(MUSB_TXCSR_AUTOSET |
+- MUSB_TXCSR_DMAMODE);
++ /*
++ * We must not clear the DMAMODE bit
++ * before the DMAENAB bit -- and the
++ * latter doesn't always get cleared
++ * before we get here...
++ */
++ csr &= ~(MUSB_TXCSR_AUTOSET
++ | MUSB_TXCSR_DMAENAB);
++ musb_writew(epio, MUSB_TXCSR, csr
++ | MUSB_TXCSR_P_WZC_BITS);
++ csr &= ~MUSB_TXCSR_DMAMODE;
+ csr |= (MUSB_TXCSR_DMAENAB |
+ MUSB_TXCSR_MODE);
+ /* against programming guide */
+@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, s
+
+ #elif defined(CONFIG_USB_TI_CPPI_DMA)
+ /* program endpoint CSR first, then setup DMA */
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_P_UNDERRUN
+- | MUSB_TXCSR_TXPKTRDY);
++ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+ csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
+ musb_writew(epio, MUSB_TXCSR,
+ (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
+@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, s
+ if (!use_dma) {
+ c->channel_release(musb_ep->dma);
+ musb_ep->dma = NULL;
+- /* ASSERT: DMAENAB clear */
+- csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
++ csr &= ~MUSB_TXCSR_DMAENAB;
++ musb_writew(epio, MUSB_TXCSR, csr);
+ /* invariant: prequest->buf is non-null */
+ }
+ #elif defined(CONFIG_USB_TUSB_OMAP_DMA)
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -593,10 +593,17 @@ musb_rx_reinit(struct musb *musb, struct
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_MODE) {
+ musb_h_tx_flush_fifo(ep);
++ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ musb_writew(ep->regs, MUSB_TXCSR,
+- MUSB_TXCSR_FRCDATATOG);
++ csr | MUSB_TXCSR_FRCDATATOG);
+ }
+- /* clear mode (and everything else) to enable Rx */
++
++ /*
++ * Clear the MODE bit (and everything else) to enable Rx.
++ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
++ */
++ if (csr & MUSB_TXCSR_DMAMODE)
++ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
+ musb_writew(ep->regs, MUSB_TXCSR, 0);
+
+ /* scrub all previous state, clearing toggle */
+@@ -693,12 +700,17 @@ static void musb_ep_program(struct musb
+
+ /* general endpoint setup */
+ if (epnum) {
+- /* ASSERT: TXCSR_DMAENAB was already cleared */
+-
+ /* flush all old state, set default */
+ musb_h_tx_flush_fifo(hw_ep);
++
++ /*
++ * We must not clear the DMAMODE bit before or in
++ * the same cycle with the DMAENAB bit, so we clear
++ * the latter first...
++ */
+ csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
+- | MUSB_TXCSR_DMAMODE
++ | MUSB_TXCSR_AUTOSET
++ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_FRCDATATOG
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_ERROR
+@@ -706,16 +718,15 @@ static void musb_ep_program(struct musb
+ );
+ csr |= MUSB_TXCSR_MODE;
+
+- if (usb_gettoggle(urb->dev,
+- qh->epnum, 1))
++ if (usb_gettoggle(urb->dev, qh->epnum, 1))
+ csr |= MUSB_TXCSR_H_WR_DATATOGGLE
+ | MUSB_TXCSR_H_DATATOGGLE;
+ else
+ csr |= MUSB_TXCSR_CLRDATATOG;
+
+- /* twice in case of double packet buffering */
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
++ csr &= ~MUSB_TXCSR_DMAMODE;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+@@ -759,34 +770,19 @@ static void musb_ep_program(struct musb
+
+ #ifdef CONFIG_USB_INVENTRA_DMA
+ if (dma_channel) {
+-
+- /* clear previous state */
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_DMAENAB);
+- csr |= MUSB_TXCSR_MODE;
+- musb_writew(epio, MUSB_TXCSR,
+- csr | MUSB_TXCSR_MODE);
+-
+ qh->segsize = min(len, dma_channel->max_len);
+-
+ if (qh->segsize <= packet_sz)
+ dma_channel->desired_mode = 0;
+ else
+ dma_channel->desired_mode = 1;
+
+-
+ if (dma_channel->desired_mode == 0) {
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE);
++ /* Against the programming guide */
+ csr |= (MUSB_TXCSR_DMAENAB);
+- /* against programming guide */
+ } else
+ csr |= (MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_DMAMODE);
+-
+ musb_writew(epio, MUSB_TXCSR, csr);
+
+ dma_ok = dma_controller->channel_program(
+@@ -803,6 +799,17 @@ static void musb_ep_program(struct musb
+ else
+ hw_ep->rx_channel = NULL;
+ dma_channel = NULL;
++
++ /*
++ * The programming guide says that we must
++ * clear the DMAENAB bit before DMAMODE...
++ */
++ csr = musb_readw(epio, MUSB_TXCSR);
++ csr &= ~(MUSB_TXCSR_DMAENAB
++ | MUSB_TXCSR_AUTOSET);
++ musb_writew(epio, MUSB_TXCSR, csr);
++ csr &= ~MUSB_TXCSR_DMAMODE;
++ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+ }
+ #endif
+@@ -810,18 +817,7 @@ static void musb_ep_program(struct musb
+ /* candidate for DMA */
+ if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+
+- /* program endpoint CSRs first, then setup DMA.
+- * assume CPPI setup succeeds.
+- * defer enabling dma.
+- */
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_DMAENAB);
+- csr |= MUSB_TXCSR_MODE;
+- musb_writew(epio, MUSB_TXCSR,
+- csr | MUSB_TXCSR_MODE);
+-
++ /* Defer enabling DMA */
+ dma_channel->actual_len = 0L;
+ qh->segsize = len;
+
+@@ -850,20 +846,9 @@ static void musb_ep_program(struct musb
+ }
+
+ if (load_count) {
+- /* ASSERT: TXCSR_DMAENAB was already cleared */
+-
+ /* PIO to load FIFO */
+ qh->segsize = load_count;
+ musb_write_fifo(hw_ep, load_count, buf);
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_DMAENAB
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_AUTOSET);
+- /* write CSR */
+- csr |= MUSB_TXCSR_MODE;
+-
+- if (epnum)
+- musb_writew(epio, MUSB_TXCSR, csr);
+ }
+
+ /* re-enable interrupt */
+--- a/drivers/usb/musb/musbhsdma.c
++++ b/drivers/usb/musb/musbhsdma.c
+@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_
+ void __iomem *mbase = musb_channel->controller->base;
+
+ u8 bchannel = musb_channel->idx;
++ int offset;
+ u16 csr;
+
+ if (channel->status == MUSB_DMA_STATUS_BUSY) {
+ if (musb_channel->transmit) {
++ offset = MUSB_EP_OFFSET(musb_channel->epnum,
++ MUSB_TXCSR);
+
+- csr = musb_readw(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum,
+- MUSB_TXCSR));
+- csr &= ~(MUSB_TXCSR_AUTOSET |
+- MUSB_TXCSR_DMAENAB |
+- MUSB_TXCSR_DMAMODE);
+- musb_writew(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR),
+- csr);
++ /*
++ * The programming guide says that we must clear
++ * the DMAENAB bit before the DMAMODE bit...
++ */
++ csr = musb_readw(mbase, offset);
++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
++ musb_writew(mbase, offset, csr);
++ csr &= ~MUSB_TXCSR_DMAMODE;
++ musb_writew(mbase, offset, csr);
+ } else {
+- csr = musb_readw(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum,
+- MUSB_RXCSR));
++ offset = MUSB_EP_OFFSET(musb_channel->epnum,
++ MUSB_RXCSR);
++
++ csr = musb_readw(mbase, offset);
+ csr &= ~(MUSB_RXCSR_AUTOCLEAR |
+ MUSB_RXCSR_DMAENAB |
+ MUSB_RXCSR_DMAMODE);
+- musb_writew(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
+- csr);
++ musb_writew(mbase, offset, csr);
+ }
+
+ musb_writew(mbase,
+@@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(in
+ && ((channel->desired_mode == 0)
+ || (channel->actual_len &
+ (musb_channel->max_packet_sz - 1)))
+- ) {
++ ) {
++ u8 epnum = musb_channel->epnum;
++ int offset = MUSB_EP_OFFSET(epnum,
++ MUSB_TXCSR);
++ u16 txcsr;
++
++ /*
++ * The programming guide says that we
++ * must clear DMAENAB before DMAMODE.
++ */
++ musb_ep_select(mbase, epnum);
++ txcsr = musb_readw(mbase, offset);
++ txcsr &= ~(MUSB_TXCSR_DMAENAB
++ | MUSB_TXCSR_AUTOSET);
++ musb_writew(mbase, offset, txcsr);
+ /* Send out the packet */
+- musb_ep_select(mbase,
+- musb_channel->epnum);
+- musb_writew(mbase, MUSB_EP_OFFSET(
+- musb_channel->epnum,
+- MUSB_TXCSR),
+- MUSB_TXCSR_TXPKTRDY);
++ txcsr &= ~MUSB_TXCSR_DMAMODE;
++ txcsr |= MUSB_TXCSR_TXPKTRDY;
++ musb_writew(mbase, offset, txcsr);
+ }
+ musb_dma_completion(musb, musb_channel->epnum,
+ musb_channel->transmit);
diff --git a/usb.current/usb-musb_host-fix-ep0-fifo-flushing.patch b/usb.current/usb-musb_host-fix-ep0-fifo-flushing.patch
new file mode 100644
index 00000000000000..edb42c45948678
--- /dev/null
+++ b/usb.current/usb-musb_host-fix-ep0-fifo-flushing.patch
@@ -0,0 +1,116 @@
+From david-b@pacbell.net Tue Apr 7 11:29:56 2009
+From: David Brownell <david-b@pacbell.net>
+Date: Thu, 26 Mar 2009 17:38:30 -0700
+Subject: USB: musb_host, fix ep0 fifo flushing
+To: Greg KH <greg@kroah.com>
+Cc: felipe.balbi@nokia.com
+Message-ID: <200903261738.30625.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: David Brownell <dbrownell@users.sourceforge.net>
+
+The MUSB host side can't share generic TX FIFO flush logic
+with EP0; the EP0 TX status register bits are different
+from those for other entpoints.
+
+Resolve this issue by providing a new EP0-specific routine
+to flush and reset the FIFO, which pays careful attention to
+restrictions listed in the latest programmer's guide. This
+gets rid of an open issue whereby the usbtest control write
+test (#14) failed.
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_host.c | 43 +++++++++++++++++++++++++++++--------------
+ 1 file changed, 29 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -125,6 +125,29 @@ static void musb_h_tx_flush_fifo(struct
+ }
+ }
+
++static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
++{
++ void __iomem *epio = ep->regs;
++ u16 csr;
++ int retries = 5;
++
++ /* scrub any data left in the fifo */
++ do {
++ csr = musb_readw(epio, MUSB_TXCSR);
++ if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
++ break;
++ musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
++ csr = musb_readw(epio, MUSB_TXCSR);
++ udelay(10);
++ } while (--retries);
++
++ WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n",
++ ep->epnum, csr);
++
++ /* and reset for the next transfer */
++ musb_writew(epio, MUSB_TXCSR, 0);
++}
++
+ /*
+ * Start transmit. Caller is responsible for locking shared resources.
+ * musb must be locked.
+@@ -694,10 +717,7 @@ static void musb_ep_program(struct musb
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+ /* endpoint 0: just flush */
+- musb_writew(epio, MUSB_CSR0,
+- csr | MUSB_CSR0_FLUSHFIFO);
+- musb_writew(epio, MUSB_CSR0,
+- csr | MUSB_CSR0_FLUSHFIFO);
++ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ /* target addr and (for multipoint) hub addr/port */
+@@ -1063,11 +1083,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *
+ csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+ musb_writew(epio, MUSB_CSR0, csr);
+ } else {
+- csr |= MUSB_CSR0_FLUSHFIFO;
+- musb_writew(epio, MUSB_CSR0, csr);
+- musb_writew(epio, MUSB_CSR0, csr);
+- csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+- musb_writew(epio, MUSB_CSR0, csr);
++ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ musb_writeb(epio, MUSB_NAKLIMIT0, 0);
+@@ -1081,10 +1097,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *
+ * SHOULD NEVER HAPPEN! */
+ ERR("no URB for end 0\n");
+
+- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
+- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
+- musb_writew(epio, MUSB_CSR0, 0);
+-
++ musb_h_ep0_flush_fifo(hw_ep);
+ goto done;
+ }
+
+@@ -2043,7 +2056,7 @@ static int musb_cleanup_urb(struct urb *
+ * endpoint's irq status here to avoid bogus irqs.
+ * clearing that status is platform-specific...
+ */
+- } else {
++ } else if (ep->epnum) {
+ musb_h_tx_flush_fifo(ep);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_AUTOSET
+@@ -2057,6 +2070,8 @@ static int musb_cleanup_urb(struct urb *
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* flush cpu writebuffer */
+ csr = musb_readw(epio, MUSB_TXCSR);
++ } else {
++ musb_h_ep0_flush_fifo(ep);
+ }
+ if (status == 0)
+ musb_advance_schedule(ep->musb, urb, ep, is_in);
diff --git a/usb.current/usb-musb_host-minor-enqueue-locking-fix.patch b/usb.current/usb-musb_host-minor-enqueue-locking-fix.patch
new file mode 100644
index 00000000000000..26aa6a2b7d2635
--- /dev/null
+++ b/usb.current/usb-musb_host-minor-enqueue-locking-fix.patch
@@ -0,0 +1,64 @@
+From david-b@pacbell.net Tue Apr 7 11:19:45 2009
+From: David Brownell <david-b@pacbell.net>
+Date: Thu, 26 Mar 2009 17:36:57 -0700
+Subject: USB: musb_host, minor enqueue locking fix (v2)
+To: Greg KH <greg@kroah.com>
+Cc: <felipe.balbi@nokia.com>
+Message-ID: <200903261736.58123.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: David Brownell <dbrownell@users.sourceforge.net>
+
+Someone noted that the enqueue path used an unlocked access
+for usb_host_endpoint->hcpriv ... fix that, by being safe
+and always accessing it under spinlock protection.
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_host.c | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -1841,7 +1841,7 @@ static int musb_urb_enqueue(
+ unsigned long flags;
+ struct musb *musb = hcd_to_musb(hcd);
+ struct usb_host_endpoint *hep = urb->ep;
+- struct musb_qh *qh = hep->hcpriv;
++ struct musb_qh *qh;
+ struct usb_endpoint_descriptor *epd = &hep->desc;
+ int ret;
+ unsigned type_reg;
+@@ -1853,22 +1853,21 @@ static int musb_urb_enqueue(
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = usb_hcd_link_urb_to_ep(hcd, urb);
++ qh = ret ? NULL : hep->hcpriv;
++ if (qh)
++ urb->hcpriv = qh;
+ spin_unlock_irqrestore(&musb->lock, flags);
+- if (ret)
+- return ret;
+
+ /* DMA mapping was already done, if needed, and this urb is on
+- * hep->urb_list ... so there's little to do unless hep wasn't
+- * yet scheduled onto a live qh.
++ * hep->urb_list now ... so we're done, unless hep wasn't yet
++ * scheduled onto a live qh.
+ *
+ * REVISIT best to keep hep->hcpriv valid until the endpoint gets
+ * disabled, testing for empty qh->ring and avoiding qh setup costs
+ * except for the first urb queued after a config change.
+ */
+- if (qh) {
+- urb->hcpriv = qh;
+- return 0;
+- }
++ if (qh || ret)
++ return ret;
+
+ /* Allocate and initialize qh, minimizing the work done each time
+ * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it.
diff --git a/usb.current/usb-option-add-ids-for-d-link-dwm-652-3.5g-modem.patch b/usb.current/usb-option-add-ids-for-d-link-dwm-652-3.5g-modem.patch
new file mode 100644
index 00000000000000..92b5d52608d72e
--- /dev/null
+++ b/usb.current/usb-option-add-ids-for-d-link-dwm-652-3.5g-modem.patch
@@ -0,0 +1,66 @@
+From pterjan@mandriva.com Tue Apr 7 11:11:00 2009
+From: Pascal Terjan <pterjan@mandriva.com>
+Date: Tue, 07 Apr 2009 14:40:42 +0200
+Subject: USB: option: Add ids for D-Link DWM-652 3.5G modem
+Message-ID: <1239108042.31094.9.camel@plop>
+
+
+This patch allows D-Link DWM-652 3.5G modem to work.
+It is an express card but was only tested with the provided usb adapter as I
+don't have machines with express card connector.
+
+/dev/ttyUSB{0,1,2} get created, and using comgt on ttyUSB1 works fine :
+
+[root@plop tmp]# comgt -d /dev/ttyUSB1 -e
+
+Enter PIN number: XXXX
+Waiting for Registration..(120 sec max).
+Registered on Home network: "Orange France",2
+Signal Quality: 15,99
+
+From: Pascal Terjan <pterjan@mandriva.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 5 +++++
+ drivers/usb/storage/unusual_devs.h | 8 ++++++++
+ 2 files changed, 13 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -300,6 +300,10 @@ static int option_resume(struct usb_ser
+ #define BENQ_VENDOR_ID 0x04a5
+ #define BENQ_PRODUCT_H10 0x4068
+
++#define DLINK_VENDOR_ID 0x1186
++#define DLINK_PRODUCT_DWM_652 0x3e04
++
++
+ static struct usb_device_id option_ids[] = {
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+@@ -516,6 +520,7 @@ static struct usb_device_id option_ids[]
+ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
+ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
+ { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
++ { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
+ { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
+ { } /* Terminating entry */
+ };
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1376,6 +1376,14 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 0),
+
++/* Reported by Pascal Terjan <pterjan@mandriva.com>
++ * Ignore driver CD mode and force into modem mode by default.
++ */
++UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000,
++ "D-Link",
++ "USB Mass Storage",
++ US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0),
++
+ /* Reported by Kevin Lloyd <linux@sierrawireless.com>
+ * Entry is needed for the initializer function override,
+ * which instructs the device to load as a modem
diff --git a/usb.current/usb-qcserial-add-extra-device-ids.patch b/usb.current/usb-qcserial-add-extra-device-ids.patch
new file mode 100644
index 00000000000000..3467b6352d9922
--- /dev/null
+++ b/usb.current/usb-qcserial-add-extra-device-ids.patch
@@ -0,0 +1,52 @@
+From mjg59@srcf.ucam.org Tue Apr 7 11:11:49 2009
+From: Matthew Garrett <mjg59@srcf.ucam.org>
+Date: Sat, 4 Apr 2009 17:24:24 +0100
+Subject: USB: qcserial: Add extra device IDs
+To: Greg KH <gregkh@suse.de>
+Cc: <shurik@gwu.edu>
+Message-ID: <20090404162424.GA5799@srcf.ucam.org>
+Content-Disposition: inline
+
+
+Add a set of device IDs from the Windows drivers. These aren't complete
+(there's a couple of cases where a QDL device is identified without the
+associated modem being identified), but it's better than the current
+situation.
+
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/qcserial.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -26,6 +26,27 @@ static struct usb_device_id id_table[] =
+ {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+ {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
+ {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
++ {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
++ {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
++ {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
++ {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
++ {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
++ {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
++ {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
++ {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
++ {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
++ {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
++ {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
++ {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
++ {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
++ {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
++ {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
++ {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
++ {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
++ {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
++ {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
++ {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
++ {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/usb.current/usb-usb-storage-augment-unusual_devs-entry-for-simple-tech-datafab.patch b/usb.current/usb-usb-storage-augment-unusual_devs-entry-for-simple-tech-datafab.patch
new file mode 100644
index 00000000000000..f15309835729bc
--- /dev/null
+++ b/usb.current/usb-usb-storage-augment-unusual_devs-entry-for-simple-tech-datafab.patch
@@ -0,0 +1,41 @@
+From stern@rowland.harvard.edu Tue Apr 7 11:29:13 2009
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 24 Mar 2009 10:39:13 -0400 (EDT)
+Subject: USB: usb-storage: augment unusual_devs entry for Simple Tech/Datafab
+To: Greg KH <greg@kroah.com>
+Cc: binbin <binbinsh@gmail.com>, Phil Dibowitz <phil@ipom.com>
+Message-ID: <Pine.LNX.4.44L0.0903241037000.3162-100000@iolanthe.rowland.org>
+
+
+This patch (as1227) adds the MAX_SECTORS_64 flag to the unusual_devs
+entry for the Simple Tech/Datafab controller. This fixes Bugzilla
+#12882.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-and-tested-by: binbin <binbinsh@gmail.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/storage/unusual_devs.h | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -975,12 +975,14 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0x
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ),
+
+-/* Reported by Rauch Wolke <rauchwolke@gmx.net> */
++/* Reported by Rauch Wolke <rauchwolke@gmx.net>
++ * and augmented by binbin <binbinsh@gmail.com> (Bugzilla #12882)
++ */
+ UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff,
+ "Simple Tech/Datafab",
+ "CF+SM Reader",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+- US_FL_IGNORE_RESIDUE ),
++ US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
+
+ /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
+ * to the USB storage specification in two ways:
diff --git a/version b/version
index 230a66c557ac82..d0380a798b790a 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-2.6.29-git13
+2.6.29-git15