1
0
Fork 0

[PATCH] Option Card driver update, Maintainer entry

This patch updates the Option Card driver:
- remove a deadlock
- add sponsor notice
- add new card
- renamed the device to what's usually printed on it
- removed some dead code
- clean up a bunch of irregular whitespace (end-of-line, tabs)

Also add a MAINTAINERS entry for the Option Card driver.

Signed-Off-By: Matthias Urlichs <smurf@smurf.noris.de>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
hifive-unleashed-5.1
Matthias Urlichs 2005-07-14 00:33:47 -07:00 committed by Linus Torvalds
parent 98848fa83b
commit ba460e4806
2 changed files with 117 additions and 115 deletions

View File

@ -2420,6 +2420,12 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net
S: Maintained S: Maintained
USB OPTION-CARD DRIVER
P: Matthias Urlichs
M: smurf@smurf.noris.de
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
USB OV511 DRIVER USB OV511 DRIVER
P: Mark McClelland P: Mark McClelland
M: mmcclell@bigfoot.com M: mmcclell@bigfoot.com

View File

@ -12,14 +12,25 @@
History: History:
2005-05-19 v0.1 Initial version, based on incomplete docs 2005-05-19 v0.1 Initial version, based on incomplete docs
and analysis of misbehavior of the standard driver and analysis of misbehavior with the standard driver
2005-05-20 v0.2 Extended the input buffer to avoid losing 2005-05-20 v0.2 Extended the input buffer to avoid losing
random 64-byte chunks of data random 64-byte chunks of data
2005-05-21 v0.3 implemented chars_in_buffer() 2005-05-21 v0.3 implemented chars_in_buffer()
turned on low_latency turned on low_latency
simplified the code somewhat simplified the code somewhat
2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load
removed some dead code
added sponsor notice
coding style clean-up
2005-06-20 v0.4.1 add missing braces :-/
killed end-of-line whitespace
2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2
Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
*/ */
#define DRIVER_VERSION "v0.3"
#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
@ -44,7 +55,6 @@ static int option_write_room (struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb, struct pt_regs *regs); static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
static int option_write (struct usb_serial_port *port, static int option_write (struct usb_serial_port *port,
const unsigned char *buf, int count); const unsigned char *buf, int count);
@ -60,14 +70,17 @@ static int option_tiocmset (struct usb_serial_port *port, struct file *file,
static int option_send_setup (struct usb_serial_port *port); static int option_send_setup (struct usb_serial_port *port);
/* Vendor and product IDs */ /* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0 #define OPTION_VENDOR_ID 0x0AF0
#define OPTION_PRODUCT_OLD 0x5000
#define OPTION_PRODUCT_FUSION 0x6000
#define OPTION_PRODUCT_FUSION2 0x6300
#define OPTION_PRODUCT_OLD 0x5000
#define OPTION_PRODUCT_WLAN 0x6000
static struct usb_device_id option_ids[] = { static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
@ -85,58 +98,62 @@ static struct usb_driver option_driver = {
* recognizes separately, thus num_port=1. * recognizes separately, thus num_port=1.
*/ */
static struct usb_serial_device_type option_3port_device = { static struct usb_serial_device_type option_3port_device = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "Option 3-port card", .name = "Option 3G data card",
.short_name = "option", .short_name = "option",
.id_table = option_ids, .id_table = option_ids,
.num_interrupt_in = NUM_DONT_CARE, .num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE,
.num_ports = 1, /* 3 */ .num_ports = 1, /* 3, but the card reports its ports separately */
.open = option_open, .open = option_open,
.close = option_close, .close = option_close,
.write = option_write, .write = option_write,
.write_room = option_write_room, .write_room = option_write_room,
.chars_in_buffer = option_chars_in_buffer, .chars_in_buffer = option_chars_in_buffer,
.throttle = option_rx_throttle, .throttle = option_rx_throttle,
.unthrottle = option_rx_unthrottle, .unthrottle = option_rx_unthrottle,
.ioctl = option_ioctl, .ioctl = option_ioctl,
.set_termios = option_set_termios, .set_termios = option_set_termios,
.break_ctl = option_break_ctl, .break_ctl = option_break_ctl,
.tiocmget = option_tiocmget, .tiocmget = option_tiocmget,
.tiocmset = option_tiocmset, .tiocmset = option_tiocmset,
.attach = option_startup, .attach = option_startup,
.shutdown = option_shutdown, .shutdown = option_shutdown,
.read_int_callback = option_instat_callback, .read_int_callback = option_instat_callback,
}; };
#ifdef CONFIG_USB_DEBUG
static int debug; static int debug;
#else
#define debug 0
#endif
/* per port private data */ /* per port private data */
#define N_IN_URB 4 #define N_IN_URB 4
#define N_OUT_URB 1 #define N_OUT_URB 1
#define IN_BUFLEN 1024 #define IN_BUFLEN 1024
#define OUT_BUFLEN 1024 #define OUT_BUFLEN 128
struct option_port_private { struct option_port_private {
/* Input endpoints and buffer for this port */ /* Input endpoints and buffer for this port */
struct urb *in_urbs[N_IN_URB]; struct urb *in_urbs[N_IN_URB];
char in_buffer[N_IN_URB][IN_BUFLEN]; char in_buffer[N_IN_URB][IN_BUFLEN];
/* Output endpoints and buffer for this port */ /* Output endpoints and buffer for this port */
struct urb *out_urbs[N_OUT_URB]; struct urb *out_urbs[N_OUT_URB];
char out_buffer[N_OUT_URB][OUT_BUFLEN]; char out_buffer[N_OUT_URB][OUT_BUFLEN];
/* Settings for the port */ /* Settings for the port */
int rts_state; /* Handshaking pins (outputs) */ int rts_state; /* Handshaking pins (outputs) */
int dtr_state; int dtr_state;
int cts_state; /* Handshaking pins (inputs) */ int cts_state; /* Handshaking pins (inputs) */
int dsr_state; int dsr_state;
int dcd_state; int dcd_state;
int ri_state; int ri_state;
// int break_on;
unsigned long tx_start_time[N_OUT_URB]; unsigned long tx_start_time[N_OUT_URB];
}; };
@ -190,13 +207,13 @@ static void
option_break_ctl (struct usb_serial_port *port, int break_state) option_break_ctl (struct usb_serial_port *port, int break_state)
{ {
/* Unfortunately, I don't know how to send a break */ /* Unfortunately, I don't know how to send a break */
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
} }
static void static void
option_set_termios (struct usb_serial_port *port, option_set_termios (struct usb_serial_port *port,
struct termios *old_termios) struct termios *old_termios)
{ {
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
@ -204,10 +221,10 @@ option_set_termios (struct usb_serial_port *port,
} }
static int static int
option_tiocmget(struct usb_serial_port *port, struct file *file) option_tiocmget (struct usb_serial_port *port, struct file *file)
{ {
unsigned int value; unsigned int value;
struct option_port_private *portdata; struct option_port_private *portdata;
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
@ -225,7 +242,7 @@ static int
option_tiocmset (struct usb_serial_port *port, struct file *file, option_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear) unsigned int set, unsigned int clear)
{ {
struct option_port_private *portdata; struct option_port_private *portdata;
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
@ -250,71 +267,50 @@ option_ioctl (struct usb_serial_port *port, struct file *file,
/* Write */ /* Write */
static int static int
option_write(struct usb_serial_port *port, option_write (struct usb_serial_port *port,
const unsigned char *buf, int count) const unsigned char *buf, int count)
{ {
struct option_port_private *portdata; struct option_port_private *portdata;
int i; int i;
int left, todo; int left, todo;
struct urb *this_urb = NULL; /* spurious */ struct urb *this_urb = NULL; /* spurious */
int err; int err;
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
dbg("%s: write (%d chars)", __FUNCTION__, count); dbg("%s: write (%d chars)", __FUNCTION__, count);
#if 0
spin_lock(&port->lock);
if (port->write_urb_busy) {
spin_unlock(&port->lock);
dbg("%s: already writing", __FUNCTION__);
return 0;
}
port->write_urb_busy = 1;
spin_unlock(&port->lock);
#endif
i = 0; i = 0;
left = count; left = count;
while (left>0) { for (i=0; left > 0 && i < N_OUT_URB; i++) {
todo = left; todo = left;
if (todo > OUT_BUFLEN) if (todo > OUT_BUFLEN)
todo = OUT_BUFLEN; todo = OUT_BUFLEN;
for (;i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i];
/* Check we have a valid urb/endpoint before we use it... */ if (this_urb->status == -EINPROGRESS) {
this_urb = portdata->out_urbs[i];
if (this_urb->status != -EINPROGRESS)
break;
if (this_urb->transfer_flags & URB_ASYNC_UNLINK) if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
continue; continue;
if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ)) if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
continue; continue;
this_urb->transfer_flags |= URB_ASYNC_UNLINK; this_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(this_urb); usb_unlink_urb(this_urb);
continue;
} }
if (this_urb->status != 0)
if (i == N_OUT_URB) { dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status);
/* no bulk out free! */
dbg("%s: no output urb -- left %d", __FUNCTION__,count-left);
#if 0
port->write_urb_busy = 0;
#endif
return count-left;
}
dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i); dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
/* send the data */
memcpy (this_urb->transfer_buffer, buf, todo); memcpy (this_urb->transfer_buffer, buf, todo);
/* send the data out the bulk port */
this_urb->transfer_buffer_length = todo; this_urb->transfer_buffer_length = todo;
this_urb->transfer_flags &= ~URB_ASYNC_UNLINK; this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev; this_urb->dev = port->serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC); err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err) { if (err) {
dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status); dbg("usb_submit_urb %p (write bulk) failed (%d, has %d)", this_urb, err, this_urb->status);
continue; continue;
} }
portdata->tx_start_time[i] = jiffies; portdata->tx_start_time[i] = jiffies;
@ -323,9 +319,6 @@ option_write(struct usb_serial_port *port,
} }
count -= left; count -= left;
#if 0
port->write_urb_busy = 0;
#endif
dbg("%s: wrote (did %d)", __FUNCTION__, count); dbg("%s: wrote (did %d)", __FUNCTION__, count);
return count; return count;
} }
@ -333,7 +326,7 @@ option_write(struct usb_serial_port *port,
static void static void
option_indat_callback (struct urb *urb, struct pt_regs *regs) option_indat_callback (struct urb *urb, struct pt_regs *regs)
{ {
int i, err; int i, err;
int endpoint; int endpoint;
struct usb_serial_port *port; struct usb_serial_port *port;
struct tty_struct *tty; struct tty_struct *tty;
@ -444,10 +437,11 @@ option_write_room (struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
for (i=0; i < N_OUT_URB; i++) for (i=0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i]; this_urb = portdata->out_urbs[i];
if (this_urb && this_urb->status != -EINPROGRESS) if (this_urb && this_urb->status != -EINPROGRESS)
data_len += OUT_BUFLEN; data_len += OUT_BUFLEN;
}
dbg("%s: %d", __FUNCTION__, data_len); dbg("%s: %d", __FUNCTION__, data_len);
return data_len; return data_len;
@ -464,11 +458,11 @@ option_chars_in_buffer (struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
for (i=0; i < N_OUT_URB; i++) for (i=0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i]; this_urb = portdata->out_urbs[i];
if (this_urb && this_urb->status == -EINPROGRESS) if (this_urb && this_urb->status == -EINPROGRESS)
data_len += this_urb->transfer_buffer_length; data_len += this_urb->transfer_buffer_length;
}
dbg("%s: %d", __FUNCTION__, data_len); dbg("%s: %d", __FUNCTION__, data_len);
return data_len; return data_len;
} }
@ -477,10 +471,10 @@ option_chars_in_buffer (struct usb_serial_port *port)
static int static int
option_open (struct usb_serial_port *port, struct file *filp) option_open (struct usb_serial_port *port, struct file *filp)
{ {
struct option_port_private *portdata; struct option_port_private *portdata;
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
int i, err; int i, err;
struct urb *urb; struct urb *urb;
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
@ -528,7 +522,7 @@ option_open (struct usb_serial_port *port, struct file *filp)
} }
static inline void static inline void
stop_urb(struct urb *urb) stop_urb (struct urb *urb)
{ {
if (urb && urb->status == -EINPROGRESS) { if (urb && urb->status == -EINPROGRESS) {
urb->transfer_flags &= ~URB_ASYNC_UNLINK; urb->transfer_flags &= ~URB_ASYNC_UNLINK;
@ -537,11 +531,11 @@ stop_urb(struct urb *urb)
} }
static void static void
option_close(struct usb_serial_port *port, struct file *filp) option_close (struct usb_serial_port *port, struct file *filp)
{ {
int i; int i;
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct option_port_private *portdata; struct option_port_private *portdata;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
@ -589,11 +583,11 @@ option_setup_urb (struct usb_serial *serial, int endpoint,
/* Setup urbs */ /* Setup urbs */
static void static void
option_setup_urbs(struct usb_serial *serial) option_setup_urbs (struct usb_serial *serial)
{ {
int j; int j;
struct usb_serial_port *port; struct usb_serial_port *port;
struct option_port_private *portdata; struct option_port_private *portdata;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
@ -617,7 +611,7 @@ option_setup_urbs(struct usb_serial *serial)
static int static int
option_send_setup(struct usb_serial_port *port) option_send_setup (struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct option_port_private *portdata; struct option_port_private *portdata;
@ -644,9 +638,9 @@ option_send_setup(struct usb_serial_port *port)
static int static int
option_startup (struct usb_serial *serial) option_startup (struct usb_serial *serial)
{ {
int i, err; int i, err;
struct usb_serial_port *port; struct usb_serial_port *port;
struct option_port_private *portdata; struct option_port_private *portdata;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
@ -677,9 +671,9 @@ option_startup (struct usb_serial *serial)
static void static void
option_shutdown (struct usb_serial *serial) option_shutdown (struct usb_serial *serial)
{ {
int i, j; int i, j;
struct usb_serial_port *port; struct usb_serial_port *port;
struct option_port_private *portdata; struct option_port_private *portdata;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
@ -724,6 +718,8 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION); MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef CONFIG_USB_DEBUG
module_param(debug, bool, S_IRUGO | S_IWUSR); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug messages"); MODULE_PARM_DESC(debug, "Debug messages");
#endif