diff options
Diffstat (limited to 'drivers/usb')
30 files changed, 384 insertions, 233 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d38a25f36ea5..31ae661e586a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -332,9 +332,9 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
| 332 | if (!ACM_READY(acm)) | 332 | if (!ACM_READY(acm)) |
| 333 | return; | 333 | return; |
| 334 | 334 | ||
| 335 | spin_lock(&acm->throttle_lock); | 335 | spin_lock_irqsave(&acm->throttle_lock, flags); |
| 336 | throttled = acm->throttle; | 336 | throttled = acm->throttle; |
| 337 | spin_unlock(&acm->throttle_lock); | 337 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
| 338 | if (throttled) | 338 | if (throttled) |
| 339 | return; | 339 | return; |
| 340 | 340 | ||
| @@ -352,9 +352,9 @@ next_buffer: | |||
| 352 | dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); | 352 | dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); |
| 353 | 353 | ||
| 354 | tty_buffer_request_room(tty, buf->size); | 354 | tty_buffer_request_room(tty, buf->size); |
| 355 | spin_lock(&acm->throttle_lock); | 355 | spin_lock_irqsave(&acm->throttle_lock, flags); |
| 356 | throttled = acm->throttle; | 356 | throttled = acm->throttle; |
| 357 | spin_unlock(&acm->throttle_lock); | 357 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
| 358 | if (!throttled) | 358 | if (!throttled) |
| 359 | tty_insert_flip_string(tty, buf->base, buf->size); | 359 | tty_insert_flip_string(tty, buf->base, buf->size); |
| 360 | tty_flip_buffer_push(tty); | 360 | tty_flip_buffer_push(tty); |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 63e50a1f1396..6584cf00f7f3 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
| @@ -202,6 +202,7 @@ struct quirk_printer_struct { | |||
| 202 | 202 | ||
| 203 | #define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */ | 203 | #define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */ |
| 204 | #define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */ | 204 | #define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */ |
| 205 | #define USBLP_QUIRK_BAD_CLASS 0x4 /* descriptor uses vendor-specific Class or SubClass */ | ||
| 205 | 206 | ||
| 206 | static const struct quirk_printer_struct quirk_printers[] = { | 207 | static const struct quirk_printer_struct quirk_printers[] = { |
| 207 | { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */ | 208 | { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */ |
| @@ -218,6 +219,7 @@ static const struct quirk_printer_struct quirk_printers[] = { | |||
| 218 | { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ | 219 | { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ |
| 219 | { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ | 220 | { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ |
| 220 | { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ | 221 | { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ |
| 222 | { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ | ||
| 221 | { 0, 0 } | 223 | { 0, 0 } |
| 222 | }; | 224 | }; |
| 223 | 225 | ||
| @@ -1048,7 +1050,8 @@ static int usblp_select_alts(struct usblp *usblp) | |||
| 1048 | ifd = &if_alt->altsetting[i]; | 1050 | ifd = &if_alt->altsetting[i]; |
| 1049 | 1051 | ||
| 1050 | if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1) | 1052 | if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1) |
| 1051 | continue; | 1053 | if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS)) |
| 1054 | continue; | ||
| 1052 | 1055 | ||
| 1053 | if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL || | 1056 | if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL || |
| 1054 | ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL) | 1057 | ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL) |
| @@ -1232,6 +1235,7 @@ static struct usb_device_id usblp_ids [] = { | |||
| 1232 | { USB_INTERFACE_INFO(7, 1, 1) }, | 1235 | { USB_INTERFACE_INFO(7, 1, 1) }, |
| 1233 | { USB_INTERFACE_INFO(7, 1, 2) }, | 1236 | { USB_INTERFACE_INFO(7, 1, 2) }, |
| 1234 | { USB_INTERFACE_INFO(7, 1, 3) }, | 1237 | { USB_INTERFACE_INFO(7, 1, 3) }, |
| 1238 | { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */ | ||
| 1235 | { } /* Terminating entry */ | 1239 | { } /* Terminating entry */ |
| 1236 | }; | 1240 | }; |
| 1237 | 1241 | ||
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 274f14f1633e..36e7a843bf91 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 912 | struct async *as; | 912 | struct async *as; |
| 913 | struct usb_ctrlrequest *dr = NULL; | 913 | struct usb_ctrlrequest *dr = NULL; |
| 914 | unsigned int u, totlen, isofrmlen; | 914 | unsigned int u, totlen, isofrmlen; |
| 915 | int ret, interval = 0, ifnum = -1; | 915 | int ret, ifnum = -1; |
| 916 | 916 | ||
| 917 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| | 917 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| |
| 918 | URB_NO_FSBR|URB_ZERO_PACKET)) | 918 | URB_NO_FSBR|URB_ZERO_PACKET)) |
| @@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 992 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 992 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) |
| 993 | != USB_ENDPOINT_XFER_ISOC) | 993 | != USB_ENDPOINT_XFER_ISOC) |
| 994 | return -EINVAL; | 994 | return -EINVAL; |
| 995 | interval = 1 << min (15, ep->desc.bInterval - 1); | ||
| 996 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; | 995 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; |
| 997 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) | 996 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) |
| 998 | return -ENOMEM; | 997 | return -ENOMEM; |
| @@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 1021 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 1020 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) |
| 1022 | != USB_ENDPOINT_XFER_INT) | 1021 | != USB_ENDPOINT_XFER_INT) |
| 1023 | return -EINVAL; | 1022 | return -EINVAL; |
| 1024 | if (ps->dev->speed == USB_SPEED_HIGH) | ||
| 1025 | interval = 1 << min (15, ep->desc.bInterval - 1); | ||
| 1026 | else | ||
| 1027 | interval = ep->desc.bInterval; | ||
| 1028 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1023 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
| 1029 | return -EINVAL; | 1024 | return -EINVAL; |
| 1030 | if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) | 1025 | 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 | as->urb->setup_packet = (unsigned char*)dr; | 1048 | as->urb->setup_packet = (unsigned char*)dr; |
| 1054 | as->urb->start_frame = uurb->start_frame; | 1049 | as->urb->start_frame = uurb->start_frame; |
| 1055 | as->urb->number_of_packets = uurb->number_of_packets; | 1050 | as->urb->number_of_packets = uurb->number_of_packets; |
| 1056 | as->urb->interval = interval; | 1051 | if (uurb->type == USBDEVFS_URB_TYPE_ISO || |
| 1052 | ps->dev->speed == USB_SPEED_HIGH) | ||
| 1053 | as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); | ||
| 1054 | else | ||
| 1055 | as->urb->interval = ep->desc.bInterval; | ||
| 1057 | as->urb->context = as; | 1056 | as->urb->context = as; |
| 1058 | as->urb->complete = async_completed; | 1057 | as->urb->complete = async_completed; |
| 1059 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { | 1058 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 41400743ce2c..b89a98e61323 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -1281,12 +1281,6 @@ int usb_new_device(struct usb_device *udev) | |||
| 1281 | { | 1281 | { |
| 1282 | int err; | 1282 | int err; |
| 1283 | 1283 | ||
| 1284 | /* Lock ourself into memory in order to keep a probe sequence | ||
| 1285 | * sleeping in a new thread from allowing us to be unloaded. | ||
| 1286 | */ | ||
| 1287 | if (!try_module_get(THIS_MODULE)) | ||
| 1288 | return -EINVAL; | ||
| 1289 | |||
| 1290 | /* Determine quirks */ | 1284 | /* Determine quirks */ |
| 1291 | usb_detect_quirks(udev); | 1285 | usb_detect_quirks(udev); |
| 1292 | 1286 | ||
| @@ -1390,7 +1384,6 @@ int usb_new_device(struct usb_device *udev) | |||
| 1390 | usb_autoresume_device(udev->parent); | 1384 | usb_autoresume_device(udev->parent); |
| 1391 | 1385 | ||
| 1392 | exit: | 1386 | exit: |
| 1393 | module_put(THIS_MODULE); | ||
| 1394 | return err; | 1387 | return err; |
| 1395 | 1388 | ||
| 1396 | fail: | 1389 | fail: |
| @@ -2443,7 +2436,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
| 2443 | 2436 | ||
| 2444 | if (portchange & USB_PORT_STAT_C_CONNECTION) { | 2437 | if (portchange & USB_PORT_STAT_C_CONNECTION) { |
| 2445 | status = hub_port_debounce(hub, port1); | 2438 | status = hub_port_debounce(hub, port1); |
| 2446 | if (status < 0) { | 2439 | if (status < 0 && printk_ratelimit()) { |
| 2447 | dev_err (hub_dev, | 2440 | dev_err (hub_dev, |
| 2448 | "connect-debounce failed, port %d disabled\n", | 2441 | "connect-debounce failed, port %d disabled\n", |
| 2449 | port1); | 2442 | port1); |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2f17468b5c1e..217a3d6d0a06 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, | |||
| 221 | 221 | ||
| 222 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | 222 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == |
| 223 | USB_ENDPOINT_XFER_INT) { | 223 | USB_ENDPOINT_XFER_INT) { |
| 224 | int interval; | ||
| 225 | |||
| 226 | if (usb_dev->speed == USB_SPEED_HIGH) | ||
| 227 | interval = 1 << min(15, ep->desc.bInterval - 1); | ||
| 228 | else | ||
| 229 | interval = ep->desc.bInterval; | ||
| 224 | pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); | 230 | pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); |
| 225 | usb_fill_int_urb(urb, usb_dev, pipe, data, len, | 231 | usb_fill_int_urb(urb, usb_dev, pipe, data, len, |
| 226 | usb_api_blocking_completion, NULL, | 232 | usb_api_blocking_completion, NULL, interval); |
| 227 | ep->desc.bInterval); | ||
| 228 | } else | 233 | } else |
| 229 | usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, | 234 | usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, |
| 230 | usb_api_blocking_completion, NULL); | 235 | usb_api_blocking_completion, NULL); |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 0e5c646cb4f6..f08ec85a6d64 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
| @@ -30,7 +30,8 @@ | |||
| 30 | static const struct usb_device_id usb_quirk_list[] = { | 30 | static const struct usb_device_id usb_quirk_list[] = { |
| 31 | /* HP 5300/5370C scanner */ | 31 | /* HP 5300/5370C scanner */ |
| 32 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, | 32 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, |
| 33 | 33 | /* Seiko Epson Corp - Perfection 1670 */ | |
| 34 | { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
| 34 | /* Elsa MicroLink 56k (V.250) */ | 35 | /* Elsa MicroLink 56k (V.250) */ |
| 35 | { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | 36 | { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, |
| 36 | 37 | ||
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index a4677802fb20..2a6e3163d944 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
| @@ -1835,7 +1835,7 @@ static int at91udc_resume(struct platform_device *pdev) | |||
| 1835 | #define at91udc_resume NULL | 1835 | #define at91udc_resume NULL |
| 1836 | #endif | 1836 | #endif |
| 1837 | 1837 | ||
| 1838 | static struct platform_driver at91_udc = { | 1838 | static struct platform_driver at91_udc_driver = { |
| 1839 | .remove = __exit_p(at91udc_remove), | 1839 | .remove = __exit_p(at91udc_remove), |
| 1840 | .shutdown = at91udc_shutdown, | 1840 | .shutdown = at91udc_shutdown, |
| 1841 | .suspend = at91udc_suspend, | 1841 | .suspend = at91udc_suspend, |
| @@ -1848,13 +1848,13 @@ static struct platform_driver at91_udc = { | |||
| 1848 | 1848 | ||
| 1849 | static int __init udc_init_module(void) | 1849 | static int __init udc_init_module(void) |
| 1850 | { | 1850 | { |
| 1851 | return platform_driver_probe(&at91_udc, at91udc_probe); | 1851 | return platform_driver_probe(&at91_udc_driver, at91udc_probe); |
| 1852 | } | 1852 | } |
| 1853 | module_init(udc_init_module); | 1853 | module_init(udc_init_module); |
| 1854 | 1854 | ||
| 1855 | static void __exit udc_exit_module(void) | 1855 | static void __exit udc_exit_module(void) |
| 1856 | { | 1856 | { |
| 1857 | platform_driver_unregister(&at91_udc); | 1857 | platform_driver_unregister(&at91_udc_driver); |
| 1858 | } | 1858 | } |
| 1859 | module_exit(udc_exit_module); | 1859 | module_exit(udc_exit_module); |
| 1860 | 1860 | ||
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 7b3a326b57ab..65c91d3735de 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
| @@ -297,27 +297,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
| 297 | 297 | ||
| 298 | /*-------------------------------------------------------------------------*/ | 298 | /*-------------------------------------------------------------------------*/ |
| 299 | 299 | ||
| 300 | #undef USE_KMALLOC | ||
| 301 | |||
| 302 | /* many common platforms have dma-coherent caches, which means that it's | ||
| 303 | * safe to use kmalloc() memory for all i/o buffers without using any | ||
| 304 | * cache flushing calls. (unless you're trying to share cache lines | ||
| 305 | * between dma and non-dma activities, which is a slow idea in any case.) | ||
| 306 | * | ||
| 307 | * other platforms need more care, with 2.6 having a moderately general | ||
| 308 | * solution except for the common "buffer is smaller than a page" case. | ||
| 309 | */ | ||
| 310 | #if defined(CONFIG_X86) | ||
| 311 | #define USE_KMALLOC | ||
| 312 | |||
| 313 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) | ||
| 314 | #define USE_KMALLOC | ||
| 315 | |||
| 316 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
| 317 | #define USE_KMALLOC | ||
| 318 | |||
| 319 | #endif | ||
| 320 | |||
| 321 | /* allocating buffers this way eliminates dma mapping overhead, which | 300 | /* allocating buffers this way eliminates dma mapping overhead, which |
| 322 | * on some platforms will mean eliminating a per-io buffer copy. with | 301 | * on some platforms will mean eliminating a per-io buffer copy. with |
| 323 | * some kinds of system caches, further tweaks may still be needed. | 302 | * 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 | return NULL; | 313 | return NULL; |
| 335 | *dma = DMA_ADDR_INVALID; | 314 | *dma = DMA_ADDR_INVALID; |
| 336 | 315 | ||
| 337 | #if defined(USE_KMALLOC) | ||
| 338 | retval = kmalloc(bytes, gfp_flags); | ||
| 339 | if (retval) | ||
| 340 | *dma = virt_to_phys(retval); | ||
| 341 | #else | ||
| 342 | if (ep->dma) { | 316 | if (ep->dma) { |
| 343 | /* the main problem with this call is that it wastes memory | 317 | /* the main problem with this call is that it wastes memory |
| 344 | * on typical 1/N page allocations: it allocates 1-N pages. | 318 | * 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 | bytes, dma, gfp_flags); | 322 | bytes, dma, gfp_flags); |
| 349 | } else | 323 | } else |
| 350 | retval = kmalloc(bytes, gfp_flags); | 324 | retval = kmalloc(bytes, gfp_flags); |
| 351 | #endif | ||
| 352 | return retval; | 325 | return retval; |
| 353 | } | 326 | } |
| 354 | 327 | ||
| @@ -356,7 +329,6 @@ static void | |||
| 356 | goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) | 329 | goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) |
| 357 | { | 330 | { |
| 358 | /* free memory into the right allocator */ | 331 | /* free memory into the right allocator */ |
| 359 | #ifndef USE_KMALLOC | ||
| 360 | if (dma != DMA_ADDR_INVALID) { | 332 | if (dma != DMA_ADDR_INVALID) { |
| 361 | struct goku_ep *ep; | 333 | struct goku_ep *ep; |
| 362 | 334 | ||
| @@ -365,7 +337,6 @@ goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) | |||
| 365 | return; | 337 | return; |
| 366 | dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); | 338 | dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); |
| 367 | } else | 339 | } else |
| 368 | #endif | ||
| 369 | kfree (buf); | 340 | kfree (buf); |
| 370 | } | 341 | } |
| 371 | 342 | ||
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 8f9a2b615422..b394e63894d2 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
| @@ -296,6 +296,15 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) | |||
| 296 | 296 | ||
| 297 | /*-------------------------------------------------------------------------*/ | 297 | /*-------------------------------------------------------------------------*/ |
| 298 | 298 | ||
| 299 | /* | ||
| 300 | * dma-coherent memory allocation (for dma-capable endpoints) | ||
| 301 | * | ||
| 302 | * NOTE: the dma_*_coherent() API calls suck. Most implementations are | ||
| 303 | * (a) page-oriented, so small buffers lose big; and (b) asymmetric with | ||
| 304 | * respect to calls with irqs disabled: alloc is safe, free is not. | ||
| 305 | * We currently work around (b), but not (a). | ||
| 306 | */ | ||
| 307 | |||
| 299 | static void * | 308 | static void * |
| 300 | omap_alloc_buffer( | 309 | omap_alloc_buffer( |
| 301 | struct usb_ep *_ep, | 310 | struct usb_ep *_ep, |
| @@ -307,6 +316,9 @@ omap_alloc_buffer( | |||
| 307 | void *retval; | 316 | void *retval; |
| 308 | struct omap_ep *ep; | 317 | struct omap_ep *ep; |
| 309 | 318 | ||
| 319 | if (!_ep) | ||
| 320 | return NULL; | ||
| 321 | |||
| 310 | ep = container_of(_ep, struct omap_ep, ep); | 322 | ep = container_of(_ep, struct omap_ep, ep); |
| 311 | if (use_dma && ep->has_dma) { | 323 | if (use_dma && ep->has_dma) { |
| 312 | static int warned; | 324 | static int warned; |
| @@ -326,6 +338,35 @@ omap_alloc_buffer( | |||
| 326 | return retval; | 338 | return retval; |
| 327 | } | 339 | } |
| 328 | 340 | ||
| 341 | static DEFINE_SPINLOCK(buflock); | ||
| 342 | static LIST_HEAD(buffers); | ||
| 343 | |||
| 344 | struct free_record { | ||
| 345 | struct list_head list; | ||
| 346 | struct device *dev; | ||
| 347 | unsigned bytes; | ||
| 348 | dma_addr_t dma; | ||
| 349 | }; | ||
| 350 | |||
| 351 | static void do_free(unsigned long ignored) | ||
| 352 | { | ||
| 353 | spin_lock_irq(&buflock); | ||
| 354 | while (!list_empty(&buffers)) { | ||
| 355 | struct free_record *buf; | ||
| 356 | |||
| 357 | buf = list_entry(buffers.next, struct free_record, list); | ||
| 358 | list_del(&buf->list); | ||
| 359 | spin_unlock_irq(&buflock); | ||
| 360 | |||
| 361 | dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma); | ||
| 362 | |||
| 363 | spin_lock_irq(&buflock); | ||
| 364 | } | ||
| 365 | spin_unlock_irq(&buflock); | ||
| 366 | } | ||
| 367 | |||
| 368 | static DECLARE_TASKLET(deferred_free, do_free, 0); | ||
| 369 | |||
| 329 | static void omap_free_buffer( | 370 | static void omap_free_buffer( |
| 330 | struct usb_ep *_ep, | 371 | struct usb_ep *_ep, |
| 331 | void *buf, | 372 | void *buf, |
| @@ -333,13 +374,29 @@ static void omap_free_buffer( | |||
| 333 | unsigned bytes | 374 | unsigned bytes |
| 334 | ) | 375 | ) |
| 335 | { | 376 | { |
| 336 | struct omap_ep *ep; | 377 | if (!_ep) { |
| 378 | WARN_ON(1); | ||
| 379 | return; | ||
| 380 | } | ||
| 337 | 381 | ||
| 338 | ep = container_of(_ep, struct omap_ep, ep); | 382 | /* free memory into the right allocator */ |
| 339 | if (use_dma && _ep && ep->has_dma) | 383 | if (dma != DMA_ADDR_INVALID) { |
| 340 | dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma); | 384 | struct omap_ep *ep; |
| 341 | else | 385 | struct free_record *rec = buf; |
| 342 | kfree (buf); | 386 | unsigned long flags; |
| 387 | |||
| 388 | ep = container_of(_ep, struct omap_ep, ep); | ||
| 389 | |||
| 390 | rec->dev = ep->udc->gadget.dev.parent; | ||
| 391 | rec->bytes = bytes; | ||
| 392 | rec->dma = dma; | ||
| 393 | |||
| 394 | spin_lock_irqsave(&buflock, flags); | ||
| 395 | list_add_tail(&rec->list, &buffers); | ||
| 396 | tasklet_schedule(&deferred_free); | ||
| 397 | spin_unlock_irqrestore(&buflock, flags); | ||
| 398 | } else | ||
| 399 | kfree(buf); | ||
| 343 | } | 400 | } |
| 344 | 401 | ||
| 345 | /*-------------------------------------------------------------------------*/ | 402 | /*-------------------------------------------------------------------------*/ |
| @@ -1691,12 +1748,38 @@ ep0out_status_stage: | |||
| 1691 | udc->ep0_pending = 0; | 1748 | udc->ep0_pending = 0; |
| 1692 | break; | 1749 | break; |
| 1693 | case USB_REQ_GET_STATUS: | 1750 | case USB_REQ_GET_STATUS: |
| 1751 | /* USB_ENDPOINT_HALT status? */ | ||
| 1752 | if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) | ||
| 1753 | goto intf_status; | ||
| 1754 | |||
| 1755 | /* ep0 never stalls */ | ||
| 1756 | if (!(w_index & 0xf)) | ||
| 1757 | goto zero_status; | ||
| 1758 | |||
| 1759 | /* only active endpoints count */ | ||
| 1760 | ep = &udc->ep[w_index & 0xf]; | ||
| 1761 | if (w_index & USB_DIR_IN) | ||
| 1762 | ep += 16; | ||
| 1763 | if (!ep->desc) | ||
| 1764 | goto do_stall; | ||
| 1765 | |||
| 1766 | /* iso never stalls */ | ||
| 1767 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) | ||
| 1768 | goto zero_status; | ||
| 1769 | |||
| 1770 | /* FIXME don't assume non-halted endpoints!! */ | ||
| 1771 | ERR("%s status, can't report\n", ep->ep.name); | ||
| 1772 | goto do_stall; | ||
| 1773 | |||
| 1774 | intf_status: | ||
| 1694 | /* return interface status. if we were pedantic, | 1775 | /* return interface status. if we were pedantic, |
| 1695 | * we'd detect non-existent interfaces, and stall. | 1776 | * we'd detect non-existent interfaces, and stall. |
| 1696 | */ | 1777 | */ |
| 1697 | if (u.r.bRequestType | 1778 | if (u.r.bRequestType |
| 1698 | != (USB_DIR_IN|USB_RECIP_INTERFACE)) | 1779 | != (USB_DIR_IN|USB_RECIP_INTERFACE)) |
| 1699 | goto delegate; | 1780 | goto delegate; |
| 1781 | |||
| 1782 | zero_status: | ||
| 1700 | /* return two zero bytes */ | 1783 | /* return two zero bytes */ |
| 1701 | UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; | 1784 | UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; |
| 1702 | UDC_DATA_REG = 0; | 1785 | UDC_DATA_REG = 0; |
| @@ -2068,7 +2151,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) | |||
| 2068 | 2151 | ||
| 2069 | /*-------------------------------------------------------------------------*/ | 2152 | /*-------------------------------------------------------------------------*/ |
| 2070 | 2153 | ||
| 2071 | static inline int machine_needs_vbus_session(void) | 2154 | static inline int machine_without_vbus_sense(void) |
| 2072 | { | 2155 | { |
| 2073 | return (machine_is_omap_innovator() | 2156 | return (machine_is_omap_innovator() |
| 2074 | || machine_is_omap_osk() | 2157 | || machine_is_omap_osk() |
| @@ -2156,7 +2239,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
| 2156 | /* boards that don't have VBUS sensing can't autogate 48MHz; | 2239 | /* boards that don't have VBUS sensing can't autogate 48MHz; |
| 2157 | * can't enter deep sleep while a gadget driver is active. | 2240 | * can't enter deep sleep while a gadget driver is active. |
| 2158 | */ | 2241 | */ |
| 2159 | if (machine_needs_vbus_session()) | 2242 | if (machine_without_vbus_sense()) |
| 2160 | omap_vbus_session(&udc->gadget, 1); | 2243 | omap_vbus_session(&udc->gadget, 1); |
| 2161 | 2244 | ||
| 2162 | done: | 2245 | done: |
| @@ -2179,7 +2262,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
| 2179 | if (udc->dc_clk != NULL) | 2262 | if (udc->dc_clk != NULL) |
| 2180 | omap_udc_enable_clock(1); | 2263 | omap_udc_enable_clock(1); |
| 2181 | 2264 | ||
| 2182 | if (machine_needs_vbus_session()) | 2265 | if (machine_without_vbus_sense()) |
| 2183 | omap_vbus_session(&udc->gadget, 0); | 2266 | omap_vbus_session(&udc->gadget, 0); |
| 2184 | 2267 | ||
| 2185 | if (udc->transceiver) | 2268 | if (udc->transceiver) |
| @@ -2822,7 +2905,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) | |||
| 2822 | hmc = HMC_1510; | 2905 | hmc = HMC_1510; |
| 2823 | type = "(unknown)"; | 2906 | type = "(unknown)"; |
| 2824 | 2907 | ||
| 2825 | if (machine_is_omap_innovator() || machine_is_sx1()) { | 2908 | if (machine_without_vbus_sense()) { |
| 2826 | /* just set up software VBUS detect, and then | 2909 | /* just set up software VBUS detect, and then |
| 2827 | * later rig it so we always report VBUS. | 2910 | * later rig it so we always report VBUS. |
| 2828 | * FIXME without really sensing VBUS, we can't | 2911 | * FIXME without really sensing VBUS, we can't |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a74056488234..c7458f7e56cc 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -669,6 +669,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
| 669 | */ | 669 | */ |
| 670 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); | 670 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); |
| 671 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); | 671 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); |
| 672 | mod_timer(&hcd->rh_timer, ehci->reset_done[i]); | ||
| 672 | } | 673 | } |
| 673 | } | 674 | } |
| 674 | 675 | ||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 9af529d22b3e..1813b7cac294 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
| @@ -653,8 +653,7 @@ static int ehci_hub_control ( | |||
| 653 | if (status & ~0xffff) /* only if wPortChange is interesting */ | 653 | if (status & ~0xffff) /* only if wPortChange is interesting */ |
| 654 | #endif | 654 | #endif |
| 655 | dbg_port (ehci, "GetStatus", wIndex + 1, temp); | 655 | dbg_port (ehci, "GetStatus", wIndex + 1, temp); |
| 656 | // we "know" this alignment is good, caller used kmalloc()... | 656 | put_unaligned(cpu_to_le32 (status), (__le32 *) buf); |
| 657 | *((__le32 *) buf) = cpu_to_le32 (status); | ||
| 658 | break; | 657 | break; |
| 659 | case SetHubFeature: | 658 | case SetHubFeature: |
| 660 | switch (wValue) { | 659 | switch (wValue) { |
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 8d24d3dc0a61..1497371583b9 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
| @@ -145,7 +145,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) | |||
| 145 | return out - buf; | 145 | return out - buf; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | 148 | static int uhci_show_qh(struct uhci_hcd *uhci, |
| 149 | struct uhci_qh *qh, char *buf, int len, int space) | ||
| 149 | { | 150 | { |
| 150 | char *out = buf; | 151 | char *out = buf; |
| 151 | int i, nurbs; | 152 | int i, nurbs; |
| @@ -190,6 +191,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
| 190 | 191 | ||
| 191 | if (list_empty(&qh->queue)) { | 192 | if (list_empty(&qh->queue)) { |
| 192 | out += sprintf(out, "%*s queue is empty\n", space, ""); | 193 | out += sprintf(out, "%*s queue is empty\n", space, ""); |
| 194 | if (qh == uhci->skel_async_qh) | ||
| 195 | out += uhci_show_td(uhci->term_td, out, | ||
| 196 | len - (out - buf), 0); | ||
| 193 | } else { | 197 | } else { |
| 194 | struct urb_priv *urbp = list_entry(qh->queue.next, | 198 | struct urb_priv *urbp = list_entry(qh->queue.next, |
| 195 | struct urb_priv, node); | 199 | struct urb_priv, node); |
| @@ -343,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
| 343 | struct list_head *tmp, *head; | 347 | struct list_head *tmp, *head; |
| 344 | int nframes, nerrs; | 348 | int nframes, nerrs; |
| 345 | __le32 link; | 349 | __le32 link; |
| 350 | __le32 fsbr_link; | ||
| 346 | 351 | ||
| 347 | static const char * const qh_names[] = { | 352 | static const char * const qh_names[] = { |
| 348 | "unlink", "iso", "int128", "int64", "int32", "int16", | 353 | "unlink", "iso", "int128", "int64", "int32", "int16", |
| @@ -424,21 +429,22 @@ check_link: | |||
| 424 | 429 | ||
| 425 | out += sprintf(out, "Skeleton QHs\n"); | 430 | out += sprintf(out, "Skeleton QHs\n"); |
| 426 | 431 | ||
| 432 | fsbr_link = 0; | ||
| 427 | for (i = 0; i < UHCI_NUM_SKELQH; ++i) { | 433 | for (i = 0; i < UHCI_NUM_SKELQH; ++i) { |
| 428 | int cnt = 0; | 434 | int cnt = 0; |
| 429 | __le32 fsbr_link = 0; | ||
| 430 | 435 | ||
| 431 | qh = uhci->skelqh[i]; | 436 | qh = uhci->skelqh[i]; |
| 432 | out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ | 437 | out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ |
| 433 | out += uhci_show_qh(qh, out, len - (out - buf), 4); | 438 | out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); |
| 434 | 439 | ||
| 435 | /* Last QH is the Terminating QH, it's different */ | 440 | /* Last QH is the Terminating QH, it's different */ |
| 436 | if (i == SKEL_TERM) { | 441 | if (i == SKEL_TERM) { |
| 437 | if (qh_element(qh) != LINK_TO_TD(uhci->term_td)) | 442 | if (qh_element(qh) != LINK_TO_TD(uhci->term_td)) |
| 438 | out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); | 443 | out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); |
| 439 | if (link == LINK_TO_QH(uhci->skel_term_qh)) | 444 | link = fsbr_link; |
| 440 | goto check_qh_link; | 445 | if (!link) |
| 441 | continue; | 446 | link = LINK_TO_QH(uhci->skel_term_qh); |
| 447 | goto check_qh_link; | ||
| 442 | } | 448 | } |
| 443 | 449 | ||
| 444 | head = &qh->node; | 450 | head = &qh->node; |
| @@ -448,7 +454,7 @@ check_link: | |||
| 448 | qh = list_entry(tmp, struct uhci_qh, node); | 454 | qh = list_entry(tmp, struct uhci_qh, node); |
| 449 | tmp = tmp->next; | 455 | tmp = tmp->next; |
| 450 | if (++cnt <= 10) | 456 | if (++cnt <= 10) |
| 451 | out += uhci_show_qh(qh, out, | 457 | out += uhci_show_qh(uhci, qh, out, |
| 452 | len - (out - buf), 4); | 458 | len - (out - buf), 4); |
| 453 | if (!fsbr_link && qh->skel >= SKEL_FSBR) | 459 | if (!fsbr_link && qh->skel >= SKEL_FSBR) |
| 454 | fsbr_link = LINK_TO_QH(qh); | 460 | fsbr_link = LINK_TO_QH(qh); |
| @@ -463,8 +469,6 @@ check_link: | |||
| 463 | link = LINK_TO_QH(uhci->skel_async_qh); | 469 | link = LINK_TO_QH(uhci->skel_async_qh); |
| 464 | else if (!uhci->fsbr_is_on) | 470 | else if (!uhci->fsbr_is_on) |
| 465 | ; | 471 | ; |
| 466 | else if (fsbr_link) | ||
| 467 | link = fsbr_link; | ||
| 468 | else | 472 | else |
| 469 | link = LINK_TO_QH(uhci->skel_term_qh); | 473 | link = LINK_TO_QH(uhci->skel_term_qh); |
| 470 | check_qh_link: | 474 | check_qh_link: |
| @@ -573,8 +577,8 @@ static const struct file_operations uhci_debug_operations = { | |||
| 573 | static inline void lprintk(char *buf) | 577 | static inline void lprintk(char *buf) |
| 574 | {} | 578 | {} |
| 575 | 579 | ||
| 576 | static inline int uhci_show_qh(struct uhci_qh *qh, char *buf, | 580 | static inline int uhci_show_qh(struct uhci_hcd *uhci, |
| 577 | int len, int space) | 581 | struct uhci_qh *qh, char *buf, int len, int space) |
| 578 | { | 582 | { |
| 579 | return 0; | 583 | return 0; |
| 580 | } | 584 | } |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 44da4334f1d6..d22da26ff167 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -632,7 +632,8 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 632 | */ | 632 | */ |
| 633 | for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i) | 633 | for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i) |
| 634 | uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh); | 634 | uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh); |
| 635 | uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM; | 635 | uhci->skel_async_qh->link = UHCI_PTR_TERM; |
| 636 | uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh); | ||
| 636 | 637 | ||
| 637 | /* This dummy TD is to work around a bug in Intel PIIX controllers */ | 638 | /* This dummy TD is to work around a bug in Intel PIIX controllers */ |
| 638 | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | | 639 | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index bacc25c53ba3..8e4427aebb14 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
| @@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] = | |||
| 33 | /* status change bits: nonzero writes will clear */ | 33 | /* status change bits: nonzero writes will clear */ |
| 34 | #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) | 34 | #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) |
| 35 | 35 | ||
| 36 | /* suspend/resume bits: port suspended or port resuming */ | ||
| 37 | #define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD) | ||
| 38 | |||
| 36 | /* A port that either is connected or has a changed-bit set will prevent | 39 | /* A port that either is connected or has a changed-bit set will prevent |
| 37 | * us from AUTO_STOPPING. | 40 | * us from AUTO_STOPPING. |
| 38 | */ | 41 | */ |
| @@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
| 96 | int status; | 99 | int status; |
| 97 | int i; | 100 | int i; |
| 98 | 101 | ||
| 99 | if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { | 102 | if (inw(port_addr) & SUSPEND_BITS) { |
| 100 | CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); | 103 | CLR_RH_PORTSTAT(SUSPEND_BITS); |
| 101 | if (test_bit(port, &uhci->resuming_ports)) | 104 | if (test_bit(port, &uhci->resuming_ports)) |
| 102 | set_bit(port, &uhci->port_c_suspend); | 105 | set_bit(port, &uhci->port_c_suspend); |
| 103 | 106 | ||
| @@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
| 107 | * Experiments show that some controllers take longer, so | 110 | * Experiments show that some controllers take longer, so |
| 108 | * we'll poll for completion. */ | 111 | * we'll poll for completion. */ |
| 109 | for (i = 0; i < 10; ++i) { | 112 | for (i = 0; i < 10; ++i) { |
| 110 | if (!(inw(port_addr) & USBPORTSC_RD)) | 113 | if (!(inw(port_addr) & SUSPEND_BITS)) |
| 111 | break; | 114 | break; |
| 112 | udelay(1); | 115 | udelay(1); |
| 113 | } | 116 | } |
| @@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
| 289 | wPortStatus |= USB_PORT_STAT_CONNECTION; | 292 | wPortStatus |= USB_PORT_STAT_CONNECTION; |
| 290 | if (status & USBPORTSC_PE) { | 293 | if (status & USBPORTSC_PE) { |
| 291 | wPortStatus |= USB_PORT_STAT_ENABLE; | 294 | wPortStatus |= USB_PORT_STAT_ENABLE; |
| 292 | if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) | 295 | if (status & SUSPEND_BITS) |
| 293 | wPortStatus |= USB_PORT_STAT_SUSPEND; | 296 | wPortStatus |= USB_PORT_STAT_SUSPEND; |
| 294 | } | 297 | } |
| 295 | if (status & USBPORTSC_OC) | 298 | if (status & USBPORTSC_OC) |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index f4ebdb3e488f..19a0cc02b9a2 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
| @@ -45,43 +45,27 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) | |||
| 45 | */ | 45 | */ |
| 46 | static void uhci_fsbr_on(struct uhci_hcd *uhci) | 46 | static void uhci_fsbr_on(struct uhci_hcd *uhci) |
| 47 | { | 47 | { |
| 48 | struct uhci_qh *fsbr_qh, *lqh, *tqh; | 48 | struct uhci_qh *lqh; |
| 49 | 49 | ||
| 50 | /* The terminating skeleton QH always points back to the first | ||
| 51 | * FSBR QH. Make the last async QH point to the terminating | ||
| 52 | * skeleton QH. */ | ||
| 50 | uhci->fsbr_is_on = 1; | 53 | uhci->fsbr_is_on = 1; |
| 51 | lqh = list_entry(uhci->skel_async_qh->node.prev, | 54 | lqh = list_entry(uhci->skel_async_qh->node.prev, |
| 52 | struct uhci_qh, node); | 55 | struct uhci_qh, node); |
| 53 | 56 | lqh->link = LINK_TO_QH(uhci->skel_term_qh); | |
| 54 | /* Find the first FSBR QH. Linear search through the list is | ||
| 55 | * acceptable because normally FSBR gets turned on as soon as | ||
| 56 | * one QH needs it. */ | ||
| 57 | fsbr_qh = NULL; | ||
| 58 | list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) { | ||
| 59 | if (tqh->skel < SKEL_FSBR) | ||
| 60 | break; | ||
| 61 | fsbr_qh = tqh; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* No FSBR QH means we must insert the terminating skeleton QH */ | ||
| 65 | if (!fsbr_qh) { | ||
| 66 | uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh); | ||
| 67 | wmb(); | ||
| 68 | lqh->link = uhci->skel_term_qh->link; | ||
| 69 | |||
| 70 | /* Otherwise loop the last QH to the first FSBR QH */ | ||
| 71 | } else | ||
| 72 | lqh->link = LINK_TO_QH(fsbr_qh); | ||
| 73 | } | 57 | } |
| 74 | 58 | ||
| 75 | static void uhci_fsbr_off(struct uhci_hcd *uhci) | 59 | static void uhci_fsbr_off(struct uhci_hcd *uhci) |
| 76 | { | 60 | { |
| 77 | struct uhci_qh *lqh; | 61 | struct uhci_qh *lqh; |
| 78 | 62 | ||
| 63 | /* Remove the link from the last async QH to the terminating | ||
| 64 | * skeleton QH. */ | ||
| 79 | uhci->fsbr_is_on = 0; | 65 | uhci->fsbr_is_on = 0; |
| 80 | lqh = list_entry(uhci->skel_async_qh->node.prev, | 66 | lqh = list_entry(uhci->skel_async_qh->node.prev, |
| 81 | struct uhci_qh, node); | 67 | struct uhci_qh, node); |
| 82 | 68 | lqh->link = UHCI_PTR_TERM; | |
| 83 | /* End the async list normally and unlink the terminating QH */ | ||
| 84 | lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
| 85 | } | 69 | } |
| 86 | 70 | ||
| 87 | static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) | 71 | static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) |
| @@ -464,9 +448,8 @@ static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
| 464 | */ | 448 | */ |
| 465 | static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) | 449 | static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) |
| 466 | { | 450 | { |
| 467 | struct uhci_qh *pqh, *lqh; | 451 | struct uhci_qh *pqh; |
| 468 | __le32 link_to_new_qh; | 452 | __le32 link_to_new_qh; |
| 469 | __le32 *extra_link = &link_to_new_qh; | ||
| 470 | 453 | ||
| 471 | /* Find the predecessor QH for our new one and insert it in the list. | 454 | /* Find the predecessor QH for our new one and insert it in the list. |
| 472 | * The list of QHs is expected to be short, so linear search won't | 455 | * The list of QHs is expected to be short, so linear search won't |
| @@ -476,31 +459,17 @@ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
| 476 | break; | 459 | break; |
| 477 | } | 460 | } |
| 478 | list_add(&qh->node, &pqh->node); | 461 | list_add(&qh->node, &pqh->node); |
| 479 | qh->link = pqh->link; | ||
| 480 | |||
| 481 | link_to_new_qh = LINK_TO_QH(qh); | ||
| 482 | |||
| 483 | /* If this is now the first FSBR QH, take special action */ | ||
| 484 | if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR && | ||
| 485 | qh->skel >= SKEL_FSBR) { | ||
| 486 | lqh = list_entry(uhci->skel_async_qh->node.prev, | ||
| 487 | struct uhci_qh, node); | ||
| 488 | |||
| 489 | /* If the new QH is also the last one, we must unlink | ||
| 490 | * the terminating skeleton QH and make the new QH point | ||
| 491 | * back to itself. */ | ||
| 492 | if (qh == lqh) { | ||
| 493 | qh->link = link_to_new_qh; | ||
| 494 | extra_link = &uhci->skel_term_qh->link; | ||
| 495 | |||
| 496 | /* Otherwise the last QH must point to the new QH */ | ||
| 497 | } else | ||
| 498 | extra_link = &lqh->link; | ||
| 499 | } | ||
| 500 | 462 | ||
| 501 | /* Link it into the schedule */ | 463 | /* Link it into the schedule */ |
| 464 | qh->link = pqh->link; | ||
| 502 | wmb(); | 465 | wmb(); |
| 503 | *extra_link = pqh->link = link_to_new_qh; | 466 | link_to_new_qh = LINK_TO_QH(qh); |
| 467 | pqh->link = link_to_new_qh; | ||
| 468 | |||
| 469 | /* If this is now the first FSBR QH, link the terminating skeleton | ||
| 470 | * QH to it. */ | ||
| 471 | if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR) | ||
| 472 | uhci->skel_term_qh->link = link_to_new_qh; | ||
| 504 | } | 473 | } |
| 505 | 474 | ||
| 506 | /* | 475 | /* |
| @@ -561,31 +530,16 @@ static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
| 561 | */ | 530 | */ |
| 562 | static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh) | 531 | static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh) |
| 563 | { | 532 | { |
| 564 | struct uhci_qh *pqh, *lqh; | 533 | struct uhci_qh *pqh; |
| 565 | __le32 link_to_next_qh = qh->link; | 534 | __le32 link_to_next_qh = qh->link; |
| 566 | 535 | ||
| 567 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); | 536 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); |
| 568 | |||
| 569 | /* If this is the first FSBQ QH, take special action */ | ||
| 570 | if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR && | ||
| 571 | qh->skel >= SKEL_FSBR) { | ||
| 572 | lqh = list_entry(uhci->skel_async_qh->node.prev, | ||
| 573 | struct uhci_qh, node); | ||
| 574 | |||
| 575 | /* If this QH is also the last one, we must link in | ||
| 576 | * the terminating skeleton QH. */ | ||
| 577 | if (qh == lqh) { | ||
| 578 | link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh); | ||
| 579 | uhci->skel_term_qh->link = link_to_next_qh; | ||
| 580 | wmb(); | ||
| 581 | qh->link = link_to_next_qh; | ||
| 582 | |||
| 583 | /* Otherwise the last QH must point to the new first FSBR QH */ | ||
| 584 | } else | ||
| 585 | lqh->link = link_to_next_qh; | ||
| 586 | } | ||
| 587 | |||
| 588 | pqh->link = link_to_next_qh; | 537 | pqh->link = link_to_next_qh; |
| 538 | |||
| 539 | /* If this was the old first FSBR QH, link the terminating skeleton | ||
| 540 | * QH to the next (new first FSBR) QH. */ | ||
| 541 | if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR) | ||
| 542 | uhci->skel_term_qh->link = link_to_next_qh; | ||
| 589 | mb(); | 543 | mb(); |
| 590 | } | 544 | } |
| 591 | 545 | ||
| @@ -1217,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) | |||
| 1217 | 1171 | ||
| 1218 | if (debug > 1 && errbuf) { | 1172 | if (debug > 1 && errbuf) { |
| 1219 | /* Print the chain for debugging */ | 1173 | /* Print the chain for debugging */ |
| 1220 | uhci_show_qh(urbp->qh, errbuf, | 1174 | uhci_show_qh(uhci, urbp->qh, errbuf, |
| 1221 | ERRBUF_LEN, 0); | 1175 | ERRBUF_LEN, 0); |
| 1222 | lprintk(errbuf); | 1176 | lprintk(errbuf); |
| 1223 | } | 1177 | } |
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index 60893c6c8221..b15f2fd8dab4 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c | |||
| @@ -69,7 +69,7 @@ static int magic_charge(struct usb_device *udev) | |||
| 69 | return retval; | 69 | return retval; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | dbg(&udev->dev, "Sending first magic command\n"); | 72 | dbg(&udev->dev, "Sending second magic command\n"); |
| 73 | retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 73 | retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 74 | 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100); | 74 | 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100); |
| 75 | if (retval != 0) { | 75 | if (retval != 0) { |
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 0c1d66ddb812..bc3327e3dd78 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
| @@ -2905,17 +2905,31 @@ static int __init ftdi_elan_init(void) | |||
| 2905 | { | 2905 | { |
| 2906 | int result; | 2906 | int result; |
| 2907 | printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, | 2907 | printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, |
| 2908 | __TIME__, __DATE__); | 2908 | __TIME__, __DATE__); |
| 2909 | init_MUTEX(&ftdi_module_lock); | 2909 | init_MUTEX(&ftdi_module_lock); |
| 2910 | INIT_LIST_HEAD(&ftdi_static_list); | 2910 | INIT_LIST_HEAD(&ftdi_static_list); |
| 2911 | status_queue = create_singlethread_workqueue("ftdi-status-control"); | 2911 | status_queue = create_singlethread_workqueue("ftdi-status-control"); |
| 2912 | if (!status_queue) | ||
| 2913 | goto err1; | ||
| 2912 | command_queue = create_singlethread_workqueue("ftdi-command-engine"); | 2914 | command_queue = create_singlethread_workqueue("ftdi-command-engine"); |
| 2915 | if (!command_queue) | ||
| 2916 | goto err2; | ||
| 2913 | respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); | 2917 | respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); |
| 2918 | if (!respond_queue) | ||
| 2919 | goto err3; | ||
| 2914 | result = usb_register(&ftdi_elan_driver); | 2920 | result = usb_register(&ftdi_elan_driver); |
| 2915 | if (result) | 2921 | if (result) |
| 2916 | printk(KERN_ERR "usb_register failed. Error number %d\n", | 2922 | printk(KERN_ERR "usb_register failed. Error number %d\n", |
| 2917 | result); | 2923 | result); |
| 2918 | return result; | 2924 | return result; |
| 2925 | |||
| 2926 | err3: | ||
| 2927 | destroy_workqueue(command_queue); | ||
| 2928 | err2: | ||
| 2929 | destroy_workqueue(status_queue); | ||
| 2930 | err1: | ||
| 2931 | printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name); | ||
| 2932 | return -ENOMEM; | ||
| 2919 | } | 2933 | } |
| 2920 | 2934 | ||
| 2921 | static void __exit ftdi_elan_exit(void) | 2935 | static void __exit ftdi_elan_exit(void) |
diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c index 4a932e1cd93b..5130cc7eb314 100644 --- a/drivers/usb/net/dm9601.c +++ b/drivers/usb/net/dm9601.c | |||
| @@ -571,9 +571,21 @@ static const struct driver_info dm9601_info = { | |||
| 571 | 571 | ||
| 572 | static const struct usb_device_id products[] = { | 572 | static const struct usb_device_id products[] = { |
| 573 | { | 573 | { |
| 574 | USB_DEVICE(0x07aa, 0x9601), /* Corega FEther USB-TXC */ | ||
| 575 | .driver_info = (unsigned long)&dm9601_info, | ||
| 576 | }, | ||
| 577 | { | ||
| 574 | USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */ | 578 | USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */ |
| 575 | .driver_info = (unsigned long)&dm9601_info, | 579 | .driver_info = (unsigned long)&dm9601_info, |
| 576 | }, | 580 | }, |
| 581 | { | ||
| 582 | USB_DEVICE(0x0a46, 0x6688), /* ZT6688 USB NIC */ | ||
| 583 | .driver_info = (unsigned long)&dm9601_info, | ||
| 584 | }, | ||
| 585 | { | ||
| 586 | USB_DEVICE(0x0a46, 0x0268), /* ShanTou ST268 USB NIC */ | ||
| 587 | .driver_info = (unsigned long)&dm9601_info, | ||
| 588 | }, | ||
| 577 | {}, // END | 589 | {}, // END |
| 578 | }; | 590 | }; |
| 579 | 591 | ||
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index d48c024cff59..6d12961cf9f9 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
| @@ -316,6 +316,7 @@ static int update_eth_regs_async(pegasus_t * pegasus) | |||
| 316 | return ret; | 316 | return ret; |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | /* Returns 0 on success, error on failure */ | ||
| 319 | static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) | 320 | static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) |
| 320 | { | 321 | { |
| 321 | int i; | 322 | int i; |
| @@ -847,10 +848,16 @@ static void intr_callback(struct urb *urb) | |||
| 847 | * d[0].NO_CARRIER kicks in only with failed TX. | 848 | * d[0].NO_CARRIER kicks in only with failed TX. |
| 848 | * ... so monitoring with MII may be safest. | 849 | * ... so monitoring with MII may be safest. |
| 849 | */ | 850 | */ |
| 850 | if (d[0] & NO_CARRIER) | 851 | if (pegasus->features & TRUST_LINK_STATUS) { |
| 851 | netif_carrier_off(net); | 852 | if (d[5] & LINK_STATUS) |
| 852 | else | 853 | netif_carrier_on(net); |
| 853 | netif_carrier_on(net); | 854 | else |
| 855 | netif_carrier_off(net); | ||
| 856 | } else { | ||
| 857 | /* Never set carrier _on_ based on ! NO_CARRIER */ | ||
| 858 | if (d[0] & NO_CARRIER) | ||
| 859 | netif_carrier_off(net); | ||
| 860 | } | ||
| 854 | 861 | ||
| 855 | /* bytes 3-4 == rx_lostpkt, reg 2E/2F */ | 862 | /* bytes 3-4 == rx_lostpkt, reg 2E/2F */ |
| 856 | pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4]; | 863 | pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4]; |
| @@ -950,7 +957,7 @@ static void set_carrier(struct net_device *net) | |||
| 950 | pegasus_t *pegasus = netdev_priv(net); | 957 | pegasus_t *pegasus = netdev_priv(net); |
| 951 | u16 tmp; | 958 | u16 tmp; |
| 952 | 959 | ||
| 953 | if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) | 960 | if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) |
| 954 | return; | 961 | return; |
| 955 | 962 | ||
| 956 | if (tmp & BMSR_LSTATUS) | 963 | if (tmp & BMSR_LSTATUS) |
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index c7467823cd1c..c7aadb413e8c 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #define PEGASUS_II 0x80000000 | 12 | #define PEGASUS_II 0x80000000 |
| 13 | #define HAS_HOME_PNA 0x40000000 | 13 | #define HAS_HOME_PNA 0x40000000 |
| 14 | #define TRUST_LINK_STATUS 0x20000000 | ||
| 14 | 15 | ||
| 15 | #define PEGASUS_MTU 1536 | 16 | #define PEGASUS_MTU 1536 |
| 16 | #define RX_SKBS 4 | 17 | #define RX_SKBS 4 |
| @@ -203,7 +204,7 @@ PEGASUS_DEV( "AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701, | |||
| 203 | PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100, | 204 | PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100, |
| 204 | DEFAULT_GPIO_RESET | PEGASUS_II ) | 205 | DEFAULT_GPIO_RESET | PEGASUS_II ) |
| 205 | PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, | 206 | PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, |
| 206 | DEFAULT_GPIO_RESET | PEGASUS_II ) | 207 | DEFAULT_GPIO_RESET | PEGASUS_II | TRUST_LINK_STATUS ) |
| 207 | PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, | 208 | PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, |
| 208 | DEFAULT_GPIO_RESET ) | 209 | DEFAULT_GPIO_RESET ) |
| 209 | PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987, | 210 | PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987, |
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 18816bf96a4d..39a498362594 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
| @@ -18,11 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | static struct usb_device_id id_table [] = { | 19 | static struct usb_device_id id_table [] = { |
| 20 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ | 20 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ |
| 21 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ | ||
| 22 | { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */ | ||
| 23 | { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */ | ||
| 24 | { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ | ||
| 25 | { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ | ||
| 26 | { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */ | 21 | { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */ |
| 27 | { }, | 22 | { }, |
| 28 | }; | 23 | }; |
| @@ -44,8 +39,43 @@ struct airprime_private { | |||
| 44 | int outstanding_urbs; | 39 | int outstanding_urbs; |
| 45 | int throttled; | 40 | int throttled; |
| 46 | struct urb *read_urbp[NUM_READ_URBS]; | 41 | struct urb *read_urbp[NUM_READ_URBS]; |
| 42 | |||
| 43 | /* Settings for the port */ | ||
| 44 | int rts_state; /* Handshaking pins (outputs) */ | ||
| 45 | int dtr_state; | ||
| 46 | int cts_state; /* Handshaking pins (inputs) */ | ||
| 47 | int dsr_state; | ||
| 48 | int dcd_state; | ||
| 49 | int ri_state; | ||
| 47 | }; | 50 | }; |
| 48 | 51 | ||
| 52 | static int airprime_send_setup(struct usb_serial_port *port) | ||
| 53 | { | ||
| 54 | struct usb_serial *serial = port->serial; | ||
| 55 | struct airprime_private *priv; | ||
| 56 | |||
| 57 | dbg("%s", __FUNCTION__); | ||
| 58 | |||
| 59 | if (port->number != 0) | ||
| 60 | return 0; | ||
| 61 | |||
| 62 | priv = usb_get_serial_port_data(port); | ||
| 63 | |||
| 64 | if (port->tty) { | ||
| 65 | int val = 0; | ||
| 66 | if (priv->dtr_state) | ||
| 67 | val |= 0x01; | ||
| 68 | if (priv->rts_state) | ||
| 69 | val |= 0x02; | ||
| 70 | |||
| 71 | return usb_control_msg(serial->dev, | ||
| 72 | usb_rcvctrlpipe(serial->dev, 0), | ||
| 73 | 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 49 | static void airprime_read_bulk_callback(struct urb *urb) | 79 | static void airprime_read_bulk_callback(struct urb *urb) |
| 50 | { | 80 | { |
| 51 | struct usb_serial_port *port = urb->context; | 81 | struct usb_serial_port *port = urb->context; |
| @@ -118,6 +148,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
| 118 | usb_set_serial_port_data(port, priv); | 148 | usb_set_serial_port_data(port, priv); |
| 119 | } | 149 | } |
| 120 | 150 | ||
| 151 | /* Set some sane defaults */ | ||
| 152 | priv->rts_state = 1; | ||
| 153 | priv->dtr_state = 1; | ||
| 154 | |||
| 121 | for (i = 0; i < NUM_READ_URBS; ++i) { | 155 | for (i = 0; i < NUM_READ_URBS; ++i) { |
| 122 | buffer = kmalloc(buffer_size, GFP_KERNEL); | 156 | buffer = kmalloc(buffer_size, GFP_KERNEL); |
| 123 | if (!buffer) { | 157 | if (!buffer) { |
| @@ -151,6 +185,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
| 151 | /* remember this urb so we can kill it when the port is closed */ | 185 | /* remember this urb so we can kill it when the port is closed */ |
| 152 | priv->read_urbp[i] = urb; | 186 | priv->read_urbp[i] = urb; |
| 153 | } | 187 | } |
| 188 | |||
| 189 | airprime_send_setup(port); | ||
| 190 | |||
| 154 | goto out; | 191 | goto out; |
| 155 | 192 | ||
| 156 | errout: | 193 | errout: |
| @@ -176,6 +213,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp) | |||
| 176 | 213 | ||
| 177 | dbg("%s - port %d", __FUNCTION__, port->number); | 214 | dbg("%s - port %d", __FUNCTION__, port->number); |
| 178 | 215 | ||
| 216 | priv->rts_state = 0; | ||
| 217 | priv->dtr_state = 0; | ||
| 218 | |||
| 219 | airprime_send_setup(port); | ||
| 220 | |||
| 179 | for (i = 0; i < NUM_READ_URBS; ++i) { | 221 | for (i = 0; i < NUM_READ_URBS; ++i) { |
| 180 | usb_kill_urb (priv->read_urbp[i]); | 222 | usb_kill_urb (priv->read_urbp[i]); |
| 181 | kfree (priv->read_urbp[i]->transfer_buffer); | 223 | kfree (priv->read_urbp[i]->transfer_buffer); |
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index db623e754899..d7d0ba986a80 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
| @@ -63,6 +63,8 @@ static struct usb_device_id id_table [] = { | |||
| 63 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ | 63 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ |
| 64 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ | 64 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ |
| 65 | { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ | 65 | { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ |
| 66 | { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ | ||
| 67 | { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ | ||
| 66 | { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ | 68 | { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ |
| 67 | { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ | 69 | { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ |
| 68 | { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ | 70 | { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c525b42dadde..8ff9d54b21e6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -315,6 +315,7 @@ static struct usb_device_id id_table_combined [] = { | |||
| 315 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, | 315 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, |
| 316 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, | 316 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, |
| 317 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, | 317 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, |
| 318 | { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, | ||
| 318 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, | 319 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, |
| 319 | { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, | 320 | { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, |
| 320 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, | 321 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, |
| @@ -420,6 +421,14 @@ static struct usb_device_id id_table_combined [] = { | |||
| 420 | { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, | 421 | { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, |
| 421 | { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, | 422 | { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, |
| 422 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, | 423 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, |
| 424 | { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) }, | ||
| 425 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) }, | ||
| 426 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) }, | ||
| 427 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) }, | ||
| 428 | { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) }, | ||
| 429 | { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, | ||
| 430 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, | ||
| 431 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, | ||
| 423 | /* | 432 | /* |
| 424 | * These will probably use user-space drivers. Uncomment them if | 433 | * These will probably use user-space drivers. Uncomment them if |
| 425 | * you need them or use the user-specified vendor/product module | 434 | * you need them or use the user-specified vendor/product module |
| @@ -459,6 +468,7 @@ static struct usb_device_id id_table_combined [] = { | |||
| 459 | { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, | 468 | { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, |
| 460 | { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, | 469 | { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, |
| 461 | { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, | 470 | { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, |
| 471 | { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, | ||
| 462 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, | 472 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, |
| 463 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, | 473 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, |
| 464 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, | 474 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, |
| @@ -533,6 +543,7 @@ static const char *ftdi_chip_name[] = { | |||
| 533 | [FT8U232AM] = "FT8U232AM", | 543 | [FT8U232AM] = "FT8U232AM", |
| 534 | [FT232BM] = "FT232BM", | 544 | [FT232BM] = "FT232BM", |
| 535 | [FT2232C] = "FT2232C", | 545 | [FT2232C] = "FT2232C", |
| 546 | [FT232RL] = "FT232RL", | ||
| 536 | }; | 547 | }; |
| 537 | 548 | ||
| 538 | 549 | ||
| @@ -588,6 +599,8 @@ struct ftdi_private { | |||
| 588 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); | 599 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); |
| 589 | static int ftdi_sio_attach (struct usb_serial *serial); | 600 | static int ftdi_sio_attach (struct usb_serial *serial); |
| 590 | static void ftdi_shutdown (struct usb_serial *serial); | 601 | static void ftdi_shutdown (struct usb_serial *serial); |
| 602 | static int ftdi_sio_port_probe (struct usb_serial_port *port); | ||
| 603 | static int ftdi_sio_port_remove (struct usb_serial_port *port); | ||
| 591 | static int ftdi_open (struct usb_serial_port *port, struct file *filp); | 604 | static int ftdi_open (struct usb_serial_port *port, struct file *filp); |
| 592 | static void ftdi_close (struct usb_serial_port *port, struct file *filp); | 605 | static void ftdi_close (struct usb_serial_port *port, struct file *filp); |
| 593 | static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); | 606 | 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 | .num_bulk_out = 1, | 635 | .num_bulk_out = 1, |
| 623 | .num_ports = 1, | 636 | .num_ports = 1, |
| 624 | .probe = ftdi_sio_probe, | 637 | .probe = ftdi_sio_probe, |
| 638 | .port_probe = ftdi_sio_port_probe, | ||
| 639 | .port_remove = ftdi_sio_port_remove, | ||
| 625 | .open = ftdi_open, | 640 | .open = ftdi_open, |
| 626 | .close = ftdi_close, | 641 | .close = ftdi_close, |
| 627 | .throttle = ftdi_throttle, | 642 | .throttle = ftdi_throttle, |
| @@ -864,6 +879,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) | |||
| 864 | break; | 879 | break; |
| 865 | case FT232BM: /* FT232BM chip */ | 880 | case FT232BM: /* FT232BM chip */ |
| 866 | case FT2232C: /* FT2232C chip */ | 881 | case FT2232C: /* FT2232C chip */ |
| 882 | case FT232RL: | ||
| 867 | if (baud <= 3000000) { | 883 | if (baud <= 3000000) { |
| 868 | div_value = ftdi_232bm_baud_to_divisor(baud); | 884 | div_value = ftdi_232bm_baud_to_divisor(baud); |
| 869 | } else { | 885 | } else { |
| @@ -1006,9 +1022,12 @@ static void ftdi_determine_type(struct usb_serial_port *port) | |||
| 1006 | /* (It might be a BM because of the iSerialNumber bug, | 1022 | /* (It might be a BM because of the iSerialNumber bug, |
| 1007 | * but it will still work as an AM device.) */ | 1023 | * but it will still work as an AM device.) */ |
| 1008 | priv->chip_type = FT8U232AM; | 1024 | priv->chip_type = FT8U232AM; |
| 1009 | } else { | 1025 | } else if (version < 0x600) { |
| 1010 | /* Assume its an FT232BM (or FT245BM) */ | 1026 | /* Assume its an FT232BM (or FT245BM) */ |
| 1011 | priv->chip_type = FT232BM; | 1027 | priv->chip_type = FT232BM; |
| 1028 | } else { | ||
| 1029 | /* Assume its an FT232R */ | ||
| 1030 | priv->chip_type = FT232RL; | ||
| 1012 | } | 1031 | } |
| 1013 | info("Detected %s", ftdi_chip_name[priv->chip_type]); | 1032 | info("Detected %s", ftdi_chip_name[priv->chip_type]); |
| 1014 | } | 1033 | } |
| @@ -1024,11 +1043,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a | |||
| 1024 | { | 1043 | { |
| 1025 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1044 | struct usb_serial_port *port = to_usb_serial_port(dev); |
| 1026 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1045 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1027 | struct usb_device *udev; | 1046 | struct usb_device *udev = port->serial->dev; |
| 1028 | unsigned short latency = 0; | 1047 | unsigned short latency = 0; |
| 1029 | int rv = 0; | 1048 | int rv = 0; |
| 1030 | 1049 | ||
| 1031 | udev = to_usb_device(dev); | ||
| 1032 | 1050 | ||
| 1033 | dbg("%s",__FUNCTION__); | 1051 | dbg("%s",__FUNCTION__); |
| 1034 | 1052 | ||
| @@ -1052,13 +1070,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute * | |||
| 1052 | { | 1070 | { |
| 1053 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1071 | struct usb_serial_port *port = to_usb_serial_port(dev); |
| 1054 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1072 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1055 | struct usb_device *udev; | 1073 | struct usb_device *udev = port->serial->dev; |
| 1056 | char buf[1]; | 1074 | char buf[1]; |
| 1057 | int v = simple_strtoul(valbuf, NULL, 10); | 1075 | int v = simple_strtoul(valbuf, NULL, 10); |
| 1058 | int rv = 0; | 1076 | int rv = 0; |
| 1059 | 1077 | ||
| 1060 | udev = to_usb_device(dev); | ||
| 1061 | |||
| 1062 | dbg("%s: setting latency timer = %i", __FUNCTION__, v); | 1078 | dbg("%s: setting latency timer = %i", __FUNCTION__, v); |
| 1063 | 1079 | ||
| 1064 | rv = usb_control_msg(udev, | 1080 | rv = usb_control_msg(udev, |
| @@ -1083,13 +1099,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att | |||
| 1083 | { | 1099 | { |
| 1084 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1100 | struct usb_serial_port *port = to_usb_serial_port(dev); |
| 1085 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1101 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1086 | struct usb_device *udev; | 1102 | struct usb_device *udev = port->serial->dev; |
| 1087 | char buf[1]; | 1103 | char buf[1]; |
| 1088 | int v = simple_strtoul(valbuf, NULL, 10); | 1104 | int v = simple_strtoul(valbuf, NULL, 10); |
| 1089 | int rv = 0; | 1105 | int rv = 0; |
| 1090 | 1106 | ||
| 1091 | udev = to_usb_device(dev); | ||
| 1092 | |||
| 1093 | dbg("%s: setting event char = %i", __FUNCTION__, v); | 1107 | dbg("%s: setting event char = %i", __FUNCTION__, v); |
| 1094 | 1108 | ||
| 1095 | rv = usb_control_msg(udev, | 1109 | rv = usb_control_msg(udev, |
| @@ -1110,46 +1124,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att | |||
| 1110 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); | 1124 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); |
| 1111 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); | 1125 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); |
| 1112 | 1126 | ||
| 1113 | static int create_sysfs_attrs(struct usb_serial *serial) | 1127 | static int create_sysfs_attrs(struct usb_serial_port *port) |
| 1114 | { | 1128 | { |
| 1115 | struct ftdi_private *priv; | 1129 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1116 | struct usb_device *udev; | ||
| 1117 | int retval = 0; | 1130 | int retval = 0; |
| 1118 | 1131 | ||
| 1119 | dbg("%s",__FUNCTION__); | 1132 | dbg("%s",__FUNCTION__); |
| 1120 | 1133 | ||
| 1121 | priv = usb_get_serial_port_data(serial->port[0]); | ||
| 1122 | udev = serial->dev; | ||
| 1123 | |||
| 1124 | /* XXX I've no idea if the original SIO supports the event_char | 1134 | /* XXX I've no idea if the original SIO supports the event_char |
| 1125 | * sysfs parameter, so I'm playing it safe. */ | 1135 | * sysfs parameter, so I'm playing it safe. */ |
| 1126 | if (priv->chip_type != SIO) { | 1136 | if (priv->chip_type != SIO) { |
| 1127 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1137 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
| 1128 | retval = device_create_file(&udev->dev, &dev_attr_event_char); | 1138 | retval = device_create_file(&port->dev, &dev_attr_event_char); |
| 1129 | if ((!retval) && | 1139 | if ((!retval) && |
| 1130 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { | 1140 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { |
| 1131 | retval = device_create_file(&udev->dev, | 1141 | retval = device_create_file(&port->dev, |
| 1132 | &dev_attr_latency_timer); | 1142 | &dev_attr_latency_timer); |
| 1133 | } | 1143 | } |
| 1134 | } | 1144 | } |
| 1135 | return retval; | 1145 | return retval; |
| 1136 | } | 1146 | } |
| 1137 | 1147 | ||
| 1138 | static void remove_sysfs_attrs(struct usb_serial *serial) | 1148 | static void remove_sysfs_attrs(struct usb_serial_port *port) |
| 1139 | { | 1149 | { |
| 1140 | struct ftdi_private *priv; | 1150 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1141 | struct usb_device *udev; | ||
| 1142 | 1151 | ||
| 1143 | dbg("%s",__FUNCTION__); | 1152 | dbg("%s",__FUNCTION__); |
| 1144 | 1153 | ||
| 1145 | priv = usb_get_serial_port_data(serial->port[0]); | ||
| 1146 | udev = serial->dev; | ||
| 1147 | |||
| 1148 | /* XXX see create_sysfs_attrs */ | 1154 | /* XXX see create_sysfs_attrs */ |
| 1149 | if (priv->chip_type != SIO) { | 1155 | if (priv->chip_type != SIO) { |
| 1150 | device_remove_file(&udev->dev, &dev_attr_event_char); | 1156 | device_remove_file(&port->dev, &dev_attr_event_char); |
| 1151 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | 1157 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { |
| 1152 | device_remove_file(&udev->dev, &dev_attr_latency_timer); | 1158 | device_remove_file(&port->dev, &dev_attr_latency_timer); |
| 1153 | } | 1159 | } |
| 1154 | } | 1160 | } |
| 1155 | 1161 | ||
| @@ -1169,13 +1175,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id | |||
| 1169 | return (0); | 1175 | return (0); |
| 1170 | } | 1176 | } |
| 1171 | 1177 | ||
| 1172 | /* attach subroutine */ | 1178 | static int ftdi_sio_port_probe(struct usb_serial_port *port) |
| 1173 | static int ftdi_sio_attach (struct usb_serial *serial) | ||
| 1174 | { | 1179 | { |
| 1175 | struct usb_serial_port *port = serial->port[0]; | ||
| 1176 | struct ftdi_private *priv; | 1180 | struct ftdi_private *priv; |
| 1177 | struct ftdi_sio_quirk *quirk; | ||
| 1178 | int retval; | ||
| 1179 | 1181 | ||
| 1180 | dbg("%s",__FUNCTION__); | 1182 | dbg("%s",__FUNCTION__); |
| 1181 | 1183 | ||
| @@ -1215,19 +1217,21 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
| 1215 | kfree(port->bulk_out_buffer); | 1217 | kfree(port->bulk_out_buffer); |
| 1216 | port->bulk_out_buffer = NULL; | 1218 | port->bulk_out_buffer = NULL; |
| 1217 | 1219 | ||
| 1218 | usb_set_serial_port_data(serial->port[0], priv); | 1220 | usb_set_serial_port_data(port, priv); |
| 1219 | 1221 | ||
| 1220 | ftdi_determine_type (serial->port[0]); | 1222 | ftdi_determine_type (port); |
| 1221 | retval = create_sysfs_attrs(serial); | 1223 | create_sysfs_attrs(port); |
| 1222 | if (retval) | 1224 | return 0; |
| 1223 | dev_err(&serial->dev->dev, "Error creating sysfs files, " | 1225 | } |
| 1224 | "continuing\n"); | ||
| 1225 | 1226 | ||
| 1227 | /* attach subroutine */ | ||
| 1228 | static int ftdi_sio_attach (struct usb_serial *serial) | ||
| 1229 | { | ||
| 1226 | /* Check for device requiring special set up. */ | 1230 | /* Check for device requiring special set up. */ |
| 1227 | quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); | 1231 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial); |
| 1228 | if (quirk && quirk->setup) { | 1232 | |
| 1233 | if (quirk && quirk->setup) | ||
| 1229 | quirk->setup(serial); | 1234 | quirk->setup(serial); |
| 1230 | } | ||
| 1231 | 1235 | ||
| 1232 | return 0; | 1236 | return 0; |
| 1233 | } /* ftdi_sio_attach */ | 1237 | } /* ftdi_sio_attach */ |
| @@ -1271,17 +1275,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) | |||
| 1271 | * calls __serial_close for each open of the port | 1275 | * calls __serial_close for each open of the port |
| 1272 | * shutdown is called then (ie ftdi_shutdown) | 1276 | * shutdown is called then (ie ftdi_shutdown) |
| 1273 | */ | 1277 | */ |
| 1274 | |||
| 1275 | |||
| 1276 | static void ftdi_shutdown (struct usb_serial *serial) | 1278 | static void ftdi_shutdown (struct usb_serial *serial) |
| 1277 | { /* ftdi_shutdown */ | 1279 | { |
| 1280 | dbg("%s", __FUNCTION__); | ||
| 1281 | } | ||
| 1278 | 1282 | ||
| 1279 | struct usb_serial_port *port = serial->port[0]; | 1283 | static int ftdi_sio_port_remove(struct usb_serial_port *port) |
| 1284 | { | ||
| 1280 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1285 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1281 | 1286 | ||
| 1282 | dbg("%s", __FUNCTION__); | 1287 | dbg("%s", __FUNCTION__); |
| 1283 | 1288 | ||
| 1284 | remove_sysfs_attrs(serial); | 1289 | remove_sysfs_attrs(port); |
| 1285 | 1290 | ||
| 1286 | /* all open ports are closed at this point | 1291 | /* all open ports are closed at this point |
| 1287 | * (by usbserial.c:__serial_close, which calls ftdi_close) | 1292 | * (by usbserial.c:__serial_close, which calls ftdi_close) |
| @@ -1291,8 +1296,9 @@ static void ftdi_shutdown (struct usb_serial *serial) | |||
| 1291 | usb_set_serial_port_data(port, NULL); | 1296 | usb_set_serial_port_data(port, NULL); |
| 1292 | kfree(priv); | 1297 | kfree(priv); |
| 1293 | } | 1298 | } |
| 1294 | } /* ftdi_shutdown */ | ||
| 1295 | 1299 | ||
| 1300 | return 0; | ||
| 1301 | } | ||
| 1296 | 1302 | ||
| 1297 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) | 1303 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) |
| 1298 | { /* ftdi_open */ | 1304 | { /* ftdi_open */ |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 1bdda935f7d9..513cfe1b768b 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ | 27 | #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ |
| 28 | #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ | 28 | #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ |
| 29 | #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ | 29 | #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ |
| 30 | #define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ | ||
| 30 | #define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ | 31 | #define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ |
| 31 | #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ | 32 | #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ |
| 32 | #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ | 33 | #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ |
| @@ -339,6 +340,12 @@ | |||
| 339 | #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ | 340 | #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ |
| 340 | 341 | ||
| 341 | /* | 342 | /* |
| 343 | * TTi (Thurlby Thandar Instruments) | ||
| 344 | */ | ||
| 345 | #define TTI_VID 0x103E /* Vendor Id */ | ||
| 346 | #define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ | ||
| 347 | |||
| 348 | /* | ||
| 342 | * Definitions for B&B Electronics products. | 349 | * Definitions for B&B Electronics products. |
| 343 | */ | 350 | */ |
| 344 | #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ | 351 | #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ |
| @@ -497,6 +504,19 @@ | |||
| 497 | #define TELLDUS_VID 0x1781 /* Vendor ID */ | 504 | #define TELLDUS_VID 0x1781 /* Vendor ID */ |
| 498 | #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ | 505 | #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ |
| 499 | 506 | ||
| 507 | /* | ||
| 508 | * IBS elektronik product ids | ||
| 509 | * Submitted by Thomas Schleusener | ||
| 510 | */ | ||
| 511 | #define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ | ||
| 512 | #define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ | ||
| 513 | #define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ | ||
| 514 | #define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ | ||
| 515 | #define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ | ||
| 516 | #define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ | ||
| 517 | #define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ | ||
| 518 | #define FTDI_IBS_PROD_PID 0xff3f /* future device */ | ||
| 519 | |||
| 500 | /* Commands */ | 520 | /* Commands */ |
| 501 | #define FTDI_SIO_RESET 0 /* Reset the port */ | 521 | #define FTDI_SIO_RESET 0 /* Reset the port */ |
| 502 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ | 522 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ |
| @@ -620,6 +640,7 @@ typedef enum { | |||
| 620 | FT8U232AM = 2, | 640 | FT8U232AM = 2, |
| 621 | FT232BM = 3, | 641 | FT232BM = 3, |
| 622 | FT2232C = 4, | 642 | FT2232C = 4, |
| 643 | FT232RL = 5, | ||
| 623 | } ftdi_chip_type_t; | 644 | } ftdi_chip_type_t; |
| 624 | 645 | ||
| 625 | typedef enum { | 646 | typedef enum { |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 53baeec8f265..4f8282ad7720 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
| @@ -20,13 +20,14 @@ | |||
| 20 | #include <linux/usb/serial.h> | 20 | #include <linux/usb/serial.h> |
| 21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
| 22 | 22 | ||
| 23 | static int generic_probe(struct usb_interface *interface, | ||
| 24 | const struct usb_device_id *id); | ||
| 25 | |||
| 26 | 23 | ||
| 27 | static int debug; | 24 | static int debug; |
| 28 | 25 | ||
| 29 | #ifdef CONFIG_USB_SERIAL_GENERIC | 26 | #ifdef CONFIG_USB_SERIAL_GENERIC |
| 27 | |||
| 28 | static int generic_probe(struct usb_interface *interface, | ||
| 29 | const struct usb_device_id *id); | ||
| 30 | |||
| 30 | static __u16 vendor = 0x05f9; | 31 | static __u16 vendor = 0x05f9; |
| 31 | static __u16 product = 0xffff; | 32 | static __u16 product = 0xffff; |
| 32 | 33 | ||
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index a408184334ea..d16e2e1764ad 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
| @@ -247,6 +247,8 @@ static struct usb_device_id ipaq_id_table [] = { | |||
| 247 | { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ | 247 | { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ |
| 248 | { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ | 248 | { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ |
| 249 | { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ | 249 | { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ |
| 250 | { USB_DEVICE(0x04AD, 0x0306) }, /* GPS Pocket PC USB Sync */ | ||
| 251 | { USB_DEVICE(0x04B7, 0x0531) }, /* MyGuide 7000 XL USB Sync */ | ||
| 250 | { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ | 252 | { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ |
| 251 | { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ | 253 | { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ |
| 252 | { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ | 254 | { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 2d588fb82573..19bf403f9db2 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
| @@ -1628,6 +1628,7 @@ static struct usb_serial_driver moschip7720_2port_driver = { | |||
| 1628 | .chars_in_buffer = mos7720_chars_in_buffer, | 1628 | .chars_in_buffer = mos7720_chars_in_buffer, |
| 1629 | .break_ctl = mos7720_break, | 1629 | .break_ctl = mos7720_break, |
| 1630 | .read_bulk_callback = mos7720_bulk_in_callback, | 1630 | .read_bulk_callback = mos7720_bulk_in_callback, |
| 1631 | .read_int_callback = mos7720_interrupt_callback, | ||
| 1631 | }; | 1632 | }; |
| 1632 | 1633 | ||
| 1633 | static int __init moschip7720_init(void) | 1634 | static int __init moschip7720_init(void) |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index db92a7fb1f7c..e178e6f40319 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -109,7 +109,6 @@ static int option_send_setup(struct usb_serial_port *port); | |||
| 109 | #define HUAWEI_PRODUCT_E220 0x1003 | 109 | #define HUAWEI_PRODUCT_E220 0x1003 |
| 110 | 110 | ||
| 111 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 | 111 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 |
| 112 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 | ||
| 113 | 112 | ||
| 114 | #define ANYDATA_VENDOR_ID 0x16d5 | 113 | #define ANYDATA_VENDOR_ID 0x16d5 |
| 115 | #define ANYDATA_PRODUCT_ID 0x6501 | 114 | #define ANYDATA_PRODUCT_ID 0x6501 |
| @@ -152,7 +151,19 @@ static struct usb_device_id option_ids[] = { | |||
| 152 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, | 151 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, |
| 153 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | 152 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, |
| 154 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, | 153 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, |
| 155 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | 154 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */ |
| 155 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */ | ||
| 156 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */ | ||
| 157 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */ | ||
| 158 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */ | ||
| 159 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */ | ||
| 160 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */ | ||
| 161 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ | ||
| 162 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel XU870 */ | ||
| 163 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */ | ||
| 164 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */ | ||
| 165 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */ | ||
| 166 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */ | ||
| 156 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, | 167 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, |
| 157 | { } /* Terminating entry */ | 168 | { } /* Terminating entry */ |
| 158 | }; | 169 | }; |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6bf22a28adb8..7639022cdf84 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -99,9 +99,12 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po | |||
| 99 | continue; | 99 | continue; |
| 100 | 100 | ||
| 101 | *minor = i; | 101 | *minor = i; |
| 102 | j = 0; | ||
| 102 | dbg("%s - minor base = %d", __FUNCTION__, *minor); | 103 | dbg("%s - minor base = %d", __FUNCTION__, *minor); |
| 103 | for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) | 104 | for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) { |
| 104 | serial_table[i] = serial; | 105 | serial_table[i] = serial; |
| 106 | serial->port[j++]->number = i; | ||
| 107 | } | ||
| 105 | spin_unlock(&table_lock); | 108 | spin_unlock(&table_lock); |
| 106 | return serial; | 109 | return serial; |
| 107 | } | 110 | } |
| @@ -826,7 +829,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 826 | num_ports = type->num_ports; | 829 | num_ports = type->num_ports; |
| 827 | } | 830 | } |
| 828 | 831 | ||
| 829 | serial->minor = minor; | ||
| 830 | serial->num_ports = num_ports; | 832 | serial->num_ports = num_ports; |
| 831 | serial->num_bulk_in = num_bulk_in; | 833 | serial->num_bulk_in = num_bulk_in; |
| 832 | serial->num_bulk_out = num_bulk_out; | 834 | serial->num_bulk_out = num_bulk_out; |
| @@ -847,7 +849,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 847 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); | 849 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); |
| 848 | if (!port) | 850 | if (!port) |
| 849 | goto probe_error; | 851 | goto probe_error; |
| 850 | port->number = i + serial->minor; | ||
| 851 | port->serial = serial; | 852 | port->serial = serial; |
| 852 | spin_lock_init(&port->lock); | 853 | spin_lock_init(&port->lock); |
| 853 | mutex_init(&port->mutex); | 854 | mutex_init(&port->mutex); |
| @@ -980,6 +981,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 980 | dev_err(&interface->dev, "No more free serial devices\n"); | 981 | dev_err(&interface->dev, "No more free serial devices\n"); |
| 981 | goto probe_error; | 982 | goto probe_error; |
| 982 | } | 983 | } |
| 984 | serial->minor = minor; | ||
| 983 | 985 | ||
| 984 | /* register all of the individual ports with the driver core */ | 986 | /* register all of the individual ports with the driver core */ |
| 985 | for (i = 0; i < num_ports; ++i) { | 987 | for (i = 0; i < num_ports; ++i) { |
| @@ -1034,9 +1036,6 @@ probe_error: | |||
| 1034 | kfree(port->interrupt_out_buffer); | 1036 | kfree(port->interrupt_out_buffer); |
| 1035 | } | 1037 | } |
| 1036 | 1038 | ||
| 1037 | /* return the minor range that this device had */ | ||
| 1038 | return_serial (serial); | ||
| 1039 | |||
| 1040 | /* free up any memory that we allocated */ | 1039 | /* free up any memory that we allocated */ |
| 1041 | for (i = 0; i < serial->num_port_pointers; ++i) | 1040 | for (i = 0; i < serial->num_port_pointers; ++i) |
| 1042 | kfree(serial->port[i]); | 1041 | kfree(serial->port[i]); |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 9644a8ea4aa7..4a9d0d5c7282 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
| @@ -146,6 +146,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, | |||
| 146 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 146 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 147 | US_FL_IGNORE_RESIDUE ), | 147 | US_FL_IGNORE_RESIDUE ), |
| 148 | 148 | ||
| 149 | /* Reported by Andrew Nayenko <relan@bk.ru> */ | ||
| 150 | UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592, | ||
| 151 | "Nokia", | ||
| 152 | "Nokia 6288", | ||
| 153 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 154 | US_FL_MAX_SECTORS_64 ), | ||
| 155 | |||
| 149 | /* Reported by Mario Rettig <mariorettig@web.de> */ | 156 | /* Reported by Mario Rettig <mariorettig@web.de> */ |
| 150 | UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, | 157 | UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, |
| 151 | "Nokia", | 158 | "Nokia", |
| @@ -320,6 +327,13 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, | |||
| 320 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 327 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 321 | US_FL_FIX_CAPACITY), | 328 | US_FL_FIX_CAPACITY), |
| 322 | 329 | ||
| 330 | /* Reported by Emil Larsson <emil@swip.net> */ | ||
| 331 | UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100, | ||
| 332 | "NIKON", | ||
| 333 | "NIKON DSC D80", | ||
| 334 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 335 | US_FL_FIX_CAPACITY), | ||
| 336 | |||
| 323 | /* BENQ DC5330 | 337 | /* BENQ DC5330 |
| 324 | * Reported by Manuel Fombuena <mfombuena@ya.com> and | 338 | * Reported by Manuel Fombuena <mfombuena@ya.com> and |
| 325 | * Frank Copeland <fjc@thingy.apana.org.au> */ | 339 | * Frank Copeland <fjc@thingy.apana.org.au> */ |
| @@ -1395,16 +1409,6 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, | |||
| 1395 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1409 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 1396 | US_FL_IGNORE_RESIDUE ), | 1410 | US_FL_IGNORE_RESIDUE ), |
| 1397 | 1411 | ||
| 1398 | /* Reported by Thomas Baechler <thomas@archlinux.org> | ||
| 1399 | * Fixes I/O errors with Teac HD-35PU devices | ||
| 1400 | */ | ||
| 1401 | |||
| 1402 | UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, | ||
| 1403 | "Super Top", | ||
| 1404 | "USB 2.0 IDE DEVICE", | ||
| 1405 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 1406 | US_FL_IGNORE_RESIDUE), | ||
| 1407 | |||
| 1408 | /* patch submitted by Davide Perini <perini.davide@dpsoftware.org> | 1412 | /* patch submitted by Davide Perini <perini.davide@dpsoftware.org> |
| 1409 | * and Renato Perini <rperini@email.it> | 1413 | * and Renato Perini <rperini@email.it> |
| 1410 | */ | 1414 | */ |
| @@ -1414,6 +1418,16 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, | |||
| 1414 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1418 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 1415 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), | 1419 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), |
| 1416 | 1420 | ||
| 1421 | /* | ||
| 1422 | * Patch by Pete Zaitcev <zaitcev@redhat.com> | ||
| 1423 | * Report by Mark Patton. Red Hat bz#208928. | ||
| 1424 | */ | ||
| 1425 | UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001, | ||
| 1426 | "Motorola", | ||
| 1427 | "RAZR V3i", | ||
| 1428 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 1429 | US_FL_FIX_CAPACITY), | ||
| 1430 | |||
| 1417 | /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */ | 1431 | /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */ |
| 1418 | UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, | 1432 | UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, |
| 1419 | "MPIO", | 1433 | "MPIO", |
