1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66#include <linux/device.h>
67#include <linux/init.h>
68#include <linux/interrupt.h>
69#include <linux/kernel.h>
70#include <linux/kref.h>
71#include <linux/kthread.h>
72#include <linux/list.h>
73#include <linux/major.h>
74#include <linux/module.h>
75#include <linux/moduleparam.h>
76#include <linux/sched.h>
77#include <linux/slab.h>
78#include <linux/spinlock.h>
79#include <linux/stat.h>
80#include <linux/tty.h>
81#include <linux/tty_flip.h>
82#include <asm/hvconsole.h>
83#include <asm/hvcserver.h>
84#include <asm/uaccess.h>
85#include <asm/vio.h>
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128#define HVCS_DRIVER_VERSION "1.3.3"
129
130MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
131MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
132MODULE_LICENSE("GPL");
133MODULE_VERSION(HVCS_DRIVER_VERSION);
134
135
136
137
138
139#define HVCS_CLOSE_WAIT (HZ/100)
140
141
142
143
144
145
146
147
148
149#define HVCS_DEFAULT_SERVER_ADAPTERS 64
150
151
152
153
154
155
156#define HVCS_MAX_SERVER_ADAPTERS 1024
157
158
159
160
161
162
163
164#define HVCS_MINOR_START 0
165
166
167
168
169
170
171
172
173#define __ALIGNED__ __attribute__((__aligned__(8)))
174
175
176
177
178
179#define HVCS_BUFF_LEN 16
180
181
182
183
184
185#define HVCS_MAX_FROM_USER 4096
186
187
188
189
190
191
192static struct ktermios hvcs_tty_termios = {
193 .c_iflag = IGNBRK | IGNPAR,
194 .c_oflag = OPOST,
195 .c_cflag = B38400 | CS8 | CREAD | HUPCL,
196 .c_cc = INIT_C_CC,
197 .c_ispeed = 38400,
198 .c_ospeed = 38400
199};
200
201
202
203
204
205
206
207static int hvcs_parm_num_devs = -1;
208module_param(hvcs_parm_num_devs, int, 0);
209
210static const char hvcs_driver_name[] = "hvcs";
211static const char hvcs_device_node[] = "hvcs";
212static const char hvcs_driver_string[]
213 = "IBM hvcs (Hypervisor Virtual Console Server) Driver";
214
215
216static int hvcs_rescan_status;
217
218static struct tty_driver *hvcs_tty_driver;
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233static int *hvcs_index_list;
234
235
236
237
238
239static int hvcs_index_count;
240
241
242
243
244
245static int hvcs_kicked;
246
247
248
249
250
251static struct task_struct *hvcs_task;
252
253
254
255
256
257static unsigned long *hvcs_pi_buff;
258
259
260static DEFINE_SPINLOCK(hvcs_pi_lock);
261
262
263struct hvcs_struct {
264 struct tty_port port;
265 spinlock_t lock;
266
267
268
269
270
271 unsigned int index;
272
273
274
275
276
277 int todo_mask;
278
279
280
281
282
283
284
285
286
287 char buffer[HVCS_BUFF_LEN];
288 int chars_in_buffer;
289
290
291
292
293
294
295
296 int connected;
297 uint32_t p_unit_address;
298 uint32_t p_partition_ID;
299 char p_location_code[HVCS_CLC_LENGTH + 1];
300 struct list_head next;
301 struct vio_dev *vdev;
302};
303
304static LIST_HEAD(hvcs_structs);
305static DEFINE_SPINLOCK(hvcs_structs_lock);
306static DEFINE_MUTEX(hvcs_init_mutex);
307
308static void hvcs_unthrottle(struct tty_struct *tty);
309static void hvcs_throttle(struct tty_struct *tty);
310static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance);
311
312static int hvcs_write(struct tty_struct *tty,
313 const unsigned char *buf, int count);
314static int hvcs_write_room(struct tty_struct *tty);
315static int hvcs_chars_in_buffer(struct tty_struct *tty);
316
317static int hvcs_has_pi(struct hvcs_struct *hvcsd);
318static void hvcs_set_pi(struct hvcs_partner_info *pi,
319 struct hvcs_struct *hvcsd);
320static int hvcs_get_pi(struct hvcs_struct *hvcsd);
321static int hvcs_rescan_devices_list(void);
322
323static int hvcs_partner_connect(struct hvcs_struct *hvcsd);
324static void hvcs_partner_free(struct hvcs_struct *hvcsd);
325
326static int hvcs_enable_device(struct hvcs_struct *hvcsd,
327 uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
328
329static int hvcs_open(struct tty_struct *tty, struct file *filp);
330static void hvcs_close(struct tty_struct *tty, struct file *filp);
331static void hvcs_hangup(struct tty_struct * tty);
332
333static int hvcs_probe(struct vio_dev *dev,
334 const struct vio_device_id *id);
335static int hvcs_remove(struct vio_dev *dev);
336static int __init hvcs_module_init(void);
337static void __exit hvcs_module_exit(void);
338static int hvcs_initialize(void);
339
340#define HVCS_SCHED_READ 0x00000001
341#define HVCS_QUICK_READ 0x00000002
342#define HVCS_TRY_WRITE 0x00000004
343#define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ)
344
345static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
346{
347 return dev_get_drvdata(&viod->dev);
348}
349
350
351static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
352{
353 struct vio_dev *viod = to_vio_dev(dev);
354 struct hvcs_struct *hvcsd = from_vio_dev(viod);
355 unsigned long flags;
356 int retval;
357
358 spin_lock_irqsave(&hvcsd->lock, flags);
359 retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
360 spin_unlock_irqrestore(&hvcsd->lock, flags);
361 return retval;
362}
363static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
364
365static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
366{
367 struct vio_dev *viod = to_vio_dev(dev);
368 struct hvcs_struct *hvcsd = from_vio_dev(viod);
369 unsigned long flags;
370 int retval;
371
372 spin_lock_irqsave(&hvcsd->lock, flags);
373 retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
374 spin_unlock_irqrestore(&hvcsd->lock, flags);
375 return retval;
376}
377static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
378
379static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
380 size_t count)
381{
382
383
384
385
386 printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
387 return -EPERM;
388}
389
390static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
391{
392 struct vio_dev *viod = to_vio_dev(dev);
393 struct hvcs_struct *hvcsd = from_vio_dev(viod);
394 unsigned long flags;
395 int retval;
396
397 spin_lock_irqsave(&hvcsd->lock, flags);
398 retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
399 spin_unlock_irqrestore(&hvcsd->lock, flags);
400 return retval;
401}
402
403static DEVICE_ATTR(current_vty,
404 S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
405
406static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
407 size_t count)
408{
409 struct vio_dev *viod = to_vio_dev(dev);
410 struct hvcs_struct *hvcsd = from_vio_dev(viod);
411 unsigned long flags;
412
413
414 if (simple_strtol(buf, NULL, 0) != 0)
415 return -EINVAL;
416
417 spin_lock_irqsave(&hvcsd->lock, flags);
418
419 if (hvcsd->port.count > 0) {
420 spin_unlock_irqrestore(&hvcsd->lock, flags);
421 printk(KERN_INFO "HVCS: vterm state unchanged. "
422 "The hvcs device node is still in use.\n");
423 return -EPERM;
424 }
425
426 if (hvcsd->connected == 0) {
427 spin_unlock_irqrestore(&hvcsd->lock, flags);
428 printk(KERN_INFO "HVCS: vterm state unchanged. The"
429 " vty-server is not connected to a vty.\n");
430 return -EPERM;
431 }
432
433 hvcs_partner_free(hvcsd);
434 printk(KERN_INFO "HVCS: Closed vty-server@%X and"
435 " partner vty@%X:%d connection.\n",
436 hvcsd->vdev->unit_address,
437 hvcsd->p_unit_address,
438 (uint32_t)hvcsd->p_partition_ID);
439
440 spin_unlock_irqrestore(&hvcsd->lock, flags);
441 return count;
442}
443
444static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
445{
446 struct vio_dev *viod = to_vio_dev(dev);
447 struct hvcs_struct *hvcsd = from_vio_dev(viod);
448 unsigned long flags;
449 int retval;
450
451 spin_lock_irqsave(&hvcsd->lock, flags);
452 retval = sprintf(buf, "%d\n", hvcsd->connected);
453 spin_unlock_irqrestore(&hvcsd->lock, flags);
454 return retval;
455}
456static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
457 hvcs_vterm_state_show, hvcs_vterm_state_store);
458
459static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
460{
461 struct vio_dev *viod = to_vio_dev(dev);
462 struct hvcs_struct *hvcsd = from_vio_dev(viod);
463 unsigned long flags;
464 int retval;
465
466 spin_lock_irqsave(&hvcsd->lock, flags);
467 retval = sprintf(buf, "%d\n", hvcsd->index);
468 spin_unlock_irqrestore(&hvcsd->lock, flags);
469 return retval;
470}
471
472static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
473
474static struct attribute *hvcs_attrs[] = {
475 &dev_attr_partner_vtys.attr,
476 &dev_attr_partner_clcs.attr,
477 &dev_attr_current_vty.attr,
478 &dev_attr_vterm_state.attr,
479 &dev_attr_index.attr,
480 NULL,
481};
482
483static struct attribute_group hvcs_attr_group = {
484 .attrs = hvcs_attrs,
485};
486
487static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf)
488{
489
490 return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
491}
492
493static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf,
494 size_t count)
495{
496 if ((simple_strtol(buf, NULL, 0) != 1)
497 && (hvcs_rescan_status != 0))
498 return -EINVAL;
499
500 hvcs_rescan_status = 1;
501 printk(KERN_INFO "HVCS: rescanning partner info for all"
502 " vty-servers.\n");
503 hvcs_rescan_devices_list();
504 hvcs_rescan_status = 0;
505 return count;
506}
507
508static DRIVER_ATTR(rescan,
509 S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
510
511static void hvcs_kick(void)
512{
513 hvcs_kicked = 1;
514 wmb();
515 wake_up_process(hvcs_task);
516}
517
518static void hvcs_unthrottle(struct tty_struct *tty)
519{
520 struct hvcs_struct *hvcsd = tty->driver_data;
521 unsigned long flags;
522
523 spin_lock_irqsave(&hvcsd->lock, flags);
524 hvcsd->todo_mask |= HVCS_SCHED_READ;
525 spin_unlock_irqrestore(&hvcsd->lock, flags);
526 hvcs_kick();
527}
528
529static void hvcs_throttle(struct tty_struct *tty)
530{
531 struct hvcs_struct *hvcsd = tty->driver_data;
532 unsigned long flags;
533
534 spin_lock_irqsave(&hvcsd->lock, flags);
535 vio_disable_interrupts(hvcsd->vdev);
536 spin_unlock_irqrestore(&hvcsd->lock, flags);
537}
538
539
540
541
542
543
544static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
545{
546 struct hvcs_struct *hvcsd = dev_instance;
547
548 spin_lock(&hvcsd->lock);
549 vio_disable_interrupts(hvcsd->vdev);
550 hvcsd->todo_mask |= HVCS_SCHED_READ;
551 spin_unlock(&hvcsd->lock);
552 hvcs_kick();
553
554 return IRQ_HANDLED;
555}
556
557
558static void hvcs_try_write(struct hvcs_struct *hvcsd)
559{
560 uint32_t unit_address = hvcsd->vdev->unit_address;
561 struct tty_struct *tty = hvcsd->port.tty;
562 int sent;
563
564 if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
565
566 sent = hvc_put_chars(unit_address,
567 &hvcsd->buffer[0],
568 hvcsd->chars_in_buffer );
569 if (sent > 0) {
570 hvcsd->chars_in_buffer = 0;
571
572 hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
573
574
575
576
577
578
579
580
581 if (tty) {
582 tty_wakeup(tty);
583 }
584 }
585 }
586}
587
588static int hvcs_io(struct hvcs_struct *hvcsd)
589{
590 uint32_t unit_address;
591 struct tty_struct *tty;
592 char buf[HVCS_BUFF_LEN] __ALIGNED__;
593 unsigned long flags;
594 int got = 0;
595
596 spin_lock_irqsave(&hvcsd->lock, flags);
597
598 unit_address = hvcsd->vdev->unit_address;
599 tty = hvcsd->port.tty;
600
601 hvcs_try_write(hvcsd);
602
603 if (!tty || test_bit(TTY_THROTTLED, &tty->flags)) {
604 hvcsd->todo_mask &= ~(HVCS_READ_MASK);
605 goto bail;
606 } else if (!(hvcsd->todo_mask & (HVCS_READ_MASK)))
607 goto bail;
608
609
610 hvcsd->todo_mask &= ~(HVCS_READ_MASK);
611
612 if (tty_buffer_request_room(&hvcsd->port, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
613 got = hvc_get_chars(unit_address,
614 &buf[0],
615 HVCS_BUFF_LEN);
616 tty_insert_flip_string(&hvcsd->port, buf, got);
617 }
618
619
620 if (got)
621 hvcsd->todo_mask |= HVCS_QUICK_READ;
622
623 spin_unlock_irqrestore(&hvcsd->lock, flags);
624
625 if(got)
626 tty_flip_buffer_push(&hvcsd->port);
627
628 if (!got) {
629
630 spin_lock_irqsave(&hvcsd->lock, flags);
631 vio_enable_interrupts(hvcsd->vdev);
632 spin_unlock_irqrestore(&hvcsd->lock, flags);
633 }
634
635 return hvcsd->todo_mask;
636
637 bail:
638 spin_unlock_irqrestore(&hvcsd->lock, flags);
639 return hvcsd->todo_mask;
640}
641
642static int khvcsd(void *unused)
643{
644 struct hvcs_struct *hvcsd;
645 int hvcs_todo_mask;
646
647 __set_current_state(TASK_RUNNING);
648
649 do {
650 hvcs_todo_mask = 0;
651 hvcs_kicked = 0;
652 wmb();
653
654 spin_lock(&hvcs_structs_lock);
655 list_for_each_entry(hvcsd, &hvcs_structs, next) {
656 hvcs_todo_mask |= hvcs_io(hvcsd);
657 }
658 spin_unlock(&hvcs_structs_lock);
659
660
661
662
663
664
665 if (hvcs_todo_mask & (HVCS_TRY_WRITE | HVCS_QUICK_READ)) {
666 yield();
667 continue;
668 }
669
670 set_current_state(TASK_INTERRUPTIBLE);
671 if (!hvcs_kicked)
672 schedule();
673 __set_current_state(TASK_RUNNING);
674 } while (!kthread_should_stop());
675
676 return 0;
677}
678
679static struct vio_device_id hvcs_driver_table[] = {
680 {"serial-server", "hvterm2"},
681 { "", "" }
682};
683MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
684
685static void hvcs_return_index(int index)
686{
687
688 if (!hvcs_index_list)
689 return;
690 if (index < 0 || index >= hvcs_index_count)
691 return;
692 if (hvcs_index_list[index] == -1)
693 return;
694 else
695 hvcs_index_list[index] = -1;
696}
697
698static void hvcs_destruct_port(struct tty_port *p)
699{
700 struct hvcs_struct *hvcsd = container_of(p, struct hvcs_struct, port);
701 struct vio_dev *vdev;
702 unsigned long flags;
703
704 spin_lock(&hvcs_structs_lock);
705 spin_lock_irqsave(&hvcsd->lock, flags);
706
707
708 list_del(&(hvcsd->next));
709
710 if (hvcsd->connected == 1) {
711 hvcs_partner_free(hvcsd);
712 printk(KERN_INFO "HVCS: Closed vty-server@%X and"
713 " partner vty@%X:%d connection.\n",
714 hvcsd->vdev->unit_address,
715 hvcsd->p_unit_address,
716 (uint32_t)hvcsd->p_partition_ID);
717 }
718 printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
719 hvcsd->vdev->unit_address);
720
721 vdev = hvcsd->vdev;
722 hvcsd->vdev = NULL;
723
724 hvcsd->p_unit_address = 0;
725 hvcsd->p_partition_ID = 0;
726 hvcs_return_index(hvcsd->index);
727 memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
728
729 spin_unlock_irqrestore(&hvcsd->lock, flags);
730 spin_unlock(&hvcs_structs_lock);
731
732 sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
733
734 kfree(hvcsd);
735}
736
737static const struct tty_port_operations hvcs_port_ops = {
738 .destruct = hvcs_destruct_port,
739};
740
741static int hvcs_get_index(void)
742{
743 int i;
744
745 if (!hvcs_index_list) {
746 printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
747 return -EFAULT;
748 }
749
750 for(i = 0; i < hvcs_index_count; i++) {
751 if (hvcs_index_list[i] == -1) {
752 hvcs_index_list[i] = 0;
753 return i;
754 }
755 }
756 return -1;
757}
758
759static int hvcs_probe(
760 struct vio_dev *dev,
761 const struct vio_device_id *id)
762{
763 struct hvcs_struct *hvcsd;
764 int index, rc;
765 int retval;
766
767 if (!dev || !id) {
768 printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
769 return -EPERM;
770 }
771
772
773 rc = hvcs_initialize();
774 if (rc) {
775 pr_err("HVCS: Failed to initialize core driver.\n");
776 return rc;
777 }
778
779
780 index = hvcs_get_index();
781 if (index < 0) {
782 return -EFAULT;
783 }
784
785 hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL);
786 if (!hvcsd)
787 return -ENODEV;
788
789 tty_port_init(&hvcsd->port);
790 hvcsd->port.ops = &hvcs_port_ops;
791 spin_lock_init(&hvcsd->lock);
792
793 hvcsd->vdev = dev;
794 dev_set_drvdata(&dev->dev, hvcsd);
795
796 hvcsd->index = index;
797
798
799 hvcsd->chars_in_buffer = 0;
800 hvcsd->todo_mask = 0;
801 hvcsd->connected = 0;
802
803
804
805
806
807 if (hvcs_get_pi(hvcsd)) {
808 printk(KERN_ERR "HVCS: Failed to fetch partner"
809 " info for vty-server@%X on device probe.\n",
810 hvcsd->vdev->unit_address);
811 }
812
813
814
815
816
817
818 spin_lock(&hvcs_structs_lock);
819 list_add_tail(&(hvcsd->next), &hvcs_structs);
820 spin_unlock(&hvcs_structs_lock);
821
822 retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group);
823 if (retval) {
824 printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n",
825 hvcsd->vdev->unit_address);
826 return retval;
827 }
828
829 printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
830
831
832
833
834
835 return 0;
836}
837
838static int hvcs_remove(struct vio_dev *dev)
839{
840 struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
841 unsigned long flags;
842 struct tty_struct *tty;
843
844 if (!hvcsd)
845 return -ENODEV;
846
847
848
849 spin_lock_irqsave(&hvcsd->lock, flags);
850
851 tty = hvcsd->port.tty;
852
853 spin_unlock_irqrestore(&hvcsd->lock, flags);
854
855
856
857
858
859 tty_port_put(&hvcsd->port);
860
861
862
863
864
865
866 if (tty)
867 tty_hangup(tty);
868
869 printk(KERN_INFO "HVCS: vty-server@%X removed from the"
870 " vio bus.\n", dev->unit_address);
871 return 0;
872};
873
874static struct vio_driver hvcs_vio_driver = {
875 .id_table = hvcs_driver_table,
876 .probe = hvcs_probe,
877 .remove = hvcs_remove,
878 .name = hvcs_driver_name,
879};
880
881
882static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
883{
884 hvcsd->p_unit_address = pi->unit_address;
885 hvcsd->p_partition_ID = pi->partition_ID;
886
887
888 strlcpy(&hvcsd->p_location_code[0],
889 &pi->location_code[0], sizeof(hvcsd->p_location_code));
890}
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905static int hvcs_get_pi(struct hvcs_struct *hvcsd)
906{
907 struct hvcs_partner_info *pi;
908 uint32_t unit_address = hvcsd->vdev->unit_address;
909 struct list_head head;
910 int retval;
911
912 spin_lock(&hvcs_pi_lock);
913 if (!hvcs_pi_buff) {
914 spin_unlock(&hvcs_pi_lock);
915 return -EFAULT;
916 }
917 retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
918 spin_unlock(&hvcs_pi_lock);
919 if (retval) {
920 printk(KERN_ERR "HVCS: Failed to fetch partner"
921 " info for vty-server@%x.\n", unit_address);
922 return retval;
923 }
924
925
926 hvcsd->p_unit_address = 0;
927 hvcsd->p_partition_ID = 0;
928
929 list_for_each_entry(pi, &head, node)
930 hvcs_set_pi(pi, hvcsd);
931
932 hvcs_free_partner_info(&head);
933 return 0;
934}
935
936
937
938
939
940static int hvcs_rescan_devices_list(void)
941{
942 struct hvcs_struct *hvcsd;
943 unsigned long flags;
944
945 spin_lock(&hvcs_structs_lock);
946
947 list_for_each_entry(hvcsd, &hvcs_structs, next) {
948 spin_lock_irqsave(&hvcsd->lock, flags);
949 hvcs_get_pi(hvcsd);
950 spin_unlock_irqrestore(&hvcsd->lock, flags);
951 }
952
953 spin_unlock(&hvcs_structs_lock);
954
955 return 0;
956}
957
958
959
960
961
962
963static int hvcs_has_pi(struct hvcs_struct *hvcsd)
964{
965 if ((!hvcsd->p_unit_address) || (!hvcsd->p_partition_ID))
966 return 0;
967 return 1;
968}
969
970
971
972
973
974
975
976static int hvcs_partner_connect(struct hvcs_struct *hvcsd)
977{
978 int retval;
979 unsigned int unit_address = hvcsd->vdev->unit_address;
980
981
982
983
984
985
986
987
988 retval = hvcs_register_connection(unit_address,
989 hvcsd->p_partition_ID,
990 hvcsd->p_unit_address);
991 if (!retval) {
992 hvcsd->connected = 1;
993 return 0;
994 } else if (retval != -EINVAL)
995 return retval;
996
997
998
999
1000
1001 if (hvcs_get_pi(hvcsd))
1002 return -ENOMEM;
1003
1004 if (!hvcs_has_pi(hvcsd))
1005 return -ENODEV;
1006
1007 retval = hvcs_register_connection(unit_address,
1008 hvcsd->p_partition_ID,
1009 hvcsd->p_unit_address);
1010 if (retval != -EINVAL) {
1011 hvcsd->connected = 1;
1012 return retval;
1013 }
1014
1015
1016
1017
1018
1019
1020
1021 printk(KERN_INFO "HVCS: vty-server or partner"
1022 " vty is busy. Try again later.\n");
1023 return -EBUSY;
1024}
1025
1026
1027static void hvcs_partner_free(struct hvcs_struct *hvcsd)
1028{
1029 int retval;
1030 do {
1031 retval = hvcs_free_connection(hvcsd->vdev->unit_address);
1032 } while (retval == -EBUSY);
1033 hvcsd->connected = 0;
1034}
1035
1036
1037static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
1038 unsigned int irq, struct vio_dev *vdev)
1039{
1040 unsigned long flags;
1041 int rc;
1042
1043
1044
1045
1046
1047 rc = request_irq(irq, &hvcs_handle_interrupt, 0, "ibmhvcs", hvcsd);
1048 if (!rc) {
1049
1050
1051
1052
1053 if (vio_enable_interrupts(vdev) == H_SUCCESS)
1054 return 0;
1055 else {
1056 printk(KERN_ERR "HVCS: int enable failed for"
1057 " vty-server@%X.\n", unit_address);
1058 free_irq(irq, hvcsd);
1059 }
1060 } else
1061 printk(KERN_ERR "HVCS: irq req failed for"
1062 " vty-server@%X.\n", unit_address);
1063
1064 spin_lock_irqsave(&hvcsd->lock, flags);
1065 hvcs_partner_free(hvcsd);
1066 spin_unlock_irqrestore(&hvcsd->lock, flags);
1067
1068 return rc;
1069
1070}
1071
1072
1073
1074
1075
1076
1077
1078
1079static struct hvcs_struct *hvcs_get_by_index(int index)
1080{
1081 struct hvcs_struct *hvcsd;
1082 unsigned long flags;
1083
1084 spin_lock(&hvcs_structs_lock);
1085 list_for_each_entry(hvcsd, &hvcs_structs, next) {
1086 spin_lock_irqsave(&hvcsd->lock, flags);
1087 if (hvcsd->index == index) {
1088 tty_port_get(&hvcsd->port);
1089 spin_unlock_irqrestore(&hvcsd->lock, flags);
1090 spin_unlock(&hvcs_structs_lock);
1091 return hvcsd;
1092 }
1093 spin_unlock_irqrestore(&hvcsd->lock, flags);
1094 }
1095 spin_unlock(&hvcs_structs_lock);
1096
1097 return NULL;
1098}
1099
1100static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
1101{
1102 struct hvcs_struct *hvcsd;
1103 struct vio_dev *vdev;
1104 unsigned long unit_address, flags;
1105 unsigned int irq;
1106 int retval;
1107
1108
1109
1110
1111
1112 hvcsd = hvcs_get_by_index(tty->index);
1113 if (!hvcsd) {
1114 printk(KERN_WARNING "HVCS: open failed, no device associated"
1115 " with tty->index %d.\n", tty->index);
1116 return -ENODEV;
1117 }
1118
1119 spin_lock_irqsave(&hvcsd->lock, flags);
1120
1121 if (hvcsd->connected == 0) {
1122 retval = hvcs_partner_connect(hvcsd);
1123 if (retval) {
1124 spin_unlock_irqrestore(&hvcsd->lock, flags);
1125 printk(KERN_WARNING "HVCS: partner connect failed.\n");
1126 goto err_put;
1127 }
1128 }
1129
1130 hvcsd->port.count = 0;
1131 hvcsd->port.tty = tty;
1132 tty->driver_data = hvcsd;
1133
1134 memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
1135
1136
1137
1138
1139
1140 irq = hvcsd->vdev->irq;
1141 vdev = hvcsd->vdev;
1142 unit_address = hvcsd->vdev->unit_address;
1143
1144 hvcsd->todo_mask |= HVCS_SCHED_READ;
1145 spin_unlock_irqrestore(&hvcsd->lock, flags);
1146
1147
1148
1149
1150
1151 retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);
1152 if (retval) {
1153 printk(KERN_WARNING "HVCS: enable device failed.\n");
1154 goto err_put;
1155 }
1156
1157 retval = tty_port_install(&hvcsd->port, driver, tty);
1158 if (retval)
1159 goto err_irq;
1160
1161 return 0;
1162err_irq:
1163 spin_lock_irqsave(&hvcsd->lock, flags);
1164 vio_disable_interrupts(hvcsd->vdev);
1165 spin_unlock_irqrestore(&hvcsd->lock, flags);
1166 free_irq(irq, hvcsd);
1167err_put:
1168 tty_port_put(&hvcsd->port);
1169
1170 return retval;
1171}
1172
1173
1174
1175
1176
1177static int hvcs_open(struct tty_struct *tty, struct file *filp)
1178{
1179 struct hvcs_struct *hvcsd = tty->driver_data;
1180 unsigned long flags;
1181
1182 spin_lock_irqsave(&hvcsd->lock, flags);
1183 hvcsd->port.count++;
1184 hvcsd->todo_mask |= HVCS_SCHED_READ;
1185 spin_unlock_irqrestore(&hvcsd->lock, flags);
1186
1187 hvcs_kick();
1188
1189 printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
1190 hvcsd->vdev->unit_address );
1191
1192 return 0;
1193}
1194
1195static void hvcs_close(struct tty_struct *tty, struct file *filp)
1196{
1197 struct hvcs_struct *hvcsd;
1198 unsigned long flags;
1199 int irq;
1200
1201
1202
1203
1204
1205 if (tty_hung_up_p(filp))
1206 return;
1207
1208
1209
1210
1211
1212
1213 if (!tty->driver_data)
1214 return;
1215
1216 hvcsd = tty->driver_data;
1217
1218 spin_lock_irqsave(&hvcsd->lock, flags);
1219 if (--hvcsd->port.count == 0) {
1220
1221 vio_disable_interrupts(hvcsd->vdev);
1222
1223
1224
1225
1226
1227
1228 hvcsd->port.tty = NULL;
1229
1230 irq = hvcsd->vdev->irq;
1231 spin_unlock_irqrestore(&hvcsd->lock, flags);
1232
1233 tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
1234
1235
1236
1237
1238
1239
1240 tty->driver_data = NULL;
1241
1242 free_irq(irq, hvcsd);
1243 return;
1244 } else if (hvcsd->port.count < 0) {
1245 printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
1246 " is missmanaged.\n",
1247 hvcsd->vdev->unit_address, hvcsd->port.count);
1248 }
1249
1250 spin_unlock_irqrestore(&hvcsd->lock, flags);
1251}
1252
1253static void hvcs_cleanup(struct tty_struct * tty)
1254{
1255 struct hvcs_struct *hvcsd = tty->driver_data;
1256
1257 tty_port_put(&hvcsd->port);
1258}
1259
1260static void hvcs_hangup(struct tty_struct * tty)
1261{
1262 struct hvcs_struct *hvcsd = tty->driver_data;
1263 unsigned long flags;
1264 int temp_open_count;
1265 int irq;
1266
1267 spin_lock_irqsave(&hvcsd->lock, flags);
1268
1269 temp_open_count = hvcsd->port.count;
1270
1271
1272
1273
1274
1275
1276 vio_disable_interrupts(hvcsd->vdev);
1277
1278 hvcsd->todo_mask = 0;
1279
1280
1281 tty->driver_data = NULL;
1282 hvcsd->port.tty = NULL;
1283
1284 hvcsd->port.count = 0;
1285
1286
1287
1288 memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
1289 hvcsd->chars_in_buffer = 0;
1290
1291 irq = hvcsd->vdev->irq;
1292
1293 spin_unlock_irqrestore(&hvcsd->lock, flags);
1294
1295 free_irq(irq, hvcsd);
1296
1297
1298
1299
1300
1301
1302 while(temp_open_count) {
1303 --temp_open_count;
1304
1305
1306
1307
1308
1309 tty_port_put(&hvcsd->port);
1310 }
1311}
1312
1313
1314
1315
1316
1317
1318
1319
1320static int hvcs_write(struct tty_struct *tty,
1321 const unsigned char *buf, int count)
1322{
1323 struct hvcs_struct *hvcsd = tty->driver_data;
1324 unsigned int unit_address;
1325 const unsigned char *charbuf;
1326 unsigned long flags;
1327 int total_sent = 0;
1328 int tosend = 0;
1329 int result = 0;
1330
1331
1332
1333
1334
1335 if (!hvcsd)
1336 return -ENODEV;
1337
1338
1339 if (count > HVCS_MAX_FROM_USER) {
1340 printk(KERN_WARNING "HVCS write: count being truncated to"
1341 " HVCS_MAX_FROM_USER.\n");
1342 count = HVCS_MAX_FROM_USER;
1343 }
1344
1345 charbuf = buf;
1346
1347 spin_lock_irqsave(&hvcsd->lock, flags);
1348
1349
1350
1351
1352
1353
1354
1355 if (hvcsd->port.count <= 0) {
1356 spin_unlock_irqrestore(&hvcsd->lock, flags);
1357 return -ENODEV;
1358 }
1359
1360 unit_address = hvcsd->vdev->unit_address;
1361
1362 while (count > 0) {
1363 tosend = min(count, (HVCS_BUFF_LEN - hvcsd->chars_in_buffer));
1364
1365
1366
1367
1368 if (!tosend)
1369 break;
1370
1371 memcpy(&hvcsd->buffer[hvcsd->chars_in_buffer],
1372 &charbuf[total_sent],
1373 tosend);
1374
1375 hvcsd->chars_in_buffer += tosend;
1376
1377 result = 0;
1378
1379
1380
1381
1382
1383
1384 if (!(hvcsd->todo_mask & HVCS_TRY_WRITE))
1385
1386 result = hvc_put_chars(unit_address,
1387 &hvcsd->buffer[0],
1388 hvcsd->chars_in_buffer);
1389
1390
1391
1392
1393
1394
1395 total_sent+=tosend;
1396 count-=tosend;
1397 if (result == 0) {
1398 hvcsd->todo_mask |= HVCS_TRY_WRITE;
1399 hvcs_kick();
1400 break;
1401 }
1402
1403 hvcsd->chars_in_buffer = 0;
1404
1405
1406
1407
1408 if (result < 0)
1409 break;
1410 }
1411
1412 spin_unlock_irqrestore(&hvcsd->lock, flags);
1413
1414 if (result == -1)
1415 return -EIO;
1416 else
1417 return total_sent;
1418}
1419
1420
1421
1422
1423
1424
1425static int hvcs_write_room(struct tty_struct *tty)
1426{
1427 struct hvcs_struct *hvcsd = tty->driver_data;
1428
1429 if (!hvcsd || hvcsd->port.count <= 0)
1430 return 0;
1431
1432 return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
1433}
1434
1435static int hvcs_chars_in_buffer(struct tty_struct *tty)
1436{
1437 struct hvcs_struct *hvcsd = tty->driver_data;
1438
1439 return hvcsd->chars_in_buffer;
1440}
1441
1442static const struct tty_operations hvcs_ops = {
1443 .install = hvcs_install,
1444 .open = hvcs_open,
1445 .close = hvcs_close,
1446 .cleanup = hvcs_cleanup,
1447 .hangup = hvcs_hangup,
1448 .write = hvcs_write,
1449 .write_room = hvcs_write_room,
1450 .chars_in_buffer = hvcs_chars_in_buffer,
1451 .unthrottle = hvcs_unthrottle,
1452 .throttle = hvcs_throttle,
1453};
1454
1455static int hvcs_alloc_index_list(int n)
1456{
1457 int i;
1458
1459 hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
1460 if (!hvcs_index_list)
1461 return -ENOMEM;
1462 hvcs_index_count = n;
1463 for (i = 0; i < hvcs_index_count; i++)
1464 hvcs_index_list[i] = -1;
1465 return 0;
1466}
1467
1468static void hvcs_free_index_list(void)
1469{
1470
1471 kfree(hvcs_index_list);
1472 hvcs_index_list = NULL;
1473 hvcs_index_count = 0;
1474}
1475
1476static int hvcs_initialize(void)
1477{
1478 int rc, num_ttys_to_alloc;
1479
1480 mutex_lock(&hvcs_init_mutex);
1481 if (hvcs_task) {
1482 mutex_unlock(&hvcs_init_mutex);
1483 return 0;
1484 }
1485
1486
1487 if (hvcs_parm_num_devs <= 0 ||
1488 (hvcs_parm_num_devs > HVCS_MAX_SERVER_ADAPTERS)) {
1489 num_ttys_to_alloc = HVCS_DEFAULT_SERVER_ADAPTERS;
1490 } else
1491 num_ttys_to_alloc = hvcs_parm_num_devs;
1492
1493 hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
1494 if (!hvcs_tty_driver) {
1495 mutex_unlock(&hvcs_init_mutex);
1496 return -ENOMEM;
1497 }
1498
1499 if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
1500 rc = -ENOMEM;
1501 goto index_fail;
1502 }
1503
1504 hvcs_tty_driver->driver_name = hvcs_driver_name;
1505 hvcs_tty_driver->name = hvcs_device_node;
1506
1507
1508
1509
1510
1511
1512 hvcs_tty_driver->minor_start = HVCS_MINOR_START;
1513 hvcs_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
1514
1515
1516
1517
1518
1519
1520 hvcs_tty_driver->init_termios = hvcs_tty_termios;
1521 hvcs_tty_driver->flags = TTY_DRIVER_REAL_RAW;
1522
1523 tty_set_operations(hvcs_tty_driver, &hvcs_ops);
1524
1525
1526
1527
1528
1529 if (tty_register_driver(hvcs_tty_driver)) {
1530 printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");
1531 rc = -EIO;
1532 goto register_fail;
1533 }
1534
1535 hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL);
1536 if (!hvcs_pi_buff) {
1537 rc = -ENOMEM;
1538 goto buff_alloc_fail;
1539 }
1540
1541 hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
1542 if (IS_ERR(hvcs_task)) {
1543 printk(KERN_ERR "HVCS: khvcsd creation failed.\n");
1544 rc = -EIO;
1545 goto kthread_fail;
1546 }
1547 mutex_unlock(&hvcs_init_mutex);
1548 return 0;
1549
1550kthread_fail:
1551 free_page((unsigned long)hvcs_pi_buff);
1552buff_alloc_fail:
1553 tty_unregister_driver(hvcs_tty_driver);
1554register_fail:
1555 hvcs_free_index_list();
1556index_fail:
1557 put_tty_driver(hvcs_tty_driver);
1558 hvcs_tty_driver = NULL;
1559 mutex_unlock(&hvcs_init_mutex);
1560 return rc;
1561}
1562
1563static int __init hvcs_module_init(void)
1564{
1565 int rc = vio_register_driver(&hvcs_vio_driver);
1566 if (rc) {
1567 printk(KERN_ERR "HVCS: can't register vio driver\n");
1568 return rc;
1569 }
1570
1571 pr_info("HVCS: Driver registered.\n");
1572
1573
1574
1575
1576 rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
1577 if (rc)
1578 pr_warning("HVCS: Failed to create rescan file (err %d)\n", rc);
1579
1580 return 0;
1581}
1582
1583static void __exit hvcs_module_exit(void)
1584{
1585
1586
1587
1588
1589 vio_unregister_driver(&hvcs_vio_driver);
1590 if (!hvcs_task)
1591 return;
1592
1593
1594
1595
1596
1597 kthread_stop(hvcs_task);
1598
1599 spin_lock(&hvcs_pi_lock);
1600 free_page((unsigned long)hvcs_pi_buff);
1601 hvcs_pi_buff = NULL;
1602 spin_unlock(&hvcs_pi_lock);
1603
1604 driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
1605
1606 tty_unregister_driver(hvcs_tty_driver);
1607
1608 hvcs_free_index_list();
1609
1610 put_tty_driver(hvcs_tty_driver);
1611
1612 printk(KERN_INFO "HVCS: driver module removed.\n");
1613}
1614
1615module_init(hvcs_module_init);
1616module_exit(hvcs_module_exit);
1617