Commit d72cd3a9 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  USB: pwc : do not pass stack allocated buffers to USB core.
  USB: otg: Fix bug on remove path without transceiver
  USB: correct error handling in cdc-wdm
  USB: removal of tty->low_latency hack dating back to the old serial code
  USB: serial: sierra driver bug fix for composite interface
  USB: gadget: omap_udc uses platform_driver_probe()
  USB: ci13xxx_udc: fix build error
  USB: musb: Prevent multiple includes of musb.h
  USB: pass mem_flags to dma_alloc_coherent
  USB: g_file_storage: fix use-after-free bug when closing files
  USB: ehci-sched.c: EHCI SITD scheduling bugfix
  USB: fix mos7840 problem with minor numbers
  USB: mos7840: add new device id
  USB: musb: fix build when !CONFIG_PM
  USB: musb: Remove my email address from few musb related drivers
  USB: Gadget: MIPS CI13xxx UDC bugfixes
  USB: Unusual Device support for Gold MP3 Player Energy
  USB: serial: fix lifetime and locking problems
parents ff91fad2 6b35ca0d
This diff is collapsed.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* This driver supports USB CDC WCM Device Management. * This driver supports USB CDC WCM Device Management.
* *
* Copyright (c) 2007-2008 Oliver Neukum * Copyright (c) 2007-2009 Oliver Neukum
* *
* Some code taken from cdc-acm.c * Some code taken from cdc-acm.c
* *
...@@ -610,7 +610,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -610,7 +610,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (!buffer) if (!buffer)
goto out; goto out;
while (buflen > 0) { while (buflen > 2) {
if (buffer [1] != USB_DT_CS_INTERFACE) { if (buffer [1] != USB_DT_CS_INTERFACE) {
dev_err(&intf->dev, "skipping garbage\n"); dev_err(&intf->dev, "skipping garbage\n");
goto next_desc; goto next_desc;
...@@ -646,16 +646,18 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -646,16 +646,18 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
spin_lock_init(&desc->iuspin); spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait); init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom; desc->wMaxCommand = maxcom;
/* this will be expanded and needed in hardware endianness */
desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
desc->intf = intf; desc->intf = intf;
INIT_WORK(&desc->rxwork, wdm_rxwork); INIT_WORK(&desc->rxwork, wdm_rxwork);
iface = &intf->altsetting[0]; rv = -EINVAL;
iface = intf->cur_altsetting;
if (iface->desc.bNumEndpoints != 1)
goto err;
ep = &iface->endpoint[0].desc; ep = &iface->endpoint[0].desc;
if (!ep || !usb_endpoint_is_int_in(ep)) { if (!ep || !usb_endpoint_is_int_in(ep))
rv = -EINVAL;
goto err; goto err;
}
desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
...@@ -711,12 +713,19 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -711,12 +713,19 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_set_intfdata(intf, desc); usb_set_intfdata(intf, desc);
rv = usb_register_dev(intf, &wdm_class); rv = usb_register_dev(intf, &wdm_class);
dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
intf->minor - WDM_MINOR_BASE);
if (rv < 0) if (rv < 0)
goto err; goto err3;
else
dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
intf->minor - WDM_MINOR_BASE);
out: out:
return rv; return rv;
err3:
usb_set_intfdata(intf, NULL);
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->bMaxPacketSize0,
desc->inbuf,
desc->response->transfer_dma);
err2: err2:
usb_buffer_free(interface_to_usbdev(desc->intf), usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize, desc->wMaxPacketSize,
......
...@@ -119,7 +119,7 @@ void *hcd_buffer_alloc( ...@@ -119,7 +119,7 @@ void *hcd_buffer_alloc(
if (size <= pool_max [i]) if (size <= pool_max [i])
return dma_pool_alloc(hcd->pool [i], mem_flags, dma); return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
} }
return dma_alloc_coherent(hcd->self.controller, size, dma, 0); return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags);
} }
void hcd_buffer_free( void hcd_buffer_free(
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
* - Gadget API (majority of optional features) * - Gadget API (majority of optional features)
* - Suspend & Remote Wakeup * - Suspend & Remote Wakeup
*/ */
#include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dmapool.h> #include <linux/dmapool.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -142,7 +143,7 @@ static struct { ...@@ -142,7 +143,7 @@ static struct {
#define CAP_DEVICEADDR (0x014UL) #define CAP_DEVICEADDR (0x014UL)
#define CAP_ENDPTLISTADDR (0x018UL) #define CAP_ENDPTLISTADDR (0x018UL)
#define CAP_PORTSC (0x044UL) #define CAP_PORTSC (0x044UL)
#define CAP_DEVLC (0x0B4UL) #define CAP_DEVLC (0x084UL)
#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL) #define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL) #define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL) #define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
...@@ -1986,6 +1987,8 @@ static int ep_enable(struct usb_ep *ep, ...@@ -1986,6 +1987,8 @@ static int ep_enable(struct usb_ep *ep,
do { do {
dbg_event(_usb_addr(mEp), "ENABLE", 0); dbg_event(_usb_addr(mEp), "ENABLE", 0);
mEp->qh[mEp->dir].ptr->cap = 0;
if (mEp->type == USB_ENDPOINT_XFER_CONTROL) if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
mEp->qh[mEp->dir].ptr->cap |= QH_IOS; mEp->qh[mEp->dir].ptr->cap |= QH_IOS;
else if (mEp->type == USB_ENDPOINT_XFER_ISOC) else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
......
...@@ -738,7 +738,6 @@ static struct fsg_dev *the_fsg; ...@@ -738,7 +738,6 @@ static struct fsg_dev *the_fsg;
static struct usb_gadget_driver fsg_driver; static struct usb_gadget_driver fsg_driver;
static void close_backing_file(struct lun *curlun); static void close_backing_file(struct lun *curlun);
static void close_all_backing_files(struct fsg_dev *fsg);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -3593,12 +3592,10 @@ static int fsg_main_thread(void *fsg_) ...@@ -3593,12 +3592,10 @@ static int fsg_main_thread(void *fsg_)
fsg->thread_task = NULL; fsg->thread_task = NULL;
spin_unlock_irq(&fsg->lock); spin_unlock_irq(&fsg->lock);
/* In case we are exiting because of a signal, unregister the /* If we are exiting because of a signal, unregister the
* gadget driver and close the backing file. */ * gadget driver. */
if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) { if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
usb_gadget_unregister_driver(&fsg_driver); usb_gadget_unregister_driver(&fsg_driver);
close_all_backing_files(fsg);
}
/* Let the unbind and cleanup routines know the thread has exited */ /* Let the unbind and cleanup routines know the thread has exited */
complete_and_exit(&fsg->thread_notifier, 0); complete_and_exit(&fsg->thread_notifier, 0);
...@@ -3703,14 +3700,6 @@ static void close_backing_file(struct lun *curlun) ...@@ -3703,14 +3700,6 @@ static void close_backing_file(struct lun *curlun)
} }
} }
static void close_all_backing_files(struct fsg_dev *fsg)
{
int i;
for (i = 0; i < fsg->nluns; ++i)
close_backing_file(&fsg->luns[i]);
}
static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf)
{ {
...@@ -3845,6 +3834,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) ...@@ -3845,6 +3834,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
if (curlun->registered) { if (curlun->registered) {
device_remove_file(&curlun->dev, &dev_attr_ro); device_remove_file(&curlun->dev, &dev_attr_ro);
device_remove_file(&curlun->dev, &dev_attr_file); device_remove_file(&curlun->dev, &dev_attr_file);
close_backing_file(curlun);
device_unregister(&curlun->dev); device_unregister(&curlun->dev);
curlun->registered = 0; curlun->registered = 0;
} }
...@@ -4190,7 +4180,6 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -4190,7 +4180,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
out: out:
fsg->state = FSG_STATE_TERMINATED; // The thread is dead fsg->state = FSG_STATE_TERMINATED; // The thread is dead
fsg_unbind(gadget); fsg_unbind(gadget);
close_all_backing_files(fsg);
complete(&fsg->thread_notifier); complete(&fsg->thread_notifier);
return rc; return rc;
} }
...@@ -4284,7 +4273,6 @@ static void __exit fsg_cleanup(void) ...@@ -4284,7 +4273,6 @@ static void __exit fsg_cleanup(void)
/* Wait for the thread to finish up */ /* Wait for the thread to finish up */
wait_for_completion(&fsg->thread_notifier); wait_for_completion(&fsg->thread_notifier);
close_all_backing_files(fsg);
kref_put(&fsg->ref, fsg_release); kref_put(&fsg->ref, fsg_release);
} }
module_exit(fsg_cleanup); module_exit(fsg_cleanup);
...@@ -3104,7 +3104,6 @@ static int omap_udc_resume(struct platform_device *dev) ...@@ -3104,7 +3104,6 @@ static int omap_udc_resume(struct platform_device *dev)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static struct platform_driver udc_driver = { static struct platform_driver udc_driver = {
.probe = omap_udc_probe,
.remove = __exit_p(omap_udc_remove), .remove = __exit_p(omap_udc_remove),
.suspend = omap_udc_suspend, .suspend = omap_udc_suspend,
.resume = omap_udc_resume, .resume = omap_udc_resume,
...@@ -3122,7 +3121,7 @@ static int __init udc_init(void) ...@@ -3122,7 +3121,7 @@ static int __init udc_init(void)
#endif #endif
"%s\n", driver_desc, "%s\n", driver_desc,
use_dma ? " (dma)" : ""); use_dma ? " (dma)" : "");
return platform_driver_register(&udc_driver); return platform_driver_probe(&udc_driver, omap_udc_probe);
} }
module_init(udc_init); module_init(udc_init);
......
...@@ -323,7 +323,7 @@ static int tt_available ( ...@@ -323,7 +323,7 @@ static int tt_available (
* already scheduled transactions * already scheduled transactions
*/ */
if (125 < usecs) { if (125 < usecs) {
int ufs = (usecs / 125) - 1; int ufs = (usecs / 125);
int i; int i;
for (i = uframe; i < (uframe + ufs) && i < 8; i++) for (i = uframe; i < (uframe + ufs) && i < 8; i++)
if (0 < tt_usecs[i]) { if (0 < tt_usecs[i]) {
......
...@@ -2191,7 +2191,7 @@ static int musb_resume_early(struct platform_device *pdev) ...@@ -2191,7 +2191,7 @@ static int musb_resume_early(struct platform_device *pdev)
#else #else
#define musb_suspend NULL #define musb_suspend NULL
#define musb_resume NULL #define musb_resume_early NULL
#endif #endif
static struct platform_driver musb_driver = { static struct platform_driver musb_driver = {
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Some code has been taken from tusb6010.c * Some code has been taken from tusb6010.c
* Copyrights for that are attributable to: * Copyrights for that are attributable to:
* Copyright (C) 2006 Nokia Corporation * Copyright (C) 2006 Nokia Corporation
* Jarkko Nikula <jarkko.nikula@nokia.com>
* Tony Lindgren <tony@atomide.com> * Tony Lindgren <tony@atomide.com>
* *
* This file is part of the Inventra Controller Driver for Linux. * This file is part of the Inventra Controller Driver for Linux.
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
* TUSB6010 USB 2.0 OTG Dual Role controller * TUSB6010 USB 2.0 OTG Dual Role controller
* *
* Copyright (C) 2006 Nokia Corporation * Copyright (C) 2006 Nokia Corporation
* Jarkko Nikula <jarkko.nikula@nokia.com>
* Tony Lindgren <tony@atomide.com> * Tony Lindgren <tony@atomide.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
* Definitions for TUSB6010 USB 2.0 OTG Dual Role controller * Definitions for TUSB6010 USB 2.0 OTG Dual Role controller
* *
* Copyright (C) 2006 Nokia Corporation * Copyright (C) 2006 Nokia Corporation
* Jarkko Nikula <jarkko.nikula@nokia.com>
* Tony Lindgren <tony@atomide.com> * Tony Lindgren <tony@atomide.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -43,7 +43,8 @@ EXPORT_SYMBOL(otg_get_transceiver); ...@@ -43,7 +43,8 @@ EXPORT_SYMBOL(otg_get_transceiver);
*/ */
void otg_put_transceiver(struct otg_transceiver *x) void otg_put_transceiver(struct otg_transceiver *x)
{ {
put_device(x->dev); if (x)
put_device(x->dev);
} }
EXPORT_SYMBOL(otg_put_transceiver); EXPORT_SYMBOL(otg_put_transceiver);
......
...@@ -175,13 +175,6 @@ static int cyberjack_open(struct tty_struct *tty, ...@@ -175,13 +175,6 @@ static int cyberjack_open(struct tty_struct *tty,
dbg("%s - usb_clear_halt", __func__); dbg("%s - usb_clear_halt", __func__);
usb_clear_halt(port->serial->dev, port->write_urb->pipe); usb_clear_halt(port->serial->dev, port->write_urb->pipe);
/* force low_latency on so that our tty_push actually forces
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
*/
if (tty)
tty->low_latency = 1;
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
priv->rdtodo = 0; priv->rdtodo = 0;
......
...@@ -656,10 +656,6 @@ static int cypress_open(struct tty_struct *tty, ...@@ -656,10 +656,6 @@ static int cypress_open(struct tty_struct *tty,
priv->rx_flags = 0; priv->rx_flags = 0;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/* setting to zero could cause data loss */
if (tty)
tty->low_latency = 1;
/* raise both lines and set termios */ /* raise both lines and set termios */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
priv->line_control = CONTROL_DTR | CONTROL_RTS; priv->line_control = CONTROL_DTR | CONTROL_RTS;
......
...@@ -478,12 +478,6 @@ static void empeg_set_termios(struct tty_struct *tty, ...@@ -478,12 +478,6 @@ static void empeg_set_termios(struct tty_struct *tty,
termios->c_cflag termios->c_cflag
|= CS8; /* character size 8 bits */ |= CS8; /* character size 8 bits */
/*
* Force low_latency on; otherwise the pushes are scheduled;
* this is bad as it opens up the possibility of dropping bytes
* on the floor. We don't want to drop bytes on the floor. :)
*/
tty->low_latency = 1;
tty_encode_baud_rate(tty, 115200, 115200); tty_encode_baud_rate(tty, 115200, 115200);
} }
......
...@@ -973,14 +973,6 @@ static int garmin_open(struct tty_struct *tty, ...@@ -973,14 +973,6 @@ static int garmin_open(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
/*
* Force low_latency on so that our tty_push actually forces the data
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
if (tty)
tty->low_latency = 1;
spin_lock_irqsave(&garmin_data_p->lock, flags); spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->mode = initial_mode; garmin_data_p->mode = initial_mode;
garmin_data_p->count = 0; garmin_data_p->count = 0;
......
...@@ -122,12 +122,6 @@ int usb_serial_generic_open(struct tty_struct *tty, ...@@ -122,12 +122,6 @@ int usb_serial_generic_open(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
/* force low_latency on so that our tty_push actually forces the data
through, otherwise it is scheduled, and with high data rates (like
with OHCI) data can get lost. */
if (tty)
tty->low_latency = 1;
/* clear the throttle flags */ /* clear the throttle flags */
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
port->throttled = 0; port->throttled = 0;
......
...@@ -193,8 +193,6 @@ static const struct divisor_table_entry divisor_table[] = { ...@@ -193,8 +193,6 @@ static const struct divisor_table_entry divisor_table[] = {
/* local variables */ /* local variables */
static int debug; static int debug;
static int low_latency = 1; /* tty low latency flag, on by default */
static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */ static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
...@@ -867,9 +865,6 @@ static int edge_open(struct tty_struct *tty, ...@@ -867,9 +865,6 @@ static int edge_open(struct tty_struct *tty,
if (edge_port == NULL) if (edge_port == NULL)
return -ENODEV; return -ENODEV;
if (tty)
tty->low_latency = low_latency;
/* see if we've set up our endpoint info yet (can't set it up /* see if we've set up our endpoint info yet (can't set it up
in edge_startup as the structures were not set up at that time.) */ in edge_startup as the structures were not set up at that time.) */
serial = port->serial; serial = port->serial;
...@@ -3299,6 +3294,3 @@ MODULE_FIRMWARE("edgeport/down2.fw"); ...@@ -3299,6 +3294,3 @@ MODULE_FIRMWARE("edgeport/down2.fw");
module_param(debug, bool, S_IRUGO | S_IWUSR); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not"); MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(low_latency, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(low_latency, "Low latency enabled or not");
...@@ -76,7 +76,6 @@ struct edgeport_uart_buf_desc { ...@@ -76,7 +76,6 @@ struct edgeport_uart_buf_desc {
#define EDGE_READ_URB_STOPPING 1 #define EDGE_READ_URB_STOPPING 1
#define EDGE_READ_URB_STOPPED 2 #define EDGE_READ_URB_STOPPED 2
#define EDGE_LOW_LATENCY 1
#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */ #define EDGE_CLOSING_WAIT 4000 /* in .01 sec */
#define EDGE_OUT_BUF_SIZE 1024 #define EDGE_OUT_BUF_SIZE 1024
...@@ -232,7 +231,6 @@ static unsigned short OperationalBuildNumber; ...@@ -232,7 +231,6 @@ static unsigned short OperationalBuildNumber;
static int debug; static int debug;
static int low_latency = EDGE_LOW_LATENCY;
static int closing_wait = EDGE_CLOSING_WAIT; static int closing_wait = EDGE_CLOSING_WAIT;
static int ignore_cpu_rev; static int ignore_cpu_rev;
static int default_uart_mode; /* RS232 */ static int default_uart_mode; /* RS232 */
...@@ -1850,9 +1848,6 @@ static int edge_open(struct tty_struct *tty, ...@@ -1850,9 +1848,6 @@ static int edge_open(struct tty_struct *tty,
if (edge_port == NULL) if (edge_port == NULL)
return -ENODEV; return -ENODEV;
if (tty)
tty->low_latency = low_latency;
port_number = port->number - port->serial->minor; port_number = port->number - port->serial->minor;
switch (port_number) { switch (port_number) {
case 0: case 0:
...@@ -3008,9 +3003,6 @@ MODULE_FIRMWARE("edgeport/down3.bin"); ...@@ -3008,9 +3003,6 @@ MODULE_FIRMWARE("edgeport/down3.bin");
module_param(debug, bool, S_IRUGO | S_IWUSR); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not"); MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(low_latency, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(low_latency, "Low latency enabled or not");
module_param(closing_wait, int, S_IRUGO | S_IWUSR); module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs"); MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
......
...@@ -631,13 +631,7 @@ static int ipaq_open(struct tty_struct *tty, ...@@ -631,13 +631,7 @@ static int ipaq_open(struct tty_struct *tty,
priv->free_len += PACKET_SIZE; priv->free_len += PACKET_SIZE;
} }
/*
* Force low latency on. This will immediately push data to the line
* discipline instead of queueing.
*/
if (tty) { if (tty) {
tty->low_latency = 1;
/* FIXME: These two are bogus */ /* FIXME: These two are bogus */
tty->raw = 1; tty->raw = 1;
tty->real_raw = 1; tty->real_raw = 1;
......
...@@ -207,9 +207,6 @@ static int ipw_open(struct tty_struct *tty, ...@@ -207,9 +207,6 @@ static int ipw_open(struct tty_struct *tty,
if (!buf_flow_init) if (!buf_flow_init)
return -ENOMEM; return -ENOMEM;
if (tty)
tty->low_latency = 1;
/* --1: Tell the modem to initialize (we think) From sniffs this is /* --1: Tell the modem to initialize (we think) From sniffs this is
* always the first thing that gets sent to the modem during * always the first thing that gets sent to the modem during
* opening of the device */ * opening of the device */
......
...@@ -1051,7 +1051,6 @@ static int iuu_open(struct tty_struct *tty, ...@@ -1051,7 +1051,6 @@ static int iuu_open(struct tty_struct *tty,
tty->termios->c_oflag = 0; tty->termios->c_oflag = 0;
tty->termios->c_iflag = 0; tty->termios->c_iflag = 0;
priv->termios_initialized = 1; priv->termios_initialized = 1;
tty->low_latency = 1;
priv->poll = 0; priv->poll = 0;
} }
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
......
...@@ -231,13 +231,7 @@ static int kobil_open(struct tty_struct *tty, ...@@ -231,13 +231,7 @@ static int kobil_open(struct tty_struct *tty,
/* someone sets the dev to 0 if the close method has been called */ /* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev; port->interrupt_in_urb->dev = port->serial->dev;
/* force low_latency on so that our tty_push actually forces
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
*/
if (tty) { if (tty) {
tty->low_latency = 1;
/* Default to echo off and other sane device settings */ /* Default to echo off and other sane device settings */
tty->termios->c_lflag = 0; tty->termios->c_lflag = 0;
......
...@@ -446,13 +446,6 @@ static int mos7720_open(struct tty_struct *tty, ...@@ -446,13 +446,6 @@ static int mos7720_open(struct tty_struct *tty,
data = 0x0c; data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
/* force low_latency on so that our tty_push actually forces *
* the data through,otherwise it is scheduled, and with *
* high data rates (like with OHCI) data can get lost. */
if (tty)
tty->low_latency = 1;
/* see if we've set up our endpoint info yet * /* see if we've set up our endpoint info yet *
* (can't set it up in mos7720_startup as the * * (can't set it up in mos7720_startup as the *
* structures were not set up at that time.) */ * structures were not set up at that time.) */
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "1.3.1" #define DRIVER_VERSION "1.3.2"
#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver" #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
/* /*
...@@ -123,6 +123,11 @@ ...@@ -123,6 +123,11 @@
#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44
#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42
/* This driver also supports the ATEN UC2324 device since it is mos7840 based
* - if I knew the device id it would also support the ATEN UC2322 */
#define USB_VENDOR_ID_ATENINTL 0x0557
#define ATENINTL_DEVICE_ID_UC2324 0x2011
/* Interrupt Routine Defines */ /* Interrupt Routine Defines */
#define SERIAL_IIR_RLS 0x06 #define SERIAL_IIR_RLS 0x06
...@@ -170,6 +175,7 @@ static struct usb_device_id moschip_port_id_table[] = { ...@@ -170,6 +175,7 @@ static struct usb_device_id moschip_port_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
{} /* terminating entry */ {} /* terminating entry */
}; };
...@@ -178,6 +184,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = { ...@@ -178,6 +184,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
{} /* terminating entry */ {} /* terminating entry */
}; };
...@@ -1000,12 +1007,6 @@ static int mos7840_open(struct tty_struct *tty, ...@@ -1000,12 +1007,6 @@ static int mos7840_open(struct tty_struct *tty,
status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
Data); Data);
/* force low_latency on so that our tty_push actually forces *
* the data through,otherwise it is scheduled, and with *
* high data rates (like with OHCI) data can get lost. */
if (tty)
tty->low_latency = 1;
/* Check to see if we've set up our endpoint info yet * /* Check to see if we've set up our endpoint info yet *
* (can't set it up in mos7840_startup as the structures * * (can't set it up in mos7840_startup as the structures *
* were not set up at that time.) */ * were not set up at that time.) */
...@@ -2477,9 +2478,14 @@ static int mos7840_startup(struct usb_serial *serial) ...@@ -2477,9 +2478,14 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_set_port_private(serial->port[i], mos7840_port); mos7840_set_port_private(serial->port[i], mos7840_port);
spin_lock_init(&mos7840_port->pool_lock); spin_lock_init(&mos7840_port->pool_lock);
mos7840_port->port_num = ((serial->port[i]->number - /* minor is not initialised until later by
(serial->port[i]->serial->minor)) + * usb-serial.c:get_free_serial() and cannot therefore be used
1); * to index device instances */
mos7840_port->port_num = i + 1;
dbg ("serial->port[i]->number = %d", serial->port[i]->number);
dbg ("serial->port[i]->serial->minor = %d", serial->port[i]->serial->minor);
dbg ("mos7840_port->port_num = %d", mos7840_port->port_num);
dbg ("serial->minor = %d", serial->minor);
if (mos7840_port->port_num == 1) { if (mos7840_port->port_num == 1) {
mos7840_port->SpRegOffset = 0x0; mos7840_port->SpRegOffset = 0x0;
...@@ -2690,13 +2696,16 @@ static void mos7840_shutdown(struct usb_serial *serial) ...@@ -2690,13 +2696,16 @@ static void mos7840_shutdown(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
mos7840_port = mos7840_get_port_private(serial->port[i]); mos7840_port = mos7840_get_port_private(serial->port[i]);
spin_lock_irqsave(&mos7840_port->pool_lock, flags); dbg ("mos7840_port %d = %p", i, mos7840_port);
mos7840_port->zombie = 1; if (mos7840_port) {
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); spin_lock_irqsave(&mos7840_port->pool_lock, flags);
usb_kill_urb(mos7840_port->control_urb); mos7840_port->zombie = 1;
kfree(mos7840_port->ctrl_buf); spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
kfree(mos7840_port->dr); usb_kill_urb(mos7840_port->control_urb);
kfree(mos7840_port); kfree(mos7840_port->ctrl_buf);
kfree(mos7840_port->dr);
kfree(mos7840_port);
}
mos7840_set_port_private(serial->port[i], NULL); mos7840_set_port_private(serial->port[i], NULL);
} }
......
...@@ -159,14 +159,6 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -159,14 +159,6 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port,
priv->port = port; priv->port = port;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/*
* Force low_latency on so that our tty_push actually forces the data
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
if (tty)
tty->low_latency = 1;
/* Start reading from the device */ /* Start reading from the device */
usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
usb_rcvbulkpipe(priv->udev, usb_rcvbulkpipe(priv->udev,
......
...@@ -936,9 +936,6 @@ static int option_open(struct tty_struct *tty, ...@@ -936,9 +936,6 @@ static int option_open(struct tty_struct *tty,
usb_pipeout(urb->pipe), 0); */ usb_pipeout(urb->pipe), 0); */
} }
if (tty)
tty->low_latency = 1;
option_send_setup(tty, port); option_send_setup(tty, port);
return 0; return 0;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/ */
#define DRIVER_VERSION "v.1.3.2" #define DRIVER_VERSION "v.1.3.3"
#define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>" #define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
...@@ -259,9 +259,21 @@ static int sierra_send_setup(struct tty_struct *tty, ...@@ -259,9 +259,21 @@ static int sierra_send_setup(struct tty_struct *tty,
val |= 0x02; val |= 0x02;
/* If composite device then properly report interface */ /* If composite device then properly report interface */
if (serial->num_ports == 1) if (serial->num_ports == 1) {
interface = sierra_calc_interface(serial); interface = sierra_calc_interface(serial);
/* Control message is sent only to interfaces with
* interrupt_in endpoints
*/
if (port->interrupt_in_urb) {
/* send control message */
return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
0x22, 0x21, val, interface,
NULL, 0, USB_CTRL_SET_TIMEOUT);
}
}
/* Otherwise the need to do non-composite mapping */ /* Otherwise the need to do non-composite mapping */
else { else {
if (port->bulk_out_endpointAddress == 2) if (port->bulk_out_endpointAddress == 2)
...@@ -270,12 +282,13 @@ static int sierra_send_setup(struct tty_struct *tty, ...@@ -270,12 +282,13 @@ static int sierra_send_setup(struct tty_struct *tty,
interface = 1; interface = 1;
else if (port->bulk_out_endpointAddress == 5) else if (port->bulk_out_endpointAddress == 5)
interface = 2; interface = 2;
}
return usb_control_msg(serial->dev, return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0), usb_rcvctrlpipe(serial->dev, 0),
0x22, 0x21, val, interface, 0x22, 0x21, val, interface,
NULL, 0, USB_CTRL_SET_TIMEOUT); NULL, 0, USB_CTRL_SET_TIMEOUT);
}
} }
return 0; return 0;
...@@ -585,9 +598,6 @@ static int sierra_open(struct tty_struct *tty, ...@@ -585,9 +598,6 @@ static int sierra_open(struct tty_struct *tty,
} }
} }
if (tty)
tty->low_latency = 1;
sierra_send_setup(tty, port); sierra_send_setup(tty, port);
/* start up the interrupt endpoint if we have one */ /* start up the interrupt endpoint if we have one */
......
...@@ -50,11 +50,10 @@ ...@@ -50,11 +50,10 @@
#define TI_TRANSFER_TIMEOUT 2 #define TI_TRANSFER_TIMEOUT 2
#define TI_DEFAULT_LOW_LATENCY 0
#define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */ #define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */
/* supported setserial flags */ /* supported setserial flags */
#define TI_SET_SERIAL_FLAGS (ASYNC_LOW_LATENCY) #define TI_SET_SERIAL_FLAGS 0
/* read urb states */ /* read urb states */
#define TI_READ_URB_RUNNING 0 #define TI_READ_URB_RUNNING 0
...@@ -161,7 +160,6 @@ static int ti_buf_get(struct circ_buf *cb, char *buf, int count); ...@@ -161,7 +160,6 @@ static int ti_buf_get(struct circ_buf *cb, char *buf, int count);
/* module parameters */ /* module parameters */
static int debug; static int debug;
static int low_latency = TI_DEFAULT_LOW_LATENCY;
static int closing_wait = TI_DEFAULT_CLOSING_WAIT; static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT]; static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];
static unsigned int vendor_3410_count; static unsigned int vendor_3410_count;
...@@ -296,10 +294,6 @@ MODULE_FIRMWARE("mts_edge.fw"); ...@@ -296,10 +294,6 @@ MODULE_FIRMWARE("mts_edge.fw");
module_param(debug, bool, S_IRUGO | S_IWUSR); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes"); MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
module_param(low_latency, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(low_latency,
"TTY low_latency flag, 0=off, 1=on, default is off");
module_param(closing_wait, int, S_IRUGO | S_IWUSR); module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, MODULE_PARM_DESC(closing_wait,
"Maximum wait for data to drain in close, in .01 secs, default is 4000"); "Maximum wait for data to drain in close, in .01 secs, default is 4000");
...@@ -448,7 +442,6 @@ static int ti_startup(struct usb_serial *serial) ...@@ -448,7 +442,6 @@ static int ti_startup(struct usb_serial *serial)
spin_lock_init(&tport->tp_lock); spin_lock_init(&tport->tp_lock);
tport->tp_uart_base_addr = (i == 0 ? tport->tp_uart_base_addr = (i == 0 ?
TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
tport->tp_closing_wait = closing_wait; tport->tp_closing_wait = closing_wait;
init_waitqueue_head(&tport->tp_msr_wait); init_waitqueue_head(&tport->tp_msr_wait);
init_waitqueue_head(&tport->tp_write_wait); init_waitqueue_head(&tport->tp_write_wait);
...@@ -528,10 +521,6 @@ static int ti_open(struct tty_struct *tty, ...@@ -528,10 +521,6 @@ static int ti_open(struct tty_struct *tty,
if (mutex_lock_interruptible(&tdev->td_open_close_lock)) if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if (tty)
tty->low_latency =
(tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
port_number = port->number - port->serial->minor; port_number = port->number - port->serial->minor;
memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount)); memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
...@@ -1454,7 +1443,6 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, ...@@ -1454,7 +1443,6 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
return -EFAULT; return -EFAULT;
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
tport->tp_closing_wait = new_serial.closing_wait; tport->tp_closing_wait = new_serial.closing_wait;
return 0; return 0;
......
...@@ -137,22 +137,10 @@ static void destroy_serial(struct kref *kref) ...@@ -137,22 +137,10 @@ static void destroy_serial(struct kref *kref)
dbg("%s - %s", __func__, serial->type->description); dbg("%s - %s", __func__, serial->type->description);
serial->type->shutdown(serial);
/* return the minor range that this device had */ /* return the minor range that this device had */
if (serial->minor != SERIAL_TTY_NO_MINOR) if (serial->minor != SERIAL_TTY_NO_MINOR)
return_serial(serial); return_serial(serial);
for (i = 0; i < serial->num_ports; ++i)
serial->port[i]->port.count = 0;
/* the ports are cleaned up and released in port_release() */
for (i = 0; i < serial->num_ports; ++i)
if (serial->port[i]->dev.parent != NULL) {
device_unregister(&serial->port[i]->dev);
serial->port[i] = NULL;
}
/* If this is a "fake" port, we have to clean it up here, as it will /* If this is a "fake" port, we have to clean it up here, as it will
* not get cleaned up in port_release() as it was never registered with * not get cleaned up in port_release() as it was never registered with
* the driver core */ * the driver core */
...@@ -187,7 +175,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -187,7 +175,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
struct usb_serial *serial; struct usb_serial *serial;
struct usb_serial_port *port; struct usb_serial_port *port;
unsigned int portNumber; unsigned int portNumber;
int retval; int retval = 0;
dbg("%s", __func__); dbg("%s", __func__);
...@@ -198,21 +186,24 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -198,21 +186,24 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
return -ENODEV; return -ENODEV;
} }
mutex_lock(&serial->disc_mutex);
portNumber = tty->index - serial->minor; portNumber = tty->index - serial->minor;
port = serial->port[portNumber]; port = serial->port[portNumber];
if (!port) { if (!port || serial->disconnected)
retval = -ENODEV;
goto bailout_kref_put;
}
if (port->serial->disconnected) {
retval = -ENODEV; retval = -ENODEV;
goto bailout_kref_put; else
} get_device(&port->dev);
/*
* Note: Our locking order requirement does not allow port->mutex
* to be acquired while serial->disc_mutex is held.
*/
mutex_unlock(&serial->disc_mutex);
if (retval)
goto bailout_serial_put;
if (mutex_lock_interruptible(&port->mutex)) { if (mutex_lock_interruptible(&port->mutex)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
goto bailout_kref_put; goto bailout_port_put;
} }
++port->port.count; ++port->port.count;
...@@ -232,14 +223,20 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -232,14 +223,20 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
goto bailout_mutex_unlock; goto bailout_mutex_unlock;
} }
retval = usb_autopm_get_interface(serial->interface); mutex_lock(&serial->disc_mutex);
if (serial->disconnected)
retval = -ENODEV;
else
retval = usb_autopm_get_interface(serial->interface);
if (retval) if (retval)
goto bailout_module_put; goto bailout_module_put;
/* only call the device specific open if this /* only call the device specific open if this
* is the first time the port is opened */ * is the first time the port is opened */
retval = serial->type->open(tty, port, filp); retval = serial->type->open(tty, port, filp);
if (retval) if (retval)
goto bailout_interface_put; goto bailout_interface_put;
mutex_unlock(&serial->disc_mutex);
} }
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
...@@ -248,13 +245,16 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -248,13 +245,16 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
bailout_interface_put: bailout_interface_put:
usb_autopm_put_interface(serial->interface); usb_autopm_put_interface(serial->interface);
bailout_module_put: bailout_module_put:
mutex_unlock(&serial->disc_mutex);
module_put(serial->type->driver.owner); module_put(serial->type->driver.owner);
bailout_mutex_unlock: bailout_mutex_unlock:
port->port.count = 0; port->port.count = 0;
tty->driver_data = NULL; tty->driver_data = NULL;
tty_port_tty_set(&port->port, NULL); tty_port_tty_set(&port->port, NULL);
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
bailout_kref_put: bailout_port_put:
put_device(&port->dev);
bailout_serial_put:
usb_serial_put(serial); usb_serial_put(serial);
return retval; return retval;
} }
...@@ -262,6 +262,9 @@ static int serial_open (struct tty_struct *tty, struct file *filp) ...@@ -262,6 +262,9 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
static void serial_close(struct tty_struct *tty, struct file *filp) static void serial_close(struct tty_struct *tty, struct file *filp)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial;
struct module *owner;
int count;
if (!port) if (!port)
return; return;
...@@ -269,6 +272,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp) ...@@ -269,6 +272,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
mutex_lock(&port->mutex); mutex_lock(&port->mutex);
serial = port->serial;
owner = serial->type->driver.owner;
if (port->port.count == 0) { if (port->port.count == 0) {
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
...@@ -281,7 +286,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp) ...@@ -281,7 +286,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
* this before we drop the port count. The call is protected * this before we drop the port count. The call is protected
* by the port mutex * by the port mutex
*/ */
port->serial->type->close(tty, port, filp); serial->type->close(tty, port, filp);
if (port->port.count == (port->console ? 2 : 1)) { if (port->port.count == (port->console ? 2 : 1)) {
struct tty_struct *tty = tty_port_tty_get(&port->port); struct tty_struct *tty = tty_port_tty_get(&port->port);
...@@ -295,17 +300,23 @@ static void serial_close(struct tty_struct *tty, struct file *filp) ...@@ -295,17 +300,23 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
} }
} }
if (port->port.count == 1) {
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected)
usb_autopm_put_interface(port->serial->interface);
mutex_unlock(&port->serial->disc_mutex);
module_put(port->serial->type->driver.owner);
}
--port->port.count; --port->port.count;
count = port->port.count;
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
usb_serial_put(port->serial); put_device(&port->dev);
/* Mustn't dereference port any more */
if (count == 0) {
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
usb_autopm_put_interface(serial->interface);
mutex_unlock(&serial->disc_mutex);
}
usb_serial_put(serial);
/* Mustn't dereference serial any more */
if (count == 0)
module_put(owner);
} }
static int serial_write(struct tty_struct *tty, const unsigned char *buf, static int serial_write(struct tty_struct *tty, const unsigned char *buf,
...@@ -549,7 +560,13 @@ static void kill_traffic(struct usb_serial_port *port) ...@@ -549,7 +560,13 @@ static void kill_traffic(struct usb_serial_port *port)
static void port_free(struct usb_serial_port *port) static void port_free(struct usb_serial_port *port)
{ {
/*
* Stop all the traffic before cancelling the work, so that
* nobody will restart it by calling usb_serial_port_softint.
*/
kill_traffic(port); kill_traffic(port);
cancel_work_sync(&port->work);
usb_free_urb(port->read_urb); usb_free_urb(port->read_urb);
usb_free_urb(port->write_urb); usb_free_urb(port->write_urb);
usb_free_urb(port->interrupt_in_urb); usb_free_urb(port->interrupt_in_urb);
...@@ -558,7 +575,6 @@ static void port_free(struct usb_serial_port *port) ...@@ -558,7 +575,6 @@ static void port_free(struct usb_serial_port *port)
kfree(port->bulk_out_buffer); kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer); kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer); kfree(port->interrupt_out_buffer);
flush_scheduled_work(); /* port->work */
kfree(port); kfree(port);
} }
...@@ -1043,6 +1059,12 @@ void usb_serial_disconnect(struct usb_interface *interface) ...@@ -1043,6 +1059,12 @@ void usb_serial_disconnect(struct usb_interface *interface)
usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL);
/* must set a flag, to signal subdrivers */ /* must set a flag, to signal subdrivers */
serial->disconnected = 1; serial->disconnected = 1;
mutex_unlock(&serial->disc_mutex);
/* Unfortunately, many of the sub-drivers expect the port structures
* to exist when their shutdown method is called, so we have to go
* through this awkward two-step unregistration procedure.
*/
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i]; port = serial->port[i];
if (port) { if (port) {
...@@ -1052,11 +1074,21 @@ void usb_serial_disconnect(struct usb_interface *interface) ...@@ -1052,11 +1074,21 @@ void usb_serial_disconnect(struct usb_interface *interface)
tty_kref_put(tty); tty_kref_put(tty);
} }
kill_traffic(port); kill_traffic(port);
cancel_work_sync(&port->work);
device_del(&port->dev);
}
}
serial->type->shutdown(serial);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port) {
put_device(&port->dev);
serial->port[i] = NULL;
} }
} }
/* let the last holder of this object /* let the last holder of this object
* cause it to be cleaned up */ * cause it to be cleaned up */
mutex_unlock(&serial->disc_mutex);
usb_serial_put(serial); usb_serial_put(serial);
dev_info(dev, "device disconnected\n"); dev_info(dev, "device disconnected\n");
} }
......
...@@ -296,14 +296,6 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -296,14 +296,6 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
priv->throttled = 0; priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/*
* Force low_latency on so that our tty_push actually forces the data
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
if (tty)
tty->low_latency = 1;
/* Start reading from the device */ /* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev, usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, usb_rcvbulkpipe(serial->dev,
......
...@@ -1851,6 +1851,12 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, ...@@ -1851,6 +1851,12 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_CAPACITY_HEURISTICS), US_FL_CAPACITY_HEURISTICS),
/* Reported by Alessio Treglia <quadrispro@ubuntu.com> */
UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
"TGE",
"Digital MP3 Audio Player",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
/* Control/Bulk transport for all SubClass values */ /* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* key configuration differences between boards. * key configuration differences between boards.
*/ */
#ifndef __LINUX_USB_MUSB_H
#define __LINUX_USB_MUSB_H
/* The USB role is defined by the connector used on the board, so long as /* The USB role is defined by the connector used on the board, so long as
* standards are being followed. (Developer boards sometimes won't.) * standards are being followed. (Developer boards sometimes won't.)
*/ */
...@@ -101,3 +104,5 @@ extern int __init tusb6010_setup_interface( ...@@ -101,3 +104,5 @@ extern int __init tusb6010_setup_interface(
extern int tusb6010_platform_retime(unsigned is_refclk); extern int tusb6010_platform_retime(unsigned is_refclk);
#endif /* OMAP2 */ #endif /* OMAP2 */
#endif /* __LINUX_USB_MUSB_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment