tty: tty_port: Add a kref object to the tty port
authorAlan Cox <alan@linux.intel.com>
Mon, 30 Nov 2009 13:17:14 +0000 (13:17 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 11 Dec 2009 23:18:07 +0000 (15:18 -0800)
Users of tty port need a way to refcount ports when hotplugging is
involved.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/char/tty_port.c
include/linux/tty.h

index 84006de2900f87e3fcaaf92f167165d292a0dd84..be492dd664370a787b6da7a2b294b3bf53451de6 100644 (file)
@@ -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
index e9269ca1542a52e0b9045050b3a78c752eec38e7..e6da667ba34df265535e8a1d15feef4611829bd1 100644 (file)
@@ -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);