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.c74
1 files changed, 35 insertions, 39 deletions
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 3436436fe2d7..d56788c83974 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -261,6 +261,7 @@ static DEFINE_SPINLOCK(hvcs_pi_lock);
261 261
262/* One vty-server per hvcs_struct */ 262/* One vty-server per hvcs_struct */
263struct hvcs_struct { 263struct hvcs_struct {
264 struct tty_port port;
264 spinlock_t lock; 265 spinlock_t lock;
265 266
266 /* 267 /*
@@ -269,9 +270,6 @@ struct hvcs_struct {
269 */ 270 */
270 unsigned int index; 271 unsigned int index;
271 272
272 struct tty_struct *tty;
273 int open_count;
274
275 /* 273 /*
276 * Used to tell the driver kernel_thread what operations need to take 274 * Used to tell the driver kernel_thread what operations need to take
277 * place upon this hvcs_struct instance. 275 * place upon this hvcs_struct instance.
@@ -290,12 +288,11 @@ struct hvcs_struct {
290 int chars_in_buffer; 288 int chars_in_buffer;
291 289
292 /* 290 /*
293 * Any variable below the kref is valid before a tty is connected and 291 * Any variable below is valid before a tty is connected and
294 * stays valid after the tty is disconnected. These shouldn't be 292 * stays valid after the tty is disconnected. These shouldn't be
295 * whacked until the kobject refcount reaches zero though some entries 293 * whacked until the kobject refcount reaches zero though some entries
296 * may be changed via sysfs initiatives. 294 * may be changed via sysfs initiatives.
297 */ 295 */
298 struct kref kref; /* ref count & hvcs_struct lifetime */
299 int connected; /* is the vty-server currently connected to a vty? */ 296 int connected; /* is the vty-server currently connected to a vty? */
300 uint32_t p_unit_address; /* partner unit address */ 297 uint32_t p_unit_address; /* partner unit address */
301 uint32_t p_partition_ID; /* partner partition ID */ 298 uint32_t p_partition_ID; /* partner partition ID */
@@ -304,9 +301,6 @@ struct hvcs_struct {
304 struct vio_dev *vdev; 301 struct vio_dev *vdev;
305}; 302};
306 303
307/* Required to back map a kref to its containing object */
308#define from_kref(k) container_of(k, struct hvcs_struct, kref)
309
310static LIST_HEAD(hvcs_structs); 304static LIST_HEAD(hvcs_structs);
311static DEFINE_SPINLOCK(hvcs_structs_lock); 305static DEFINE_SPINLOCK(hvcs_structs_lock);
312static DEFINE_MUTEX(hvcs_init_mutex); 306static DEFINE_MUTEX(hvcs_init_mutex);
@@ -422,7 +416,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribut
422 416
423 spin_lock_irqsave(&hvcsd->lock, flags); 417 spin_lock_irqsave(&hvcsd->lock, flags);
424 418
425 if (hvcsd->open_count > 0) { 419 if (hvcsd->port.count > 0) {
426 spin_unlock_irqrestore(&hvcsd->lock, flags); 420 spin_unlock_irqrestore(&hvcsd->lock, flags);
427 printk(KERN_INFO "HVCS: vterm state unchanged. " 421 printk(KERN_INFO "HVCS: vterm state unchanged. "
428 "The hvcs device node is still in use.\n"); 422 "The hvcs device node is still in use.\n");
@@ -564,7 +558,7 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
564static void hvcs_try_write(struct hvcs_struct *hvcsd) 558static void hvcs_try_write(struct hvcs_struct *hvcsd)
565{ 559{
566 uint32_t unit_address = hvcsd->vdev->unit_address; 560 uint32_t unit_address = hvcsd->vdev->unit_address;
567 struct tty_struct *tty = hvcsd->tty; 561 struct tty_struct *tty = hvcsd->port.tty;
568 int sent; 562 int sent;
569 563
570 if (hvcsd->todo_mask & HVCS_TRY_WRITE) { 564 if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
@@ -602,7 +596,7 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
602 spin_lock_irqsave(&hvcsd->lock, flags); 596 spin_lock_irqsave(&hvcsd->lock, flags);
603 597
604 unit_address = hvcsd->vdev->unit_address; 598 unit_address = hvcsd->vdev->unit_address;
605 tty = hvcsd->tty; 599 tty = hvcsd->port.tty;
606 600
607 hvcs_try_write(hvcsd); 601 hvcs_try_write(hvcsd);
608 602
@@ -701,10 +695,9 @@ static void hvcs_return_index(int index)
701 hvcs_index_list[index] = -1; 695 hvcs_index_list[index] = -1;
702} 696}
703 697
704/* callback when the kref ref count reaches zero */ 698static void hvcs_destruct_port(struct tty_port *p)
705static void destroy_hvcs_struct(struct kref *kref)
706{ 699{
707 struct hvcs_struct *hvcsd = from_kref(kref); 700 struct hvcs_struct *hvcsd = container_of(p, struct hvcs_struct, port);
708 struct vio_dev *vdev; 701 struct vio_dev *vdev;
709 unsigned long flags; 702 unsigned long flags;
710 703
@@ -741,6 +734,10 @@ static void destroy_hvcs_struct(struct kref *kref)
741 kfree(hvcsd); 734 kfree(hvcsd);
742} 735}
743 736
737static const struct tty_port_operations hvcs_port_ops = {
738 .destruct = hvcs_destruct_port,
739};
740
744static int hvcs_get_index(void) 741static int hvcs_get_index(void)
745{ 742{
746 int i; 743 int i;
@@ -789,10 +786,9 @@ static int __devinit hvcs_probe(
789 if (!hvcsd) 786 if (!hvcsd)
790 return -ENODEV; 787 return -ENODEV;
791 788
792 789 tty_port_init(&hvcsd->port);
790 hvcsd->port.ops = &hvcs_port_ops;
793 spin_lock_init(&hvcsd->lock); 791 spin_lock_init(&hvcsd->lock);
794 /* Automatically incs the refcount the first time */
795 kref_init(&hvcsd->kref);
796 792
797 hvcsd->vdev = dev; 793 hvcsd->vdev = dev;
798 dev_set_drvdata(&dev->dev, hvcsd); 794 dev_set_drvdata(&dev->dev, hvcsd);
@@ -852,7 +848,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
852 848
853 spin_lock_irqsave(&hvcsd->lock, flags); 849 spin_lock_irqsave(&hvcsd->lock, flags);
854 850
855 tty = hvcsd->tty; 851 tty = hvcsd->port.tty;
856 852
857 spin_unlock_irqrestore(&hvcsd->lock, flags); 853 spin_unlock_irqrestore(&hvcsd->lock, flags);
858 854
@@ -860,7 +856,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
860 * Let the last holder of this object cause it to be removed, which 856 * Let the last holder of this object cause it to be removed, which
861 * would probably be tty_hangup below. 857 * would probably be tty_hangup below.
862 */ 858 */
863 kref_put(&hvcsd->kref, destroy_hvcs_struct); 859 tty_port_put(&hvcsd->port);
864 860
865 /* 861 /*
866 * The hangup is a scheduled function which will auto chain call 862 * The hangup is a scheduled function which will auto chain call
@@ -1094,7 +1090,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
1094 list_for_each_entry(hvcsd, &hvcs_structs, next) { 1090 list_for_each_entry(hvcsd, &hvcs_structs, next) {
1095 spin_lock_irqsave(&hvcsd->lock, flags); 1091 spin_lock_irqsave(&hvcsd->lock, flags);
1096 if (hvcsd->index == index) { 1092 if (hvcsd->index == index) {
1097 kref_get(&hvcsd->kref); 1093 tty_port_get(&hvcsd->port);
1098 spin_unlock_irqrestore(&hvcsd->lock, flags); 1094 spin_unlock_irqrestore(&hvcsd->lock, flags);
1099 spin_unlock(&hvcs_structs_lock); 1095 spin_unlock(&hvcs_structs_lock);
1100 return hvcsd; 1096 return hvcsd;
@@ -1138,8 +1134,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
1138 if ((retval = hvcs_partner_connect(hvcsd))) 1134 if ((retval = hvcs_partner_connect(hvcsd)))
1139 goto error_release; 1135 goto error_release;
1140 1136
1141 hvcsd->open_count = 1; 1137 hvcsd->port.count = 1;
1142 hvcsd->tty = tty; 1138 hvcsd->port.tty = tty;
1143 tty->driver_data = hvcsd; 1139 tty->driver_data = hvcsd;
1144 1140
1145 memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); 1141 memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
@@ -1160,7 +1156,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
1160 * and will grab the spinlock and free the connection if it fails. 1156 * and will grab the spinlock and free the connection if it fails.
1161 */ 1157 */
1162 if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { 1158 if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
1163 kref_put(&hvcsd->kref, destroy_hvcs_struct); 1159 tty_port_put(&hvcsd->port);
1164 printk(KERN_WARNING "HVCS: enable device failed.\n"); 1160 printk(KERN_WARNING "HVCS: enable device failed.\n");
1165 return rc; 1161 return rc;
1166 } 1162 }
@@ -1171,8 +1167,8 @@ fast_open:
1171 hvcsd = tty->driver_data; 1167 hvcsd = tty->driver_data;
1172 1168
1173 spin_lock_irqsave(&hvcsd->lock, flags); 1169 spin_lock_irqsave(&hvcsd->lock, flags);
1174 kref_get(&hvcsd->kref); 1170 tty_port_get(&hvcsd->port);
1175 hvcsd->open_count++; 1171 hvcsd->port.count++;
1176 hvcsd->todo_mask |= HVCS_SCHED_READ; 1172 hvcsd->todo_mask |= HVCS_SCHED_READ;
1177 spin_unlock_irqrestore(&hvcsd->lock, flags); 1173 spin_unlock_irqrestore(&hvcsd->lock, flags);
1178 1174
@@ -1186,7 +1182,7 @@ open_success:
1186 1182
1187error_release: 1183error_release:
1188 spin_unlock_irqrestore(&hvcsd->lock, flags); 1184 spin_unlock_irqrestore(&hvcsd->lock, flags);
1189 kref_put(&hvcsd->kref, destroy_hvcs_struct); 1185 tty_port_put(&hvcsd->port);
1190 1186
1191 printk(KERN_WARNING "HVCS: partner connect failed.\n"); 1187 printk(KERN_WARNING "HVCS: partner connect failed.\n");
1192 return retval; 1188 return retval;
@@ -1216,7 +1212,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
1216 hvcsd = tty->driver_data; 1212 hvcsd = tty->driver_data;
1217 1213
1218 spin_lock_irqsave(&hvcsd->lock, flags); 1214 spin_lock_irqsave(&hvcsd->lock, flags);
1219 if (--hvcsd->open_count == 0) { 1215 if (--hvcsd->port.count == 0) {
1220 1216
1221 vio_disable_interrupts(hvcsd->vdev); 1217 vio_disable_interrupts(hvcsd->vdev);
1222 1218
@@ -1225,7 +1221,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
1225 * execute any operations on the TTY even though it is obligated 1221 * execute any operations on the TTY even though it is obligated
1226 * to deliver any pending I/O to the hypervisor. 1222 * to deliver any pending I/O to the hypervisor.
1227 */ 1223 */
1228 hvcsd->tty = NULL; 1224 hvcsd->port.tty = NULL;
1229 1225
1230 irq = hvcsd->vdev->irq; 1226 irq = hvcsd->vdev->irq;
1231 spin_unlock_irqrestore(&hvcsd->lock, flags); 1227 spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -1240,16 +1236,16 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
1240 tty->driver_data = NULL; 1236 tty->driver_data = NULL;
1241 1237
1242 free_irq(irq, hvcsd); 1238 free_irq(irq, hvcsd);
1243 kref_put(&hvcsd->kref, destroy_hvcs_struct); 1239 tty_port_put(&hvcsd->port);
1244 return; 1240 return;
1245 } else if (hvcsd->open_count < 0) { 1241 } else if (hvcsd->port.count < 0) {
1246 printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" 1242 printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
1247 " is missmanaged.\n", 1243 " is missmanaged.\n",
1248 hvcsd->vdev->unit_address, hvcsd->open_count); 1244 hvcsd->vdev->unit_address, hvcsd->port.count);
1249 } 1245 }
1250 1246
1251 spin_unlock_irqrestore(&hvcsd->lock, flags); 1247 spin_unlock_irqrestore(&hvcsd->lock, flags);
1252 kref_put(&hvcsd->kref, destroy_hvcs_struct); 1248 tty_port_put(&hvcsd->port);
1253} 1249}
1254 1250
1255static void hvcs_hangup(struct tty_struct * tty) 1251static void hvcs_hangup(struct tty_struct * tty)
@@ -1261,7 +1257,7 @@ static void hvcs_hangup(struct tty_struct * tty)
1261 1257
1262 spin_lock_irqsave(&hvcsd->lock, flags); 1258 spin_lock_irqsave(&hvcsd->lock, flags);
1263 /* Preserve this so that we know how many kref refs to put */ 1259 /* Preserve this so that we know how many kref refs to put */
1264 temp_open_count = hvcsd->open_count; 1260 temp_open_count = hvcsd->port.count;
1265 1261
1266 /* 1262 /*
1267 * Don't kref put inside the spinlock because the destruction 1263 * Don't kref put inside the spinlock because the destruction
@@ -1273,10 +1269,10 @@ static void hvcs_hangup(struct tty_struct * tty)
1273 hvcsd->todo_mask = 0; 1269 hvcsd->todo_mask = 0;
1274 1270
1275 /* I don't think the tty needs the hvcs_struct pointer after a hangup */ 1271 /* I don't think the tty needs the hvcs_struct pointer after a hangup */
1276 hvcsd->tty->driver_data = NULL; 1272 tty->driver_data = NULL;
1277 hvcsd->tty = NULL; 1273 hvcsd->port.tty = NULL;
1278 1274
1279 hvcsd->open_count = 0; 1275 hvcsd->port.count = 0;
1280 1276
1281 /* This will drop any buffered data on the floor which is OK in a hangup 1277 /* This will drop any buffered data on the floor which is OK in a hangup
1282 * scenario. */ 1278 * scenario. */
@@ -1301,7 +1297,7 @@ static void hvcs_hangup(struct tty_struct * tty)
1301 * NOTE: If this hangup was signaled from user space then the 1297 * NOTE: If this hangup was signaled from user space then the
1302 * final put will never happen. 1298 * final put will never happen.
1303 */ 1299 */
1304 kref_put(&hvcsd->kref, destroy_hvcs_struct); 1300 tty_port_put(&hvcsd->port);
1305 } 1301 }
1306} 1302}
1307 1303
@@ -1347,7 +1343,7 @@ static int hvcs_write(struct tty_struct *tty,
1347 * the middle of a write operation? This is a crummy place to do this 1343 * the middle of a write operation? This is a crummy place to do this
1348 * but we want to keep it all in the spinlock. 1344 * but we want to keep it all in the spinlock.
1349 */ 1345 */
1350 if (hvcsd->open_count <= 0) { 1346 if (hvcsd->port.count <= 0) {
1351 spin_unlock_irqrestore(&hvcsd->lock, flags); 1347 spin_unlock_irqrestore(&hvcsd->lock, flags);
1352 return -ENODEV; 1348 return -ENODEV;
1353 } 1349 }
@@ -1421,7 +1417,7 @@ static int hvcs_write_room(struct tty_struct *tty)
1421{ 1417{
1422 struct hvcs_struct *hvcsd = tty->driver_data; 1418 struct hvcs_struct *hvcsd = tty->driver_data;
1423 1419
1424 if (!hvcsd || hvcsd->open_count <= 0) 1420 if (!hvcsd || hvcsd->port.count <= 0)
1425 return 0; 1421 return 0;
1426 1422
1427 return HVCS_BUFF_LEN - hvcsd->chars_in_buffer; 1423 return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;