diff options
Diffstat (limited to 'drivers/tty/hvc')
-rw-r--r-- | drivers/tty/hvc/hvc_console.c | 31 | ||||
-rw-r--r-- | drivers/tty/hvc/hvcs.c | 82 | ||||
-rw-r--r-- | drivers/tty/hvc/hvsi.c | 2 | ||||
-rw-r--r-- | drivers/tty/hvc/hvsi_lib.c | 2 |
4 files changed, 77 insertions, 40 deletions
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 2d691eb..7f80f15 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -299,20 +299,33 @@ static void hvc_unthrottle(struct tty_struct *tty) hvc_kick(); } +static int hvc_install(struct tty_driver *driver, struct tty_struct *tty) +{ + struct hvc_struct *hp; + int rc; + + /* Auto increments kref reference if found. */ + if (!(hp = hvc_get_by_index(tty->index))) + return -ENODEV; + + tty->driver_data = hp; + + rc = tty_port_install(&hp->port, driver, tty); + if (rc) + tty_port_put(&hp->port); + return rc; +} + /* * The TTY interface won't be used until after the vio layer has exposed the vty * adapter to the kernel. */ static int hvc_open(struct tty_struct *tty, struct file * filp) { - struct hvc_struct *hp; + struct hvc_struct *hp = tty->driver_data; unsigned long flags; int rc = 0; - /* Auto increments kref reference if found. */ - if (!(hp = hvc_get_by_index(tty->index))) - return -ENODEV; - spin_lock_irqsave(&hp->port.lock, flags); /* Check and then increment for fast path open. */ if (hp->port.count++ > 0) { @@ -322,7 +335,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) } /* else count == 0 */ spin_unlock_irqrestore(&hp->port.lock, flags); - tty->driver_data = hp; tty_port_tty_set(&hp->port, tty); if (hp->ops->notifier_add) @@ -389,6 +401,11 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) hp->vtermno, hp->port.count); spin_unlock_irqrestore(&hp->port.lock, flags); } +} + +static void hvc_cleanup(struct tty_struct *tty) +{ + struct hvc_struct *hp = tty->driver_data; tty_port_put(&hp->port); } @@ -792,8 +809,10 @@ static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch) #endif static const struct tty_operations hvc_ops = { + .install = hvc_install, .open = hvc_open, .close = hvc_close, + .cleanup = hvc_cleanup, .write = hvc_write, .hangup = hvc_hangup, .unthrottle = hvc_unthrottle, diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index d56788c..cab5c7a 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1102,27 +1102,20 @@ static struct hvcs_struct *hvcs_get_by_index(int index) return NULL; } -/* - * This is invoked via the tty_open interface when a user app connects to the - * /dev node. - */ -static int hvcs_open(struct tty_struct *tty, struct file *filp) +static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty) { struct hvcs_struct *hvcsd; - int rc, retval = 0; - unsigned long flags; - unsigned int irq; struct vio_dev *vdev; - unsigned long unit_address; - - if (tty->driver_data) - goto fast_open; + unsigned long unit_address, flags; + unsigned int irq; + int retval; /* * Is there a vty-server that shares the same index? * This function increments the kref index. */ - if (!(hvcsd = hvcs_get_by_index(tty->index))) { + hvcsd = hvcs_get_by_index(tty->index); + if (!hvcsd) { printk(KERN_WARNING "HVCS: open failed, no device associated" " with tty->index %d.\n", tty->index); return -ENODEV; @@ -1130,11 +1123,16 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) spin_lock_irqsave(&hvcsd->lock, flags); - if (hvcsd->connected == 0) - if ((retval = hvcs_partner_connect(hvcsd))) - goto error_release; + if (hvcsd->connected == 0) { + retval = hvcs_partner_connect(hvcsd); + if (retval) { + spin_unlock_irqrestore(&hvcsd->lock, flags); + printk(KERN_WARNING "HVCS: partner connect failed.\n"); + goto err_put; + } + } - hvcsd->port.count = 1; + hvcsd->port.count = 0; hvcsd->port.tty = tty; tty->driver_data = hvcsd; @@ -1155,37 +1153,48 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) * This must be done outside of the spinlock because it requests irqs * and will grab the spinlock and free the connection if it fails. */ - if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { - tty_port_put(&hvcsd->port); + retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev); + if (retval) { printk(KERN_WARNING "HVCS: enable device failed.\n"); - return rc; + goto err_put; } - goto open_success; + retval = tty_port_install(&hvcsd->port, driver, tty); + if (retval) + goto err_irq; -fast_open: - hvcsd = tty->driver_data; + return 0; +err_irq: + spin_lock_irqsave(&hvcsd->lock, flags); + vio_disable_interrupts(hvcsd->vdev); + spin_unlock_irqrestore(&hvcsd->lock, flags); + free_irq(irq, hvcsd); +err_put: + tty_port_put(&hvcsd->port); + + return retval; +} + +/* + * This is invoked via the tty_open interface when a user app connects to the + * /dev node. + */ +static int hvcs_open(struct tty_struct *tty, struct file *filp) +{ + struct hvcs_struct *hvcsd = tty->driver_data; + unsigned long flags; spin_lock_irqsave(&hvcsd->lock, flags); - tty_port_get(&hvcsd->port); hvcsd->port.count++; hvcsd->todo_mask |= HVCS_SCHED_READ; spin_unlock_irqrestore(&hvcsd->lock, flags); -open_success: hvcs_kick(); printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n", hvcsd->vdev->unit_address ); return 0; - -error_release: - spin_unlock_irqrestore(&hvcsd->lock, flags); - tty_port_put(&hvcsd->port); - - printk(KERN_WARNING "HVCS: partner connect failed.\n"); - return retval; } static void hvcs_close(struct tty_struct *tty, struct file *filp) @@ -1236,7 +1245,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; free_irq(irq, hvcsd); - tty_port_put(&hvcsd->port); return; } else if (hvcsd->port.count < 0) { printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" @@ -1245,6 +1253,12 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) } spin_unlock_irqrestore(&hvcsd->lock, flags); +} + +static void hvcs_cleanup(struct tty_struct * tty) +{ + struct hvcs_struct *hvcsd = tty->driver_data; + tty_port_put(&hvcsd->port); } @@ -1431,8 +1445,10 @@ static int hvcs_chars_in_buffer(struct tty_struct *tty) } static const struct tty_operations hvcs_ops = { + .install = hvcs_install, .open = hvcs_open, .close = hvcs_close, + .cleanup = hvcs_cleanup, .hangup = hvcs_hangup, .write = hvcs_write, .write_room = hvcs_write_room, diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 6f5bc49..0083bc1 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -1080,6 +1080,8 @@ static int __init hvsi_init(void) struct hvsi_struct *hp = &hvsi_ports[i]; int ret = 1; + tty_port_link_device(&hp->port, hvsi_driver, i); + ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp); if (ret) printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n", diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c index 59c135d..3396eb9 100644 --- a/drivers/tty/hvc/hvsi_lib.c +++ b/drivers/tty/hvc/hvsi_lib.c @@ -400,7 +400,7 @@ void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp) spin_unlock_irqrestore(&hp->lock, flags); /* Clear our own DTR */ - if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL)) + if (!pv->tty || (pv->tty->termios.c_cflag & HUPCL)) hvsilib_write_mctrl(pv, 0); /* Tear down the connection */ |