summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-05-30 14:13:32 +0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-30 14:13:32 +0800
commitc7b7dc719d3c3184794f5419ca4074ee998f0ec1 (patch)
tree111fca1f67ae56ac9e17a91c74ff13cd4570a16f
parent1c258d2c9ace09fd43430a15b5f715d0849886a1 (diff)
downloadstable-queue-c7b7dc719d3c3184794f5419ca4074ee998f0ec1.tar.gz
.39 patches
-rw-r--r--queue-2.6.39/bind-only-modem-at-command-endpoint-to-option-module.patch44
-rw-r--r--queue-2.6.39/cx88-fix-locking-of-sub-driver-operations.patch116
-rw-r--r--queue-2.6.39/cx88-hold-device-lock-during-sub-driver.patch88
-rw-r--r--queue-2.6.39/cx88-protect-per-device-driver-list-with-device.patch161
-rw-r--r--queue-2.6.39/dibxxxx-get-rid-of-dma-buffer-on-stack.patch1188
-rw-r--r--queue-2.6.39/ecryptfs-allow-2-scatterlist-entries-for-encrypted.patch143
-rw-r--r--queue-2.6.39/ecryptfs-clear-i_nlink-in-rmdir.patch33
-rw-r--r--queue-2.6.39/mfd-fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch67
-rw-r--r--queue-2.6.39/ohci-fix-regression-caused-by-nvidia-shutdown-workaround.patch68
-rw-r--r--queue-2.6.39/p54usb-add-zoom-4410-usbid.patch28
-rw-r--r--queue-2.6.39/series26
-rw-r--r--queue-2.6.39/sh-clkfwk-fixup-clk_rate_table_build-parameter-in-div6.patch33
-rw-r--r--queue-2.6.39/sh-fixup-fpu.o-compile-order.patch38
-rw-r--r--queue-2.6.39/usb-cdc_acm-fix-oops-when-droids-muin-lcd-is-connected.patch70
-rw-r--r--queue-2.6.39/usb-cp210x-add-4-device-ids-for-ac-services-devices.patch32
-rw-r--r--queue-2.6.39/usb-gadget-at91sam9g20-fix-end-point-max-packet-size.patch30
-rw-r--r--queue-2.6.39/usb-gadget-g_multi-fixed-vendor-and-product-id-in-inf.patch60
-rw-r--r--queue-2.6.39/usb-gadget-rndis-don-t-test-against-req-length.patch38
-rw-r--r--queue-2.6.39/usb-gamin_gps-fix-for-data-transfer-problems-in-native.patch115
-rw-r--r--queue-2.6.39/usb-moto_modem-add-usb-identifier-for-the-motorola-ve240.patch29
-rw-r--r--queue-2.6.39/usb-option-add-support-for-huawei-e353-device.patch46
-rw-r--r--queue-2.6.39/usb-remove-remaining-usages-of-hcd-state-from-usbcore-and.patch192
-rw-r--r--queue-2.6.39/usb-serial-ftdi_sio-adding-support-for-tavir-stk500.patch47
-rw-r--r--queue-2.6.39/xhci-fix-bug-in-control-transfer-cancellation.patch84
-rw-r--r--queue-2.6.39/xhci-fix-full-speed-binterval-encoding.patch63
-rw-r--r--queue-2.6.39/xhci-fix-memory-leak-bug-when-dropping-endpoints.patch65
-rw-r--r--queue-2.6.39/xhci-fix-memory-leak-in-ring-cache-deallocation.patch64
27 files changed, 2968 insertions, 0 deletions
diff --git a/queue-2.6.39/bind-only-modem-at-command-endpoint-to-option-module.patch b/queue-2.6.39/bind-only-modem-at-command-endpoint-to-option-module.patch
new file mode 100644
index 0000000000..82a6cd4a1b
--- /dev/null
+++ b/queue-2.6.39/bind-only-modem-at-command-endpoint-to-option-module.patch
@@ -0,0 +1,44 @@
+From 15b2f3204a5c878c32939094775fb7349f707263 Mon Sep 17 00:00:00 2001
+From: "Marius B. Kotsbak" <marius@kotsbak.com>
+Date: Mon, 21 Mar 2011 23:27:21 +0100
+Subject: Bind only modem AT command endpoint to option module.
+
+From: "Marius B. Kotsbak" <marius@kotsbak.com>
+
+commit 15b2f3204a5c878c32939094775fb7349f707263 upstream.
+
+Network interface is handled by upcoming gt_b3730 module.
+
+Removed "GT-B3710" from comment, it is another modem with another USB ID.
+
+Signed-off-by: Marius B. Kotsbak <marius@kotsbak.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -972,7 +972,7 @@ static const struct usb_device_id option
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+ { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+- { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730/GT-B3710 LTE USB modem.*/
++ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);
+@@ -1109,6 +1109,12 @@ static int option_probe(struct usb_seria
+ serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+ return -ENODEV;
+
++ /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
++ if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
++ serial->dev->descriptor.idProduct == SAMSUNG_PRODUCT_GT_B3730 &&
++ serial->interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA)
++ return -ENODEV;
++
+ data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
+
+ if (!data)
diff --git a/queue-2.6.39/cx88-fix-locking-of-sub-driver-operations.patch b/queue-2.6.39/cx88-fix-locking-of-sub-driver-operations.patch
new file mode 100644
index 0000000000..610fd58291
--- /dev/null
+++ b/queue-2.6.39/cx88-fix-locking-of-sub-driver-operations.patch
@@ -0,0 +1,116 @@
+From 1fe70e963028f34ba5e32488a7870ff4b410b19b Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Sun, 1 May 2011 06:29:37 -0300
+Subject: [media] cx88: fix locking of sub-driver operations
+
+From: Jonathan Nieder <jrnieder@gmail.com>
+
+commit 1fe70e963028f34ba5e32488a7870ff4b410b19b upstream.
+
+The BKL conversion of this driver seems to have gone wrong.
+Loading the cx88-blackbird driver deadlocks.
+
+The cause: mpeg_ops::open in the cx2388x blackbird driver acquires the
+device lock and calls the sub-driver's request_acquire, which tries to
+acquire the lock again. Fix it by clarifying the semantics of
+request_acquire, request_release, advise_acquire, and advise_release:
+now all will rely on the caller to acquire the device lock.
+
+Based on work by Ben Hutchings <ben@decadent.org.uk>.
+
+Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=31962
+
+Reported-by: Andi Huber <hobrom@gmx.at>
+Tested-by: Andi Huber <hobrom@gmx.at>
+Tested-by: Marlon de Boer <marlon@hyves.nl>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/video/cx88/cx88-blackbird.c | 4 ++--
+ drivers/media/video/cx88/cx88-dvb.c | 3 +--
+ drivers/media/video/cx88/cx88-mpeg.c | 4 ----
+ drivers/media/video/cx88/cx88.h | 3 ++-
+ 4 files changed, 5 insertions(+), 9 deletions(-)
+
+--- a/drivers/media/video/cx88/cx88-blackbird.c
++++ b/drivers/media/video/cx88/cx88-blackbird.c
+@@ -1125,13 +1125,13 @@ static int mpeg_release(struct file *fil
+
+ /* Make sure we release the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+- mutex_unlock(&dev->core->lock);
+-
+ if (drv)
+ drv->request_release(drv);
+
+ atomic_dec(&dev->core->mpeg_users);
+
++ mutex_unlock(&dev->core->lock);
++
+ return 0;
+ }
+
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -135,8 +135,6 @@ static int cx88_dvb_bus_ctrl(struct dvb_
+
+ mutex_lock(&dev->core->lock);
+ drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
+- mutex_unlock(&dev->core->lock);
+-
+ if (drv) {
+ if (acquire){
+ dev->frontends.active_fe_id = fe_id;
+@@ -146,6 +144,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_
+ dev->frontends.active_fe_id = 0;
+ }
+ }
++ mutex_unlock(&dev->core->lock);
+
+ return ret;
+ }
+--- a/drivers/media/video/cx88/cx88-mpeg.c
++++ b/drivers/media/video/cx88/cx88-mpeg.c
+@@ -624,13 +624,11 @@ static int cx8802_request_acquire(struct
+
+ if (drv->advise_acquire)
+ {
+- mutex_lock(&drv->core->lock);
+ core->active_ref++;
+ if (core->active_type_id == CX88_BOARD_NONE) {
+ core->active_type_id = drv->type_id;
+ drv->advise_acquire(drv);
+ }
+- mutex_unlock(&drv->core->lock);
+
+ mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ }
+@@ -643,14 +641,12 @@ static int cx8802_request_release(struct
+ {
+ struct cx88_core *core = drv->core;
+
+- mutex_lock(&drv->core->lock);
+ if (drv->advise_release && --core->active_ref == 0)
+ {
+ drv->advise_release(drv);
+ core->active_type_id = CX88_BOARD_NONE;
+ mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ }
+- mutex_unlock(&drv->core->lock);
+
+ return 0;
+ }
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -510,7 +510,8 @@ struct cx8802_driver {
+ /* Caller must _not_ hold core->lock */
+ int (*probe)(struct cx8802_driver *drv);
+
+- /* Caller must hold core->lock */
++ /* Callers to the following functions must hold core->lock */
++
+ int (*remove)(struct cx8802_driver *drv);
+
+ /* MPEG 8802 -> mini driver - Access for hardware control */
diff --git a/queue-2.6.39/cx88-hold-device-lock-during-sub-driver.patch b/queue-2.6.39/cx88-hold-device-lock-during-sub-driver.patch
new file mode 100644
index 0000000000..60243fe829
--- /dev/null
+++ b/queue-2.6.39/cx88-hold-device-lock-during-sub-driver.patch
@@ -0,0 +1,88 @@
+From 1d6213ab995c61f7d1d81cf6cf876acf15d6e714 Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Sun, 1 May 2011 06:29:56 -0300
+Subject: [media] cx88: hold device lock during sub-driver
+ initialization
+
+From: Jonathan Nieder <jrnieder@gmail.com>
+
+commit 1d6213ab995c61f7d1d81cf6cf876acf15d6e714 upstream.
+
+cx8802_blackbird_probe makes a device node for the mpeg sub-device
+before it has been added to dev->drvlist. If the device is opened
+during that time, the open succeeds but request_acquire cannot be
+called, so the reference count remains zero. Later, when the device
+is closed, the reference count becomes negative --- uh oh.
+
+Close the race by holding core->lock during probe and not releasing
+until the device is in drvlist and initialization finished.
+Previously the BKL prevented this race.
+
+Reported-by: Andreas Huber <hobrom@gmx.at>
+Tested-by: Andi Huber <hobrom@gmx.at>
+Tested-by: Marlon de Boer <marlon@hyves.nl>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/video/cx88/cx88-blackbird.c | 2 --
+ drivers/media/video/cx88/cx88-mpeg.c | 5 ++---
+ drivers/media/video/cx88/cx88.h | 7 ++-----
+ 3 files changed, 4 insertions(+), 10 deletions(-)
+
+--- a/drivers/media/video/cx88/cx88-blackbird.c
++++ b/drivers/media/video/cx88/cx88-blackbird.c
+@@ -1335,11 +1335,9 @@ static int cx8802_blackbird_probe(struct
+ blackbird_register_video(dev);
+
+ /* initial device configuration: needed ? */
+- mutex_lock(&dev->core->lock);
+ // init_controls(core);
+ cx88_set_tvnorm(core,core->tvnorm);
+ cx88_video_mux(core,0);
+- mutex_unlock(&dev->core->lock);
+
+ return 0;
+
+--- a/drivers/media/video/cx88/cx88-mpeg.c
++++ b/drivers/media/video/cx88/cx88-mpeg.c
+@@ -709,18 +709,17 @@ int cx8802_register_driver(struct cx8802
+ drv->request_release = cx8802_request_release;
+ memcpy(driver, drv, sizeof(*driver));
+
++ mutex_lock(&drv->core->lock);
+ err = drv->probe(driver);
+ if (err == 0) {
+ i++;
+- mutex_lock(&drv->core->lock);
+ list_add_tail(&driver->drvlist, &dev->drvlist);
+- mutex_unlock(&drv->core->lock);
+ } else {
+ printk(KERN_ERR
+ "%s/2: cx8802 probe failed, err = %d\n",
+ dev->core->name, err);
+ }
+-
++ mutex_unlock(&drv->core->lock);
+ }
+
+ return i ? 0 : -ENODEV;
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -505,13 +505,10 @@ struct cx8802_driver {
+ int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
+ int (*resume)(struct pci_dev *pci_dev);
+
+- /* MPEG 8802 -> mini driver - Driver probe and configuration */
+-
+- /* Caller must _not_ hold core->lock */
+- int (*probe)(struct cx8802_driver *drv);
+-
+ /* Callers to the following functions must hold core->lock */
+
++ /* MPEG 8802 -> mini driver - Driver probe and configuration */
++ int (*probe)(struct cx8802_driver *drv);
+ int (*remove)(struct cx8802_driver *drv);
+
+ /* MPEG 8802 -> mini driver - Access for hardware control */
diff --git a/queue-2.6.39/cx88-protect-per-device-driver-list-with-device.patch b/queue-2.6.39/cx88-protect-per-device-driver-list-with-device.patch
new file mode 100644
index 0000000000..062b0615d1
--- /dev/null
+++ b/queue-2.6.39/cx88-protect-per-device-driver-list-with-device.patch
@@ -0,0 +1,161 @@
+From 8a317a8760cfffa8185b56ff59fb4b6c58488d79 Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Sun, 1 May 2011 06:29:16 -0300
+Subject: [media] cx88: protect per-device driver list with device
+ lock
+
+From: Jonathan Nieder <jrnieder@gmail.com>
+
+commit 8a317a8760cfffa8185b56ff59fb4b6c58488d79 upstream.
+
+The BKL conversion of this driver seems to have gone wrong. Various
+uses of the sub-device and driver lists appear to be subject to race
+conditions.
+
+In particular, some functions access drvlist without a relevant lock
+held, which will race against removal of drivers. Let's start with
+that --- clean up by consistently protecting dev->drvlist with
+dev->core->lock, noting driver functions that require the device lock
+to be held or not to be held.
+
+After this patch, there are still some races --- e.g.,
+cx8802_blackbird_remove can run between the time the blackbird driver
+is acquired and the time it is used in mpeg_release, and there's a
+similar race in cx88_dvb_bus_ctrl. Later patches will address the
+remaining known races and the deadlock noticed by Andi. This patch
+just makes the semantics clearer in preparation for those later
+changes.
+
+Based on work by Ben Hutchings <ben@decadent.org.uk>.
+
+Tested-by: Andi Huber <hobrom@gmx.at>
+Tested-by: Marlon de Boer <marlon@hyves.nl>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/video/cx88/cx88-blackbird.c | 3 ++-
+ drivers/media/video/cx88/cx88-dvb.c | 3 +++
+ drivers/media/video/cx88/cx88-mpeg.c | 11 +++++++----
+ drivers/media/video/cx88/cx88.h | 9 ++++++++-
+ 4 files changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/media/video/cx88/cx88-blackbird.c
++++ b/drivers/media/video/cx88/cx88-blackbird.c
+@@ -1122,10 +1122,11 @@ static int mpeg_release(struct file *fil
+ mutex_lock(&dev->core->lock);
+ file->private_data = NULL;
+ kfree(fh);
+- mutex_unlock(&dev->core->lock);
+
+ /* Make sure we release the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
++ mutex_unlock(&dev->core->lock);
++
+ if (drv)
+ drv->request_release(drv);
+
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -133,7 +133,10 @@ static int cx88_dvb_bus_ctrl(struct dvb_
+ return -EINVAL;
+ }
+
++ mutex_lock(&dev->core->lock);
+ drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
++ mutex_unlock(&dev->core->lock);
++
+ if (drv) {
+ if (acquire){
+ dev->frontends.active_fe_id = fe_id;
+--- a/drivers/media/video/cx88/cx88-mpeg.c
++++ b/drivers/media/video/cx88/cx88-mpeg.c
+@@ -748,6 +748,8 @@ int cx8802_unregister_driver(struct cx88
+ dev->pci->subsystem_device, dev->core->board.name,
+ dev->core->boardnr);
+
++ mutex_lock(&dev->core->lock);
++
+ list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
+ /* only unregister the correct driver type */
+ if (d->type_id != drv->type_id)
+@@ -755,15 +757,14 @@ int cx8802_unregister_driver(struct cx88
+
+ err = d->remove(d);
+ if (err == 0) {
+- mutex_lock(&drv->core->lock);
+ list_del(&d->drvlist);
+- mutex_unlock(&drv->core->lock);
+ kfree(d);
+ } else
+ printk(KERN_ERR "%s/2: cx8802 driver remove "
+ "failed (%d)\n", dev->core->name, err);
+ }
+
++ mutex_unlock(&dev->core->lock);
+ }
+
+ return err;
+@@ -827,6 +828,8 @@ static void __devexit cx8802_remove(stru
+
+ flush_request_modules(dev);
+
++ mutex_lock(&dev->core->lock);
++
+ if (!list_empty(&dev->drvlist)) {
+ struct cx8802_driver *drv, *tmp;
+ int err;
+@@ -838,9 +841,7 @@ static void __devexit cx8802_remove(stru
+ list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
+ err = drv->remove(drv);
+ if (err == 0) {
+- mutex_lock(&drv->core->lock);
+ list_del(&drv->drvlist);
+- mutex_unlock(&drv->core->lock);
+ } else
+ printk(KERN_ERR "%s/2: cx8802 driver remove "
+ "failed (%d)\n", dev->core->name, err);
+@@ -848,6 +849,8 @@ static void __devexit cx8802_remove(stru
+ }
+ }
+
++ mutex_unlock(&dev->core->lock);
++
+ /* Destroy any 8802 reference. */
+ dev->core->dvbdev = NULL;
+
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -506,7 +506,11 @@ struct cx8802_driver {
+ int (*resume)(struct pci_dev *pci_dev);
+
+ /* MPEG 8802 -> mini driver - Driver probe and configuration */
++
++ /* Caller must _not_ hold core->lock */
+ int (*probe)(struct cx8802_driver *drv);
++
++ /* Caller must hold core->lock */
+ int (*remove)(struct cx8802_driver *drv);
+
+ /* MPEG 8802 -> mini driver - Access for hardware control */
+@@ -561,8 +565,9 @@ struct cx8802_dev {
+ /* for switching modulation types */
+ unsigned char ts_gen_cntrl;
+
+- /* List of attached drivers */
++ /* List of attached drivers; must hold core->lock to access */
+ struct list_head drvlist;
++
+ struct work_struct request_module_wk;
+ };
+
+@@ -685,6 +690,8 @@ int cx88_audio_thread(void *data);
+
+ int cx8802_register_driver(struct cx8802_driver *drv);
+ int cx8802_unregister_driver(struct cx8802_driver *drv);
++
++/* Caller must hold core->lock */
+ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+
+ /* ----------------------------------------------------------- */
diff --git a/queue-2.6.39/dibxxxx-get-rid-of-dma-buffer-on-stack.patch b/queue-2.6.39/dibxxxx-get-rid-of-dma-buffer-on-stack.patch
new file mode 100644
index 0000000000..8643834125
--- /dev/null
+++ b/queue-2.6.39/dibxxxx-get-rid-of-dma-buffer-on-stack.patch
@@ -0,0 +1,1188 @@
+From 5a0deeed5741117ee8625d6305d0034e219f102c Mon Sep 17 00:00:00 2001
+From: Olivier Grenie <olivier.grenie@dibcom.fr>
+Date: Tue, 3 May 2011 12:27:33 -0300
+Subject: [media] DiBxxxx: get rid of DMA buffer on stack
+
+From: Olivier Grenie <olivier.grenie@dibcom.fr>
+
+commit 5a0deeed5741117ee8625d6305d0034e219f102c upstream.
+
+This patch removes the remaining on-stack buffer for USB DMA transfer.
+This patch also reduces the stack memory usage.
+
+Cc: Florian Mickler <florian@mickler.org>
+Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
+Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/dvb/frontends/dib0070.c | 40 ++++--
+ drivers/media/dvb/frontends/dib0090.c | 71 ++++++++---
+ drivers/media/dvb/frontends/dib7000m.c | 47 ++++---
+ drivers/media/dvb/frontends/dib7000p.c | 72 ++++++++---
+ drivers/media/dvb/frontends/dib8000.c | 126 ++++++++++++++-----
+ drivers/media/dvb/frontends/dib9000.c | 172 +++++++++++++++++----------
+ drivers/media/dvb/frontends/dibx000_common.c | 113 ++++++++++-------
+ drivers/media/dvb/frontends/dibx000_common.h | 5
+ 8 files changed, 444 insertions(+), 202 deletions(-)
+
+--- a/drivers/media/dvb/frontends/dib0070.c
++++ b/drivers/media/dvb/frontends/dib0070.c
+@@ -73,27 +73,47 @@ struct dib0070_state {
+
+ u8 wbd_gain_current;
+ u16 wbd_offset_3_3[2];
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[2];
++ u8 i2c_write_buffer[3];
++ u8 i2c_read_buffer[2];
+ };
+
+ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+ {
+- u8 b[2];
+- struct i2c_msg msg[2] = {
+- { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
+- { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
+- };
+- if (i2c_transfer(state->i2c, msg, 2) != 2) {
++ state->i2c_write_buffer[0] = reg;
++
++ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
++ state->msg[0].addr = state->cfg->i2c_address;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 1;
++ state->msg[1].addr = state->cfg->i2c_address;
++ state->msg[1].flags = I2C_M_RD;
++ state->msg[1].buf = state->i2c_read_buffer;
++ state->msg[1].len = 2;
++
++ if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0070 I2C read failed\n");
+ return 0;
+ }
+- return (b[0] << 8) | b[1];
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+ {
+- u8 b[3] = { reg, val >> 8, val & 0xff };
+- struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
+- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++ state->i2c_write_buffer[0] = reg;
++ state->i2c_write_buffer[1] = val >> 8;
++ state->i2c_write_buffer[2] = val & 0xff;
++
++ memset(state->msg, 0, sizeof(struct i2c_msg));
++ state->msg[0].addr = state->cfg->i2c_address;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 3;
++
++ if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0070 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+--- a/drivers/media/dvb/frontends/dib0090.c
++++ b/drivers/media/dvb/frontends/dib0090.c
+@@ -191,6 +191,11 @@ struct dib0090_state {
+ u8 wbd_calibration_gain;
+ const struct dib0090_wbd_slope *current_wbd_table;
+ u16 wbdmux;
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[2];
++ u8 i2c_write_buffer[3];
++ u8 i2c_read_buffer[2];
+ };
+
+ struct dib0090_fw_state {
+@@ -198,27 +203,48 @@ struct dib0090_fw_state {
+ struct dvb_frontend *fe;
+ struct dib0090_identity identity;
+ const struct dib0090_config *config;
++
++ /* for the I2C transfer */
++ struct i2c_msg msg;
++ u8 i2c_write_buffer[2];
++ u8 i2c_read_buffer[2];
+ };
+
+ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+ {
+- u8 b[2];
+- struct i2c_msg msg[2] = {
+- {.addr = state->config->i2c_address, .flags = 0, .buf = &reg, .len = 1},
+- {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
+- };
+- if (i2c_transfer(state->i2c, msg, 2) != 2) {
++ state->i2c_write_buffer[0] = reg;
++
++ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
++ state->msg[0].addr = state->config->i2c_address;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 1;
++ state->msg[1].addr = state->config->i2c_address;
++ state->msg[1].flags = I2C_M_RD;
++ state->msg[1].buf = state->i2c_read_buffer;
++ state->msg[1].len = 2;
++
++ if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0090 I2C read failed\n");
+ return 0;
+ }
+- return (b[0] << 8) | b[1];
++
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+ {
+- u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
+- struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
+- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++ state->i2c_write_buffer[0] = reg & 0xff;
++ state->i2c_write_buffer[1] = val >> 8;
++ state->i2c_write_buffer[2] = val & 0xff;
++
++ memset(state->msg, 0, sizeof(struct i2c_msg));
++ state->msg[0].addr = state->config->i2c_address;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 3;
++
++ if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+@@ -227,20 +253,31 @@ static int dib0090_write_reg(struct dib0
+
+ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+ {
+- u8 b[2];
+- struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 };
+- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++ state->i2c_write_buffer[0] = reg;
++
++ memset(&state->msg, 0, sizeof(struct i2c_msg));
++ state->msg.addr = reg;
++ state->msg.flags = I2C_M_RD;
++ state->msg.buf = state->i2c_read_buffer;
++ state->msg.len = 2;
++ if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C read failed\n");
+ return 0;
+ }
+- return (b[0] << 8) | b[1];
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+ {
+- u8 b[2] = { val >> 8, val & 0xff };
+- struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 };
+- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++ state->i2c_write_buffer[0] = val >> 8;
++ state->i2c_write_buffer[1] = val & 0xff;
++
++ memset(&state->msg, 0, sizeof(struct i2c_msg));
++ state->msg.addr = reg;
++ state->msg.flags = 0;
++ state->msg.buf = state->i2c_write_buffer;
++ state->msg.len = 2;
++ if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+--- a/drivers/media/dvb/frontends/dib7000m.c
++++ b/drivers/media/dvb/frontends/dib7000m.c
+@@ -50,6 +50,11 @@ struct dib7000m_state {
+ u16 revision;
+
+ u8 agc_state;
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[2];
++ u8 i2c_write_buffer[4];
++ u8 i2c_read_buffer[2];
+ };
+
+ enum dib7000m_power_mode {
+@@ -64,29 +69,39 @@ enum dib7000m_power_mode {
+
+ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+ {
+- u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+- u8 rb[2];
+- struct i2c_msg msg[2] = {
+- { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
+- { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+- };
++ state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
++ state->i2c_write_buffer[1] = reg & 0xff;
++
++ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c_addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 2;
++ state->msg[1].addr = state->i2c_addr >> 1;
++ state->msg[1].flags = I2C_M_RD;
++ state->msg[1].buf = state->i2c_read_buffer;
++ state->msg[1].len = 2;
+
+- if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
++ if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+ dprintk("i2c read error on %d",reg);
+
+- return (rb[0] << 8) | rb[1];
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+ {
+- u8 b[4] = {
+- (reg >> 8) & 0xff, reg & 0xff,
+- (val >> 8) & 0xff, val & 0xff,
+- };
+- struct i2c_msg msg = {
+- .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+- };
+- return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
++ state->i2c_write_buffer[1] = reg & 0xff;
++ state->i2c_write_buffer[2] = (val >> 8) & 0xff;
++ state->i2c_write_buffer[3] = val & 0xff;
++
++ memset(&state->msg[0], 0, sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c_addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 4;
++
++ return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+ static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
+ {
+--- a/drivers/media/dvb/frontends/dib7000p.c
++++ b/drivers/media/dvb/frontends/dib7000p.c
+@@ -63,6 +63,11 @@ struct dib7000p_state {
+
+ u16 tuner_enable;
+ struct i2c_adapter dib7090_tuner_adap;
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[2];
++ u8 i2c_write_buffer[4];
++ u8 i2c_read_buffer[2];
+ };
+
+ enum dib7000p_power_mode {
+@@ -76,29 +81,39 @@ static int dib7090_set_diversity_in(stru
+
+ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+ {
+- u8 wb[2] = { reg >> 8, reg & 0xff };
+- u8 rb[2];
+- struct i2c_msg msg[2] = {
+- {.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
+- {.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
+- };
++ state->i2c_write_buffer[0] = reg >> 8;
++ state->i2c_write_buffer[1] = reg & 0xff;
++
++ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c_addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 2;
++ state->msg[1].addr = state->i2c_addr >> 1;
++ state->msg[1].flags = I2C_M_RD;
++ state->msg[1].buf = state->i2c_read_buffer;
++ state->msg[1].len = 2;
+
+- if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
++ if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (rb[0] << 8) | rb[1];
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+ {
+- u8 b[4] = {
+- (reg >> 8) & 0xff, reg & 0xff,
+- (val >> 8) & 0xff, val & 0xff,
+- };
+- struct i2c_msg msg = {
+- .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+- };
+- return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
++ state->i2c_write_buffer[1] = reg & 0xff;
++ state->i2c_write_buffer[2] = (val >> 8) & 0xff;
++ state->i2c_write_buffer[3] = val & 0xff;
++
++ memset(&state->msg[0], 0, sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c_addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 4;
++
++ return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+ static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
+@@ -1550,11 +1565,24 @@ static void dib7000p_release(struct dvb_
+
+ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+ {
+- u8 tx[2], rx[2];
++ u8 *tx, *rx;
+ struct i2c_msg msg[2] = {
+- {.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2},
+- {.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2},
++ {.addr = 18 >> 1, .flags = 0, .len = 2},
++ {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
+ };
++ int ret = 0;
++
++ tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
++ if (!tx)
++ return -ENOMEM;
++ rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
++ if (!rx) {
++ goto rx_memory_error;
++ ret = -ENOMEM;
++ }
++
++ msg[0].buf = tx;
++ msg[1].buf = rx;
+
+ tx[0] = 0x03;
+ tx[1] = 0x00;
+@@ -1574,7 +1602,11 @@ int dib7000pc_detection(struct i2c_adapt
+ }
+
+ dprintk("-D- DiB7000PC not detected");
+- return 0;
++
++ kfree(rx);
++rx_memory_error:
++ kfree(tx);
++ return ret;
+ }
+ EXPORT_SYMBOL(dib7000pc_detection);
+
+--- a/drivers/media/dvb/frontends/dib8000.c
++++ b/drivers/media/dvb/frontends/dib8000.c
+@@ -35,6 +35,8 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+ struct i2c_device {
+ struct i2c_adapter *adap;
+ u8 addr;
++ u8 *i2c_write_buffer;
++ u8 *i2c_read_buffer;
+ };
+
+ struct dib8000_state {
+@@ -70,6 +72,11 @@ struct dib8000_state {
+ u32 status;
+
+ struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[2];
++ u8 i2c_write_buffer[4];
++ u8 i2c_read_buffer[2];
+ };
+
+ enum dib8000_power_mode {
+@@ -79,22 +86,41 @@ enum dib8000_power_mode {
+
+ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
+ {
+- u8 wb[2] = { reg >> 8, reg & 0xff };
+- u8 rb[2];
+ struct i2c_msg msg[2] = {
+- {.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2},
+- {.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2},
++ {.addr = i2c->addr >> 1, .flags = 0,
++ .buf = i2c->i2c_write_buffer, .len = 2},
++ {.addr = i2c->addr >> 1, .flags = I2C_M_RD,
++ .buf = i2c->i2c_read_buffer, .len = 2},
+ };
+
++ msg[0].buf[0] = reg >> 8;
++ msg[0].buf[1] = reg & 0xff;
++
+ if (i2c_transfer(i2c->adap, msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (rb[0] << 8) | rb[1];
++ return (msg[1].buf[0] << 8) | msg[1].buf[1];
+ }
+
+ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+ {
+- return dib8000_i2c_read16(&state->i2c, reg);
++ state->i2c_write_buffer[0] = reg >> 8;
++ state->i2c_write_buffer[1] = reg & 0xff;
++
++ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c.addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 2;
++ state->msg[1].addr = state->i2c.addr >> 1;
++ state->msg[1].flags = I2C_M_RD;
++ state->msg[1].buf = state->i2c_read_buffer;
++ state->msg[1].len = 2;
++
++ if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
++ dprintk("i2c read error on %d", reg);
++
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
+@@ -109,19 +135,34 @@ static u32 dib8000_read32(struct dib8000
+
+ static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+ {
+- u8 b[4] = {
+- (reg >> 8) & 0xff, reg & 0xff,
+- (val >> 8) & 0xff, val & 0xff,
+- };
+- struct i2c_msg msg = {
+- .addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4
+- };
+- return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
++ .buf = i2c->i2c_write_buffer, .len = 4};
++ int ret = 0;
++
++ msg.buf[0] = (reg >> 8) & 0xff;
++ msg.buf[1] = reg & 0xff;
++ msg.buf[2] = (val >> 8) & 0xff;
++ msg.buf[3] = val & 0xff;
++
++ ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++
++ return ret;
+ }
+
+ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
+ {
+- return dib8000_i2c_write16(&state->i2c, reg, val);
++ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
++ state->i2c_write_buffer[1] = reg & 0xff;
++ state->i2c_write_buffer[2] = (val >> 8) & 0xff;
++ state->i2c_write_buffer[3] = val & 0xff;
++
++ memset(&state->msg[0], 0, sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c.addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 4;
++
++ return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+ static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
+@@ -980,30 +1021,31 @@ static void dib8000_update_timf(struct d
+ dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
+ }
+
++static const u16 adc_target_16dB[11] = {
++ (1 << 13) - 825 - 117,
++ (1 << 13) - 837 - 117,
++ (1 << 13) - 811 - 117,
++ (1 << 13) - 766 - 117,
++ (1 << 13) - 737 - 117,
++ (1 << 13) - 693 - 117,
++ (1 << 13) - 648 - 117,
++ (1 << 13) - 619 - 117,
++ (1 << 13) - 575 - 117,
++ (1 << 13) - 531 - 117,
++ (1 << 13) - 501 - 117
++};
++static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
++
+ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
+ {
+ u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
+ u8 guard, crate, constellation, timeI;
+- u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
+ u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled
+ const s16 *ncoeff = NULL, *ana_fe;
+ u16 tmcc_pow = 0;
+ u16 coff_pow = 0x2800;
+ u16 init_prbs = 0xfff;
+ u16 ana_gain = 0;
+- u16 adc_target_16dB[11] = {
+- (1 << 13) - 825 - 117,
+- (1 << 13) - 837 - 117,
+- (1 << 13) - 811 - 117,
+- (1 << 13) - 766 - 117,
+- (1 << 13) - 737 - 117,
+- (1 << 13) - 693 - 117,
+- (1 << 13) - 648 - 117,
+- (1 << 13) - 619 - 117,
+- (1 << 13) - 575 - 117,
+- (1 << 13) - 531 - 117,
+- (1 << 13) - 501 - 117
+- };
+
+ if (state->ber_monitored_layer != LAYER_ALL)
+ dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
+@@ -2379,10 +2421,22 @@ EXPORT_SYMBOL(dib8000_get_slave_frontend
+
+ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+ {
+- int k = 0;
++ int k = 0, ret = 0;
+ u8 new_addr = 0;
+ struct i2c_device client = {.adap = host };
+
++ client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
++ if (!client.i2c_write_buffer) {
++ dprintk("%s: not enough memory", __func__);
++ return -ENOMEM;
++ }
++ client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
++ if (!client.i2c_read_buffer) {
++ dprintk("%s: not enough memory", __func__);
++ ret = -ENOMEM;
++ goto error_memory;
++ }
++
+ for (k = no_of_demods - 1; k >= 0; k--) {
+ /* designated i2c address */
+ new_addr = first_addr + (k << 1);
+@@ -2394,7 +2448,8 @@ int dib8000_i2c_enumeration(struct i2c_a
+ client.addr = default_addr;
+ if (dib8000_identify(&client) == 0) {
+ dprintk("#%d: not identified", k);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto error;
+ }
+ }
+
+@@ -2420,7 +2475,12 @@ int dib8000_i2c_enumeration(struct i2c_a
+ dib8000_i2c_write16(&client, 1286, 0);
+ }
+
+- return 0;
++error:
++ kfree(client.i2c_read_buffer);
++error_memory:
++ kfree(client.i2c_write_buffer);
++
++ return ret;
+ }
+
+ EXPORT_SYMBOL(dib8000_i2c_enumeration);
+@@ -2519,6 +2579,8 @@ struct dvb_frontend *dib8000_attach(stru
+ memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
+ state->i2c.adap = i2c_adap;
+ state->i2c.addr = i2c_addr;
++ state->i2c.i2c_write_buffer = state->i2c_write_buffer;
++ state->i2c.i2c_read_buffer = state->i2c_read_buffer;
+ state->gpio_val = cfg->gpio_val;
+ state->gpio_dir = cfg->gpio_dir;
+
+--- a/drivers/media/dvb/frontends/dib9000.c
++++ b/drivers/media/dvb/frontends/dib9000.c
+@@ -27,6 +27,8 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+ struct i2c_device {
+ struct i2c_adapter *i2c_adap;
+ u8 i2c_addr;
++ u8 *i2c_read_buffer;
++ u8 *i2c_write_buffer;
+ };
+
+ /* lock */
+@@ -92,11 +94,16 @@ struct dib9000_state {
+
+ struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+ u16 component_bus_speed;
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[2];
++ u8 i2c_write_buffer[255];
++ u8 i2c_read_buffer[255];
+ };
+
+-u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+- 0, 0, 0
++ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ enum dib9000_power_mode {
+@@ -217,25 +224,33 @@ static u16 dib9000_read16_attr(struct di
+ u32 chunk_size = 126;
+ u32 l;
+ int ret;
+- u8 wb[2] = { reg >> 8, reg & 0xff };
+- struct i2c_msg msg[2] = {
+- {.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
+- {.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
+- };
+
+ if (state->platform.risc.fw_is_running && (reg < 1024))
+ return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
+
++ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c.i2c_addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = 2;
++ state->msg[1].addr = state->i2c.i2c_addr >> 1;
++ state->msg[1].flags = I2C_M_RD;
++ state->msg[1].buf = b;
++ state->msg[1].len = len;
++
++ state->i2c_write_buffer[0] = reg >> 8;
++ state->i2c_write_buffer[1] = reg & 0xff;
++
+ if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+- wb[0] |= (1 << 5);
++ state->i2c_write_buffer[0] |= (1 << 5);
+ if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+- wb[0] |= (1 << 4);
++ state->i2c_write_buffer[0] |= (1 << 4);
+
+ do {
+ l = len < chunk_size ? len : chunk_size;
+- msg[1].len = l;
+- msg[1].buf = b;
+- ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
++ state->msg[1].len = l;
++ state->msg[1].buf = b;
++ ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
+ if (ret != 0) {
+ dprintk("i2c read error on %d", reg);
+ return -EREMOTEIO;
+@@ -253,50 +268,47 @@ static u16 dib9000_read16_attr(struct di
+
+ static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
+ {
+- u8 b[2];
+- u8 wb[2] = { reg >> 8, reg & 0xff };
+ struct i2c_msg msg[2] = {
+- {.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
+- {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
++ {.addr = i2c->i2c_addr >> 1, .flags = 0,
++ .buf = i2c->i2c_write_buffer, .len = 2},
++ {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
++ .buf = i2c->i2c_read_buffer, .len = 2},
+ };
+
++ i2c->i2c_write_buffer[0] = reg >> 8;
++ i2c->i2c_write_buffer[1] = reg & 0xff;
++
+ if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
+ dprintk("read register %x error", reg);
+ return 0;
+ }
+
+- return (b[0] << 8) | b[1];
++ return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
+ }
+
+ static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
+ {
+- u8 b[2];
+- if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
++ if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
+ return 0;
+- return (b[0] << 8 | b[1]);
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
+ {
+- u8 b[2];
+- if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
++ if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
++ attribute) != 0)
+ return 0;
+- return (b[0] << 8 | b[1]);
++ return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ }
+
+ #define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+
+ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
+ {
+- u8 b[255];
+ u32 chunk_size = 126;
+ u32 l;
+ int ret;
+
+- struct i2c_msg msg = {
+- .addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
+- };
+-
+ if (state->platform.risc.fw_is_running && (reg < 1024)) {
+ if (dib9000_risc_apb_access_write
+ (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
+@@ -304,20 +316,26 @@ static u16 dib9000_write16_attr(struct d
+ return 0;
+ }
+
+- b[0] = (reg >> 8) & 0xff;
+- b[1] = (reg) & 0xff;
++ memset(&state->msg[0], 0, sizeof(struct i2c_msg));
++ state->msg[0].addr = state->i2c.i2c_addr >> 1;
++ state->msg[0].flags = 0;
++ state->msg[0].buf = state->i2c_write_buffer;
++ state->msg[0].len = len + 2;
++
++ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
++ state->i2c_write_buffer[1] = (reg) & 0xff;
+
+ if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+- b[0] |= (1 << 5);
++ state->i2c_write_buffer[0] |= (1 << 5);
+ if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+- b[0] |= (1 << 4);
++ state->i2c_write_buffer[0] |= (1 << 4);
+
+ do {
+ l = len < chunk_size ? len : chunk_size;
+- msg.len = l + 2;
+- memcpy(&b[2], buf, l);
++ state->msg[0].len = l + 2;
++ memcpy(&state->i2c_write_buffer[2], buf, l);
+
+- ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++ ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+
+ buf += l;
+ len -= l;
+@@ -331,11 +349,16 @@ static u16 dib9000_write16_attr(struct d
+
+ static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+ {
+- u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
+ struct i2c_msg msg = {
+- .addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
++ .addr = i2c->i2c_addr >> 1, .flags = 0,
++ .buf = i2c->i2c_write_buffer, .len = 4
+ };
+
++ i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
++ i2c->i2c_write_buffer[1] = reg & 0xff;
++ i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
++ i2c->i2c_write_buffer[3] = val & 0xff;
++
+ return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+@@ -1015,8 +1038,8 @@ static int dib9000_fw_memmbx_sync(struct
+ return 0;
+ dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
+ do {
+- dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
+- } while (i && index_loop--);
++ dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
++ } while (state->i2c_read_buffer[0] && index_loop--);
+
+ if (index_loop > 0)
+ return 0;
+@@ -1139,7 +1162,7 @@ static int dib9000_fw_get_channel(struct
+
+ s8 intlv_native;
+ };
+- struct dibDVBTChannel ch;
++ struct dibDVBTChannel *ch;
+ int ret = 0;
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+@@ -1148,9 +1171,12 @@ static int dib9000_fw_get_channel(struct
+ ret = -EIO;
+ }
+
+- dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
++ dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
++ state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
++ ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
++
+
+- switch (ch.spectrum_inversion & 0x7) {
++ switch (ch->spectrum_inversion & 0x7) {
+ case 1:
+ state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
+ break;
+@@ -1162,7 +1188,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
+ break;
+ }
+- switch (ch.nfft) {
++ switch (ch->nfft) {
+ case 0:
+ state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+@@ -1177,7 +1203,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
+ break;
+ }
+- switch (ch.guard) {
++ switch (ch->guard) {
+ case 0:
+ state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
+ break;
+@@ -1195,7 +1221,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
+ break;
+ }
+- switch (ch.constellation) {
++ switch (ch->constellation) {
+ case 2:
+ state->fe[0]->dtv_property_cache.modulation = QAM_64;
+ break;
+@@ -1210,7 +1236,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
+ break;
+ }
+- switch (ch.hrch) {
++ switch (ch->hrch) {
+ case 0:
+ state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
+ break;
+@@ -1222,7 +1248,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
+ break;
+ }
+- switch (ch.code_rate_hp) {
++ switch (ch->code_rate_hp) {
+ case 1:
+ state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
+ break;
+@@ -1243,7 +1269,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
+ break;
+ }
+- switch (ch.code_rate_lp) {
++ switch (ch->code_rate_lp) {
+ case 1:
+ state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
+ break;
+@@ -1439,9 +1465,10 @@ static int dib9000_fw_tune(struct dvb_fr
+ break;
+ case CT_DEMOD_STEP_1:
+ if (search)
+- dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
++ dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
+ else
+- dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
++ dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
++ i = (s8)state->i2c_read_buffer[0];
+ switch (i) { /* something happened */
+ case 0:
+ break;
+@@ -2038,14 +2065,17 @@ static int dib9000_read_status(struct dv
+ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 c[16];
++ u16 *c;
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
++ state->i2c_read_buffer, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
++ c = (u16 *)state->i2c_read_buffer;
++
+ *ber = c[10] << 16 | c[11];
+ return 0;
+ }
+@@ -2054,7 +2084,7 @@ static int dib9000_read_signal_strength(
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+ u8 index_frontend;
+- u16 c[16];
++ u16 *c = (u16 *)state->i2c_read_buffer;
+ u16 val;
+
+ *strength = 0;
+@@ -2069,7 +2099,7 @@ static int dib9000_read_signal_strength(
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ val = 65535 - c[4];
+@@ -2083,14 +2113,14 @@ static int dib9000_read_signal_strength(
+ static u32 dib9000_get_snr(struct dvb_frontend *fe)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 c[16];
++ u16 *c = (u16 *)state->i2c_read_buffer;
+ u32 n, s, exp;
+ u16 val;
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ val = c[7];
+@@ -2137,12 +2167,12 @@ static int dib9000_read_snr(struct dvb_f
+ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 c[16];
++ u16 *c = (u16 *)state->i2c_read_buffer;
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ *unc = c[12];
+@@ -2151,10 +2181,22 @@ static int dib9000_read_unc_blocks(struc
+
+ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
+ {
+- int k = 0;
++ int k = 0, ret = 0;
+ u8 new_addr = 0;
+ struct i2c_device client = {.i2c_adap = i2c };
+
++ client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
++ if (!client.i2c_write_buffer) {
++ dprintk("%s: not enough memory", __func__);
++ return -ENOMEM;
++ }
++ client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
++ if (!client.i2c_read_buffer) {
++ dprintk("%s: not enough memory", __func__);
++ ret = -ENOMEM;
++ goto error_memory;
++ }
++
+ client.i2c_addr = default_addr + 16;
+ dib9000_i2c_write16(&client, 1796, 0x0);
+
+@@ -2178,7 +2220,8 @@ int dib9000_i2c_enumeration(struct i2c_a
+ client.i2c_addr = default_addr;
+ if (dib9000_identify(&client) == 0) {
+ dprintk("DiB9000 #%d: not identified", k);
+- return -EIO;
++ ret = -EIO;
++ goto error;
+ }
+ }
+
+@@ -2196,7 +2239,12 @@ int dib9000_i2c_enumeration(struct i2c_a
+ dib9000_i2c_write16(&client, 1795, 0);
+ }
+
+- return 0;
++error:
++ kfree(client.i2c_read_buffer);
++error_memory:
++ kfree(client.i2c_write_buffer);
++
++ return ret;
+ }
+ EXPORT_SYMBOL(dib9000_i2c_enumeration);
+
+@@ -2261,6 +2309,8 @@ struct dvb_frontend *dib9000_attach(stru
+ memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
+ st->i2c.i2c_adap = i2c_adap;
+ st->i2c.i2c_addr = i2c_addr;
++ st->i2c.i2c_write_buffer = st->i2c_write_buffer;
++ st->i2c.i2c_read_buffer = st->i2c_read_buffer;
+
+ st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
+ st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
+--- a/drivers/media/dvb/frontends/dibx000_common.c
++++ b/drivers/media/dvb/frontends/dibx000_common.c
+@@ -10,30 +10,39 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+
+ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+ {
+- u8 b[4] = {
+- (reg >> 8) & 0xff, reg & 0xff,
+- (val >> 8) & 0xff, val & 0xff,
+- };
+- struct i2c_msg msg = {
+- .addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
+- };
++ mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
++ mst->i2c_write_buffer[1] = reg & 0xff;
++ mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
++ mst->i2c_write_buffer[3] = val & 0xff;
++
++ memset(mst->msg, 0, sizeof(struct i2c_msg));
++ mst->msg[0].addr = mst->i2c_addr;
++ mst->msg[0].flags = 0;
++ mst->msg[0].buf = mst->i2c_write_buffer;
++ mst->msg[0].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++ return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+ {
+- u8 wb[2] = { reg >> 8, reg & 0xff };
+- u8 rb[2];
+- struct i2c_msg msg[2] = {
+- {.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2},
+- {.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2},
+- };
++ mst->i2c_write_buffer[0] = reg >> 8;
++ mst->i2c_write_buffer[1] = reg & 0xff;
+
+- if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
++ memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
++ mst->msg[0].addr = mst->i2c_addr;
++ mst->msg[0].flags = 0;
++ mst->msg[0].buf = mst->i2c_write_buffer;
++ mst->msg[0].len = 2;
++ mst->msg[1].addr = mst->i2c_addr;
++ mst->msg[1].flags = I2C_M_RD;
++ mst->msg[1].buf = mst->i2c_read_buffer;
++ mst->msg[1].len = 2;
++
++ if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (rb[0] << 8) | rb[1];
++ return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+ }
+
+ static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
+@@ -248,26 +257,32 @@ static int dibx000_i2c_gated_gpio67_xfer
+ struct i2c_msg msg[], int num)
+ {
+ struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+- struct i2c_msg m[2 + num];
+- u8 tx_open[4], tx_close[4];
+
+- memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
++ if (num > 32) {
++ dprintk("%s: too much I2C message to be transmitted (%i).\
++ Maximum is 32", __func__, num);
++ return -ENOMEM;
++ }
++
++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
+ dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
+
+- dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
+- m[0].addr = mst->i2c_addr;
+- m[0].buf = tx_open;
+- m[0].len = 4;
+-
+- memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+-
+- dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
+- m[num + 1].addr = mst->i2c_addr;
+- m[num + 1].buf = tx_close;
+- m[num + 1].len = 4;
++ /* open the gate */
++ dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
++ mst->msg[0].addr = mst->i2c_addr;
++ mst->msg[0].buf = &mst->i2c_write_buffer[0];
++ mst->msg[0].len = 4;
++
++ memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
++
++ /* close the gate */
++ dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
++ mst->msg[num + 1].addr = mst->i2c_addr;
++ mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
++ mst->msg[num + 1].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
++ return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+ }
+
+ static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
+@@ -279,26 +294,32 @@ static int dibx000_i2c_gated_tuner_xfer(
+ struct i2c_msg msg[], int num)
+ {
+ struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+- struct i2c_msg m[2 + num];
+- u8 tx_open[4], tx_close[4];
+
+- memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
++ if (num > 32) {
++ dprintk("%s: too much I2C message to be transmitted (%i).\
++ Maximum is 32", __func__, num);
++ return -ENOMEM;
++ }
++
++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
+ dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+
+- dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
+- m[0].addr = mst->i2c_addr;
+- m[0].buf = tx_open;
+- m[0].len = 4;
+-
+- memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+-
+- dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
+- m[num + 1].addr = mst->i2c_addr;
+- m[num + 1].buf = tx_close;
+- m[num + 1].len = 4;
++ /* open the gate */
++ dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
++ mst->msg[0].addr = mst->i2c_addr;
++ mst->msg[0].buf = &mst->i2c_write_buffer[0];
++ mst->msg[0].len = 4;
++
++ memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
++
++ /* close the gate */
++ dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
++ mst->msg[num + 1].addr = mst->i2c_addr;
++ mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
++ mst->msg[num + 1].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
++ return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+ }
+
+ static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+--- a/drivers/media/dvb/frontends/dibx000_common.h
++++ b/drivers/media/dvb/frontends/dibx000_common.h
+@@ -28,6 +28,11 @@ struct dibx000_i2c_master {
+ u8 i2c_addr;
+
+ u16 base_reg;
++
++ /* for the I2C transfer */
++ struct i2c_msg msg[34];
++ u8 i2c_write_buffer[8];
++ u8 i2c_read_buffer[2];
+ };
+
+ extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
diff --git a/queue-2.6.39/ecryptfs-allow-2-scatterlist-entries-for-encrypted.patch b/queue-2.6.39/ecryptfs-allow-2-scatterlist-entries-for-encrypted.patch
new file mode 100644
index 0000000000..7996ece1c1
--- /dev/null
+++ b/queue-2.6.39/ecryptfs-allow-2-scatterlist-entries-for-encrypted.patch
@@ -0,0 +1,143 @@
+From 8d08dab786ad5cc2aca2bf870de370144b78c85a Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Date: Tue, 17 May 2011 00:50:33 -0500
+Subject: eCryptfs: Allow 2 scatterlist entries for encrypted
+ filenames
+
+From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+
+commit 8d08dab786ad5cc2aca2bf870de370144b78c85a upstream.
+
+The buffers allocated while encrypting and decrypting long filenames can
+sometimes straddle two pages. In this situation, virt_to_scatterlist()
+will return -ENOMEM, causing the operation to fail and the user will get
+scary error messages in their logs:
+
+kernel: ecryptfs_write_tag_70_packet: Internal error whilst attempting
+to convert filename memory to scatterlist; expected rc = 1; got rc =
+[-12]. block_aligned_filename_size = [272]
+kernel: ecryptfs_encrypt_filename: Error attempting to generate tag 70
+packet; rc = [-12]
+kernel: ecryptfs_encrypt_and_encode_filename: Error attempting to
+encrypt filename; rc = [-12]
+kernel: ecryptfs_lookup: Error attempting to encrypt and encode
+filename; rc = [-12]
+
+The solution is to allow up to 2 scatterlist entries to be used.
+
+Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/keystore.c | 46 +++++++++++++++++++++-------------------------
+ 1 file changed, 21 insertions(+), 25 deletions(-)
+
+--- a/fs/ecryptfs/keystore.c
++++ b/fs/ecryptfs/keystore.c
+@@ -599,8 +599,8 @@ struct ecryptfs_write_tag_70_packet_sill
+ struct mutex *tfm_mutex;
+ char *block_aligned_filename;
+ struct ecryptfs_auth_tok *auth_tok;
+- struct scatterlist src_sg;
+- struct scatterlist dst_sg;
++ struct scatterlist src_sg[2];
++ struct scatterlist dst_sg[2];
+ struct blkcipher_desc desc;
+ char iv[ECRYPTFS_MAX_IV_BYTES];
+ char hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
+@@ -816,23 +816,21 @@ ecryptfs_write_tag_70_packet(char *dest,
+ memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,
+ filename_size);
+ rc = virt_to_scatterlist(s->block_aligned_filename,
+- s->block_aligned_filename_size, &s->src_sg, 1);
+- if (rc != 1) {
++ s->block_aligned_filename_size, s->src_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+- "convert filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
++ "convert filename memory to scatterlist; rc = [%d]. "
+ "block_aligned_filename_size = [%zd]\n", __func__, rc,
+ s->block_aligned_filename_size);
+ goto out_release_free_unlock;
+ }
+ rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size,
+- &s->dst_sg, 1);
+- if (rc != 1) {
++ s->dst_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert encrypted filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
+- "block_aligned_filename_size = [%zd]\n", __func__, rc,
+- s->block_aligned_filename_size);
++ "rc = [%d]. block_aligned_filename_size = [%zd]\n",
++ __func__, rc, s->block_aligned_filename_size);
+ goto out_release_free_unlock;
+ }
+ /* The characters in the first block effectively do the job
+@@ -855,7 +853,7 @@ ecryptfs_write_tag_70_packet(char *dest,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ goto out_release_free_unlock;
+ }
+- rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
++ rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg,
+ s->block_aligned_filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to encrypt filename; "
+@@ -891,8 +889,8 @@ struct ecryptfs_parse_tag_70_packet_sill
+ struct mutex *tfm_mutex;
+ char *decrypted_filename;
+ struct ecryptfs_auth_tok *auth_tok;
+- struct scatterlist src_sg;
+- struct scatterlist dst_sg;
++ struct scatterlist src_sg[2];
++ struct scatterlist dst_sg[2];
+ struct blkcipher_desc desc;
+ char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
+ char iv[ECRYPTFS_MAX_IV_BYTES];
+@@ -1008,13 +1006,12 @@ ecryptfs_parse_tag_70_packet(char **file
+ }
+ mutex_lock(s->tfm_mutex);
+ rc = virt_to_scatterlist(&data[(*packet_size)],
+- s->block_aligned_filename_size, &s->src_sg, 1);
+- if (rc != 1) {
++ s->block_aligned_filename_size, s->src_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert encrypted filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
+- "block_aligned_filename_size = [%zd]\n", __func__, rc,
+- s->block_aligned_filename_size);
++ "rc = [%d]. block_aligned_filename_size = [%zd]\n",
++ __func__, rc, s->block_aligned_filename_size);
+ goto out_unlock;
+ }
+ (*packet_size) += s->block_aligned_filename_size;
+@@ -1028,13 +1025,12 @@ ecryptfs_parse_tag_70_packet(char **file
+ goto out_unlock;
+ }
+ rc = virt_to_scatterlist(s->decrypted_filename,
+- s->block_aligned_filename_size, &s->dst_sg, 1);
+- if (rc != 1) {
++ s->block_aligned_filename_size, s->dst_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert decrypted filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
+- "block_aligned_filename_size = [%zd]\n", __func__, rc,
+- s->block_aligned_filename_size);
++ "rc = [%d]. block_aligned_filename_size = [%zd]\n",
++ __func__, rc, s->block_aligned_filename_size);
+ goto out_free_unlock;
+ }
+ /* The characters in the first block effectively do the job of
+@@ -1065,7 +1061,7 @@ ecryptfs_parse_tag_70_packet(char **file
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ goto out_free_unlock;
+ }
+- rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
++ rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg,
+ s->block_aligned_filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to decrypt filename; "
diff --git a/queue-2.6.39/ecryptfs-clear-i_nlink-in-rmdir.patch b/queue-2.6.39/ecryptfs-clear-i_nlink-in-rmdir.patch
new file mode 100644
index 0000000000..491b7c2813
--- /dev/null
+++ b/queue-2.6.39/ecryptfs-clear-i_nlink-in-rmdir.patch
@@ -0,0 +1,33 @@
+From 07850552b92b3637fa56767b5e460b4238014447 Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Date: Fri, 29 Apr 2011 16:26:27 -0500
+Subject: eCryptfs: Clear i_nlink in rmdir
+
+From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+
+commit 07850552b92b3637fa56767b5e460b4238014447 upstream.
+
+eCryptfs wasn't clearing the eCryptfs inode's i_nlink after a successful
+vfs_rmdir() on the lower directory. This resulted in the inode evict and
+destroy paths to be missed.
+
+https://bugs.launchpad.net/ecryptfs/+bug/723518
+
+Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/inode.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -527,6 +527,8 @@ static int ecryptfs_rmdir(struct inode *
+ dget(lower_dentry);
+ rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+ dput(lower_dentry);
++ if (!rc && dentry->d_inode)
++ clear_nlink(dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ unlock_dir(lower_dir_dentry);
diff --git a/queue-2.6.39/mfd-fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch b/queue-2.6.39/mfd-fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch
new file mode 100644
index 0000000000..2f16127d6d
--- /dev/null
+++ b/queue-2.6.39/mfd-fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch
@@ -0,0 +1,67 @@
+From 6eb6fbbf3eca6dfba73e72de5ab2eeb52ae41f7a Mon Sep 17 00:00:00 2001
+From: Keshava Munegowda <Keshava_mgowda@ti.com>
+Date: Mon, 16 May 2011 14:24:58 +0530
+Subject: mfd: Fix omap usbhs crash when rmmoding ehci or ohci
+
+From: Keshava Munegowda <Keshava_mgowda@ti.com>
+
+commit 6eb6fbbf3eca6dfba73e72de5ab2eeb52ae41f7a upstream.
+
+The disabling of clocks and freeing GPIO are changed
+to fix the occurrence of the crash of rmmod of ehci and ohci
+drivers. The GPIOs should be freed after the spin locks are
+unlocked.
+
+Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
+Acked-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mfd/omap-usb-host.c | 27 +++++++++++++++++++--------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+--- a/drivers/mfd/omap-usb-host.c
++++ b/drivers/mfd/omap-usb-host.c
+@@ -994,22 +994,33 @@ static void usbhs_disable(struct device
+ dev_dbg(dev, "operation timed out\n");
+ }
+
+- if (pdata->ehci_data->phy_reset) {
+- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+- gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+-
+- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
++ if (is_omap_usbhs_rev2(omap)) {
++ if (is_ehci_tll_mode(pdata->port_mode[0]))
++ clk_enable(omap->usbtll_p1_fck);
++ if (is_ehci_tll_mode(pdata->port_mode[1]))
++ clk_enable(omap->usbtll_p2_fck);
++ clk_disable(omap->utmi_p2_fck);
++ clk_disable(omap->utmi_p1_fck);
+ }
+
+- clk_disable(omap->utmi_p2_fck);
+- clk_disable(omap->utmi_p1_fck);
+ clk_disable(omap->usbtll_ick);
+ clk_disable(omap->usbtll_fck);
+ clk_disable(omap->usbhost_fs_fck);
+ clk_disable(omap->usbhost_hs_fck);
+ clk_disable(omap->usbhost_ick);
+
++ /* The gpio_free migh sleep; so unlock the spinlock */
++ spin_unlock_irqrestore(&omap->lock, flags);
++
++ if (pdata->ehci_data->phy_reset) {
++ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
++ gpio_free(pdata->ehci_data->reset_gpio_port[0]);
++
++ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
++ gpio_free(pdata->ehci_data->reset_gpio_port[1]);
++ }
++ return;
++
+ end_disble:
+ spin_unlock_irqrestore(&omap->lock, flags);
+ }
diff --git a/queue-2.6.39/ohci-fix-regression-caused-by-nvidia-shutdown-workaround.patch b/queue-2.6.39/ohci-fix-regression-caused-by-nvidia-shutdown-workaround.patch
new file mode 100644
index 0000000000..a037f48311
--- /dev/null
+++ b/queue-2.6.39/ohci-fix-regression-caused-by-nvidia-shutdown-workaround.patch
@@ -0,0 +1,68 @@
+From 2b7aaf503d56216b847c8265421d2a7d9b42df3e Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 16 May 2011 12:15:19 -0400
+Subject: OHCI: fix regression caused by nVidia shutdown workaround
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 2b7aaf503d56216b847c8265421d2a7d9b42df3e upstream.
+
+This patch (as1463) fixes a regression caused by commit
+3df7169e73fc1d71a39cffeacc969f6840cdf52b (OHCI: work around for nVidia
+shutdown problem).
+
+The original problem encountered by people using NVIDIA chipsets was
+that USB devices were not turning off when the system shut down. For
+example, the LED on an optical mouse would remain on, draining a
+laptop's battery. The problem was caused by a bug in the chipset; an
+OHCI controller in the Reset state would continue to drive a bus reset
+signal even after system shutdown. The workaround was to put the
+controllers into the Suspend state instead.
+
+It turns out that later NVIDIA chipsets do not suffer from this bug.
+Instead some have the opposite bug: If a system is shut down while an
+OHCI controller is in the Suspend state, USB devices remain powered!
+On other systems, shutting down with a Suspended controller causes the
+system to reboot immediately. Thus, working around the original bug
+on some machines exposes other bugs on other machines.
+
+The best solution seems to be to limit the workaround to OHCI
+controllers with a low-numbered PCI product ID. I don't know exactly
+at what point NVIDIA changed their chipsets; the value used here is a
+guess. So far it was worked out okay for all the people who have
+tested it.
+
+This fixes Bugzilla #35032.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Andre "Osku" Schmidt <andre.osku.schmidt@googlemail.com>
+Tested-by: Yury Siamashka <yurand2@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ohci-pci.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -181,10 +181,18 @@ static int ohci_quirk_amd700(struct usb_
+ */
+ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+ {
++ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+- ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+- ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++ /* Evidently nVidia fixed their later hardware; this is a guess at
++ * the changeover point.
++ */
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB 0x026d
++
++ if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
++ ohci->flags |= OHCI_QUIRK_SHUTDOWN;
++ ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++ }
+
+ return 0;
+ }
diff --git a/queue-2.6.39/p54usb-add-zoom-4410-usbid.patch b/queue-2.6.39/p54usb-add-zoom-4410-usbid.patch
new file mode 100644
index 0000000000..979aaea9c1
--- /dev/null
+++ b/queue-2.6.39/p54usb-add-zoom-4410-usbid.patch
@@ -0,0 +1,28 @@
+From 9368a9a2378ab721f82f59430a135b4ce4ff5109 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 13 May 2011 21:47:23 +0200
+Subject: p54usb: add zoom 4410 usbid
+
+From: Christian Lamparter <chunkeey@googlemail.com>
+
+commit 9368a9a2378ab721f82f59430a135b4ce4ff5109 upstream.
+
+Reported-by: Mark Davis <marked86@gmail.com>
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/p54/p54usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/p54/p54usb.c
++++ b/drivers/net/wireless/p54/p54usb.c
+@@ -82,6 +82,7 @@ static struct usb_device_id p54u_table[]
+ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
+ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
+ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
++ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */
+ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
+ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
+ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
diff --git a/queue-2.6.39/series b/queue-2.6.39/series
index 68a5444f5a..f222988a83 100644
--- a/queue-2.6.39/series
+++ b/queue-2.6.39/series
@@ -104,3 +104,29 @@ loop-limit-max_part-module-param-to-disk_max_parts.patch
loop-handle-on-demand-devices-correctly.patch
i2c-tegra-enable-new-slave-mode.patch
i2c-writing-clients-fix-foo_driver.id_table.patch
+usb-cp210x-add-4-device-ids-for-ac-services-devices.patch
+usb-moto_modem-add-usb-identifier-for-the-motorola-ve240.patch
+usb-serial-ftdi_sio-adding-support-for-tavir-stk500.patch
+usb-gadget-g_multi-fixed-vendor-and-product-id-in-inf.patch
+usb-gamin_gps-fix-for-data-transfer-problems-in-native.patch
+bind-only-modem-at-command-endpoint-to-option-module.patch
+usb-cdc_acm-fix-oops-when-droids-muin-lcd-is-connected.patch
+xhci-fix-bug-in-control-transfer-cancellation.patch
+usb-gadget-at91sam9g20-fix-end-point-max-packet-size.patch
+usb-gadget-rndis-don-t-test-against-req-length.patch
+xhci-fix-full-speed-binterval-encoding.patch
+xhci-fix-memory-leak-in-ring-cache-deallocation.patch
+xhci-fix-memory-leak-bug-when-dropping-endpoints.patch
+usb-option-add-support-for-huawei-e353-device.patch
+ohci-fix-regression-caused-by-nvidia-shutdown-workaround.patch
+usb-remove-remaining-usages-of-hcd-state-from-usbcore-and.patch
+dibxxxx-get-rid-of-dma-buffer-on-stack.patch
+cx88-protect-per-device-driver-list-with-device.patch
+cx88-fix-locking-of-sub-driver-operations.patch
+cx88-hold-device-lock-during-sub-driver.patch
+sh-clkfwk-fixup-clk_rate_table_build-parameter-in-div6.patch
+sh-fixup-fpu.o-compile-order.patch
+mfd-fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch
+p54usb-add-zoom-4410-usbid.patch
+ecryptfs-clear-i_nlink-in-rmdir.patch
+ecryptfs-allow-2-scatterlist-entries-for-encrypted.patch
diff --git a/queue-2.6.39/sh-clkfwk-fixup-clk_rate_table_build-parameter-in-div6.patch b/queue-2.6.39/sh-clkfwk-fixup-clk_rate_table_build-parameter-in-div6.patch
new file mode 100644
index 0000000000..4a78dfa440
--- /dev/null
+++ b/queue-2.6.39/sh-clkfwk-fixup-clk_rate_table_build-parameter-in-div6.patch
@@ -0,0 +1,33 @@
+From 52c10ad22b7e317960b4d411c9a9ddeaf3d5ae39 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 14 Apr 2011 17:13:53 +0900
+Subject: sh: clkfwk: fixup clk_rate_table_build parameter in div6
+ clock
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+commit 52c10ad22b7e317960b4d411c9a9ddeaf3d5ae39 upstream.
+
+div6 clock should not use arch_flags for clk_rate_table_build,
+because SH_CLK_DIV6_EXT doesn't care .arch_flags.
+clk->freq_table[] will be all CPUFREQ_ENTRY_INVALID without this patch.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/sh/clk/cpg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -105,7 +105,7 @@ static int sh_clk_div6_set_parent(struct
+
+ /* Rebuild the frequency table */
+ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+- table, &clk->arch_flags);
++ table, NULL);
+
+ return 0;
+ }
diff --git a/queue-2.6.39/sh-fixup-fpu.o-compile-order.patch b/queue-2.6.39/sh-fixup-fpu.o-compile-order.patch
new file mode 100644
index 0000000000..26f5fb484c
--- /dev/null
+++ b/queue-2.6.39/sh-fixup-fpu.o-compile-order.patch
@@ -0,0 +1,38 @@
+From a375b15164dd9264f724ad941825e52c90145151 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 15 Apr 2011 16:44:27 +0900
+Subject: sh: fixup fpu.o compile order
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+commit a375b15164dd9264f724ad941825e52c90145151 upstream.
+
+arch_ptrace() was modified to reference init_fpu() to fix up xstate
+initialization, which overlooked the fact that there are configurations
+that don't enable any of hard FPU support or emulation, resulting in
+build errors on DSP parts.
+
+Given that init_fpu() simply sets up the xstate slab cache and is
+side-stepped entirely for the DSP case, we can simply always build in the
+helper and fix up the references.
+
+Reported-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sh/kernel/cpu/Makefile | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/arch/sh/kernel/cpu/Makefile
++++ b/arch/sh/kernel/cpu/Makefile
+@@ -17,7 +17,5 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/
+
+ obj-$(CONFIG_SH_ADC) += adc.o
+ obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o
+-obj-$(CONFIG_SH_FPU) += fpu.o
+-obj-$(CONFIG_SH_FPU_EMU) += fpu.o
+
+-obj-y += irq/ init.o clock.o hwblk.o proc.o
++obj-y += irq/ init.o clock.o fpu.o hwblk.o proc.o
diff --git a/queue-2.6.39/usb-cdc_acm-fix-oops-when-droids-muin-lcd-is-connected.patch b/queue-2.6.39/usb-cdc_acm-fix-oops-when-droids-muin-lcd-is-connected.patch
new file mode 100644
index 0000000000..b169b3b372
--- /dev/null
+++ b/queue-2.6.39/usb-cdc_acm-fix-oops-when-droids-muin-lcd-is-connected.patch
@@ -0,0 +1,70 @@
+From fd5054c169d29747a44b4e1419ff47f57ae82dbc Mon Sep 17 00:00:00 2001
+From: Erik Slagter <erik@slagter.name>
+Date: Wed, 11 May 2011 12:06:55 +0200
+Subject: USB: cdc_acm: Fix oops when Droids MuIn LCD is connected
+
+From: Erik Slagter <erik@slagter.name>
+
+commit fd5054c169d29747a44b4e1419ff47f57ae82dbc upstream.
+
+The Droids MuIn LCD operates like a serial remote terminal.
+Data received are displayed directly on the LCD. This patch
+fixes the kernel null pointer oops when it is plugged in.
+
+Add NO_DATA_INTERFACE quirk to tell the driver that "control"
+and "data" interfaces are not separated for this device, which
+prevents dereferencing a null pointer in the device probe code.
+
+Signed-off-by: Erik Slagter <erik@slagter.name>
+Signed-off-by: Maxin B. John <maxin.john@gmail.com>
+Tested-by: Erik Slagter <erik@slagter.name>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 13 +++++++++++--
+ drivers/usb/class/cdc-acm.h | 1 +
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -946,7 +946,7 @@ static int acm_probe(struct usb_interfac
+ u8 ac_management_function = 0;
+ u8 call_management_function = 0;
+ int call_interface_num = -1;
+- int data_interface_num;
++ int data_interface_num = -1;
+ unsigned long quirks;
+ int num_rx_buf;
+ int i;
+@@ -1030,7 +1030,11 @@ next_desc:
+ if (!union_header) {
+ if (call_interface_num > 0) {
+ dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n");
+- data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
++ /* quirks for Droids MuIn LCD */
++ if (quirks & NO_DATA_INTERFACE)
++ data_interface = usb_ifnum_to_if(usb_dev, 0);
++ else
++ data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
+ control_interface = intf;
+ } else {
+ if (intf->cur_altsetting->desc.bNumEndpoints != 3) {
+@@ -1622,6 +1626,11 @@ static const struct usb_device_id acm_id
+ .driver_info = NOT_A_MODEM,
+ },
+
++ /* Support for Droids MuIn LCD */
++ { USB_DEVICE(0x04d8, 0x000b),
++ .driver_info = NO_DATA_INTERFACE,
++ },
++
+ /* control interfaces without any protocol set */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTO_NONE) },
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -137,3 +137,4 @@ struct acm {
+ #define SINGLE_RX_URB 2
+ #define NO_CAP_LINE 4
+ #define NOT_A_MODEM 8
++#define NO_DATA_INTERFACE 16
diff --git a/queue-2.6.39/usb-cp210x-add-4-device-ids-for-ac-services-devices.patch b/queue-2.6.39/usb-cp210x-add-4-device-ids-for-ac-services-devices.patch
new file mode 100644
index 0000000000..6c2b131b8d
--- /dev/null
+++ b/queue-2.6.39/usb-cp210x-add-4-device-ids-for-ac-services-devices.patch
@@ -0,0 +1,32 @@
+From 4eff0b40a7174896b860312910e0db51f2dcc567 Mon Sep 17 00:00:00 2001
+From: Craig Shelley <craig@microtron.org.uk>
+Date: Sun, 20 Mar 2011 13:51:13 +0000
+Subject: USB: CP210x Add 4 Device IDs for AC-Services Devices
+
+From: Craig Shelley <craig@microtron.org.uk>
+
+commit 4eff0b40a7174896b860312910e0db51f2dcc567 upstream.
+
+This patch adds 4 device IDs for CP2102 based devices manufactured by
+AC-Services. See http://www.ac-services.eu for further info.
+
+Signed-off-by: Craig Shelley <craig@microtron.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/cp210x.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -112,6 +112,10 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
+ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
+ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
++ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
++ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
++ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
++ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
diff --git a/queue-2.6.39/usb-gadget-at91sam9g20-fix-end-point-max-packet-size.patch b/queue-2.6.39/usb-gadget-at91sam9g20-fix-end-point-max-packet-size.patch
new file mode 100644
index 0000000000..e446d0558a
--- /dev/null
+++ b/queue-2.6.39/usb-gadget-at91sam9g20-fix-end-point-max-packet-size.patch
@@ -0,0 +1,30 @@
+From bf1f0a05d472e33dda8e5e69525be1584cdbd03a Mon Sep 17 00:00:00 2001
+From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Fri, 13 May 2011 17:03:02 +0200
+Subject: usb/gadget: at91sam9g20 fix end point max packet size
+
+From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit bf1f0a05d472e33dda8e5e69525be1584cdbd03a upstream.
+
+on 9g20 they are the same as the 9260
+
+Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/at91_udc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/at91_udc.c
++++ b/drivers/usb/gadget/at91_udc.c
+@@ -1767,7 +1767,7 @@ static int __init at91udc_probe(struct p
+ }
+
+ /* newer chips have more FIFO memory than rm9200 */
+- if (cpu_is_at91sam9260()) {
++ if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
+ udc->ep[0].maxpacket = 64;
+ udc->ep[3].maxpacket = 64;
+ udc->ep[4].maxpacket = 512;
diff --git a/queue-2.6.39/usb-gadget-g_multi-fixed-vendor-and-product-id-in-inf.patch b/queue-2.6.39/usb-gadget-g_multi-fixed-vendor-and-product-id-in-inf.patch
new file mode 100644
index 0000000000..22802b2735
--- /dev/null
+++ b/queue-2.6.39/usb-gadget-g_multi-fixed-vendor-and-product-id-in-inf.patch
@@ -0,0 +1,60 @@
+From 7701846fd52f86dffe50715e0e63154088b7c982 Mon Sep 17 00:00:00 2001
+From: Michal Nazarewicz <mina86@mina86.com>
+Date: Tue, 26 Apr 2011 19:08:36 +0200
+Subject: USB: gadget: g_multi: fixed vendor and product ID in inf
+ files
+
+From: Michal Nazarewicz <mina86@mina86.com>
+
+commit 7701846fd52f86dffe50715e0e63154088b7c982 upstream.
+
+Commit 1c6529e92b "USB: gadget: g_multi: fixed vendor and
+product ID" replaced g_multi's vendor and product ID with
+proper ID's from Linux Foundation. This commit now updates
+INF files in the Documentation/usb directory which were
+omitted in the original commit.
+
+Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/linux-cdc-acm.inf | 4 ++--
+ Documentation/usb/linux.inf | 6 +++---
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/Documentation/usb/linux-cdc-acm.inf
++++ b/Documentation/usb/linux-cdc-acm.inf
+@@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys
+ [SourceDisksFiles]
+ [SourceDisksNames]
+ [DeviceList]
+-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
++%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+
+ [DeviceList.NTamd64]
+-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
++%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+
+
+ ;------------------------------------------------------------------------------
+--- a/Documentation/usb/linux.inf
++++ b/Documentation/usb/linux.inf
+@@ -18,15 +18,15 @@ DriverVer = 06/21/2006,6.0.600
+
+ ; Decoration for x86 architecture
+ [LinuxDevices.NTx86]
+-%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
++%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
+
+ ; Decoration for x64 architecture
+ [LinuxDevices.NTamd64]
+-%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
++%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
+
+ ; Decoration for ia64 architecture
+ [LinuxDevices.NTia64]
+-%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
++%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
+
+ ;@@@ This is the common setting for setup
+ [ControlFlags]
diff --git a/queue-2.6.39/usb-gadget-rndis-don-t-test-against-req-length.patch b/queue-2.6.39/usb-gadget-rndis-don-t-test-against-req-length.patch
new file mode 100644
index 0000000000..f878fa39c1
--- /dev/null
+++ b/queue-2.6.39/usb-gadget-rndis-don-t-test-against-req-length.patch
@@ -0,0 +1,38 @@
+From 472b91274a6c6857877b5caddb875dcb5ecdfcb8 Mon Sep 17 00:00:00 2001
+From: Felipe Balbi <balbi@ti.com>
+Date: Fri, 13 May 2011 16:53:48 +0300
+Subject: usb: gadget: rndis: don't test against req->length
+
+From: Felipe Balbi <balbi@ti.com>
+
+commit 472b91274a6c6857877b5caddb875dcb5ecdfcb8 upstream.
+
+composite.c always sets req->length to zero
+and expects function driver's setup handlers
+to return the amount of bytes to be used
+on req->length. If we test against req->length
+w_length will always be greater than req->length
+thus making us always stall that particular
+SEND_ENCAPSULATED_COMMAND request.
+
+Tested against a Windows XP SP3.
+
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/f_rndis.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/f_rndis.c
++++ b/drivers/usb/gadget/f_rndis.c
+@@ -420,8 +420,7 @@ rndis_setup(struct usb_function *f, cons
+ */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SEND_ENCAPSULATED_COMMAND:
+- if (w_length > req->length || w_value
+- || w_index != rndis->ctrl_id)
++ if (w_value || w_index != rndis->ctrl_id)
+ goto invalid;
+ /* read the request; process it later */
+ value = w_length;
diff --git a/queue-2.6.39/usb-gamin_gps-fix-for-data-transfer-problems-in-native.patch b/queue-2.6.39/usb-gamin_gps-fix-for-data-transfer-problems-in-native.patch
new file mode 100644
index 0000000000..28031fbc4e
--- /dev/null
+++ b/queue-2.6.39/usb-gamin_gps-fix-for-data-transfer-problems-in-native.patch
@@ -0,0 +1,115 @@
+From b4026c4584cd70858d4d3450abfb1cd0714d4f32 Mon Sep 17 00:00:00 2001
+From: Hermann Kneissel <herkne@gmx.de>
+Date: Fri, 29 Apr 2011 08:58:43 +0200
+Subject: USB: gamin_gps: Fix for data transfer problems in native
+ mode
+
+From: Hermann Kneissel <herkne@gmx.de>
+
+commit b4026c4584cd70858d4d3450abfb1cd0714d4f32 upstream.
+
+This patch fixes a problem where data received from the gps is sometimes
+transferred incompletely to the serial port. If used in native mode now
+all data received via the bulk queue will be forwarded to the serial
+port.
+
+Signed-off-by: Hermann Kneissel <herkne@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/garmin_gps.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -1,7 +1,7 @@
+ /*
+ * Garmin GPS driver
+ *
+- * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net
++ * Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de
+ *
+ * The latest version of the driver can be found at
+ * http://sourceforge.net/projects/garmin-gps/
+@@ -51,7 +51,7 @@ static int debug;
+ */
+
+ #define VERSION_MAJOR 0
+-#define VERSION_MINOR 33
++#define VERSION_MINOR 36
+
+ #define _STR(s) #s
+ #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
+@@ -410,6 +410,7 @@ static int gsp_send_ack(struct garmin_da
+ */
+ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
+ {
++ unsigned long flags;
+ const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
+ __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
+
+@@ -458,7 +459,9 @@ static int gsp_rec_packet(struct garmin_
+ /* if this was an abort-transfer command, flush all
+ queued data. */
+ if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
++ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags |= FLAGS_DROP_DATA;
++ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ pkt_clear(garmin_data_p);
+ }
+
+@@ -943,7 +946,7 @@ static int garmin_open(struct tty_struct
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->mode = initial_mode;
+ garmin_data_p->count = 0;
+- garmin_data_p->flags = 0;
++ garmin_data_p->flags &= FLAGS_SESSION_REPLY1_SEEN;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+ /* shutdown any bulk reads that might be going on */
+@@ -1178,7 +1181,8 @@ static int garmin_write_room(struct tty_
+
+
+ static void garmin_read_process(struct garmin_data *garmin_data_p,
+- unsigned char *data, unsigned data_length)
++ unsigned char *data, unsigned data_length,
++ int bulk_data)
+ {
+ unsigned long flags;
+
+@@ -1193,7 +1197,8 @@ static void garmin_read_process(struct g
+ send it directly to the tty port */
+ if (garmin_data_p->flags & FLAGS_QUEUING) {
+ pkt_add(garmin_data_p, data, data_length);
+- } else if (getLayerId(data) == GARMIN_LAYERID_APPL) {
++ } else if (bulk_data ||
++ getLayerId(data) == GARMIN_LAYERID_APPL) {
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags |= APP_RESP_SEEN;
+@@ -1237,7 +1242,7 @@ static void garmin_read_bulk_callback(st
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, urb->actual_length, data);
+
+- garmin_read_process(garmin_data_p, data, urb->actual_length);
++ garmin_read_process(garmin_data_p, data, urb->actual_length, 1);
+
+ if (urb->actual_length == 0 &&
+ 0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
+@@ -1346,7 +1351,7 @@ static void garmin_read_int_callback(str
+ __func__, garmin_data_p->serial_num);
+ }
+
+- garmin_read_process(garmin_data_p, data, urb->actual_length);
++ garmin_read_process(garmin_data_p, data, urb->actual_length, 0);
+
+ port->interrupt_in_urb->dev = port->serial->dev;
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+@@ -1461,6 +1466,7 @@ static int garmin_attach(struct usb_seri
+ garmin_data_p->timer.function = timeout_handler;
+ garmin_data_p->port = port;
+ garmin_data_p->state = 0;
++ garmin_data_p->flags = 0;
+ garmin_data_p->count = 0;
+ usb_set_serial_port_data(port, garmin_data_p);
+
diff --git a/queue-2.6.39/usb-moto_modem-add-usb-identifier-for-the-motorola-ve240.patch b/queue-2.6.39/usb-moto_modem-add-usb-identifier-for-the-motorola-ve240.patch
new file mode 100644
index 0000000000..89380eec65
--- /dev/null
+++ b/queue-2.6.39/usb-moto_modem-add-usb-identifier-for-the-motorola-ve240.patch
@@ -0,0 +1,29 @@
+From 3938a0b32dc12229e76735679b37095bc2bc1578 Mon Sep 17 00:00:00 2001
+From: Elizabeth Jennifer Myers <elizabeth@sporksirc.net>
+Date: Sat, 16 Apr 2011 14:49:51 -0400
+Subject: USB: moto_modem: Add USB identifier for the Motorola VE240.
+
+From: Elizabeth Jennifer Myers <elizabeth@sporksirc.net>
+
+commit 3938a0b32dc12229e76735679b37095bc2bc1578 upstream.
+
+Tested on my phone, the ttyUSB device is created and is fully
+functional.
+
+Signed-off-by: Elizabeth Jennifer Myers <elizabeth@sporksirc.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/moto_modem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/moto_modem.c
++++ b/drivers/usb/serial/moto_modem.c
+@@ -25,6 +25,7 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */
+ { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */
+ { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */
++ { USB_DEVICE(0x22b8, 0x2c84) }, /* Motorola VE240 phone */
+ { USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */
+ { },
+ };
diff --git a/queue-2.6.39/usb-option-add-support-for-huawei-e353-device.patch b/queue-2.6.39/usb-option-add-support-for-huawei-e353-device.patch
new file mode 100644
index 0000000000..17a3cd877a
--- /dev/null
+++ b/queue-2.6.39/usb-option-add-support-for-huawei-e353-device.patch
@@ -0,0 +1,46 @@
+From 610ba42f29c3dfa46a05ff8c2cadc29f544ff76d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marcin=20Ga=C5=82czy=C5=84ski?= <marcin@galczynski.pl>
+Date: Sun, 15 May 2011 11:41:54 +0200
+Subject: USB: option: add support for Huawei E353 device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Marcin=20Ga=C5=82czy=C5=84ski?= <marcin@galczynski.pl>
+
+commit 610ba42f29c3dfa46a05ff8c2cadc29f544ff76d upstream.
+
+I am sharing patch to the devices/usb/serial/option.c. This allows
+operation of Huawei E353 broadband modem using the “option” driver. The
+patch simply adds new constant with proper product ID and an entry to
+usb_device_id. I worked on the 2.6.38.6 sources. Tested on Dell inspiron
+1764 (i3 core cpu) and brand new Huawei E353 modem, Fedora 15 beta.
+
+Looking at the type of change, i doubt it has potential to introduce
+problems in other parts of kernel or the driver itself.
+
+Signed-off-by: Marcin Galczynski <marcin@galczynski.pl>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -149,6 +149,7 @@ static void option_instat_callback(struc
+ #define HUAWEI_PRODUCT_K3765 0x1465
+ #define HUAWEI_PRODUCT_E14AC 0x14AC
+ #define HUAWEI_PRODUCT_ETS1220 0x1803
++#define HUAWEI_PRODUCT_E353 0x1506
+
+ #define QUANTA_VENDOR_ID 0x0408
+ #define QUANTA_PRODUCT_Q101 0xEA02
+@@ -532,6 +533,7 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
diff --git a/queue-2.6.39/usb-remove-remaining-usages-of-hcd-state-from-usbcore-and.patch b/queue-2.6.39/usb-remove-remaining-usages-of-hcd-state-from-usbcore-and.patch
new file mode 100644
index 0000000000..ac1bd1469d
--- /dev/null
+++ b/queue-2.6.39/usb-remove-remaining-usages-of-hcd-state-from-usbcore-and.patch
@@ -0,0 +1,192 @@
+From 69fff59de4d844f8b4c2454c3c23d32b69dcbfd7 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 17 May 2011 17:27:12 -0400
+Subject: USB: remove remaining usages of hcd->state from usbcore and
+ fix regression
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 69fff59de4d844f8b4c2454c3c23d32b69dcbfd7 upstream.
+
+This patch (as1467) removes the last usages of hcd->state from
+usbcore. We no longer check to see if an interrupt handler finds that
+a controller has died; instead we rely on host controller drivers to
+make an explicit call to usb_hc_died().
+
+This fixes a regression introduced by commit
+9b37596a2e860404503a3f2a6513db60c296bfdc (USB: move usbcore away from
+hcd->state). It used to be that when a controller shared an IRQ with
+another device and an interrupt arrived while hcd->state was set to
+HC_STATE_HALT, the interrupt handler would be skipped. The commit
+removed that test; as a result the current code doesn't skip calling
+the handler and ends up believing the controller has died, even though
+it's only temporarily stopped. The solution is to ignore HC_STATE_HALT
+following the handler's return.
+
+As a consequence of this change, several of the host controller
+drivers need to be modified. They can no longer implicitly rely on
+usbcore realizing that a controller has died because of hcd->state.
+The patch adds calls to usb_hc_died() in the appropriate places.
+
+The patch also changes a few of the interrupt handlers. They don't
+expect to be called when hcd->state is equal to HC_STATE_HALT, even if
+the controller is still alive. Early returns were added to avoid any
+confusion.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Manuel Lauss <manuel.lauss@googlemail.com>
+CC: Rodolfo Giometti <giometti@linux.it>
+CC: Olav Kongas <ok@artecdesign.ee>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd.c | 5 +----
+ drivers/usb/host/ehci-hcd.c | 4 +++-
+ drivers/usb/host/ehci-sched.c | 8 ++++++--
+ drivers/usb/host/isp116x-hcd.c | 1 +
+ drivers/usb/host/ohci-hcd.c | 4 +++-
+ drivers/usb/host/oxu210hp-hcd.c | 6 +++++-
+ 6 files changed, 19 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -986,7 +986,7 @@ static int register_root_hub(struct usb_
+ spin_unlock_irq (&hcd_root_hub_lock);
+
+ /* Did the HC die before the root hub was registered? */
+- if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
++ if (HCD_DEAD(hcd))
+ usb_hc_died (hcd); /* This time clean up */
+ }
+
+@@ -2128,9 +2128,6 @@ irqreturn_t usb_hcd_irq (int irq, void *
+ set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ if (hcd->shared_hcd)
+ set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
+-
+- if (unlikely(hcd->state == HC_STATE_HALT))
+- usb_hc_died(hcd);
+ rc = IRQ_HANDLED;
+ }
+
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -777,8 +777,9 @@ static irqreturn_t ehci_irq (struct usb_
+ goto dead;
+ }
+
++ /* Shared IRQ? */
+ masked_status = status & INTR_MASK;
+- if (!masked_status) { /* irq sharing? */
++ if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
+ spin_unlock(&ehci->lock);
+ return IRQ_NONE;
+ }
+@@ -873,6 +874,7 @@ static irqreturn_t ehci_irq (struct usb_
+ dead:
+ ehci_reset(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++ usb_hc_died(hcd);
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -471,8 +471,10 @@ static int enable_periodic (struct ehci_
+ */
+ status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ STS_PSS, 0, 9 * 125);
+- if (status)
++ if (status) {
++ usb_hc_died(ehci_to_hcd(ehci));
+ return status;
++ }
+
+ cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -510,8 +512,10 @@ static int disable_periodic (struct ehci
+ */
+ status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ STS_PSS, STS_PSS, 9 * 125);
+- if (status)
++ if (status) {
++ usb_hc_died(ehci_to_hcd(ehci));
+ return status;
++ }
+
+ cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -612,6 +612,7 @@ static irqreturn_t isp116x_irq(struct us
+ /* IRQ's are off, we do no DMA,
+ perfectly ready to die ... */
+ hcd->state = HC_STATE_HALT;
++ usb_hc_died(hcd);
+ ret = IRQ_HANDLED;
+ goto done;
+ }
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -764,6 +764,7 @@ static irqreturn_t ohci_irq (struct usb_
+ if (ints == ~(u32)0) {
+ disable (ohci);
+ ohci_dbg (ohci, "device removed!\n");
++ usb_hc_died(hcd);
+ return IRQ_HANDLED;
+ }
+
+@@ -771,7 +772,7 @@ static irqreturn_t ohci_irq (struct usb_
+ ints &= ohci_readl(ohci, &regs->intrenable);
+
+ /* interrupt for some other device? */
+- if (ints == 0)
++ if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT))
+ return IRQ_NOTMINE;
+
+ if (ints & OHCI_INTR_UE) {
+@@ -788,6 +789,7 @@ static irqreturn_t ohci_irq (struct usb_
+ } else {
+ disable (ohci);
+ ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
++ usb_hc_died(hcd);
+ }
+
+ ohci_dump (ohci, 1);
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -1884,6 +1884,7 @@ static int enable_periodic(struct oxu_hc
+ status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125);
+ if (status != 0) {
+ oxu_to_hcd(oxu)->state = HC_STATE_HALT;
++ usb_hc_died(oxu_to_hcd(oxu));
+ return status;
+ }
+
+@@ -1909,6 +1910,7 @@ static int disable_periodic(struct oxu_h
+ status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125);
+ if (status != 0) {
+ oxu_to_hcd(oxu)->state = HC_STATE_HALT;
++ usb_hc_died(oxu_to_hcd(oxu));
+ return status;
+ }
+
+@@ -2449,8 +2451,9 @@ static irqreturn_t oxu210_hcd_irq(struct
+ goto dead;
+ }
+
++ /* Shared IRQ? */
+ status &= INTR_MASK;
+- if (!status) { /* irq sharing? */
++ if (!status || unlikely(hcd->state == HC_STATE_HALT)) {
+ spin_unlock(&oxu->lock);
+ return IRQ_NONE;
+ }
+@@ -2516,6 +2519,7 @@ static irqreturn_t oxu210_hcd_irq(struct
+ dead:
+ ehci_reset(oxu);
+ writel(0, &oxu->regs->configured_flag);
++ usb_hc_died(hcd);
+ /* generic layer kills/unlinks all urbs, then
+ * uses oxu_stop to clean up the rest
+ */
diff --git a/queue-2.6.39/usb-serial-ftdi_sio-adding-support-for-tavir-stk500.patch b/queue-2.6.39/usb-serial-ftdi_sio-adding-support-for-tavir-stk500.patch
new file mode 100644
index 0000000000..49316951d9
--- /dev/null
+++ b/queue-2.6.39/usb-serial-ftdi_sio-adding-support-for-tavir-stk500.patch
@@ -0,0 +1,47 @@
+From 37909fe588c9e09ab57cd267e98678a17ceda64a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Benedek=20L=C3=A1szl=C3=B3?= <benedekl@gmail.com>
+Date: Wed, 20 Apr 2011 03:22:21 +0200
+Subject: USB: serial: ftdi_sio: adding support for TavIR STK500
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Benedek=20L=C3=A1szl=C3=B3?= <benedekl@gmail.com>
+
+commit 37909fe588c9e09ab57cd267e98678a17ceda64a upstream.
+
+Adding support for the TavIR STK500 (id 0403:FA33)
+Atmel AVR programmer device based on FTDI FT232RL.
+
+Signed-off-by: Benedek László <benedekl@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -566,6 +566,7 @@ static struct usb_device_id id_table_com
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
+ /*
+ * ELV devices:
+ */
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -491,6 +491,11 @@
+ /* www.canusb.com Lawicel CANUSB device (FTDI_VID) */
+ #define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+
++/*
++ * TavIR AVR product ids (FTDI_VID)
++ */
++#define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */
++
+
+
+ /********************************/
diff --git a/queue-2.6.39/xhci-fix-bug-in-control-transfer-cancellation.patch b/queue-2.6.39/xhci-fix-bug-in-control-transfer-cancellation.patch
new file mode 100644
index 0000000000..dcc90f4dff
--- /dev/null
+++ b/queue-2.6.39/xhci-fix-bug-in-control-transfer-cancellation.patch
@@ -0,0 +1,84 @@
+From 3abeca998a44205cfd837fa0bf1f7c24f8294acb Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 5 May 2011 19:08:09 -0700
+Subject: xhci: Fix bug in control transfer cancellation.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 3abeca998a44205cfd837fa0bf1f7c24f8294acb upstream.
+
+When the xHCI driver attempts to cancel a transfer, it issues a Stop
+Endpoint command and waits for the host controller to indicate which TRB
+it was in the middle of processing. The host will put an event TRB with
+completion code COMP_STOP on the event ring if it stops on a control
+transfer TRB (or other types of transfer TRBs). The ring handling code
+is supposed to set ep->stopped_trb to the TRB that the host stopped on
+when this happens.
+
+Unfortunately, there is a long-standing bug in the control transfer
+completion code. It doesn't actually check to see if COMP_STOP is set
+before attempting to process the transfer based on which part of the
+control TD completed. So when we get an event on the data phase of the
+control TRB with COMP_STOP set, it thinks it's a normal completion of
+the transfer and doesn't set ep->stopped_td or ep->stopped_trb.
+
+When the ring handling code goes on to process the completion of the Stop
+Endpoint command, it sees that ep->stopped_trb is not a part of the TD
+it's trying to cancel. It thinks the hardware has its enqueue pointer
+somewhere further up in the ring, and thinks it's safe to turn the control
+TRBs into no-op TRBs. Since the hardware was in the middle of the control
+TRBs to be cancelled, the proper software behavior is to issue a Set TR
+dequeue pointer command.
+
+It turns out that the NEC host controllers can handle active TRBs being
+set to no-op TRBs after a stop endpoint command, but other host
+controllers have issues with this out-of-spec software behavior. Fix this
+behavior.
+
+This patch should be backported to kernels as far back as 2.6.31, but it
+may be a bit challenging, since process_ctrl_td() was introduced in some
+refactoring done in 2.6.36, and some endian-safe patches added in 2.6.40
+that touch the same lines.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1632,6 +1632,9 @@ static int process_ctrl_td(struct xhci_h
+ else
+ *status = 0;
+ break;
++ case COMP_STOP_INVAL:
++ case COMP_STOP:
++ return finish_td(xhci, td, event_trb, event, ep, status, false);
+ default:
+ if (!xhci_requires_manual_halt_cleanup(xhci,
+ ep_ctx, trb_comp_code))
+@@ -1676,15 +1679,12 @@ static int process_ctrl_td(struct xhci_h
+ }
+ } else {
+ /* Maybe the event was for the data stage? */
+- if (trb_comp_code != COMP_STOP_INVAL) {
+- /* We didn't stop on a link TRB in the middle */
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length -
+- TRB_LEN(event->transfer_len);
+- xhci_dbg(xhci, "Waiting for status "
+- "stage event\n");
+- return 0;
+- }
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length -
++ TRB_LEN(le32_to_cpu(event->transfer_len));
++ xhci_dbg(xhci, "Waiting for status "
++ "stage event\n");
++ return 0;
+ }
+ }
+
diff --git a/queue-2.6.39/xhci-fix-full-speed-binterval-encoding.patch b/queue-2.6.39/xhci-fix-full-speed-binterval-encoding.patch
new file mode 100644
index 0000000000..88abcc7ee6
--- /dev/null
+++ b/queue-2.6.39/xhci-fix-full-speed-binterval-encoding.patch
@@ -0,0 +1,63 @@
+From b513d44751bfb609a3c20463f764c8ce822d63e9 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 13 May 2011 13:10:01 -0700
+Subject: xhci: Fix full speed bInterval encoding.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit b513d44751bfb609a3c20463f764c8ce822d63e9 upstream.
+
+Dmitry's patch
+
+dfa49c4ad120a784ef1ff0717168aa79f55a483a USB: xhci - fix math in xhci_get_endpoint_interval()
+
+introduced a bug. The USB 2.0 spec says that full speed isochronous endpoints'
+bInterval must be decoded as an exponent to a power of two (e.g. interval =
+2^(bInterval - 1)). Full speed interrupt endpoints, on the other hand, don't
+use exponents, and the interval in frames is encoded straight into bInterval.
+
+Dmitry's patch was supposed to fix up the full speed isochronous to parse
+bInterval as an exponent, but instead it changed the *interrupt* endpoint
+bInterval decoding. The isochronous endpoint encoding was the same.
+
+This caused full speed devices with interrupt endpoints (including mice, hubs,
+and USB to ethernet devices) to fail under NEC 0.96 xHCI host controllers:
+
+[ 100.909818] xhci_hcd 0000:06:00.0: add ep 0x83, slot id 1, new drop flags = 0x0, new add flags = 0x99, new slot info = 0x38100000
+[ 100.909821] xhci_hcd 0000:06:00.0: xhci_check_bandwidth called for udev ffff88011f0ea000
+...
+[ 100.910187] xhci_hcd 0000:06:00.0: ERROR: unexpected command completion code 0x11.
+[ 100.910190] xhci_hcd 0000:06:00.0: xhci_reset_bandwidth called for udev ffff88011f0ea000
+
+When the interrupt endpoint was added and a Configure Endpoint command was
+issued to the host, the host controller would return a very odd error message
+(0x11 means "Slot Not Enabled", which isn't true because the slot was enabled).
+Probably the host controller was getting very confused with the bad encoding.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: Dmitry Torokhov <dtor@vmware.com>
+Reported-by: Thomas Lindroth <thomas.lindroth@gmail.com>
+Tested-by: Thomas Lindroth <thomas.lindroth@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1046,12 +1046,12 @@ static unsigned int xhci_get_endpoint_in
+ break;
+
+ case USB_SPEED_FULL:
+- if (usb_endpoint_xfer_int(&ep->desc)) {
++ if (usb_endpoint_xfer_isoc(&ep->desc)) {
+ interval = xhci_parse_exponent_interval(udev, ep);
+ break;
+ }
+ /*
+- * Fall through for isochronous endpoint interval decoding
++ * Fall through for interrupt endpoint interval decoding
+ * since it uses the same rules as low speed interrupt
+ * endpoints.
+ */
diff --git a/queue-2.6.39/xhci-fix-memory-leak-bug-when-dropping-endpoints.patch b/queue-2.6.39/xhci-fix-memory-leak-bug-when-dropping-endpoints.patch
new file mode 100644
index 0000000000..9ea7c04504
--- /dev/null
+++ b/queue-2.6.39/xhci-fix-memory-leak-bug-when-dropping-endpoints.patch
@@ -0,0 +1,65 @@
+From 834cb0fc4712a3b21c6b8c5cb55bd13607191311 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 12 May 2011 18:06:37 -0700
+Subject: xhci: Fix memory leak bug when dropping endpoints
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 834cb0fc4712a3b21c6b8c5cb55bd13607191311 upstream.
+
+When the USB core wants to change to an alternate interface setting that
+doesn't include an active endpoint, or de-configuring the device, the xHCI
+driver needs to issue a Configure Endpoint command to tell the host to
+drop some endpoints from the schedule. After the command completes, the
+xHCI driver needs to free rings for any endpoints that were dropped.
+
+Unfortunately, the xHCI driver wasn't actually freeing the endpoint rings
+for dropped endpoints. The rings would be freed if the endpoint's
+information was simply changed (and a new ring was installed), but dropped
+endpoints never had their rings freed. This caused errors when the ring
+segment DMA pool was freed when the xHCI driver was unloaded:
+
+[ 5582.883995] xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff88003371d000 busy
+[ 5582.884002] xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff880033716000 busy
+[ 5582.884011] xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff880033455000 busy
+[ 5582.884018] xhci_hcd 0000:06:00.0: Freed segment pool
+[ 5582.884026] xhci_hcd 0000:06:00.0: Freed device context pool
+[ 5582.884033] xhci_hcd 0000:06:00.0: Freed small stream array pool
+[ 5582.884038] xhci_hcd 0000:06:00.0: Freed medium stream array pool
+[ 5582.884048] xhci_hcd 0000:06:00.0: xhci_stop completed - status = 1
+[ 5582.884061] xhci_hcd 0000:06:00.0: USB bus 3 deregistered
+[ 5582.884193] xhci_hcd 0000:06:00.0: PCI INT A disabled
+
+Fix this issue and free endpoint rings when their endpoints are
+successfully dropped.
+
+This patch should be backported to kernels as old as 2.6.31.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1692,8 +1692,17 @@ int xhci_check_bandwidth(struct usb_hcd
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx,
+ LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
+
++ /* Free any rings that were dropped, but not changed. */
++ for (i = 1; i < 31; ++i) {
++ if ((ctrl_ctx->drop_flags & (1 << (i + 1))) &&
++ !(ctrl_ctx->add_flags & (1 << (i + 1))))
++ xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
++ }
+ xhci_zero_in_ctx(xhci, virt_dev);
+- /* Install new rings and free or cache any old rings */
++ /*
++ * Install any rings for completely new endpoints or changed endpoints,
++ * and free or cache any old rings from changed endpoints.
++ */
+ for (i = 1; i < 31; ++i) {
+ if (!virt_dev->eps[i].new_ring)
+ continue;
diff --git a/queue-2.6.39/xhci-fix-memory-leak-in-ring-cache-deallocation.patch b/queue-2.6.39/xhci-fix-memory-leak-in-ring-cache-deallocation.patch
new file mode 100644
index 0000000000..b5c3756bb4
--- /dev/null
+++ b/queue-2.6.39/xhci-fix-memory-leak-in-ring-cache-deallocation.patch
@@ -0,0 +1,64 @@
+From 30f89ca021c3e584b61bc5a14eede89f74b2e826 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 16 May 2011 13:09:08 -0700
+Subject: xhci: Fix memory leak in ring cache deallocation.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 30f89ca021c3e584b61bc5a14eede89f74b2e826 upstream.
+
+When an endpoint ring is freed, it is either cached in a per-device ring
+cache, or simply freed if the ring cache is full. If the ring was added
+to the cache, then virt_dev->num_rings_cached is incremented. The cache
+is designed to hold up to 31 endpoint rings, in array indexes 0 to 30.
+When the device is freed (when the slot was disabled),
+xhci_free_virt_device() is called, it would free the cached rings in
+array indexes 0 to virt_dev->num_rings_cached.
+
+Unfortunately, the original code in xhci_free_or_cache_endpoint_ring()
+would put the first entry into the ring cache in array index 1, instead of
+array index 0. This was caused by the second assignment to rings_cached:
+
+ rings_cached = virt_dev->num_rings_cached;
+ if (rings_cached < XHCI_MAX_RINGS_CACHED) {
+ virt_dev->num_rings_cached++;
+ rings_cached = virt_dev->num_rings_cached;
+ virt_dev->ring_cache[rings_cached] =
+ virt_dev->eps[ep_index].ring;
+
+This meant that when the device was freed, cached rings with indexes 0 to
+N would be freed, and the last cached ring in index N+1 would not be
+freed. When the driver was unloaded, this caused interesting messages
+like:
+
+xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff880063040000 busy
+
+This should be queued to stable kernels back to 2.6.33.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -207,14 +207,13 @@ void xhci_free_or_cache_endpoint_ring(st
+
+ rings_cached = virt_dev->num_rings_cached;
+ if (rings_cached < XHCI_MAX_RINGS_CACHED) {
+- virt_dev->num_rings_cached++;
+- rings_cached = virt_dev->num_rings_cached;
+ virt_dev->ring_cache[rings_cached] =
+ virt_dev->eps[ep_index].ring;
++ virt_dev->num_rings_cached++;
+ xhci_dbg(xhci, "Cached old ring, "
+ "%d ring%s cached\n",
+- rings_cached,
+- (rings_cached > 1) ? "s" : "");
++ virt_dev->num_rings_cached,
++ (virt_dev->num_rings_cached > 1) ? "s" : "");
+ } else {
+ xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
+ xhci_dbg(xhci, "Ring cache full (%d rings), "