aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/generic_serial.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 08:45:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:38 -0500
commit31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch)
tree39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/generic_serial.c
parentc9b3976e3fec266be25c5001a70aa0a890b6c476 (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.c43
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
398int gs_block_til_ready(void *port_, struct file * filp) 398int 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}