From 839ab1d4ce4dfd7e6c189391a82c584292488b41 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 26 Apr 2006 14:39:11 -0700 Subject: [PATCH] USB: fix bug in ohci-hcd.c ohci_restart() A loop on a power-lost resume path used the wrong index. I suspect khubd has been working around such bugs. Noticed by Andreas Mohr . Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 544f7589912..73f5a379d9b 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -863,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci) i = ohci->num_ports; while (i--) ohci_writel (ohci, RH_PS_PSS, - &ohci->regs->roothub.portstatus [temp]); + &ohci->regs->roothub.portstatus [i]); ohci_dbg (ohci, "restart complete\n"); } return 0; -- cgit v1.2.3 From 67c752b41a4238c1a2d7eebcd061ff8c1127d3e9 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 28 Apr 2006 18:44:06 +0200 Subject: [PATCH] USBATM: change the default speedtouch iso altsetting The maximum possible bandwidth for a speedtouch modem is about 7Mbaud. You can only get this by using isochronous urbs (enable_isoc=1) and altsetting 3. With the current default altsetting of 2, the modem maxes out at about 4Mbaud. So change the default altsetting to 3 when using isochronous urbs. It would be nice to base the altsetting on the detected line speed, but that's hard given the current design. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/speedtch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 7860c8a5800..956b7a1e8af 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -69,7 +69,7 @@ static const char speedtch_driver_name[] = "speedtch"; #define RESUBMIT_DELAY 1000 /* milliseconds */ #define DEFAULT_BULK_ALTSETTING 1 -#define DEFAULT_ISOC_ALTSETTING 2 +#define DEFAULT_ISOC_ALTSETTING 3 #define DEFAULT_DL_512_FIRST 0 #define DEFAULT_ENABLE_ISOC 0 #define DEFAULT_SW_BUFFERING 0 -- cgit v1.2.3 From 6275cdfa0fe032208937a3567ebb8bcfd42d20b1 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 28 Apr 2006 18:52:16 +0200 Subject: [PATCH] USBATM: fix modinfo output Because of the way stringify works, using an expression like 64 * 1024 for UDSL_MAX_BUF_SIZE results in 64 * 1024 turning up in the modinfo output instead of 65536. So use 65536 directly (this was the only way I found of fixing this). Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index c1211fc037d..546249843b8 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -99,11 +99,11 @@ static const char usbatm_driver_name[] = "usbatm"; #define UDSL_MAX_RCV_URBS 16 #define UDSL_MAX_SND_URBS 16 -#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */ +#define UDSL_MAX_BUF_SIZE 65536 #define UDSL_DEFAULT_RCV_URBS 4 #define UDSL_DEFAULT_SND_URBS 4 -#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */ -#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */ +#define UDSL_DEFAULT_RCV_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */ +#define UDSL_DEFAULT_SND_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */ #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) @@ -135,7 +135,7 @@ MODULE_PARM_DESC(rcv_buf_bytes, 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_MAX_BUF_SIZE) ", default: " __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); -- cgit v1.2.3 From 7e713b825610de9a9584c189c72e2d9f2326359c Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 1 May 2006 14:02:45 -0700 Subject: [PATCH] USB: pegasus fixes (logstorm, suspend) Teach "pegasus" to handle a few of the disconnect fault paths without hundreds of usless syslog messages. Handle the carrier check workqueue entry even if the driver has not been opened. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/pegasus.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 2deb4c01539..7683926a1b6 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -318,6 +318,8 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) set_register(pegasus, PhyCtrl, (indx | PHY_READ)); for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, PhyCtrl, 1, data); + if (ret == -ESHUTDOWN) + goto fail; if (data[0] & PHY_DONE) break; } @@ -326,6 +328,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) *regd = le16_to_cpu(regdi); return ret; } +fail: if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); @@ -354,12 +357,15 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, PhyCtrl, 1, data); + if (ret == -ESHUTDOWN) + goto fail; if (data[0] & PHY_DONE) break; } if (i < REG_TIMEOUT) return ret; +fail: if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return -ETIMEDOUT; @@ -387,6 +393,8 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) ret = get_registers(pegasus, EpromCtrl, 1, &tmp); if (tmp & EPROM_DONE) break; + if (ret == -ESHUTDOWN) + goto fail; } if (i < REG_TIMEOUT) { ret = get_registers(pegasus, EpromData, 2, &retdatai); @@ -394,6 +402,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) return ret; } +fail: if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return -ETIMEDOUT; @@ -433,12 +442,15 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, EpromCtrl, 1, &tmp); + if (ret == -ESHUTDOWN) + goto fail; if (tmp & EPROM_DONE) break; } disable_eprom_write(pegasus); if (i < REG_TIMEOUT) return ret; +fail: if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return -ETIMEDOUT; @@ -1378,9 +1390,8 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message) struct pegasus *pegasus = usb_get_intfdata(intf); netif_device_detach (pegasus->net); + cancel_delayed_work(&pegasus->carrier_check); if (netif_running(pegasus->net)) { - cancel_delayed_work(&pegasus->carrier_check); - usb_kill_urb(pegasus->rx_urb); usb_kill_urb(pegasus->intr_urb); } @@ -1400,10 +1411,9 @@ static int pegasus_resume (struct usb_interface *intf) pegasus->intr_urb->status = 0; pegasus->intr_urb->actual_length = 0; intr_callback(pegasus->intr_urb, NULL); - - queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, - CARRIER_CHECK_DELAY); } + queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, + CARRIER_CHECK_DELAY); return 0; } -- cgit v1.2.3 From db4cefaaea4c6d67cdaebfd315abc791c5c9d22f Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 1 May 2006 22:07:13 -0700 Subject: [PATCH] USB: fix OHCI PM regression This fixes a small regression in USB controller power usage for many OHCI controllers, notably including every non-PCI version of OHCI: on those systems, the runtime autosuspend mechanism is no longer enabled. The change moves to saner defaults. All root hubs are expected to handle remote wakeup (and hence autosuspend), although drivers for buggy silicon may override that default. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fbd938d4ea5..e2e00ba4e1e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1805,6 +1805,12 @@ int usb_add_hcd(struct usb_hcd *hcd, USB_SPEED_FULL; hcd->self.root_hub = rhdev; + /* wakeup flag init defaults to "everything works" for root hubs, + * but drivers can override it in reset() if needed, along with + * recording the overall controller's system wakeup capability. + */ + device_init_wakeup(&rhdev->dev, 1); + /* "reset" is misnamed; its role is now one-time init. the controller * should already have been reset (and boot firmware kicked off etc). */ @@ -1813,13 +1819,6 @@ int usb_add_hcd(struct usb_hcd *hcd, goto err_hcd_driver_setup; } - /* wakeup flag init is in transition; for now we can't rely on PCI to - * initialize these bits properly, so we let reset() override it. - * This init should _precede_ the reset() once PCI behaves. - */ - device_init_wakeup(&rhdev->dev, - device_can_wakeup(hcd->self.controller)); - /* NOTE: root hub and controller capabilities may not be the same */ if (device_can_wakeup(hcd->self.controller) && device_can_wakeup(&hcd->self.root_hub->dev)) -- cgit v1.2.3 From 436f5762bcd4929825a0725d4bc78337e6fc0d8f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 2 May 2006 15:22:41 -0400 Subject: [PATCH] USB: usbcore: don't check the device's power source The choose_configuration() routine contains code the determine the device's power source, so that configurations requiring external power can be ruled out if the device is running on bus power. Unfortunately it turns out that some devices have errors in their config descriptors and other devices don't like the GET_DEVICE_STATUS request. Since that information wasn't used for anything else, this patch (as673) removes the code, leaving only a comment. It fixes bugzilla entry #6448. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0c87f73f293..90b8d43c6b3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1168,19 +1168,9 @@ static inline const char *plural(int n) static int choose_configuration(struct usb_device *udev) { int i; - u16 devstatus; - int bus_powered; int num_configs; struct usb_host_config *c, *best; - /* If this fails, assume the device is bus-powered */ - devstatus = 0; - usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); - le16_to_cpus(&devstatus); - bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0); - dev_dbg(&udev->dev, "device is %s-powered\n", - bus_powered ? "bus" : "self"); - best = NULL; c = udev->config; num_configs = udev->descriptor.bNumConfigurations; @@ -1197,6 +1187,19 @@ static int choose_configuration(struct usb_device *udev) * similar errors in their descriptors. If the next test * were allowed to execute, such configurations would always * be rejected and the devices would not work as expected. + * In the meantime, we run the risk of selecting a config + * that requires external power at a time when that power + * isn't available. It seems to be the lesser of two evils. + * + * Bugzilla #6448 reports a device that appears to crash + * when it receives a GET_DEVICE_STATUS request! We don't + * have any other way to tell whether a device is self-powered, + * but since we don't use that information anywhere but here, + * the call has been removed. + * + * Maybe the GET_DEVICE_STATUS call and the test below can + * be reinstated when device firmwares become more reliable. + * Don't hold your breath. */ #if 0 /* Rule out self-powered configs for a bus-powered device */ -- cgit v1.2.3 From 77ef6c4d6e23653a79eedacdd6d1d0da7083e59c Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Wed, 3 May 2006 00:16:00 -0700 Subject: [PATCH] USB: ub oops in block_uevent In kernel 2.6.16, if a mounted storage device is removed, an oops happens because ub supplies an interface device (and kobject) to the block layer, but neglects to pin it. And apparently, the block layer expects its users to pin device structures. The code in ub was broken this way for years. But the bug was exposed only by 2.6.16 when it started to call block_uevent on close, which traverses device structures (kobjects actually). Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index f73446f580d..c688c25992e 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -536,6 +536,9 @@ static void ub_cleanup(struct ub_dev *sc) kfree(lun); } + usb_set_intfdata(sc->intf, NULL); + usb_put_intf(sc->intf); + usb_put_dev(sc->dev); kfree(sc); } @@ -2221,7 +2224,12 @@ static int ub_probe(struct usb_interface *intf, // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, sc); usb_get_dev(sc->dev); - // usb_get_intf(sc->intf); /* Do we need this? */ + /* + * Since we give the interface struct to the block level through + * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent + * oopses on close after a disconnect (kernels 2.6.16 and up). + */ + usb_get_intf(sc->intf); snprintf(sc->name, 12, DRV_NAME "(%d.%d)", sc->dev->bus->busnum, sc->dev->devnum); @@ -2286,7 +2294,7 @@ static int ub_probe(struct usb_interface *intf, err_dev_desc: usb_set_intfdata(intf, NULL); - // usb_put_intf(sc->intf); + usb_put_intf(sc->intf); usb_put_dev(sc->dev); kfree(sc); err_core: @@ -2461,12 +2469,6 @@ static void ub_disconnect(struct usb_interface *intf) * and no URBs left in transit. */ - usb_set_intfdata(intf, NULL); - // usb_put_intf(sc->intf); - sc->intf = NULL; - usb_put_dev(sc->dev); - sc->dev = NULL; - ub_put(sc); } -- cgit v1.2.3 From 20a0f47e18c646bcc772282512fc59e56b2fc968 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 4 May 2006 11:34:25 +0100 Subject: [PATCH] USB: ftdi_sio: Add support for HCG HF Dual ISO RFID Reader This patch adds support for ACG Identification Technologies GmbH's HF Dual ISO Reader (an RFID tag reader) to the ftdi_sio driver's device ID table. The product ID was supplied by anotonios (anton at goto10 dot org) on the ftdi-usb-sio-devel list and subsequently verified by myself (Ian Abbott). Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 82151207d81..9498da46103 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -498,6 +498,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 2c55a5ea9c9..3e4123f09e0 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -426,6 +426,11 @@ #define PAPOUCH_VID 0x5050 /* Vendor ID */ #define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ +/* + * ACG Identification Technologies GmbH products (http://www.acg.de/). + * Submitted by anton -at- goto10 -dot- org. + */ +#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ -- cgit v1.2.3 From 72a9f958421a519e69b3e7b409948c3a294f4a32 Mon Sep 17 00:00:00 2001 From: Razvan Gavril Date: Thu, 4 May 2006 11:35:49 +0300 Subject: [PATCH] USB: ftdi_sio: add device id for ACT Solutions HomePro ZWave interface Signed-off-by: Razvan Gavril Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9498da46103..986d7622273 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -307,6 +307,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { static struct usb_device_id id_table_combined [] = { + { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 3e4123f09e0..d69a917e768 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -32,6 +32,10 @@ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ +/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */ +#define FTDI_ACTZWAVE_PID 0xF2D0 + + /* www.irtrans.de device */ #define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ -- cgit v1.2.3 From b68f7de02ae380ddb4e5e457e3fe945ddfd0aa08 Mon Sep 17 00:00:00 2001 From: Ken Brush Date: Mon, 8 May 2006 20:24:12 -0500 Subject: [PATCH] USB: Add Sieraa Wireless 580 evdo card to airprime.c This adds the Sierra Wireless card to airprime.c. I tested this on my laptop. Signed-off-by: Ken Brush Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/airprime.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index dbf1f063098..694b205f9b7 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -18,6 +18,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ + { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From 332bbf613868a5d5938ad9fb7436b2beae72d53d Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 5 May 2006 11:07:21 +0200 Subject: [PATCH] USB: add an IBM USB keyboard to the HID_QUIRK_NOGET blacklist After recent changes, the USB keyboard as shipped with IBM pSeries systems does not work anymore, unless the keyboard is replugged after reboot. Adding this model to the blacklist fixes it. Signed-off-by: Olaf Hering Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index f419bd82ab7..435273e7c85 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1557,6 +1557,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_HP 0x03f0 #define USB_DEVICE_ID_HP_USBHUB_KB 0x020c +#define USB_VENDOR_ID_IBM 0x04b3 +#define USB_DEVICE_ID_IBM_USBHUB_KB 0x3005 + #define USB_VENDOR_ID_CREATIVELABS 0x062a #define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 @@ -1681,6 +1684,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET }, { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET }, -- cgit v1.2.3 From 16c23f7d88cbcce491f9370b2846fad66e8ef319 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 9 May 2006 12:37:22 -0700 Subject: [PATCH] USB: Emagic USB firmware loading fixes It's become apparent as machines get faster that the emagic kernel firmware loaders (based on the ezusb loader) have a reset race. a 400MHz TiBook never tripped it, but a 2GHz Pentium M seems to hit it about 30% of the time. The bug is seen as a hung USB box and the kernel error: drivers/usb/misc/emi62.c: emi62_load_firmware - error loading firmware: error = -110 The patch below inserts a delay after deasserting reset to allow the box to settle before a new command is issued. This affects only device startup. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/emi26.c | 4 ++++ drivers/usb/misc/emi62.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 3824df33094..1fd9cb85f4c 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -15,6 +15,7 @@ #include #include #include +#include #define MAX_INTEL_HEX_RECORD_LENGTH 16 typedef struct _INTEL_HEX_RECORD @@ -114,6 +115,7 @@ static int emi26_load_firmware (struct usb_device *dev) /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); + msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI * Note: collect up to 1023 (yes!) bytes and send them with @@ -150,6 +152,7 @@ static int emi26_load_firmware (struct usb_device *dev) goto wraperr; } } + msleep(250); /* let device settle */ /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); @@ -192,6 +195,7 @@ static int emi26_load_firmware (struct usb_device *dev) err("%s - error loading firmware: error = %d", __FUNCTION__, err); goto wraperr; } + msleep(250); /* let device settle */ /* return 1 to fail the driver inialization * and give real driver change to load */ diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 52fea2e08db..fe351371f27 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -15,6 +15,7 @@ #include #include #include +#include #define MAX_INTEL_HEX_RECORD_LENGTH 16 typedef struct _INTEL_HEX_RECORD @@ -123,6 +124,7 @@ static int emi62_load_firmware (struct usb_device *dev) /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); + msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI * Note: collect up to 1023 (yes!) bytes and send them with @@ -166,6 +168,7 @@ static int emi62_load_firmware (struct usb_device *dev) err("%s - error loading firmware: error = %d", __FUNCTION__, err); goto wraperr; } + msleep(250); /* let device settle */ /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -228,6 +231,7 @@ static int emi62_load_firmware (struct usb_device *dev) err("%s - error loading firmware: error = %d", __FUNCTION__, err); goto wraperr; } + msleep(250); /* let device settle */ kfree(buf); -- cgit v1.2.3 From 704936a25bda9bb12e35bb222d5e3f26186dc279 Mon Sep 17 00:00:00 2001 From: Luiz Fernando Capitulino Date: Thu, 11 May 2006 22:34:17 -0300 Subject: [PATCH] usbserial: Fixes use-after-free in serial_open(). If the device is disconnected while serial_open() is executing and either try_module_get() or the device specific open function fails, the kref_put() call in the 'bailout_kref_put' label will free the memory pointed out by 'port'. The subsequent dereferences in the 'bailout_kref_put' label will be invalid. The fix is just to assure kref_put() is called after any 'port' usage. Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 071f86a59c0..d9dceb4f57b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -225,9 +225,9 @@ static int serial_open (struct tty_struct *tty, struct file * filp) bailout_module_put: module_put(serial->type->driver.owner); bailout_kref_put: - kref_put(&serial->kref, destroy_serial); port->open_count = 0; mutex_unlock(&port->mutex); + kref_put(&serial->kref, destroy_serial); return retval; } -- cgit v1.2.3 From 71a84163ca6b4e36744978385e94150af32f9d75 Mon Sep 17 00:00:00 2001 From: Luiz Fernando Capitulino Date: Thu, 11 May 2006 22:34:24 -0300 Subject: [PATCH] usbserial: Fixes leak in serial_open() error path. If serial_open() fails at the port assignment or mutex_lock_interruptible() is interrupted, the 'serial' object will never be freed. We should call kref_put() when those errors happens. Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d9dceb4f57b..9c36f0ece20 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -189,11 +189,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp) portNumber = tty->index - serial->minor; port = serial->port[portNumber]; - if (!port) - return -ENODEV; + if (!port) { + retval = -ENODEV; + goto bailout_kref_put; + } - if (mutex_lock_interruptible(&port->mutex)) - return -ERESTARTSYS; + if (mutex_lock_interruptible(&port->mutex)) { + retval = -ERESTARTSYS; + goto bailout_kref_put; + } ++port->open_count; @@ -209,7 +213,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) * safe because we are called with BKL held */ if (!try_module_get(serial->type->driver.owner)) { retval = -ENODEV; - goto bailout_kref_put; + goto bailout_mutex_unlock; } /* only call the device specific open if this @@ -224,9 +228,10 @@ static int serial_open (struct tty_struct *tty, struct file * filp) bailout_module_put: module_put(serial->type->driver.owner); -bailout_kref_put: +bailout_mutex_unlock: port->open_count = 0; mutex_unlock(&port->mutex); +bailout_kref_put: kref_put(&serial->kref, destroy_serial); return retval; } -- cgit v1.2.3 From 815ddc99dd8108908d14c699a37d0f5974da6def Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 May 2006 11:05:29 -0700 Subject: [PATCH] USB: add ark3116 usb to serial driver Based on Simon's original driver, with some minor code cleanups and tidying by me. Cc: Simon Schulz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 10 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/ark3116.c | 465 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/serial/generic.c | 1 + 4 files changed, 477 insertions(+) create mode 100644 drivers/usb/serial/ark3116.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index f96b73f54bf..5c60be52156 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -71,6 +71,16 @@ config USB_SERIAL_ANYDATA To compile this driver as a module, choose M here: the module will be called anydata. +config USB_SERIAL_ARK3116 + tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)" + depends on USB_SERIAL && EXPERIMENTAL + help + Say Y here if you want to use a ARK Micro 3116 USB to Serial + device. + + To compile this driver as a module, choose M here: the + module will be called ark3116 + config USB_SERIAL_BELKIN tristate "USB Belkin and Peracom Single Port Serial Driver" depends on USB_SERIAL diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 93c21245b1a..5a0960fc9d3 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -13,6 +13,7 @@ usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o +obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c new file mode 100644 index 00000000000..8dec796222a --- /dev/null +++ b/drivers/usb/serial/ark3116.c @@ -0,0 +1,465 @@ +/* + * ark3116 + * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, + * productid=0x0232) (used in a datacable called KQ-U8A) + * + * - based on code by krisfx -> thanks !! + * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457) + * + * - based on logs created by usbsnoopy + * + * Author : Simon Schulz [ark3116_driverauctionant.de] + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include "usb-serial.h" + + +static int debug; + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x6547, 0x0232) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +struct ark3116_private { + spinlock_t lock; + u8 termios_initialized; +}; + +static inline void ARK3116_SND(struct usb_serial *serial, int seq, + __u8 request, __u8 requesttype, + __u16 value, __u16 index) +{ + int result; + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev,0), + request, requesttype, value, index, + NULL,0x00, 1000); + dbg("%03d > ok",seq); +} + +static inline void ARK3116_RCV(struct usb_serial *serial, int seq, + __u8 request, __u8 requesttype, + __u16 value, __u16 index, __u8 expected, + char *buf) +{ + int result; + result = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev,0), + request, requesttype, value, index, + buf, 0x0000001, 1000); + if (result) + dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]); + else + dbg("%03d < 0 bytes", seq); +} + + +static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, + __u8 request, __u8 requesttype, + __u16 value, __u16 index, char *buf) +{ + usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev,0), + request, requesttype, value, index, + buf, 0x0000001, 1000); +} + + +static int ark3116_attach(struct usb_serial *serial) +{ + char *buf; + struct ark3116_private *priv; + int i; + + for (i = 0; i < serial->num_ports; ++i) { + priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL); + if (!priv) + goto cleanup; + memset (priv, 0x00, sizeof (struct ark3116_private)); + spin_lock_init(&priv->lock); + + usb_set_serial_port_data(serial->port[i], priv); + } + + buf = kmalloc(1, GFP_KERNEL); + if (!buf) { + dbg("error kmalloc -> out of mem ?"); + goto cleanup; + } + + /* 3 */ + ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002); + ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001); + ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008); + ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B); + + /* <-- seq7 */ + ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf); + ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003); + ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000); + ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001); + ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003); + + /* <-- seq12 */ + ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf); + ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004); + + /* 14 */ + ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf); + ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004); + + /* 16 */ + ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf); + /* --> seq17 */ + ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004); + + /* <-- seq18 */ + ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf); + + /* --> seq19 */ + ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004); + + + /* <-- seq20 */ + /* seems like serial port status info (RTS, CTS,...) */ + /* returns modem control line status ?! */ + ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf); + + /* set 9600 baud & do some init ?! */ + ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003); + ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000); + ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001); + ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003); + ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf); + ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003); + ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf); + ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003); + + kfree(buf); + return(0); + +cleanup: + for (--i; i>=0; --i) + usb_set_serial_port_data(serial->port[i], NULL); + return -ENOMEM; +} + +static void ark3116_set_termios(struct usb_serial_port *port, + struct termios *old_termios) +{ + struct usb_serial *serial = port->serial; + struct ark3116_private *priv = usb_get_serial_port_data(port); + unsigned int cflag = port->tty->termios->c_cflag; + unsigned long flags; + int baud; + int ark3116_baud; + char *buf; + char config; + + config = 0; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if ((!port->tty) || (!port->tty->termios)) { + dbg("%s - no tty structures", __FUNCTION__); + return; + } + + spin_lock_irqsave(&priv->lock, flags); + if (!priv->termios_initialized) { + *(port->tty->termios) = tty_std_termios; + port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + priv->termios_initialized = 1; + } + spin_unlock_irqrestore(&priv->lock, flags); + + cflag = port->tty->termios->c_cflag; + + /* check that they really want us to change something: */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(port->tty->termios->c_iflag) == + RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg("%s - nothing to change...", __FUNCTION__); + return; + } + } + + buf = kmalloc(1, GFP_KERNEL); + if (!buf) { + dbg("error kmalloc"); + return; + } + + /* set data bit count (8/7/6/5) */ + if (cflag & CSIZE){ + switch (cflag & CSIZE){ + case CS5: + config |= 0x00; + dbg("setting CS5"); + break; + case CS6: + config |= 0x01; + dbg("setting CS6"); + break; + case CS7: + config |= 0x02; + dbg("setting CS7"); + break; + default: + err ("CSIZE was set but not CS5-CS8, using CS8!"); + case CS8: + config |= 0x03; + dbg("setting CS8"); + break; + } + } + + /* set parity (NONE,EVEN,ODD) */ + if (cflag & PARENB){ + if (cflag & PARODD) { + config |= 0x08; + dbg("setting parity to ODD"); + } else { + config |= 0x18; + dbg("setting parity to EVEN"); + } + } else { + dbg("setting parity to NONE"); + } + + /* SET STOPBIT (1/2) */ + if (cflag & CSTOPB) { + config |= 0x04; + dbg ("setting 2 stop bits"); + } else { + dbg ("setting 1 stop bit"); + } + + + /* set baudrate: */ + baud = 0; + switch (cflag & CBAUD){ + case B0: + err("can't set 0baud, using 9600 instead"); + break; + case B75: baud = 75; break; + case B150: baud = 150; break; + case B300: baud = 300; break; + case B600: baud = 600; break; + case B1200: baud = 1200; break; + case B1800: baud = 1800; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + case B9600: baud = 9600; break; + case B19200: baud = 19200; break; + case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + case B230400: baud = 230400; break; + case B460800: baud = 460800; break; + default: + dbg("does not support the baudrate requested (fix it)"); + break; + } + + /* set 9600 as default (if given baudrate is invalid for example) */ + if (baud == 0) + baud = 9600; + + /* + * found by try'n'error, be careful, maybe there are other options + * for multiplicator etc! + */ + if (baud == 460800) + /* strange, for 460800 the formula is wrong + * (dont use round(), then 9600baud is wrong) */ + ark3116_baud = 7; + else + ark3116_baud = 3000000 / baud; + + /* ? */ + ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf); + /* offset = buf[0]; */ + /* offset = 0x03; */ + /* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */ + + + /* set baudrate */ + dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud); + ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003); + ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF) ,0x0000); + ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001); + ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003); + + /* ? */ + ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf); + ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003); + + /* set data bit count, stop bit count & parity: */ + dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config); + ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf); + ARK3116_SND(serial,154,0xFE,0x40,config,0x0003); + + if (cflag & CRTSCTS) + dbg("CRTSCTS not supported by chipset ?!"); + + /* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */ + + kfree(buf); + return; +} + +static int ark3116_open(struct usb_serial_port *port, struct file *filp) +{ + struct termios tmp_termios; + struct usb_serial *serial = port->serial; + char *buf; + int result = 0; + + dbg("%s - port %d", __FUNCTION__, port->number); + + buf = kmalloc(1, GFP_KERNEL); + if (!buf) { + dbg("error kmalloc -> out of mem ?"); + return -ENOMEM; + } + + result = usb_serial_generic_open(port, filp); + if (result) + return result; + + /* open */ + ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf); + + ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003); + ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000); + ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001); + ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003); + + ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf); + ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004); + + ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf); + ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004); + + ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf); + + ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004); + + ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf); + + ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004); + + /* returns different values (control lines ?!) */ + ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf); + + /* initialise termios: */ + if (port->tty) + ark3116_set_termios(port, &tmp_termios); + + kfree(buf); + + return result; + +} + +static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + dbg("ioctl not supported yet..."); + return -ENOIOCTLCMD; +} + +static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file) +{ + struct usb_serial *serial = port->serial; + char *buf; + char temp; + + /* seems like serial port status info (RTS, CTS,...) is stored + * in reg(?) 0x0006 + * pcb connection point 11 = GND -> sets bit4 of response + * pcb connection point 7 = GND -> sets bit6 of response + */ + + buf = kmalloc(1, GFP_KERNEL); + if (!buf) { + dbg("error kmalloc"); + return -ENOMEM; + } + + /* read register: */ + ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf); + temp = buf[0]; + kfree(buf); + + /* i do not really know if bit4=CTS and bit6=DSR... was just a + * quick guess !! + */ + return (temp & (1<<4) ? TIOCM_CTS : 0) | + (temp & (1<<6) ? TIOCM_DSR : 0); +} + +static struct usb_driver ark3116_driver = { + .name = "ark3116", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, +}; + +static struct usb_serial_driver ark3116_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ark3116", + }, + .id_table = id_table, + .num_interrupt_in = 1, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .attach = ark3116_attach, + .set_termios = ark3116_set_termios, + .ioctl = ark3116_ioctl, + .tiocmget = ark3116_tiocmget, + .open = ark3116_open, +}; + +static int __init ark3116_init(void) +{ + int retval; + + retval = usb_serial_register(&ark3116_device); + if (retval) + return retval; + retval = usb_register(&ark3116_driver); + if (retval) + usb_serial_deregister(&ark3116_device); + return retval; +} + +static void __exit ark3116_exit(void) +{ + usb_deregister(&ark3116_driver); + usb_serial_deregister(&ark3116_device); +} + +module_init(ark3116_init); +module_exit(ark3116_exit); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 476cda107f4..c62cc287651 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -138,6 +138,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) return result; } +EXPORT_SYMBOL_GPL(usb_serial_generic_open); static void generic_cleanup (struct usb_serial_port *port) { -- cgit v1.2.3 From df3fccb14ad02c5fabe095a104a0323c223f2833 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 May 2006 08:44:45 +0200 Subject: [PATCH] USB: fix omninet driver bug I introduced this way back in 2.6.13 when adding the port lock logic. This device talks out through different "ports" all at the same time, so the lock logic was wrong, preventing any data from ever being sent properly. Thanks a lot to Bernhard Reiter for being patient and helping with debugging this. Cc: Bernhard Reiter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 4d40704dea2..238033a8709 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -257,14 +257,14 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf return (0); } - spin_lock(&port->lock); - if (port->write_urb_busy) { - spin_unlock(&port->lock); + spin_lock(&wport->lock); + if (wport->write_urb_busy) { + spin_unlock(&wport->lock); dbg("%s - already writing", __FUNCTION__); return 0; } - port->write_urb_busy = 1; - spin_unlock(&port->lock); + wport->write_urb_busy = 1; + spin_unlock(&wport->lock); count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; @@ -283,7 +283,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf wport->write_urb->dev = serial->dev; result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); if (result) { - port->write_urb_busy = 0; + wport->write_urb_busy = 0; err("%s - failed submitting write urb, error %d", __FUNCTION__, result); } else result = count; -- cgit v1.2.3