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/generic.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/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 537f12a027c2..5128018c2766 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -112,7 +112,8 @@ void usb_serial_generic_deregister (void) | |||
112 | #endif | 112 | #endif |
113 | } | 113 | } |
114 | 114 | ||
115 | int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | 115 | int usb_serial_generic_open(struct tty_struct *tty, |
116 | struct usb_serial_port *port, struct file *filp) | ||
116 | { | 117 | { |
117 | struct usb_serial *serial = port->serial; | 118 | struct usb_serial *serial = port->serial; |
118 | int result = 0; | 119 | int result = 0; |
@@ -123,8 +124,8 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | |||
123 | /* force low_latency on so that our tty_push actually forces the data through, | 124 | /* force low_latency on so that our tty_push actually forces the data through, |
124 | otherwise it is scheduled, and with high data rates (like with OHCI) data | 125 | otherwise it is scheduled, and with high data rates (like with OHCI) data |
125 | can get lost. */ | 126 | can get lost. */ |
126 | if (port->tty) | 127 | if (tty) |
127 | port->tty->low_latency = 1; | 128 | tty->low_latency = 1; |
128 | 129 | ||
129 | /* clear the throttle flags */ | 130 | /* clear the throttle flags */ |
130 | spin_lock_irqsave(&port->lock, flags); | 131 | spin_lock_irqsave(&port->lock, flags); |
@@ -152,7 +153,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | |||
152 | } | 153 | } |
153 | EXPORT_SYMBOL_GPL(usb_serial_generic_open); | 154 | EXPORT_SYMBOL_GPL(usb_serial_generic_open); |
154 | 155 | ||
155 | static void generic_cleanup (struct usb_serial_port *port) | 156 | static void generic_cleanup(struct usb_serial_port *port) |
156 | { | 157 | { |
157 | struct usb_serial *serial = port->serial; | 158 | struct usb_serial *serial = port->serial; |
158 | 159 | ||
@@ -182,7 +183,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
182 | #endif | 183 | #endif |
183 | for (i = 0; i < serial->num_ports; i++) { | 184 | for (i = 0; i < serial->num_ports; i++) { |
184 | port = serial->port[i]; | 185 | port = serial->port[i]; |
185 | if (port->open_count && port->read_urb) { | 186 | if (port->port.count && port->read_urb) { |
186 | r = usb_submit_urb(port->read_urb, GFP_NOIO); | 187 | r = usb_submit_urb(port->read_urb, GFP_NOIO); |
187 | if (r < 0) | 188 | if (r < 0) |
188 | c++; | 189 | c++; |
@@ -192,13 +193,15 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
192 | return c ? -EIO : 0; | 193 | return c ? -EIO : 0; |
193 | } | 194 | } |
194 | 195 | ||
195 | void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) | 196 | void usb_serial_generic_close(struct tty_struct *tty, |
197 | struct usb_serial_port *port, struct file * filp) | ||
196 | { | 198 | { |
197 | dbg("%s - port %d", __func__, port->number); | 199 | dbg("%s - port %d", __func__, port->number); |
198 | generic_cleanup (port); | 200 | generic_cleanup (port); |
199 | } | 201 | } |
200 | 202 | ||
201 | int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count) | 203 | int usb_serial_generic_write(struct tty_struct *tty, |
204 | struct usb_serial_port *port, const unsigned char *buf, int count) | ||
202 | { | 205 | { |
203 | struct usb_serial *serial = port->serial; | 206 | struct usb_serial *serial = port->serial; |
204 | int result; | 207 | int result; |
@@ -255,8 +258,9 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
255 | return 0; | 258 | return 0; |
256 | } | 259 | } |
257 | 260 | ||
258 | int usb_serial_generic_write_room (struct usb_serial_port *port) | 261 | int usb_serial_generic_write_room (struct tty_struct *tty) |
259 | { | 262 | { |
263 | struct usb_serial_port *port = tty->driver_data; | ||
260 | struct usb_serial *serial = port->serial; | 264 | struct usb_serial *serial = port->serial; |
261 | int room = 0; | 265 | int room = 0; |
262 | 266 | ||
@@ -272,8 +276,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port) | |||
272 | return room; | 276 | return room; |
273 | } | 277 | } |
274 | 278 | ||
275 | int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | 279 | int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) |
276 | { | 280 | { |
281 | struct usb_serial_port *port = tty->driver_data; | ||
277 | struct usb_serial *serial = port->serial; | 282 | struct usb_serial *serial = port->serial; |
278 | int chars = 0; | 283 | int chars = 0; |
279 | 284 | ||
@@ -286,7 +291,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
286 | } | 291 | } |
287 | 292 | ||
288 | dbg("%s - returns %d", __func__, chars); | 293 | dbg("%s - returns %d", __func__, chars); |
289 | return (chars); | 294 | return chars; |
290 | } | 295 | } |
291 | 296 | ||
292 | 297 | ||
@@ -311,10 +316,10 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) | |||
311 | } | 316 | } |
312 | 317 | ||
313 | /* Push data to tty layer and resubmit the bulk read URB */ | 318 | /* Push data to tty layer and resubmit the bulk read URB */ |
314 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | 319 | static void flush_and_resubmit_read_urb(struct usb_serial_port *port) |
315 | { | 320 | { |
316 | struct urb *urb = port->read_urb; | 321 | struct urb *urb = port->read_urb; |
317 | struct tty_struct *tty = port->tty; | 322 | struct tty_struct *tty = port->port.tty; |
318 | int room; | 323 | int room; |
319 | 324 | ||
320 | /* Push data to tty */ | 325 | /* Push data to tty */ |
@@ -329,7 +334,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | |||
329 | resubmit_read_urb(port, GFP_ATOMIC); | 334 | resubmit_read_urb(port, GFP_ATOMIC); |
330 | } | 335 | } |
331 | 336 | ||
332 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | 337 | void usb_serial_generic_read_bulk_callback(struct urb *urb) |
333 | { | 338 | { |
334 | struct usb_serial_port *port = urb->context; | 339 | struct usb_serial_port *port = urb->context; |
335 | unsigned char *data = urb->transfer_buffer; | 340 | unsigned char *data = urb->transfer_buffer; |
@@ -357,7 +362,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) | |||
357 | } | 362 | } |
358 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); | 363 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); |
359 | 364 | ||
360 | void usb_serial_generic_write_bulk_callback (struct urb *urb) | 365 | void usb_serial_generic_write_bulk_callback(struct urb *urb) |
361 | { | 366 | { |
362 | struct usb_serial_port *port = urb->context; | 367 | struct usb_serial_port *port = urb->context; |
363 | int status = urb->status; | 368 | int status = urb->status; |
@@ -374,8 +379,9 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb) | |||
374 | } | 379 | } |
375 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 380 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
376 | 381 | ||
377 | void usb_serial_generic_throttle (struct usb_serial_port *port) | 382 | void usb_serial_generic_throttle(struct tty_struct *tty) |
378 | { | 383 | { |
384 | struct usb_serial_port *port = tty->driver_data; | ||
379 | unsigned long flags; | 385 | unsigned long flags; |
380 | 386 | ||
381 | dbg("%s - port %d", __func__, port->number); | 387 | dbg("%s - port %d", __func__, port->number); |
@@ -387,8 +393,9 @@ void usb_serial_generic_throttle (struct usb_serial_port *port) | |||
387 | spin_unlock_irqrestore(&port->lock, flags); | 393 | spin_unlock_irqrestore(&port->lock, flags); |
388 | } | 394 | } |
389 | 395 | ||
390 | void usb_serial_generic_unthrottle (struct usb_serial_port *port) | 396 | void usb_serial_generic_unthrottle(struct tty_struct *tty) |
391 | { | 397 | { |
398 | struct usb_serial_port *port = tty->driver_data; | ||
392 | int was_throttled; | 399 | int was_throttled; |
393 | unsigned long flags; | 400 | unsigned long flags; |
394 | 401 | ||