aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-01-18 11:28:05 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-18 11:28:05 -0800
commit7695771e986729e6eae9fac3657668fbf01b19b1 (patch)
tree04c16c11fcd7cb117fe138738bdbd481fdc53c77 /usb
parent05f961a7cefc2f1441dcbaef4b175023c44b2342 (diff)
downloadpatches-7695771e986729e6eae9fac3657668fbf01b19b1.tar.gz
new usb patches and 2.6.16-rc1 refresh
Diffstat (limited to 'usb')
-rw-r--r--usb/ueagle-add-iso-support.patch104
-rw-r--r--usb/ueagle-cmv-name-bug.patch31
-rw-r--r--usb/ueagle-cosmetic.patch126
-rw-r--r--usb/usb-add-et61x51-video4linux2-driver.patch6
-rw-r--r--usb/usb-add-new-auerswald-device-ids.patch32
-rw-r--r--usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch274
-rw-r--r--usb/usb-libusual-fix-warning-on-64bit-boxes.patch34
-rw-r--r--usb/usbatm-add-flags-field.patch171
-rw-r--r--usb/usbatm-allow-isochronous-transfer.patch341
-rw-r--r--usb/usbatm-bump-version-numbers.patch37
-rw-r--r--usb/usbatm-eilseq-workaround.patch44
-rw-r--r--usb/usbatm-handle-urbs-containing-partial-cells.patch394
-rw-r--r--usb/usbatm-kzalloc-conversion.patch89
-rw-r--r--usb/usbatm-measure-buffer-size-in-bytes-force-valid-sizes.patch280
-rw-r--r--usb/usbatm-remove-.owner.patch80
-rw-r--r--usb/usbatm-return-correct-error-code-when-out-of-memory.patch34
-rw-r--r--usb/usbatm-semaphore-to-mutex-conversion.patch313
-rw-r--r--usb/usbatm-shutdown-open-connections-when-disconnected.patch172
-rw-r--r--usb/usbatm-trivial-modifications.patch924
-rw-r--r--usb/usbatm-use-dev_kfree_skb_any-rather-than-dev_kfree_skb.patch46
-rw-r--r--usb/usbatm-xusbatm-rewrite.patch190
21 files changed, 3446 insertions, 276 deletions
diff --git a/usb/ueagle-add-iso-support.patch b/usb/ueagle-add-iso-support.patch
new file mode 100644
index 0000000000000..86ba2929b5d1c
--- /dev/null
+++ b/usb/ueagle-add-iso-support.patch
@@ -0,0 +1,104 @@
+From castet.matthieu@free.fr Tue Jan 17 22:36:43 2006
+Message-ID: <43CDE25B.6030503@free.fr>
+Date: Wed, 18 Jan 2006 07:38:19 +0100
+From: matthieu castet <castet.matthieu@free.fr>
+To: greg@kroah.com
+Subject: [PATCH 1/2] UEAGLE : add iso support
+
+This patch adds the support for isochronous pipe.
+
+A new module parameter is added to select iso mode. It is set to iso by
+default because bulk mode doesn't work well at high speed rate (>3 Mbps
+for upload).
+
+We use UDSL_IGNORE_EILSEQ flags because ADI firmware doesn't reply to
+ISO IN when it has nothing to send [1].
+
+
+[1]
+from cypress datasheet :
+
+The ISOSEND0 Bit (bit 7 in the USBPAIR Register) is used when the EZ-USB
+FX chip receives an isochronous IN token while the IN FIFO is empty. If
+ISOSEND0=0 (the default value), the USB core does not respond to the IN
+token. If ISOSEND0=1, the USB core sends a zero-length data packet in
+response to the IN token. The action to take depends on the overall
+system design. The ISOSEND0 Bit applies to all of the isochronous IN
+endpoints, IN-8 through IN-15.
+
+
+Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/ueagle-atm.c | 26 +++++++++++++++++++++++++-
+ 1 file changed, 25 insertions(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -68,7 +68,7 @@
+
+ #include "usbatm.h"
+
+-#define EAGLEUSBVERSION "ueagle 1.1"
++#define EAGLEUSBVERSION "ueagle 1.2"
+
+
+ /*
+@@ -364,11 +364,14 @@ static const char *chip_name[] = {"ADI93
+
+ static int modem_index;
+ static unsigned int debug;
++static int use_iso[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = 1};
+ static int sync_wait[NB_MODEM];
+ static char *cmv_file[NB_MODEM];
+
+ module_param(debug, uint, 0644);
+ MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
++module_param_array(use_iso, bool, NULL, 0644);
++MODULE_PARM_DESC(use_iso, "use isochronous usb pipe for incoming traffic");
+ module_param_array(sync_wait, bool, NULL, 0644);
+ MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
+ module_param_array(cmv_file, charp, NULL, 0644);
+@@ -936,6 +939,7 @@ static int uea_stat(struct uea_softc *sc
+ * ADI930 don't support it (-EPIPE error).
+ */
+ if (UEA_CHIP_VERSION(sc) != ADI930
++ && !use_iso[sc->modem_index]
+ && sc->stats.phy.dsrate != (data >> 16) * 32) {
+ /* Original timming from ADI(used in windows driver)
+ * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
+@@ -1659,6 +1663,25 @@ static int uea_bind(struct usbatm_data *
+ sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
+ sc->driver_info = id->driver_info;
+
++ /* ADI930 don't support iso */
++ if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) {
++ int i;
++
++ /* try set fastest alternate for inbound traffic interface */
++ for (i = FASTEST_ISO_INTF; i > 0; i--)
++ if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0)
++ break;
++
++ if (i > 0) {
++ uea_dbg(usb, "set alternate %d for 2 interface\n", i);
++ uea_info(usb, "using iso mode\n");
++ usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
++ } else {
++ uea_err(usb, "setting any alternate failed for "
++ "2 interface, using bulk mode\n");
++ }
++ }
++
+ ret = uea_boot(sc);
+ if (ret < 0) {
+ kfree(sc);
+@@ -1708,6 +1731,7 @@ static struct usbatm_driver uea_usbatm_d
+ .heavy_init = uea_heavy,
+ .bulk_in = UEA_BULK_DATA_PIPE,
+ .bulk_out = UEA_BULK_DATA_PIPE,
++ .isoc_in = UEA_ISO_DATA_PIPE,
+ };
+
+ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
diff --git a/usb/ueagle-cmv-name-bug.patch b/usb/ueagle-cmv-name-bug.patch
new file mode 100644
index 0000000000000..a015e1d0778cb
--- /dev/null
+++ b/usb/ueagle-cmv-name-bug.patch
@@ -0,0 +1,31 @@
+From castet.matthieu@free.fr Tue Jan 17 22:37:55 2006
+Message-ID: <43CDE29F.5080902@free.fr>
+Date: Wed, 18 Jan 2006 07:39:27 +0100
+From: matthieu castet <castet.matthieu@free.fr>
+To: greg@kroah.com
+Subject: [PATCH 3/2] UEAGLE : cmv name bug (was cosmetic)
+
+this patch correct a possible bug with cmv_name being static. If there
+is 2 modems and the driver is scheduled when filling cmv_name this could
+result with garbage in cmv_name. We allocate cmv_name on the stack but
+with a small size in order to avoid that.
+
+
+Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/ueagle-atm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -1013,7 +1013,7 @@ static int request_cmvs(struct uea_softc
+ int ret, size;
+ u8 *data;
+ char *file;
+- static char cmv_name[256] = FW_DIR;
++ char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */
+
+ if (cmv_file[sc->modem_index] == NULL) {
+ if (UEA_CHIP_VERSION(sc) == ADI930)
diff --git a/usb/ueagle-cosmetic.patch b/usb/ueagle-cosmetic.patch
new file mode 100644
index 0000000000000..648fb8b5a0662
--- /dev/null
+++ b/usb/ueagle-cosmetic.patch
@@ -0,0 +1,126 @@
+From castet.matthieu@free.fr Tue Jan 17 22:37:00 2006
+Message-ID: <43CDE26D.8040002@free.fr>
+Date: Wed, 18 Jan 2006 07:38:37 +0100
+From: matthieu castet <castet.matthieu@free.fr>
+To: greg@kroah.com
+Subject: [PATCH 2/2] UEAGLE : cosmetic
+
+this patch is purely cosmetic. There is :
+- indentation cleaning
+- unneeded cast removing
+- comments cleaning
+
+
+Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/ueagle-atm.c | 32 +++++++++++---------------------
+ 1 file changed, 11 insertions(+), 21 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -632,8 +632,7 @@ static int request_dsp(struct uea_softc
+ dsp_name = FW_DIR "DSPep.bin";
+ }
+
+- ret = request_firmware(&sc->dsp_firm,
+- dsp_name, &sc->usb_dev->dev);
++ ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "requesting firmware %s failed with error %d\n",
+@@ -748,7 +747,6 @@ static inline int wait_cmv_ack(struct ue
+ return ret;
+
+ return (ret == 0) ? -ETIMEDOUT : 0;
+-
+ }
+
+ #define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
+@@ -1189,8 +1187,7 @@ static int load_XILINX_firmware(struct u
+ }
+ }
+
+- /* finish to send the fpga
+- */
++ /* finish to send the fpga */
+ ret = uea_request(sc, 0xe, 1, 0, NULL);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+@@ -1198,9 +1195,7 @@ static int load_XILINX_firmware(struct u
+ goto err1;
+ }
+
+- /*
+- * Tell the modem we finish : de-assert reset
+- */
++ /* Tell the modem we finish : de-assert reset */
+ value = 0;
+ ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
+ if (ret < 0)
+@@ -1214,6 +1209,7 @@ err0:
+ return ret;
+ }
+
++/* The modem send us an ack. First with check if it right */
+ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
+ {
+ uea_enters(INS_TO_USBDEV(sc));
+@@ -1273,23 +1269,19 @@ bad1:
+ */
+ static void uea_intr(struct urb *urb, struct pt_regs *regs)
+ {
+- struct uea_softc *sc = (struct uea_softc *)urb->context;
+- struct intr_pkt *intr;
++ struct uea_softc *sc = urb->context;
++ struct intr_pkt *intr = urb->transfer_buffer;
+ uea_enters(INS_TO_USBDEV(sc));
+
+- if (urb->status < 0) {
++ if (unlikely(urb->status < 0)) {
+ uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
+ urb->status);
+ return;
+ }
+
+- intr = (struct intr_pkt *) urb->transfer_buffer;
+-
+ /* device-to-host interrupt */
+ if (intr->bType != 0x08 || sc->booting) {
+- uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
+- // rebooting ?
+- // sc->reset = 1;
++ uea_err(INS_TO_USBDEV(sc), "wrong interrupt\n");
+ goto resubmit;
+ }
+
+@@ -1305,7 +1297,7 @@ static void uea_intr(struct urb *urb, st
+ break;
+
+ default:
+- uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
++ uea_err(INS_TO_USBDEV(sc), "unknown interrupt %u\n",
+ le16_to_cpu(intr->wInterrupt));
+ }
+
+@@ -1384,7 +1376,7 @@ static void uea_stop(struct uea_softc *s
+ int ret;
+ uea_enters(INS_TO_USBDEV(sc));
+ ret = kthread_stop(sc->kthread);
+- uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
++ uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+
+ /* stop any pending boot process */
+ flush_scheduled_work();
+@@ -1641,9 +1633,7 @@ static int uea_bind(struct usbatm_data *
+ if (ret < 0)
+ return ret;
+
+- /* ADI930 has only 2 interfaces and inbound traffic
+- * is on interface 1
+- */
++ /* ADI930 has only 2 interfaces and inbound traffic is on interface 1 */
+ if (UEA_CHIP_VERSION(id) != ADI930) {
+ /* interface 2 is for inbound traffic */
+ ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
diff --git a/usb/usb-add-et61x51-video4linux2-driver.patch b/usb/usb-add-et61x51-video4linux2-driver.patch
index 9906f896e570e..90242ade8b4be 100644
--- a/usb/usb-add-et61x51-video4linux2-driver.patch
+++ b/usb/usb-add-et61x51-video4linux2-driver.patch
@@ -3490,7 +3490,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
* F O R M A T E N U M E R A T I O N
--- gregkh-2.6.orig/MAINTAINERS
+++ gregkh-2.6/MAINTAINERS
-@@ -2661,6 +2661,14 @@ M: dbrownell@users.sourceforge.net
+@@ -2663,6 +2663,14 @@ M: dbrownell@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
@@ -3505,7 +3505,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
USB HID/HIDBP DRIVERS
P: Vojtech Pavlik
M: vojtech@suse.cz
-@@ -2824,6 +2832,7 @@ USB SN9C10x DRIVER
+@@ -2826,6 +2834,7 @@ USB SN9C10x DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
@@ -3513,7 +3513,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
W: http://www.linux-projects.org
S: Maintained
-@@ -2853,6 +2862,7 @@ USB W996[87]CF DRIVER
+@@ -2855,6 +2864,7 @@ USB W996[87]CF DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
diff --git a/usb/usb-add-new-auerswald-device-ids.patch b/usb/usb-add-new-auerswald-device-ids.patch
new file mode 100644
index 0000000000000..7bba8e9a31e52
--- /dev/null
+++ b/usb/usb-add-new-auerswald-device-ids.patch
@@ -0,0 +1,32 @@
+From akpm@osdl.org Tue Jan 17 15:35:31 2006
+Message-Id: <200601172335.k0HNZMlR006374@shell0.pdx.osdl.net>
+From: Andrew Morton <akpm@osdl.org>
+Subject: USB: add new auerswald device ids
+To: akpm@osdl.org, dj-tj@gmx.de, greg@kroah.com, mm-commits@vger.kernel.org
+Date: Tue, 17 Jan 2006 15:37:22 -0800
+
+
+From: Andrew Morton <akpm@osdl.org>
+
+Add device support for a couple more Auerswald TK-devices.
+
+Via Thomas Jackle <dj-tj@gmx.de>, typed in from
+http://bugzilla.kernel.org/show_bug.cgi?id=5908.
+
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/misc/auerswald.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/misc/auerswald.c
++++ gregkh-2.6/drivers/usb/misc/auerswald.c
+@@ -2093,6 +2093,8 @@ static void auerswald_disconnect (struct
+ static struct usb_device_id auerswald_ids [] = {
+ { USB_DEVICE (ID_AUERSWALD, 0x00C0) }, /* COMpact 2104 USB */
+ { USB_DEVICE (ID_AUERSWALD, 0x00DB) }, /* COMpact 4410/2206 USB */
++ { USB_DEVICE (ID_AUERSWALD, 0x00DC) }, /* COMpact 4406 DSL */
++ { USB_DEVICE (ID_AUERSWALD, 0x00DD) }, /* COMpact 2204 USB */
+ { USB_DEVICE (ID_AUERSWALD, 0x00F1) }, /* Comfort 2000 System Telephone */
+ { USB_DEVICE (ID_AUERSWALD, 0x00F2) }, /* Comfort 1200 System Telephone */
+ { } /* Terminating entry */
diff --git a/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch b/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch
index e7ea1ad73a108..988c0030875a9 100644
--- a/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch
+++ b/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch
@@ -14,10 +14,6 @@ Signed-off-by: Arjan van de Ven <arjan@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
- drivers/usb/atm/cxacru.c | 8 +-
- drivers/usb/atm/ueagle-atm.c | 27 +++---
- drivers/usb/atm/usbatm.c | 24 +++---
- drivers/usb/atm/usbatm.h | 3
drivers/usb/class/cdc-acm.c | 23 +++--
drivers/usb/class/usblp.c | 15 ++-
drivers/usb/core/devices.c | 7 +
@@ -52,7 +48,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/storage/scsiglue.c | 9 +-
drivers/usb/storage/usb.c | 25 +++---
drivers/usb/storage/usb.h | 5 -
- 38 files changed, 414 insertions(+), 394 deletions(-)
+ 34 files changed, 382 insertions(+), 364 deletions(-)
--- gregkh-2.6.orig/drivers/usb/class/cdc-acm.c
+++ gregkh-2.6/drivers/usb/class/cdc-acm.c
@@ -1068,274 +1064,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
extern struct file_operations mon_fops_text;
extern struct file_operations mon_fops_stat;
---- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
-+++ gregkh-2.6/drivers/usb/atm/usbatm.c
-@@ -741,7 +741,7 @@ static int usbatm_atm_open(struct atm_vc
- return -EINVAL;
- }
-
-- down(&instance->serialize); /* vs self, usbatm_atm_close */
-+ mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close */
-
- if (usbatm_find_vcc(instance, vpi, vci)) {
- atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);
-@@ -777,7 +777,7 @@ static int usbatm_atm_open(struct atm_vc
- set_bit(ATM_VF_PARTIAL, &vcc->flags);
- set_bit(ATM_VF_READY, &vcc->flags);
-
-- up(&instance->serialize);
-+ mutex_unlock(&instance->serialize);
-
- atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
-
-@@ -785,7 +785,7 @@ static int usbatm_atm_open(struct atm_vc
-
- fail:
- kfree(new);
-- up(&instance->serialize);
-+ mutex_unlock(&instance->serialize);
- return ret;
- }
-
-@@ -806,7 +806,7 @@ static void usbatm_atm_close(struct atm_
-
- usbatm_cancel_send(instance, vcc);
-
-- down(&instance->serialize); /* vs self, usbatm_atm_open */
-+ mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open */
-
- tasklet_disable(&instance->rx_channel.tasklet);
- list_del(&vcc_data->list);
-@@ -824,7 +824,7 @@ static void usbatm_atm_close(struct atm_
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
-
-- up(&instance->serialize);
-+ mutex_unlock(&instance->serialize);
-
- atm_dbg(instance, "%s successful\n", __func__);
- }
-@@ -903,9 +903,9 @@ static int usbatm_do_heavy_init(void *ar
- if (!ret)
- ret = usbatm_atm_init(instance);
-
-- down(&instance->serialize);
-+ mutex_lock(&instance->serialize);
- instance->thread_pid = -1;
-- up(&instance->serialize);
-+ mutex_unlock(&instance->serialize);
-
- complete_and_exit(&instance->thread_exited, ret);
- }
-@@ -919,9 +919,9 @@ static int usbatm_heavy_init(struct usba
- return ret;
- }
-
-- down(&instance->serialize);
-+ mutex_lock(&instance->serialize);
- instance->thread_pid = ret;
-- up(&instance->serialize);
-+ mutex_unlock(&instance->serialize);
-
- wait_for_completion(&instance->thread_started);
-
-@@ -1005,7 +1005,7 @@ int usbatm_usb_probe(struct usb_interfac
- /* private fields */
-
- kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */
-- init_MUTEX(&instance->serialize);
-+ mutex_init(&instance->serialize);
-
- instance->thread_pid = -1;
- init_completion(&instance->thread_started);
-@@ -1125,10 +1125,10 @@ void usbatm_usb_disconnect(struct usb_in
-
- usb_set_intfdata(intf, NULL);
-
-- down(&instance->serialize);
-+ mutex_lock(&instance->serialize);
- if (instance->thread_pid >= 0)
- kill_proc(instance->thread_pid, SIGTERM, 1);
-- up(&instance->serialize);
-+ mutex_unlock(&instance->serialize);
-
- wait_for_completion(&instance->thread_exited);
-
---- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
-+++ gregkh-2.6/drivers/usb/atm/usbatm.h
-@@ -39,6 +39,7 @@
- #include <linux/list.h>
- #include <linux/stringify.h>
- #include <linux/usb.h>
-+#include <linux/mutex.h>
-
- #ifdef DEBUG
- #define UDSL_ASSERT(x) BUG_ON(!(x))
-@@ -157,7 +158,7 @@ struct usbatm_data {
- ********************************/
-
- struct kref refcount;
-- struct semaphore serialize;
-+ struct mutex serialize;
-
- /* heavy init */
- int thread_pid;
---- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
-+++ gregkh-2.6/drivers/usb/atm/cxacru.c
-@@ -160,7 +160,7 @@ struct cxacru_data {
- struct work_struct poll_work;
-
- /* contol handles */
-- struct semaphore cm_serialize;
-+ struct mutex cm_serialize;
- u8 *rcv_buf;
- u8 *snd_buf;
- struct urb *rcv_urb;
-@@ -219,7 +219,7 @@ static int cxacru_cm(struct cxacru_data
- goto fail;
- }
-
-- down(&instance->cm_serialize);
-+ mutex_lock(&instance->cm_serialize);
-
- /* submit reading urb before the writing one */
- init_completion(&instance->rcv_done);
-@@ -288,7 +288,7 @@ static int cxacru_cm(struct cxacru_data
- ret = offd;
- dbg("cm %#x", cm);
- fail:
-- up(&instance->cm_serialize);
-+ mutex_unlock(&instance->cm_serialize);
- return ret;
- }
-
-@@ -721,7 +721,7 @@ static int cxacru_bind(struct usbatm_dat
- instance->snd_buf, PAGE_SIZE,
- cxacru_blocking_completion, &instance->snd_done, 4);
-
-- init_MUTEX(&instance->cm_serialize);
-+ mutex_init(&instance->cm_serialize);
-
- INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);
-
---- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
-+++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
-@@ -63,6 +63,7 @@
- #include <linux/ctype.h>
- #include <linux/kthread.h>
- #include <linux/version.h>
-+#include <linux/mutex.h>
- #include <asm/unaligned.h>
-
- #include "usbatm.h"
-@@ -358,7 +359,7 @@ struct intr_pkt {
- #define INTR_PKT_SIZE 28
-
- static struct usb_driver uea_driver;
--static DECLARE_MUTEX(uea_semaphore);
-+static DEFINE_MUTEX(uea_mutex);
- static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
-
- static int modem_index;
-@@ -1418,13 +1419,13 @@ static ssize_t read_status(struct device
- int ret = -ENODEV;
- struct uea_softc *sc;
-
-- down(&uea_semaphore);
-+ mutex_lock(&uea_mutex);
- sc = dev_to_uea(dev);
- if (!sc)
- goto out;
- ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
- out:
-- up(&uea_semaphore);
-+ mutex_unlock(&uea_mutex);
- return ret;
- }
-
-@@ -1434,14 +1435,14 @@ static ssize_t reboot(struct device *dev
- int ret = -ENODEV;
- struct uea_softc *sc;
-
-- down(&uea_semaphore);
-+ mutex_lock(&uea_mutex);
- sc = dev_to_uea(dev);
- if (!sc)
- goto out;
- sc->reset = 1;
- ret = count;
- out:
-- up(&uea_semaphore);
-+ mutex_unlock(&uea_mutex);
- return ret;
- }
-
-@@ -1453,7 +1454,7 @@ static ssize_t read_human_status(struct
- int ret = -ENODEV;
- struct uea_softc *sc;
-
-- down(&uea_semaphore);
-+ mutex_lock(&uea_mutex);
- sc = dev_to_uea(dev);
- if (!sc)
- goto out;
-@@ -1473,7 +1474,7 @@ static ssize_t read_human_status(struct
- break;
- }
- out:
-- up(&uea_semaphore);
-+ mutex_unlock(&uea_mutex);
- return ret;
- }
-
-@@ -1485,7 +1486,7 @@ static ssize_t read_delin(struct device
- int ret = -ENODEV;
- struct uea_softc *sc;
-
-- down(&uea_semaphore);
-+ mutex_lock(&uea_mutex);
- sc = dev_to_uea(dev);
- if (!sc)
- goto out;
-@@ -1497,7 +1498,7 @@ static ssize_t read_delin(struct device
- else
- ret = sprintf(buf, "GOOD\n");
- out:
-- up(&uea_semaphore);
-+ mutex_unlock(&uea_mutex);
- return ret;
- }
-
-@@ -1511,7 +1512,7 @@ static ssize_t read_##name(struct device
- int ret = -ENODEV; \
- struct uea_softc *sc; \
- \
-- down(&uea_semaphore); \
-+ mutex_lock(&uea_mutex); \
- sc = dev_to_uea(dev); \
- if (!sc) \
- goto out; \
-@@ -1519,7 +1520,7 @@ static ssize_t read_##name(struct device
- if (reset) \
- sc->stats.phy.name = 0; \
- out: \
-- up(&uea_semaphore); \
-+ mutex_unlock(&uea_mutex); \
- return ret; \
- } \
- \
-@@ -1738,9 +1739,9 @@ static void uea_disconnect(struct usb_in
- * Pre-firmware device has one interface
- */
- if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
-- down(&uea_semaphore);
-+ mutex_lock(&uea_mutex);
- usbatm_usb_disconnect(intf);
-- up(&uea_semaphore);
-+ mutex_unlock(&uea_mutex);
- uea_info(usb, "ADSL device removed\n");
- }
-
--- gregkh-2.6.orig/drivers/usb/image/mdc800.c
+++ gregkh-2.6/drivers/usb/image/mdc800.c
@@ -96,6 +96,7 @@
diff --git a/usb/usb-libusual-fix-warning-on-64bit-boxes.patch b/usb/usb-libusual-fix-warning-on-64bit-boxes.patch
new file mode 100644
index 0000000000000..ba4e4f4112e7e
--- /dev/null
+++ b/usb/usb-libusual-fix-warning-on-64bit-boxes.patch
@@ -0,0 +1,34 @@
+From akpm@osdl.org Tue Jan 17 15:37:25 2006
+Message-Id: <200601172337.k0HNbPhc006451@shell0.pdx.osdl.net>
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Subject: USB: libusual: fix warning on 64bit boxes
+To: alan@lxorguk.ukuu.org.uk, alan@redhat.com, greg@kroah.com,
+ zaitcev@redhat.com, mm-commits@vger.kernel.org
+From: akpm@osdl.org
+Date: Tue, 17 Jan 2006 15:39:25 -0800
+
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+We cast an int to a void * which not unreasonably makes gcc suspicious.
+We don't actually care what type "type" is so use unsigned long so it
+matches pointer length on all platforms.
+
+Signed-off-by: Alan Cox <alan@redhat.com>
+Acked-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/storage/libusual.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/drivers/usb/storage/libusual.c
++++ gregkh-2.6/drivers/usb/storage/libusual.c
+@@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(usb_usual_check_type);
+ static int usu_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- int type;
++ unsigned long type;
+ int rc;
+ unsigned long flags;
+
diff --git a/usb/usbatm-add-flags-field.patch b/usb/usbatm-add-flags-field.patch
new file mode 100644
index 0000000000000..3dee1bf337277
--- /dev/null
+++ b/usb/usbatm-add-flags-field.patch
@@ -0,0 +1,171 @@
+From baldrick@free.fr Tue Jan 17 02:16:16 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 02/13] USBATM: add flags field
+Content-Disposition: inline
+Date: Tue, 17 Jan 2006 11:16:13 +0100
+Message-Id: <200601171116.13805.baldrick@free.fr>
+
+Have minidrivers and the core signal special requirements
+using a flags field in struct usbatm_data. For the moment
+this is only used to replace the need_heavy_init bind
+parameter, but there'll be new flags in later patches.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/cxacru.c | 5 ++---
+ drivers/usb/atm/speedtch.c | 9 ++++-----
+ drivers/usb/atm/ueagle-atm.c | 4 ++--
+ drivers/usb/atm/usbatm.c | 6 ++----
+ drivers/usb/atm/usbatm.h | 13 ++++++++-----
+ drivers/usb/atm/xusbatm.c | 3 +--
+ 6 files changed, 19 insertions(+), 21 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
++++ gregkh-2.6/drivers/usb/atm/cxacru.c
+@@ -666,8 +666,7 @@ static int cxacru_heavy_init(struct usba
+ }
+
+ static int cxacru_bind(struct usbatm_data *usbatm_instance,
+- struct usb_interface *intf, const struct usb_device_id *id,
+- int *need_heavy_init)
++ struct usb_interface *intf, const struct usb_device_id *id)
+ {
+ struct cxacru_data *instance;
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+@@ -726,7 +725,7 @@ static int cxacru_bind(struct usbatm_dat
+
+ usbatm_instance->driver_data = instance;
+
+- *need_heavy_init = cxacru_card_status(instance);
++ usbatm_instance->flags = (cxacru_card_status(instance) ? 0 : UDSL_SKIP_HEAVY_INIT);
+
+ return 0;
+
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -681,8 +681,7 @@ static void speedtch_release_interfaces(
+
+ static int speedtch_bind(struct usbatm_data *usbatm,
+ struct usb_interface *intf,
+- const struct usb_device_id *id,
+- int *need_heavy_init)
++ const struct usb_device_id *id)
+ {
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct usb_interface *cur_intf;
+@@ -754,11 +753,11 @@ static int speedtch_bind(struct usbatm_d
+ 0x12, 0xc0, 0x07, 0x00,
+ instance->scratch_buffer + OFFSET_7, SIZE_7, 500);
+
+- *need_heavy_init = (ret != SIZE_7);
++ usbatm->flags = (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0);
+
+- usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already");
++ usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not");
+
+- if (*need_heavy_init)
++ if (!(usbatm->flags & UDSL_SKIP_HEAVY_INIT))
+ if ((ret = usb_reset_device(usb_dev)) < 0) {
+ usb_err(usbatm, "%s: device reset failed (%d)!\n", __func__, ret);
+ goto fail_free;
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -1617,7 +1617,7 @@ static void create_fs_entries(struct uea
+ }
+
+ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
+- const struct usb_device_id *id, int *heavy)
++ const struct usb_device_id *id)
+ {
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct uea_softc *sc;
+@@ -1629,7 +1629,7 @@ static int uea_bind(struct usbatm_data *
+ if (ifnum != UEA_INTR_IFACE_NO)
+ return -ENODEV;
+
+- *heavy = sync_wait[modem_index];
++ usbatm_instance->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);
+
+ /* interface 1 is for outbound traffic */
+ ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -969,7 +969,6 @@ int usbatm_usb_probe(struct usb_interfac
+ char *buf;
+ int error = -ENOMEM;
+ int i, length;
+- int need_heavy;
+
+ dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
+ __func__, driver->driver_name,
+@@ -1014,8 +1013,7 @@ int usbatm_usb_probe(struct usb_interfac
+ snprintf(buf, length, ")");
+
+ bind:
+- need_heavy = 1;
+- if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) {
++ if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) {
+ dev_err(dev, "%s: bind failed: %d!\n", __func__, error);
+ goto fail_free;
+ }
+@@ -1098,7 +1096,7 @@ int usbatm_usb_probe(struct usb_interfac
+ __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
+ }
+
+- if (need_heavy && driver->heavy_init) {
++ if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) {
+ error = usbatm_heavy_init(instance);
+ } else {
+ complete(&instance->thread_exited); /* pretend that heavy_init was run */
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -84,6 +84,11 @@
+ #endif
+
+
++/* flags, set by mini-driver in bind() */
++
++#define UDSL_SKIP_HEAVY_INIT (1<<0)
++
++
+ /* mini driver */
+
+ struct usbatm_data;
+@@ -99,12 +104,9 @@ struct usbatm_driver {
+
+ const char *driver_name;
+
+- /*
+- * init device ... can sleep, or cause probe() failure. Drivers with a heavy_init
+- * method can avoid having it called by setting need_heavy_init to zero.
+- */
++ /* init device ... can sleep, or cause probe() failure */
+ int (*bind) (struct usbatm_data *, struct usb_interface *,
+- const struct usb_device_id *id, int *need_heavy_init);
++ const struct usb_device_id *id);
+
+ /* additional device initialization that is too slow to be done in probe() */
+ int (*heavy_init) (struct usbatm_data *, struct usb_interface *);
+@@ -152,6 +154,7 @@ struct usbatm_data {
+ struct usbatm_driver *driver;
+ void *driver_data;
+ char driver_name[16];
++ unsigned int flags; /* set by mini-driver in bind() */
+
+ /* USB device */
+ struct usb_device *usb_dev;
+--- gregkh-2.6.orig/drivers/usb/atm/xusbatm.c
++++ gregkh-2.6/drivers/usb/atm/xusbatm.c
+@@ -62,8 +62,7 @@ static int usb_intf_has_ep(const struct
+ }
+
+ static int xusbatm_bind(struct usbatm_data *usbatm,
+- struct usb_interface *intf, const struct usb_device_id *id,
+- int *need_heavy_init)
++ struct usb_interface *intf, const struct usb_device_id *id)
+ {
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ int drv_ix = id - xusbatm_usb_ids;
diff --git a/usb/usbatm-allow-isochronous-transfer.patch b/usb/usbatm-allow-isochronous-transfer.patch
new file mode 100644
index 0000000000000..833829c13b9d2
--- /dev/null
+++ b/usb/usbatm-allow-isochronous-transfer.patch
@@ -0,0 +1,341 @@
+From baldrick@free.fr Fri Jan 13 01:59:23 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 10/13] USBATM: allow isochronous transfer
+Date: Fri, 13 Jan 2006 10:59:23 +0100
+Message-Id: <200601131059.24275.baldrick@free.fr>
+
+While the usbatm core has had some support for using isoc urbs
+for some time, there was no way for users to turn it on. While
+use of isoc transfer should still be considered experimental, it
+now works well enough to let users turn it on. Minidrivers signal
+to the core that they want to use isoc transfer by setting the new
+UDSL_USE_ISOC flag. The speedtch minidriver gets a new module
+parameter enable_isoc (defaults to false), plus some logic that
+checks for the existence of an isoc receive endpoint (not all
+speedtouch modems have one).
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/cxacru.c | 4 +-
+ drivers/usb/atm/speedtch.c | 82 ++++++++++++++++++++++++++++++++++---------
+ drivers/usb/atm/ueagle-atm.c | 4 +-
+ drivers/usb/atm/usbatm.c | 30 +++++++--------
+ drivers/usb/atm/usbatm.h | 7 ++-
+ drivers/usb/atm/xusbatm.c | 4 +-
+ 6 files changed, 92 insertions(+), 39 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
++++ gregkh-2.6/drivers/usb/atm/cxacru.c
+@@ -836,8 +836,8 @@ static struct usbatm_driver cxacru_drive
+ .heavy_init = cxacru_heavy_init,
+ .unbind = cxacru_unbind,
+ .atm_start = cxacru_atm_start,
+- .in = CXACRU_EP_DATA,
+- .out = CXACRU_EP_DATA,
++ .bulk_in = CXACRU_EP_DATA,
++ .bulk_out = CXACRU_EP_DATA,
+ .rx_padding = 3,
+ .tx_padding = 11,
+ };
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -35,6 +35,8 @@
+ #include <linux/slab.h>
+ #include <linux/stat.h>
+ #include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/usb_ch9.h>
+ #include <linux/workqueue.h>
+
+ #include "usbatm.h"
+@@ -66,24 +68,33 @@ static const char speedtch_driver_name[]
+
+ #define RESUBMIT_DELAY 1000 /* milliseconds */
+
+-#define DEFAULT_ALTSETTING 1
++#define DEFAULT_BULK_ALTSETTING 1
++#define DEFAULT_ISOC_ALTSETTING 2
+ #define DEFAULT_DL_512_FIRST 0
++#define DEFAULT_ENABLE_ISOC 0
+ #define DEFAULT_SW_BUFFERING 0
+
+-static int altsetting = DEFAULT_ALTSETTING;
++static unsigned int altsetting = 0; /* zero means: use the default */
+ static int dl_512_first = DEFAULT_DL_512_FIRST;
++static int enable_isoc = DEFAULT_ENABLE_ISOC;
+ static int sw_buffering = DEFAULT_SW_BUFFERING;
+
+-module_param(altsetting, int, S_IRUGO | S_IWUSR);
++module_param(altsetting, uint, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(altsetting,
+- "Alternative setting for data interface (default: "
+- __MODULE_STRING(DEFAULT_ALTSETTING) ")");
++ "Alternative setting for data interface (bulk_default: "
++ __MODULE_STRING(DEFAULT_BULK_ALTSETTING) "; isoc_default: "
++ __MODULE_STRING(DEFAULT_ISOC_ALTSETTING) ")");
+
+ module_param(dl_512_first, bool, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(dl_512_first,
+ "Read 512 bytes before sending firmware (default: "
+ __MODULE_STRING(DEFAULT_DL_512_FIRST) ")");
+
++module_param(enable_isoc, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(enable_isoc,
++ "Use isochronous transfers if available (default: "
++ __MODULE_STRING(DEFAULT_ENABLE_ISOC) ")");
++
+ module_param(sw_buffering, bool, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(sw_buffering,
+ "Enable software buffering (default: "
+@@ -91,7 +102,8 @@ MODULE_PARM_DESC(sw_buffering,
+
+ #define INTERFACE_DATA 1
+ #define ENDPOINT_INT 0x81
+-#define ENDPOINT_DATA 0x07
++#define ENDPOINT_BULK_DATA 0x07
++#define ENDPOINT_ISOC_DATA 0x07
+ #define ENDPOINT_FIRMWARE 0x05
+
+ #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )
+@@ -687,11 +699,12 @@ static int speedtch_bind(struct usbatm_d
+ const struct usb_device_id *id)
+ {
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+- struct usb_interface *cur_intf;
++ struct usb_interface *cur_intf, *data_intf;
+ struct speedtch_instance_data *instance;
+ int ifnum = intf->altsetting->desc.bInterfaceNumber;
+ int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;
+ int i, ret;
++ int use_isoc;
+
+ usb_dbg(usbatm, "%s entered\n", __func__);
+
+@@ -702,6 +715,11 @@ static int speedtch_bind(struct usbatm_d
+ return -ENODEV;
+ }
+
++ if (!(data_intf = usb_ifnum_to_if(usb_dev, INTERFACE_DATA))) {
++ usb_err(usbatm, "%s: data interface not found!\n", __func__);
++ return -ENODEV;
++ }
++
+ /* claim all interfaces */
+
+ for (i=0; i < num_interfaces; i++) {
+@@ -728,8 +746,9 @@ static int speedtch_bind(struct usbatm_d
+
+ instance->usbatm = usbatm;
+
+- /* altsetting may change at any moment, so take a snapshot */
++ /* altsetting and enable_isoc may change at any moment, so take a snapshot */
+ instance->altsetting = altsetting;
++ use_isoc = enable_isoc;
+
+ if (instance->altsetting)
+ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
+@@ -737,14 +756,44 @@ static int speedtch_bind(struct usbatm_d
+ instance->altsetting = 0; /* fall back to default */
+ }
+
+- if (!instance->altsetting) {
+- if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ALTSETTING)) < 0) {
+- usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ALTSETTING, ret);
+- goto fail_free;
++ if (!instance->altsetting && use_isoc)
++ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) {
++ usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret);
++ use_isoc = 0; /* fall back to bulk */
+ }
+- instance->altsetting = DEFAULT_ALTSETTING;
++
++ if (use_isoc) {
++ const struct usb_host_interface *desc = data_intf->cur_altsetting;
++ const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in;
++ int i;
++
++ use_isoc = 0; /* fall back to bulk if endpoint not found */
++
++ for (i=0; i<desc->desc.bNumEndpoints; i++) {
++ const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
++
++ if ((endpoint_desc->bEndpointAddress == target_address)) {
++ use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
++ USB_ENDPOINT_XFER_ISOC;
++ break;
++ }
++ }
++
++ if (!use_isoc)
++ usb_info(usbatm, "isochronous transfer not supported - using bulk\n");
+ }
+
++ if (!use_isoc && !instance->altsetting)
++ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) {
++ usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret);
++ goto fail_free;
++ }
++
++ if (!instance->altsetting)
++ instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING;
++
++ usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
++
+ INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
+
+ instance->status_checker.timer.function = speedtch_status_poll;
+@@ -771,7 +820,7 @@ static int speedtch_bind(struct usbatm_d
+ 0x12, 0xc0, 0x07, 0x00,
+ instance->scratch_buffer + OFFSET_7, SIZE_7, 500);
+
+- usbatm->flags = (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0);
++ usbatm->flags |= (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0);
+
+ usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not");
+
+@@ -817,8 +866,9 @@ static struct usbatm_driver speedtch_usb
+ .unbind = speedtch_unbind,
+ .atm_start = speedtch_atm_start,
+ .atm_stop = speedtch_atm_stop,
+- .in = ENDPOINT_DATA,
+- .out = ENDPOINT_DATA
++ .bulk_in = ENDPOINT_BULK_DATA,
++ .bulk_out = ENDPOINT_BULK_DATA,
++ .isoc_in = ENDPOINT_ISOC_DATA
+ };
+
+ static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -1705,8 +1705,8 @@ static struct usbatm_driver uea_usbatm_d
+ .atm_start = uea_atm_open,
+ .unbind = uea_unbind,
+ .heavy_init = uea_heavy,
+- .in = UEA_BULK_DATA_PIPE,
+- .out = UEA_BULK_DATA_PIPE,
++ .bulk_in = UEA_BULK_DATA_PIPE,
++ .bulk_out = UEA_BULK_DATA_PIPE,
+ };
+
+ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -1049,17 +1049,23 @@ int usbatm_usb_probe(struct usb_interfac
+ init_completion(&instance->thread_exited);
+
+ INIT_LIST_HEAD(&instance->vcc_list);
++ skb_queue_head_init(&instance->sndqueue);
+
+ usbatm_init_channel(&instance->rx_channel);
+ usbatm_init_channel(&instance->tx_channel);
+ tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance);
+ tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance);
+- instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in);
+- instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out);
+ instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;
+ instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;
+ instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;
+
++ if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in)
++ instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in);
++ else
++ instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in);
++
++ instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out);
++
+ /* tx buffer size must be a positive multiple of the stride */
+ instance->tx_channel.buf_size = max (instance->tx_channel.stride,
+ snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
+@@ -1080,6 +1086,7 @@ int usbatm_usb_probe(struct usb_interfac
+ num_packets--;
+
+ instance->rx_channel.buf_size = num_packets * maxpacket;
++ instance->rx_channel.packet_size = maxpacket;
+
+ #ifdef DEBUG
+ for (i = 0; i < 2; i++) {
+@@ -1090,22 +1097,16 @@ int usbatm_usb_probe(struct usb_interfac
+ }
+ #endif
+
+- skb_queue_head_init(&instance->sndqueue);
++ /* initialize urbs */
+
+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
+- struct urb *urb;
+ u8 *buffer;
+- unsigned int iso_packets = 0, iso_size = 0;
+ struct usbatm_channel *channel = i < num_rcv_urbs ?
+ &instance->rx_channel : &instance->tx_channel;
++ struct urb *urb;
++ unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
+
+- if (usb_pipeisoc(channel->endpoint)) {
+- /* don't expect iso out endpoints */
+- iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0);
+- iso_size -= iso_size % channel->stride; /* alignment */
+- BUG_ON(!iso_size);
+- iso_packets = (channel->buf_size - 1) / iso_size + 1;
+- }
++ UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
+
+ urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
+ if (!urb) {
+@@ -1132,9 +1133,8 @@ int usbatm_usb_probe(struct usb_interfac
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->number_of_packets = iso_packets;
+ for (j = 0; j < iso_packets; j++) {
+- urb->iso_frame_desc[j].offset = iso_size * j;
+- urb->iso_frame_desc[j].length = min_t(int, iso_size,
+- channel->buf_size - urb->iso_frame_desc[j].offset);
++ urb->iso_frame_desc[j].offset = channel->packet_size * j;
++ urb->iso_frame_desc[j].length = channel->packet_size;
+ }
+ }
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -87,6 +87,7 @@
+ /* flags, set by mini-driver in bind() */
+
+ #define UDSL_SKIP_HEAVY_INIT (1<<0)
++#define UDSL_USE_ISOC (1<<1)
+
+
+ /* mini driver */
+@@ -118,8 +119,9 @@ struct usbatm_driver {
+ /* cleanup ATM device ... can sleep, but can't fail */
+ void (*atm_stop) (struct usbatm_data *, struct atm_dev *);
+
+- int in; /* rx endpoint */
+- int out; /* tx endpoint */
++ int bulk_in; /* bulk rx endpoint */
++ int isoc_in; /* isochronous rx endpoint */
++ int bulk_out; /* bulk tx endpoint */
+
+ unsigned rx_padding;
+ unsigned tx_padding;
+@@ -134,6 +136,7 @@ struct usbatm_channel {
+ int endpoint; /* usb pipe */
+ unsigned int stride; /* ATM cell size + padding */
+ unsigned int buf_size; /* urb buffer size */
++ unsigned int packet_size; /* endpoint maxpacket */
+ spinlock_t lock;
+ struct list_head list;
+ struct tasklet_struct tasklet;
+--- gregkh-2.6.orig/drivers/usb/atm/xusbatm.c
++++ gregkh-2.6/drivers/usb/atm/xusbatm.c
+@@ -210,8 +210,8 @@ static int __init xusbatm_init(void)
+ xusbatm_drivers[i].bind = xusbatm_bind;
+ xusbatm_drivers[i].unbind = xusbatm_unbind;
+ xusbatm_drivers[i].atm_start = xusbatm_atm_start;
+- xusbatm_drivers[i].in = rx_endpoint[i];
+- xusbatm_drivers[i].out = tx_endpoint[i];
++ xusbatm_drivers[i].bulk_in = rx_endpoint[i];
++ xusbatm_drivers[i].bulk_out = tx_endpoint[i];
+ xusbatm_drivers[i].rx_padding = rx_padding[i];
+ xusbatm_drivers[i].tx_padding = tx_padding[i];
+ }
diff --git a/usb/usbatm-bump-version-numbers.patch b/usb/usbatm-bump-version-numbers.patch
new file mode 100644
index 0000000000000..be4379a8570b8
--- /dev/null
+++ b/usb/usbatm-bump-version-numbers.patch
@@ -0,0 +1,37 @@
+From baldrick@free.fr Fri Jan 13 02:08:14 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 12/13] USBATM: bump version numbers
+Date: Fri, 13 Jan 2006 11:08:05 +0100
+Message-Id: <200601131108.06255.baldrick@free.fr>
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/speedtch.c | 2 +-
+ drivers/usb/atm/usbatm.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -42,7 +42,7 @@
+ #include "usbatm.h"
+
+ #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
+-#define DRIVER_VERSION "1.9"
++#define DRIVER_VERSION "1.10"
+ #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION
+
+ static const char speedtch_driver_name[] = "speedtch";
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -92,7 +92,7 @@ static int usbatm_print_packet(const uns
+ #endif
+
+ #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
+-#define DRIVER_VERSION "1.9"
++#define DRIVER_VERSION "1.10"
+ #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
+
+ static const char usbatm_driver_name[] = "usbatm";
diff --git a/usb/usbatm-eilseq-workaround.patch b/usb/usbatm-eilseq-workaround.patch
new file mode 100644
index 0000000000000..caad2738b9502
--- /dev/null
+++ b/usb/usbatm-eilseq-workaround.patch
@@ -0,0 +1,44 @@
+From baldrick@free.fr Fri Jan 13 02:13:02 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 13/13] USBATM: -EILSEQ workaround
+Date: Fri, 13 Jan 2006 11:12:58 +0100
+Message-Id: <200601131112.59414.baldrick@free.fr>
+
+Don't throttle on -EILSEQ urb status if requested by a minidriver.
+It seems the ueagle modems are buggy, giving -EILSEQ when they
+have no data to send. The ueagle change will be sent separately
+by the ueagle guys. Patch by Matthieu Castet.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/usbatm.c | 5 ++++-
+ drivers/usb/atm/usbatm.h | 1 +
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -270,7 +270,10 @@ static void usbatm_complete(struct urb *
+
+ spin_unlock_irqrestore(&channel->lock, flags);
+
+- if (unlikely(urb->status)) {
++ if (unlikely(urb->status) &&
++ (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
++ urb->status != -EILSEQ ))
++ {
+ if (printk_ratelimit())
+ atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
+ __func__, urb, urb->status);
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -88,6 +88,7 @@
+
+ #define UDSL_SKIP_HEAVY_INIT (1<<0)
+ #define UDSL_USE_ISOC (1<<1)
++#define UDSL_IGNORE_EILSEQ (1<<2)
+
+
+ /* mini driver */
diff --git a/usb/usbatm-handle-urbs-containing-partial-cells.patch b/usb/usbatm-handle-urbs-containing-partial-cells.patch
new file mode 100644
index 0000000000000..f9dbeea887820
--- /dev/null
+++ b/usb/usbatm-handle-urbs-containing-partial-cells.patch
@@ -0,0 +1,394 @@
+From baldrick@free.fr Fri Jan 13 02:06:55 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 11/13] USBATM: handle urbs containing partial cells
+Date: Fri, 13 Jan 2006 11:06:46 +0100
+Message-Id: <200601131106.47262.baldrick@free.fr>
+
+The receive logic has always assumed that urbs contain an integral
+number of ATM cells, which is a bit naughty, though it never caused
+any problems with bulk transfers. Isochronous urbs spank us soundly
+for this. Fixed thanks to this patch, mostly by Stanislaw Gruszka.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/usbatm.c | 275 ++++++++++++++++++++++++++++++-----------------
+ drivers/usb/atm/usbatm.h | 7 +
+ 2 files changed, 184 insertions(+), 98 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -296,126 +296,159 @@ static inline struct usbatm_vcc_data *us
+ return NULL;
+ }
+
+-static void usbatm_extract_cells(struct usbatm_data *instance,
+- unsigned char *source, unsigned int avail_data)
++static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char *source)
+ {
+- struct usbatm_vcc_data *cached_vcc = NULL;
+ struct atm_vcc *vcc;
+ struct sk_buff *sarb;
+- unsigned int stride = instance->rx_channel.stride;
+- int vci, cached_vci = 0;
+- short vpi, cached_vpi = 0;
+- u8 pti;
++ short vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);
++ int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
++ u8 pti = ((source[3] & 0xe) >> 1);
+
+- for (; avail_data >= stride; avail_data -= stride, source += stride) {
+- vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);
+- vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
+- pti = ((source[3] & 0xe) >> 1);
++ vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
+
+- vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
++ if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
++ instance->cached_vpi = vpi;
++ instance->cached_vci = vci;
+
+- if ((vci != cached_vci) || (vpi != cached_vpi)) {
+- cached_vpi = vpi;
+- cached_vci = vci;
++ instance->cached_vcc = usbatm_find_vcc(instance, vpi, vci);
+
+- cached_vcc = usbatm_find_vcc(instance, vpi, vci);
++ if (!instance->cached_vcc)
++ atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
++ }
+
+- if (!cached_vcc)
+- atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
+- }
++ if (!instance->cached_vcc)
++ return;
+
+- if (!cached_vcc)
+- continue;
++ vcc = instance->cached_vcc->vcc;
+
+- vcc = cached_vcc->vcc;
++ /* OAM F5 end-to-end */
++ if (pti == ATM_PTI_E2EF5) {
++ if (printk_ratelimit())
++ atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
++ __func__, vpi, vci);
++ atomic_inc(&vcc->stats->rx_err);
++ return;
++ }
+
+- /* OAM F5 end-to-end */
+- if (pti == ATM_PTI_E2EF5) {
+- if (printk_ratelimit())
+- atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
+- __func__, vpi, vci);
++ sarb = instance->cached_vcc->sarb;
++
++ if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
++ atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
++ __func__, sarb->len, vcc);
++ /* discard cells already received */
++ skb_trim(sarb, 0);
++ UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
++ }
++
++ memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
++ __skb_put(sarb, ATM_CELL_PAYLOAD);
++
++ if (pti & 1) {
++ struct sk_buff *skb;
++ unsigned int length;
++ unsigned int pdu_length;
++
++ length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
++
++ /* guard against overflow */
++ if (length > ATM_MAX_AAL5_PDU) {
++ atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
++ __func__, length, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+- continue;
++ goto out;
+ }
+
+- sarb = cached_vcc->sarb;
++ pdu_length = usbatm_pdu_length(length);
+
+- if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
+- atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
+- __func__, sarb->len, vcc);
+- /* discard cells already received */
+- skb_trim(sarb, 0);
+- UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
+- }
+-
+- memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
+- __skb_put(sarb, ATM_CELL_PAYLOAD);
+-
+- if (pti & 1) {
+- struct sk_buff *skb;
+- unsigned int length;
+- unsigned int pdu_length;
+-
+- length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
+-
+- /* guard against overflow */
+- if (length > ATM_MAX_AAL5_PDU) {
+- atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
+- __func__, length, vcc);
+- atomic_inc(&vcc->stats->rx_err);
+- goto out;
+- }
++ if (sarb->len < pdu_length) {
++ atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
++ __func__, pdu_length, sarb->len, vcc);
++ atomic_inc(&vcc->stats->rx_err);
++ goto out;
++ }
+
+- pdu_length = usbatm_pdu_length(length);
++ if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
++ atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
++ __func__, vcc);
++ atomic_inc(&vcc->stats->rx_err);
++ goto out;
++ }
+
+- if (sarb->len < pdu_length) {
+- atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
+- __func__, pdu_length, sarb->len, vcc);
+- atomic_inc(&vcc->stats->rx_err);
+- goto out;
+- }
++ vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
+
+- if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
+- atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
+- __func__, vcc);
+- atomic_inc(&vcc->stats->rx_err);
+- goto out;
+- }
++ if (!(skb = dev_alloc_skb(length))) {
++ if (printk_ratelimit())
++ atm_err(instance, "%s: no memory for skb (length: %u)!\n",
++ __func__, length);
++ atomic_inc(&vcc->stats->rx_drop);
++ goto out;
++ }
+
+- vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
++ vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
+
+- if (!(skb = dev_alloc_skb(length))) {
+- if (printk_ratelimit())
+- atm_err(instance, "%s: no memory for skb (length: %u)!\n",
+- __func__, length);
+- atomic_inc(&vcc->stats->rx_drop);
+- goto out;
+- }
++ if (!atm_charge(vcc, skb->truesize)) {
++ atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
++ __func__, skb->truesize);
++ dev_kfree_skb_any(skb);
++ goto out; /* atm_charge increments rx_drop */
++ }
+
+- vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
++ memcpy(skb->data, sarb->tail - pdu_length, length);
++ __skb_put(skb, length);
+
+- if (!atm_charge(vcc, skb->truesize)) {
+- atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
+- __func__, skb->truesize);
+- dev_kfree_skb_any(skb);
+- goto out; /* atm_charge increments rx_drop */
+- }
++ vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
++ __func__, skb, skb->len, skb->truesize);
+
+- memcpy(skb->data, sarb->tail - pdu_length, length);
+- __skb_put(skb, length);
++ PACKETDEBUG(skb->data, skb->len);
+
+- vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
+- __func__, skb, skb->len, skb->truesize);
++ vcc->push(vcc, skb);
+
+- PACKETDEBUG(skb->data, skb->len);
++ atomic_inc(&vcc->stats->rx);
++ out:
++ skb_trim(sarb, 0);
++ }
++}
+
+- vcc->push(vcc, skb);
++static void usbatm_extract_cells(struct usbatm_data *instance,
++ unsigned char *source, unsigned int avail_data)
++{
++ unsigned int stride = instance->rx_channel.stride;
++ unsigned int buf_usage = instance->buf_usage;
+
+- atomic_inc(&vcc->stats->rx);
+- out:
+- skb_trim(sarb, 0);
++ /* extract cells from incoming data, taking into account that
++ * the length of avail data may not be a multiple of stride */
++
++ if (buf_usage > 0) {
++ /* we have a partially received atm cell */
++ unsigned char *cell_buf = instance->cell_buf;
++ unsigned int space_left = stride - buf_usage;
++
++ UDSL_ASSERT(buf_usage <= stride);
++
++ if (avail_data >= space_left) {
++ /* add new data and process cell */
++ memcpy(cell_buf + buf_usage, source, space_left);
++ source += space_left;
++ avail_data -= space_left;
++ usbatm_extract_one_cell(instance, cell_buf);
++ instance->buf_usage = 0;
++ } else {
++ /* not enough data to fill the cell */
++ memcpy(cell_buf + buf_usage, source, avail_data);
++ instance->buf_usage = buf_usage + avail_data;
++ return;
+ }
+ }
++
++ for (; avail_data >= stride; avail_data -= stride, source += stride)
++ usbatm_extract_one_cell(instance, source);
++
++ if (avail_data > 0) {
++ /* length was not a multiple of stride -
++ * save remaining data for next call */
++ memcpy(instance->cell_buf, source, avail_data);
++ instance->buf_usage = avail_data;
++ }
+ }
+
+
+@@ -496,16 +529,40 @@ static void usbatm_rx_process(unsigned l
+ vdbg("%s: processing urb 0x%p", __func__, urb);
+
+ if (usb_pipeisoc(urb->pipe)) {
++ unsigned char *merge_start = NULL;
++ unsigned int merge_length = 0;
++ const unsigned int packet_size = instance->rx_channel.packet_size;
+ int i;
+- for (i = 0; i < urb->number_of_packets; i++)
+- if (!urb->iso_frame_desc[i].status)
+- usbatm_extract_cells(instance,
+- (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+- urb->iso_frame_desc[i].actual_length);
+- }
+- else
++
++ for (i = 0; i < urb->number_of_packets; i++) {
++ if (!urb->iso_frame_desc[i].status) {
++ unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
++
++ UDSL_ASSERT(actual_length <= packet_size);
++
++ if (!merge_length)
++ merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
++ merge_length += actual_length;
++ if (merge_length && (actual_length < packet_size)) {
++ usbatm_extract_cells(instance, merge_start, merge_length);
++ merge_length = 0;
++ }
++ } else {
++ atm_rldbg(instance, "%s: status %d in frame %d!\n", __func__, urb->status, i);
++ if (merge_length)
++ usbatm_extract_cells(instance, merge_start, merge_length);
++ merge_length = 0;
++ instance->buf_usage = 0;
++ }
++ }
++
++ if (merge_length)
++ usbatm_extract_cells(instance, merge_start, merge_length);
++ } else
+ if (!urb->status)
+ usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length);
++ else
++ instance->buf_usage = 0;
+
+ if (usbatm_submit_urb(urb))
+ return;
+@@ -797,6 +854,9 @@ static int usbatm_atm_open(struct atm_vc
+ vcc->dev_data = new;
+
+ tasklet_disable(&instance->rx_channel.tasklet);
++ instance->cached_vcc = new;
++ instance->cached_vpi = vpi;
++ instance->cached_vci = vci;
+ list_add(&new->list, &instance->vcc_list);
+ tasklet_enable(&instance->rx_channel.tasklet);
+
+@@ -836,6 +896,11 @@ static void usbatm_atm_close(struct atm_
+ down(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
+
+ tasklet_disable(&instance->rx_channel.tasklet);
++ if (instance->cached_vcc == vcc_data) {
++ instance->cached_vcc = NULL;
++ instance->cached_vpi = ATM_VPI_UNSPEC;
++ instance->cached_vci = ATM_VCI_UNSPEC;
++ }
+ list_del(&vcc_data->list);
+ tasklet_enable(&instance->rx_channel.tasklet);
+
+@@ -1146,6 +1211,16 @@ int usbatm_usb_probe(struct usb_interfac
+ __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
+ }
+
++ instance->cached_vpi = ATM_VPI_UNSPEC;
++ instance->cached_vci = ATM_VCI_UNSPEC;
++ instance->cell_buf = kmalloc(instance->rx_channel.stride, GFP_KERNEL);
++
++ if (!instance->cell_buf) {
++ dev_err(dev, "%s: no memory for cell buffer!\n", __func__);
++ error = -ENOMEM;
++ goto fail_unbind;
++ }
++
+ if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) {
+ error = usbatm_heavy_init(instance);
+ } else {
+@@ -1165,6 +1240,8 @@ int usbatm_usb_probe(struct usb_interfac
+ if (instance->driver->unbind)
+ instance->driver->unbind(instance, intf);
+ fail_free:
++ kfree(instance->cell_buf);
++
+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
+ if (instance->urbs[i])
+ kfree(instance->urbs[i]->transfer_buffer);
+@@ -1236,6 +1313,8 @@ void usbatm_usb_disconnect(struct usb_in
+ usb_free_urb(instance->urbs[i]);
+ }
+
++ kfree(instance->cell_buf);
++
+ /* ATM finalize */
+ if (instance->atm_dev)
+ atm_dev_deregister(instance->atm_dev);
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -187,6 +187,13 @@ struct usbatm_data {
+ struct sk_buff_head sndqueue;
+ struct sk_buff *current_skb; /* being emptied */
+
++ struct usbatm_vcc_data *cached_vcc;
++ int cached_vci;
++ short cached_vpi;
++
++ unsigned char *cell_buf; /* holds partial rx cell */
++ unsigned int buf_usage;
++
+ struct urb *urbs[0];
+ };
+
diff --git a/usb/usbatm-kzalloc-conversion.patch b/usb/usbatm-kzalloc-conversion.patch
new file mode 100644
index 0000000000000..f59b73331dd01
--- /dev/null
+++ b/usb/usbatm-kzalloc-conversion.patch
@@ -0,0 +1,89 @@
+From baldrick@free.fr Fri Jan 13 00:38:21 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 04/13] USBATM: kzalloc conversion
+Date: Fri, 13 Jan 2006 09:38:22 +0100
+Message-Id: <200601130938.22715.baldrick@free.fr>
+
+Convert kmalloc + memset to kzalloc.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/cxacru.c | 4 +---
+ drivers/usb/atm/speedtch.c | 4 +---
+ drivers/usb/atm/usbatm.c | 8 +++-----
+ 3 files changed, 5 insertions(+), 11 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
++++ gregkh-2.6/drivers/usb/atm/cxacru.c
+@@ -673,14 +673,12 @@ static int cxacru_bind(struct usbatm_dat
+ int ret;
+
+ /* instance init */
+- instance = kmalloc(sizeof(*instance), GFP_KERNEL);
++ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+ if (!instance) {
+ dbg("cxacru_bind: no memory for instance data");
+ return -ENOMEM;
+ }
+
+- memset(instance, 0, sizeof(*instance));
+-
+ instance->usbatm = usbatm_instance;
+ instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
+
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -715,7 +715,7 @@ static int speedtch_bind(struct usbatm_d
+ }
+ }
+
+- instance = kmalloc(sizeof(*instance), GFP_KERNEL);
++ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+
+ if (!instance) {
+ usb_err(usbatm, "%s: no memory for instance data!\n", __func__);
+@@ -723,8 +723,6 @@ static int speedtch_bind(struct usbatm_d
+ goto fail_release;
+ }
+
+- memset(instance, 0, sizeof(struct speedtch_instance_data));
+-
+ instance->usbatm = usbatm;
+
+ INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -763,13 +763,12 @@ static int usbatm_atm_open(struct atm_vc
+ goto fail;
+ }
+
+- if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
++ if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
+ atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+- memset(new, 0, sizeof(struct usbatm_vcc_data));
+ new->vcc = vcc;
+ new->vpi = vpi;
+ new->vci = vci;
+@@ -1066,13 +1065,12 @@ int usbatm_usb_probe(struct usb_interfac
+
+ instance->urbs[i] = urb;
+
+- buffer = kmalloc(channel->buf_size, GFP_KERNEL);
++ /* zero the tx padding to avoid leaking information */
++ buffer = kzalloc(channel->buf_size, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
+ goto fail_unbind;
+ }
+- /* zero the tx padding to avoid leaking information */
+- memset(buffer, 0, channel->buf_size);
+
+ usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,
+ buffer, channel->buf_size, usbatm_complete, channel);
diff --git a/usb/usbatm-measure-buffer-size-in-bytes-force-valid-sizes.patch b/usb/usbatm-measure-buffer-size-in-bytes-force-valid-sizes.patch
new file mode 100644
index 0000000000000..98ca54b834a32
--- /dev/null
+++ b/usb/usbatm-measure-buffer-size-in-bytes-force-valid-sizes.patch
@@ -0,0 +1,280 @@
+From baldrick@free.fr Fri Jan 13 01:52:41 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 09/13] USBATM: measure buffer size in bytes; force valid sizes
+Date: Fri, 13 Jan 2006 10:52:38 +0100
+Message-Id: <200601131052.39257.baldrick@free.fr>
+
+Change the module parameters rcv_buf_size and snd_buf_size to
+specify buffer sizes in bytes rather than ATM cells. Since
+there is some danger that users may not notice this change,
+the parameters are renamed to rcv_buf_bytes etc. The transmit
+buffer needs to be a multiple of the ATM cell size in length,
+while the receive buffer should be a multiple of the endpoint
+maxpacket size (this wasn't enforced before, which causes trouble
+with isochronous transfers), so enforce these restrictions. Now
+that the usbatm probe method inspects the endpoint maxpacket size,
+minidriver bind routines need to set the correct alternate setting
+for the interface in their bind routine. This is the reason for
+the speedtch changes.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/speedtch.c | 30 ++++++++++++---
+ drivers/usb/atm/usbatm.c | 90 +++++++++++++++++++++++++++++----------------
+ 2 files changed, 84 insertions(+), 36 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -99,12 +99,11 @@ static const char usbatm_driver_name[] =
+
+ #define UDSL_MAX_RCV_URBS 16
+ #define UDSL_MAX_SND_URBS 16
+-#define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */
+-#define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */
++#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */
+ #define UDSL_DEFAULT_RCV_URBS 4
+ #define UDSL_DEFAULT_SND_URBS 4
+-#define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */
+-#define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */
++#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
++#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
+
+ #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
+
+@@ -112,8 +111,8 @@ static const char usbatm_driver_name[] =
+
+ static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;
+ static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;
+-static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;
+-static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;
++static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE;
++static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE;
+
+ module_param(num_rcv_urbs, uint, S_IRUGO);
+ MODULE_PARM_DESC(num_rcv_urbs,
+@@ -127,15 +126,15 @@ MODULE_PARM_DESC(num_snd_urbs,
+ __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "
+ __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");
+
+-module_param(rcv_buf_size, uint, S_IRUGO);
+-MODULE_PARM_DESC(rcv_buf_size,
+- "Size of the buffers used for reception in ATM cells (range: 1-"
+- __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: "
++module_param(rcv_buf_bytes, uint, S_IRUGO);
++MODULE_PARM_DESC(rcv_buf_bytes,
++ "Size of the buffers used for reception, in bytes (range: 1-"
++ __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
+ __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");
+
+-module_param(snd_buf_size, uint, S_IRUGO);
+-MODULE_PARM_DESC(snd_buf_size,
+- "Size of the buffers used for transmission in ATM cells (range: 1-"
++module_param(snd_buf_bytes, uint, S_IRUGO);
++MODULE_PARM_DESC(snd_buf_bytes,
++ "Size of the buffers used for transmission, in bytes (range: 1-"
+ __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
+ __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
+
+@@ -430,14 +429,14 @@ static unsigned int usbatm_write_cells(s
+ {
+ struct usbatm_control *ctrl = UDSL_SKB(skb);
+ struct atm_vcc *vcc = ctrl->atm.vcc;
+- unsigned int num_written;
++ unsigned int bytes_written;
+ unsigned int stride = instance->tx_channel.stride;
+
+ vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);
+ UDSL_ASSERT(!(avail_space % stride));
+
+- for (num_written = 0; num_written < avail_space && ctrl->len;
+- num_written += stride, target += stride) {
++ for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
++ bytes_written += stride, target += stride) {
+ unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);
+ unsigned int left = ATM_CELL_PAYLOAD - data_len;
+ u8 *ptr = target;
+@@ -480,7 +479,7 @@ static unsigned int usbatm_write_cells(s
+ ctrl->crc = crc32_be(ctrl->crc, ptr, left);
+ }
+
+- return num_written;
++ return bytes_written;
+ }
+
+
+@@ -524,7 +523,7 @@ static void usbatm_tx_process(unsigned l
+ struct sk_buff *skb = instance->current_skb;
+ struct urb *urb = NULL;
+ const unsigned int buf_size = instance->tx_channel.buf_size;
+- unsigned int num_written = 0;
++ unsigned int bytes_written = 0;
+ u8 *buffer = NULL;
+
+ if (!skb)
+@@ -536,16 +535,16 @@ static void usbatm_tx_process(unsigned l
+ if (!urb)
+ break; /* no more senders */
+ buffer = urb->transfer_buffer;
+- num_written = (urb->status == -EAGAIN) ?
++ bytes_written = (urb->status == -EAGAIN) ?
+ urb->transfer_buffer_length : 0;
+ }
+
+- num_written += usbatm_write_cells(instance, skb,
+- buffer + num_written,
+- buf_size - num_written);
++ bytes_written += usbatm_write_cells(instance, skb,
++ buffer + bytes_written,
++ buf_size - bytes_written);
+
+ vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p",
+- __func__, num_written, skb, urb);
++ __func__, bytes_written, skb, urb);
+
+ if (!UDSL_SKB(skb)->len) {
+ struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;
+@@ -556,8 +555,8 @@ static void usbatm_tx_process(unsigned l
+ skb = skb_dequeue(&instance->sndqueue);
+ }
+
+- if (num_written == buf_size || (!skb && num_written)) {
+- urb->transfer_buffer_length = num_written;
++ if (bytes_written == buf_size || (!skb && bytes_written)) {
++ urb->transfer_buffer_length = bytes_written;
+
+ if (usbatm_submit_urb(urb))
+ break;
+@@ -990,6 +989,7 @@ int usbatm_usb_probe(struct usb_interfac
+ char *buf;
+ int error = -ENOMEM;
+ int i, length;
++ unsigned int maxpacket, num_packets;
+
+ dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
+ __func__, driver->driver_name,
+@@ -1058,10 +1058,38 @@ int usbatm_usb_probe(struct usb_interfac
+ instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out);
+ instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;
+ instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;
+- instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride;
+- instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride;
+ instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;
+
++ /* tx buffer size must be a positive multiple of the stride */
++ instance->tx_channel.buf_size = max (instance->tx_channel.stride,
++ snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
++
++ /* rx buffer size must be a positive multiple of the endpoint maxpacket */
++ maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0);
++
++ if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) {
++ dev_err(dev, "%s: invalid endpoint %02x!\n", __func__,
++ usb_pipeendpoint(instance->rx_channel.endpoint));
++ error = -EINVAL;
++ goto fail_unbind;
++ }
++
++ num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */
++
++ if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE)
++ num_packets--;
++
++ instance->rx_channel.buf_size = num_packets * maxpacket;
++
++#ifdef DEBUG
++ for (i = 0; i < 2; i++) {
++ struct usbatm_channel *channel = i ?
++ &instance->tx_channel : &instance->rx_channel;
++
++ dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);
++ }
++#endif
++
+ skb_queue_head_init(&instance->sndqueue);
+
+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
+@@ -1232,10 +1260,10 @@ static int __init usbatm_usb_init(void)
+
+ if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)
+ || (num_snd_urbs > UDSL_MAX_SND_URBS)
+- || (rcv_buf_size < 1)
+- || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)
+- || (snd_buf_size < 1)
+- || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))
++ || (rcv_buf_bytes < 1)
++ || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE)
++ || (snd_buf_bytes < 1)
++ || (snd_buf_bytes > UDSL_MAX_BUF_SIZE))
+ return -EINVAL;
+
+ return 0;
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -89,6 +89,7 @@ MODULE_PARM_DESC(sw_buffering,
+ "Enable software buffering (default: "
+ __MODULE_STRING(DEFAULT_SW_BUFFERING) ")");
+
++#define INTERFACE_DATA 1
+ #define ENDPOINT_INT 0x81
+ #define ENDPOINT_DATA 0x07
+ #define ENDPOINT_FIRMWARE 0x05
+@@ -98,6 +99,8 @@ MODULE_PARM_DESC(sw_buffering,
+ struct speedtch_instance_data {
+ struct usbatm_data *usbatm;
+
++ unsigned int altsetting;
++
+ struct work_struct status_checker;
+
+ unsigned char last_status;
+@@ -270,6 +273,11 @@ static int speedtch_upload_firmware(stru
+ because we're in our own kernel thread anyway. */
+ msleep_interruptible(1000);
+
++ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
++ usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret);
++ goto out_free;
++ }
++
+ /* Enable software buffering, if requested */
+ if (sw_buffering)
+ speedtch_set_swbuff(instance, 1);
+@@ -586,11 +594,6 @@ static int speedtch_atm_start(struct usb
+
+ atm_dbg(usbatm, "%s entered\n", __func__);
+
+- if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) {
+- atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret);
+- return ret;
+- }
+-
+ /* Set MAC address, it is stored in the serial number */
+ memset(atm_dev->esi, 0, sizeof(atm_dev->esi));
+ if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) {
+@@ -725,6 +728,23 @@ static int speedtch_bind(struct usbatm_d
+
+ instance->usbatm = usbatm;
+
++ /* altsetting may change at any moment, so take a snapshot */
++ instance->altsetting = altsetting;
++
++ if (instance->altsetting)
++ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
++ usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret);
++ instance->altsetting = 0; /* fall back to default */
++ }
++
++ if (!instance->altsetting) {
++ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ALTSETTING)) < 0) {
++ usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ALTSETTING, ret);
++ goto fail_free;
++ }
++ instance->altsetting = DEFAULT_ALTSETTING;
++ }
++
+ INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
+
+ instance->status_checker.timer.function = speedtch_status_poll;
diff --git a/usb/usbatm-remove-.owner.patch b/usb/usbatm-remove-.owner.patch
new file mode 100644
index 0000000000000..78a30bed73599
--- /dev/null
+++ b/usb/usbatm-remove-.owner.patch
@@ -0,0 +1,80 @@
+From baldrick@free.fr Fri Jan 13 00:36:22 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 03/13] USBATM: remove .owner
+Date: Fri, 13 Jan 2006 09:36:20 +0100
+Message-Id: <200601130936.21286.baldrick@free.fr>
+
+Remove the unused .owner field in struct usbatm_driver.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/cxacru.c | 1 -
+ drivers/usb/atm/speedtch.c | 1 -
+ drivers/usb/atm/ueagle-atm.c | 3 +--
+ drivers/usb/atm/usbatm.h | 2 --
+ drivers/usb/atm/xusbatm.c | 1 -
+ 5 files changed, 1 insertion(+), 7 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
++++ gregkh-2.6/drivers/usb/atm/cxacru.c
+@@ -833,7 +833,6 @@ static const struct usb_device_id cxacru
+ MODULE_DEVICE_TABLE(usb, cxacru_usb_ids);
+
+ static struct usbatm_driver cxacru_driver = {
+- .owner = THIS_MODULE,
+ .driver_name = cxacru_driver_name,
+ .bind = cxacru_bind,
+ .heavy_init = cxacru_heavy_init,
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -793,7 +793,6 @@ static void speedtch_unbind(struct usbat
+ ***********/
+
+ static struct usbatm_driver speedtch_usbatm_driver = {
+- .owner = THIS_MODULE,
+ .driver_name = speedtch_driver_name,
+ .bind = speedtch_bind,
+ .heavy_init = speedtch_heavy_init,
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -1629,7 +1629,7 @@ static int uea_bind(struct usbatm_data *
+ if (ifnum != UEA_INTR_IFACE_NO)
+ return -ENODEV;
+
+- usbatm_instance->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);
++ usbatm->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);
+
+ /* interface 1 is for outbound traffic */
+ ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
+@@ -1701,7 +1701,6 @@ static void uea_unbind(struct usbatm_dat
+
+ static struct usbatm_driver uea_usbatm_driver = {
+ .driver_name = "ueagle-atm",
+- .owner = THIS_MODULE,
+ .bind = uea_bind,
+ .atm_start = uea_atm_open,
+ .unbind = uea_unbind,
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -100,8 +100,6 @@ struct usbatm_data;
+ */
+
+ struct usbatm_driver {
+- struct module *owner;
+-
+ const char *driver_name;
+
+ /* init device ... can sleep, or cause probe() failure */
+--- gregkh-2.6.orig/drivers/usb/atm/xusbatm.c
++++ gregkh-2.6/drivers/usb/atm/xusbatm.c
+@@ -166,7 +166,6 @@ static int __init xusbatm_init(void)
+ xusbatm_usb_ids[i].idProduct = product[i];
+
+
+- xusbatm_drivers[i].owner = THIS_MODULE;
+ xusbatm_drivers[i].driver_name = xusbatm_driver_name;
+ xusbatm_drivers[i].bind = xusbatm_bind;
+ xusbatm_drivers[i].unbind = xusbatm_unbind;
diff --git a/usb/usbatm-return-correct-error-code-when-out-of-memory.patch b/usb/usbatm-return-correct-error-code-when-out-of-memory.patch
new file mode 100644
index 0000000000000..d006b5deb5a15
--- /dev/null
+++ b/usb/usbatm-return-correct-error-code-when-out-of-memory.patch
@@ -0,0 +1,34 @@
+From baldrick@free.fr Fri Jan 13 01:07:18 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 07/13] USBATM: return correct error code when out of memory
+Date: Fri, 13 Jan 2006 10:07:08 +0100
+Message-Id: <200601131007.09403.baldrick@free.fr>
+
+We weren't always returning -ENOMEM.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/usbatm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -1081,6 +1081,7 @@ int usbatm_usb_probe(struct usb_interfac
+ urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
+ if (!urb) {
+ dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
++ error = -ENOMEM;
+ goto fail_unbind;
+ }
+
+@@ -1090,6 +1091,7 @@ int usbatm_usb_probe(struct usb_interfac
+ buffer = kzalloc(channel->buf_size, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
++ error = -ENOMEM;
+ goto fail_unbind;
+ }
+
diff --git a/usb/usbatm-semaphore-to-mutex-conversion.patch b/usb/usbatm-semaphore-to-mutex-conversion.patch
new file mode 100644
index 0000000000000..12bc03cec29fe
--- /dev/null
+++ b/usb/usbatm-semaphore-to-mutex-conversion.patch
@@ -0,0 +1,313 @@
+From baldrick@free.fr Fri Jan 13 06:53:18 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 14/13] USBATM: semaphore to mutex conversion
+Cc: Ingo Molnar <mingo@elte.hu>, Arjan van de Ven <arjan@infradead.org>, Jes Sorensen <jes@trained-monkey.org>
+Date: Fri, 13 Jan 2006 15:52:55 +0100
+Message-Id: <200601131552.55795.baldrick@free.fr>
+
+From: Arjan van de Ven <arjan@infradead.org>
+
+This is the usbatm part of the Arjan, Jes and Ingo
+mass semaphore to mutex conversion, reworked to apply on top
+of the patches I just sent to you. This time, with correct
+attribution and signed-off lines.
+
+Signed-off-by: Arjan van de Ven <arjan@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/cxacru.c | 9 +++++----
+ drivers/usb/atm/ueagle-atm.c | 27 ++++++++++++++-------------
+ drivers/usb/atm/usbatm.c | 28 ++++++++++++++--------------
+ drivers/usb/atm/usbatm.h | 3 ++-
+ 4 files changed, 35 insertions(+), 32 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
++++ gregkh-2.6/drivers/usb/atm/cxacru.c
+@@ -36,6 +36,7 @@
+ #include <linux/init.h>
+ #include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */
+ #include <linux/firmware.h>
++#include <linux/mutex.h>
+
+ #include "usbatm.h"
+
+@@ -160,7 +161,7 @@ struct cxacru_data {
+ struct work_struct poll_work;
+
+ /* contol handles */
+- struct semaphore cm_serialize;
++ struct mutex cm_serialize;
+ u8 *rcv_buf;
+ u8 *snd_buf;
+ struct urb *rcv_urb;
+@@ -219,7 +220,7 @@ static int cxacru_cm(struct cxacru_data
+ goto fail;
+ }
+
+- down(&instance->cm_serialize);
++ mutex_lock(&instance->cm_serialize);
+
+ /* submit reading urb before the writing one */
+ init_completion(&instance->rcv_done);
+@@ -288,7 +289,7 @@ static int cxacru_cm(struct cxacru_data
+ ret = offd;
+ dbg("cm %#x", cm);
+ fail:
+- up(&instance->cm_serialize);
++ mutex_unlock(&instance->cm_serialize);
+ return ret;
+ }
+
+@@ -717,7 +718,7 @@ static int cxacru_bind(struct usbatm_dat
+ instance->snd_buf, PAGE_SIZE,
+ cxacru_blocking_completion, &instance->snd_done, 4);
+
+- init_MUTEX(&instance->cm_serialize);
++ mutex_init(&instance->cm_serialize);
+
+ INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);
+
+--- gregkh-2.6.orig/drivers/usb/atm/ueagle-atm.c
++++ gregkh-2.6/drivers/usb/atm/ueagle-atm.c
+@@ -63,6 +63,7 @@
+ #include <linux/ctype.h>
+ #include <linux/kthread.h>
+ #include <linux/version.h>
++#include <linux/mutex.h>
+ #include <asm/unaligned.h>
+
+ #include "usbatm.h"
+@@ -358,7 +359,7 @@ struct intr_pkt {
+ #define INTR_PKT_SIZE 28
+
+ static struct usb_driver uea_driver;
+-static DECLARE_MUTEX(uea_semaphore);
++static DEFINE_MUTEX(uea_mutex);
+ static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
+
+ static int modem_index;
+@@ -1418,13 +1419,13 @@ static ssize_t read_status(struct device
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+- down(&uea_semaphore);
++ mutex_lock(&uea_mutex);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+ ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
+ out:
+- up(&uea_semaphore);
++ mutex_unlock(&uea_mutex);
+ return ret;
+ }
+
+@@ -1434,14 +1435,14 @@ static ssize_t reboot(struct device *dev
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+- down(&uea_semaphore);
++ mutex_lock(&uea_mutex);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+ sc->reset = 1;
+ ret = count;
+ out:
+- up(&uea_semaphore);
++ mutex_unlock(&uea_mutex);
+ return ret;
+ }
+
+@@ -1453,7 +1454,7 @@ static ssize_t read_human_status(struct
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+- down(&uea_semaphore);
++ mutex_lock(&uea_mutex);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+@@ -1473,7 +1474,7 @@ static ssize_t read_human_status(struct
+ break;
+ }
+ out:
+- up(&uea_semaphore);
++ mutex_unlock(&uea_mutex);
+ return ret;
+ }
+
+@@ -1485,7 +1486,7 @@ static ssize_t read_delin(struct device
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+- down(&uea_semaphore);
++ mutex_lock(&uea_mutex);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+@@ -1497,7 +1498,7 @@ static ssize_t read_delin(struct device
+ else
+ ret = sprintf(buf, "GOOD\n");
+ out:
+- up(&uea_semaphore);
++ mutex_unlock(&uea_mutex);
+ return ret;
+ }
+
+@@ -1511,7 +1512,7 @@ static ssize_t read_##name(struct device
+ int ret = -ENODEV; \
+ struct uea_softc *sc; \
+ \
+- down(&uea_semaphore); \
++ mutex_lock(&uea_mutex); \
+ sc = dev_to_uea(dev); \
+ if (!sc) \
+ goto out; \
+@@ -1519,7 +1520,7 @@ static ssize_t read_##name(struct device
+ if (reset) \
+ sc->stats.phy.name = 0; \
+ out: \
+- up(&uea_semaphore); \
++ mutex_unlock(&uea_mutex); \
+ return ret; \
+ } \
+ \
+@@ -1737,9 +1738,9 @@ static void uea_disconnect(struct usb_in
+ * Pre-firmware device has one interface
+ */
+ if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
+- down(&uea_semaphore);
++ mutex_lock(&uea_mutex);
+ usbatm_usb_disconnect(intf);
+- up(&uea_semaphore);
++ mutex_unlock(&uea_mutex);
+ uea_info(usb, "ADSL device removed\n");
+ }
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -823,7 +823,7 @@ static int usbatm_atm_open(struct atm_vc
+ return -EINVAL;
+ }
+
+- down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
++ mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
+
+ if (instance->disconnected) {
+ atm_dbg(instance, "%s: disconnected!\n", __func__);
+@@ -867,7 +867,7 @@ static int usbatm_atm_open(struct atm_vc
+ set_bit(ATM_VF_PARTIAL, &vcc->flags);
+ set_bit(ATM_VF_READY, &vcc->flags);
+
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+
+ atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
+
+@@ -875,7 +875,7 @@ static int usbatm_atm_open(struct atm_vc
+
+ fail:
+ kfree(new);
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+ return ret;
+ }
+
+@@ -896,7 +896,7 @@ static void usbatm_atm_close(struct atm_
+
+ usbatm_cancel_send(instance, vcc);
+
+- down(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
++ mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
+
+ tasklet_disable(&instance->rx_channel.tasklet);
+ if (instance->cached_vcc == vcc_data) {
+@@ -919,7 +919,7 @@ static void usbatm_atm_close(struct atm_
+ clear_bit(ATM_VF_PARTIAL, &vcc->flags);
+ clear_bit(ATM_VF_ADDR, &vcc->flags);
+
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+
+ atm_dbg(instance, "%s successful\n", __func__);
+ }
+@@ -1009,9 +1009,9 @@ static int usbatm_do_heavy_init(void *ar
+ if (!ret)
+ ret = usbatm_atm_init(instance);
+
+- down(&instance->serialize);
++ mutex_lock(&instance->serialize);
+ instance->thread_pid = -1;
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+
+ complete_and_exit(&instance->thread_exited, ret);
+ }
+@@ -1025,9 +1025,9 @@ static int usbatm_heavy_init(struct usba
+ return ret;
+ }
+
+- down(&instance->serialize);
++ mutex_lock(&instance->serialize);
+ instance->thread_pid = ret;
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+
+ wait_for_completion(&instance->thread_started);
+
+@@ -1110,7 +1110,7 @@ int usbatm_usb_probe(struct usb_interfac
+ /* private fields */
+
+ kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */
+- init_MUTEX(&instance->serialize);
++ mutex_init(&instance->serialize);
+
+ instance->thread_pid = -1;
+ init_completion(&instance->thread_started);
+@@ -1273,18 +1273,18 @@ void usbatm_usb_disconnect(struct usb_in
+
+ usb_set_intfdata(intf, NULL);
+
+- down(&instance->serialize);
++ mutex_lock(&instance->serialize);
+ instance->disconnected = 1;
+ if (instance->thread_pid >= 0)
+ kill_proc(instance->thread_pid, SIGTERM, 1);
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+
+ wait_for_completion(&instance->thread_exited);
+
+- down(&instance->serialize);
++ mutex_lock(&instance->serialize);
+ list_for_each_entry(vcc_data, &instance->vcc_list, list)
+ vcc_release_async(vcc_data->vcc, -EPIPE);
+- up(&instance->serialize);
++ mutex_unlock(&instance->serialize);
+
+ tasklet_disable(&instance->rx_channel.tasklet);
+ tasklet_disable(&instance->tx_channel.tasklet);
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -34,6 +34,7 @@
+ #include <linux/list.h>
+ #include <linux/stringify.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+
+ /*
+ #define VERBOSE_DEBUG
+@@ -171,7 +172,7 @@ struct usbatm_data {
+ ********************************/
+
+ struct kref refcount;
+- struct semaphore serialize;
++ struct mutex serialize;
+ int disconnected;
+
+ /* heavy init */
diff --git a/usb/usbatm-shutdown-open-connections-when-disconnected.patch b/usb/usbatm-shutdown-open-connections-when-disconnected.patch
new file mode 100644
index 0000000000000..46af88774bb35
--- /dev/null
+++ b/usb/usbatm-shutdown-open-connections-when-disconnected.patch
@@ -0,0 +1,172 @@
+From baldrick@free.fr Fri Jan 13 01:05:25 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 06/13] USBATM: shutdown open connections when disconnected
+Date: Fri, 13 Jan 2006 10:05:15 +0100
+Message-Id: <200601131005.15690.baldrick@free.fr>
+
+This patch causes vcc_release_async to be applied to any open
+vcc's when the modem is disconnected. This signals a socket
+shutdown, letting the socket user know that the game is up.
+I wrote this patch because of reports that pppd would keep
+connections open forever when the modem is disconnected.
+This patch does not fix that problem, but it's a step in the
+right direction. It doesn't help because the pppoatm module
+doesn't yet monitor state changes on the ATM socket, so simply
+never realises that the ATM connection has gone down (meaning
+it doesn't tell the ppp layer). But at least there is a socket
+state change now. Unfortunately this patch may create problems
+for those rare users like me who use routed IP or some other
+non-ppp connection method that goes via the ATM ARP daemon: the
+daemon is buggy, and with this patch will crash when the modem
+is disconnected. Users with a buggy atmarpd can simply restart
+it after disconnecting the modem.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/usbatm.c | 66 +++++++++++++++++++++++++++++++++--------------
+ drivers/usb/atm/usbatm.h | 1
+ 2 files changed, 48 insertions(+), 19 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -602,8 +602,12 @@ static int usbatm_atm_send(struct atm_vc
+
+ vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);
+
+- if (!instance) {
+- dbg("%s: NULL data!", __func__);
++ /* racy disconnection check - fine */
++ if (!instance || instance->disconnected) {
++#ifdef DEBUG
++ if (printk_ratelimit())
++ printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
++#endif
+ err = -ENODEV;
+ goto fail;
+ }
+@@ -715,15 +719,19 @@ static int usbatm_atm_proc_read(struct a
+ atomic_read(&atm_dev->stats.aal5.rx_err),
+ atomic_read(&atm_dev->stats.aal5.rx_drop));
+
+- if (!left--)
+- switch (atm_dev->signal) {
+- case ATM_PHY_SIG_FOUND:
+- return sprintf(page, "Line up\n");
+- case ATM_PHY_SIG_LOST:
+- return sprintf(page, "Line down\n");
+- default:
+- return sprintf(page, "Line state unknown\n");
+- }
++ if (!left--) {
++ if (instance->disconnected)
++ return sprintf(page, "Disconnected\n");
++ else
++ switch (atm_dev->signal) {
++ case ATM_PHY_SIG_FOUND:
++ return sprintf(page, "Line up\n");
++ case ATM_PHY_SIG_LOST:
++ return sprintf(page, "Line down\n");
++ default:
++ return sprintf(page, "Line state unknown\n");
++ }
++ }
+
+ return 0;
+ }
+@@ -757,6 +765,12 @@ static int usbatm_atm_open(struct atm_vc
+
+ down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
+
++ if (instance->disconnected) {
++ atm_dbg(instance, "%s: disconnected!\n", __func__);
++ ret = -ENODEV;
++ goto fail;
++ }
++
+ if (usbatm_find_vcc(instance, vpi, vci)) {
+ atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);
+ ret = -EADDRINUSE;
+@@ -845,6 +859,13 @@ static void usbatm_atm_close(struct atm_
+ static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
+ void __user * arg)
+ {
++ struct usbatm_data *instance = atm_dev->dev_data;
++
++ if (!instance || instance->disconnected) {
++ dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance");
++ return -ENODEV;
++ }
++
+ switch (cmd) {
+ case ATM_QUERYLOOP:
+ return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;
+@@ -1129,6 +1150,7 @@ void usbatm_usb_disconnect(struct usb_in
+ {
+ struct device *dev = &intf->dev;
+ struct usbatm_data *instance = usb_get_intfdata(intf);
++ struct usbatm_vcc_data *vcc_data;
+ int i;
+
+ dev_dbg(dev, "%s entered\n", __func__);
+@@ -1141,12 +1163,18 @@ void usbatm_usb_disconnect(struct usb_in
+ usb_set_intfdata(intf, NULL);
+
+ down(&instance->serialize);
++ instance->disconnected = 1;
+ if (instance->thread_pid >= 0)
+ kill_proc(instance->thread_pid, SIGTERM, 1);
+ up(&instance->serialize);
+
+ wait_for_completion(&instance->thread_exited);
+
++ down(&instance->serialize);
++ list_for_each_entry(vcc_data, &instance->vcc_list, list)
++ vcc_release_async(vcc_data->vcc, -EPIPE);
++ up(&instance->serialize);
++
+ tasklet_disable(&instance->rx_channel.tasklet);
+ tasklet_disable(&instance->tx_channel.tasklet);
+
+@@ -1156,6 +1184,14 @@ void usbatm_usb_disconnect(struct usb_in
+ del_timer_sync(&instance->rx_channel.delay);
+ del_timer_sync(&instance->tx_channel.delay);
+
++ /* turn usbatm_[rt]x_process into something close to a no-op */
++ /* no need to take the spinlock */
++ INIT_LIST_HEAD(&instance->rx_channel.list);
++ INIT_LIST_HEAD(&instance->tx_channel.list);
++
++ tasklet_enable(&instance->rx_channel.tasklet);
++ tasklet_enable(&instance->tx_channel.tasklet);
++
+ if (instance->atm_dev && instance->driver->atm_stop)
+ instance->driver->atm_stop(instance, instance->atm_dev);
+
+@@ -1164,14 +1200,6 @@ void usbatm_usb_disconnect(struct usb_in
+
+ instance->driver_data = NULL;
+
+- /* turn usbatm_[rt]x_process into noop */
+- /* no need to take the spinlock */
+- INIT_LIST_HEAD(&instance->rx_channel.list);
+- INIT_LIST_HEAD(&instance->tx_channel.list);
+-
+- tasklet_enable(&instance->rx_channel.tasklet);
+- tasklet_enable(&instance->tx_channel.tasklet);
+-
+ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
+ kfree(instance->urbs[i]->transfer_buffer);
+ usb_free_urb(instance->urbs[i]);
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -168,6 +168,7 @@ struct usbatm_data {
+
+ struct kref refcount;
+ struct semaphore serialize;
++ int disconnected;
+
+ /* heavy init */
+ int thread_pid;
diff --git a/usb/usbatm-trivial-modifications.patch b/usb/usbatm-trivial-modifications.patch
new file mode 100644
index 0000000000000..c8e691b175c59
--- /dev/null
+++ b/usb/usbatm-trivial-modifications.patch
@@ -0,0 +1,924 @@
+From baldrick@free.fr Tue Jan 17 02:15:31 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 01/13] USBATM: trivial modifications
+Content-Disposition: inline
+Date: Tue, 17 Jan 2006 11:15:13 +0100
+Message-Id: <200601171115.13698.baldrick@free.fr>
+
+Formatting, changes to variable names, comments, log level changes,
+printk rate limiting.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/atm/cxacru.c | 69 +++++++++++++++---------------
+ drivers/usb/atm/speedtch.c | 53 +++++++++++++----------
+ drivers/usb/atm/usbatm.c | 101 ++++++++++++++++++++++++++-------------------
+ drivers/usb/atm/usbatm.h | 25 +++++++----
+ drivers/usb/atm/xusbatm.c | 23 +++++-----
+ 5 files changed, 153 insertions(+), 118 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/cxacru.c
++++ gregkh-2.6/drivers/usb/atm/cxacru.c
+@@ -352,7 +352,6 @@ static int cxacru_atm_start(struct usbat
+ struct atm_dev *atm_dev)
+ {
+ struct cxacru_data *instance = usbatm_instance->driver_data;
+- struct device *dev = &usbatm_instance->usb_intf->dev;
+ /*
+ struct atm_dev *atm_dev = usbatm_instance->atm_dev;
+ */
+@@ -364,14 +363,14 @@ static int cxacru_atm_start(struct usbat
+ ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,
+ atm_dev->esi, sizeof(atm_dev->esi));
+ if (ret < 0) {
+- dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
++ atm_err(usbatm_instance, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
+ return ret;
+ }
+
+ /* start ADSL */
+ ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
+ if (ret < 0) {
+- dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
++ atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
+ return ret;
+ }
+
+@@ -383,13 +382,13 @@ static int cxacru_atm_start(struct usbat
+ static void cxacru_poll_status(struct cxacru_data *instance)
+ {
+ u32 buf[CXINF_MAX] = {};
+- struct device *dev = &instance->usbatm->usb_intf->dev;
+- struct atm_dev *atm_dev = instance->usbatm->atm_dev;
++ struct usbatm_data *usbatm = instance->usbatm;
++ struct atm_dev *atm_dev = usbatm->atm_dev;
+ int ret;
+
+ ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
+ if (ret < 0) {
+- dev_warn(dev, "poll status: error %d\n", ret);
++ atm_warn(usbatm, "poll status: error %d\n", ret);
+ goto reschedule;
+ }
+
+@@ -400,50 +399,50 @@ static void cxacru_poll_status(struct cx
+ switch (instance->line_status) {
+ case 0:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: down\n");
++ atm_info(usbatm, "ADSL line: down\n");
+ break;
+
+ case 1:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: attemtping to activate\n");
++ atm_info(usbatm, "ADSL line: attempting to activate\n");
+ break;
+
+ case 2:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: training\n");
++ atm_info(usbatm, "ADSL line: training\n");
+ break;
+
+ case 3:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: channel analysis\n");
++ atm_info(usbatm, "ADSL line: channel analysis\n");
+ break;
+
+ case 4:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: exchange\n");
++ atm_info(usbatm, "ADSL line: exchange\n");
+ break;
+
+ case 5:
+ atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
+ atm_dev->signal = ATM_PHY_SIG_FOUND;
+
+- dev_info(dev, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
++ atm_info(usbatm, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
+ buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);
+ break;
+
+ case 6:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: waiting\n");
++ atm_info(usbatm, "ADSL line: waiting\n");
+ break;
+
+ case 7:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+- dev_info(dev, "ADSL line: initializing\n");
++ atm_info(usbatm, "ADSL line: initializing\n");
+ break;
+
+ default:
+ atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
+- dev_info(dev, "Unknown line state %02x\n", instance->line_status);
++ atm_info(usbatm, "Unknown line state %02x\n", instance->line_status);
+ break;
+ }
+ reschedule:
+@@ -504,8 +503,8 @@ static void cxacru_upload_firmware(struc
+ {
+ int ret;
+ int off;
+- struct usb_device *usb_dev = instance->usbatm->usb_dev;
+- struct device *dev = &instance->usbatm->usb_intf->dev;
++ struct usbatm_data *usbatm = instance->usbatm;
++ struct usb_device *usb_dev = usbatm->usb_dev;
+ u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct };
+ u32 val;
+
+@@ -515,7 +514,7 @@ static void cxacru_upload_firmware(struc
+ val = cpu_to_le32(instance->modem_type->pll_f_clk);
+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
+ if (ret) {
+- dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret);
++ usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
+ return;
+ }
+
+@@ -523,7 +522,7 @@ static void cxacru_upload_firmware(struc
+ val = cpu_to_le32(instance->modem_type->pll_b_clk);
+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
+ if (ret) {
+- dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret);
++ usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
+ return;
+ }
+
+@@ -531,14 +530,14 @@ static void cxacru_upload_firmware(struc
+ val = cpu_to_le32(SDRAM_ENA);
+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
+ if (ret) {
+- dev_err(dev, "Enable SDRAM failed: %d\n", ret);
++ usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
+ return;
+ }
+
+ /* Firmware */
+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
+ if (ret) {
+- dev_err(dev, "Firmware upload failed: %d\n", ret);
++ usb_err(usbatm, "Firmware upload failed: %d\n", ret);
+ return;
+ }
+
+@@ -546,7 +545,7 @@ static void cxacru_upload_firmware(struc
+ if (instance->modem_type->boot_rom_patch) {
+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
+ if (ret) {
+- dev_err(dev, "Boot ROM patching failed: %d\n", ret);
++ usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
+ return;
+ }
+ }
+@@ -554,7 +553,7 @@ static void cxacru_upload_firmware(struc
+ /* Signature */
+ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
+ if (ret) {
+- dev_err(dev, "Signature storing failed: %d\n", ret);
++ usb_err(usbatm, "Signature storing failed: %d\n", ret);
+ return;
+ }
+
+@@ -566,7 +565,7 @@ static void cxacru_upload_firmware(struc
+ ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
+ }
+ if (ret) {
+- dev_err(dev, "Passing control to firmware failed: %d\n", ret);
++ usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
+ return;
+ }
+
+@@ -580,7 +579,7 @@ static void cxacru_upload_firmware(struc
+
+ ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
+ if (ret < 0) {
+- dev_err(dev, "modem failed to initialize: %d\n", ret);
++ usb_err(usbatm, "modem failed to initialize: %d\n", ret);
+ return;
+ }
+
+@@ -597,7 +596,7 @@ static void cxacru_upload_firmware(struc
+ ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
+ (u8 *) buf, len, NULL, 0);
+ if (ret < 0) {
+- dev_err(dev, "load config data failed: %d\n", ret);
++ usb_err(usbatm, "load config data failed: %d\n", ret);
+ return;
+ }
+ }
+@@ -608,18 +607,19 @@ static void cxacru_upload_firmware(struc
+ static int cxacru_find_firmware(struct cxacru_data *instance,
+ char* phase, const struct firmware **fw_p)
+ {
+- struct device *dev = &instance->usbatm->usb_intf->dev;
++ struct usbatm_data *usbatm = instance->usbatm;
++ struct device *dev = &usbatm->usb_intf->dev;
+ char buf[16];
+
+ sprintf(buf, "cxacru-%s.bin", phase);
+ dbg("cxacru_find_firmware: looking for %s", buf);
+
+ if (request_firmware(fw_p, buf, dev)) {
+- dev_dbg(dev, "no stage %s firmware found\n", phase);
++ usb_dbg(usbatm, "no stage %s firmware found\n", phase);
+ return -ENOENT;
+ }
+
+- dev_info(dev, "found firmware %s\n", buf);
++ usb_info(usbatm, "found firmware %s\n", buf);
+
+ return 0;
+ }
+@@ -627,20 +627,19 @@ static int cxacru_find_firmware(struct c
+ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
+ struct usb_interface *usb_intf)
+ {
+- struct device *dev = &usbatm_instance->usb_intf->dev;
+ const struct firmware *fw, *bp, *cf;
+ struct cxacru_data *instance = usbatm_instance->driver_data;
+
+ int ret = cxacru_find_firmware(instance, "fw", &fw);
+ if (ret) {
+- dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n");
++ usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
+ return ret;
+ }
+
+ if (instance->modem_type->boot_rom_patch) {
+ ret = cxacru_find_firmware(instance, "bp", &bp);
+ if (ret) {
+- dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n");
++ usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n");
+ release_firmware(fw);
+ return ret;
+ }
+@@ -787,12 +786,12 @@ static const struct usb_device_id cxacru
+ { /* V = Conexant P = ADSL modem (Hasbani project) */
+ USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00
+ },
+- { /* V = Conexant P = ADSL modem (Well PTI-800 */
+- USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00
+- },
+ { /* V = Conexant P = ADSL modem */
+ USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00
+ },
++ { /* V = Conexant P = ADSL modem (Well PTI-800) */
++ USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00
++ },
+ { /* V = Conexant P = ADSL modem */
+ USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00
+ },
+--- gregkh-2.6.orig/drivers/usb/atm/speedtch.c
++++ gregkh-2.6/drivers/usb/atm/speedtch.c
+@@ -205,7 +205,7 @@ static int speedtch_upload_firmware(stru
+ buffer, 0x200, &actual_length, 2000);
+
+ if (ret < 0 && ret != -ETIMEDOUT)
+- usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
++ usb_warn(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
+ else
+ usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret);
+ }
+@@ -219,7 +219,7 @@ static int speedtch_upload_firmware(stru
+ buffer, thislen, &actual_length, DATA_TIMEOUT);
+
+ if (ret < 0) {
+- usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
++ usb_err(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
+ goto out_free;
+ }
+ usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size);
+@@ -232,7 +232,7 @@ static int speedtch_upload_firmware(stru
+ buffer, 0x200, &actual_length, DATA_TIMEOUT);
+
+ if (ret < 0) {
+- usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
++ usb_err(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
+ goto out_free;
+ }
+ usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length);
+@@ -246,7 +246,7 @@ static int speedtch_upload_firmware(stru
+ buffer, thislen, &actual_length, DATA_TIMEOUT);
+
+ if (ret < 0) {
+- usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
++ usb_err(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
+ goto out_free;
+ }
+ }
+@@ -259,7 +259,7 @@ static int speedtch_upload_firmware(stru
+ buffer, 0x200, &actual_length, DATA_TIMEOUT);
+
+ if (ret < 0) {
+- usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
++ usb_err(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
+ goto out_free;
+ }
+
+@@ -285,8 +285,8 @@ out:
+ return ret;
+ }
+
+-static int speedtch_find_firmware(struct usb_interface *intf, int phase,
+- const struct firmware **fw_p)
++static int speedtch_find_firmware(struct usbatm_data *usbatm, struct usb_interface *intf,
++ int phase, const struct firmware **fw_p)
+ {
+ struct device *dev = &intf->dev;
+ const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice);
+@@ -295,24 +295,24 @@ static int speedtch_find_firmware(struct
+ char buf[24];
+
+ sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision);
+- dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
++ usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
+
+ if (request_firmware(fw_p, buf, dev)) {
+ sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision);
+- dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
++ usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
+
+ if (request_firmware(fw_p, buf, dev)) {
+ sprintf(buf, "speedtch-%d.bin", phase);
+- dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
++ usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
+
+ if (request_firmware(fw_p, buf, dev)) {
+- dev_warn(dev, "no stage %d firmware found!\n", phase);
++ usb_err(usbatm, "%s: no stage %d firmware found!\n", __func__, phase);
+ return -ENOENT;
+ }
+ }
+ }
+
+- dev_info(dev, "found stage %d firmware %s\n", phase, buf);
++ usb_info(usbatm, "found stage %d firmware %s\n", phase, buf);
+
+ return 0;
+ }
+@@ -323,15 +323,16 @@ static int speedtch_heavy_init(struct us
+ struct speedtch_instance_data *instance = usbatm->driver_data;
+ int ret;
+
+- if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0)
+- return ret;
++ if ((ret = speedtch_find_firmware(usbatm, intf, 1, &fw1)) < 0)
++ return ret;
+
+- if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) {
++ if ((ret = speedtch_find_firmware(usbatm, intf, 2, &fw2)) < 0) {
+ release_firmware(fw1);
+ return ret;
+ }
+
+- ret = speedtch_upload_firmware(instance, fw1, fw2);
++ if ((ret = speedtch_upload_firmware(instance, fw1, fw2)) < 0)
++ usb_err(usbatm, "%s: firmware upload failed (%d)!\n", __func__, ret);
+
+ release_firmware(fw2);
+ release_firmware(fw1);
+@@ -428,7 +429,9 @@ static void speedtch_check_status(struct
+ int down_speed, up_speed, ret;
+ unsigned char status;
+
++#ifdef VERBOSE_DEBUG
+ atm_dbg(usbatm, "%s entered\n", __func__);
++#endif
+
+ ret = speedtch_read_status(instance);
+ if (ret < 0) {
+@@ -441,9 +444,9 @@ static void speedtch_check_status(struct
+
+ status = buf[OFFSET_7];
+
+- atm_dbg(usbatm, "%s: line state %02x\n", __func__, status);
+-
+ if ((status != instance->last_status) || !status) {
++ atm_dbg(usbatm, "%s: line state 0x%02x\n", __func__, status);
++
+ switch (status) {
+ case 0:
+ atm_dev->signal = ATM_PHY_SIG_LOST;
+@@ -484,7 +487,7 @@ static void speedtch_check_status(struct
+
+ default:
+ atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
+- atm_info(usbatm, "Unknown line state %02x\n", status);
++ atm_info(usbatm, "unknown line state %02x\n", status);
+ break;
+ }
+
+@@ -690,8 +693,10 @@ static int speedtch_bind(struct usbatm_d
+
+ usb_dbg(usbatm, "%s entered\n", __func__);
+
++ /* sanity checks */
++
+ if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
+- usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);
++ usb_err(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);
+ return -ENODEV;
+ }
+
+@@ -704,7 +709,7 @@ static int speedtch_bind(struct usbatm_d
+ ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm);
+
+ if (ret < 0) {
+- usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret);
++ usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, i, ret);
+ speedtch_release_interfaces(usb_dev, i);
+ return ret;
+ }
+@@ -714,7 +719,7 @@ static int speedtch_bind(struct usbatm_d
+ instance = kmalloc(sizeof(*instance), GFP_KERNEL);
+
+ if (!instance) {
+- usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__);
++ usb_err(usbatm, "%s: no memory for instance data!\n", __func__);
+ ret = -ENOMEM;
+ goto fail_release;
+ }
+@@ -754,8 +759,10 @@ static int speedtch_bind(struct usbatm_d
+ usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already");
+
+ if (*need_heavy_init)
+- if ((ret = usb_reset_device(usb_dev)) < 0)
++ if ((ret = usb_reset_device(usb_dev)) < 0) {
++ usb_err(usbatm, "%s: device reset failed (%d)!\n", __func__, ret);
+ goto fail_free;
++ }
+
+ usbatm->driver_data = instance;
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -166,10 +166,10 @@ struct usbatm_control {
+
+ /* ATM */
+
+-static void usbatm_atm_dev_close(struct atm_dev *dev);
++static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
+ static int usbatm_atm_open(struct atm_vcc *vcc);
+ static void usbatm_atm_close(struct atm_vcc *vcc);
+-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);
++static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
+ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
+ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
+
+@@ -234,8 +234,9 @@ static int usbatm_submit_urb(struct urb
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret) {
+- atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
+- __func__, urb, ret);
++ if (printk_ratelimit())
++ atm_warn(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
++ __func__, urb, ret);
+
+ /* consider all errors transient and return the buffer back to the queue */
+ urb->status = -EAGAIN;
+@@ -269,10 +270,13 @@ static void usbatm_complete(struct urb *
+
+ spin_unlock_irqrestore(&channel->lock, flags);
+
+- if (unlikely(urb->status))
++ if (unlikely(urb->status)) {
++ if (printk_ratelimit())
++ atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
++ __func__, urb, urb->status);
+ /* throttle processing in case of an error */
+ mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));
+- else
++ } else
+ tasklet_schedule(&channel->tasklet);
+ }
+
+@@ -284,11 +288,11 @@ static void usbatm_complete(struct urb *
+ static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance,
+ short vpi, int vci)
+ {
+- struct usbatm_vcc_data *vcc;
++ struct usbatm_vcc_data *vcc_data;
+
+- list_for_each_entry(vcc, &instance->vcc_list, list)
+- if ((vcc->vci == vci) && (vcc->vpi == vpi))
+- return vcc;
++ list_for_each_entry(vcc_data, &instance->vcc_list, list)
++ if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi))
++ return vcc_data;
+ return NULL;
+ }
+
+@@ -317,7 +321,7 @@ static void usbatm_extract_cells(struct
+ cached_vcc = usbatm_find_vcc(instance, vpi, vci);
+
+ if (!cached_vcc)
+- atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
++ atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
+ }
+
+ if (!cached_vcc)
+@@ -327,7 +331,9 @@ static void usbatm_extract_cells(struct
+
+ /* OAM F5 end-to-end */
+ if (pti == ATM_PTI_E2EF5) {
+- atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci);
++ if (printk_ratelimit())
++ atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
++ __func__, vpi, vci);
+ atomic_inc(&vcc->stats->rx_err);
+ continue;
+ }
+@@ -335,7 +341,7 @@ static void usbatm_extract_cells(struct
+ sarb = cached_vcc->sarb;
+
+ if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
+- atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
++ atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
+ __func__, sarb->len, vcc);
+ /* discard cells already received */
+ skb_trim(sarb, 0);
+@@ -354,7 +360,7 @@ static void usbatm_extract_cells(struct
+
+ /* guard against overflow */
+ if (length > ATM_MAX_AAL5_PDU) {
+- atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
++ atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
+ __func__, length, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+ goto out;
+@@ -363,14 +369,14 @@ static void usbatm_extract_cells(struct
+ pdu_length = usbatm_pdu_length(length);
+
+ if (sarb->len < pdu_length) {
+- atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
++ atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
+ __func__, pdu_length, sarb->len, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+ goto out;
+ }
+
+ if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
+- atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
++ atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
+ __func__, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+ goto out;
+@@ -379,7 +385,9 @@ static void usbatm_extract_cells(struct
+ vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
+
+ if (!(skb = dev_alloc_skb(length))) {
+- atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length);
++ if (printk_ratelimit())
++ atm_err(instance, "%s: no memory for skb (length: %u)!\n",
++ __func__, length);
+ atomic_inc(&vcc->stats->rx_drop);
+ goto out;
+ }
+@@ -387,7 +395,8 @@ static void usbatm_extract_cells(struct
+ vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
+
+ if (!atm_charge(vcc, skb->truesize)) {
+- atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize);
++ atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
++ __func__, skb->truesize);
+ dev_kfree_skb(skb);
+ goto out; /* atm_charge increments rx_drop */
+ }
+@@ -600,13 +609,13 @@ static int usbatm_atm_send(struct atm_vc
+ }
+
+ if (vcc->qos.aal != ATM_AAL5) {
+- atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
++ atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
+ err = -EINVAL;
+ goto fail;
+ }
+
+ if (skb->len > ATM_MAX_AAL5_PDU) {
+- atm_dbg(instance, "%s: packet too long (%d vs %d)!\n",
++ atm_rldbg(instance, "%s: packet too long (%d vs %d)!\n",
+ __func__, skb->len, ATM_MAX_AAL5_PDU);
+ err = -EINVAL;
+ goto fail;
+@@ -665,16 +674,16 @@ static void usbatm_put_instance(struct u
+ ** ATM **
+ **********/
+
+-static void usbatm_atm_dev_close(struct atm_dev *dev)
++static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
+ {
+- struct usbatm_data *instance = dev->dev_data;
++ struct usbatm_data *instance = atm_dev->dev_data;
+
+ dbg("%s", __func__);
+
+ if (!instance)
+ return;
+
+- dev->dev_data = NULL;
++ atm_dev->dev_data = NULL; /* catch bugs */
+ usbatm_put_instance(instance); /* taken in usbatm_atm_init */
+ }
+
+@@ -735,13 +744,18 @@ static int usbatm_atm_open(struct atm_vc
+ atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
+
+ /* only support AAL5 */
+- if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0)
+- || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
+- atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
++ if ((vcc->qos.aal != ATM_AAL5)) {
++ atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
++ return -EINVAL;
++ }
++
++ /* sanity checks */
++ if ((vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
++ atm_dbg(instance, "%s: max_sdu %d out of range!\n", __func__, vcc->qos.rxtp.max_sdu);
+ return -EINVAL;
+ }
+
+- down(&instance->serialize); /* vs self, usbatm_atm_close */
++ down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
+
+ if (usbatm_find_vcc(instance, vpi, vci)) {
+ atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);
+@@ -750,7 +764,7 @@ static int usbatm_atm_open(struct atm_vc
+ }
+
+ if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
+- atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__);
++ atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+@@ -762,7 +776,7 @@ static int usbatm_atm_open(struct atm_vc
+
+ new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL);
+ if (!new->sarb) {
+- atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__);
++ atm_err(instance, "%s: no memory for SAR buffer!\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+@@ -806,7 +820,7 @@ static void usbatm_atm_close(struct atm_
+
+ usbatm_cancel_send(instance, vcc);
+
+- down(&instance->serialize); /* vs self, usbatm_atm_open */
++ down(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
+
+ tasklet_disable(&instance->rx_channel.tasklet);
+ list_del(&vcc_data->list);
+@@ -829,7 +843,7 @@ static void usbatm_atm_close(struct atm_
+ atm_dbg(instance, "%s successful\n", __func__);
+ }
+
+-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd,
++static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
+ void __user * arg)
+ {
+ switch (cmd) {
+@@ -845,10 +859,13 @@ static int usbatm_atm_init(struct usbatm
+ struct atm_dev *atm_dev;
+ int ret, i;
+
+- /* ATM init */
++ /* ATM init. The ATM initialization scheme suffers from an intrinsic race
++ * condition: callbacks we register can be executed at once, before we have
++ * initialized the struct atm_dev. To protect against this, all callbacks
++ * abort if atm_dev->dev_data is NULL. */
+ atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
+ if (!atm_dev) {
+- usb_dbg(instance, "%s: failed to register ATM device!\n", __func__);
++ usb_err(instance, "%s: failed to register ATM device!\n", __func__);
+ return -1;
+ }
+
+@@ -862,12 +879,13 @@ static int usbatm_atm_init(struct usbatm
+ atm_dev->link_rate = 128 * 1000 / 424;
+
+ if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
+- atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret);
++ atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
+ goto fail;
+ }
+
+- /* ready for ATM callbacks */
+ usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */
++
++ /* ready for ATM callbacks */
+ mb();
+ atm_dev->dev_data = instance;
+
+@@ -915,7 +933,7 @@ static int usbatm_heavy_init(struct usba
+ int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
+
+ if (ret < 0) {
+- usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
++ usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
+ return ret;
+ }
+
+@@ -953,7 +971,7 @@ int usbatm_usb_probe(struct usb_interfac
+ int i, length;
+ int need_heavy;
+
+- dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n",
++ dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
+ __func__, driver->driver_name,
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+@@ -962,7 +980,7 @@ int usbatm_usb_probe(struct usb_interfac
+ /* instance init */
+ instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
+ if (!instance) {
+- dev_dbg(dev, "%s: no memory for instance data!\n", __func__);
++ dev_err(dev, "%s: no memory for instance data!\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -998,7 +1016,7 @@ int usbatm_usb_probe(struct usb_interfac
+ bind:
+ need_heavy = 1;
+ if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) {
+- dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error);
++ dev_err(dev, "%s: bind failed: %d!\n", __func__, error);
+ goto fail_free;
+ }
+
+@@ -1044,7 +1062,7 @@ int usbatm_usb_probe(struct usb_interfac
+
+ urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
+ if (!urb) {
+- dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i);
++ dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
+ goto fail_unbind;
+ }
+
+@@ -1052,9 +1070,10 @@ int usbatm_usb_probe(struct usb_interfac
+
+ buffer = kmalloc(channel->buf_size, GFP_KERNEL);
+ if (!buffer) {
+- dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i);
++ dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
+ goto fail_unbind;
+ }
++ /* zero the tx padding to avoid leaking information */
+ memset(buffer, 0, channel->buf_size);
+
+ usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.h
++++ gregkh-2.6/drivers/usb/atm/usbatm.h
+@@ -24,22 +24,21 @@
+ #ifndef _USBATM_H_
+ #define _USBATM_H_
+
+-#include <linux/config.h>
+-
+-/*
+-#define VERBOSE_DEBUG
+-*/
+-
+ #include <asm/semaphore.h>
+ #include <linux/atm.h>
+ #include <linux/atmdev.h>
+ #include <linux/completion.h>
+ #include <linux/device.h>
++#include <linux/kernel.h>
+ #include <linux/kref.h>
+ #include <linux/list.h>
+ #include <linux/stringify.h>
+ #include <linux/usb.h>
+
++/*
++#define VERBOSE_DEBUG
++*/
++
+ #ifdef DEBUG
+ #define UDSL_ASSERT(x) BUG_ON(!(x))
+ #else
+@@ -52,8 +51,13 @@
+ dev_info(&(instance)->usb_intf->dev , format , ## arg)
+ #define usb_warn(instance, format, arg...) \
+ dev_warn(&(instance)->usb_intf->dev , format , ## arg)
++#ifdef DEBUG
++#define usb_dbg(instance, format, arg...) \
++ dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
++#else
+ #define usb_dbg(instance, format, arg...) \
+- dev_dbg(&(instance)->usb_intf->dev , format , ## arg)
++ do {} while (0)
++#endif
+
+ /* FIXME: move to dev_* once ATM is driver model aware */
+ #define atm_printk(level, instance, format, arg...) \
+@@ -69,9 +73,14 @@
+ #ifdef DEBUG
+ #define atm_dbg(instance, format, arg...) \
+ atm_printk(KERN_DEBUG, instance , format , ## arg)
++#define atm_rldbg(instance, format, arg...) \
++ if (printk_ratelimit()) \
++ atm_printk(KERN_DEBUG, instance , format , ## arg)
+ #else
+ #define atm_dbg(instance, format, arg...) \
+ do {} while (0)
++#define atm_rldbg(instance, format, arg...) \
++ do {} while (0)
+ #endif
+
+
+@@ -171,7 +180,7 @@ struct usbatm_data {
+ struct usbatm_channel tx_channel;
+
+ struct sk_buff_head sndqueue;
+- struct sk_buff *current_skb; /* being emptied */
++ struct sk_buff *current_skb; /* being emptied */
+
+ struct urb *urbs[0];
+ };
+--- gregkh-2.6.orig/drivers/usb/atm/xusbatm.c
++++ gregkh-2.6/drivers/usb/atm/xusbatm.c
+@@ -61,7 +61,7 @@ static int usb_intf_has_ep(const struct
+ return 0;
+ }
+
+-static int xusbatm_bind(struct usbatm_data *usbatm_instance,
++static int xusbatm_bind(struct usbatm_data *usbatm,
+ struct usb_interface *intf, const struct usb_device_id *id,
+ int *need_heavy_init)
+ {
+@@ -72,14 +72,14 @@ static int xusbatm_bind(struct usbatm_da
+ u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];
+ int i, ret;
+
+- usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x"
+- " rx: ep %#x padd %d tx: ep %#x padd %d\n",
++ usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
++ " rx: ep %02x padd %d tx: ep %02x padd %d\n",
+ __func__, drv_ix, vendor[drv_ix], product[drv_ix],
+ rx_endpoint[drv_ix], rx_padding[drv_ix],
+ tx_endpoint[drv_ix], tx_padding[drv_ix]);
+
+ if (!rx_ep_present && !tx_ep_present) {
+- usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
++ usb_dbg(usbatm, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
+ __func__, intf->altsetting->desc.bInterfaceNumber,
+ rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
+ return -ENODEV;
+@@ -93,25 +93,26 @@ static int xusbatm_bind(struct usbatm_da
+
+ if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {
+ ret = usb_driver_claim_interface(&xusbatm_usb_driver,
+- cur_if, usbatm_instance);
++ cur_if, usbatm);
+ if (!ret)
+- usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n",
++ usb_err(usbatm, "%s: failed to claim interface #%d (%d)\n",
+ __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
+ return ret;
+ }
+ }
+
+- usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n",
++ usb_err(usbatm, "%s: no interface has endpoint %#x\n",
+ __func__, searched_ep);
+ return -ENODEV;
+ }
+
+-static void xusbatm_unbind(struct usbatm_data *usbatm_instance,
++static void xusbatm_unbind(struct usbatm_data *usbatm,
+ struct usb_interface *intf)
+ {
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ int i;
+- usb_dbg(usbatm_instance, "%s entered\n", __func__);
++
++ usb_dbg(usbatm, "%s entered\n", __func__);
+
+ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
+ struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
+@@ -120,10 +121,10 @@ static void xusbatm_unbind(struct usbatm
+ }
+ }
+
+-static int xusbatm_atm_start(struct usbatm_data *usbatm_instance,
++static int xusbatm_atm_start(struct usbatm_data *usbatm,
+ struct atm_dev *atm_dev)
+ {
+- atm_dbg(usbatm_instance, "%s entered\n", __func__);
++ atm_dbg(usbatm, "%s entered\n", __func__);
+
+ /* use random MAC as we've no way to get it from the device */
+ random_ether_addr(atm_dev->esi);
diff --git a/usb/usbatm-use-dev_kfree_skb_any-rather-than-dev_kfree_skb.patch b/usb/usbatm-use-dev_kfree_skb_any-rather-than-dev_kfree_skb.patch
new file mode 100644
index 0000000000000..e386638ab3c73
--- /dev/null
+++ b/usb/usbatm-use-dev_kfree_skb_any-rather-than-dev_kfree_skb.patch
@@ -0,0 +1,46 @@
+From baldrick@free.fr Fri Jan 13 01:13:25 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 08/13] USBATM: use dev_kfree_skb_any rather than dev_kfree_skb
+Date: Fri, 13 Jan 2006 10:13:19 +0100
+Message-Id: <200601131013.19986.baldrick@free.fr>
+
+In one spot (usbatm_cancel_send) we were calling dev_kfree_skb with irqs
+disabled. This mistake is just too easy to make, so systematically use
+dev_kfree_skb_any rather than dev_kfree_skb.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/usbatm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/usbatm.c
++++ gregkh-2.6/drivers/usb/atm/usbatm.c
+@@ -72,6 +72,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
++#include <linux/netdevice.h>
+ #include <linux/proc_fs.h>
+ #include <linux/sched.h>
+ #include <linux/signal.h>
+@@ -199,7 +200,7 @@ static inline void usbatm_pop(struct atm
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+- dev_kfree_skb(skb);
++ dev_kfree_skb_any(skb);
+ }
+
+
+@@ -397,7 +398,7 @@ static void usbatm_extract_cells(struct
+ if (!atm_charge(vcc, skb->truesize)) {
+ atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
+ __func__, skb->truesize);
+- dev_kfree_skb(skb);
++ dev_kfree_skb_any(skb);
+ goto out; /* atm_charge increments rx_drop */
+ }
+
diff --git a/usb/usbatm-xusbatm-rewrite.patch b/usb/usbatm-xusbatm-rewrite.patch
new file mode 100644
index 0000000000000..1a8cdfb58efa8
--- /dev/null
+++ b/usb/usbatm-xusbatm-rewrite.patch
@@ -0,0 +1,190 @@
+From baldrick@free.fr Fri Jan 13 00:48:36 2006
+From: Duncan Sands <baldrick@free.fr>
+To: Greg KH <greg@kroah.com>
+Subject: [PATCH 05/13] USBATM: xusbatm rewrite
+Date: Fri, 13 Jan 2006 09:48:36 +0100
+Message-Id: <200601130948.36673.baldrick@free.fr>
+
+The xusbatm driver is for otherwise unsupported modems.
+All it does is grab hold of a user-specified set of
+interfaces - the generic usbatm core methods (hopefully)
+do the rest. As Aurelio Arroyo discovered when he tried
+to use xusbatm (big mistake!), the interface grabbing logic
+was completely borked. Here is a rewrite that works.
+
+Signed-off-by: Duncan Sands <baldrick@free.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/xusbatm.c | 112 +++++++++++++++++++++++++++++++---------------
+ 1 file changed, 76 insertions(+), 36 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/atm/xusbatm.c
++++ gregkh-2.6/drivers/usb/atm/xusbatm.c
+@@ -41,6 +41,8 @@ XUSBATM_PARM(rx_endpoint, unsigned char,
+ XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
+ XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
+ XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
++XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
++XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
+
+ static const char xusbatm_driver_name[] = "xusbatm";
+
+@@ -48,61 +50,94 @@ static struct usbatm_driver xusbatm_driv
+ static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
+ static struct usb_driver xusbatm_usb_driver;
+
+-static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep)
++static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep)
+ {
++ struct usb_host_interface *alt;
++ struct usb_interface *intf;
+ int i, j;
+
+- for (i = 0; i < intf->num_altsetting; i++) {
+- struct usb_host_interface *alt = intf->altsetting;
+- for (j = 0; j < alt->desc.bNumEndpoints; j++)
+- if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep)
+- return 1;
++ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
++ if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
++ for (j = 0; j < alt->desc.bNumEndpoints; j++)
++ if (alt->endpoint[j].desc.bEndpointAddress == ep)
++ return intf;
++ return NULL;
++}
++
++static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev,
++ struct usb_interface *intf, int altsetting, int claim)
++{
++ int ifnum = intf->altsetting->desc.bInterfaceNumber;
++ int ret;
++
++ if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
++ usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
++ return ret;
++ }
++ if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) {
++ usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
++ return ret;
+ }
+ return 0;
+ }
+
++static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
++{
++ if (claimed) {
++ usb_set_intfdata(intf, NULL);
++ usb_driver_release_interface(&xusbatm_usb_driver, intf);
++ }
++}
++
+ static int xusbatm_bind(struct usbatm_data *usbatm,
+ struct usb_interface *intf, const struct usb_device_id *id)
+ {
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ int drv_ix = id - xusbatm_usb_ids;
+- int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]);
+- int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]);
+- u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];
+- int i, ret;
++ int rx_alt = rx_altsetting[drv_ix];
++ int tx_alt = tx_altsetting[drv_ix];
++ struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
++ struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
++ int ret;
+
+ usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
+- " rx: ep %02x padd %d tx: ep %02x padd %d\n",
++ " rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
+ __func__, drv_ix, vendor[drv_ix], product[drv_ix],
+- rx_endpoint[drv_ix], rx_padding[drv_ix],
+- tx_endpoint[drv_ix], tx_padding[drv_ix]);
++ rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
++ tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);
+
+- if (!rx_ep_present && !tx_ep_present) {
+- usb_dbg(usbatm, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
+- __func__, intf->altsetting->desc.bInterfaceNumber,
+- rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
++ if (!rx_intf || !tx_intf) {
++ if (!rx_intf)
++ usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
++ __func__, rx_endpoint[drv_ix], rx_alt);
++ if (!tx_intf)
++ usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
++ __func__, tx_endpoint[drv_ix], tx_alt);
+ return -ENODEV;
+ }
+
+- if (rx_ep_present && tx_ep_present)
+- return 0;
++ if ((rx_intf != intf) && (tx_intf != intf))
++ return -ENODEV;
+
+- for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
+- struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
++ if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
++ usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
++ rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
++ return -EINVAL;
++ }
+
+- if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {
+- ret = usb_driver_claim_interface(&xusbatm_usb_driver,
+- cur_if, usbatm);
+- if (!ret)
+- usb_err(usbatm, "%s: failed to claim interface #%d (%d)\n",
+- __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
+- return ret;
+- }
++ usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
++ rx_intf->altsetting->desc.bInterfaceNumber,
++ tx_intf->altsetting->desc.bInterfaceNumber);
++
++ if ((ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf)))
++ return ret;
++
++ if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
++ xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
++ return ret;
+ }
+
+- usb_err(usbatm, "%s: no interface has endpoint %#x\n",
+- __func__, searched_ep);
+- return -ENODEV;
++ return 0;
+ }
+
+ static void xusbatm_unbind(struct usbatm_data *usbatm,
+@@ -114,9 +149,12 @@ static void xusbatm_unbind(struct usbatm
+ usb_dbg(usbatm, "%s entered\n", __func__);
+
+ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
+- struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
+- usb_set_intfdata(cur_if, NULL);
+- usb_driver_release_interface(&xusbatm_usb_driver, cur_if);
++ struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
++
++ if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
++ usb_set_intfdata(cur_intf, NULL);
++ usb_driver_release_interface(&xusbatm_usb_driver, cur_intf);
++ }
+ }
+ }
+
+@@ -161,11 +199,13 @@ static int __init xusbatm_init(void)
+ }
+
+ for (i = 0; i < num_vendor; i++) {
++ rx_endpoint[i] |= USB_DIR_IN;
++ tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK;
++
+ xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ xusbatm_usb_ids[i].idVendor = vendor[i];
+ xusbatm_usb_ids[i].idProduct = product[i];
+
+-
+ xusbatm_drivers[i].driver_name = xusbatm_driver_name;
+ xusbatm_drivers[i].bind = xusbatm_bind;
+ xusbatm_drivers[i].unbind = xusbatm_unbind;