aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/generic_serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/generic_serial.c')
-rw-r--r--drivers/char/generic_serial.c76
1 files changed, 44 insertions, 32 deletions
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index c6090f84a2e4..9e4e569dc00d 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -376,7 +376,8 @@ static void gs_shutdown_port (struct gs_port *port)
376 376
377void gs_hangup(struct tty_struct *tty) 377void gs_hangup(struct tty_struct *tty)
378{ 378{
379 struct gs_port *port; 379 struct gs_port *port;
380 unsigned long flags;
380 381
381 func_enter (); 382 func_enter ();
382 383
@@ -386,9 +387,11 @@ void gs_hangup(struct tty_struct *tty)
386 return; 387 return;
387 388
388 gs_shutdown_port (port); 389 gs_shutdown_port (port);
390 spin_lock_irqsave(&port->port.lock, flags);
389 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE); 391 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
390 port->port.tty = NULL; 392 port->port.tty = NULL;
391 port->port.count = 0; 393 port->port.count = 0;
394 spin_unlock_irqrestore(&port->port.lock, flags);
392 395
393 wake_up_interruptible(&port->port.open_wait); 396 wake_up_interruptible(&port->port.open_wait);
394 func_exit (); 397 func_exit ();
@@ -397,7 +400,8 @@ void gs_hangup(struct tty_struct *tty)
397 400
398int gs_block_til_ready(void *port_, struct file * filp) 401int gs_block_til_ready(void *port_, struct file * filp)
399{ 402{
400 struct gs_port *port = port_; 403 struct gs_port *gp = port_;
404 struct tty_port *port = &gp->port;
401 DECLARE_WAITQUEUE(wait, current); 405 DECLARE_WAITQUEUE(wait, current);
402 int retval; 406 int retval;
403 int do_clocal = 0; 407 int do_clocal = 0;
@@ -409,16 +413,16 @@ int gs_block_til_ready(void *port_, struct file * filp)
409 413
410 if (!port) return 0; 414 if (!port) return 0;
411 415
412 tty = port->port.tty; 416 tty = port->tty;
413 417
414 gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 418 gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n");
415 /* 419 /*
416 * If the device is in the middle of being closed, then block 420 * If the device is in the middle of being closed, then block
417 * until it's done, and then try again. 421 * until it's done, and then try again.
418 */ 422 */
419 if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { 423 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
420 interruptible_sleep_on(&port->port.close_wait); 424 interruptible_sleep_on(&port->close_wait);
421 if (port->port.flags & ASYNC_HUP_NOTIFY) 425 if (port->flags & ASYNC_HUP_NOTIFY)
422 return -EAGAIN; 426 return -EAGAIN;
423 else 427 else
424 return -ERESTARTSYS; 428 return -ERESTARTSYS;
@@ -432,7 +436,7 @@ int gs_block_til_ready(void *port_, struct file * filp)
432 */ 436 */
433 if ((filp->f_flags & O_NONBLOCK) || 437 if ((filp->f_flags & O_NONBLOCK) ||
434 (tty->flags & (1 << TTY_IO_ERROR))) { 438 (tty->flags & (1 << TTY_IO_ERROR))) {
435 port->port.flags |= ASYNC_NORMAL_ACTIVE; 439 port->flags |= ASYNC_NORMAL_ACTIVE;
436 return 0; 440 return 0;
437 } 441 }
438 442
@@ -444,34 +448,34 @@ int gs_block_til_ready(void *port_, struct file * filp)
444 /* 448 /*
445 * Block waiting for the carrier detect and the line to become 449 * 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 450 * 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 451 * this loop, port->count is dropped by one, so that
448 * rs_close() knows when to free things. We restore it upon 452 * rs_close() knows when to free things. We restore it upon
449 * exit, either normal or abnormal. 453 * exit, either normal or abnormal.
450 */ 454 */
451 retval = 0; 455 retval = 0;
452 456
453 add_wait_queue(&port->port.open_wait, &wait); 457 add_wait_queue(&port->open_wait, &wait);
454 458
455 gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 459 gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
456 spin_lock_irqsave(&port->driver_lock, flags); 460 spin_lock_irqsave(&port->lock, flags);
457 if (!tty_hung_up_p(filp)) { 461 if (!tty_hung_up_p(filp)) {
458 port->port.count--; 462 port->count--;
459 } 463 }
460 spin_unlock_irqrestore(&port->driver_lock, flags); 464 port->blocked_open++;
461 port->port.blocked_open++; 465 spin_unlock_irqrestore(&port->lock, flags);
462 while (1) { 466 while (1) {
463 CD = port->rd->get_CD (port); 467 CD = tty_port_carrier_raised(port);
464 gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); 468 gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
465 set_current_state (TASK_INTERRUPTIBLE); 469 set_current_state (TASK_INTERRUPTIBLE);
466 if (tty_hung_up_p(filp) || 470 if (tty_hung_up_p(filp) ||
467 !(port->port.flags & ASYNC_INITIALIZED)) { 471 !(port->flags & ASYNC_INITIALIZED)) {
468 if (port->port.flags & ASYNC_HUP_NOTIFY) 472 if (port->flags & ASYNC_HUP_NOTIFY)
469 retval = -EAGAIN; 473 retval = -EAGAIN;
470 else 474 else
471 retval = -ERESTARTSYS; 475 retval = -ERESTARTSYS;
472 break; 476 break;
473 } 477 }
474 if (!(port->port.flags & ASYNC_CLOSING) && 478 if (!(port->flags & ASYNC_CLOSING) &&
475 (do_clocal || CD)) 479 (do_clocal || CD))
476 break; 480 break;
477 gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", 481 gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n",
@@ -483,19 +487,20 @@ int gs_block_til_ready(void *port_, struct file * filp)
483 schedule(); 487 schedule();
484 } 488 }
485 gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", 489 gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
486 port->port.blocked_open); 490 port->blocked_open);
487 set_current_state (TASK_RUNNING); 491 set_current_state (TASK_RUNNING);
488 remove_wait_queue(&port->port.open_wait, &wait); 492 remove_wait_queue(&port->open_wait, &wait);
493
494 spin_lock_irqsave(&port->lock, flags);
489 if (!tty_hung_up_p(filp)) { 495 if (!tty_hung_up_p(filp)) {
490 port->port.count++; 496 port->count++;
491 } 497 }
492 port->port.blocked_open--; 498 port->blocked_open--;
493 if (retval) 499 if (retval == 0)
494 return retval; 500 port->flags |= ASYNC_NORMAL_ACTIVE;
495 501 spin_unlock_irqrestore(&port->lock, flags);
496 port->port.flags |= ASYNC_NORMAL_ACTIVE;
497 func_exit (); 502 func_exit ();
498 return 0; 503 return retval;
499} 504}
500 505
501 506
@@ -506,7 +511,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
506 511
507 func_enter (); 512 func_enter ();
508 513
509 port = (struct gs_port *) tty->driver_data; 514 port = tty->driver_data;
510 515
511 if (!port) return; 516 if (!port) return;
512 517
@@ -516,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
516 port->port.tty = tty; 521 port->port.tty = tty;
517 } 522 }
518 523
519 spin_lock_irqsave(&port->driver_lock, flags); 524 spin_lock_irqsave(&port->port.lock, flags);
520 525
521 if (tty_hung_up_p(filp)) { 526 if (tty_hung_up_p(filp)) {
522 spin_unlock_irqrestore(&port->driver_lock, flags); 527 spin_unlock_irqrestore(&port->port.lock, flags);
523 if (port->rd->hungup) 528 if (port->rd->hungup)
524 port->rd->hungup (port); 529 port->rd->hungup (port);
525 func_exit (); 530 func_exit ();
@@ -538,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
538 543
539 if (port->port.count) { 544 if (port->port.count) {
540 gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count); 545 gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
541 spin_unlock_irqrestore(&port->driver_lock, flags); 546 spin_unlock_irqrestore(&port->port.lock, flags);
542 func_exit (); 547 func_exit ();
543 return; 548 return;
544 } 549 }
@@ -559,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
559 * line status register. 564 * line status register.
560 */ 565 */
561 566
567 spin_lock_irqsave(&port->driver_lock, flags);
562 port->rd->disable_rx_interrupts (port); 568 port->rd->disable_rx_interrupts (port);
563 spin_unlock_irqrestore(&port->driver_lock, flags); 569 spin_unlock_irqrestore(&port->driver_lock, flags);
570 spin_unlock_irqrestore(&port->port.lock, flags);
564 571
565 /* close has no way of returning "EINTR", so discard return value */ 572 /* close has no way of returning "EINTR", so discard return value */
566 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) 573 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
@@ -573,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp)
573 tty_ldisc_flush(tty); 580 tty_ldisc_flush(tty);
574 tty->closing = 0; 581 tty->closing = 0;
575 582
583 spin_lock_irqsave(&port->driver_lock, flags);
576 port->event = 0; 584 port->event = 0;
577 port->rd->close (port); 585 port->rd->close (port);
578 port->rd->shutdown_port (port); 586 port->rd->shutdown_port (port);
587 spin_unlock_irqrestore(&port->driver_lock, flags);
588
589 spin_lock_irqsave(&port->port.lock, flags);
579 port->port.tty = NULL; 590 port->port.tty = NULL;
580 591
581 if (port->port.blocked_open) { 592 if (port->port.blocked_open) {
582 if (port->close_delay) { 593 if (port->close_delay) {
583 spin_unlock_irqrestore(&port->driver_lock, flags); 594 spin_unlock_irqrestore(&port->port.lock, flags);
584 msleep_interruptible(jiffies_to_msecs(port->close_delay)); 595 msleep_interruptible(jiffies_to_msecs(port->close_delay));
585 spin_lock_irqsave(&port->driver_lock, flags); 596 spin_lock_irqsave(&port->port.lock, flags);
586 } 597 }
587 wake_up_interruptible(&port->port.open_wait); 598 wake_up_interruptible(&port->port.open_wait);
588 } 599 }
589 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED); 600 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
601 spin_unlock_irqrestore(&port->port.lock, flags);
590 wake_up_interruptible(&port->port.close_wait); 602 wake_up_interruptible(&port->port.close_wait);
591 603
592 func_exit (); 604 func_exit ();