diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 |
commit | 0f4974c439dd7826c85bae4e6a8088ce2db0f498 (patch) | |
tree | fdabc7d9bb7d7bc49aad547c0aac3a633ce01f09 /drivers/usb | |
parent | 3126c136bc30225d7a43af741778aa50e95e467a (diff) | |
parent | 36ba782e9674cdc29ec7003757df0b375e99fa96 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (58 commits)
tty: split the lock up a bit further
tty: Move the leader test in disassociate
tty: Push the bkl down a bit in the hangup code
tty: Push the lock down further into the ldisc code
tty: push the BKL down into the handlers a bit
tty: moxa: split open lock
tty: moxa: Kill the use of lock_kernel
tty: moxa: Fix modem op locking
tty: moxa: Kill off the throttle method
tty: moxa: Locking clean up
tty: moxa: rework the locking a bit
tty: moxa: Use more tty_port ops
tty: isicom: fix deadlock on shutdown
tty: mxser: Use the new locking rules to fix setserial properly
tty: mxser: use the tty_port_open method
tty: isicom: sort out the board init logic
tty: isicom: switch to the new tty_port_open helper
tty: tty_port: Add a kref object to the tty port
tty: istallion: tty port open/close methods
tty: stallion: Convert to the tty_port_open/close methods
...
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/opticon.c | 7 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 83 |
2 files changed, 32 insertions, 58 deletions
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 80f59b6350cb..4cdb975caa89 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -501,12 +501,13 @@ static int opticon_resume(struct usb_interface *intf) | |||
501 | struct usb_serial_port *port = serial->port[0]; | 501 | struct usb_serial_port *port = serial->port[0]; |
502 | int result; | 502 | int result; |
503 | 503 | ||
504 | mutex_lock(&port->mutex); | 504 | mutex_lock(&port->port.mutex); |
505 | if (port->port.count) | 505 | /* This is protected by the port mutex against close/open */ |
506 | if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
506 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); | 507 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); |
507 | else | 508 | else |
508 | result = 0; | 509 | result = 0; |
509 | mutex_unlock(&port->mutex); | 510 | mutex_unlock(&port->port.mutex); |
510 | return result; | 511 | return result; |
511 | } | 512 | } |
512 | 513 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd3fa7ff15b1..4543f359be75 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -247,96 +247,66 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
247 | return retval; | 247 | return retval; |
248 | } | 248 | } |
249 | 249 | ||
250 | static int serial_open(struct tty_struct *tty, struct file *filp) | 250 | static int serial_activate(struct tty_port *tport, struct tty_struct *tty) |
251 | { | 251 | { |
252 | struct usb_serial_port *port = tty->driver_data; | 252 | struct usb_serial_port *port = |
253 | container_of(tport, struct usb_serial_port, port); | ||
253 | struct usb_serial *serial = port->serial; | 254 | struct usb_serial *serial = port->serial; |
254 | int retval; | 255 | int retval; |
255 | 256 | ||
256 | dbg("%s - port %d", __func__, port->number); | 257 | mutex_lock(&serial->disc_mutex); |
257 | 258 | if (serial->disconnected) | |
258 | spin_lock_irq(&port->port.lock); | 259 | retval = -ENODEV; |
259 | if (!tty_hung_up_p(filp)) | 260 | else |
260 | ++port->port.count; | 261 | retval = port->serial->type->open(tty, port); |
261 | spin_unlock_irq(&port->port.lock); | 262 | mutex_unlock(&serial->disc_mutex); |
262 | tty_port_tty_set(&port->port, tty); | 263 | return retval; |
264 | } | ||
263 | 265 | ||
264 | /* Do the device-specific open only if the hardware isn't | 266 | static int serial_open(struct tty_struct *tty, struct file *filp) |
265 | * already initialized. | 267 | { |
266 | */ | 268 | struct usb_serial_port *port = tty->driver_data; |
267 | if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { | ||
268 | if (mutex_lock_interruptible(&port->mutex)) | ||
269 | return -ERESTARTSYS; | ||
270 | mutex_lock(&serial->disc_mutex); | ||
271 | if (serial->disconnected) | ||
272 | retval = -ENODEV; | ||
273 | else | ||
274 | retval = port->serial->type->open(tty, port); | ||
275 | mutex_unlock(&serial->disc_mutex); | ||
276 | mutex_unlock(&port->mutex); | ||
277 | if (retval) | ||
278 | return retval; | ||
279 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | ||
280 | } | ||
281 | 269 | ||
282 | /* Now do the correct tty layer semantics */ | 270 | dbg("%s - port %d", __func__, port->number); |
283 | retval = tty_port_block_til_ready(&port->port, tty, filp); | 271 | return tty_port_open(&port->port, tty, filp); |
284 | return retval; | ||
285 | } | 272 | } |
286 | 273 | ||
287 | /** | 274 | /** |
288 | * serial_down - shut down hardware | 275 | * serial_down - shut down hardware |
289 | * @port: port to shut down | 276 | * @tport: tty port to shut down |
290 | * | 277 | * |
291 | * Shut down a USB serial port unless it is the console. We never | 278 | * Shut down a USB serial port unless it is the console. We never |
292 | * shut down the console hardware as it will always be in use. | 279 | * shut down the console hardware as it will always be in use. Serialized |
280 | * against activate by the tport mutex and kept to matching open/close pairs | ||
281 | * of calls by the ASYNCB_INITIALIZED flag. | ||
293 | */ | 282 | */ |
294 | static void serial_down(struct usb_serial_port *port) | 283 | static void serial_down(struct tty_port *tport) |
295 | { | 284 | { |
285 | struct usb_serial_port *port = | ||
286 | container_of(tport, struct usb_serial_port, port); | ||
296 | struct usb_serial_driver *drv = port->serial->type; | 287 | struct usb_serial_driver *drv = port->serial->type; |
297 | |||
298 | /* | 288 | /* |
299 | * The console is magical. Do not hang up the console hardware | 289 | * The console is magical. Do not hang up the console hardware |
300 | * or there will be tears. | 290 | * or there will be tears. |
301 | */ | 291 | */ |
302 | if (port->console) | 292 | if (port->console) |
303 | return; | 293 | return; |
304 | |||
305 | /* Don't call the close method if the hardware hasn't been | ||
306 | * initialized. | ||
307 | */ | ||
308 | if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
309 | return; | ||
310 | |||
311 | mutex_lock(&port->mutex); | ||
312 | if (drv->close) | 294 | if (drv->close) |
313 | drv->close(port); | 295 | drv->close(port); |
314 | mutex_unlock(&port->mutex); | ||
315 | } | 296 | } |
316 | 297 | ||
317 | static void serial_hangup(struct tty_struct *tty) | 298 | static void serial_hangup(struct tty_struct *tty) |
318 | { | 299 | { |
319 | struct usb_serial_port *port = tty->driver_data; | 300 | struct usb_serial_port *port = tty->driver_data; |
320 | |||
321 | dbg("%s - port %d", __func__, port->number); | 301 | dbg("%s - port %d", __func__, port->number); |
322 | |||
323 | serial_down(port); | ||
324 | tty_port_hangup(&port->port); | 302 | tty_port_hangup(&port->port); |
325 | } | 303 | } |
326 | 304 | ||
327 | static void serial_close(struct tty_struct *tty, struct file *filp) | 305 | static void serial_close(struct tty_struct *tty, struct file *filp) |
328 | { | 306 | { |
329 | struct usb_serial_port *port = tty->driver_data; | 307 | struct usb_serial_port *port = tty->driver_data; |
330 | |||
331 | dbg("%s - port %d", __func__, port->number); | 308 | dbg("%s - port %d", __func__, port->number); |
332 | 309 | tty_port_close(&port->port, tty, filp); | |
333 | if (tty_hung_up_p(filp)) | ||
334 | return; | ||
335 | if (tty_port_close_start(&port->port, tty, filp) == 0) | ||
336 | return; | ||
337 | serial_down(port); | ||
338 | tty_port_close_end(&port->port, tty); | ||
339 | tty_port_tty_set(&port->port, NULL); | ||
340 | } | 310 | } |
341 | 311 | ||
342 | /** | 312 | /** |
@@ -725,6 +695,8 @@ static void serial_dtr_rts(struct tty_port *port, int on) | |||
725 | static const struct tty_port_operations serial_port_ops = { | 695 | static const struct tty_port_operations serial_port_ops = { |
726 | .carrier_raised = serial_carrier_raised, | 696 | .carrier_raised = serial_carrier_raised, |
727 | .dtr_rts = serial_dtr_rts, | 697 | .dtr_rts = serial_dtr_rts, |
698 | .activate = serial_activate, | ||
699 | .shutdown = serial_down, | ||
728 | }; | 700 | }; |
729 | 701 | ||
730 | int usb_serial_probe(struct usb_interface *interface, | 702 | int usb_serial_probe(struct usb_interface *interface, |
@@ -923,7 +895,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
923 | port->port.ops = &serial_port_ops; | 895 | port->port.ops = &serial_port_ops; |
924 | port->serial = serial; | 896 | port->serial = serial; |
925 | spin_lock_init(&port->lock); | 897 | spin_lock_init(&port->lock); |
926 | mutex_init(&port->mutex); | 898 | /* Keep this for private driver use for the moment but |
899 | should probably go away */ | ||
927 | INIT_WORK(&port->work, usb_serial_port_work); | 900 | INIT_WORK(&port->work, usb_serial_port_work); |
928 | serial->port[i] = port; | 901 | serial->port[i] = port; |
929 | port->dev.parent = &interface->dev; | 902 | port->dev.parent = &interface->dev; |