tty: Add a full port_close function
Now we are extracting out methods for shutdown and the like we can add a proper tty_port_close method that knows all the innards of the tty closing process and hides the lot from the caller. At some point in the future this will be paired with a similar open() helper and the drivers can stick to hardware management. Signed-off-by: Alan Cox <alan@linux.intel.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
24d481ecae
commit
7ca0ff9ab3
|
@ -96,6 +96,14 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_tty_set);
|
EXPORT_SYMBOL(tty_port_tty_set);
|
||||||
|
|
||||||
|
static void tty_port_shutdown(struct tty_port *port)
|
||||||
|
{
|
||||||
|
if (port->ops->shutdown &&
|
||||||
|
test_and_clear_bit(ASYNC_INITIALIZED, &port->flags))
|
||||||
|
port->ops->shutdown(port);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tty_port_hangup - hangup helper
|
* tty_port_hangup - hangup helper
|
||||||
* @port: tty port
|
* @port: tty port
|
||||||
|
@ -116,6 +124,7 @@ void tty_port_hangup(struct tty_port *port)
|
||||||
port->tty = NULL;
|
port->tty = NULL;
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
wake_up_interruptible(&port->open_wait);
|
wake_up_interruptible(&port->open_wait);
|
||||||
|
tty_port_shutdown(port);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_hangup);
|
EXPORT_SYMBOL(tty_port_hangup);
|
||||||
|
|
||||||
|
@ -296,15 +305,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
|
||||||
|
|
||||||
if (port->count) {
|
if (port->count) {
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
if (port->ops->drop)
|
||||||
|
port->ops->drop(port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
port->flags |= ASYNC_CLOSING;
|
set_bit(ASYNC_CLOSING, &port->flags);
|
||||||
tty->closing = 1;
|
tty->closing = 1;
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
/* Don't block on a stalled port, just pull the chain */
|
/* Don't block on a stalled port, just pull the chain */
|
||||||
if (tty->flow_stopped)
|
if (tty->flow_stopped)
|
||||||
tty_driver_flush_buffer(tty);
|
tty_driver_flush_buffer(tty);
|
||||||
if (port->flags & ASYNC_INITIALIZED &&
|
if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
|
||||||
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
|
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
|
||||||
tty_wait_until_sent(tty, port->closing_wait);
|
tty_wait_until_sent(tty, port->closing_wait);
|
||||||
if (port->drain_delay) {
|
if (port->drain_delay) {
|
||||||
|
@ -318,6 +329,9 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
|
||||||
timeout = 2 * HZ;
|
timeout = 2 * HZ;
|
||||||
schedule_timeout_interruptible(timeout);
|
schedule_timeout_interruptible(timeout);
|
||||||
}
|
}
|
||||||
|
/* Don't call port->drop for the last reference. Callers will want
|
||||||
|
to drop the last active reference in ->shutdown() or the tty
|
||||||
|
shutdown path */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_close_start);
|
EXPORT_SYMBOL(tty_port_close_start);
|
||||||
|
@ -348,3 +362,14 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_close_end);
|
EXPORT_SYMBOL(tty_port_close_end);
|
||||||
|
|
||||||
|
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
|
||||||
|
struct file *filp)
|
||||||
|
{
|
||||||
|
if (tty_port_close_start(port, tty, filp) == 0)
|
||||||
|
return;
|
||||||
|
tty_port_shutdown(port);
|
||||||
|
tty_port_close_end(port, tty);
|
||||||
|
tty_port_tty_set(port, NULL);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tty_port_close);
|
||||||
|
|
|
@ -187,7 +187,12 @@ struct tty_port;
|
||||||
struct tty_port_operations {
|
struct tty_port_operations {
|
||||||
/* Return 1 if the carrier is raised */
|
/* Return 1 if the carrier is raised */
|
||||||
int (*carrier_raised)(struct tty_port *port);
|
int (*carrier_raised)(struct tty_port *port);
|
||||||
|
/* Control the DTR line */
|
||||||
void (*dtr_rts)(struct tty_port *port, int raise);
|
void (*dtr_rts)(struct tty_port *port, int raise);
|
||||||
|
/* Called when the last close completes or a hangup finishes
|
||||||
|
IFF the port was initialized. Do not use to free resources */
|
||||||
|
void (*shutdown)(struct tty_port *port);
|
||||||
|
void (*drop)(struct tty_port *port);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tty_port {
|
struct tty_port {
|
||||||
|
@ -459,7 +464,8 @@ extern int tty_port_block_til_ready(struct tty_port *port,
|
||||||
extern int tty_port_close_start(struct tty_port *port,
|
extern int tty_port_close_start(struct tty_port *port,
|
||||||
struct tty_struct *tty, struct file *filp);
|
struct tty_struct *tty, struct file *filp);
|
||||||
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
|
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
|
||||||
|
extern void tty_port_close(struct tty_port *port,
|
||||||
|
struct tty_struct *tty, struct file *filp);
|
||||||
extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
|
extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
|
||||||
extern int tty_unregister_ldisc(int disc);
|
extern int tty_unregister_ldisc(int disc);
|
||||||
extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
|
extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
|
||||||
|
|
Loading…
Reference in New Issue