OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [hvcs.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * IBM eServer Hypervisor Virtual Console Server Device Driver
3
 * Copyright (C) 2003, 2004 IBM Corp.
4
 *  Ryan S. Arnold (rsa@us.ibm.com)
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19
 *
20
 * Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>
21
 *
22
 * This is the device driver for the IBM Hypervisor Virtual Console Server,
23
 * "hvcs".  The IBM hvcs provides a tty driver interface to allow Linux
24
 * user space applications access to the system consoles of logically
25
 * partitioned operating systems, e.g. Linux, running on the same partitioned
26
 * Power5 ppc64 system.  Physical hardware consoles per partition are not
27
 * practical on this hardware so system consoles are accessed by this driver
28
 * using inter-partition firmware interfaces to virtual terminal devices.
29
 *
30
 * A vty is known to the HMC as a "virtual serial server adapter".  It is a
31
 * virtual terminal device that is created by firmware upon partition creation
32
 * to act as a partitioned OS's console device.
33
 *
34
 * Firmware dynamically (via hotplug) exposes vty-servers to a running ppc64
35
 * Linux system upon their creation by the HMC or their exposure during boot.
36
 * The non-user interactive backend of this driver is implemented as a vio
37
 * device driver so that it can receive notification of vty-server lifetimes
38
 * after it registers with the vio bus to handle vty-server probe and remove
39
 * callbacks.
40
 *
41
 * Many vty-servers can be configured to connect to one vty, but a vty can
42
 * only be actively connected to by a single vty-server, in any manner, at one
43
 * time.  If the HMC is currently hosting the console for a target Linux
44
 * partition; attempts to open the tty device to the partition's console using
45
 * the hvcs on any partition will return -EBUSY with every open attempt until
46
 * the HMC frees the connection between its vty-server and the desired
47
 * partition's vty device.  Conversely, a vty-server may only be connected to
48
 * a single vty at one time even though it may have several configured vty
49
 * partner possibilities.
50
 *
51
 * Firmware does not provide notification of vty partner changes to this
52
 * driver.  This means that an HMC Super Admin may add or remove partner vtys
53
 * from a vty-server's partner list but the changes will not be signaled to
54
 * the vty-server.  Firmware only notifies the driver when a vty-server is
55
 * added or removed from the system.  To compensate for this deficiency, this
56
 * driver implements a sysfs update attribute which provides a method for
57
 * rescanning partner information upon a user's request.
58
 *
59
 * Each vty-server, prior to being exposed to this driver is reference counted
60
 * using the 2.6 Linux kernel kobject construct.  This kobject is also used by
61
 * the vio bus to provide a vio device sysfs entry that this driver attaches
62
 * device specific attributes to, including partner information.  The vio bus
63
 * framework also provides a sysfs entry for each vio driver.  The hvcs driver
64
 * provides driver attributes in this entry.
65
 *
66
 * For direction on installation and usage of this driver please reference
67
 * Documentation/powerpc/hvcs.txt.
68
 */
69
 
70
#include <linux/device.h>
71
#include <linux/init.h>
72
#include <linux/interrupt.h>
73
#include <linux/kernel.h>
74
#include <linux/kobject.h>
75
#include <linux/kthread.h>
76
#include <linux/list.h>
77
#include <linux/major.h>
78
#include <linux/module.h>
79
#include <linux/moduleparam.h>
80
#include <linux/sched.h>
81
#include <linux/spinlock.h>
82
#include <linux/stat.h>
83
#include <linux/tty.h>
84
#include <linux/tty_flip.h>
85
#include <asm/hvconsole.h>
86
#include <asm/hvcserver.h>
87
#include <asm/uaccess.h>
88
#include <asm/vio.h>
89
 
90
/*
91
 * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).
92
 * Removed braces around single statements following conditionals.  Removed '=
93
 * 0' after static int declarations since these default to zero.  Removed
94
 * list_for_each_safe() and replaced with list_for_each_entry() in
95
 * hvcs_get_by_index().  The 'safe' version is un-needed now that the driver is
96
 * using spinlocks.  Changed spin_lock_irqsave() to spin_lock() when locking
97
 * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int
98
 * handler.  Initialized hvcs_structs_lock and hvcs_pi_lock to
99
 * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init().
100
 * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the
101
 * list traversals from a deletion.  Removed '= NULL' from pointer declaration
102
 * statements since they are initialized NULL by default.  Removed wmb()
103
 * instances from hvcs_try_write().  They probably aren't needed with locking in
104
 * place.  Added check and cleanup for hvcs_pi_buff = kmalloc() in
105
 * hvcs_module_init().  Exposed hvcs_struct.index via a sysfs attribute so that
106
 * the coupling between /dev/hvcs* and a vty-server can be automatically
107
 * determined.  Moved kobject_put() in hvcs_open outside of the
108
 * spin_unlock_irqrestore().
109
 *
110
 * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it
111
 * align with how the tty layer always assigns the lowest index available.  This
112
 * change resulted in a list of ints that denotes which indexes are available.
113
 * Device additions and removals use the new hvcs_get_index() and
114
 * hvcs_return_index() helper functions.  The list is created with
115
 * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list().
116
 * Without these fixes hotplug vty-server adapter support goes crazy with this
117
 * driver if the user removes a vty-server adapter.  Moved free_irq() outside of
118
 * the hvcs_final_close() function in order to get it out of the spinlock.
119
 * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping
120
 * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from
121
 * include/asm-powerpc/hvcserver.h
122
 *
123
 * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to
124
 * prevent possible lockup with realtime scheduling as similarily pointed out by
125
 * akpm in hvc_console.  Changed resulted in the removal of hvcs_final_close()
126
 * to reorder cleanup operations and prevent discarding of pending data during
127
 * an hvcs_close().  Removed spinlock protection of hvcs_struct data members in
128
 * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed.
129
 */
130
 
131
#define HVCS_DRIVER_VERSION "1.3.3"
132
 
133
MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
134
MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
135
MODULE_LICENSE("GPL");
136
MODULE_VERSION(HVCS_DRIVER_VERSION);
137
 
138
/*
139
 * Wait this long per iteration while trying to push buffered data to the
140
 * hypervisor before allowing the tty to complete a close operation.
141
 */
142
#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
143
 
144
/*
145
 * Since the Linux TTY code does not currently (2-04-2004) support dynamic
146
 * addition of tty derived devices and we shouldn't allocate thousands of
147
 * tty_device pointers when the number of vty-server & vty partner connections
148
 * will most often be much lower than this, we'll arbitrarily allocate
149
 * HVCS_DEFAULT_SERVER_ADAPTERS tty_structs and cdev's by default when we
150
 * register the tty_driver. This can be overridden using an insmod parameter.
151
 */
152
#define HVCS_DEFAULT_SERVER_ADAPTERS    64
153
 
154
/*
155
 * The user can't insmod with more than HVCS_MAX_SERVER_ADAPTERS hvcs device
156
 * nodes as a sanity check.  Theoretically there can be over 1 Billion
157
 * vty-server & vty partner connections.
158
 */
159
#define HVCS_MAX_SERVER_ADAPTERS        1024
160
 
161
/*
162
 * We let Linux assign us a major number and we start the minors at zero.  There
163
 * is no intuitive mapping between minor number and the target vty-server
164
 * adapter except that each new vty-server adapter is always assigned to the
165
 * smallest minor number available.
166
 */
167
#define HVCS_MINOR_START        0
168
 
169
/*
170
 * The hcall interface involves putting 8 chars into each of two registers.
171
 * We load up those 2 registers (in arch/powerpc/platforms/pseries/hvconsole.c)
172
 * by casting char[16] to long[2].  It would work without __ALIGNED__, but a
173
 * little (tiny) bit slower because an unaligned load is slower than aligned
174
 * load.
175
 */
176
#define __ALIGNED__     __attribute__((__aligned__(8)))
177
 
178
/*
179
 * How much data can firmware send with each hvc_put_chars()?  Maybe this
180
 * should be moved into an architecture specific area.
181
 */
182
#define HVCS_BUFF_LEN   16
183
 
184
/*
185
 * This is the maximum amount of data we'll let the user send us (hvcs_write) at
186
 * once in a chunk as a sanity check.
187
 */
188
#define HVCS_MAX_FROM_USER      4096
189
 
190
/*
191
 * Be careful when adding flags to this line discipline.  Don't add anything
192
 * that will cause echoing or we'll go into recursive loop echoing chars back
193
 * and forth with the console drivers.
194
 */
195
static struct ktermios hvcs_tty_termios = {
196
        .c_iflag = IGNBRK | IGNPAR,
197
        .c_oflag = OPOST,
198
        .c_cflag = B38400 | CS8 | CREAD | HUPCL,
199
        .c_cc = INIT_C_CC,
200
        .c_ispeed = 38400,
201
        .c_ospeed = 38400
202
};
203
 
204
/*
205
 * This value is used to take the place of a command line parameter when the
206
 * module is inserted.  It starts as -1 and stays as such if the user doesn't
207
 * specify a module insmod parameter.  If they DO specify one then it is set to
208
 * the value of the integer passed in.
209
 */
210
static int hvcs_parm_num_devs = -1;
211
module_param(hvcs_parm_num_devs, int, 0);
212
 
213
static const char hvcs_driver_name[] = "hvcs";
214
static const char hvcs_device_node[] = "hvcs";
215
static const char hvcs_driver_string[]
216
        = "IBM hvcs (Hypervisor Virtual Console Server) Driver";
217
 
218
/* Status of partner info rescan triggered via sysfs. */
219
static int hvcs_rescan_status;
220
 
221
static struct tty_driver *hvcs_tty_driver;
222
 
223
/*
224
 * In order to be somewhat sane this driver always associates the hvcs_struct
225
 * index element with the numerically equal tty->index.  This means that a
226
 * hotplugged vty-server adapter will always map to the lowest index valued
227
 * device node.  If vty-servers were hotplug removed from the system and then
228
 * new ones added the new vty-server may have the largest slot number of all
229
 * the vty-server adapters in the partition but it may have the lowest dev node
230
 * index of all the adapters due to the hole left by the hotplug removed
231
 * adapter.  There are a set of functions provided to get the lowest index for
232
 * a new device as well as return the index to the list.  This list is allocated
233
 * with a number of elements equal to the number of device nodes requested when
234
 * the module was inserted.
235
 */
236
static int *hvcs_index_list;
237
 
238
/*
239
 * How large is the list?  This is kept for traversal since the list is
240
 * dynamically created.
241
 */
242
static int hvcs_index_count;
243
 
244
/*
245
 * Used by the khvcsd to pick up I/O operations when the kernel_thread is
246
 * already awake but potentially shifted to TASK_INTERRUPTIBLE state.
247
 */
248
static int hvcs_kicked;
249
 
250
/*
251
 * Use by the kthread construct for task operations like waking the sleeping
252
 * thread and stopping the kthread.
253
 */
254
static struct task_struct *hvcs_task;
255
 
256
/*
257
 * We allocate this for the use of all of the hvcs_structs when they fetch
258
 * partner info.
259
 */
260
static unsigned long *hvcs_pi_buff;
261
 
262
/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */
263
static DEFINE_SPINLOCK(hvcs_pi_lock);
264
 
265
/* One vty-server per hvcs_struct */
266
struct hvcs_struct {
267
        spinlock_t lock;
268
 
269
        /*
270
         * This index identifies this hvcs device as the complement to a
271
         * specific tty index.
272
         */
273
        unsigned int index;
274
 
275
        struct tty_struct *tty;
276
        unsigned int open_count;
277
 
278
        /*
279
         * Used to tell the driver kernel_thread what operations need to take
280
         * place upon this hvcs_struct instance.
281
         */
282
        int todo_mask;
283
 
284
        /*
285
         * This buffer is required so that when hvcs_write_room() reports that
286
         * it can send HVCS_BUFF_LEN characters that it will buffer the full
287
         * HVCS_BUFF_LEN characters if need be.  This is essential for opost
288
         * writes since they do not do high level buffering and expect to be
289
         * able to send what the driver commits to sending buffering
290
         * [e.g. tab to space conversions in n_tty.c opost()].
291
         */
292
        char buffer[HVCS_BUFF_LEN];
293
        int chars_in_buffer;
294
 
295
        /*
296
         * Any variable below the kobject is valid before a tty is connected and
297
         * stays valid after the tty is disconnected.  These shouldn't be
298
         * whacked until the koject refcount reaches zero though some entries
299
         * may be changed via sysfs initiatives.
300
         */
301
        struct kobject kobj; /* ref count & hvcs_struct lifetime */
302
        int connected; /* is the vty-server currently connected to a vty? */
303
        uint32_t p_unit_address; /* partner unit address */
304
        uint32_t p_partition_ID; /* partner partition ID */
305
        char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */
306
        struct list_head next; /* list management */
307
        struct vio_dev *vdev;
308
};
309
 
310
/* Required to back map a kobject to its containing object */
311
#define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
312
 
313
static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
314
static DEFINE_SPINLOCK(hvcs_structs_lock);
315
 
316
static void hvcs_unthrottle(struct tty_struct *tty);
317
static void hvcs_throttle(struct tty_struct *tty);
318
static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance);
319
 
320
static int hvcs_write(struct tty_struct *tty,
321
                const unsigned char *buf, int count);
322
static int hvcs_write_room(struct tty_struct *tty);
323
static int hvcs_chars_in_buffer(struct tty_struct *tty);
324
 
325
static int hvcs_has_pi(struct hvcs_struct *hvcsd);
326
static void hvcs_set_pi(struct hvcs_partner_info *pi,
327
                struct hvcs_struct *hvcsd);
328
static int hvcs_get_pi(struct hvcs_struct *hvcsd);
329
static int hvcs_rescan_devices_list(void);
330
 
331
static int hvcs_partner_connect(struct hvcs_struct *hvcsd);
332
static void hvcs_partner_free(struct hvcs_struct *hvcsd);
333
 
334
static int hvcs_enable_device(struct hvcs_struct *hvcsd,
335
                uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
336
 
337
static void destroy_hvcs_struct(struct kobject *kobj);
338
static int hvcs_open(struct tty_struct *tty, struct file *filp);
339
static void hvcs_close(struct tty_struct *tty, struct file *filp);
340
static void hvcs_hangup(struct tty_struct * tty);
341
 
342
static int __devinit hvcs_probe(struct vio_dev *dev,
343
                const struct vio_device_id *id);
344
static int __devexit hvcs_remove(struct vio_dev *dev);
345
static int __init hvcs_module_init(void);
346
static void __exit hvcs_module_exit(void);
347
 
348
#define HVCS_SCHED_READ 0x00000001
349
#define HVCS_QUICK_READ 0x00000002
350
#define HVCS_TRY_WRITE  0x00000004
351
#define HVCS_READ_MASK  (HVCS_SCHED_READ | HVCS_QUICK_READ)
352
 
353
static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
354
{
355
        return viod->dev.driver_data;
356
}
357
/* The sysfs interface for the driver and devices */
358
 
359
static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
360
{
361
        struct vio_dev *viod = to_vio_dev(dev);
362
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
363
        unsigned long flags;
364
        int retval;
365
 
366
        spin_lock_irqsave(&hvcsd->lock, flags);
367
        retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
368
        spin_unlock_irqrestore(&hvcsd->lock, flags);
369
        return retval;
370
}
371
static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
372
 
373
static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
374
{
375
        struct vio_dev *viod = to_vio_dev(dev);
376
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
377
        unsigned long flags;
378
        int retval;
379
 
380
        spin_lock_irqsave(&hvcsd->lock, flags);
381
        retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
382
        spin_unlock_irqrestore(&hvcsd->lock, flags);
383
        return retval;
384
}
385
static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
386
 
387
static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
388
                size_t count)
389
{
390
        /*
391
         * Don't need this feature at the present time because firmware doesn't
392
         * yet support multiple partners.
393
         */
394
        printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
395
        return -EPERM;
396
}
397
 
398
static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
399
{
400
        struct vio_dev *viod = to_vio_dev(dev);
401
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
402
        unsigned long flags;
403
        int retval;
404
 
405
        spin_lock_irqsave(&hvcsd->lock, flags);
406
        retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
407
        spin_unlock_irqrestore(&hvcsd->lock, flags);
408
        return retval;
409
}
410
 
411
static DEVICE_ATTR(current_vty,
412
        S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
413
 
414
static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
415
                size_t count)
416
{
417
        struct vio_dev *viod = to_vio_dev(dev);
418
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
419
        unsigned long flags;
420
 
421
        /* writing a '0' to this sysfs entry will result in the disconnect. */
422
        if (simple_strtol(buf, NULL, 0) != 0)
423
                return -EINVAL;
424
 
425
        spin_lock_irqsave(&hvcsd->lock, flags);
426
 
427
        if (hvcsd->open_count > 0) {
428
                spin_unlock_irqrestore(&hvcsd->lock, flags);
429
                printk(KERN_INFO "HVCS: vterm state unchanged.  "
430
                                "The hvcs device node is still in use.\n");
431
                return -EPERM;
432
        }
433
 
434
        if (hvcsd->connected == 0) {
435
                spin_unlock_irqrestore(&hvcsd->lock, flags);
436
                printk(KERN_INFO "HVCS: vterm state unchanged. The"
437
                                " vty-server is not connected to a vty.\n");
438
                return -EPERM;
439
        }
440
 
441
        hvcs_partner_free(hvcsd);
442
        printk(KERN_INFO "HVCS: Closed vty-server@%X and"
443
                        " partner vty@%X:%d connection.\n",
444
                        hvcsd->vdev->unit_address,
445
                        hvcsd->p_unit_address,
446
                        (uint32_t)hvcsd->p_partition_ID);
447
 
448
        spin_unlock_irqrestore(&hvcsd->lock, flags);
449
        return count;
450
}
451
 
452
static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
453
{
454
        struct vio_dev *viod = to_vio_dev(dev);
455
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
456
        unsigned long flags;
457
        int retval;
458
 
459
        spin_lock_irqsave(&hvcsd->lock, flags);
460
        retval = sprintf(buf, "%d\n", hvcsd->connected);
461
        spin_unlock_irqrestore(&hvcsd->lock, flags);
462
        return retval;
463
}
464
static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
465
                hvcs_vterm_state_show, hvcs_vterm_state_store);
466
 
467
static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
468
{
469
        struct vio_dev *viod = to_vio_dev(dev);
470
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
471
        unsigned long flags;
472
        int retval;
473
 
474
        spin_lock_irqsave(&hvcsd->lock, flags);
475
        retval = sprintf(buf, "%d\n", hvcsd->index);
476
        spin_unlock_irqrestore(&hvcsd->lock, flags);
477
        return retval;
478
}
479
 
480
static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
481
 
482
static struct attribute *hvcs_attrs[] = {
483
        &dev_attr_partner_vtys.attr,
484
        &dev_attr_partner_clcs.attr,
485
        &dev_attr_current_vty.attr,
486
        &dev_attr_vterm_state.attr,
487
        &dev_attr_index.attr,
488
        NULL,
489
};
490
 
491
static struct attribute_group hvcs_attr_group = {
492
        .attrs = hvcs_attrs,
493
};
494
 
495
static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf)
496
{
497
        /* A 1 means it is updating, a 0 means it is done updating */
498
        return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
499
}
500
 
501
static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf,
502
                size_t count)
503
{
504
        if ((simple_strtol(buf, NULL, 0) != 1)
505
                && (hvcs_rescan_status != 0))
506
                return -EINVAL;
507
 
508
        hvcs_rescan_status = 1;
509
        printk(KERN_INFO "HVCS: rescanning partner info for all"
510
                " vty-servers.\n");
511
        hvcs_rescan_devices_list();
512
        hvcs_rescan_status = 0;
513
        return count;
514
}
515
 
516
static DRIVER_ATTR(rescan,
517
        S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
518
 
519
static void hvcs_kick(void)
520
{
521
        hvcs_kicked = 1;
522
        wmb();
523
        wake_up_process(hvcs_task);
524
}
525
 
526
static void hvcs_unthrottle(struct tty_struct *tty)
527
{
528
        struct hvcs_struct *hvcsd = tty->driver_data;
529
        unsigned long flags;
530
 
531
        spin_lock_irqsave(&hvcsd->lock, flags);
532
        hvcsd->todo_mask |= HVCS_SCHED_READ;
533
        spin_unlock_irqrestore(&hvcsd->lock, flags);
534
        hvcs_kick();
535
}
536
 
537
static void hvcs_throttle(struct tty_struct *tty)
538
{
539
        struct hvcs_struct *hvcsd = tty->driver_data;
540
        unsigned long flags;
541
 
542
        spin_lock_irqsave(&hvcsd->lock, flags);
543
        vio_disable_interrupts(hvcsd->vdev);
544
        spin_unlock_irqrestore(&hvcsd->lock, flags);
545
}
546
 
547
/*
548
 * If the device is being removed we don't have to worry about this interrupt
549
 * handler taking any further interrupts because they are disabled which means
550
 * the hvcs_struct will always be valid in this handler.
551
 */
552
static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
553
{
554
        struct hvcs_struct *hvcsd = dev_instance;
555
 
556
        spin_lock(&hvcsd->lock);
557
        vio_disable_interrupts(hvcsd->vdev);
558
        hvcsd->todo_mask |= HVCS_SCHED_READ;
559
        spin_unlock(&hvcsd->lock);
560
        hvcs_kick();
561
 
562
        return IRQ_HANDLED;
563
}
564
 
565
/* This function must be called with the hvcsd->lock held */
566
static void hvcs_try_write(struct hvcs_struct *hvcsd)
567
{
568
        uint32_t unit_address = hvcsd->vdev->unit_address;
569
        struct tty_struct *tty = hvcsd->tty;
570
        int sent;
571
 
572
        if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
573
                /* won't send partial writes */
574
                sent = hvc_put_chars(unit_address,
575
                                &hvcsd->buffer[0],
576
                                hvcsd->chars_in_buffer );
577
                if (sent > 0) {
578
                        hvcsd->chars_in_buffer = 0;
579
                        /* wmb(); */
580
                        hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
581
                        /* wmb(); */
582
 
583
                        /*
584
                         * We are still obligated to deliver the data to the
585
                         * hypervisor even if the tty has been closed because
586
                         * we commited to delivering it.  But don't try to wake
587
                         * a non-existent tty.
588
                         */
589
                        if (tty) {
590
                                tty_wakeup(tty);
591
                        }
592
                }
593
        }
594
}
595
 
596
static int hvcs_io(struct hvcs_struct *hvcsd)
597
{
598
        uint32_t unit_address;
599
        struct tty_struct *tty;
600
        char buf[HVCS_BUFF_LEN] __ALIGNED__;
601
        unsigned long flags;
602
        int got = 0;
603
 
604
        spin_lock_irqsave(&hvcsd->lock, flags);
605
 
606
        unit_address = hvcsd->vdev->unit_address;
607
        tty = hvcsd->tty;
608
 
609
        hvcs_try_write(hvcsd);
610
 
611
        if (!tty || test_bit(TTY_THROTTLED, &tty->flags)) {
612
                hvcsd->todo_mask &= ~(HVCS_READ_MASK);
613
                goto bail;
614
        } else if (!(hvcsd->todo_mask & (HVCS_READ_MASK)))
615
                goto bail;
616
 
617
        /* remove the read masks */
618
        hvcsd->todo_mask &= ~(HVCS_READ_MASK);
619
 
620
        if (tty_buffer_request_room(tty, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
621
                got = hvc_get_chars(unit_address,
622
                                &buf[0],
623
                                HVCS_BUFF_LEN);
624
                tty_insert_flip_string(tty, buf, got);
625
        }
626
 
627
        /* Give the TTY time to process the data we just sent. */
628
        if (got)
629
                hvcsd->todo_mask |= HVCS_QUICK_READ;
630
 
631
        spin_unlock_irqrestore(&hvcsd->lock, flags);
632
        /* This is synch because tty->low_latency == 1 */
633
        if(got)
634
                tty_flip_buffer_push(tty);
635
 
636
        if (!got) {
637
                /* Do this _after_ the flip_buffer_push */
638
                spin_lock_irqsave(&hvcsd->lock, flags);
639
                vio_enable_interrupts(hvcsd->vdev);
640
                spin_unlock_irqrestore(&hvcsd->lock, flags);
641
        }
642
 
643
        return hvcsd->todo_mask;
644
 
645
 bail:
646
        spin_unlock_irqrestore(&hvcsd->lock, flags);
647
        return hvcsd->todo_mask;
648
}
649
 
650
static int khvcsd(void *unused)
651
{
652
        struct hvcs_struct *hvcsd;
653
        int hvcs_todo_mask;
654
 
655
        __set_current_state(TASK_RUNNING);
656
 
657
        do {
658
                hvcs_todo_mask = 0;
659
                hvcs_kicked = 0;
660
                wmb();
661
 
662
                spin_lock(&hvcs_structs_lock);
663
                list_for_each_entry(hvcsd, &hvcs_structs, next) {
664
                        hvcs_todo_mask |= hvcs_io(hvcsd);
665
                }
666
                spin_unlock(&hvcs_structs_lock);
667
 
668
                /*
669
                 * If any of the hvcs adapters want to try a write or quick read
670
                 * don't schedule(), yield a smidgen then execute the hvcs_io
671
                 * thread again for those that want the write.
672
                 */
673
                 if (hvcs_todo_mask & (HVCS_TRY_WRITE | HVCS_QUICK_READ)) {
674
                        yield();
675
                        continue;
676
                }
677
 
678
                set_current_state(TASK_INTERRUPTIBLE);
679
                if (!hvcs_kicked)
680
                        schedule();
681
                __set_current_state(TASK_RUNNING);
682
        } while (!kthread_should_stop());
683
 
684
        return 0;
685
}
686
 
687
static struct vio_device_id hvcs_driver_table[] __devinitdata= {
688
        {"serial-server", "hvterm2"},
689
        { "", "" }
690
};
691
MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
692
 
693
static void hvcs_return_index(int index)
694
{
695
        /* Paranoia check */
696
        if (!hvcs_index_list)
697
                return;
698
        if (index < 0 || index >= hvcs_index_count)
699
                return;
700
        if (hvcs_index_list[index] == -1)
701
                return;
702
        else
703
                hvcs_index_list[index] = -1;
704
}
705
 
706
/* callback when the kboject ref count reaches zero */
707
static void destroy_hvcs_struct(struct kobject *kobj)
708
{
709
        struct hvcs_struct *hvcsd = from_kobj(kobj);
710
        struct vio_dev *vdev;
711
        unsigned long flags;
712
 
713
        spin_lock(&hvcs_structs_lock);
714
        spin_lock_irqsave(&hvcsd->lock, flags);
715
 
716
        /* the list_del poisons the pointers */
717
        list_del(&(hvcsd->next));
718
 
719
        if (hvcsd->connected == 1) {
720
                hvcs_partner_free(hvcsd);
721
                printk(KERN_INFO "HVCS: Closed vty-server@%X and"
722
                                " partner vty@%X:%d connection.\n",
723
                                hvcsd->vdev->unit_address,
724
                                hvcsd->p_unit_address,
725
                                (uint32_t)hvcsd->p_partition_ID);
726
        }
727
        printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
728
                        hvcsd->vdev->unit_address);
729
 
730
        vdev = hvcsd->vdev;
731
        hvcsd->vdev = NULL;
732
 
733
        hvcsd->p_unit_address = 0;
734
        hvcsd->p_partition_ID = 0;
735
        hvcs_return_index(hvcsd->index);
736
        memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
737
 
738
        spin_unlock_irqrestore(&hvcsd->lock, flags);
739
        spin_unlock(&hvcs_structs_lock);
740
 
741
        sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
742
 
743
        kfree(hvcsd);
744
}
745
 
746
static struct kobj_type hvcs_kobj_type = {
747
        .release = destroy_hvcs_struct,
748
};
749
 
750
static int hvcs_get_index(void)
751
{
752
        int i;
753
        /* Paranoia check */
754
        if (!hvcs_index_list) {
755
                printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
756
                return -EFAULT;
757
        }
758
        /* Find the numerically lowest first free index. */
759
        for(i = 0; i < hvcs_index_count; i++) {
760
                if (hvcs_index_list[i] == -1) {
761
                        hvcs_index_list[i] = 0;
762
                        return i;
763
                }
764
        }
765
        return -1;
766
}
767
 
768
static int __devinit hvcs_probe(
769
        struct vio_dev *dev,
770
        const struct vio_device_id *id)
771
{
772
        struct hvcs_struct *hvcsd;
773
        int index;
774
        int retval;
775
 
776
        if (!dev || !id) {
777
                printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
778
                return -EPERM;
779
        }
780
 
781
        /* early to avoid cleanup on failure */
782
        index = hvcs_get_index();
783
        if (index < 0) {
784
                return -EFAULT;
785
        }
786
 
787
        hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL);
788
        if (!hvcsd)
789
                return -ENODEV;
790
 
791
 
792
        spin_lock_init(&hvcsd->lock);
793
        /* Automatically incs the refcount the first time */
794
        kobject_init(&hvcsd->kobj);
795
        /* Set up the callback for terminating the hvcs_struct's life */
796
        hvcsd->kobj.ktype = &hvcs_kobj_type;
797
 
798
        hvcsd->vdev = dev;
799
        dev->dev.driver_data = hvcsd;
800
 
801
        hvcsd->index = index;
802
 
803
        /* hvcsd->index = ++hvcs_struct_count; */
804
        hvcsd->chars_in_buffer = 0;
805
        hvcsd->todo_mask = 0;
806
        hvcsd->connected = 0;
807
 
808
        /*
809
         * This will populate the hvcs_struct's partner info fields for the
810
         * first time.
811
         */
812
        if (hvcs_get_pi(hvcsd)) {
813
                printk(KERN_ERR "HVCS: Failed to fetch partner"
814
                        " info for vty-server@%X on device probe.\n",
815
                        hvcsd->vdev->unit_address);
816
        }
817
 
818
        /*
819
         * If a user app opens a tty that corresponds to this vty-server before
820
         * the hvcs_struct has been added to the devices list then the user app
821
         * will get -ENODEV.
822
         */
823
        spin_lock(&hvcs_structs_lock);
824
        list_add_tail(&(hvcsd->next), &hvcs_structs);
825
        spin_unlock(&hvcs_structs_lock);
826
 
827
        retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group);
828
        if (retval) {
829
                printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n",
830
                       hvcsd->vdev->unit_address);
831
                return retval;
832
        }
833
 
834
        printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
835
 
836
        /*
837
         * DON'T enable interrupts here because there is no user to receive the
838
         * data.
839
         */
840
        return 0;
841
}
842
 
843
static int __devexit hvcs_remove(struct vio_dev *dev)
844
{
845
        struct hvcs_struct *hvcsd = dev->dev.driver_data;
846
        unsigned long flags;
847
        struct kobject *kobjp;
848
        struct tty_struct *tty;
849
 
850
        if (!hvcsd)
851
                return -ENODEV;
852
 
853
        /* By this time the vty-server won't be getting any more interrups */
854
 
855
        spin_lock_irqsave(&hvcsd->lock, flags);
856
 
857
        tty = hvcsd->tty;
858
 
859
        kobjp = &hvcsd->kobj;
860
 
861
        spin_unlock_irqrestore(&hvcsd->lock, flags);
862
 
863
        /*
864
         * Let the last holder of this object cause it to be removed, which
865
         * would probably be tty_hangup below.
866
         */
867
        kobject_put (kobjp);
868
 
869
        /*
870
         * The hangup is a scheduled function which will auto chain call
871
         * hvcs_hangup.  The tty should always be valid at this time unless a
872
         * simultaneous tty close already cleaned up the hvcs_struct.
873
         */
874
        if (tty)
875
                tty_hangup(tty);
876
 
877
        printk(KERN_INFO "HVCS: vty-server@%X removed from the"
878
                        " vio bus.\n", dev->unit_address);
879
        return 0;
880
};
881
 
882
static struct vio_driver hvcs_vio_driver = {
883
        .id_table       = hvcs_driver_table,
884
        .probe          = hvcs_probe,
885
        .remove         = hvcs_remove,
886
        .driver         = {
887
                .name   = hvcs_driver_name,
888
                .owner  = THIS_MODULE,
889
        }
890
};
891
 
892
/* Only called from hvcs_get_pi please */
893
static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
894
{
895
        int clclength;
896
 
897
        hvcsd->p_unit_address = pi->unit_address;
898
        hvcsd->p_partition_ID  = pi->partition_ID;
899
        clclength = strlen(&pi->location_code[0]);
900
        if (clclength > HVCS_CLC_LENGTH)
901
                clclength = HVCS_CLC_LENGTH;
902
 
903
        /* copy the null-term char too */
904
        strncpy(&hvcsd->p_location_code[0],
905
                        &pi->location_code[0], clclength + 1);
906
}
907
 
908
/*
909
 * Traverse the list and add the partner info that is found to the hvcs_struct
910
 * struct entry. NOTE: At this time I know that partner info will return a
911
 * single entry but in the future there may be multiple partner info entries per
912
 * vty-server and you'll want to zero out that list and reset it.  If for some
913
 * reason you have an old version of this driver but there IS more than one
914
 * partner info then hvcsd->p_* will hold the last partner info data from the
915
 * firmware query.  A good way to update this code would be to replace the three
916
 * partner info fields in hvcs_struct with a list of hvcs_partner_info
917
 * instances.
918
 *
919
 * This function must be called with the hvcsd->lock held.
920
 */
921
static int hvcs_get_pi(struct hvcs_struct *hvcsd)
922
{
923
        struct hvcs_partner_info *pi;
924
        uint32_t unit_address = hvcsd->vdev->unit_address;
925
        struct list_head head;
926
        int retval;
927
 
928
        spin_lock(&hvcs_pi_lock);
929
        if (!hvcs_pi_buff) {
930
                spin_unlock(&hvcs_pi_lock);
931
                return -EFAULT;
932
        }
933
        retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
934
        spin_unlock(&hvcs_pi_lock);
935
        if (retval) {
936
                printk(KERN_ERR "HVCS: Failed to fetch partner"
937
                        " info for vty-server@%x.\n", unit_address);
938
                return retval;
939
        }
940
 
941
        /* nixes the values if the partner vty went away */
942
        hvcsd->p_unit_address = 0;
943
        hvcsd->p_partition_ID = 0;
944
 
945
        list_for_each_entry(pi, &head, node)
946
                hvcs_set_pi(pi, hvcsd);
947
 
948
        hvcs_free_partner_info(&head);
949
        return 0;
950
}
951
 
952
/*
953
 * This function is executed by the driver "rescan" sysfs entry.  It shouldn't
954
 * be executed elsewhere, in order to prevent deadlock issues.
955
 */
956
static int hvcs_rescan_devices_list(void)
957
{
958
        struct hvcs_struct *hvcsd;
959
        unsigned long flags;
960
 
961
        spin_lock(&hvcs_structs_lock);
962
 
963
        list_for_each_entry(hvcsd, &hvcs_structs, next) {
964
                spin_lock_irqsave(&hvcsd->lock, flags);
965
                hvcs_get_pi(hvcsd);
966
                spin_unlock_irqrestore(&hvcsd->lock, flags);
967
        }
968
 
969
        spin_unlock(&hvcs_structs_lock);
970
 
971
        return 0;
972
}
973
 
974
/*
975
 * Farm this off into its own function because it could be more complex once
976
 * multiple partners support is added. This function should be called with
977
 * the hvcsd->lock held.
978
 */
979
static int hvcs_has_pi(struct hvcs_struct *hvcsd)
980
{
981
        if ((!hvcsd->p_unit_address) || (!hvcsd->p_partition_ID))
982
                return 0;
983
        return 1;
984
}
985
 
986
/*
987
 * NOTE: It is possible that the super admin removed a partner vty and then
988
 * added a different vty as the new partner.
989
 *
990
 * This function must be called with the hvcsd->lock held.
991
 */
992
static int hvcs_partner_connect(struct hvcs_struct *hvcsd)
993
{
994
        int retval;
995
        unsigned int unit_address = hvcsd->vdev->unit_address;
996
 
997
        /*
998
         * If there wasn't any pi when the device was added it doesn't meant
999
         * there isn't any now.  This driver isn't notified when a new partner
1000
         * vty is added to a vty-server so we discover changes on our own.
1001
         * Please see comments in hvcs_register_connection() for justification
1002
         * of this bizarre code.
1003
         */
1004
        retval = hvcs_register_connection(unit_address,
1005
                        hvcsd->p_partition_ID,
1006
                        hvcsd->p_unit_address);
1007
        if (!retval) {
1008
                hvcsd->connected = 1;
1009
                return 0;
1010
        } else if (retval != -EINVAL)
1011
                return retval;
1012
 
1013
        /*
1014
         * As per the spec re-get the pi and try again if -EINVAL after the
1015
         * first connection attempt.
1016
         */
1017
        if (hvcs_get_pi(hvcsd))
1018
                return -ENOMEM;
1019
 
1020
        if (!hvcs_has_pi(hvcsd))
1021
                return -ENODEV;
1022
 
1023
        retval = hvcs_register_connection(unit_address,
1024
                        hvcsd->p_partition_ID,
1025
                        hvcsd->p_unit_address);
1026
        if (retval != -EINVAL) {
1027
                hvcsd->connected = 1;
1028
                return retval;
1029
        }
1030
 
1031
        /*
1032
         * EBUSY is the most likely scenario though the vty could have been
1033
         * removed or there really could be an hcall error due to the parameter
1034
         * data but thanks to ambiguous firmware return codes we can't really
1035
         * tell.
1036
         */
1037
        printk(KERN_INFO "HVCS: vty-server or partner"
1038
                        " vty is busy.  Try again later.\n");
1039
        return -EBUSY;
1040
}
1041
 
1042
/* This function must be called with the hvcsd->lock held */
1043
static void hvcs_partner_free(struct hvcs_struct *hvcsd)
1044
{
1045
        int retval;
1046
        do {
1047
                retval = hvcs_free_connection(hvcsd->vdev->unit_address);
1048
        } while (retval == -EBUSY);
1049
        hvcsd->connected = 0;
1050
}
1051
 
1052
/* This helper function must be called WITHOUT the hvcsd->lock held */
1053
static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
1054
                unsigned int irq, struct vio_dev *vdev)
1055
{
1056
        unsigned long flags;
1057
        int rc;
1058
 
1059
        /*
1060
         * It is possible that the vty-server was removed between the time that
1061
         * the conn was registered and now.
1062
         */
1063
        if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
1064
                                IRQF_DISABLED, "ibmhvcs", hvcsd))) {
1065
                /*
1066
                 * It is possible the vty-server was removed after the irq was
1067
                 * requested but before we have time to enable interrupts.
1068
                 */
1069
                if (vio_enable_interrupts(vdev) == H_SUCCESS)
1070
                        return 0;
1071
                else {
1072
                        printk(KERN_ERR "HVCS: int enable failed for"
1073
                                        " vty-server@%X.\n", unit_address);
1074
                        free_irq(irq, hvcsd);
1075
                }
1076
        } else
1077
                printk(KERN_ERR "HVCS: irq req failed for"
1078
                                " vty-server@%X.\n", unit_address);
1079
 
1080
        spin_lock_irqsave(&hvcsd->lock, flags);
1081
        hvcs_partner_free(hvcsd);
1082
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1083
 
1084
        return rc;
1085
 
1086
}
1087
 
1088
/*
1089
 * This always increments the kobject ref count if the call is successful.
1090
 * Please remember to dec when you are done with the instance.
1091
 *
1092
 * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when
1093
 * calling this function or you will get deadlock.
1094
 */
1095
static struct hvcs_struct *hvcs_get_by_index(int index)
1096
{
1097
        struct hvcs_struct *hvcsd = NULL;
1098
        unsigned long flags;
1099
 
1100
        spin_lock(&hvcs_structs_lock);
1101
        /* We can immediately discard OOB requests */
1102
        if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) {
1103
                list_for_each_entry(hvcsd, &hvcs_structs, next) {
1104
                        spin_lock_irqsave(&hvcsd->lock, flags);
1105
                        if (hvcsd->index == index) {
1106
                                kobject_get(&hvcsd->kobj);
1107
                                spin_unlock_irqrestore(&hvcsd->lock, flags);
1108
                                spin_unlock(&hvcs_structs_lock);
1109
                                return hvcsd;
1110
                        }
1111
                        spin_unlock_irqrestore(&hvcsd->lock, flags);
1112
                }
1113
                hvcsd = NULL;
1114
        }
1115
 
1116
        spin_unlock(&hvcs_structs_lock);
1117
        return hvcsd;
1118
}
1119
 
1120
/*
1121
 * This is invoked via the tty_open interface when a user app connects to the
1122
 * /dev node.
1123
 */
1124
static int hvcs_open(struct tty_struct *tty, struct file *filp)
1125
{
1126
        struct hvcs_struct *hvcsd;
1127
        int rc, retval = 0;
1128
        unsigned long flags;
1129
        unsigned int irq;
1130
        struct vio_dev *vdev;
1131
        unsigned long unit_address;
1132
        struct kobject *kobjp;
1133
 
1134
        if (tty->driver_data)
1135
                goto fast_open;
1136
 
1137
        /*
1138
         * Is there a vty-server that shares the same index?
1139
         * This function increments the kobject index.
1140
         */
1141
        if (!(hvcsd = hvcs_get_by_index(tty->index))) {
1142
                printk(KERN_WARNING "HVCS: open failed, no device associated"
1143
                                " with tty->index %d.\n", tty->index);
1144
                return -ENODEV;
1145
        }
1146
 
1147
        spin_lock_irqsave(&hvcsd->lock, flags);
1148
 
1149
        if (hvcsd->connected == 0)
1150
                if ((retval = hvcs_partner_connect(hvcsd)))
1151
                        goto error_release;
1152
 
1153
        hvcsd->open_count = 1;
1154
        hvcsd->tty = tty;
1155
        tty->driver_data = hvcsd;
1156
 
1157
        /*
1158
         * Set this driver to low latency so that we actually have a chance at
1159
         * catching a throttled TTY after we flip_buffer_push.  Otherwise the
1160
         * flush_to_async may not execute until after the kernel_thread has
1161
         * yielded and resumed the next flip_buffer_push resulting in data
1162
         * loss.
1163
         */
1164
        tty->low_latency = 1;
1165
 
1166
        memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
1167
 
1168
        /*
1169
         * Save these in the spinlock for the enable operations that need them
1170
         * outside of the spinlock.
1171
         */
1172
        irq = hvcsd->vdev->irq;
1173
        vdev = hvcsd->vdev;
1174
        unit_address = hvcsd->vdev->unit_address;
1175
 
1176
        hvcsd->todo_mask |= HVCS_SCHED_READ;
1177
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1178
 
1179
        /*
1180
         * This must be done outside of the spinlock because it requests irqs
1181
         * and will grab the spinlock and free the connection if it fails.
1182
         */
1183
        if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
1184
                kobject_put(&hvcsd->kobj);
1185
                printk(KERN_WARNING "HVCS: enable device failed.\n");
1186
                return rc;
1187
        }
1188
 
1189
        goto open_success;
1190
 
1191
fast_open:
1192
        hvcsd = tty->driver_data;
1193
 
1194
        spin_lock_irqsave(&hvcsd->lock, flags);
1195
        if (!kobject_get(&hvcsd->kobj)) {
1196
                spin_unlock_irqrestore(&hvcsd->lock, flags);
1197
                printk(KERN_ERR "HVCS: Kobject of open"
1198
                        " hvcs doesn't exist.\n");
1199
                return -EFAULT; /* Is this the right return value? */
1200
        }
1201
 
1202
        hvcsd->open_count++;
1203
 
1204
        hvcsd->todo_mask |= HVCS_SCHED_READ;
1205
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1206
open_success:
1207
        hvcs_kick();
1208
 
1209
        printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
1210
                hvcsd->vdev->unit_address );
1211
 
1212
        return 0;
1213
 
1214
error_release:
1215
        kobjp = &hvcsd->kobj;
1216
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1217
        kobject_put(&hvcsd->kobj);
1218
 
1219
        printk(KERN_WARNING "HVCS: partner connect failed.\n");
1220
        return retval;
1221
}
1222
 
1223
static void hvcs_close(struct tty_struct *tty, struct file *filp)
1224
{
1225
        struct hvcs_struct *hvcsd;
1226
        unsigned long flags;
1227
        struct kobject *kobjp;
1228
        int irq = NO_IRQ;
1229
 
1230
        /*
1231
         * Is someone trying to close the file associated with this device after
1232
         * we have hung up?  If so tty->driver_data wouldn't be valid.
1233
         */
1234
        if (tty_hung_up_p(filp))
1235
                return;
1236
 
1237
        /*
1238
         * No driver_data means that this close was probably issued after a
1239
         * failed hvcs_open by the tty layer's release_dev() api and we can just
1240
         * exit cleanly.
1241
         */
1242
        if (!tty->driver_data)
1243
                return;
1244
 
1245
        hvcsd = tty->driver_data;
1246
 
1247
        spin_lock_irqsave(&hvcsd->lock, flags);
1248
        kobjp = &hvcsd->kobj;
1249
        if (--hvcsd->open_count == 0) {
1250
 
1251
                vio_disable_interrupts(hvcsd->vdev);
1252
 
1253
                /*
1254
                 * NULL this early so that the kernel_thread doesn't try to
1255
                 * execute any operations on the TTY even though it is obligated
1256
                 * to deliver any pending I/O to the hypervisor.
1257
                 */
1258
                hvcsd->tty = NULL;
1259
 
1260
                irq = hvcsd->vdev->irq;
1261
                spin_unlock_irqrestore(&hvcsd->lock, flags);
1262
 
1263
                tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
1264
 
1265
                /*
1266
                 * This line is important because it tells hvcs_open that this
1267
                 * device needs to be re-configured the next time hvcs_open is
1268
                 * called.
1269
                 */
1270
                tty->driver_data = NULL;
1271
 
1272
                free_irq(irq, hvcsd);
1273
                kobject_put(kobjp);
1274
                return;
1275
        } else if (hvcsd->open_count < 0) {
1276
                printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
1277
                                " is missmanaged.\n",
1278
                hvcsd->vdev->unit_address, hvcsd->open_count);
1279
        }
1280
 
1281
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1282
        kobject_put(kobjp);
1283
}
1284
 
1285
static void hvcs_hangup(struct tty_struct * tty)
1286
{
1287
        struct hvcs_struct *hvcsd = tty->driver_data;
1288
        unsigned long flags;
1289
        int temp_open_count;
1290
        struct kobject *kobjp;
1291
        int irq = NO_IRQ;
1292
 
1293
        spin_lock_irqsave(&hvcsd->lock, flags);
1294
        /* Preserve this so that we know how many kobject refs to put */
1295
        temp_open_count = hvcsd->open_count;
1296
 
1297
        /*
1298
         * Don't kobject put inside the spinlock because the destruction
1299
         * callback may use the spinlock and it may get called before the
1300
         * spinlock has been released.  Get a pointer to the kobject and
1301
         * kobject_put on that after releasing the spinlock.
1302
         */
1303
        kobjp = &hvcsd->kobj;
1304
 
1305
        vio_disable_interrupts(hvcsd->vdev);
1306
 
1307
        hvcsd->todo_mask = 0;
1308
 
1309
        /* I don't think the tty needs the hvcs_struct pointer after a hangup */
1310
        hvcsd->tty->driver_data = NULL;
1311
        hvcsd->tty = NULL;
1312
 
1313
        hvcsd->open_count = 0;
1314
 
1315
        /* This will drop any buffered data on the floor which is OK in a hangup
1316
         * scenario. */
1317
        memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
1318
        hvcsd->chars_in_buffer = 0;
1319
 
1320
        irq = hvcsd->vdev->irq;
1321
 
1322
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1323
 
1324
        free_irq(irq, hvcsd);
1325
 
1326
        /*
1327
         * We need to kobject_put() for every open_count we have since the
1328
         * tty_hangup() function doesn't invoke a close per open connection on a
1329
         * non-console device.
1330
         */
1331
        while(temp_open_count) {
1332
                --temp_open_count;
1333
                /*
1334
                 * The final put will trigger destruction of the hvcs_struct.
1335
                 * NOTE:  If this hangup was signaled from user space then the
1336
                 * final put will never happen.
1337
                 */
1338
                kobject_put(kobjp);
1339
        }
1340
}
1341
 
1342
/*
1343
 * NOTE: This is almost always from_user since user level apps interact with the
1344
 * /dev nodes. I'm trusting that if hvcs_write gets called and interrupted by
1345
 * hvcs_remove (which removes the target device and executes tty_hangup()) that
1346
 * tty_hangup will allow hvcs_write time to complete execution before it
1347
 * terminates our device.
1348
 */
1349
static int hvcs_write(struct tty_struct *tty,
1350
                const unsigned char *buf, int count)
1351
{
1352
        struct hvcs_struct *hvcsd = tty->driver_data;
1353
        unsigned int unit_address;
1354
        const unsigned char *charbuf;
1355
        unsigned long flags;
1356
        int total_sent = 0;
1357
        int tosend = 0;
1358
        int result = 0;
1359
 
1360
        /*
1361
         * If they don't check the return code off of their open they may
1362
         * attempt this even if there is no connected device.
1363
         */
1364
        if (!hvcsd)
1365
                return -ENODEV;
1366
 
1367
        /* Reasonable size to prevent user level flooding */
1368
        if (count > HVCS_MAX_FROM_USER) {
1369
                printk(KERN_WARNING "HVCS write: count being truncated to"
1370
                                " HVCS_MAX_FROM_USER.\n");
1371
                count = HVCS_MAX_FROM_USER;
1372
        }
1373
 
1374
        charbuf = buf;
1375
 
1376
        spin_lock_irqsave(&hvcsd->lock, flags);
1377
 
1378
        /*
1379
         * Somehow an open succedded but the device was removed or the
1380
         * connection terminated between the vty-server and partner vty during
1381
         * the middle of a write operation?  This is a crummy place to do this
1382
         * but we want to keep it all in the spinlock.
1383
         */
1384
        if (hvcsd->open_count <= 0) {
1385
                spin_unlock_irqrestore(&hvcsd->lock, flags);
1386
                return -ENODEV;
1387
        }
1388
 
1389
        unit_address = hvcsd->vdev->unit_address;
1390
 
1391
        while (count > 0) {
1392
                tosend = min(count, (HVCS_BUFF_LEN - hvcsd->chars_in_buffer));
1393
                /*
1394
                 * No more space, this probably means that the last call to
1395
                 * hvcs_write() didn't succeed and the buffer was filled up.
1396
                 */
1397
                if (!tosend)
1398
                        break;
1399
 
1400
                memcpy(&hvcsd->buffer[hvcsd->chars_in_buffer],
1401
                                &charbuf[total_sent],
1402
                                tosend);
1403
 
1404
                hvcsd->chars_in_buffer += tosend;
1405
 
1406
                result = 0;
1407
 
1408
                /*
1409
                 * If this is true then we don't want to try writing to the
1410
                 * hypervisor because that is the kernel_threads job now.  We'll
1411
                 * just add to the buffer.
1412
                 */
1413
                if (!(hvcsd->todo_mask & HVCS_TRY_WRITE))
1414
                        /* won't send partial writes */
1415
                        result = hvc_put_chars(unit_address,
1416
                                        &hvcsd->buffer[0],
1417
                                        hvcsd->chars_in_buffer);
1418
 
1419
                /*
1420
                 * Since we know we have enough room in hvcsd->buffer for
1421
                 * tosend we record that it was sent regardless of whether the
1422
                 * hypervisor actually took it because we have it buffered.
1423
                 */
1424
                total_sent+=tosend;
1425
                count-=tosend;
1426
                if (result == 0) {
1427
                        hvcsd->todo_mask |= HVCS_TRY_WRITE;
1428
                        hvcs_kick();
1429
                        break;
1430
                }
1431
 
1432
                hvcsd->chars_in_buffer = 0;
1433
                /*
1434
                 * Test after the chars_in_buffer reset otherwise this could
1435
                 * deadlock our writes if hvc_put_chars fails.
1436
                 */
1437
                if (result < 0)
1438
                        break;
1439
        }
1440
 
1441
        spin_unlock_irqrestore(&hvcsd->lock, flags);
1442
 
1443
        if (result == -1)
1444
                return -EIO;
1445
        else
1446
                return total_sent;
1447
}
1448
 
1449
/*
1450
 * This is really asking how much can we guarentee that we can send or that we
1451
 * absolutely WILL BUFFER if we can't send it.  This driver MUST honor the
1452
 * return value, hence the reason for hvcs_struct buffering.
1453
 */
1454
static int hvcs_write_room(struct tty_struct *tty)
1455
{
1456
        struct hvcs_struct *hvcsd = tty->driver_data;
1457
 
1458
        if (!hvcsd || hvcsd->open_count <= 0)
1459
                return 0;
1460
 
1461
        return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
1462
}
1463
 
1464
static int hvcs_chars_in_buffer(struct tty_struct *tty)
1465
{
1466
        struct hvcs_struct *hvcsd = tty->driver_data;
1467
 
1468
        return hvcsd->chars_in_buffer;
1469
}
1470
 
1471
static const struct tty_operations hvcs_ops = {
1472
        .open = hvcs_open,
1473
        .close = hvcs_close,
1474
        .hangup = hvcs_hangup,
1475
        .write = hvcs_write,
1476
        .write_room = hvcs_write_room,
1477
        .chars_in_buffer = hvcs_chars_in_buffer,
1478
        .unthrottle = hvcs_unthrottle,
1479
        .throttle = hvcs_throttle,
1480
};
1481
 
1482
static int hvcs_alloc_index_list(int n)
1483
{
1484
        int i;
1485
 
1486
        hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
1487
        if (!hvcs_index_list)
1488
                return -ENOMEM;
1489
        hvcs_index_count = n;
1490
        for (i = 0; i < hvcs_index_count; i++)
1491
                hvcs_index_list[i] = -1;
1492
        return 0;
1493
}
1494
 
1495
static void hvcs_free_index_list(void)
1496
{
1497
        /* Paranoia check to be thorough. */
1498
        kfree(hvcs_index_list);
1499
        hvcs_index_list = NULL;
1500
        hvcs_index_count = 0;
1501
}
1502
 
1503
static int __init hvcs_module_init(void)
1504
{
1505
        int rc;
1506
        int num_ttys_to_alloc;
1507
 
1508
        printk(KERN_INFO "Initializing %s\n", hvcs_driver_string);
1509
 
1510
        /* Has the user specified an overload with an insmod param? */
1511
        if (hvcs_parm_num_devs <= 0 ||
1512
                (hvcs_parm_num_devs > HVCS_MAX_SERVER_ADAPTERS)) {
1513
                num_ttys_to_alloc = HVCS_DEFAULT_SERVER_ADAPTERS;
1514
        } else
1515
                num_ttys_to_alloc = hvcs_parm_num_devs;
1516
 
1517
        hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
1518
        if (!hvcs_tty_driver)
1519
                return -ENOMEM;
1520
 
1521
        if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
1522
                rc = -ENOMEM;
1523
                goto index_fail;
1524
        }
1525
 
1526
        hvcs_tty_driver->owner = THIS_MODULE;
1527
 
1528
        hvcs_tty_driver->driver_name = hvcs_driver_name;
1529
        hvcs_tty_driver->name = hvcs_device_node;
1530
 
1531
        /*
1532
         * We'll let the system assign us a major number, indicated by leaving
1533
         * it blank.
1534
         */
1535
 
1536
        hvcs_tty_driver->minor_start = HVCS_MINOR_START;
1537
        hvcs_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
1538
 
1539
        /*
1540
         * We role our own so that we DONT ECHO.  We can't echo because the
1541
         * device we are connecting to already echoes by default and this would
1542
         * throw us into a horrible recursive echo-echo-echo loop.
1543
         */
1544
        hvcs_tty_driver->init_termios = hvcs_tty_termios;
1545
        hvcs_tty_driver->flags = TTY_DRIVER_REAL_RAW;
1546
 
1547
        tty_set_operations(hvcs_tty_driver, &hvcs_ops);
1548
 
1549
        /*
1550
         * The following call will result in sysfs entries that denote the
1551
         * dynamically assigned major and minor numbers for our devices.
1552
         */
1553
        if (tty_register_driver(hvcs_tty_driver)) {
1554
                printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");
1555
                rc = -EIO;
1556
                goto register_fail;
1557
        }
1558
 
1559
        hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
1560
        if (!hvcs_pi_buff) {
1561
                rc = -ENOMEM;
1562
                goto buff_alloc_fail;
1563
        }
1564
 
1565
        hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
1566
        if (IS_ERR(hvcs_task)) {
1567
                printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
1568
                rc = -EIO;
1569
                goto kthread_fail;
1570
        }
1571
 
1572
        rc = vio_register_driver(&hvcs_vio_driver);
1573
        if (rc) {
1574
                printk(KERN_ERR "HVCS: can't register vio driver\n");
1575
                goto vio_fail;
1576
        }
1577
 
1578
        /*
1579
         * This needs to be done AFTER the vio_register_driver() call or else
1580
         * the kobjects won't be initialized properly.
1581
         */
1582
        rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
1583
        if (rc) {
1584
                printk(KERN_ERR "HVCS: sysfs attr create failed\n");
1585
                goto attr_fail;
1586
        }
1587
 
1588
        printk(KERN_INFO "HVCS: driver module inserted.\n");
1589
 
1590
        return 0;
1591
 
1592
attr_fail:
1593
        vio_unregister_driver(&hvcs_vio_driver);
1594
vio_fail:
1595
        kthread_stop(hvcs_task);
1596
kthread_fail:
1597
        kfree(hvcs_pi_buff);
1598
buff_alloc_fail:
1599
        tty_unregister_driver(hvcs_tty_driver);
1600
register_fail:
1601
        hvcs_free_index_list();
1602
index_fail:
1603
        put_tty_driver(hvcs_tty_driver);
1604
        hvcs_tty_driver = NULL;
1605
        return rc;
1606
}
1607
 
1608
static void __exit hvcs_module_exit(void)
1609
{
1610
        /*
1611
         * This driver receives hvcs_remove callbacks for each device upon
1612
         * module removal.
1613
         */
1614
 
1615
        /*
1616
         * This synchronous operation  will wake the khvcsd kthread if it is
1617
         * asleep and will return when khvcsd has terminated.
1618
         */
1619
        kthread_stop(hvcs_task);
1620
 
1621
        spin_lock(&hvcs_pi_lock);
1622
        kfree(hvcs_pi_buff);
1623
        hvcs_pi_buff = NULL;
1624
        spin_unlock(&hvcs_pi_lock);
1625
 
1626
        driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
1627
 
1628
        vio_unregister_driver(&hvcs_vio_driver);
1629
 
1630
        tty_unregister_driver(hvcs_tty_driver);
1631
 
1632
        hvcs_free_index_list();
1633
 
1634
        put_tty_driver(hvcs_tty_driver);
1635
 
1636
        printk(KERN_INFO "HVCS: driver module removed.\n");
1637
}
1638
 
1639
module_init(hvcs_module_init);
1640
module_exit(hvcs_module_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.