Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+35 −17
Original line number Diff line number Diff line
/*
  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
  Sierra Wireless. Use at your own risk.
@@ -14,8 +17,8 @@
  Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/

#define DRIVER_VERSION "v.1.3.5"
#define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>"
#define DRIVER_VERSION "v.1.3.6"
#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"

#include <linux/kernel.h>
@@ -34,6 +37,11 @@
#define N_OUT_URB	64
#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 nmea;

@@ -419,50 +427,58 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
	unsigned long flags;
	unsigned char *buffer;
	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);

	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);
	dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__,
		portdata->outstanding_urbs);
	if (portdata->outstanding_urbs > N_OUT_URB) {
		spin_unlock_irqrestore(&portdata->lock, flags);
		dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
		return 0;
	}
	portdata->outstanding_urbs++;
	dev_dbg(&port->dev, "%s - 1, outstanding_urbs: %d\n", __func__,
		portdata->outstanding_urbs);
	spin_unlock_irqrestore(&portdata->lock, flags);

	buffer = kmalloc(count, GFP_ATOMIC);
	buffer = kmalloc(writesize, GFP_ATOMIC);
	if (!buffer) {
		dev_err(&port->dev, "out of memory\n");
		count = -ENOMEM;
		retval = -ENOMEM;
		goto error_no_buffer;
	}

	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb) {
		dev_err(&port->dev, "no more free urbs\n");
		count = -ENOMEM;
		retval = -ENOMEM;
		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_sndbulkpipe(serial->dev,
					  port->bulk_out_endpointAddress),
			  buffer, count, sierra_outdat_callback, port);
			  buffer, writesize, sierra_outdat_callback, port);

	/* send it down the pipe */
	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status) {
	retval = usb_submit_urb(urb, GFP_ATOMIC);
	if (retval) {
		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
			"with status = %d\n", __func__, status);
		count = status;
			"with status = %d\n", __func__, retval);
		goto error;
	}

@@ -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 */
	usb_free_urb(urb);

	return count;
	return writesize;
error:
	usb_free_urb(urb);
error_no_urb:
@@ -478,8 +494,10 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
error_no_buffer:
	spin_lock_irqsave(&portdata->lock, flags);
	--portdata->outstanding_urbs;
	dev_dbg(&port->dev, "%s - 2. outstanding_urbs: %d\n", __func__,
		portdata->outstanding_urbs);
	spin_unlock_irqrestore(&portdata->lock, flags);
	return count;
	return retval;
}

static void sierra_indat_callback(struct urb *urb)