aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/io_ti.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-22 06:09:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:03:22 -0400
commit95da310e66ee8090119596c70ca8432e57f9a97f (patch)
tree7f18c30e9c9ad4d7d53df6453fa338be06f09a85 /drivers/usb/serial/io_ti.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/io_ti.c')
-rw-r--r--drivers/usb/serial/io_ti.c109
1 files changed, 58 insertions, 51 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a58822a14a87..7cf383a2a556 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -243,9 +243,9 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
243static void stop_read(struct edgeport_port *edge_port); 243static void stop_read(struct edgeport_port *edge_port);
244static int restart_read(struct edgeport_port *edge_port); 244static int restart_read(struct edgeport_port *edge_port);
245 245
246static void edge_set_termios(struct usb_serial_port *port, 246static void edge_set_termios(struct tty_struct *tty,
247 struct ktermios *old_termios); 247 struct usb_serial_port *port, struct ktermios *old_termios);
248static void edge_send(struct usb_serial_port *port); 248static void edge_send(struct tty_struct *tty);
249 249
250/* sysfs attributes */ 250/* sysfs attributes */
251static int edge_create_sysfs_attrs(struct usb_serial_port *port); 251static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
572 int flush) 572 int flush)
573{ 573{
574 int baud_rate; 574 int baud_rate;
575 struct tty_struct *tty = port->port->tty; 575 struct tty_struct *tty = port->port->port.tty;
576 wait_queue_t wait; 576 wait_queue_t wait;
577 unsigned long flags; 577 unsigned long flags;
578 578
@@ -1554,7 +1554,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
1554 /* Save the new modem status */ 1554 /* Save the new modem status */
1555 edge_port->shadow_msr = msr & 0xf0; 1555 edge_port->shadow_msr = msr & 0xf0;
1556 1556
1557 tty = edge_port->port->tty; 1557 tty = edge_port->port->port.tty;
1558 /* handle CTS flow control */ 1558 /* handle CTS flow control */
1559 if (tty && C_CRTSCTS(tty)) { 1559 if (tty && C_CRTSCTS(tty)) {
1560 if (msr & EDGEPORT_MSR_CTS) { 1560 if (msr & EDGEPORT_MSR_CTS) {
@@ -1587,9 +1587,8 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
1587 new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); 1587 new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
1588 1588
1589 /* Place LSR data byte into Rx buffer */ 1589 /* Place LSR data byte into Rx buffer */
1590 if (lsr_data && edge_port->port->tty) 1590 if (lsr_data && edge_port->port->port.tty)
1591 edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, 1591 edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1);
1592 &data, 1);
1593 1592
1594 /* update input line counters */ 1593 /* update input line counters */
1595 icount = &edge_port->icount; 1594 icount = &edge_port->icount;
@@ -1750,7 +1749,7 @@ static void edge_bulk_in_callback(struct urb *urb)
1750 ++data; 1749 ++data;
1751 } 1750 }
1752 1751
1753 tty = edge_port->port->tty; 1752 tty = edge_port->port->port.tty;
1754 if (tty && urb->actual_length) { 1753 if (tty && urb->actual_length) {
1755 usb_serial_debug_data(debug, &edge_port->port->dev, 1754 usb_serial_debug_data(debug, &edge_port->port->dev,
1756 __func__, urb->actual_length, data); 1755 __func__, urb->actual_length, data);
@@ -1819,10 +1818,11 @@ static void edge_bulk_out_callback(struct urb *urb)
1819 } 1818 }
1820 1819
1821 /* send any buffered data */ 1820 /* send any buffered data */
1822 edge_send(port); 1821 edge_send(port->port.tty);
1823} 1822}
1824 1823
1825static int edge_open(struct usb_serial_port *port, struct file *filp) 1824static int edge_open(struct tty_struct *tty,
1825 struct usb_serial_port *port, struct file *filp)
1826{ 1826{
1827 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 1827 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
1828 struct edgeport_serial *edge_serial; 1828 struct edgeport_serial *edge_serial;
@@ -1838,7 +1838,8 @@ static int edge_open(struct usb_serial_port *port, struct file *filp)
1838 if (edge_port == NULL) 1838 if (edge_port == NULL)
1839 return -ENODEV; 1839 return -ENODEV;
1840 1840
1841 port->tty->low_latency = low_latency; 1841 if (tty)
1842 tty->low_latency = low_latency;
1842 1843
1843 port_number = port->number - port->serial->minor; 1844 port_number = port->number - port->serial->minor;
1844 switch (port_number) { 1845 switch (port_number) {
@@ -1874,7 +1875,8 @@ static int edge_open(struct usb_serial_port *port, struct file *filp)
1874 } 1875 }
1875 1876
1876 /* set up the port settings */ 1877 /* set up the port settings */
1877 edge_set_termios(port, port->tty->termios); 1878 if (tty)
1879 edge_set_termios(tty, port, port->port.tty->termios);
1878 1880
1879 /* open up the port */ 1881 /* open up the port */
1880 1882
@@ -2000,7 +2002,8 @@ release_es_lock:
2000 return status; 2002 return status;
2001} 2003}
2002 2004
2003static void edge_close(struct usb_serial_port *port, struct file *filp) 2005static void edge_close(struct tty_struct *tty,
2006 struct usb_serial_port *port, struct file *filp)
2004{ 2007{
2005 struct edgeport_serial *edge_serial; 2008 struct edgeport_serial *edge_serial;
2006 struct edgeport_port *edge_port; 2009 struct edgeport_port *edge_port;
@@ -2048,8 +2051,8 @@ static void edge_close(struct usb_serial_port *port, struct file *filp)
2048 dbg("%s - exited", __func__); 2051 dbg("%s - exited", __func__);
2049} 2052}
2050 2053
2051static int edge_write(struct usb_serial_port *port, const unsigned char *data, 2054static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
2052 int count) 2055 const unsigned char *data, int count)
2053{ 2056{
2054 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2057 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2055 unsigned long flags; 2058 unsigned long flags;
@@ -2070,16 +2073,16 @@ static int edge_write(struct usb_serial_port *port, const unsigned char *data,
2070 count = edge_buf_put(edge_port->ep_out_buf, data, count); 2073 count = edge_buf_put(edge_port->ep_out_buf, data, count);
2071 spin_unlock_irqrestore(&edge_port->ep_lock, flags); 2074 spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2072 2075
2073 edge_send(port); 2076 edge_send(tty);
2074 2077
2075 return count; 2078 return count;
2076} 2079}
2077 2080
2078static void edge_send(struct usb_serial_port *port) 2081static void edge_send(struct tty_struct *tty)
2079{ 2082{
2083 struct usb_serial_port *port = tty->driver_data;
2080 int count, result; 2084 int count, result;
2081 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2085 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2082 struct tty_struct *tty = port->tty;
2083 unsigned long flags; 2086 unsigned long flags;
2084 2087
2085 2088
@@ -2133,8 +2136,9 @@ static void edge_send(struct usb_serial_port *port)
2133 tty_wakeup(tty); 2136 tty_wakeup(tty);
2134} 2137}
2135 2138
2136static int edge_write_room(struct usb_serial_port *port) 2139static int edge_write_room(struct tty_struct *tty)
2137{ 2140{
2141 struct usb_serial_port *port = tty->driver_data;
2138 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2142 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2139 int room = 0; 2143 int room = 0;
2140 unsigned long flags; 2144 unsigned long flags;
@@ -2154,8 +2158,9 @@ static int edge_write_room(struct usb_serial_port *port)
2154 return room; 2158 return room;
2155} 2159}
2156 2160
2157static int edge_chars_in_buffer(struct usb_serial_port *port) 2161static int edge_chars_in_buffer(struct tty_struct *tty)
2158{ 2162{
2163 struct usb_serial_port *port = tty->driver_data;
2159 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2164 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2160 int chars = 0; 2165 int chars = 0;
2161 unsigned long flags; 2166 unsigned long flags;
@@ -2175,10 +2180,10 @@ static int edge_chars_in_buffer(struct usb_serial_port *port)
2175 return chars; 2180 return chars;
2176} 2181}
2177 2182
2178static void edge_throttle(struct usb_serial_port *port) 2183static void edge_throttle(struct tty_struct *tty)
2179{ 2184{
2185 struct usb_serial_port *port = tty->driver_data;
2180 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2186 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2181 struct tty_struct *tty = port->tty;
2182 int status; 2187 int status;
2183 2188
2184 dbg("%s - port %d", __func__, port->number); 2189 dbg("%s - port %d", __func__, port->number);
@@ -2189,11 +2194,10 @@ static void edge_throttle(struct usb_serial_port *port)
2189 /* if we are implementing XON/XOFF, send the stop character */ 2194 /* if we are implementing XON/XOFF, send the stop character */
2190 if (I_IXOFF(tty)) { 2195 if (I_IXOFF(tty)) {
2191 unsigned char stop_char = STOP_CHAR(tty); 2196 unsigned char stop_char = STOP_CHAR(tty);
2192 status = edge_write(port, &stop_char, 1); 2197 status = edge_write(tty, port, &stop_char, 1);
2193 if (status <= 0) 2198 if (status <= 0) {
2194 dev_err(&port->dev, 2199 dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
2195 "%s - failed to write stop character, %d\n", 2200 }
2196 __func__, status);
2197 } 2201 }
2198 2202
2199 /* if we are implementing RTS/CTS, stop reads */ 2203 /* if we are implementing RTS/CTS, stop reads */
@@ -2203,10 +2207,10 @@ static void edge_throttle(struct usb_serial_port *port)
2203 2207
2204} 2208}
2205 2209
2206static void edge_unthrottle(struct usb_serial_port *port) 2210static void edge_unthrottle(struct tty_struct *tty)
2207{ 2211{
2212 struct usb_serial_port *port = tty->driver_data;
2208 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2213 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2209 struct tty_struct *tty = port->tty;
2210 int status; 2214 int status;
2211 2215
2212 dbg("%s - port %d", __func__, port->number); 2216 dbg("%s - port %d", __func__, port->number);
@@ -2217,11 +2221,10 @@ static void edge_unthrottle(struct usb_serial_port *port)
2217 /* if we are implementing XON/XOFF, send the start character */ 2221 /* if we are implementing XON/XOFF, send the start character */
2218 if (I_IXOFF(tty)) { 2222 if (I_IXOFF(tty)) {
2219 unsigned char start_char = START_CHAR(tty); 2223 unsigned char start_char = START_CHAR(tty);
2220 status = edge_write(port, &start_char, 1); 2224 status = edge_write(tty, port, &start_char, 1);
2221 if (status <= 0) 2225 if (status <= 0) {
2222 dev_err(&port->dev, 2226 dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
2223 "%s - failed to write start character, %d\n", 2227 }
2224 __func__, status);
2225 } 2228 }
2226 /* if we are implementing RTS/CTS, restart reads */ 2229 /* if we are implementing RTS/CTS, restart reads */
2227 /* are the Edgeport will assert the RTS line */ 2230 /* are the Edgeport will assert the RTS line */
@@ -2271,11 +2274,10 @@ static int restart_read(struct edgeport_port *edge_port)
2271 return status; 2274 return status;
2272} 2275}
2273 2276
2274static void change_port_settings(struct edgeport_port *edge_port, 2277static void change_port_settings(struct tty_struct *tty,
2275 struct ktermios *old_termios) 2278 struct edgeport_port *edge_port, struct ktermios *old_termios)
2276{ 2279{
2277 struct ump_uart_config *config; 2280 struct ump_uart_config *config;
2278 struct tty_struct *tty;
2279 int baud; 2281 int baud;
2280 unsigned cflag; 2282 unsigned cflag;
2281 int status; 2283 int status;
@@ -2284,9 +2286,7 @@ static void change_port_settings(struct edgeport_port *edge_port,
2284 2286
2285 dbg("%s - port %d", __func__, edge_port->port->number); 2287 dbg("%s - port %d", __func__, edge_port->port->number);
2286 2288
2287 tty = edge_port->port->tty; 2289 config = kmalloc (sizeof (*config), GFP_KERNEL);
2288
2289 config = kmalloc(sizeof(*config), GFP_KERNEL);
2290 if (!config) { 2290 if (!config) {
2291 *tty->termios = *old_termios; 2291 *tty->termios = *old_termios;
2292 dev_err(&edge_port->port->dev, "%s - out of memory\n", 2292 dev_err(&edge_port->port->dev, "%s - out of memory\n",
@@ -2419,11 +2419,13 @@ static void change_port_settings(struct edgeport_port *edge_port,
2419 return; 2419 return;
2420} 2420}
2421 2421
2422static void edge_set_termios(struct usb_serial_port *port, 2422static void edge_set_termios(struct tty_struct *tty,
2423 struct ktermios *old_termios) 2423 struct usb_serial_port *port, struct ktermios *old_termios)
2424{ 2424{
2425 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2425 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2426 struct tty_struct *tty = port->tty; 2426 unsigned int cflag;
2427
2428 cflag = tty->termios->c_cflag;
2427 2429
2428 dbg("%s - clfag %08x iflag %08x", __func__, 2430 dbg("%s - clfag %08x iflag %08x", __func__,
2429 tty->termios->c_cflag, tty->termios->c_iflag); 2431 tty->termios->c_cflag, tty->termios->c_iflag);
@@ -2434,12 +2436,14 @@ static void edge_set_termios(struct usb_serial_port *port,
2434 if (edge_port == NULL) 2436 if (edge_port == NULL)
2435 return; 2437 return;
2436 /* change the port settings to the new ones specified */ 2438 /* change the port settings to the new ones specified */
2437 change_port_settings(edge_port, old_termios); 2439 change_port_settings(tty, edge_port, old_termios);
2440 return;
2438} 2441}
2439 2442
2440static int edge_tiocmset(struct usb_serial_port *port, struct file *file, 2443static int edge_tiocmset(struct tty_struct *tty, struct file *file,
2441 unsigned int set, unsigned int clear) 2444 unsigned int set, unsigned int clear)
2442{ 2445{
2446 struct usb_serial_port *port = tty->driver_data;
2443 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2447 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2444 unsigned int mcr; 2448 unsigned int mcr;
2445 unsigned long flags; 2449 unsigned long flags;
@@ -2469,8 +2473,9 @@ static int edge_tiocmset(struct usb_serial_port *port, struct file *file,
2469 return 0; 2473 return 0;
2470} 2474}
2471 2475
2472static int edge_tiocmget(struct usb_serial_port *port, struct file *file) 2476static int edge_tiocmget(struct tty_struct *tty, struct file *file)
2473{ 2477{
2478 struct usb_serial_port *port = tty->driver_data;
2474 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2479 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2475 unsigned int result = 0; 2480 unsigned int result = 0;
2476 unsigned int msr; 2481 unsigned int msr;
@@ -2522,9 +2527,10 @@ static int get_serial_info(struct edgeport_port *edge_port,
2522 return 0; 2527 return 0;
2523} 2528}
2524 2529
2525static int edge_ioctl(struct usb_serial_port *port, struct file *file, 2530static int edge_ioctl(struct tty_struct *tty, struct file *file,
2526 unsigned int cmd, unsigned long arg) 2531 unsigned int cmd, unsigned long arg)
2527{ 2532{
2533 struct usb_serial_port *port = tty->driver_data;
2528 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2534 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2529 struct async_icount cnow; 2535 struct async_icount cnow;
2530 struct async_icount cprev; 2536 struct async_icount cprev;
@@ -2569,18 +2575,19 @@ static int edge_ioctl(struct usb_serial_port *port, struct file *file,
2569 return -ENOIOCTLCMD; 2575 return -ENOIOCTLCMD;
2570} 2576}
2571 2577
2572static void edge_break(struct usb_serial_port *port, int on) 2578static void edge_break(struct tty_struct *tty, int break_state)
2573{ 2579{
2580 struct usb_serial_port *port = tty->driver_data;
2574 struct edgeport_port *edge_port = usb_get_serial_port_data(port); 2581 struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2575 int status; 2582 int status;
2576 int bv = 0; /* Off */ 2583 int bv = 0; /* Off */
2577 2584
2578 dbg("%s - state = %d", __func__, on); 2585 dbg("%s - state = %d", __func__, break_state);
2579 2586
2580 /* chase the port close */ 2587 /* chase the port close */
2581 chase_port(edge_port, 0, 0); 2588 chase_port(edge_port, 0, 0);
2582 2589
2583 if (on == -1) 2590 if (break_state == -1)
2584 bv = 1; /* On */ 2591 bv = 1; /* On */
2585 status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); 2592 status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
2586 if (status) 2593 if (status)