diff options
author | Alan Cox <alan@redhat.com> | 2008-07-22 06:09:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:03:22 -0400 |
commit | 95da310e66ee8090119596c70ca8432e57f9a97f (patch) | |
tree | 7f18c30e9c9ad4d7d53df6453fa338be06f09a85 /drivers/usb/serial/empeg.c | |
parent | 1aa3692da57c773e5c76de55c5c4a953962d360e (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/empeg.c')
-rw-r--r-- | drivers/usb/serial/empeg.c | 78 |
1 files changed, 30 insertions, 48 deletions
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index c5ec309a3cb1..47ebdf5fad8e 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * Moved MOD_DEC_USE_COUNT to end of empeg_close(). | 31 | * Moved MOD_DEC_USE_COUNT to end of empeg_close(). |
32 | * | 32 | * |
33 | * (12/03/2000) gb | 33 | * (12/03/2000) gb |
34 | * Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open() | 34 | * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to empeg_open() |
35 | * This notifies the tty driver that the termios have changed. | 35 | * This notifies the tty driver that the termios have changed. |
36 | * | 36 | * |
37 | * (11/13/2000) gb | 37 | * (11/13/2000) gb |
@@ -77,22 +77,18 @@ static int debug; | |||
77 | #define EMPEG_PRODUCT_ID 0x0001 | 77 | #define EMPEG_PRODUCT_ID 0x0001 |
78 | 78 | ||
79 | /* function prototypes for an empeg-car player */ | 79 | /* function prototypes for an empeg-car player */ |
80 | static int empeg_open (struct usb_serial_port *port, struct file *filp); | 80 | static int empeg_open (struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); |
81 | static void empeg_close (struct usb_serial_port *port, struct file *filp); | 81 | static void empeg_close (struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); |
82 | static int empeg_write (struct usb_serial_port *port, | 82 | static int empeg_write (struct tty_struct *tty, struct usb_serial_port *port, |
83 | const unsigned char *buf, | 83 | const unsigned char *buf, |
84 | int count); | 84 | int count); |
85 | static int empeg_write_room (struct usb_serial_port *port); | 85 | static int empeg_write_room (struct tty_struct *tty); |
86 | static int empeg_chars_in_buffer (struct usb_serial_port *port); | 86 | static int empeg_chars_in_buffer (struct tty_struct *tty); |
87 | static void empeg_throttle (struct usb_serial_port *port); | 87 | static void empeg_throttle (struct tty_struct *tty); |
88 | static void empeg_unthrottle (struct usb_serial_port *port); | 88 | static void empeg_unthrottle (struct tty_struct *tty); |
89 | static int empeg_startup (struct usb_serial *serial); | 89 | static int empeg_startup (struct usb_serial *serial); |
90 | static void empeg_shutdown (struct usb_serial *serial); | 90 | static void empeg_shutdown (struct usb_serial *serial); |
91 | static int empeg_ioctl (struct usb_serial_port *port, | 91 | static void empeg_set_termios (struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); |
92 | struct file * file, | ||
93 | unsigned int cmd, | ||
94 | unsigned long arg); | ||
95 | static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); | ||
96 | static void empeg_write_bulk_callback (struct urb *urb); | 92 | static void empeg_write_bulk_callback (struct urb *urb); |
97 | static void empeg_read_bulk_callback (struct urb *urb); | 93 | static void empeg_read_bulk_callback (struct urb *urb); |
98 | 94 | ||
@@ -125,7 +121,6 @@ static struct usb_serial_driver empeg_device = { | |||
125 | .unthrottle = empeg_unthrottle, | 121 | .unthrottle = empeg_unthrottle, |
126 | .attach = empeg_startup, | 122 | .attach = empeg_startup, |
127 | .shutdown = empeg_shutdown, | 123 | .shutdown = empeg_shutdown, |
128 | .ioctl = empeg_ioctl, | ||
129 | .set_termios = empeg_set_termios, | 124 | .set_termios = empeg_set_termios, |
130 | .write = empeg_write, | 125 | .write = empeg_write, |
131 | .write_room = empeg_write_room, | 126 | .write_room = empeg_write_room, |
@@ -145,7 +140,8 @@ static int bytes_out; | |||
145 | /****************************************************************************** | 140 | /****************************************************************************** |
146 | * Empeg specific driver functions | 141 | * Empeg specific driver functions |
147 | ******************************************************************************/ | 142 | ******************************************************************************/ |
148 | static int empeg_open (struct usb_serial_port *port, struct file *filp) | 143 | static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port, |
144 | struct file *filp) | ||
149 | { | 145 | { |
150 | struct usb_serial *serial = port->serial; | 146 | struct usb_serial *serial = port->serial; |
151 | int result = 0; | 147 | int result = 0; |
@@ -153,7 +149,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp) | |||
153 | dbg("%s - port %d", __func__, port->number); | 149 | dbg("%s - port %d", __func__, port->number); |
154 | 150 | ||
155 | /* Force default termio settings */ | 151 | /* Force default termio settings */ |
156 | empeg_set_termios (port, NULL) ; | 152 | empeg_set_termios (tty, port, NULL) ; |
157 | 153 | ||
158 | bytes_in = 0; | 154 | bytes_in = 0; |
159 | bytes_out = 0; | 155 | bytes_out = 0; |
@@ -178,7 +174,8 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp) | |||
178 | } | 174 | } |
179 | 175 | ||
180 | 176 | ||
181 | static void empeg_close (struct usb_serial_port *port, struct file * filp) | 177 | static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port, |
178 | struct file * filp) | ||
182 | { | 179 | { |
183 | dbg("%s - port %d", __func__, port->number); | 180 | dbg("%s - port %d", __func__, port->number); |
184 | 181 | ||
@@ -189,7 +186,7 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp) | |||
189 | } | 186 | } |
190 | 187 | ||
191 | 188 | ||
192 | static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count) | 189 | static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) |
193 | { | 190 | { |
194 | struct usb_serial *serial = port->serial; | 191 | struct usb_serial *serial = port->serial; |
195 | struct urb *urb; | 192 | struct urb *urb; |
@@ -203,7 +200,6 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, | |||
203 | dbg("%s - port %d", __func__, port->number); | 200 | dbg("%s - port %d", __func__, port->number); |
204 | 201 | ||
205 | while (count > 0) { | 202 | while (count > 0) { |
206 | |||
207 | /* try to find a free urb in our list of them */ | 203 | /* try to find a free urb in our list of them */ |
208 | urb = NULL; | 204 | urb = NULL; |
209 | 205 | ||
@@ -262,15 +258,14 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, | |||
262 | bytes_out += transfer_size; | 258 | bytes_out += transfer_size; |
263 | 259 | ||
264 | } | 260 | } |
265 | |||
266 | exit: | 261 | exit: |
267 | return bytes_sent; | 262 | return bytes_sent; |
268 | |||
269 | } | 263 | } |
270 | 264 | ||
271 | 265 | ||
272 | static int empeg_write_room (struct usb_serial_port *port) | 266 | static int empeg_write_room(struct tty_struct *tty) |
273 | { | 267 | { |
268 | struct usb_serial_port *port = tty->driver_data; | ||
274 | unsigned long flags; | 269 | unsigned long flags; |
275 | int i; | 270 | int i; |
276 | int room = 0; | 271 | int room = 0; |
@@ -278,25 +273,22 @@ static int empeg_write_room (struct usb_serial_port *port) | |||
278 | dbg("%s - port %d", __func__, port->number); | 273 | dbg("%s - port %d", __func__, port->number); |
279 | 274 | ||
280 | spin_lock_irqsave (&write_urb_pool_lock, flags); | 275 | spin_lock_irqsave (&write_urb_pool_lock, flags); |
281 | |||
282 | /* tally up the number of bytes available */ | 276 | /* tally up the number of bytes available */ |
283 | for (i = 0; i < NUM_URBS; ++i) { | 277 | for (i = 0; i < NUM_URBS; ++i) { |
284 | if (write_urb_pool[i]->status != -EINPROGRESS) { | 278 | if (write_urb_pool[i]->status != -EINPROGRESS) { |
285 | room += URB_TRANSFER_BUFFER_SIZE; | 279 | room += URB_TRANSFER_BUFFER_SIZE; |
286 | } | 280 | } |
287 | } | 281 | } |
288 | |||
289 | spin_unlock_irqrestore (&write_urb_pool_lock, flags); | 282 | spin_unlock_irqrestore (&write_urb_pool_lock, flags); |
290 | |||
291 | dbg("%s - returns %d", __func__, room); | 283 | dbg("%s - returns %d", __func__, room); |
292 | 284 | return room; | |
293 | return (room); | ||
294 | 285 | ||
295 | } | 286 | } |
296 | 287 | ||
297 | 288 | ||
298 | static int empeg_chars_in_buffer (struct usb_serial_port *port) | 289 | static int empeg_chars_in_buffer(struct tty_struct *tty) |
299 | { | 290 | { |
291 | struct usb_serial_port *port = tty->driver_data; | ||
300 | unsigned long flags; | 292 | unsigned long flags; |
301 | int i; | 293 | int i; |
302 | int chars = 0; | 294 | int chars = 0; |
@@ -356,7 +348,7 @@ static void empeg_read_bulk_callback (struct urb *urb) | |||
356 | 348 | ||
357 | usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); | 349 | usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); |
358 | 350 | ||
359 | tty = port->tty; | 351 | tty = port->port.tty; |
360 | 352 | ||
361 | if (urb->actual_length) { | 353 | if (urb->actual_length) { |
362 | tty_buffer_request_room(tty, urb->actual_length); | 354 | tty_buffer_request_room(tty, urb->actual_length); |
@@ -386,27 +378,24 @@ static void empeg_read_bulk_callback (struct urb *urb) | |||
386 | } | 378 | } |
387 | 379 | ||
388 | 380 | ||
389 | static void empeg_throttle (struct usb_serial_port *port) | 381 | static void empeg_throttle(struct tty_struct *tty) |
390 | { | 382 | { |
383 | struct usb_serial_port *port = tty->driver_data; | ||
391 | dbg("%s - port %d", __func__, port->number); | 384 | dbg("%s - port %d", __func__, port->number); |
392 | usb_kill_urb(port->read_urb); | 385 | usb_kill_urb(port->read_urb); |
393 | } | 386 | } |
394 | 387 | ||
395 | 388 | ||
396 | static void empeg_unthrottle (struct usb_serial_port *port) | 389 | static void empeg_unthrottle(struct tty_struct *tty) |
397 | { | 390 | { |
391 | struct usb_serial_port *port = tty->driver_data; | ||
398 | int result; | 392 | int result; |
399 | |||
400 | dbg("%s - port %d", __func__, port->number); | 393 | dbg("%s - port %d", __func__, port->number); |
401 | 394 | ||
402 | port->read_urb->dev = port->serial->dev; | 395 | port->read_urb->dev = port->serial->dev; |
403 | |||
404 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 396 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
405 | |||
406 | if (result) | 397 | if (result) |
407 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); | 398 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); |
408 | |||
409 | return; | ||
410 | } | 399 | } |
411 | 400 | ||
412 | 401 | ||
@@ -436,17 +425,10 @@ static void empeg_shutdown (struct usb_serial *serial) | |||
436 | } | 425 | } |
437 | 426 | ||
438 | 427 | ||
439 | static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) | 428 | static void empeg_set_termios(struct tty_struct *tty, |
440 | { | 429 | struct usb_serial_port *port, struct ktermios *old_termios) |
441 | dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); | ||
442 | |||
443 | return -ENOIOCTLCMD; | ||
444 | } | ||
445 | |||
446 | |||
447 | static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) | ||
448 | { | 430 | { |
449 | struct ktermios *termios = port->tty->termios; | 431 | struct ktermios *termios = tty->termios; |
450 | dbg("%s - port %d", __func__, port->number); | 432 | dbg("%s - port %d", __func__, port->number); |
451 | 433 | ||
452 | /* | 434 | /* |
@@ -491,8 +473,8 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol | |||
491 | * this is bad as it opens up the possibility of dropping bytes | 473 | * this is bad as it opens up the possibility of dropping bytes |
492 | * on the floor. We don't want to drop bytes on the floor. :) | 474 | * on the floor. We don't want to drop bytes on the floor. :) |
493 | */ | 475 | */ |
494 | port->tty->low_latency = 1; | 476 | tty->low_latency = 1; |
495 | tty_encode_baud_rate(port->tty, 115200, 115200); | 477 | tty_encode_baud_rate(tty, 115200, 115200); |
496 | } | 478 | } |
497 | 479 | ||
498 | 480 | ||