aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/hvc/hvcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/hvc/hvcs.c')
-rw-r--r--drivers/tty/hvc/hvcs.c82
1 files changed, 49 insertions, 33 deletions
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index d56788c83974..cab5c7adf8e8 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)
1102 return NULL; 1102 return NULL;
1103} 1103}
1104 1104
1105/* 1105static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
1106 * This is invoked via the tty_open interface when a user app connects to the
1107 * /dev node.
1108 */
1109static int hvcs_open(struct tty_struct *tty, struct file *filp)
1110{ 1106{
1111 struct hvcs_struct *hvcsd; 1107 struct hvcs_struct *hvcsd;
1112 int rc, retval = 0;
1113 unsigned long flags;
1114 unsigned int irq;
1115 struct vio_dev *vdev; 1108 struct vio_dev *vdev;
1116 unsigned long unit_address; 1109 unsigned long unit_address, flags;
1117 1110 unsigned int irq;
1118 if (tty->driver_data) 1111 int retval;
1119 goto fast_open;
1120 1112
1121 /* 1113 /*
1122 * Is there a vty-server that shares the same index? 1114 * Is there a vty-server that shares the same index?
1123 * This function increments the kref index. 1115 * This function increments the kref index.
1124 */ 1116 */
1125 if (!(hvcsd = hvcs_get_by_index(tty->index))) { 1117 hvcsd = hvcs_get_by_index(tty->index);
1118 if (!hvcsd) {
1126 printk(KERN_WARNING "HVCS: open failed, no device associated" 1119 printk(KERN_WARNING "HVCS: open failed, no device associated"
1127 " with tty->index %d.\n", tty->index); 1120 " with tty->index %d.\n", tty->index);
1128 return -ENODEV; 1121 return -ENODEV;
@@ -1130,11 +1123,16 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
1130 1123
1131 spin_lock_irqsave(&hvcsd->lock, flags); 1124 spin_lock_irqsave(&hvcsd->lock, flags);
1132 1125
1133 if (hvcsd->connected == 0) 1126 if (hvcsd->connected == 0) {
1134 if ((retval = hvcs_partner_connect(hvcsd))) 1127 retval = hvcs_partner_connect(hvcsd);
1135 goto error_release; 1128 if (retval) {
1129 spin_unlock_irqrestore(&hvcsd->lock, flags);
1130 printk(KERN_WARNING "HVCS: partner connect failed.\n");
1131 goto err_put;
1132 }
1133 }
1136 1134
1137 hvcsd->port.count = 1; 1135 hvcsd->port.count = 0;
1138 hvcsd->port.tty = tty; 1136 hvcsd->port.tty = tty;
1139 tty->driver_data = hvcsd; 1137 tty->driver_data = hvcsd;
1140 1138
@@ -1155,37 +1153,48 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
1155 * This must be done outside of the spinlock because it requests irqs 1153 * This must be done outside of the spinlock because it requests irqs
1156 * and will grab the spinlock and free the connection if it fails. 1154 * and will grab the spinlock and free the connection if it fails.
1157 */ 1155 */
1158 if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { 1156 retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);
1159 tty_port_put(&hvcsd->port); 1157 if (retval) {
1160 printk(KERN_WARNING "HVCS: enable device failed.\n"); 1158 printk(KERN_WARNING "HVCS: enable device failed.\n");
1161 return rc; 1159 goto err_put;
1162 } 1160 }
1163 1161
1164 goto open_success; 1162 retval = tty_port_install(&hvcsd->port, driver, tty);
1163 if (retval)
1164 goto err_irq;
1165 1165
1166fast_open: 1166 return 0;
1167 hvcsd = tty->driver_data; 1167err_irq:
1168 spin_lock_irqsave(&hvcsd->lock, flags);
1169 vio_disable_interrupts(hvcsd->vdev);
1170 spin_unlock_irqrestore(&hvcsd->lock, flags);
1171 free_irq(irq, hvcsd);
1172err_put:
1173 tty_port_put(&hvcsd->port);
1174
1175 return retval;
1176}
1177
1178/*
1179 * This is invoked via the tty_open interface when a user app connects to the
1180 * /dev node.
1181 */
1182static int hvcs_open(struct tty_struct *tty, struct file *filp)
1183{
1184 struct hvcs_struct *hvcsd = tty->driver_data;
1185 unsigned long flags;
1168 1186
1169 spin_lock_irqsave(&hvcsd->lock, flags); 1187 spin_lock_irqsave(&hvcsd->lock, flags);
1170 tty_port_get(&hvcsd->port);
1171 hvcsd->port.count++; 1188 hvcsd->port.count++;
1172 hvcsd->todo_mask |= HVCS_SCHED_READ; 1189 hvcsd->todo_mask |= HVCS_SCHED_READ;
1173 spin_unlock_irqrestore(&hvcsd->lock, flags); 1190 spin_unlock_irqrestore(&hvcsd->lock, flags);
1174 1191
1175open_success:
1176 hvcs_kick(); 1192 hvcs_kick();
1177 1193
1178 printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n", 1194 printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
1179 hvcsd->vdev->unit_address ); 1195 hvcsd->vdev->unit_address );
1180 1196
1181 return 0; 1197 return 0;
1182
1183error_release:
1184 spin_unlock_irqrestore(&hvcsd->lock, flags);
1185 tty_port_put(&hvcsd->port);
1186
1187 printk(KERN_WARNING "HVCS: partner connect failed.\n");
1188 return retval;
1189} 1198}
1190 1199
1191static void hvcs_close(struct tty_struct *tty, struct file *filp) 1200static 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)
1236 tty->driver_data = NULL; 1245 tty->driver_data = NULL;
1237 1246
1238 free_irq(irq, hvcsd); 1247 free_irq(irq, hvcsd);
1239 tty_port_put(&hvcsd->port);
1240 return; 1248 return;
1241 } else if (hvcsd->port.count < 0) { 1249 } else if (hvcsd->port.count < 0) {
1242 printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" 1250 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)
1245 } 1253 }
1246 1254
1247 spin_unlock_irqrestore(&hvcsd->lock, flags); 1255 spin_unlock_irqrestore(&hvcsd->lock, flags);
1256}
1257
1258static void hvcs_cleanup(struct tty_struct * tty)
1259{
1260 struct hvcs_struct *hvcsd = tty->driver_data;
1261
1248 tty_port_put(&hvcsd->port); 1262 tty_port_put(&hvcsd->port);
1249} 1263}
1250 1264
@@ -1431,8 +1445,10 @@ static int hvcs_chars_in_buffer(struct tty_struct *tty)
1431} 1445}
1432 1446
1433static const struct tty_operations hvcs_ops = { 1447static const struct tty_operations hvcs_ops = {
1448 .install = hvcs_install,
1434 .open = hvcs_open, 1449 .open = hvcs_open,
1435 .close = hvcs_close, 1450 .close = hvcs_close,
1451 .cleanup = hvcs_cleanup,
1436 .hangup = hvcs_hangup, 1452 .hangup = hvcs_hangup,
1437 .write = hvcs_write, 1453 .write = hvcs_write,
1438 .write_room = hvcs_write_room, 1454 .write_room = hvcs_write_room,