Hi,
Here's a patch against the usb-serial drivers that fixes a number of SMP
locking issues (like holding a spinlock while calling copy_from_user)
and other not so nice things.
The patch is against 2.4.6-pre1.
thanks,
greg k-h
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/belkin_sa.c Tue Jun 5 14:02:34 2001
@@ -24,6 +24,9 @@
* -- Add support for flush commands
* -- Add everything that is missing :)
*
+ * (30-May-2001 gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* 08-Apr-2001 gb
* - Identify version on module load.
*
@@ -85,7 +88,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "William Greathouse <[EMAIL PROTECTED]>"
#define DRIVER_DESC "USB Belkin Serial converter driver"
@@ -282,11 +285,11 @@
static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
{
- unsigned long flags;
+ int retval = 0;
dbg(__FUNCTION__" port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
++port->open_count;
MOD_INC_USE_COUNT;
@@ -299,30 +302,32 @@
* enhance buffering. Win trace shows 16 initial read URBs.
*/
port->read_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->read_urb))
+ retval = usb_submit_urb(port->read_urb);
+ if (retval) {
err("usb_submit_urb(read bulk) failed");
+ goto exit;
+ }
port->interrupt_in_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->interrupt_in_urb))
+ retval = usb_submit_urb(port->interrupt_in_urb);
+ if (retval)
err(" usb_submit_urb(read int) failed");
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+exit:
+ up (&port->sem);
- return 0;
+ return retval;
} /* belkin_sa_open */
static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
{
- unsigned long flags;
-
dbg(__FUNCTION__" port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
- MOD_DEC_USE_COUNT;
if (port->open_count <= 0) {
/* shutdown our bulk reads and writes */
@@ -332,7 +337,8 @@
port->active = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
+ MOD_DEC_USE_COUNT;
} /* belkin_sa_close */
diff -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/empeg.c Tue Jun 5 14:02:34 2001
@@ -1,10 +1,10 @@
/*
* USB Empeg empeg-car player driver
*
- * Copyright (C) 2000
+ * Copyright (C) 2000, 2001
* Gary Brubaker ([EMAIL PROTECTED])
*
- * Copyright (C) 1999, 2000
+ * Copyright (C) 1999 - 2001
* Greg Kroah-Hartman ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
@@ -13,6 +13,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (05/30/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (04/08/2001) gb
* Identify version on module load.
*
@@ -71,7 +74,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]>, Gary Brubaker
<[EMAIL PROTECTED]>"
#define DRIVER_DESC "USB Empeg Mark I/II Driver"
@@ -147,15 +150,14 @@
static int empeg_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
- int result;
+ int result = 0;;
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
++port->open_count;
MOD_INC_USE_COUNT;
@@ -236,9 +238,9 @@
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
- return 0;
+ return result;
}
@@ -246,7 +248,6 @@
{
struct usb_serial *serial;
unsigned char *transfer_buffer;
- unsigned long flags;
if (port_paranoia_check (port, __FUNCTION__))
return;
@@ -257,7 +258,7 @@
if (!serial)
return;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
@@ -276,13 +277,12 @@
port->open_count = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
/* Uncomment the following line if you want to see some statistics in your
syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
MOD_DEC_USE_COUNT;
-
}
@@ -377,7 +377,7 @@
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
/* tally up the number of bytes available */
for (i = 0; i < NUM_URBS; ++i) {
@@ -386,7 +386,7 @@
}
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
dbg(__FUNCTION__ " - returns %d", room);
@@ -403,7 +403,7 @@
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
/* tally up the number of bytes waiting */
for (i = 0; i < NUM_URBS; ++i) {
@@ -412,7 +412,7 @@
}
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
dbg (__FUNCTION__ " - returns %d", chars);
@@ -514,15 +514,13 @@
static void empeg_throttle (struct usb_serial_port *port)
{
- unsigned long flags;
-
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
usb_unlink_urb (port->read_urb);
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
return;
@@ -531,12 +529,11 @@
static void empeg_unthrottle (struct usb_serial_port *port)
{
- unsigned long flags;
int result;
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
port->read_urb->dev = port->serial->dev;
@@ -545,7 +542,7 @@
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
return;
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c Tue Jun 5 14:02:33 2001
+++ b/drivers/usb/serial/ftdi_sio.c Tue Jun 5 14:02:33 2001
@@ -1,7 +1,7 @@
/*
* USB FTDI SIO driver
*
- * Copyright (C) 1999, 2000
+ * Copyright (C) 1999 - 2001
* Greg Kroah-Hartman ([EMAIL PROTECTED])
* Bill Ryder ([EMAIL PROTECTED])
*
@@ -15,6 +15,9 @@
* See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
* and extra documentation
*
+ * (31/May/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (23/May/2001) Bill Ryder
* Added runtime debug patch (thanx Tyson D Sawyer).
* Cleaned up comments for 8U232
@@ -301,13 +304,12 @@
{ /* ftdi_sio_open */
struct termios tmp_termios;
struct usb_serial *serial = port->serial;
- unsigned long flags; /* Used for spinlock */
- int result;
+ int result = 0;
char buf[1]; /* Needed for the usb_control_msg I think */
dbg(__FUNCTION__);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
MOD_INC_USE_COUNT;
++port->open_count;
@@ -315,8 +317,6 @@
if (!port->active){
port->active = 1;
- spin_unlock_irqrestore (&port->port_lock, flags);
-
/* This will push the characters through immediately rather
than queue a task to deliver them */
port->tty->low_latency = 1;
@@ -352,11 +352,10 @@
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
- } else { /* the port was already active - so no initialisation is done */
- spin_unlock_irqrestore (&port->port_lock, flags);
}
- return (0);
+ up (&port->sem);
+ return result;
} /* ftdi_sio_open */
@@ -365,15 +364,13 @@
struct usb_serial *serial = port->serial;
unsigned int c_cflag = port->tty->termios->c_cflag;
char buf[1];
- unsigned long flags;
dbg( __FUNCTION__);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
- spin_unlock_irqrestore (&port->port_lock, flags);
if (c_cflag & HUPCL){
/* Disable flow control */
if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,
0),
@@ -400,8 +397,6 @@
port->active = 0;
port->open_count = 0;
} else {
- spin_unlock_irqrestore (&port->port_lock, flags);
-
/* Send a HUP if necessary */
if (!(port->tty->termios->c_cflag & CLOCAL)){
tty_hangup(port->tty);
@@ -409,6 +404,7 @@
}
+ up (&port->sem);
MOD_DEC_USE_COUNT;
} /* ftdi_sio_close */
diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/keyspan.c Tue Jun 5 14:02:34 2001
@@ -28,6 +28,9 @@
open source projects.
Change History
+ Thu May 31 11:56:42 PDT 2001 gkh
+ switched from using spinlock to a semaphore
+
(04/08/2001) gb
Identify version on module load.
@@ -833,7 +836,6 @@
struct usb_serial *serial = port->serial;
const keyspan_device_details *d_details;
int i, already_active, err;
- unsigned long flags;
urb_t *urb;
s_priv = (struct keyspan_serial_private *)(serial->private);
@@ -843,11 +845,11 @@
/* dbg("keyspan_open called."); */
MOD_INC_USE_COUNT;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
++port->open_count;
already_active = port->active;
port->active = 1;
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
if (already_active)
return 0;
@@ -887,13 +889,12 @@
struct usb_serial *serial = port->serial; /* FIXME should so sanity
check */
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
- unsigned long flags;
/* dbg("keyspan_close called"); */
s_priv = (struct keyspan_serial_private *)(serial->private);
p_priv = (struct keyspan_port_private *)(port->private);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
if (--port->open_count <= 0) {
if (port->active) {
@@ -914,7 +915,7 @@
port->open_count = 0;
port->tty = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
MOD_DEC_USE_COUNT;
}
diff -Nru a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c Tue Jun 5 14:02:33 2001
+++ b/drivers/usb/serial/keyspan_pda.c Tue Jun 5 14:02:33 2001
@@ -1,7 +1,7 @@
/*
* USB Keyspan PDA Converter driver
*
- * Copyright (c) 1999, 2000 Greg Kroah-Hartman <[EMAIL PROTECTED]>
+ * Copyright (c) 1999 - 2001 Greg Kroah-Hartman <[EMAIL PROTECTED]>
* Copyright (c) 1999, 2000 Brian Warner <[EMAIL PROTECTED]>
* Copyright (c) 2000 Al Borchers <[EMAIL PROTECTED]>
*
@@ -12,6 +12,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (05/31/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (04/08/2001) gb
* Identify version on module load.
*
@@ -452,7 +455,6 @@
int request_unthrottle = 0;
int rc = 0;
struct keyspan_pda_private *priv;
- unsigned long flags;
priv = (struct keyspan_pda_private *)(port->private);
/* guess how much room is left in the device's ring buffer, and if we
@@ -482,7 +484,6 @@
finished). Also, the tx process is not throttled. So we are
ready to write. */
- spin_lock_irqsave (&port->port_lock, flags);
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
/* Check if we might overrun the Tx buffer. If so, ask the
@@ -502,13 +503,12 @@
2*HZ);
if (rc < 0) {
dbg(" roomquery failed");
- spin_unlock_irqrestore (&port->port_lock, flags);
- return rc; /* failed */
+ goto exit;
}
if (rc == 0) {
dbg(" roomquery returned 0 bytes");
- spin_unlock_irqrestore (&port->port_lock, flags);
- return -EIO; /* device didn't return any data */
+ rc = -EIO; /* device didn't return any data */
+ goto exit;
}
dbg(" roomquery says %d", room);
priv->tx_room = room;
@@ -525,8 +525,8 @@
if (from_user) {
if( copy_from_user(port->write_urb->transfer_buffer,
buf, count) ) {
- spin_unlock_irqrestore (&port->port_lock, flags);
- return( -EFAULT );
+ rc = -EFAULT;
+ goto exit;
}
}
else {
@@ -538,10 +538,10 @@
priv->tx_room -= count;
port->write_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->write_urb)) {
+ rc = usb_submit_urb(port->write_urb);
+ if (rc) {
dbg(" usb_submit_urb(write bulk) failed");
- spin_unlock_irqrestore (&port->port_lock, flags);
- return (0);
+ goto exit;
}
}
else {
@@ -557,8 +557,9 @@
MOD_DEC_USE_COUNT;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
- return (count);
+ rc = count;
+exit:
+ return rc;
}
@@ -616,11 +617,10 @@
{
struct usb_serial *serial = port->serial;
unsigned char room;
- int rc;
+ int rc = 0;
struct keyspan_pda_private *priv;
- unsigned long flags;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
MOD_INC_USE_COUNT;
++port->open_count;
@@ -629,7 +629,6 @@
port->active = 1;
/* find out how much room is in the Tx ring */
- spin_unlock_irqrestore (&port->port_lock, flags);
rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
6, /* write_room */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -639,7 +638,6 @@
&room,
1,
2*HZ);
- spin_lock_irqsave (&port->port_lock, flags);
if (rc < 0) {
dbg(__FUNCTION__" - roomquery failed");
goto error;
@@ -655,7 +653,6 @@
/* the normal serial device seems to always turn on DTR and RTS here,
so do the same */
- spin_unlock_irqrestore (&port->port_lock, flags);
if (port->tty->termios->c_cflag & CBAUD)
keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
else
@@ -663,19 +660,22 @@
/*Start reading from the device*/
port->interrupt_in_urb->dev = serial->dev;
- if (usb_submit_urb(port->interrupt_in_urb))
+ rc = usb_submit_urb(port->interrupt_in_urb);
+ if (rc) {
dbg(__FUNCTION__" - usb_submit_urb(read int) failed");
- } else {
- spin_unlock_irqrestore (&port->port_lock, flags);
+ goto error;
+ }
+
}
- return (0);
+ up (&port->sem);
+ return rc;
error:
--port->open_count;
port->active = 0;
MOD_DEC_USE_COUNT;
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
return rc;
}
@@ -683,19 +683,15 @@
static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
- MOD_DEC_USE_COUNT;
if (port->open_count <= 0) {
/* the normal serial device seems to always shut off DTR and RTS now */
- spin_unlock_irqrestore (&port->port_lock, flags);
if (port->tty->termios->c_cflag & HUPCL)
keyspan_pda_set_modem_info(serial, 0);
- spin_lock_irqsave (&port->port_lock, flags);
/* shutdown our bulk reads and writes */
usb_unlink_urb (port->write_urb);
@@ -704,7 +700,8 @@
port->open_count = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
+ MOD_DEC_USE_COUNT;
}
diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/mct_u232.c Tue Jun 5 14:02:34 2001
@@ -24,6 +24,9 @@
* Basic tests have been performed with minicom/zmodem transfers and
* modem dialing under Linux 2.4.0-test10 (for me it works fine).
*
+ * 30-May-2001 Greg Kroah-Hartman
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* 04-May-2001 Stelian Pop
* - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
* instead of the device reported 32 (using 32 bytes causes many data
@@ -79,7 +82,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Wolfgang Grandegger <[EMAIL PROTECTED]>"
#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
@@ -391,13 +394,13 @@
static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
{
- unsigned long flags;
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ int retval = 0;
dbg(__FUNCTION__" port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
++port->open_count;
MOD_INC_USE_COUNT;
@@ -443,16 +446,21 @@
}
port->read_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->read_urb))
+ retval = usb_submit_urb(port->read_urb);
+ if (retval) {
err("usb_submit_urb(read bulk) failed");
+ goto exit;
+ }
port->interrupt_in_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->interrupt_in_urb))
+ retval = usb_submit_urb(port->interrupt_in_urb);
+ if (retval)
err(" usb_submit_urb(read int) failed");
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+exit:
+ up (&port->sem);
return 0;
} /* mct_u232_open */
@@ -460,14 +468,11 @@
static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
{
- unsigned long flags;
-
dbg(__FUNCTION__" port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
- MOD_DEC_USE_COUNT;
if (port->open_count <= 0) {
/* shutdown our bulk reads and writes */
@@ -478,8 +483,8 @@
port->active = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
-
+ up (&port->sem);
+ MOD_DEC_USE_COUNT;
} /* mct_u232_close */
@@ -490,7 +495,6 @@
const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
int result, bytes_sent, size;
dbg(__FUNCTION__ " - port %d", port->number);
@@ -513,7 +517,7 @@
bytes_sent = 0;
while (count > 0) {
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
@@ -541,11 +545,11 @@
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
- spin_unlock_irqrestore (&port->port_lock, flags);
- return bytes_sent;
+ up (&port->sem);
+ return result;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
bytes_sent += size;
if (write_blocking)
diff -Nru a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
--- a/drivers/usb/serial/omninet.c Tue Jun 5 14:02:33 2001
+++ b/drivers/usb/serial/omninet.c Tue Jun 5 14:02:33 2001
@@ -10,6 +10,9 @@
*
* Please report both successes and troubles to the author at [EMAIL PROTECTED]
*
+ * (05/30/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (04/08/2001) gb
* Identify version on module load.
*
@@ -60,7 +63,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Anonymous"
#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
@@ -145,8 +148,7 @@
struct usb_serial *serial;
struct usb_serial_port *wport;
struct omninet_data *od;
- unsigned long flags;
- int result;
+ int result = 0;
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
@@ -157,7 +159,7 @@
if (!serial)
return -ENODEV;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
MOD_INC_USE_COUNT;
++port->open_count;
@@ -170,7 +172,7 @@
err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct
omninet_data));
--port->open_count;
port->active = 0;
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
@@ -189,9 +191,9 @@
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
- return (0);
+ return result;
}
static void omninet_close (struct usb_serial_port *port, struct file * filp)
@@ -199,7 +201,6 @@
struct usb_serial *serial;
struct usb_serial_port *wport;
struct omninet_data *od;
- unsigned long flags;
if (port_paranoia_check (port, __FUNCTION__))
return;
@@ -210,10 +211,9 @@
if (!serial)
return;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
- MOD_DEC_USE_COUNT;
if (port->open_count <= 0) {
od = (struct omninet_data *)port->private;
@@ -228,7 +228,8 @@
kfree(od);
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
+ MOD_DEC_USE_COUNT;
}
@@ -296,7 +297,6 @@
struct omninet_data *od = (struct omninet_data *) port->private;
struct omninet_header *header = (struct omninet_header *)
wport->write_urb->transfer_buffer;
- unsigned long flags;
int result;
// dbg("omninet_write port %d", port->number);
@@ -310,12 +310,13 @@
return (0);
}
- spin_lock_irqsave (&port->port_lock, flags);
-
count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
if (from_user) {
- copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
buf, count);
+ if (copy_from_user(wport->write_urb->transfer_buffer +
+OMNINET_DATAOFFSET, buf, count) != 0) {
+ result = -EFAULT;
+ goto exit;
+ }
}
else {
memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf,
count);
@@ -333,16 +334,13 @@
wport->write_urb->dev = serial->dev;
result = usb_submit_urb(wport->write_urb);
- if (result) {
+ if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
- spin_unlock_irqrestore (&port->port_lock, flags);
- return 0;
- }
-
-// dbg("omninet_write returns %d", count);
+ else
+ result = count;
- spin_unlock_irqrestore (&port->port_lock, flags);
- return (count);
+exit:
+ return result;
}
diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h Tue Jun 5 14:02:33 2001
+++ b/drivers/usb/serial/usb-serial.h Tue Jun 5 14:02:33 2001
@@ -1,7 +1,7 @@
/*
* USB Serial Converter driver
*
- * Copyright (C) 1999, 2000
+ * Copyright (C) 1999 - 2001
* Greg Kroah-Hartman ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
@@ -11,6 +11,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (05/30/2001) gkh
+ * added sem to port structure and removed port_lock
+ *
* (10/05/2000) gkh
* Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
* fix bug with urb->dev not being set properly, now that the usb core
@@ -77,7 +80,7 @@
struct tq_struct tqueue; /* task queue for line discipline
waking up */
int open_count; /* number of times this port has been
opened */
- spinlock_t port_lock;
+ struct semaphore sem; /* locks this structure */
void * private; /* data private to the specific port */
};
diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/usbserial.c Tue Jun 5 14:02:34 2001
@@ -1,7 +1,7 @@
/*
* USB Serial Converter driver
*
- * Copyright (C) 1999, 2000 Greg Kroah-Hartman ([EMAIL PROTECTED])
+ * Copyright (C) 1999 - 2001 Greg Kroah-Hartman ([EMAIL PROTECTED])
* Copyright (c) 2000 Peter Berger ([EMAIL PROTECTED])
* Copyright (c) 2000 Al Borchers ([EMAIL PROTECTED])
*
@@ -15,6 +15,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (05/30/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (04/08/2001) gb
* Identify version on module load.
*
@@ -288,7 +291,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, [EMAIL PROTECTED],
http://www.kroah.com/linux-usb/"
#define DRIVER_DESC "USB Serial Driver"
@@ -735,8 +738,7 @@
static int generic_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
- int result;
+ int result = 0;
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
@@ -745,7 +747,7 @@
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
++port->open_count;
@@ -773,20 +775,19 @@
}
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
- return 0;
+ return result;
}
static void generic_close (struct usb_serial_port *port, struct file * filp)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
@@ -801,7 +802,7 @@
port->open_count = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
MOD_DEC_USE_COUNT;
}
@@ -809,7 +810,6 @@
static int generic_write (struct usb_serial_port *port, int from_user, const unsigned
char *buf, int count)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
int result;
dbg(__FUNCTION__ " - port %d", port->number);
@@ -826,7 +826,6 @@
return (0);
}
- spin_lock_irqsave (&port->port_lock, flags);
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
if (from_user) {
@@ -849,14 +848,12 @@
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb);
- if (result) {
+ if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d",
result);
- spin_unlock_irqrestore (&port->port_lock, flags);
- return 0;
- }
+ else
+ result = count;
- spin_unlock_irqrestore (&port->port_lock, flags);
- return (count);
+ return result;
}
/* no bulk out, so return 0 bytes written */
@@ -871,9 +868,10 @@
dbg(__FUNCTION__ " - port %d", port->number);
- if (serial->num_bulk_out)
+ if (serial->num_bulk_out) {
if (port->write_urb->status != -EINPROGRESS)
room = port->bulk_out_size;
+ }
dbg(__FUNCTION__ " - returns %d", room);
return (room);
@@ -887,9 +885,10 @@
dbg(__FUNCTION__ " - port %d", port->number);
- if (serial->num_bulk_out)
+ if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS)
chars = port->write_urb->transfer_buffer_length;
+ }
dbg (__FUNCTION__ " - returns %d", chars);
return (chars);
@@ -1222,7 +1221,7 @@
port->magic = USB_SERIAL_PORT_MAGIC;
port->tqueue.routine = port_softint;
port->tqueue.data = port;
- spin_lock_init (&port->port_lock);
+ init_MUTEX (&port->sem);
}
/* initialize the devfs nodes for this device and let the user know what ports
we are bound to */
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/visor.c Tue Jun 5 14:02:34 2001
@@ -11,6 +11,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (05/30/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (05/28/2000) gkh
* Added initial support for the Palm m500 and Palm m505 devices.
*
@@ -112,7 +115,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.1"
+#define DRIVER_VERSION "v1.2"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]>"
#define DRIVER_DESC "USB HandSpring Visor driver"
@@ -253,15 +256,14 @@
static int visor_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- unsigned long flags;
- int result;
+ int result = 0;
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
++port->open_count;
MOD_INC_USE_COUNT;
@@ -286,9 +288,9 @@
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
- return 0;
+ return result;
}
@@ -296,7 +298,6 @@
{
struct usb_serial *serial;
unsigned char *transfer_buffer;
- unsigned long flags;
if (port_paranoia_check (port, __FUNCTION__))
return;
@@ -307,7 +308,7 @@
if (!serial)
return;
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
--port->open_count;
@@ -328,7 +329,7 @@
port->open_count = 0;
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
/* Uncomment the following line if you want to see some statistics in your
syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
@@ -410,7 +411,7 @@
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status != -EINPROGRESS) {
@@ -418,7 +419,7 @@
}
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
dbg(__FUNCTION__ " - returns %d", room);
return (room);
@@ -433,7 +434,7 @@
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status == -EINPROGRESS) {
@@ -441,7 +442,7 @@
}
}
- spin_unlock_irqrestore (&port->port_lock, flags);
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
dbg (__FUNCTION__ " - returns %d", chars);
return (chars);
@@ -523,15 +524,14 @@
static void visor_throttle (struct usb_serial_port *port)
{
- unsigned long flags;
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
usb_unlink_urb (port->read_urb);
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
return;
}
@@ -539,19 +539,18 @@
static void visor_unthrottle (struct usb_serial_port *port)
{
- unsigned long flags;
int result;
dbg(__FUNCTION__ " - port %d", port->number);
- spin_lock_irqsave (&port->port_lock, flags);
+ down (&port->sem);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
- spin_unlock_irqrestore (&port->port_lock, flags);
+ up (&port->sem);
return;
}
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c Tue Jun 5 14:02:34 2001
+++ b/drivers/usb/serial/whiteheat.c Tue Jun 5 14:02:34 2001
@@ -11,6 +11,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (05/30/2001) gkh
+ * switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
* (04/08/2001) gb
* Identify version on module load.
*
@@ -85,7 +88,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]>"
#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
@@ -251,6 +254,7 @@
struct usb_serial_port *port;
int timeout;
__u8 *transfer_buffer;
+ int retval = 0;
dbg(__FUNCTION__" - command %d", command);
@@ -263,9 +267,10 @@
memcpy (&transfer_buffer[1], data, datasize);
port->write_urb->transfer_buffer_length = datasize + 1;
port->write_urb->dev = serial->dev;
- if (usb_submit_urb (port->write_urb)) {
+ retval = usb_submit_urb (port->write_urb);
+ if (retval) {
dbg (__FUNCTION__" - submit urb failed");
- return -1;
+ goto exit;
}
/* wait for the command to complete */
@@ -276,20 +281,21 @@
if (info->command_finished == FALSE) {
dbg (__FUNCTION__ " - command timed out.");
- return -1;
+ retval = -ETIMEDOUT;
+ goto exit;
}
if (info->command_finished == WHITEHEAT_CMD_FAILURE) {
dbg (__FUNCTION__ " - command failed.");
- return -1;
+ retval = -EIO;
+ goto exit;
}
- if (info->command_finished == WHITEHEAT_CMD_COMPLETE) {
+ if (info->command_finished == WHITEHEAT_CMD_COMPLETE)
dbg (__FUNCTION__ " - command completed.");
- return 0;
- }
- return 0;
+exit:
+ return retval;
}
@@ -298,10 +304,12 @@
struct whiteheat_min_set open_command;
struct usb_serial_port *command_port;
struct whiteheat_private *info;
- int result;
+ int retval = 0;
dbg(__FUNCTION__" - port %d", port->number);
+ down (&port->sem);
+
++port->open_count;
MOD_INC_USE_COUNT;
@@ -314,7 +322,8 @@
info = (struct whiteheat_private *)kmalloc (sizeof(struct
whiteheat_private), GFP_KERNEL);
if (info == NULL) {
err(__FUNCTION__ " - out of memory");
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto error_exit;
}
init_waitqueue_head(&info->wait_command);
@@ -323,27 +332,45 @@
command_port->read_urb->complete = command_port_read_callback;
command_port->read_urb->dev = port->serial->dev;
command_port->tty = port->tty; /* need this to "fake"
our our sanity check macros */
- usb_submit_urb (command_port->read_urb);
+ retval = usb_submit_urb (command_port->read_urb);
+ if (retval) {
+ err(__FUNCTION__ " - failed submitting read urb, error
+%d", retval);
+ goto error_exit;
+ }
}
/* Start reading from the device */
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb);
- if (result)
- err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
+ retval = usb_submit_urb(port->read_urb);
+ if (retval) {
+ err(__FUNCTION__ " - failed submitting read urb, error %d",
+retval);
+ goto error_exit;
+ }
/* send an open port command */
/* firmware uses 1 based port numbering */
open_command.port = port->number - port->serial->minor + 1;
- whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8
*)&open_command, sizeof(open_command));
+ retval = whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8
+*)&open_command, sizeof(open_command));
+ if (retval)
+ goto error_exit;
/* Need to do device specific setup here (control lines, baud rate,
etc.) */
/* FIXME!!! */
}
dbg(__FUNCTION__ " - exit");
+ up (&port->sem);
- return 0;
+ return retval;
+
+error_exit:
+ --port->open_count;
+ MOD_DEC_USE_COUNT;
+
+ dbg(__FUNCTION__ " - error_exit");
+ up (&port->sem);
+
+ return retval;
}
@@ -353,6 +380,7 @@
dbg(__FUNCTION__ " - port %d", port->number);
+ down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
@@ -370,6 +398,7 @@
port->active = 0;
}
MOD_DEC_USE_COUNT;
+ up (&port->sem);
}
@@ -388,18 +417,19 @@
dbg(__FUNCTION__ " -port %d", port->number);
+ down (&port->sem);
/* check that they really want us to change something */
if (old_termios) {
if ((cflag == old_termios->c_cflag) &&
(RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
RELEVANT_IFLAG(old_termios->c_iflag))) {
dbg(__FUNCTION__ " - nothing to change...");
- return;
+ goto exit;
}
}
if ((!port->tty) || (!port->tty->termios)) {
dbg(__FUNCTION__" - no tty structures");
- return;
+ goto exit;
}
/* set the port number */
@@ -466,6 +496,8 @@
/* now send the message to the device */
whiteheat_send_cmd (port->serial, WHITEHEAT_SETUP_PORT, (__u8
*)&port_settings, sizeof(port_settings));
+exit:
+ up (&port->sem);
return;
}