diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-18 11:28:05 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-18 11:28:05 -0800 |
commit | 7695771e986729e6eae9fac3657668fbf01b19b1 (patch) | |
tree | 04c16c11fcd7cb117fe138738bdbd481fdc53c77 /usb | |
parent | 05f961a7cefc2f1441dcbaef4b175023c44b2342 (diff) | |
download | patches-7695771e986729e6eae9fac3657668fbf01b19b1.tar.gz |
new usb patches and 2.6.16-rc1 refresh
Diffstat (limited to 'usb')
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; |