diff options
author | Elina Pasheva <epasheva@sierrawireless.com> | 2009-04-29 13:26:46 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:45 -0400 |
commit | 40d2ff32f102e69d482480265ec60ffb86b028de (patch) | |
tree | e296e28a1139c3f785328e043c112332764ca584 /drivers | |
parent | e05b8e6e1066e7583dbb6b00407508797b737995 (diff) |
USB: serial: sierra driver write path improvements
- Updated Copyright notice with new authors names
- Version number set to 1.3.6
- Added a MAX_TRANSFER constant following Greg Kroah-Hartman's
recommended setting of PAGE_SIZE-512 for USB transfer buffers and
modified accordingly sierra_write() function.
Signed-off-by: Elina Pasheva <epasheva@sierrawireless.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/serial/sierra.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index f75688416b65..27f41f95aefb 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -1,7 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | USB Driver for Sierra Wireless | 2 | USB Driver for Sierra Wireless |
3 | 3 | ||
4 | Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com> | 4 | Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com>, |
5 | |||
6 | Copyright (C) 2008, 2009 Elina Pasheva, Matthew Safar, Rory Filer | ||
7 | <linux@sierrawireless.com> | ||
5 | 8 | ||
6 | IMPORTANT DISCLAIMER: This driver is not commercially supported by | 9 | IMPORTANT DISCLAIMER: This driver is not commercially supported by |
7 | Sierra Wireless. Use at your own risk. | 10 | Sierra Wireless. Use at your own risk. |
@@ -14,8 +17,8 @@ | |||
14 | Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> | 17 | Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> |
15 | */ | 18 | */ |
16 | 19 | ||
17 | #define DRIVER_VERSION "v.1.3.5" | 20 | #define DRIVER_VERSION "v.1.3.6" |
18 | #define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>" | 21 | #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" |
19 | #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" | 22 | #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" |
20 | 23 | ||
21 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
@@ -34,6 +37,11 @@ | |||
34 | #define N_OUT_URB 64 | 37 | #define N_OUT_URB 64 |
35 | #define IN_BUFLEN 4096 | 38 | #define IN_BUFLEN 4096 |
36 | 39 | ||
40 | #define MAX_TRANSFER (PAGE_SIZE - 512) | ||
41 | /* MAX_TRANSFER is chosen so that the VM is not stressed by | ||
42 | allocations > PAGE_SIZE and the number of packets in a page | ||
43 | is an integer 512 is the largest possible packet on EHCI */ | ||
44 | |||
37 | static int debug; | 45 | static int debug; |
38 | static int nmea; | 46 | static int nmea; |
39 | 47 | ||
@@ -419,50 +427,58 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
419 | unsigned long flags; | 427 | unsigned long flags; |
420 | unsigned char *buffer; | 428 | unsigned char *buffer; |
421 | struct urb *urb; | 429 | struct urb *urb; |
422 | int status; | 430 | size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER); |
431 | int retval = 0; | ||
432 | |||
433 | /* verify that we actually have some data to write */ | ||
434 | if (count == 0) | ||
435 | return 0; | ||
423 | 436 | ||
424 | portdata = usb_get_serial_port_data(port); | 437 | portdata = usb_get_serial_port_data(port); |
425 | 438 | ||
426 | dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); | 439 | dev_dbg(&port->dev, "%s: write (%d bytes)\n", __func__, writesize); |
427 | 440 | ||
428 | spin_lock_irqsave(&portdata->lock, flags); | 441 | spin_lock_irqsave(&portdata->lock, flags); |
442 | dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__, | ||
443 | portdata->outstanding_urbs); | ||
429 | if (portdata->outstanding_urbs > N_OUT_URB) { | 444 | if (portdata->outstanding_urbs > N_OUT_URB) { |
430 | spin_unlock_irqrestore(&portdata->lock, flags); | 445 | spin_unlock_irqrestore(&portdata->lock, flags); |
431 | dev_dbg(&port->dev, "%s - write limit hit\n", __func__); | 446 | dev_dbg(&port->dev, "%s - write limit hit\n", __func__); |
432 | return 0; | 447 | return 0; |
433 | } | 448 | } |
434 | portdata->outstanding_urbs++; | 449 | portdata->outstanding_urbs++; |
450 | dev_dbg(&port->dev, "%s - 1, outstanding_urbs: %d\n", __func__, | ||
451 | portdata->outstanding_urbs); | ||
435 | spin_unlock_irqrestore(&portdata->lock, flags); | 452 | spin_unlock_irqrestore(&portdata->lock, flags); |
436 | 453 | ||
437 | buffer = kmalloc(count, GFP_ATOMIC); | 454 | buffer = kmalloc(writesize, GFP_ATOMIC); |
438 | if (!buffer) { | 455 | if (!buffer) { |
439 | dev_err(&port->dev, "out of memory\n"); | 456 | dev_err(&port->dev, "out of memory\n"); |
440 | count = -ENOMEM; | 457 | retval = -ENOMEM; |
441 | goto error_no_buffer; | 458 | goto error_no_buffer; |
442 | } | 459 | } |
443 | 460 | ||
444 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 461 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
445 | if (!urb) { | 462 | if (!urb) { |
446 | dev_err(&port->dev, "no more free urbs\n"); | 463 | dev_err(&port->dev, "no more free urbs\n"); |
447 | count = -ENOMEM; | 464 | retval = -ENOMEM; |
448 | goto error_no_urb; | 465 | goto error_no_urb; |
449 | } | 466 | } |
450 | 467 | ||
451 | memcpy(buffer, buf, count); | 468 | memcpy(buffer, buf, writesize); |
452 | 469 | ||
453 | usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); | 470 | usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer); |
454 | 471 | ||
455 | usb_fill_bulk_urb(urb, serial->dev, | 472 | usb_fill_bulk_urb(urb, serial->dev, |
456 | usb_sndbulkpipe(serial->dev, | 473 | usb_sndbulkpipe(serial->dev, |
457 | port->bulk_out_endpointAddress), | 474 | port->bulk_out_endpointAddress), |
458 | buffer, count, sierra_outdat_callback, port); | 475 | buffer, writesize, sierra_outdat_callback, port); |
459 | 476 | ||
460 | /* send it down the pipe */ | 477 | /* send it down the pipe */ |
461 | status = usb_submit_urb(urb, GFP_ATOMIC); | 478 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
462 | if (status) { | 479 | if (retval) { |
463 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " | 480 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " |
464 | "with status = %d\n", __func__, status); | 481 | "with status = %d\n", __func__, retval); |
465 | count = status; | ||
466 | goto error; | 482 | goto error; |
467 | } | 483 | } |
468 | 484 | ||
@@ -470,7 +486,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
470 | * really free it when it is finished with it */ | 486 | * really free it when it is finished with it */ |
471 | usb_free_urb(urb); | 487 | usb_free_urb(urb); |
472 | 488 | ||
473 | return count; | 489 | return writesize; |
474 | error: | 490 | error: |
475 | usb_free_urb(urb); | 491 | usb_free_urb(urb); |
476 | error_no_urb: | 492 | error_no_urb: |
@@ -478,8 +494,10 @@ error_no_urb: | |||
478 | error_no_buffer: | 494 | error_no_buffer: |
479 | spin_lock_irqsave(&portdata->lock, flags); | 495 | spin_lock_irqsave(&portdata->lock, flags); |
480 | --portdata->outstanding_urbs; | 496 | --portdata->outstanding_urbs; |
497 | dev_dbg(&port->dev, "%s - 2. outstanding_urbs: %d\n", __func__, | ||
498 | portdata->outstanding_urbs); | ||
481 | spin_unlock_irqrestore(&portdata->lock, flags); | 499 | spin_unlock_irqrestore(&portdata->lock, flags); |
482 | return count; | 500 | return retval; |
483 | } | 501 | } |
484 | 502 | ||
485 | static void sierra_indat_callback(struct urb *urb) | 503 | static void sierra_indat_callback(struct urb *urb) |