summaryrefslogtreecommitdiff
path: root/drivers/usb/serial/pl2303.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-22 11:09:07 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 13:03:22 -0700
commit95da310e66ee8090119596c70ca8432e57f9a97f (patch)
tree7f18c30e9c9ad4d7d53df6453fa338be06f09a85 /drivers/usb/serial/pl2303.c
parent1aa3692da57c773e5c76de55c5c4a953962d360e (diff)
usb_serial: API all change
USB serial likes to use port->tty back pointers for the real work it does and to do so without any actual locking. Unfortunately when you consider hangup events, hangup/parallel reopen or even worse hangup followed by parallel close events the tty->port and port->tty pointers are not guaranteed to be the same as port->tty is the active tty while tty->port is the port the tty may or may not still be attached to. So rework the entire API to pass the tty struct. For console cases we need to pass both for now. This shows up multiple drivers that immediately crash with USB console some of which have been fixed in the process. Longer term we need a proper tty as console abstraction Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r--drivers/usb/serial/pl2303.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2a0dd1b50dc4..a0016725d314 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -458,8 +458,8 @@ static void pl2303_send(struct usb_serial_port *port)
usb_serial_port_softint(port);
}
-static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int pl2303_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -478,8 +478,9 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
return count;
}
-static int pl2303_write_room(struct usb_serial_port *port)
+static int pl2303_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -494,8 +495,9 @@ static int pl2303_write_room(struct usb_serial_port *port)
return room;
}
-static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+static int pl2303_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -510,8 +512,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
return chars;
}
-static void pl2303_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void pl2303_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -526,11 +528,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
- HUPCL | CLOCAL;
- port->tty->termios->c_ispeed = 9600;
- port->tty->termios->c_ospeed = 9600;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -539,16 +540,16 @@ static void pl2303_set_termios(struct usb_serial_port *port,
serial settings even to the same values as before. Thus
we actually need to filter in this specific case */
- if (!tty_termios_hw_change(port->tty->termios, old_termios))
+ if (!tty_termios_hw_change(tty->termios, old_termios))
return;
- cflag = port->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
buf = kzalloc(7, GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n", __func__);
/* Report back no change occurred */
- *port->tty->termios = *old_termios;
+ *tty->termios = *old_termios;
return;
}
@@ -569,7 +570,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
dbg("%s - data bits = %d", __func__, buf[6]);
}
- baud = tty_get_baud_rate(port->tty);;
+ baud = tty_get_baud_rate(tty);
dbg("%s - baud = %d", __func__, baud);
if (baud) {
buf[0] = baud & 0xff;
@@ -646,12 +647,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
/* FIXME: Need to read back resulting baud rate */
if (baud)
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
kfree(buf);
}
-static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -666,7 +668,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = PL2303_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (pl2303_buf_data_avail(priv->buf) == 0 ||
@@ -678,7 +680,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
pl2303_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -690,7 +692,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
/* for lower rates we should really know how much */
/* data is in the buffer to compute a delay */
/* that is not unnecessarily long) */
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
timeout = max((HZ*2560)/bps,HZ/10);
else
@@ -703,8 +705,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
@@ -715,7 +717,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
}
}
-static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+static int pl2303_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -734,9 +737,8 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
}
/* Setup termios */
- if (port->tty) {
- pl2303_set_termios(port, &tmp_termios);
- }
+ if (tty)
+ pl2303_set_termios(tty, port, &tmp_termios);
//FIXME: need to assert RTS and DTR if CRTSCTS off
@@ -746,7 +748,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- pl2303_close(port, NULL);
+ pl2303_close(tty, port, NULL);
return -EPROTO;
}
@@ -756,15 +758,16 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, result);
- pl2303_close(port, NULL);
+ pl2303_close(tty, port, NULL);
return -EPROTO;
}
return 0;
}
-static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -787,8 +790,9 @@ static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
return set_control_lines(port->serial->dev, control);
}
-static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
@@ -853,9 +857,10 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
@@ -871,8 +876,9 @@ static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
-static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
u16 state;
int result;
@@ -1001,7 +1007,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
if (status) {
dbg("%s - urb status = %d", __func__, status);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port is closed, exiting.", __func__);
return;
}
@@ -1044,7 +1050,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dbg("%s - tty_flag = %d", __func__, tty_flag);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -1056,7 +1062,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)