]> Pileus Git - ~andy/linux/blobdiff - drivers/tty/hvc/hvc_console.c
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / drivers / tty / hvc / hvc_console.c
index 8880adf5fc6f65ae084481dffb8c390ed40c7ad4..2d691eb7c40aa28f30602834902cc48fc1c52dad 100644 (file)
@@ -107,7 +107,7 @@ static struct hvc_struct *hvc_get_by_index(int index)
        list_for_each_entry(hp, &hvc_structs, next) {
                spin_lock_irqsave(&hp->lock, flags);
                if (hp->index == index) {
-                       kref_get(&hp->kref);
+                       tty_port_get(&hp->port);
                        spin_unlock_irqrestore(&hp->lock, flags);
                        spin_unlock(&hvc_structs_lock);
                        return hp;
@@ -229,9 +229,9 @@ static int __init hvc_console_init(void)
 console_initcall(hvc_console_init);
 
 /* callback when the kboject ref count reaches zero. */
-static void destroy_hvc_struct(struct kref *kref)
+static void hvc_port_destruct(struct tty_port *port)
 {
-       struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
+       struct hvc_struct *hp = container_of(port, struct hvc_struct, port);
        unsigned long flags;
 
        spin_lock(&hvc_structs_lock);
@@ -264,7 +264,7 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
        /* make sure no no tty has been registered in this index */
        hp = hvc_get_by_index(index);
        if (hp) {
-               kref_put(&hp->kref, destroy_hvc_struct);
+               tty_port_put(&hp->port);
                return -1;
        }
 
@@ -313,20 +313,17 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
        if (!(hp = hvc_get_by_index(tty->index)))
                return -ENODEV;
 
-       spin_lock_irqsave(&hp->lock, flags);
+       spin_lock_irqsave(&hp->port.lock, flags);
        /* Check and then increment for fast path open. */
-       if (hp->count++ > 0) {
-               tty_kref_get(tty);
-               spin_unlock_irqrestore(&hp->lock, flags);
+       if (hp->port.count++ > 0) {
+               spin_unlock_irqrestore(&hp->port.lock, flags);
                hvc_kick();
                return 0;
        } /* else count == 0 */
+       spin_unlock_irqrestore(&hp->port.lock, flags);
 
        tty->driver_data = hp;
-
-       hp->tty = tty_kref_get(tty);
-
-       spin_unlock_irqrestore(&hp->lock, flags);
+       tty_port_tty_set(&hp->port, tty);
 
        if (hp->ops->notifier_add)
                rc = hp->ops->notifier_add(hp, hp->data);
@@ -338,12 +335,9 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
         * tty fields and return the kref reference.
         */
        if (rc) {
-               spin_lock_irqsave(&hp->lock, flags);
-               hp->tty = NULL;
-               spin_unlock_irqrestore(&hp->lock, flags);
-               tty_kref_put(tty);
+               tty_port_tty_set(&hp->port, NULL);
                tty->driver_data = NULL;
-               kref_put(&hp->kref, destroy_hvc_struct);
+               tty_port_put(&hp->port);
                printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
        }
        /* Force wakeup of the polling thread */
@@ -370,12 +364,12 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 
        hp = tty->driver_data;
 
-       spin_lock_irqsave(&hp->lock, flags);
+       spin_lock_irqsave(&hp->port.lock, flags);
 
-       if (--hp->count == 0) {
+       if (--hp->port.count == 0) {
+               spin_unlock_irqrestore(&hp->port.lock, flags);
                /* We are done with the tty pointer now. */
-               hp->tty = NULL;
-               spin_unlock_irqrestore(&hp->lock, flags);
+               tty_port_tty_set(&hp->port, NULL);
 
                if (hp->ops->notifier_del)
                        hp->ops->notifier_del(hp, hp->data);
@@ -390,14 +384,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
                 */
                tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT);
        } else {
-               if (hp->count < 0)
+               if (hp->port.count < 0)
                        printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
-                               hp->vtermno, hp->count);
-               spin_unlock_irqrestore(&hp->lock, flags);
+                               hp->vtermno, hp->port.count);
+               spin_unlock_irqrestore(&hp->port.lock, flags);
        }
 
-       tty_kref_put(tty);
-       kref_put(&hp->kref, destroy_hvc_struct);
+       tty_port_put(&hp->port);
 }
 
 static void hvc_hangup(struct tty_struct *tty)
@@ -412,32 +405,31 @@ static void hvc_hangup(struct tty_struct *tty)
        /* cancel pending tty resize work */
        cancel_work_sync(&hp->tty_resize);
 
-       spin_lock_irqsave(&hp->lock, flags);
+       spin_lock_irqsave(&hp->port.lock, flags);
 
        /*
         * The N_TTY line discipline has problems such that in a close vs
         * open->hangup case this can be called after the final close so prevent
         * that from happening for now.
         */
-       if (hp->count <= 0) {
-               spin_unlock_irqrestore(&hp->lock, flags);
+       if (hp->port.count <= 0) {
+               spin_unlock_irqrestore(&hp->port.lock, flags);
                return;
        }
 
-       temp_open_count = hp->count;
-       hp->count = 0;
-       hp->n_outbuf = 0;
-       hp->tty = NULL;
+       temp_open_count = hp->port.count;
+       hp->port.count = 0;
+       spin_unlock_irqrestore(&hp->port.lock, flags);
+       tty_port_tty_set(&hp->port, NULL);
 
-       spin_unlock_irqrestore(&hp->lock, flags);
+       hp->n_outbuf = 0;
 
        if (hp->ops->notifier_hangup)
                hp->ops->notifier_hangup(hp, hp->data);
 
        while(temp_open_count) {
                --temp_open_count;
-               tty_kref_put(tty);
-               kref_put(&hp->kref, destroy_hvc_struct);
+               tty_port_put(&hp->port);
        }
 }
 
@@ -478,7 +470,8 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
        if (!hp)
                return -EPIPE;
 
-       if (hp->count <= 0)
+       /* FIXME what's this (unprotected) check for? */
+       if (hp->port.count <= 0)
                return -EIO;
 
        spin_lock_irqsave(&hp->lock, flags);
@@ -526,13 +519,12 @@ static void hvc_set_winsz(struct work_struct *work)
 
        hp = container_of(work, struct hvc_struct, tty_resize);
 
-       spin_lock_irqsave(&hp->lock, hvc_flags);
-       if (!hp->tty) {
-               spin_unlock_irqrestore(&hp->lock, hvc_flags);
+       tty = tty_port_tty_get(&hp->port);
+       if (!tty)
                return;
-       }
-       ws  = hp->ws;
-       tty = tty_kref_get(hp->tty);
+
+       spin_lock_irqsave(&hp->lock, hvc_flags);
+       ws = hp->ws;
        spin_unlock_irqrestore(&hp->lock, hvc_flags);
 
        tty_do_resize(tty, &ws);
@@ -601,7 +593,7 @@ int hvc_poll(struct hvc_struct *hp)
        }
 
        /* No tty attached, just skip */
-       tty = tty_kref_get(hp->tty);
+       tty = tty_port_tty_get(&hp->port);
        if (tty == NULL)
                goto bail;
 
@@ -681,8 +673,7 @@ int hvc_poll(struct hvc_struct *hp)
 
                tty_flip_buffer_push(tty);
        }
-       if (tty)
-               tty_kref_put(tty);
+       tty_kref_put(tty);
 
        return poll_mask;
 }
@@ -817,6 +808,10 @@ static const struct tty_operations hvc_ops = {
 #endif
 };
 
+static const struct tty_port_operations hvc_port_ops = {
+       .destruct = hvc_port_destruct,
+};
+
 struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
                             const struct hv_ops *ops,
                             int outbuf_size)
@@ -842,7 +837,8 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
        hp->outbuf_size = outbuf_size;
        hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
 
-       kref_init(&hp->kref);
+       tty_port_init(&hp->port);
+       hp->port.ops = &hvc_port_ops;
 
        INIT_WORK(&hp->tty_resize, hvc_set_winsz);
        spin_lock_init(&hp->lock);
@@ -875,9 +871,9 @@ int hvc_remove(struct hvc_struct *hp)
        unsigned long flags;
        struct tty_struct *tty;
 
-       spin_lock_irqsave(&hp->lock, flags);
-       tty = tty_kref_get(hp->tty);
+       tty = tty_port_tty_get(&hp->port);
 
+       spin_lock_irqsave(&hp->lock, flags);
        if (hp->index < MAX_NR_HVC_CONSOLES)
                vtermnos[hp->index] = -1;
 
@@ -891,7 +887,7 @@ int hvc_remove(struct hvc_struct *hp)
         * kref cause it to be removed, which will probably be the tty_vhangup
         * below.
         */
-       kref_put(&hp->kref, destroy_hvc_struct);
+       tty_port_put(&hp->port);
 
        /*
         * This function call will auto chain call hvc_hangup.