Commit 2695cf41 authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (23 commits)
  USB Elan FTDI: check for workqueue creation
  USB: fix spinlock recursion in cdc-acm.c
  USB: fix Unaligned access in EHCI driver
  USB: Product ID for FT232RL in ftdi_sio
  USBNET: DM9501: Add Corega FEther USB-TXC support.
  USB: ipaq.c: Additional devices
  USB: further fix for usb-serial
  USB: fix usb-serial device naming bug
  USB: RTS/DTR signal patch for airprime driver
  USB: ftdi_sio: use port_probe / port_remove thereby fixing access to the latency_timer
  usb-serial: fix shutdown / device_unregister order
  USB: add Additional PIDs in ftdi_sio
  USB: add QL355P power supply ids to fdti_sio
  USB: New device IDs for cp2101 driver
  USB: kill dead code from hub.c
  USB: ratelimit debounce error messages
  USB: pxa2xx_udc: fix hardcoded irq number
  UHCI: fix port resume problem
  USB: set the correct interval for interrupt URBs
  USB: goku_udc: Remove crude cache coherency code
  ...
parents 63e34ca9 ee17b289
...@@ -332,9 +332,9 @@ static void acm_rx_tasklet(unsigned long _acm) ...@@ -332,9 +332,9 @@ static void acm_rx_tasklet(unsigned long _acm)
if (!ACM_READY(acm)) if (!ACM_READY(acm))
return; return;
spin_lock(&acm->throttle_lock); spin_lock_irqsave(&acm->throttle_lock, flags);
throttled = acm->throttle; throttled = acm->throttle;
spin_unlock(&acm->throttle_lock); spin_unlock_irqrestore(&acm->throttle_lock, flags);
if (throttled) if (throttled)
return; return;
...@@ -352,9 +352,9 @@ static void acm_rx_tasklet(unsigned long _acm) ...@@ -352,9 +352,9 @@ static void acm_rx_tasklet(unsigned long _acm)
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
tty_buffer_request_room(tty, buf->size); tty_buffer_request_room(tty, buf->size);
spin_lock(&acm->throttle_lock); spin_lock_irqsave(&acm->throttle_lock, flags);
throttled = acm->throttle; throttled = acm->throttle;
spin_unlock(&acm->throttle_lock); spin_unlock_irqrestore(&acm->throttle_lock, flags);
if (!throttled) if (!throttled)
tty_insert_flip_string(tty, buf->base, buf->size); tty_insert_flip_string(tty, buf->base, buf->size);
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
......
...@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ...@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
struct async *as; struct async *as;
struct usb_ctrlrequest *dr = NULL; struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen; unsigned int u, totlen, isofrmlen;
int ret, interval = 0, ifnum = -1; int ret, ifnum = -1;
if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
URB_NO_FSBR|URB_ZERO_PACKET)) URB_NO_FSBR|URB_ZERO_PACKET))
...@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ...@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_ISOC) != USB_ENDPOINT_XFER_ISOC)
return -EINVAL; return -EINVAL;
interval = 1 << min (15, ep->desc.bInterval - 1);
isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
...@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ...@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT) != USB_ENDPOINT_XFER_INT)
return -EINVAL; return -EINVAL;
if (ps->dev->speed == USB_SPEED_HIGH)
interval = 1 << min (15, ep->desc.bInterval - 1);
else
interval = ep->desc.bInterval;
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL; return -EINVAL;
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
...@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ...@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
as->urb->setup_packet = (unsigned char*)dr; as->urb->setup_packet = (unsigned char*)dr;
as->urb->start_frame = uurb->start_frame; as->urb->start_frame = uurb->start_frame;
as->urb->number_of_packets = uurb->number_of_packets; as->urb->number_of_packets = uurb->number_of_packets;
as->urb->interval = interval; if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
ps->dev->speed == USB_SPEED_HIGH)
as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
else
as->urb->interval = ep->desc.bInterval;
as->urb->context = as; as->urb->context = as;
as->urb->complete = async_completed; as->urb->complete = async_completed;
for (totlen = u = 0; u < uurb->number_of_packets; u++) { for (totlen = u = 0; u < uurb->number_of_packets; u++) {
......
...@@ -1281,12 +1281,6 @@ int usb_new_device(struct usb_device *udev) ...@@ -1281,12 +1281,6 @@ int usb_new_device(struct usb_device *udev)
{ {
int err; int err;
/* Lock ourself into memory in order to keep a probe sequence
* sleeping in a new thread from allowing us to be unloaded.
*/
if (!try_module_get(THIS_MODULE))
return -EINVAL;
/* Determine quirks */ /* Determine quirks */
usb_detect_quirks(udev); usb_detect_quirks(udev);
...@@ -1390,7 +1384,6 @@ int usb_new_device(struct usb_device *udev) ...@@ -1390,7 +1384,6 @@ int usb_new_device(struct usb_device *udev)
usb_autoresume_device(udev->parent); usb_autoresume_device(udev->parent);
exit: exit:
module_put(THIS_MODULE);
return err; return err;
fail: fail:
...@@ -2443,7 +2436,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -2443,7 +2436,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (portchange & USB_PORT_STAT_C_CONNECTION) { if (portchange & USB_PORT_STAT_C_CONNECTION) {
status = hub_port_debounce(hub, port1); status = hub_port_debounce(hub, port1);
if (status < 0) { if (status < 0 && printk_ratelimit()) {
dev_err (hub_dev, dev_err (hub_dev,
"connect-debounce failed, port %d disabled\n", "connect-debounce failed, port %d disabled\n",
port1); port1);
......
...@@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, ...@@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT) { USB_ENDPOINT_XFER_INT) {
int interval;
if (usb_dev->speed == USB_SPEED_HIGH)
interval = 1 << min(15, ep->desc.bInterval - 1);
else
interval = ep->desc.bInterval;
pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
usb_fill_int_urb(urb, usb_dev, pipe, data, len, usb_fill_int_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL, usb_api_blocking_completion, NULL, interval);
ep->desc.bInterval);
} else } else
usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL); usb_api_blocking_completion, NULL);
......
...@@ -1835,7 +1835,7 @@ static int at91udc_resume(struct platform_device *pdev) ...@@ -1835,7 +1835,7 @@ static int at91udc_resume(struct platform_device *pdev)
#define at91udc_resume NULL #define at91udc_resume NULL
#endif #endif
static struct platform_driver at91_udc = { static struct platform_driver at91_udc_driver = {
.remove = __exit_p(at91udc_remove), .remove = __exit_p(at91udc_remove),
.shutdown = at91udc_shutdown, .shutdown = at91udc_shutdown,
.suspend = at91udc_suspend, .suspend = at91udc_suspend,
...@@ -1848,13 +1848,13 @@ static struct platform_driver at91_udc = { ...@@ -1848,13 +1848,13 @@ static struct platform_driver at91_udc = {
static int __init udc_init_module(void) static int __init udc_init_module(void)
{ {
return platform_driver_probe(&at91_udc, at91udc_probe); return platform_driver_probe(&at91_udc_driver, at91udc_probe);
} }
module_init(udc_init_module); module_init(udc_init_module);
static void __exit udc_exit_module(void) static void __exit udc_exit_module(void)
{ {
platform_driver_unregister(&at91_udc); platform_driver_unregister(&at91_udc_driver);
} }
module_exit(udc_exit_module); module_exit(udc_exit_module);
......
...@@ -297,27 +297,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) ...@@ -297,27 +297,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#undef USE_KMALLOC
/* many common platforms have dma-coherent caches, which means that it's
* safe to use kmalloc() memory for all i/o buffers without using any
* cache flushing calls. (unless you're trying to share cache lines
* between dma and non-dma activities, which is a slow idea in any case.)
*
* other platforms need more care, with 2.6 having a moderately general
* solution except for the common "buffer is smaller than a page" case.
*/
#if defined(CONFIG_X86)
#define USE_KMALLOC
#elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
#define USE_KMALLOC
#elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
#define USE_KMALLOC
#endif
/* allocating buffers this way eliminates dma mapping overhead, which /* allocating buffers this way eliminates dma mapping overhead, which
* on some platforms will mean eliminating a per-io buffer copy. with * on some platforms will mean eliminating a per-io buffer copy. with
* some kinds of system caches, further tweaks may still be needed. * some kinds of system caches, further tweaks may still be needed.
...@@ -334,11 +313,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, ...@@ -334,11 +313,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
return NULL; return NULL;
*dma = DMA_ADDR_INVALID; *dma = DMA_ADDR_INVALID;
#if defined(USE_KMALLOC)
retval = kmalloc(bytes, gfp_flags);
if (retval)
*dma = virt_to_phys(retval);
#else
if (ep->dma) { if (ep->dma) {
/* the main problem with this call is that it wastes memory /* the main problem with this call is that it wastes memory
* on typical 1/N page allocations: it allocates 1-N pages. * on typical 1/N page allocations: it allocates 1-N pages.
...@@ -348,7 +322,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, ...@@ -348,7 +322,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
bytes, dma, gfp_flags); bytes, dma, gfp_flags);
} else } else
retval = kmalloc(bytes, gfp_flags); retval = kmalloc(bytes, gfp_flags);
#endif
return retval; return retval;
} }
...@@ -356,7 +329,6 @@ static void ...@@ -356,7 +329,6 @@ static void
goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
{ {
/* free memory into the right allocator */ /* free memory into the right allocator */
#ifndef USE_KMALLOC
if (dma != DMA_ADDR_INVALID) { if (dma != DMA_ADDR_INVALID) {
struct goku_ep *ep; struct goku_ep *ep;
...@@ -365,7 +337,6 @@ goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) ...@@ -365,7 +337,6 @@ goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
return; return;
dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
} else } else
#endif
kfree (buf); kfree (buf);
} }
......
...@@ -2616,7 +2616,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) ...@@ -2616,7 +2616,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (retval != 0) { if (retval != 0) {
printk(KERN_ERR "%s: can't get irq %i, err %d\n", printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, vbus_irq, retval); driver_name, vbus_irq, retval);
free_irq(IRQ_USB, dev); free_irq(irq, dev);
return -EBUSY; return -EBUSY;
} }
} }
......
...@@ -653,8 +653,7 @@ static int ehci_hub_control ( ...@@ -653,8 +653,7 @@ static int ehci_hub_control (
if (status & ~0xffff) /* only if wPortChange is interesting */ if (status & ~0xffff) /* only if wPortChange is interesting */
#endif #endif
dbg_port (ehci, "GetStatus", wIndex + 1, temp); dbg_port (ehci, "GetStatus", wIndex + 1, temp);
// we "know" this alignment is good, caller used kmalloc()... put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
*((__le32 *) buf) = cpu_to_le32 (status);
break; break;
case SetHubFeature: case SetHubFeature:
switch (wValue) { switch (wValue) {
......
...@@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] = ...@@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] =
/* status change bits: nonzero writes will clear */ /* status change bits: nonzero writes will clear */
#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
/* suspend/resume bits: port suspended or port resuming */
#define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD)
/* A port that either is connected or has a changed-bit set will prevent /* A port that either is connected or has a changed-bit set will prevent
* us from AUTO_STOPPING. * us from AUTO_STOPPING.
*/ */
...@@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, ...@@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
int status; int status;
int i; int i;
if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { if (inw(port_addr) & SUSPEND_BITS) {
CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); CLR_RH_PORTSTAT(SUSPEND_BITS);
if (test_bit(port, &uhci->resuming_ports)) if (test_bit(port, &uhci->resuming_ports))
set_bit(port, &uhci->port_c_suspend); set_bit(port, &uhci->port_c_suspend);
...@@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, ...@@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
* Experiments show that some controllers take longer, so * Experiments show that some controllers take longer, so
* we'll poll for completion. */ * we'll poll for completion. */
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
if (!(inw(port_addr) & USBPORTSC_RD)) if (!(inw(port_addr) & SUSPEND_BITS))
break; break;
udelay(1); udelay(1);
} }
...@@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortStatus |= USB_PORT_STAT_CONNECTION; wPortStatus |= USB_PORT_STAT_CONNECTION;
if (status & USBPORTSC_PE) { if (status & USBPORTSC_PE) {
wPortStatus |= USB_PORT_STAT_ENABLE; wPortStatus |= USB_PORT_STAT_ENABLE;
if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) if (status & SUSPEND_BITS)
wPortStatus |= USB_PORT_STAT_SUSPEND; wPortStatus |= USB_PORT_STAT_SUSPEND;
} }
if (status & USBPORTSC_OC) if (status & USBPORTSC_OC)
......
...@@ -2905,17 +2905,31 @@ static int __init ftdi_elan_init(void) ...@@ -2905,17 +2905,31 @@ static int __init ftdi_elan_init(void)
{ {
int result; int result;
printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
__TIME__, __DATE__); __TIME__, __DATE__);
init_MUTEX(&ftdi_module_lock); init_MUTEX(&ftdi_module_lock);
INIT_LIST_HEAD(&ftdi_static_list); INIT_LIST_HEAD(&ftdi_static_list);
status_queue = create_singlethread_workqueue("ftdi-status-control"); status_queue = create_singlethread_workqueue("ftdi-status-control");
if (!status_queue)
goto err1;
command_queue = create_singlethread_workqueue("ftdi-command-engine"); command_queue = create_singlethread_workqueue("ftdi-command-engine");
if (!command_queue)
goto err2;
respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
if (!respond_queue)
goto err3;
result = usb_register(&ftdi_elan_driver); result = usb_register(&ftdi_elan_driver);
if (result) if (result)
printk(KERN_ERR "usb_register failed. Error number %d\n", printk(KERN_ERR "usb_register failed. Error number %d\n",
result); result);
return result; return result;
err3:
destroy_workqueue(command_queue);
err2:
destroy_workqueue(status_queue);
err1:
printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name);
return -ENOMEM;
} }
static void __exit ftdi_elan_exit(void) static void __exit ftdi_elan_exit(void)
......
...@@ -570,6 +570,10 @@ static const struct driver_info dm9601_info = { ...@@ -570,6 +570,10 @@ static const struct driver_info dm9601_info = {
}; };
static const struct usb_device_id products[] = { static const struct usb_device_id products[] = {
{
USB_DEVICE(0x07aa, 0x9601), /* Corega FEther USB-TXC */
.driver_info = (unsigned long)&dm9601_info,
},
{ {
USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */ USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */
.driver_info = (unsigned long)&dm9601_info, .driver_info = (unsigned long)&dm9601_info,
......
...@@ -44,8 +44,43 @@ struct airprime_private { ...@@ -44,8 +44,43 @@ struct airprime_private {
int outstanding_urbs; int outstanding_urbs;
int throttled; int throttled;
struct urb *read_urbp[NUM_READ_URBS]; struct urb *read_urbp[NUM_READ_URBS];
/* Settings for the port */
int rts_state; /* Handshaking pins (outputs) */
int dtr_state;
int cts_state; /* Handshaking pins (inputs) */
int dsr_state;
int dcd_state;
int ri_state;
}; };
static int airprime_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct airprime_private *priv;
dbg("%s", __FUNCTION__);
if (port->number != 0)
return 0;
priv = usb_get_serial_port_data(port);
if (port->tty) {
int val = 0;
if (priv->dtr_state)
val |= 0x01;
if (priv->rts_state)
val |= 0x02;
return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
}
return 0;
}
static void airprime_read_bulk_callback(struct urb *urb) static void airprime_read_bulk_callback(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
...@@ -118,6 +153,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) ...@@ -118,6 +153,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
usb_set_serial_port_data(port, priv); usb_set_serial_port_data(port, priv);
} }
/* Set some sane defaults */
priv->rts_state = 1;
priv->dtr_state = 1;
for (i = 0; i < NUM_READ_URBS; ++i) { for (i = 0; i < NUM_READ_URBS; ++i) {
buffer = kmalloc(buffer_size, GFP_KERNEL); buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) { if (!buffer) {
...@@ -151,6 +190,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) ...@@ -151,6 +190,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
/* remember this urb so we can kill it when the port is closed */ /* remember this urb so we can kill it when the port is closed */
priv->read_urbp[i] = urb; priv->read_urbp[i] = urb;
} }
airprime_send_setup(port);
goto out; goto out;
errout: errout:
...@@ -176,6 +218,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp) ...@@ -176,6 +218,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
priv->rts_state = 0;
priv->dtr_state = 0;
airprime_send_setup(port);
for (i = 0; i < NUM_READ_URBS; ++i) { for (i = 0; i < NUM_READ_URBS; ++i) {
usb_kill_urb (priv->read_urbp[i]); usb_kill_urb (priv->read_urbp[i]);
kfree (priv->read_urbp[i]->transfer_buffer); kfree (priv->read_urbp[i]->transfer_buffer);
......
...@@ -63,6 +63,8 @@ static struct usb_device_id id_table [] = { ...@@ -63,6 +63,8 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
......
...@@ -315,6 +315,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -315,6 +315,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
...@@ -420,6 +421,14 @@ static struct usb_device_id id_table_combined [] = { ...@@ -420,6 +421,14 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
/* /*
* These will probably use user-space drivers. Uncomment them if * These will probably use user-space drivers. Uncomment them if
* you need them or use the user-specified vendor/product module * you need them or use the user-specified vendor/product module
...@@ -459,6 +468,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -459,6 +468,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
{ USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
...@@ -533,6 +543,7 @@ static const char *ftdi_chip_name[] = { ...@@ -533,6 +543,7 @@ static const char *ftdi_chip_name[] = {
[FT8U232AM] = "FT8U232AM", [FT8U232AM] = "FT8U232AM",
[FT232BM] = "FT232BM", [FT232BM] = "FT232BM",
[FT2232C] = "FT2232C", [FT2232C] = "FT2232C",
[FT232RL] = "FT232RL",
}; };
...@@ -588,6 +599,8 @@ struct ftdi_private { ...@@ -588,6 +599,8 @@ struct ftdi_private {
static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
static int ftdi_sio_attach (struct usb_serial *serial); static int ftdi_sio_attach (struct usb_serial *serial);
static void ftdi_shutdown (struct usb_serial *serial); static void ftdi_shutdown (struct usb_serial *serial);
static int ftdi_sio_port_probe (struct usb_serial_port *port);
static int ftdi_sio_port_remove (struct usb_serial_port *port);
static int ftdi_open (struct usb_serial_port *port, struct file *filp); static int ftdi_open (struct usb_serial_port *port, struct file *filp);
static void ftdi_close (struct usb_serial_port *port, struct file *filp); static void ftdi_close (struct usb_serial_port *port, struct file *filp);
static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count);
...@@ -622,6 +635,8 @@ static struct usb_serial_driver ftdi_sio_device = { ...@@ -622,6 +635,8 @@ static struct usb_serial_driver ftdi_sio_device = {
.num_bulk_out = 1, .num_bulk_out = 1,
.num_ports = 1, .num_ports = 1,
.probe = ftdi_sio_probe, .probe = ftdi_sio_probe,
.port_probe = ftdi_sio_port_probe,
.port_remove = ftdi_sio_port_remove,
.open = ftdi_open, .open = ftdi_open,
.close = ftdi_close, .close = ftdi_close,
.throttle = ftdi_throttle, .throttle = ftdi_throttle,
...@@ -1024,11 +1039,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a ...@@ -1024,11 +1039,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
{ {
struct usb_serial_port *port = to_usb_serial_port(dev); struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev; struct usb_device *udev = port->serial->dev;
unsigned short latency = 0; unsigned short latency = 0;
int rv = 0; int rv = 0;
udev = to_usb_device(dev);
dbg("%s",__FUNCTION__); dbg("%s",__FUNCTION__);
...@@ -1052,13 +1066,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute * ...@@ -1052,13 +1066,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
{ {
struct usb_serial_port *port = to_usb_serial_port(dev); struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev; struct usb_device *udev = port->serial->dev;
char buf[1]; char buf[1];
int v = simple_strtoul(valbuf, NULL, 10); int v = simple_strtoul(valbuf, NULL, 10);
int rv = 0; int rv = 0;
udev = to_usb_device(dev);
dbg("%s: setting latency timer = %i", __FUNCTION__, v); dbg("%s: setting latency timer = %i", __FUNCTION__, v);
rv = usb_control_msg(udev, rv = usb_control_msg(udev,
...@@ -1083,13 +1095,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att ...@@ -1083,13 +1095,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
{ {
struct usb_serial_port *port = to_usb_serial_port(dev); struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev; struct usb_device *udev = port->serial->dev;
char buf[1]; char buf[1];
int v = simple_strtoul(valbuf, NULL, 10); int v = simple_strtoul(valbuf, NULL, 10);
int rv = 0; int rv = 0;
udev = to_usb_device(dev);
dbg("%s: setting event char = %i", __FUNCTION__, v); dbg("%s: setting event char = %i", __FUNCTION__, v);
rv = usb_control_msg(udev, rv = usb_control_msg(udev,
...@@ -1110,46 +1120,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att ...@@ -1110,46 +1120,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
static int create_sysfs_attrs(struct usb_serial *serial) static int create_sysfs_attrs(struct usb_serial_port *port)
{ {
struct ftdi_private *priv; struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev;
int retval = 0; int retval = 0;
dbg("%s",__FUNCTION__); dbg("%s",__FUNCTION__);
priv = usb_get_serial_port_data(serial->port[0]);
udev = serial->dev;
/* XXX I've no idea if the original SIO supports the event_char /* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */ * sysfs parameter, so I'm playing it safe. */
if (priv->chip_type != SIO) { if (priv->chip_type != SIO) {
dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
retval = device_create_file(&udev->dev, &dev_attr_event_char); retval = device_create_file(&port->dev, &dev_attr_event_char);
if ((!retval) && if ((!retval) &&
(priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
retval = device_create_file(&udev->dev, retval = device_create_file(&port->dev,
&dev_attr_latency_timer); &dev_attr_latency_timer);
} }
} }
return retval; return retval;
} }
static void remove_sysfs_attrs(struct usb_serial *serial) static void remove_sysfs_attrs(struct usb_serial_port *port)
{ {
struct ftdi_private *priv; struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev;
dbg("%s",__FUNCTION__); dbg("%s",__FUNCTION__);
priv = usb_get_serial_port_data(serial->port[0]);
udev = serial->dev;
/* XXX see create_sysfs_attrs */ /* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) { if (priv->chip_type != SIO) {
device_remove_file(&udev->dev, &dev_attr_event_char); device_remove_file(&port->dev, &dev_attr_event_char);
if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
device_remove_file(&udev->dev, &dev_attr_latency_timer); device_remove_file(&port->dev, &dev_attr_latency_timer);
} }
} }
...@@ -1169,13 +1171,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id ...@@ -1169,13 +1171,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
return (0); return (0);
} }
/* attach subroutine */ static int ftdi_sio_port_probe(struct usb_serial_port *port)
static int ftdi_sio_attach (struct usb_serial *serial)
{ {
struct usb_serial_port *port = serial->port[0];
struct ftdi_private *priv; struct ftdi_private *priv;
struct ftdi_sio_quirk *quirk;
int retval;
dbg("%s",__FUNCTION__); dbg("%s",__FUNCTION__);
...@@ -1215,19 +1213,21 @@ static int ftdi_sio_attach (struct usb_serial *serial) ...@@ -1215,19 +1213,21 @@ static int ftdi_sio_attach (struct usb_serial *serial)
kfree(port->bulk_out_buffer); kfree(port->bulk_out_buffer);
port->bulk_out_buffer = NULL; port->bulk_out_buffer = NULL;
usb_set_serial_port_data(serial->port[0], priv); usb_set_serial_port_data(port, priv);
ftdi_determine_type (serial->port[0]); ftdi_determine_type (port);
retval = create_sysfs_attrs(serial); create_sysfs_attrs(port);
if (retval) return 0;
dev_err(&serial->dev->dev, "Error creating sysfs files, " }
"continuing\n");
/* attach subroutine */
static int ftdi_sio_attach (struct usb_serial *serial)
{
/* Check for device requiring special set up. */ /* Check for device requiring special set up. */
quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
if (quirk && quirk->setup) {
if (quirk && quirk->setup)
quirk->setup(serial); quirk->setup(serial);
}
return 0; return 0;
} /* ftdi_sio_attach */ } /* ftdi_sio_attach */
...@@ -1271,17 +1271,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) ...@@ -1271,17 +1271,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
* calls __serial_close for each open of the port * calls __serial_close for each open of the port
* shutdown is called then (ie ftdi_shutdown) * shutdown is called then (ie ftdi_shutdown)
*/ */
static void ftdi_shutdown (struct usb_serial *serial) static void ftdi_shutdown (struct usb_serial *serial)
{ /* ftdi_shutdown */ {
dbg("%s", __FUNCTION__);
}
struct usb_serial_port *port = serial->port[0]; static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
remove_sysfs_attrs(serial); remove_sysfs_attrs(port);
/* all open ports are closed at this point /* all open ports are closed at this point
* (by usbserial.c:__serial_close, which calls ftdi_close) * (by usbserial.c:__serial_close, which calls ftdi_close)
...@@ -1291,8 +1292,9 @@ static void ftdi_shutdown (struct usb_serial *serial) ...@@ -1291,8 +1292,9 @@ static void ftdi_shutdown (struct usb_serial *serial)
usb_set_serial_port_data(port, NULL); usb_set_serial_port_data(port, NULL);
kfree(priv); kfree(priv);
} }
} /* ftdi_shutdown */
return 0;
}
static int ftdi_open (struct usb_serial_port *port, struct file *filp) static int ftdi_open (struct usb_serial_port *port, struct file *filp)
{ /* ftdi_open */ { /* ftdi_open */
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ #define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */
...@@ -338,6 +339,12 @@ ...@@ -338,6 +339,12 @@
*/ */
#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */
/*
* TTi (Thurlby Thandar Instruments)
*/
#define TTI_VID 0x103E /* Vendor Id */
#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */
/* /*
* Definitions for B&B Electronics products. * Definitions for B&B Electronics products.
*/ */
...@@ -497,6 +504,19 @@ ...@@ -497,6 +504,19 @@
#define TELLDUS_VID 0x1781 /* Vendor ID */ #define TELLDUS_VID 0x1781 /* Vendor ID */
#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */
/*
* IBS elektronik product ids
* Submitted by Thomas Schleusener
*/
#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */
#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */
#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */
#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */
#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */
#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */
#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */
#define FTDI_IBS_PROD_PID 0xff3f /* future device */
/* Commands */ /* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
...@@ -620,6 +640,7 @@ typedef enum { ...@@ -620,6 +640,7 @@ typedef enum {
FT8U232AM = 2, FT8U232AM = 2,
FT232BM = 3, FT232BM = 3,
FT2232C = 4, FT2232C = 4,
FT232RL = 5,
} ftdi_chip_type_t; } ftdi_chip_type_t;
typedef enum { typedef enum {
......
...@@ -247,6 +247,8 @@ static struct usb_device_id ipaq_id_table [] = { ...@@ -247,6 +247,8 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
{ USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
{ USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
{ USB_DEVICE(0x04AD, 0x0306) }, /* GPS Pocket PC USB Sync */
{ USB_DEVICE(0x04B7, 0x0531) }, /* MyGuide 7000 XL USB Sync */
{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
......
...@@ -99,9 +99,12 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po ...@@ -99,9 +99,12 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
continue; continue;
*minor = i; *minor = i;
j = 0;
dbg("%s - minor base = %d", __FUNCTION__, *minor); dbg("%s - minor base = %d", __FUNCTION__, *minor);
for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
serial_table[i] = serial; serial_table[i] = serial;
serial->port[j++]->number = i;
}
spin_unlock(&table_lock); spin_unlock(&table_lock);
return serial; return serial;
} }
...@@ -135,11 +138,6 @@ static void destroy_serial(struct kref *kref) ...@@ -135,11 +138,6 @@ static void destroy_serial(struct kref *kref)
dbg("%s - %s", __FUNCTION__, serial->type->description); dbg("%s - %s", __FUNCTION__, serial->type->description);
serial->type->shutdown(serial);
/* return the minor range that this device had */
return_serial(serial);
for (i = 0; i < serial->num_ports; ++i) for (i = 0; i < serial->num_ports; ++i)
serial->port[i]->open_count = 0; serial->port[i]->open_count = 0;
...@@ -150,6 +148,12 @@ static void destroy_serial(struct kref *kref) ...@@ -150,6 +148,12 @@ static void destroy_serial(struct kref *kref)
serial->port[i] = NULL; serial->port[i] = NULL;
} }
if (serial->type->shutdown)
serial->type->shutdown(serial);
/* return the minor range that this device had */
return_serial(serial);
/* 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 */
...@@ -826,7 +830,6 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -826,7 +830,6 @@ int usb_serial_probe(struct usb_interface *interface,
num_ports = type->num_ports; num_ports = type->num_ports;
} }
serial->minor = minor;
serial->num_ports = num_ports; serial->num_ports = num_ports;
serial->num_bulk_in = num_bulk_in; serial->num_bulk_in = num_bulk_in;
serial->num_bulk_out = num_bulk_out; serial->num_bulk_out = num_bulk_out;
...@@ -847,7 +850,6 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -847,7 +850,6 @@ int usb_serial_probe(struct usb_interface *interface,
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
if (!port) if (!port)
goto probe_error; goto probe_error;
port->number = i + serial->minor;
port->serial = serial; port->serial = serial;
spin_lock_init(&port->lock); spin_lock_init(&port->lock);
mutex_init(&port->mutex); mutex_init(&port->mutex);
...@@ -980,6 +982,7 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -980,6 +982,7 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, "No more free serial devices\n"); dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error; goto probe_error;
} }
serial->minor = minor;
/* register all of the individual ports with the driver core */ /* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) { for (i = 0; i < num_ports; ++i) {
...@@ -1034,9 +1037,6 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -1034,9 +1037,6 @@ int usb_serial_probe(struct usb_interface *interface,
kfree(port->interrupt_out_buffer); kfree(port->interrupt_out_buffer);
} }
/* return the minor range that this device had */
return_serial (serial);
/* free up any memory that we allocated */ /* free up any memory that we allocated */
for (i = 0; i < serial->num_port_pointers; ++i) for (i = 0; i < serial->num_port_pointers; ++i)
kfree(serial->port[i]); kfree(serial->port[i]);
......
...@@ -146,6 +146,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, ...@@ -146,6 +146,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Reported by Andrew Nayenko <relan@bk.ru> */
UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592,
"Nokia",
"Nokia 6288",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 ),
/* Reported by Mario Rettig <mariorettig@web.de> */ /* Reported by Mario Rettig <mariorettig@web.de> */
UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
"Nokia", "Nokia",
...@@ -1395,16 +1402,6 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, ...@@ -1395,16 +1402,6 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Reported by Thomas Baechler <thomas@archlinux.org>
* Fixes I/O errors with Teac HD-35PU devices
*/
UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
"Super Top",
"USB 2.0 IDE DEVICE",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE),
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org> /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
* and Renato Perini <rperini@email.it> * and Renato Perini <rperini@email.it>
*/ */
......
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