diff options
Diffstat (limited to 'drivers/char/generic_serial.c')
-rw-r--r-- | drivers/char/generic_serial.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 2356994ee010..2f040d1ed89f 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 | ||
377 | void gs_hangup(struct tty_struct *tty) | 377 | void 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 (); |
@@ -454,12 +457,12 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
454 | add_wait_queue(&port->open_wait, &wait); | 457 | add_wait_queue(&port->open_wait, &wait); |
455 | 458 | ||
456 | gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); | 459 | gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); |
457 | spin_lock_irqsave(&gp->driver_lock, flags); | 460 | spin_lock_irqsave(&port->lock, flags); |
458 | if (!tty_hung_up_p(filp)) { | 461 | if (!tty_hung_up_p(filp)) { |
459 | port->count--; | 462 | port->count--; |
460 | } | 463 | } |
461 | spin_unlock_irqrestore(&gp->driver_lock, flags); | ||
462 | port->blocked_open++; | 464 | port->blocked_open++; |
465 | spin_unlock_irqrestore(&port->lock, flags); | ||
463 | while (1) { | 466 | while (1) { |
464 | CD = tty_port_carrier_raised(port); | 467 | CD = tty_port_carrier_raised(port); |
465 | gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); | 468 | gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); |
@@ -487,16 +490,17 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
487 | port->blocked_open); | 490 | port->blocked_open); |
488 | set_current_state (TASK_RUNNING); | 491 | set_current_state (TASK_RUNNING); |
489 | remove_wait_queue(&port->open_wait, &wait); | 492 | remove_wait_queue(&port->open_wait, &wait); |
493 | |||
494 | spin_lock_irqsave(&port->lock, flags); | ||
490 | if (!tty_hung_up_p(filp)) { | 495 | if (!tty_hung_up_p(filp)) { |
491 | port->count++; | 496 | port->count++; |
492 | } | 497 | } |
493 | port->blocked_open--; | 498 | port->blocked_open--; |
494 | if (retval) | 499 | if (retval == 0) |
495 | return retval; | 500 | port->flags |= ASYNC_NORMAL_ACTIVE; |
496 | 501 | spin_unlock_irqrestore(&port->lock, flags); | |
497 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
498 | func_exit (); | 502 | func_exit (); |
499 | return 0; | 503 | return retval; |
500 | } | 504 | } |
501 | 505 | ||
502 | 506 | ||
@@ -517,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
517 | port->port.tty = tty; | 521 | port->port.tty = tty; |
518 | } | 522 | } |
519 | 523 | ||
520 | spin_lock_irqsave(&port->driver_lock, flags); | 524 | spin_lock_irqsave(&port->port.lock, flags); |
521 | 525 | ||
522 | if (tty_hung_up_p(filp)) { | 526 | if (tty_hung_up_p(filp)) { |
523 | spin_unlock_irqrestore(&port->driver_lock, flags); | 527 | spin_unlock_irqrestore(&port->port.lock, flags); |
524 | if (port->rd->hungup) | 528 | if (port->rd->hungup) |
525 | port->rd->hungup (port); | 529 | port->rd->hungup (port); |
526 | func_exit (); | 530 | func_exit (); |
@@ -539,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
539 | 543 | ||
540 | if (port->port.count) { | 544 | if (port->port.count) { |
541 | 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); |
542 | spin_unlock_irqrestore(&port->driver_lock, flags); | 546 | spin_unlock_irqrestore(&port->port.lock, flags); |
543 | func_exit (); | 547 | func_exit (); |
544 | return; | 548 | return; |
545 | } | 549 | } |
@@ -560,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
560 | * line status register. | 564 | * line status register. |
561 | */ | 565 | */ |
562 | 566 | ||
567 | spin_lock_irqsave(&port->driver_lock, flags); | ||
563 | port->rd->disable_rx_interrupts (port); | 568 | port->rd->disable_rx_interrupts (port); |
564 | spin_unlock_irqrestore(&port->driver_lock, flags); | 569 | spin_unlock_irqrestore(&port->driver_lock, flags); |
570 | spin_unlock_irqrestore(&port->port.lock, flags); | ||
565 | 571 | ||
566 | /* close has no way of returning "EINTR", so discard return value */ | 572 | /* close has no way of returning "EINTR", so discard return value */ |
567 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 573 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
@@ -574,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
574 | tty_ldisc_flush(tty); | 580 | tty_ldisc_flush(tty); |
575 | tty->closing = 0; | 581 | tty->closing = 0; |
576 | 582 | ||
583 | spin_lock_irqsave(&port->driver_lock, flags); | ||
577 | port->event = 0; | 584 | port->event = 0; |
578 | port->rd->close (port); | 585 | port->rd->close (port); |
579 | 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); | ||
580 | port->port.tty = NULL; | 590 | port->port.tty = NULL; |
581 | 591 | ||
582 | if (port->port.blocked_open) { | 592 | if (port->port.blocked_open) { |
583 | if (port->close_delay) { | 593 | if (port->close_delay) { |
584 | spin_unlock_irqrestore(&port->driver_lock, flags); | 594 | spin_unlock_irqrestore(&port->port.lock, flags); |
585 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); | 595 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); |
586 | spin_lock_irqsave(&port->driver_lock, flags); | 596 | spin_lock_irqsave(&port->port.lock, flags); |
587 | } | 597 | } |
588 | wake_up_interruptible(&port->port.open_wait); | 598 | wake_up_interruptible(&port->port.open_wait); |
589 | } | 599 | } |
590 | 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); | ||
591 | wake_up_interruptible(&port->port.close_wait); | 602 | wake_up_interruptible(&port->port.close_wait); |
592 | 603 | ||
593 | func_exit (); | 604 | func_exit (); |