0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 #include <linux/device.h>
0054 #include <linux/init.h>
0055 #include <linux/interrupt.h>
0056 #include <linux/kernel.h>
0057 #include <linux/kref.h>
0058 #include <linux/kthread.h>
0059 #include <linux/list.h>
0060 #include <linux/major.h>
0061 #include <linux/module.h>
0062 #include <linux/moduleparam.h>
0063 #include <linux/sched.h>
0064 #include <linux/slab.h>
0065 #include <linux/spinlock.h>
0066 #include <linux/stat.h>
0067 #include <linux/tty.h>
0068 #include <linux/tty_flip.h>
0069 #include <asm/hvconsole.h>
0070 #include <asm/hvcserver.h>
0071 #include <linux/uaccess.h>
0072 #include <asm/vio.h>
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 #define HVCS_DRIVER_VERSION "1.3.3"
0116
0117 MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
0118 MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
0119 MODULE_LICENSE("GPL");
0120 MODULE_VERSION(HVCS_DRIVER_VERSION);
0121
0122
0123
0124
0125
0126 #define HVCS_CLOSE_WAIT (HZ/100)
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 #define HVCS_DEFAULT_SERVER_ADAPTERS 64
0137
0138
0139
0140
0141
0142
0143 #define HVCS_MAX_SERVER_ADAPTERS 1024
0144
0145
0146
0147
0148
0149
0150
0151 #define HVCS_MINOR_START 0
0152
0153
0154
0155
0156
0157
0158
0159
0160 #define __ALIGNED__ __attribute__((__aligned__(8)))
0161
0162
0163
0164
0165
0166 #define HVCS_BUFF_LEN 16
0167
0168
0169
0170
0171
0172 #define HVCS_MAX_FROM_USER 4096
0173
0174
0175
0176
0177
0178
0179 static const struct ktermios hvcs_tty_termios = {
0180 .c_iflag = IGNBRK | IGNPAR,
0181 .c_oflag = OPOST,
0182 .c_cflag = B38400 | CS8 | CREAD | HUPCL,
0183 .c_cc = INIT_C_CC,
0184 .c_ispeed = 38400,
0185 .c_ospeed = 38400
0186 };
0187
0188
0189
0190
0191
0192
0193
0194 static int hvcs_parm_num_devs = -1;
0195 module_param(hvcs_parm_num_devs, int, 0);
0196
0197 static const char hvcs_driver_name[] = "hvcs";
0198 static const char hvcs_device_node[] = "hvcs";
0199
0200
0201 static int hvcs_rescan_status;
0202
0203 static struct tty_driver *hvcs_tty_driver;
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 static int *hvcs_index_list;
0219
0220
0221
0222
0223
0224 static int hvcs_index_count;
0225
0226
0227
0228
0229
0230 static int hvcs_kicked;
0231
0232
0233
0234
0235
0236 static struct task_struct *hvcs_task;
0237
0238
0239
0240
0241
0242 static unsigned long *hvcs_pi_buff;
0243
0244
0245 static DEFINE_SPINLOCK(hvcs_pi_lock);
0246
0247
0248 struct hvcs_struct {
0249 struct tty_port port;
0250 spinlock_t lock;
0251
0252
0253
0254
0255
0256 unsigned int index;
0257
0258
0259
0260
0261
0262 int todo_mask;
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 char buffer[HVCS_BUFF_LEN];
0273 int chars_in_buffer;
0274
0275
0276
0277
0278
0279
0280
0281 int connected;
0282 uint32_t p_unit_address;
0283 uint32_t p_partition_ID;
0284 char p_location_code[HVCS_CLC_LENGTH + 1];
0285 struct list_head next;
0286 struct vio_dev *vdev;
0287 };
0288
0289 static LIST_HEAD(hvcs_structs);
0290 static DEFINE_SPINLOCK(hvcs_structs_lock);
0291 static DEFINE_MUTEX(hvcs_init_mutex);
0292
0293 static int hvcs_get_pi(struct hvcs_struct *hvcsd);
0294 static int hvcs_rescan_devices_list(void);
0295
0296 static void hvcs_partner_free(struct hvcs_struct *hvcsd);
0297
0298 static int hvcs_initialize(void);
0299
0300 #define HVCS_SCHED_READ 0x00000001
0301 #define HVCS_QUICK_READ 0x00000002
0302 #define HVCS_TRY_WRITE 0x00000004
0303 #define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ)
0304
0305 static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
0306 {
0307 return dev_get_drvdata(&viod->dev);
0308 }
0309
0310
0311 static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
0312 {
0313 struct vio_dev *viod = to_vio_dev(dev);
0314 struct hvcs_struct *hvcsd = from_vio_dev(viod);
0315 unsigned long flags;
0316 int retval;
0317
0318 spin_lock_irqsave(&hvcsd->lock, flags);
0319 retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
0320 spin_unlock_irqrestore(&hvcsd->lock, flags);
0321 return retval;
0322 }
0323 static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
0324
0325 static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
0326 {
0327 struct vio_dev *viod = to_vio_dev(dev);
0328 struct hvcs_struct *hvcsd = from_vio_dev(viod);
0329 unsigned long flags;
0330 int retval;
0331
0332 spin_lock_irqsave(&hvcsd->lock, flags);
0333 retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
0334 spin_unlock_irqrestore(&hvcsd->lock, flags);
0335 return retval;
0336 }
0337 static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
0338
0339 static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
0340 size_t count)
0341 {
0342
0343
0344
0345
0346 printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
0347 return -EPERM;
0348 }
0349
0350 static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
0351 {
0352 struct vio_dev *viod = to_vio_dev(dev);
0353 struct hvcs_struct *hvcsd = from_vio_dev(viod);
0354 unsigned long flags;
0355 int retval;
0356
0357 spin_lock_irqsave(&hvcsd->lock, flags);
0358 retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
0359 spin_unlock_irqrestore(&hvcsd->lock, flags);
0360 return retval;
0361 }
0362
0363 static DEVICE_ATTR(current_vty,
0364 S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
0365
0366 static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
0367 size_t count)
0368 {
0369 struct vio_dev *viod = to_vio_dev(dev);
0370 struct hvcs_struct *hvcsd = from_vio_dev(viod);
0371 unsigned long flags;
0372
0373
0374 if (simple_strtol(buf, NULL, 0) != 0)
0375 return -EINVAL;
0376
0377 spin_lock_irqsave(&hvcsd->lock, flags);
0378
0379 if (hvcsd->port.count > 0) {
0380 spin_unlock_irqrestore(&hvcsd->lock, flags);
0381 printk(KERN_INFO "HVCS: vterm state unchanged. "
0382 "The hvcs device node is still in use.\n");
0383 return -EPERM;
0384 }
0385
0386 if (hvcsd->connected == 0) {
0387 spin_unlock_irqrestore(&hvcsd->lock, flags);
0388 printk(KERN_INFO "HVCS: vterm state unchanged. The"
0389 " vty-server is not connected to a vty.\n");
0390 return -EPERM;
0391 }
0392
0393 hvcs_partner_free(hvcsd);
0394 printk(KERN_INFO "HVCS: Closed vty-server@%X and"
0395 " partner vty@%X:%d connection.\n",
0396 hvcsd->vdev->unit_address,
0397 hvcsd->p_unit_address,
0398 (uint32_t)hvcsd->p_partition_ID);
0399
0400 spin_unlock_irqrestore(&hvcsd->lock, flags);
0401 return count;
0402 }
0403
0404 static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
0405 {
0406 struct vio_dev *viod = to_vio_dev(dev);
0407 struct hvcs_struct *hvcsd = from_vio_dev(viod);
0408 unsigned long flags;
0409 int retval;
0410
0411 spin_lock_irqsave(&hvcsd->lock, flags);
0412 retval = sprintf(buf, "%d\n", hvcsd->connected);
0413 spin_unlock_irqrestore(&hvcsd->lock, flags);
0414 return retval;
0415 }
0416 static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
0417 hvcs_vterm_state_show, hvcs_vterm_state_store);
0418
0419 static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
0420 {
0421 struct vio_dev *viod = to_vio_dev(dev);
0422 struct hvcs_struct *hvcsd = from_vio_dev(viod);
0423 unsigned long flags;
0424 int retval;
0425
0426 spin_lock_irqsave(&hvcsd->lock, flags);
0427 retval = sprintf(buf, "%d\n", hvcsd->index);
0428 spin_unlock_irqrestore(&hvcsd->lock, flags);
0429 return retval;
0430 }
0431
0432 static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
0433
0434 static struct attribute *hvcs_attrs[] = {
0435 &dev_attr_partner_vtys.attr,
0436 &dev_attr_partner_clcs.attr,
0437 &dev_attr_current_vty.attr,
0438 &dev_attr_vterm_state.attr,
0439 &dev_attr_index.attr,
0440 NULL,
0441 };
0442
0443 static struct attribute_group hvcs_attr_group = {
0444 .attrs = hvcs_attrs,
0445 };
0446
0447 static ssize_t rescan_show(struct device_driver *ddp, char *buf)
0448 {
0449
0450 return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
0451 }
0452
0453 static ssize_t rescan_store(struct device_driver *ddp, const char * buf,
0454 size_t count)
0455 {
0456 if ((simple_strtol(buf, NULL, 0) != 1)
0457 && (hvcs_rescan_status != 0))
0458 return -EINVAL;
0459
0460 hvcs_rescan_status = 1;
0461 printk(KERN_INFO "HVCS: rescanning partner info for all"
0462 " vty-servers.\n");
0463 hvcs_rescan_devices_list();
0464 hvcs_rescan_status = 0;
0465 return count;
0466 }
0467
0468 static DRIVER_ATTR_RW(rescan);
0469
0470 static void hvcs_kick(void)
0471 {
0472 hvcs_kicked = 1;
0473 wmb();
0474 wake_up_process(hvcs_task);
0475 }
0476
0477 static void hvcs_unthrottle(struct tty_struct *tty)
0478 {
0479 struct hvcs_struct *hvcsd = tty->driver_data;
0480 unsigned long flags;
0481
0482 spin_lock_irqsave(&hvcsd->lock, flags);
0483 hvcsd->todo_mask |= HVCS_SCHED_READ;
0484 spin_unlock_irqrestore(&hvcsd->lock, flags);
0485 hvcs_kick();
0486 }
0487
0488 static void hvcs_throttle(struct tty_struct *tty)
0489 {
0490 struct hvcs_struct *hvcsd = tty->driver_data;
0491 unsigned long flags;
0492
0493 spin_lock_irqsave(&hvcsd->lock, flags);
0494 vio_disable_interrupts(hvcsd->vdev);
0495 spin_unlock_irqrestore(&hvcsd->lock, flags);
0496 }
0497
0498
0499
0500
0501
0502
0503 static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
0504 {
0505 struct hvcs_struct *hvcsd = dev_instance;
0506
0507 spin_lock(&hvcsd->lock);
0508 vio_disable_interrupts(hvcsd->vdev);
0509 hvcsd->todo_mask |= HVCS_SCHED_READ;
0510 spin_unlock(&hvcsd->lock);
0511 hvcs_kick();
0512
0513 return IRQ_HANDLED;
0514 }
0515
0516
0517 static void hvcs_try_write(struct hvcs_struct *hvcsd)
0518 {
0519 uint32_t unit_address = hvcsd->vdev->unit_address;
0520 struct tty_struct *tty = hvcsd->port.tty;
0521 int sent;
0522
0523 if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
0524
0525 sent = hvc_put_chars(unit_address,
0526 &hvcsd->buffer[0],
0527 hvcsd->chars_in_buffer );
0528 if (sent > 0) {
0529 hvcsd->chars_in_buffer = 0;
0530
0531 hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
0532
0533
0534
0535
0536
0537
0538
0539
0540 if (tty) {
0541 tty_wakeup(tty);
0542 }
0543 }
0544 }
0545 }
0546
0547 static int hvcs_io(struct hvcs_struct *hvcsd)
0548 {
0549 uint32_t unit_address;
0550 struct tty_struct *tty;
0551 char buf[HVCS_BUFF_LEN] __ALIGNED__;
0552 unsigned long flags;
0553 int got = 0;
0554
0555 spin_lock_irqsave(&hvcsd->lock, flags);
0556
0557 unit_address = hvcsd->vdev->unit_address;
0558 tty = hvcsd->port.tty;
0559
0560 hvcs_try_write(hvcsd);
0561
0562 if (!tty || tty_throttled(tty)) {
0563 hvcsd->todo_mask &= ~(HVCS_READ_MASK);
0564 goto bail;
0565 } else if (!(hvcsd->todo_mask & (HVCS_READ_MASK)))
0566 goto bail;
0567
0568
0569 hvcsd->todo_mask &= ~(HVCS_READ_MASK);
0570
0571 if (tty_buffer_request_room(&hvcsd->port, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
0572 got = hvc_get_chars(unit_address,
0573 &buf[0],
0574 HVCS_BUFF_LEN);
0575 tty_insert_flip_string(&hvcsd->port, buf, got);
0576 }
0577
0578
0579 if (got)
0580 hvcsd->todo_mask |= HVCS_QUICK_READ;
0581
0582 spin_unlock_irqrestore(&hvcsd->lock, flags);
0583
0584 if (got)
0585 tty_flip_buffer_push(&hvcsd->port);
0586 else {
0587
0588 spin_lock_irqsave(&hvcsd->lock, flags);
0589 vio_enable_interrupts(hvcsd->vdev);
0590 spin_unlock_irqrestore(&hvcsd->lock, flags);
0591 }
0592
0593 return hvcsd->todo_mask;
0594
0595 bail:
0596 spin_unlock_irqrestore(&hvcsd->lock, flags);
0597 return hvcsd->todo_mask;
0598 }
0599
0600 static int khvcsd(void *unused)
0601 {
0602 struct hvcs_struct *hvcsd;
0603 int hvcs_todo_mask;
0604
0605 __set_current_state(TASK_RUNNING);
0606
0607 do {
0608 hvcs_todo_mask = 0;
0609 hvcs_kicked = 0;
0610 wmb();
0611
0612 spin_lock(&hvcs_structs_lock);
0613 list_for_each_entry(hvcsd, &hvcs_structs, next) {
0614 hvcs_todo_mask |= hvcs_io(hvcsd);
0615 }
0616 spin_unlock(&hvcs_structs_lock);
0617
0618
0619
0620
0621
0622
0623 if (hvcs_todo_mask & (HVCS_TRY_WRITE | HVCS_QUICK_READ)) {
0624 yield();
0625 continue;
0626 }
0627
0628 set_current_state(TASK_INTERRUPTIBLE);
0629 if (!hvcs_kicked)
0630 schedule();
0631 __set_current_state(TASK_RUNNING);
0632 } while (!kthread_should_stop());
0633
0634 return 0;
0635 }
0636
0637 static const struct vio_device_id hvcs_driver_table[] = {
0638 {"serial-server", "hvterm2"},
0639 { "", "" }
0640 };
0641 MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
0642
0643 static void hvcs_return_index(int index)
0644 {
0645
0646 if (!hvcs_index_list)
0647 return;
0648 if (index < 0 || index >= hvcs_index_count)
0649 return;
0650 if (hvcs_index_list[index] == -1)
0651 return;
0652 else
0653 hvcs_index_list[index] = -1;
0654 }
0655
0656 static void hvcs_destruct_port(struct tty_port *p)
0657 {
0658 struct hvcs_struct *hvcsd = container_of(p, struct hvcs_struct, port);
0659 struct vio_dev *vdev;
0660 unsigned long flags;
0661
0662 spin_lock(&hvcs_structs_lock);
0663 spin_lock_irqsave(&hvcsd->lock, flags);
0664
0665
0666 list_del(&(hvcsd->next));
0667
0668 if (hvcsd->connected == 1) {
0669 hvcs_partner_free(hvcsd);
0670 printk(KERN_INFO "HVCS: Closed vty-server@%X and"
0671 " partner vty@%X:%d connection.\n",
0672 hvcsd->vdev->unit_address,
0673 hvcsd->p_unit_address,
0674 (uint32_t)hvcsd->p_partition_ID);
0675 }
0676 printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
0677 hvcsd->vdev->unit_address);
0678
0679 vdev = hvcsd->vdev;
0680 hvcsd->vdev = NULL;
0681
0682 hvcsd->p_unit_address = 0;
0683 hvcsd->p_partition_ID = 0;
0684 hvcs_return_index(hvcsd->index);
0685 memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
0686
0687 spin_unlock_irqrestore(&hvcsd->lock, flags);
0688 spin_unlock(&hvcs_structs_lock);
0689
0690 sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
0691
0692 kfree(hvcsd);
0693 }
0694
0695 static const struct tty_port_operations hvcs_port_ops = {
0696 .destruct = hvcs_destruct_port,
0697 };
0698
0699 static int hvcs_get_index(void)
0700 {
0701 int i;
0702
0703 if (!hvcs_index_list) {
0704 printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
0705 return -EFAULT;
0706 }
0707
0708 for(i = 0; i < hvcs_index_count; i++) {
0709 if (hvcs_index_list[i] == -1) {
0710 hvcs_index_list[i] = 0;
0711 return i;
0712 }
0713 }
0714 return -1;
0715 }
0716
0717 static int hvcs_probe(
0718 struct vio_dev *dev,
0719 const struct vio_device_id *id)
0720 {
0721 struct hvcs_struct *hvcsd;
0722 int index, rc;
0723 int retval;
0724
0725 if (!dev || !id) {
0726 printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
0727 return -EPERM;
0728 }
0729
0730
0731 rc = hvcs_initialize();
0732 if (rc) {
0733 pr_err("HVCS: Failed to initialize core driver.\n");
0734 return rc;
0735 }
0736
0737
0738 index = hvcs_get_index();
0739 if (index < 0) {
0740 return -EFAULT;
0741 }
0742
0743 hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL);
0744 if (!hvcsd)
0745 return -ENODEV;
0746
0747 tty_port_init(&hvcsd->port);
0748 hvcsd->port.ops = &hvcs_port_ops;
0749 spin_lock_init(&hvcsd->lock);
0750
0751 hvcsd->vdev = dev;
0752 dev_set_drvdata(&dev->dev, hvcsd);
0753
0754 hvcsd->index = index;
0755
0756
0757 hvcsd->chars_in_buffer = 0;
0758 hvcsd->todo_mask = 0;
0759 hvcsd->connected = 0;
0760
0761
0762
0763
0764
0765 if (hvcs_get_pi(hvcsd)) {
0766 printk(KERN_ERR "HVCS: Failed to fetch partner"
0767 " info for vty-server@%X on device probe.\n",
0768 hvcsd->vdev->unit_address);
0769 }
0770
0771
0772
0773
0774
0775
0776 spin_lock(&hvcs_structs_lock);
0777 list_add_tail(&(hvcsd->next), &hvcs_structs);
0778 spin_unlock(&hvcs_structs_lock);
0779
0780 retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group);
0781 if (retval) {
0782 printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n",
0783 hvcsd->vdev->unit_address);
0784 return retval;
0785 }
0786
0787 printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
0788
0789
0790
0791
0792
0793 return 0;
0794 }
0795
0796 static void hvcs_remove(struct vio_dev *dev)
0797 {
0798 struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
0799 unsigned long flags;
0800 struct tty_struct *tty;
0801
0802
0803
0804 spin_lock_irqsave(&hvcsd->lock, flags);
0805
0806 tty = hvcsd->port.tty;
0807
0808 spin_unlock_irqrestore(&hvcsd->lock, flags);
0809
0810
0811
0812
0813
0814 tty_port_put(&hvcsd->port);
0815
0816
0817
0818
0819
0820
0821 if (tty)
0822 tty_hangup(tty);
0823
0824 printk(KERN_INFO "HVCS: vty-server@%X removed from the"
0825 " vio bus.\n", dev->unit_address);
0826 };
0827
0828 static struct vio_driver hvcs_vio_driver = {
0829 .id_table = hvcs_driver_table,
0830 .probe = hvcs_probe,
0831 .remove = hvcs_remove,
0832 .name = hvcs_driver_name,
0833 };
0834
0835
0836 static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
0837 {
0838 hvcsd->p_unit_address = pi->unit_address;
0839 hvcsd->p_partition_ID = pi->partition_ID;
0840
0841
0842 strlcpy(hvcsd->p_location_code, pi->location_code,
0843 sizeof(hvcsd->p_location_code));
0844 }
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859 static int hvcs_get_pi(struct hvcs_struct *hvcsd)
0860 {
0861 struct hvcs_partner_info *pi;
0862 uint32_t unit_address = hvcsd->vdev->unit_address;
0863 struct list_head head;
0864 int retval;
0865
0866 spin_lock(&hvcs_pi_lock);
0867 if (!hvcs_pi_buff) {
0868 spin_unlock(&hvcs_pi_lock);
0869 return -EFAULT;
0870 }
0871 retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
0872 spin_unlock(&hvcs_pi_lock);
0873 if (retval) {
0874 printk(KERN_ERR "HVCS: Failed to fetch partner"
0875 " info for vty-server@%x.\n", unit_address);
0876 return retval;
0877 }
0878
0879
0880 hvcsd->p_unit_address = 0;
0881 hvcsd->p_partition_ID = 0;
0882
0883 list_for_each_entry(pi, &head, node)
0884 hvcs_set_pi(pi, hvcsd);
0885
0886 hvcs_free_partner_info(&head);
0887 return 0;
0888 }
0889
0890
0891
0892
0893
0894 static int hvcs_rescan_devices_list(void)
0895 {
0896 struct hvcs_struct *hvcsd;
0897 unsigned long flags;
0898
0899 spin_lock(&hvcs_structs_lock);
0900
0901 list_for_each_entry(hvcsd, &hvcs_structs, next) {
0902 spin_lock_irqsave(&hvcsd->lock, flags);
0903 hvcs_get_pi(hvcsd);
0904 spin_unlock_irqrestore(&hvcsd->lock, flags);
0905 }
0906
0907 spin_unlock(&hvcs_structs_lock);
0908
0909 return 0;
0910 }
0911
0912
0913
0914
0915
0916
0917 static int hvcs_has_pi(struct hvcs_struct *hvcsd)
0918 {
0919 if ((!hvcsd->p_unit_address) || (!hvcsd->p_partition_ID))
0920 return 0;
0921 return 1;
0922 }
0923
0924
0925
0926
0927
0928
0929
0930 static int hvcs_partner_connect(struct hvcs_struct *hvcsd)
0931 {
0932 int retval;
0933 unsigned int unit_address = hvcsd->vdev->unit_address;
0934
0935
0936
0937
0938
0939
0940
0941
0942 retval = hvcs_register_connection(unit_address,
0943 hvcsd->p_partition_ID,
0944 hvcsd->p_unit_address);
0945 if (!retval) {
0946 hvcsd->connected = 1;
0947 return 0;
0948 } else if (retval != -EINVAL)
0949 return retval;
0950
0951
0952
0953
0954
0955 if (hvcs_get_pi(hvcsd))
0956 return -ENOMEM;
0957
0958 if (!hvcs_has_pi(hvcsd))
0959 return -ENODEV;
0960
0961 retval = hvcs_register_connection(unit_address,
0962 hvcsd->p_partition_ID,
0963 hvcsd->p_unit_address);
0964 if (retval != -EINVAL) {
0965 hvcsd->connected = 1;
0966 return retval;
0967 }
0968
0969
0970
0971
0972
0973
0974
0975 printk(KERN_INFO "HVCS: vty-server or partner"
0976 " vty is busy. Try again later.\n");
0977 return -EBUSY;
0978 }
0979
0980
0981 static void hvcs_partner_free(struct hvcs_struct *hvcsd)
0982 {
0983 int retval;
0984 do {
0985 retval = hvcs_free_connection(hvcsd->vdev->unit_address);
0986 } while (retval == -EBUSY);
0987 hvcsd->connected = 0;
0988 }
0989
0990
0991 static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
0992 unsigned int irq, struct vio_dev *vdev)
0993 {
0994 unsigned long flags;
0995 int rc;
0996
0997
0998
0999
1000
1001 rc = request_irq(irq, &hvcs_handle_interrupt, 0, "ibmhvcs", hvcsd);
1002 if (!rc) {
1003
1004
1005
1006
1007 if (vio_enable_interrupts(vdev) == H_SUCCESS)
1008 return 0;
1009 else {
1010 printk(KERN_ERR "HVCS: int enable failed for"
1011 " vty-server@%X.\n", unit_address);
1012 free_irq(irq, hvcsd);
1013 }
1014 } else
1015 printk(KERN_ERR "HVCS: irq req failed for"
1016 " vty-server@%X.\n", unit_address);
1017
1018 spin_lock_irqsave(&hvcsd->lock, flags);
1019 hvcs_partner_free(hvcsd);
1020 spin_unlock_irqrestore(&hvcsd->lock, flags);
1021
1022 return rc;
1023
1024 }
1025
1026
1027
1028
1029
1030
1031
1032
1033 static struct hvcs_struct *hvcs_get_by_index(int index)
1034 {
1035 struct hvcs_struct *hvcsd;
1036 unsigned long flags;
1037
1038 spin_lock(&hvcs_structs_lock);
1039 list_for_each_entry(hvcsd, &hvcs_structs, next) {
1040 spin_lock_irqsave(&hvcsd->lock, flags);
1041 if (hvcsd->index == index) {
1042 tty_port_get(&hvcsd->port);
1043 spin_unlock_irqrestore(&hvcsd->lock, flags);
1044 spin_unlock(&hvcs_structs_lock);
1045 return hvcsd;
1046 }
1047 spin_unlock_irqrestore(&hvcsd->lock, flags);
1048 }
1049 spin_unlock(&hvcs_structs_lock);
1050
1051 return NULL;
1052 }
1053
1054 static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
1055 {
1056 struct hvcs_struct *hvcsd;
1057 struct vio_dev *vdev;
1058 unsigned long unit_address, flags;
1059 unsigned int irq;
1060 int retval;
1061
1062
1063
1064
1065
1066 hvcsd = hvcs_get_by_index(tty->index);
1067 if (!hvcsd) {
1068 printk(KERN_WARNING "HVCS: open failed, no device associated"
1069 " with tty->index %d.\n", tty->index);
1070 return -ENODEV;
1071 }
1072
1073 spin_lock_irqsave(&hvcsd->lock, flags);
1074
1075 if (hvcsd->connected == 0) {
1076 retval = hvcs_partner_connect(hvcsd);
1077 if (retval) {
1078 spin_unlock_irqrestore(&hvcsd->lock, flags);
1079 printk(KERN_WARNING "HVCS: partner connect failed.\n");
1080 goto err_put;
1081 }
1082 }
1083
1084 hvcsd->port.count = 0;
1085 hvcsd->port.tty = tty;
1086 tty->driver_data = hvcsd;
1087
1088 memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
1089
1090
1091
1092
1093
1094 irq = hvcsd->vdev->irq;
1095 vdev = hvcsd->vdev;
1096 unit_address = hvcsd->vdev->unit_address;
1097
1098 hvcsd->todo_mask |= HVCS_SCHED_READ;
1099 spin_unlock_irqrestore(&hvcsd->lock, flags);
1100
1101
1102
1103
1104
1105 retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);
1106 if (retval) {
1107 printk(KERN_WARNING "HVCS: enable device failed.\n");
1108 goto err_put;
1109 }
1110
1111 retval = tty_port_install(&hvcsd->port, driver, tty);
1112 if (retval)
1113 goto err_irq;
1114
1115 return 0;
1116 err_irq:
1117 spin_lock_irqsave(&hvcsd->lock, flags);
1118 vio_disable_interrupts(hvcsd->vdev);
1119 spin_unlock_irqrestore(&hvcsd->lock, flags);
1120 free_irq(irq, hvcsd);
1121 err_put:
1122 tty_port_put(&hvcsd->port);
1123
1124 return retval;
1125 }
1126
1127
1128
1129
1130
1131 static int hvcs_open(struct tty_struct *tty, struct file *filp)
1132 {
1133 struct hvcs_struct *hvcsd = tty->driver_data;
1134 unsigned long flags;
1135
1136 spin_lock_irqsave(&hvcsd->lock, flags);
1137 hvcsd->port.count++;
1138 hvcsd->todo_mask |= HVCS_SCHED_READ;
1139 spin_unlock_irqrestore(&hvcsd->lock, flags);
1140
1141 hvcs_kick();
1142
1143 printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
1144 hvcsd->vdev->unit_address );
1145
1146 return 0;
1147 }
1148
1149 static void hvcs_close(struct tty_struct *tty, struct file *filp)
1150 {
1151 struct hvcs_struct *hvcsd;
1152 unsigned long flags;
1153 int irq;
1154
1155
1156
1157
1158
1159 if (tty_hung_up_p(filp))
1160 return;
1161
1162
1163
1164
1165
1166
1167 if (!tty->driver_data)
1168 return;
1169
1170 hvcsd = tty->driver_data;
1171
1172 spin_lock_irqsave(&hvcsd->lock, flags);
1173 if (--hvcsd->port.count == 0) {
1174
1175 vio_disable_interrupts(hvcsd->vdev);
1176
1177
1178
1179
1180
1181
1182 hvcsd->port.tty = NULL;
1183
1184 irq = hvcsd->vdev->irq;
1185 spin_unlock_irqrestore(&hvcsd->lock, flags);
1186
1187 tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
1188
1189 free_irq(irq, hvcsd);
1190 return;
1191 } else if (hvcsd->port.count < 0) {
1192 printk(KERN_ERR "HVCS: vty-server@%X open_count: %d is mismanaged.\n",
1193 hvcsd->vdev->unit_address, hvcsd->port.count);
1194 }
1195
1196 spin_unlock_irqrestore(&hvcsd->lock, flags);
1197 }
1198
1199 static void hvcs_cleanup(struct tty_struct * tty)
1200 {
1201 struct hvcs_struct *hvcsd = tty->driver_data;
1202
1203
1204
1205
1206
1207
1208 tty->driver_data = NULL;
1209
1210 tty_port_put(&hvcsd->port);
1211 }
1212
1213 static void hvcs_hangup(struct tty_struct * tty)
1214 {
1215 struct hvcs_struct *hvcsd = tty->driver_data;
1216 unsigned long flags;
1217 int temp_open_count;
1218 int irq;
1219
1220 spin_lock_irqsave(&hvcsd->lock, flags);
1221
1222 temp_open_count = hvcsd->port.count;
1223
1224
1225
1226
1227
1228
1229 vio_disable_interrupts(hvcsd->vdev);
1230
1231 hvcsd->todo_mask = 0;
1232
1233
1234 tty->driver_data = NULL;
1235 hvcsd->port.tty = NULL;
1236
1237 hvcsd->port.count = 0;
1238
1239
1240
1241 memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
1242 hvcsd->chars_in_buffer = 0;
1243
1244 irq = hvcsd->vdev->irq;
1245
1246 spin_unlock_irqrestore(&hvcsd->lock, flags);
1247
1248 free_irq(irq, hvcsd);
1249
1250
1251
1252
1253
1254
1255 while(temp_open_count) {
1256 --temp_open_count;
1257
1258
1259
1260
1261
1262 tty_port_put(&hvcsd->port);
1263 }
1264 }
1265
1266
1267
1268
1269
1270
1271
1272
1273 static int hvcs_write(struct tty_struct *tty,
1274 const unsigned char *buf, int count)
1275 {
1276 struct hvcs_struct *hvcsd = tty->driver_data;
1277 unsigned int unit_address;
1278 const unsigned char *charbuf;
1279 unsigned long flags;
1280 int total_sent = 0;
1281 int tosend = 0;
1282 int result = 0;
1283
1284
1285
1286
1287
1288 if (!hvcsd)
1289 return -ENODEV;
1290
1291
1292 if (count > HVCS_MAX_FROM_USER) {
1293 printk(KERN_WARNING "HVCS write: count being truncated to"
1294 " HVCS_MAX_FROM_USER.\n");
1295 count = HVCS_MAX_FROM_USER;
1296 }
1297
1298 charbuf = buf;
1299
1300 spin_lock_irqsave(&hvcsd->lock, flags);
1301
1302
1303
1304
1305
1306
1307
1308 if (hvcsd->port.count <= 0) {
1309 spin_unlock_irqrestore(&hvcsd->lock, flags);
1310 return -ENODEV;
1311 }
1312
1313 unit_address = hvcsd->vdev->unit_address;
1314
1315 while (count > 0) {
1316 tosend = min(count, (HVCS_BUFF_LEN - hvcsd->chars_in_buffer));
1317
1318
1319
1320
1321 if (!tosend)
1322 break;
1323
1324 memcpy(&hvcsd->buffer[hvcsd->chars_in_buffer],
1325 &charbuf[total_sent],
1326 tosend);
1327
1328 hvcsd->chars_in_buffer += tosend;
1329
1330 result = 0;
1331
1332
1333
1334
1335
1336
1337 if (!(hvcsd->todo_mask & HVCS_TRY_WRITE))
1338
1339 result = hvc_put_chars(unit_address,
1340 &hvcsd->buffer[0],
1341 hvcsd->chars_in_buffer);
1342
1343
1344
1345
1346
1347
1348 total_sent+=tosend;
1349 count-=tosend;
1350 if (result == 0) {
1351 hvcsd->todo_mask |= HVCS_TRY_WRITE;
1352 hvcs_kick();
1353 break;
1354 }
1355
1356 hvcsd->chars_in_buffer = 0;
1357
1358
1359
1360
1361 if (result < 0)
1362 break;
1363 }
1364
1365 spin_unlock_irqrestore(&hvcsd->lock, flags);
1366
1367 if (result == -1)
1368 return -EIO;
1369 else
1370 return total_sent;
1371 }
1372
1373
1374
1375
1376
1377
1378 static unsigned int hvcs_write_room(struct tty_struct *tty)
1379 {
1380 struct hvcs_struct *hvcsd = tty->driver_data;
1381
1382 if (!hvcsd || hvcsd->port.count <= 0)
1383 return 0;
1384
1385 return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
1386 }
1387
1388 static unsigned int hvcs_chars_in_buffer(struct tty_struct *tty)
1389 {
1390 struct hvcs_struct *hvcsd = tty->driver_data;
1391
1392 return hvcsd->chars_in_buffer;
1393 }
1394
1395 static const struct tty_operations hvcs_ops = {
1396 .install = hvcs_install,
1397 .open = hvcs_open,
1398 .close = hvcs_close,
1399 .cleanup = hvcs_cleanup,
1400 .hangup = hvcs_hangup,
1401 .write = hvcs_write,
1402 .write_room = hvcs_write_room,
1403 .chars_in_buffer = hvcs_chars_in_buffer,
1404 .unthrottle = hvcs_unthrottle,
1405 .throttle = hvcs_throttle,
1406 };
1407
1408 static int hvcs_alloc_index_list(int n)
1409 {
1410 int i;
1411
1412 hvcs_index_list = kmalloc_array(n, sizeof(hvcs_index_count),
1413 GFP_KERNEL);
1414 if (!hvcs_index_list)
1415 return -ENOMEM;
1416 hvcs_index_count = n;
1417 for (i = 0; i < hvcs_index_count; i++)
1418 hvcs_index_list[i] = -1;
1419 return 0;
1420 }
1421
1422 static void hvcs_free_index_list(void)
1423 {
1424
1425 kfree(hvcs_index_list);
1426 hvcs_index_list = NULL;
1427 hvcs_index_count = 0;
1428 }
1429
1430 static int hvcs_initialize(void)
1431 {
1432 int rc, num_ttys_to_alloc;
1433
1434 mutex_lock(&hvcs_init_mutex);
1435 if (hvcs_task) {
1436 mutex_unlock(&hvcs_init_mutex);
1437 return 0;
1438 }
1439
1440
1441 if (hvcs_parm_num_devs <= 0 ||
1442 (hvcs_parm_num_devs > HVCS_MAX_SERVER_ADAPTERS)) {
1443 num_ttys_to_alloc = HVCS_DEFAULT_SERVER_ADAPTERS;
1444 } else
1445 num_ttys_to_alloc = hvcs_parm_num_devs;
1446
1447 hvcs_tty_driver = tty_alloc_driver(num_ttys_to_alloc,
1448 TTY_DRIVER_REAL_RAW);
1449 if (IS_ERR(hvcs_tty_driver)) {
1450 mutex_unlock(&hvcs_init_mutex);
1451 return PTR_ERR(hvcs_tty_driver);
1452 }
1453
1454 if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
1455 rc = -ENOMEM;
1456 goto index_fail;
1457 }
1458
1459 hvcs_tty_driver->driver_name = hvcs_driver_name;
1460 hvcs_tty_driver->name = hvcs_device_node;
1461
1462
1463
1464
1465
1466
1467 hvcs_tty_driver->minor_start = HVCS_MINOR_START;
1468 hvcs_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
1469
1470
1471
1472
1473
1474
1475 hvcs_tty_driver->init_termios = hvcs_tty_termios;
1476
1477 tty_set_operations(hvcs_tty_driver, &hvcs_ops);
1478
1479
1480
1481
1482
1483 if (tty_register_driver(hvcs_tty_driver)) {
1484 printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");
1485 rc = -EIO;
1486 goto register_fail;
1487 }
1488
1489 hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL);
1490 if (!hvcs_pi_buff) {
1491 rc = -ENOMEM;
1492 goto buff_alloc_fail;
1493 }
1494
1495 hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
1496 if (IS_ERR(hvcs_task)) {
1497 printk(KERN_ERR "HVCS: khvcsd creation failed.\n");
1498 rc = -EIO;
1499 goto kthread_fail;
1500 }
1501 mutex_unlock(&hvcs_init_mutex);
1502 return 0;
1503
1504 kthread_fail:
1505 free_page((unsigned long)hvcs_pi_buff);
1506 buff_alloc_fail:
1507 tty_unregister_driver(hvcs_tty_driver);
1508 register_fail:
1509 hvcs_free_index_list();
1510 index_fail:
1511 tty_driver_kref_put(hvcs_tty_driver);
1512 hvcs_tty_driver = NULL;
1513 mutex_unlock(&hvcs_init_mutex);
1514 return rc;
1515 }
1516
1517 static int __init hvcs_module_init(void)
1518 {
1519 int rc = vio_register_driver(&hvcs_vio_driver);
1520 if (rc) {
1521 printk(KERN_ERR "HVCS: can't register vio driver\n");
1522 return rc;
1523 }
1524
1525 pr_info("HVCS: Driver registered.\n");
1526
1527
1528
1529
1530 rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
1531 if (rc)
1532 pr_warn("HVCS: Failed to create rescan file (err %d)\n", rc);
1533
1534 return 0;
1535 }
1536
1537 static void __exit hvcs_module_exit(void)
1538 {
1539
1540
1541
1542
1543 vio_unregister_driver(&hvcs_vio_driver);
1544 if (!hvcs_task)
1545 return;
1546
1547
1548
1549
1550
1551 kthread_stop(hvcs_task);
1552
1553 spin_lock(&hvcs_pi_lock);
1554 free_page((unsigned long)hvcs_pi_buff);
1555 hvcs_pi_buff = NULL;
1556 spin_unlock(&hvcs_pi_lock);
1557
1558 driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
1559
1560 tty_unregister_driver(hvcs_tty_driver);
1561
1562 hvcs_free_index_list();
1563
1564 tty_driver_kref_put(hvcs_tty_driver);
1565
1566 printk(KERN_INFO "HVCS: driver module removed.\n");
1567 }
1568
1569 module_init(hvcs_module_init);
1570 module_exit(hvcs_module_exit);