diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:45:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:38 -0500 |
commit | 31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch) | |
tree | 39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/generic_serial.c | |
parent | c9b3976e3fec266be25c5001a70aa0a890b6c476 (diff) |
tty_port: Add a port level carrier detect operation
This is the first step to generalising the various pieces of waiting logic
duplicated in all sorts of serial drivers.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/generic_serial.c')
-rw-r--r-- | drivers/char/generic_serial.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index c6090f84a2e4..2356994ee010 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -397,7 +397,8 @@ void gs_hangup(struct tty_struct *tty) | |||
397 | 397 | ||
398 | int gs_block_til_ready(void *port_, struct file * filp) | 398 | int gs_block_til_ready(void *port_, struct file * filp) |
399 | { | 399 | { |
400 | struct gs_port *port = port_; | 400 | struct gs_port *gp = port_; |
401 | struct tty_port *port = &gp->port; | ||
401 | DECLARE_WAITQUEUE(wait, current); | 402 | DECLARE_WAITQUEUE(wait, current); |
402 | int retval; | 403 | int retval; |
403 | int do_clocal = 0; | 404 | int do_clocal = 0; |
@@ -409,16 +410,16 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
409 | 410 | ||
410 | if (!port) return 0; | 411 | if (!port) return 0; |
411 | 412 | ||
412 | tty = port->port.tty; | 413 | tty = port->tty; |
413 | 414 | ||
414 | gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); | 415 | gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); |
415 | /* | 416 | /* |
416 | * If the device is in the middle of being closed, then block | 417 | * If the device is in the middle of being closed, then block |
417 | * until it's done, and then try again. | 418 | * until it's done, and then try again. |
418 | */ | 419 | */ |
419 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | 420 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
420 | interruptible_sleep_on(&port->port.close_wait); | 421 | interruptible_sleep_on(&port->close_wait); |
421 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 422 | if (port->flags & ASYNC_HUP_NOTIFY) |
422 | return -EAGAIN; | 423 | return -EAGAIN; |
423 | else | 424 | else |
424 | return -ERESTARTSYS; | 425 | return -ERESTARTSYS; |
@@ -432,7 +433,7 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
432 | */ | 433 | */ |
433 | if ((filp->f_flags & O_NONBLOCK) || | 434 | if ((filp->f_flags & O_NONBLOCK) || |
434 | (tty->flags & (1 << TTY_IO_ERROR))) { | 435 | (tty->flags & (1 << TTY_IO_ERROR))) { |
435 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 436 | port->flags |= ASYNC_NORMAL_ACTIVE; |
436 | return 0; | 437 | return 0; |
437 | } | 438 | } |
438 | 439 | ||
@@ -444,34 +445,34 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
444 | /* | 445 | /* |
445 | * Block waiting for the carrier detect and the line to become | 446 | * Block waiting for the carrier detect and the line to become |
446 | * free (i.e., not in use by the callout). While we are in | 447 | * free (i.e., not in use by the callout). While we are in |
447 | * this loop, port->port.count is dropped by one, so that | 448 | * this loop, port->count is dropped by one, so that |
448 | * rs_close() knows when to free things. We restore it upon | 449 | * rs_close() knows when to free things. We restore it upon |
449 | * exit, either normal or abnormal. | 450 | * exit, either normal or abnormal. |
450 | */ | 451 | */ |
451 | retval = 0; | 452 | retval = 0; |
452 | 453 | ||
453 | add_wait_queue(&port->port.open_wait, &wait); | 454 | add_wait_queue(&port->open_wait, &wait); |
454 | 455 | ||
455 | gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); | 456 | gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); |
456 | spin_lock_irqsave(&port->driver_lock, flags); | 457 | spin_lock_irqsave(&gp->driver_lock, flags); |
457 | if (!tty_hung_up_p(filp)) { | 458 | if (!tty_hung_up_p(filp)) { |
458 | port->port.count--; | 459 | port->count--; |
459 | } | 460 | } |
460 | spin_unlock_irqrestore(&port->driver_lock, flags); | 461 | spin_unlock_irqrestore(&gp->driver_lock, flags); |
461 | port->port.blocked_open++; | 462 | port->blocked_open++; |
462 | while (1) { | 463 | while (1) { |
463 | CD = port->rd->get_CD (port); | 464 | CD = tty_port_carrier_raised(port); |
464 | gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); | 465 | gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); |
465 | set_current_state (TASK_INTERRUPTIBLE); | 466 | set_current_state (TASK_INTERRUPTIBLE); |
466 | if (tty_hung_up_p(filp) || | 467 | if (tty_hung_up_p(filp) || |
467 | !(port->port.flags & ASYNC_INITIALIZED)) { | 468 | !(port->flags & ASYNC_INITIALIZED)) { |
468 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 469 | if (port->flags & ASYNC_HUP_NOTIFY) |
469 | retval = -EAGAIN; | 470 | retval = -EAGAIN; |
470 | else | 471 | else |
471 | retval = -ERESTARTSYS; | 472 | retval = -ERESTARTSYS; |
472 | break; | 473 | break; |
473 | } | 474 | } |
474 | if (!(port->port.flags & ASYNC_CLOSING) && | 475 | if (!(port->flags & ASYNC_CLOSING) && |
475 | (do_clocal || CD)) | 476 | (do_clocal || CD)) |
476 | break; | 477 | break; |
477 | gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", | 478 | gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", |
@@ -483,17 +484,17 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
483 | schedule(); | 484 | schedule(); |
484 | } | 485 | } |
485 | gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", | 486 | gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", |
486 | port->port.blocked_open); | 487 | port->blocked_open); |
487 | set_current_state (TASK_RUNNING); | 488 | set_current_state (TASK_RUNNING); |
488 | remove_wait_queue(&port->port.open_wait, &wait); | 489 | remove_wait_queue(&port->open_wait, &wait); |
489 | if (!tty_hung_up_p(filp)) { | 490 | if (!tty_hung_up_p(filp)) { |
490 | port->port.count++; | 491 | port->count++; |
491 | } | 492 | } |
492 | port->port.blocked_open--; | 493 | port->blocked_open--; |
493 | if (retval) | 494 | if (retval) |
494 | return retval; | 495 | return retval; |
495 | 496 | ||
496 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 497 | port->flags |= ASYNC_NORMAL_ACTIVE; |
497 | func_exit (); | 498 | func_exit (); |
498 | return 0; | 499 | return 0; |
499 | } | 500 | } |