From e4375729ff79417ccf151d161028a02348281e45 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 30 Nov 2009 13:17:14 +0000 Subject: [PATCH] --- yaml --- r: 175348 b: refs/heads/master c: 568aafc627e2978509e8a80c640ba534d1e843cc h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/char/tty_port.c | 18 ++++++++++++++++++ trunk/include/linux/tty.h | 12 ++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index bfd424bdcf62..c3168eee00fa 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 338818fd802a6baacb7e5b6910d52c8996ca6d28 +refs/heads/master: 568aafc627e2978509e8a80c640ba534d1e843cc diff --git a/trunk/drivers/char/tty_port.c b/trunk/drivers/char/tty_port.c index 84006de2900f..be492dd66437 100644 --- a/trunk/drivers/char/tty_port.c +++ b/trunk/drivers/char/tty_port.c @@ -29,6 +29,7 @@ void tty_port_init(struct tty_port *port) spin_lock_init(&port->lock); port->close_delay = (50 * HZ) / 100; port->closing_wait = (3000 * HZ) / 100; + kref_init(&port->kref); } EXPORT_SYMBOL(tty_port_init); @@ -56,6 +57,23 @@ void tty_port_free_xmit_buf(struct tty_port *port) } EXPORT_SYMBOL(tty_port_free_xmit_buf); +static void tty_port_destructor(struct kref *kref) +{ + struct tty_port *port = container_of(kref, struct tty_port, kref); + if (port->xmit_buf) + free_page((unsigned long)port->xmit_buf); + if (port->ops->destruct) + port->ops->destruct(port); + else + kfree(port); +} + +void tty_port_put(struct tty_port *port) +{ + if (port) + kref_put(&port->kref, tty_port_destructor); +} +EXPORT_SYMBOL(tty_port_put); /** * tty_port_tty_get - get a tty reference diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index e9269ca1542a..e6da667ba34d 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -199,6 +199,8 @@ struct tty_port_operations { /* FIXME: long term getting the tty argument *out* of this would be good for consoles */ int (*activate)(struct tty_port *port, struct tty_struct *tty); + /* Called on the final put of a port */ + void (*destruct)(struct tty_port *port); }; struct tty_port { @@ -219,6 +221,7 @@ struct tty_port { int drain_delay; /* Set to zero if no pure time based drain is needed else set to size of fifo */ + struct kref kref; /* Ref counter */ }; /* @@ -461,6 +464,15 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay); extern void tty_port_init(struct tty_port *port); extern int tty_port_alloc_xmit_buf(struct tty_port *port); extern void tty_port_free_xmit_buf(struct tty_port *port); +extern void tty_port_put(struct tty_port *port); + +extern inline struct tty_port *tty_port_get(struct tty_port *port) +{ + if (port) + kref_get(&port->kref); + return port; +} + extern struct tty_struct *tty_port_tty_get(struct tty_port *port); extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); extern int tty_port_carrier_raised(struct tty_port *port);