Commit 40d2ff32 authored by Elina Pasheva's avatar Elina Pasheva Committed by Greg Kroah-Hartman

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: default avatarElina Pasheva <epasheva@sierrawireless.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e05b8e6e
/* /*
USB Driver for Sierra Wireless USB Driver for Sierra Wireless
Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com> Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com>,
Copyright (C) 2008, 2009 Elina Pasheva, Matthew Safar, Rory Filer
<linux@sierrawireless.com>
IMPORTANT DISCLAIMER: This driver is not commercially supported by IMPORTANT DISCLAIMER: This driver is not commercially supported by
Sierra Wireless. Use at your own risk. Sierra Wireless. Use at your own risk.
...@@ -14,8 +17,8 @@ ...@@ -14,8 +17,8 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/ */
#define DRIVER_VERSION "v.1.3.5" #define DRIVER_VERSION "v.1.3.6"
#define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>" #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -34,6 +37,11 @@ ...@@ -34,6 +37,11 @@
#define N_OUT_URB 64 #define N_OUT_URB 64
#define IN_BUFLEN 4096 #define IN_BUFLEN 4096
#define MAX_TRANSFER (PAGE_SIZE - 512)
/* MAX_TRANSFER is chosen so that the VM is not stressed by
allocations > PAGE_SIZE and the number of packets in a page
is an integer 512 is the largest possible packet on EHCI */
static int debug; static int debug;
static int nmea; static int nmea;
...@@ -419,50 +427,58 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -419,50 +427,58 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
unsigned long flags; unsigned long flags;
unsigned char *buffer; unsigned char *buffer;
struct urb *urb; struct urb *urb;
int status; size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER);
int retval = 0;
/* verify that we actually have some data to write */
if (count == 0)
return 0;
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); dev_dbg(&port->dev, "%s: write (%d bytes)\n", __func__, writesize);
spin_lock_irqsave(&portdata->lock, flags); spin_lock_irqsave(&portdata->lock, flags);
dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__,
portdata->outstanding_urbs);
if (portdata->outstanding_urbs > N_OUT_URB) { if (portdata->outstanding_urbs > N_OUT_URB) {
spin_unlock_irqrestore(&portdata->lock, flags); spin_unlock_irqrestore(&portdata->lock, flags);
dev_dbg(&port->dev, "%s - write limit hit\n", __func__); dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
return 0; return 0;
} }
portdata->outstanding_urbs++; portdata->outstanding_urbs++;
dev_dbg(&port->dev, "%s - 1, outstanding_urbs: %d\n", __func__,
portdata->outstanding_urbs);
spin_unlock_irqrestore(&portdata->lock, flags); spin_unlock_irqrestore(&portdata->lock, flags);
buffer = kmalloc(count, GFP_ATOMIC); buffer = kmalloc(writesize, GFP_ATOMIC);
if (!buffer) { if (!buffer) {
dev_err(&port->dev, "out of memory\n"); dev_err(&port->dev, "out of memory\n");
count = -ENOMEM; retval = -ENOMEM;
goto error_no_buffer; goto error_no_buffer;
} }
urb = usb_alloc_urb(0, GFP_ATOMIC); urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) { if (!urb) {
dev_err(&port->dev, "no more free urbs\n"); dev_err(&port->dev, "no more free urbs\n");
count = -ENOMEM; retval = -ENOMEM;
goto error_no_urb; goto error_no_urb;
} }
memcpy(buffer, buf, count); memcpy(buffer, buf, writesize);
usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer);
usb_fill_bulk_urb(urb, serial->dev, usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, usb_sndbulkpipe(serial->dev,
port->bulk_out_endpointAddress), port->bulk_out_endpointAddress),
buffer, count, sierra_outdat_callback, port); buffer, writesize, sierra_outdat_callback, port);
/* send it down the pipe */ /* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC); retval = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (retval) {
dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
"with status = %d\n", __func__, status); "with status = %d\n", __func__, retval);
count = status;
goto error; goto error;
} }
...@@ -470,7 +486,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -470,7 +486,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
* really free it when it is finished with it */ * really free it when it is finished with it */
usb_free_urb(urb); usb_free_urb(urb);
return count; return writesize;
error: error:
usb_free_urb(urb); usb_free_urb(urb);
error_no_urb: error_no_urb:
...@@ -478,8 +494,10 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -478,8 +494,10 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
error_no_buffer: error_no_buffer:
spin_lock_irqsave(&portdata->lock, flags); spin_lock_irqsave(&portdata->lock, flags);
--portdata->outstanding_urbs; --portdata->outstanding_urbs;
dev_dbg(&port->dev, "%s - 2. outstanding_urbs: %d\n", __func__,
portdata->outstanding_urbs);
spin_unlock_irqrestore(&portdata->lock, flags); spin_unlock_irqrestore(&portdata->lock, flags);
return count; return retval;
} }
static void sierra_indat_callback(struct urb *urb) static void sierra_indat_callback(struct urb *urb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment