Commit 510a3049 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: relock generic_serial

Switch generic_serial to do port count locking via the tty_port structure
ready for moving to a common port wait routine. Keep the old driver lock for
internal calling so we don't risk messing up the drivers below until we
are ready.

Still needs kref conversions
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 3e61696b
...@@ -376,7 +376,8 @@ static void gs_shutdown_port (struct gs_port *port) ...@@ -376,7 +376,8 @@ static void gs_shutdown_port (struct gs_port *port)
void gs_hangup(struct tty_struct *tty) void gs_hangup(struct tty_struct *tty)
{ {
struct gs_port *port; struct gs_port *port;
unsigned long flags;
func_enter (); func_enter ();
...@@ -386,9 +387,11 @@ void gs_hangup(struct tty_struct *tty) ...@@ -386,9 +387,11 @@ void gs_hangup(struct tty_struct *tty)
return; return;
gs_shutdown_port (port); gs_shutdown_port (port);
spin_lock_irqsave(&port->port.lock, flags);
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE); port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
port->port.tty = NULL; port->port.tty = NULL;
port->port.count = 0; port->port.count = 0;
spin_unlock_irqrestore(&port->port.lock, flags);
wake_up_interruptible(&port->port.open_wait); wake_up_interruptible(&port->port.open_wait);
func_exit (); func_exit ();
...@@ -454,12 +457,12 @@ int gs_block_til_ready(void *port_, struct file * filp) ...@@ -454,12 +457,12 @@ int gs_block_til_ready(void *port_, struct file * filp)
add_wait_queue(&port->open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
spin_lock_irqsave(&gp->driver_lock, flags); spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
port->count--; port->count--;
} }
spin_unlock_irqrestore(&gp->driver_lock, flags);
port->blocked_open++; port->blocked_open++;
spin_unlock_irqrestore(&port->lock, flags);
while (1) { while (1) {
CD = tty_port_carrier_raised(port); CD = tty_port_carrier_raised(port);
gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); 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,16 +490,17 @@ int gs_block_til_ready(void *port_, struct file * filp)
port->blocked_open); port->blocked_open);
set_current_state (TASK_RUNNING); set_current_state (TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
port->count++; port->count++;
} }
port->blocked_open--; port->blocked_open--;
if (retval) if (retval == 0)
return retval; port->flags |= ASYNC_NORMAL_ACTIVE;
spin_unlock_irqrestore(&port->lock, flags);
port->flags |= ASYNC_NORMAL_ACTIVE;
func_exit (); func_exit ();
return 0; return retval;
} }
...@@ -517,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp) ...@@ -517,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
port->port.tty = tty; port->port.tty = tty;
} }
spin_lock_irqsave(&port->driver_lock, flags); spin_lock_irqsave(&port->port.lock, flags);
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&port->driver_lock, flags); spin_unlock_irqrestore(&port->port.lock, flags);
if (port->rd->hungup) if (port->rd->hungup)
port->rd->hungup (port); port->rd->hungup (port);
func_exit (); func_exit ();
...@@ -539,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) ...@@ -539,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
if (port->port.count) { if (port->port.count) {
gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count); gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
spin_unlock_irqrestore(&port->driver_lock, flags); spin_unlock_irqrestore(&port->port.lock, flags);
func_exit (); func_exit ();
return; return;
} }
...@@ -560,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp) ...@@ -560,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
* line status register. * line status register.
*/ */
spin_lock_irqsave(&port->driver_lock, flags);
port->rd->disable_rx_interrupts (port); port->rd->disable_rx_interrupts (port);
spin_unlock_irqrestore(&port->driver_lock, flags); spin_unlock_irqrestore(&port->driver_lock, flags);
spin_unlock_irqrestore(&port->port.lock, flags);
/* close has no way of returning "EINTR", so discard return value */ /* close has no way of returning "EINTR", so discard return value */
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
...@@ -574,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp) ...@@ -574,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp)
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
tty->closing = 0; tty->closing = 0;
spin_lock_irqsave(&port->driver_lock, flags);
port->event = 0; port->event = 0;
port->rd->close (port); port->rd->close (port);
port->rd->shutdown_port (port); port->rd->shutdown_port (port);
spin_unlock_irqrestore(&port->driver_lock, flags);
spin_lock_irqsave(&port->port.lock, flags);
port->port.tty = NULL; port->port.tty = NULL;
if (port->port.blocked_open) { if (port->port.blocked_open) {
if (port->close_delay) { if (port->close_delay) {
spin_unlock_irqrestore(&port->driver_lock, flags); spin_unlock_irqrestore(&port->port.lock, flags);
msleep_interruptible(jiffies_to_msecs(port->close_delay)); msleep_interruptible(jiffies_to_msecs(port->close_delay));
spin_lock_irqsave(&port->driver_lock, flags); spin_lock_irqsave(&port->port.lock, flags);
} }
wake_up_interruptible(&port->port.open_wait); wake_up_interruptible(&port->port.open_wait);
} }
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED); port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
spin_unlock_irqrestore(&port->port.lock, flags);
wake_up_interruptible(&port->port.close_wait); wake_up_interruptible(&port->port.close_wait);
func_exit (); func_exit ();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment