Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / drivers / s390 / char / vmlogrdr.c
1 /*
2  * drivers/s390/char/vmlogrdr.c
3  *      character device driver for reading z/VM system service records
4  *
5  *
6  *      Copyright (C) 2004 IBM Corporation
7  *      character device driver for reading z/VM system service records,
8  *      Version 1.0
9  *      Author(s): Xenia Tkatschow <xenia@us.ibm.com>
10  *                 Stefan Weinhuber <wein@de.ibm.com>
11  *
12  */
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/types.h>
17 #include <linux/interrupt.h>
18 #include <linux/spinlock.h>
19 #include <asm/atomic.h>
20 #include <asm/uaccess.h>
21 #include <asm/cpcmd.h>
22 #include <asm/debug.h>
23 #include <asm/ebcdic.h>
24 #include "../net/iucv.h"
25 #include <linux/kmod.h>
26 #include <linux/cdev.h>
27 #include <linux/device.h>
28 #include <linux/string.h>
29
30
31
32 MODULE_AUTHOR
33         ("(C) 2004 IBM Corporation by Xenia Tkatschow (xenia@us.ibm.com)\n"
34          "                            Stefan Weinhuber (wein@de.ibm.com)");
35 MODULE_DESCRIPTION ("Character device driver for reading z/VM "
36                     "system service records.");
37 MODULE_LICENSE("GPL");
38
39
40 /*
41  * The size of the buffer for iucv data transfer is one page,
42  * but in addition to the data we read from iucv we also
43  * place an integer and some characters into that buffer,
44  * so the maximum size for record data is a little less then
45  * one page.
46  */
47 #define NET_BUFFER_SIZE (PAGE_SIZE - sizeof(int) - sizeof(FENCE))
48
49 /*
50  * The elements that are concurrently accessed by bottom halves are
51  * connection_established, iucv_path_severed, local_interrupt_buffer
52  * and receive_ready. The first three can be protected by
53  * priv_lock.  receive_ready is atomic, so it can be incremented and
54  * decremented without holding a lock.
55  * The variable dev_in_use needs to be protected by the lock, since
56  * it's a flag used by open to make sure that the device is opened only
57  * by one user at the same time.
58  */
59 struct vmlogrdr_priv_t {
60         char system_service[8];
61         char internal_name[8];
62         char recording_name[8];
63         u16 pathid;
64         int connection_established;
65         int iucv_path_severed;
66         iucv_MessagePending local_interrupt_buffer;
67         atomic_t receive_ready;
68         iucv_handle_t iucv_handle;
69         int minor_num;
70         char * buffer;
71         char * current_position;
72         int remaining;
73         ulong residual_length;
74         int buffer_free;
75         int dev_in_use; /* 1: already opened, 0: not opened*/
76         spinlock_t priv_lock;
77         struct device  *device;
78         struct class_device  *class_device;
79         int autorecording;
80         int autopurge;
81 };
82
83
84 /*
85  * File operation structure for vmlogrdr devices
86  */
87 static int vmlogrdr_open(struct inode *, struct file *);
88 static int vmlogrdr_release(struct inode *, struct file *);
89 static ssize_t vmlogrdr_read (struct file *filp, char __user *data,
90                               size_t count, loff_t * ppos);
91
92 static struct file_operations vmlogrdr_fops = {
93         .owner   = THIS_MODULE,
94         .open    = vmlogrdr_open,
95         .release = vmlogrdr_release,
96         .read    = vmlogrdr_read,
97 };
98
99
100 static u8 iucvMagic[16] = {
101         0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
102         0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
103 };
104
105
106 static u8 mask[] = {
107         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
110         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
111 };
112
113
114 static u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
115
116
117 static void
118 vmlogrdr_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data);
119 static void
120 vmlogrdr_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data);
121 static void
122 vmlogrdr_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data);
123
124
125 static iucv_interrupt_ops_t vmlogrdr_iucvops = {
126         .ConnectionComplete = vmlogrdr_iucv_ConnectionComplete,
127         .ConnectionSevered  = vmlogrdr_iucv_ConnectionSevered,
128         .MessagePending     = vmlogrdr_iucv_MessagePending,
129 };
130
131
132 DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
133 DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
134
135 /*
136  * pointer to system service private structure
137  * minor number 0 --> logrec
138  * minor number 1 --> account
139  * minor number 2 --> symptom
140  */
141
142 static struct vmlogrdr_priv_t sys_ser[] = {
143         { .system_service = "*LOGREC ",
144           .internal_name  = "logrec",
145           .recording_name = "EREP",
146           .minor_num      = 0,
147           .buffer_free    = 1,
148           .priv_lock      = SPIN_LOCK_UNLOCKED,
149           .autorecording  = 1,
150           .autopurge      = 1,
151         },
152         { .system_service = "*ACCOUNT",
153           .internal_name  = "account",
154           .recording_name = "ACCOUNT",
155           .minor_num      = 1,
156           .buffer_free    = 1,
157           .priv_lock      = SPIN_LOCK_UNLOCKED,
158           .autorecording  = 1,
159           .autopurge      = 1,
160         },
161         { .system_service = "*SYMPTOM",
162           .internal_name  = "symptom",
163           .recording_name = "SYMPTOM",
164           .minor_num      = 2,
165           .buffer_free    = 1,
166           .priv_lock      = SPIN_LOCK_UNLOCKED,
167           .autorecording  = 1,
168           .autopurge      = 1,
169         }
170 };
171
172 #define MAXMINOR  (sizeof(sys_ser)/sizeof(struct vmlogrdr_priv_t))
173
174 static char FENCE[] = {"EOR"};
175 static int vmlogrdr_major = 0;
176 static struct cdev  *vmlogrdr_cdev = NULL;
177 static int recording_class_AB;
178
179
180 static void
181 vmlogrdr_iucv_ConnectionComplete (iucv_ConnectionComplete * eib,
182                                    void * pgm_data)
183 {
184         struct vmlogrdr_priv_t * logptr = pgm_data;
185         spin_lock(&logptr->priv_lock);
186         logptr->connection_established = 1;
187         spin_unlock(&logptr->priv_lock);
188         wake_up(&conn_wait_queue);
189         return;
190 }
191
192
193 static void
194 vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
195 {
196         u8 reason = (u8) eib->ipuser[8];
197         struct vmlogrdr_priv_t * logptr = pgm_data;
198
199         printk (KERN_ERR "vmlogrdr: connection severed with"
200                 " reason %i\n", reason);
201
202         spin_lock(&logptr->priv_lock);
203         logptr->connection_established = 0;
204         logptr->iucv_path_severed = 1;
205         spin_unlock(&logptr->priv_lock);
206
207         wake_up(&conn_wait_queue);
208         /* just in case we're sleeping waiting for a record */
209         wake_up_interruptible(&read_wait_queue);
210 }
211
212
213 static void
214 vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
215 {
216         struct vmlogrdr_priv_t * logptr = pgm_data;
217
218         /*
219          * This function is the bottom half so it should be quick.
220          * Copy the external interrupt data into our local eib and increment
221          * the usage count
222          */
223         spin_lock(&logptr->priv_lock);
224         memcpy(&(logptr->local_interrupt_buffer), eib, sizeof(*eib));
225         atomic_inc(&logptr->receive_ready);
226         spin_unlock(&logptr->priv_lock);
227         wake_up_interruptible(&read_wait_queue);
228 }
229
230
231 static int
232 vmlogrdr_get_recording_class_AB(void) {
233         char cp_command[]="QUERY COMMAND RECORDING ";
234         char cp_response[80];
235         char *tail;
236         int len,i;
237
238         printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
239         cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
240         printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
241         len = strnlen(cp_response,sizeof(cp_response));
242         // now the parsing
243         tail=strnchr(cp_response,len,'=');
244         if (!tail)
245                 return 0;
246         tail++;
247         if (!strncmp("ANY",tail,3))
248                 return 1;
249         if (!strncmp("NONE",tail,4))
250                 return 0;
251         /*
252          * expect comma separated list of classes here, if one of them
253          * is A or B return 1 otherwise 0
254          */
255         for (i=tail-cp_response; i<len; i++)
256                 if ( cp_response[i]=='A' || cp_response[i]=='B' )
257                         return 1;
258         return 0;
259 }
260
261
262 static int
263 vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
264
265         char cp_command[80];
266         char cp_response[160];
267         char *onoff, *qid_string;
268
269         memset(cp_command, 0x00, sizeof(cp_command));
270         memset(cp_response, 0x00, sizeof(cp_response));
271
272         onoff = ((action == 1) ? "ON" : "OFF");
273         qid_string = ((recording_class_AB == 1) ? " QID * " : "");
274
275         /*
276          * The recording commands needs to be called with option QID
277          * for guests that have previlege classes A or B.
278          * Purging has to be done as separate step, because recording
279          * can't be switched on as long as records are on the queue.
280          * Doing both at the same time doesn't work.
281          */
282
283         if (purge) {
284                 snprintf(cp_command, sizeof(cp_command),
285                          "RECORDING %s PURGE %s",
286                          logptr->recording_name,
287                          qid_string);
288
289                 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
290                         cp_command);
291                 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
292                 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
293                         cp_response);
294         }
295
296         memset(cp_command, 0x00, sizeof(cp_command));
297         memset(cp_response, 0x00, sizeof(cp_response));
298         snprintf(cp_command, sizeof(cp_command), "RECORDING %s %s %s",
299                 logptr->recording_name,
300                 onoff,
301                 qid_string);
302
303         printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
304         cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
305         printk (KERN_DEBUG "vmlogrdr: recording response: %s",
306                 cp_response);
307         /* The recording command will usually answer with 'Command complete'
308          * on success, but when the specific service was never connected
309          * before then there might be an additional informational message
310          * 'HCPCRC8072I Recording entry not found' before the
311          * 'Command complete'. So I use strstr rather then the strncmp.
312          */
313         if (strstr(cp_response,"Command complete"))
314                 return 0;
315         else
316                 return -EIO;
317
318 }
319
320
321 static int
322 vmlogrdr_open (struct inode *inode, struct file *filp)
323 {
324         int dev_num = 0;
325         struct vmlogrdr_priv_t * logptr = NULL;
326         int connect_rc = 0;
327         int ret;
328
329         dev_num = iminor(inode);
330         if (dev_num > MAXMINOR)
331                 return -ENODEV;
332
333         logptr = &sys_ser[dev_num];
334         if (logptr == NULL)
335                 return -ENODEV;
336
337         /*
338          * only allow for blocking reads to be open
339          */
340         if (filp->f_flags & O_NONBLOCK)
341                 return -ENOSYS;
342
343         /* Besure this device hasn't already been opened */
344         spin_lock_bh(&logptr->priv_lock);
345         if (logptr->dev_in_use) {
346                 spin_unlock_bh(&logptr->priv_lock);
347                 return -EBUSY;
348         } else {
349                 logptr->dev_in_use = 1;
350                 spin_unlock_bh(&logptr->priv_lock);
351         }
352
353         atomic_set(&logptr->receive_ready, 0);
354         logptr->buffer_free = 1;
355
356         /* set the file options */
357         filp->private_data = logptr;
358         filp->f_op = &vmlogrdr_fops;
359
360         /* start recording for this service*/
361         ret=0;
362         if (logptr->autorecording)
363                 ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
364         if (ret)
365                 printk (KERN_WARNING "vmlogrdr: failed to start "
366                         "recording automatically\n");
367
368         /* Register with iucv driver */
369         logptr->iucv_handle = iucv_register_program(iucvMagic,
370                         logptr->system_service, mask, &vmlogrdr_iucvops,
371                         logptr);
372
373         if (logptr->iucv_handle == NULL) {
374                 printk (KERN_ERR "vmlogrdr: failed to register with"
375                         "iucv driver\n");
376                 goto not_registered;
377         }
378
379         /* create connection to the system service */
380         spin_lock_bh(&logptr->priv_lock);
381         logptr->connection_established = 0;
382         logptr->iucv_path_severed = 0;
383         spin_unlock_bh(&logptr->priv_lock);
384
385         connect_rc = iucv_connect (&(logptr->pathid), 10, iucvMagic,
386                                         logptr->system_service, iucv_host, 0,
387                                         NULL, NULL,
388                                         logptr->iucv_handle, NULL);
389         if (connect_rc) {
390                 printk (KERN_ERR "vmlogrdr: iucv connection to %s "
391                         "failed with rc %i \n", logptr->system_service,
392                         connect_rc);
393                 goto not_connected;
394         }
395
396         /* We've issued the connect and now we must wait for a
397          * ConnectionComplete or ConnectinSevered Interrupt
398          * before we can continue to process.
399          */
400         wait_event(conn_wait_queue, (logptr->connection_established)
401                    || (logptr->iucv_path_severed));
402         if (logptr->iucv_path_severed) {
403                 goto not_connected;
404         }
405
406         return nonseekable_open(inode, filp);
407
408 not_connected:
409         iucv_unregister_program(logptr->iucv_handle);
410         logptr->iucv_handle = NULL;
411 not_registered:
412         if (logptr->autorecording)
413                 vmlogrdr_recording(logptr,0,logptr->autopurge);
414         logptr->dev_in_use = 0;
415         return -EIO;
416
417
418 }
419
420
421 static int
422 vmlogrdr_release (struct inode *inode, struct file *filp)
423 {
424         int ret;
425
426         struct vmlogrdr_priv_t * logptr = filp->private_data;
427
428         iucv_unregister_program(logptr->iucv_handle);
429         logptr->iucv_handle = NULL;
430
431         if (logptr->autorecording) {
432                 ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
433                 if (ret)
434                         printk (KERN_WARNING "vmlogrdr: failed to stop "
435                                 "recording automatically\n");
436         }
437         logptr->dev_in_use = 0;
438
439         return 0;
440 }
441
442
443 static int
444 vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
445         int rc, *temp;
446         /* we need to keep track of two data sizes here:
447          * The number of bytes we need to receive from iucv and
448          * the total number of bytes we actually write into the buffer.
449          */
450         int user_data_count, iucv_data_count;
451         char * buffer;
452
453         if (atomic_read(&priv->receive_ready)) {
454                 spin_lock_bh(&priv->priv_lock);
455                 if (priv->residual_length){
456                         /* receive second half of a record */
457                         iucv_data_count = priv->residual_length;
458                         user_data_count = 0;
459                         buffer = priv->buffer;
460                 } else {
461                         /* receive a new record:
462                          * We need to return the total length of the record
463                          * + size of FENCE in the first 4 bytes of the buffer.
464                          */
465                         iucv_data_count =
466                                 priv->local_interrupt_buffer.ln1msg2.ipbfln1f;
467                         user_data_count = sizeof(int);
468                         temp = (int*)priv->buffer;
469                         *temp= iucv_data_count + sizeof(FENCE);
470                         buffer = priv->buffer + sizeof(int);
471                 }
472                 /*
473                  * If the record is bigger then our buffer, we receive only
474                  * a part of it. We can get the rest later.
475                  */
476                 if (iucv_data_count > NET_BUFFER_SIZE)
477                         iucv_data_count = NET_BUFFER_SIZE;
478                 rc = iucv_receive(priv->pathid,
479                                   priv->local_interrupt_buffer.ipmsgid,
480                                   priv->local_interrupt_buffer.iptrgcls,
481                                   buffer,
482                                   iucv_data_count,
483                                   NULL,
484                                   NULL,
485                                   &priv->residual_length);
486                 spin_unlock_bh(&priv->priv_lock);
487                 /* An rc of 5 indicates that the record was bigger then
488                  * the buffer, which is OK for us. A 9 indicates that the
489                  * record was purged befor we could receive it.
490                  */
491                 if (rc == 5)
492                         rc = 0;
493                 if (rc == 9)
494                         atomic_set(&priv->receive_ready, 0);
495         } else {
496                 rc = 1;
497         }
498         if (!rc) {
499                 priv->buffer_free = 0;
500                 user_data_count += iucv_data_count;
501                 priv->current_position = priv->buffer;
502                 if (priv->residual_length == 0){
503                         /* the whole record has been captured,
504                          * now add the fence */
505                         atomic_dec(&priv->receive_ready);
506                         buffer = priv->buffer + user_data_count;
507                         memcpy(buffer, FENCE, sizeof(FENCE));
508                         user_data_count += sizeof(FENCE);
509                 }
510                 priv->remaining = user_data_count;
511         }
512
513         return rc;
514 }
515
516
517 static ssize_t
518 vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
519 {
520         int rc;
521         struct vmlogrdr_priv_t * priv = filp->private_data;
522
523         while (priv->buffer_free) {
524                 rc = vmlogrdr_receive_data(priv);
525                 if (rc) {
526                         rc = wait_event_interruptible(read_wait_queue,
527                                         atomic_read(&priv->receive_ready));
528                         if (rc)
529                                 return rc;
530                 }
531         }
532         /* copy only up to end of record */
533         if (count > priv->remaining)
534                 count = priv->remaining;
535
536         if (copy_to_user(data, priv->current_position, count))
537                 return -EFAULT;
538
539         *ppos += count;
540         priv->current_position += count;
541         priv->remaining -= count;
542
543         /* if all data has been transferred, set buffer free */
544         if (priv->remaining == 0)
545                 priv->buffer_free = 1;
546
547         return count;
548 }
549
550 static ssize_t
551 vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
552         struct vmlogrdr_priv_t *priv = dev->driver_data;
553         ssize_t ret = count;
554
555         switch (buf[0]) {
556         case '0':
557                 priv->autopurge=0;
558                 break;
559         case '1':
560                 priv->autopurge=1;
561                 break;
562         default:
563                 ret = -EINVAL;
564         }
565         return ret;
566 }
567
568
569 static ssize_t
570 vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {
571         struct vmlogrdr_priv_t *priv = dev->driver_data;
572         return sprintf(buf, "%u\n", priv->autopurge);
573 }
574
575
576 static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
577                    vmlogrdr_autopurge_store);
578
579
580 static ssize_t
581 vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
582
583         char cp_command[80];
584         char cp_response[80];
585         struct vmlogrdr_priv_t *priv = dev->driver_data;
586
587         if (buf[0] != '1')
588                 return -EINVAL;
589
590         memset(cp_command, 0x00, sizeof(cp_command));
591         memset(cp_response, 0x00, sizeof(cp_response));
592
593         /*
594          * The recording command needs to be called with option QID
595          * for guests that have previlege classes A or B.
596          * Other guests will not recognize the command and we have to
597          * issue the same command without the QID parameter.
598          */
599
600         if (recording_class_AB)
601                 snprintf(cp_command, sizeof(cp_command),
602                          "RECORDING %s PURGE QID * ",
603                          priv->recording_name);
604         else
605                 snprintf(cp_command, sizeof(cp_command),
606                          "RECORDING %s PURGE ",
607                          priv->recording_name);
608
609         printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
610         cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
611         printk (KERN_DEBUG "vmlogrdr: recording response: %s",
612                 cp_response);
613
614         return count;
615 }
616
617
618 static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
619
620
621 static ssize_t
622 vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,
623                              size_t count) {
624         struct vmlogrdr_priv_t *priv = dev->driver_data;
625         ssize_t ret = count;
626
627         switch (buf[0]) {
628         case '0':
629                 priv->autorecording=0;
630                 break;
631         case '1':
632                 priv->autorecording=1;
633                 break;
634         default:
635                 ret = -EINVAL;
636         }
637         return ret;
638 }
639
640
641 static ssize_t
642 vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {
643         struct vmlogrdr_priv_t *priv = dev->driver_data;
644         return sprintf(buf, "%u\n", priv->autorecording);
645 }
646
647
648 static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
649                    vmlogrdr_autorecording_store);
650
651
652 static ssize_t
653 vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
654
655         struct vmlogrdr_priv_t *priv = dev->driver_data;
656         ssize_t ret;
657
658         switch (buf[0]) {
659         case '0':
660                 ret = vmlogrdr_recording(priv,0,0);
661                 break;
662         case '1':
663                 ret = vmlogrdr_recording(priv,1,0);
664                 break;
665         default:
666                 ret = -EINVAL;
667         }
668         if (ret)
669                 return ret;
670         else
671                 return count;
672
673 }
674
675
676 static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
677
678
679 static ssize_t
680 vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {
681
682         char cp_command[] = "QUERY RECORDING ";
683         int len;
684
685         cpcmd(cp_command, buf, 4096, NULL);
686         len = strlen(buf);
687         return len;
688 }
689
690
691 static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show,
692                    NULL);
693
694 static struct attribute *vmlogrdr_attrs[] = {
695         &dev_attr_autopurge.attr,
696         &dev_attr_purge.attr,
697         &dev_attr_autorecording.attr,
698         &dev_attr_recording.attr,
699         NULL,
700 };
701
702 static struct attribute_group vmlogrdr_attr_group = {
703         .attrs = vmlogrdr_attrs,
704 };
705
706 static struct class *vmlogrdr_class;
707 static struct device_driver vmlogrdr_driver = {
708         .name = "vmlogrdr",
709         .bus  = &iucv_bus,
710 };
711
712
713 static int
714 vmlogrdr_register_driver(void) {
715         int ret;
716
717         ret = driver_register(&vmlogrdr_driver);
718         if (ret) {
719                 printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
720                 return ret;
721         }
722
723         ret = driver_create_file(&vmlogrdr_driver,
724                                  &driver_attr_recording_status);
725         if (ret) {
726                 printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
727                 goto unregdriver;
728         }
729
730         vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
731         if (IS_ERR(vmlogrdr_class)) {
732                 printk(KERN_ERR "vmlogrdr: failed to create class.\n");
733                 ret=PTR_ERR(vmlogrdr_class);
734                 vmlogrdr_class=NULL;
735                 goto unregattr;
736         }
737         return 0;
738
739 unregattr:
740         driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
741 unregdriver:
742         driver_unregister(&vmlogrdr_driver);
743         return ret;
744 }
745
746
747 static void
748 vmlogrdr_unregister_driver(void) {
749         class_destroy(vmlogrdr_class);
750         vmlogrdr_class = NULL;
751         driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
752         driver_unregister(&vmlogrdr_driver);
753         return;
754 }
755
756
757 static int
758 vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
759         struct device *dev;
760         int ret;
761
762         dev = kzalloc(sizeof(struct device), GFP_KERNEL);
763         if (dev) {
764                 snprintf(dev->bus_id, BUS_ID_SIZE, "%s",
765                          priv->internal_name);
766                 dev->bus = &iucv_bus;
767                 dev->parent = iucv_root;
768                 dev->driver = &vmlogrdr_driver;
769                 /*
770                  * The release function could be called after the
771                  * module has been unloaded. It's _only_ task is to
772                  * free the struct. Therefore, we specify kfree()
773                  * directly here. (Probably a little bit obfuscating
774                  * but legitime ...).
775                  */
776                 dev->release = (void (*)(struct device *))kfree;
777         } else
778                 return -ENOMEM;
779         ret = device_register(dev);
780         if (ret)
781                 return ret;
782
783         ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group);
784         if (ret) {
785                 device_unregister(dev);
786                 return ret;
787         }
788         priv->class_device = class_device_create(
789                                 vmlogrdr_class,
790                                 NULL,
791                                 MKDEV(vmlogrdr_major, priv->minor_num),
792                                 dev,
793                                 "%s", dev->bus_id );
794         if (IS_ERR(priv->class_device)) {
795                 ret = PTR_ERR(priv->class_device);
796                 priv->class_device=NULL;
797                 sysfs_remove_group(&dev->kobj, &vmlogrdr_attr_group);
798                 device_unregister(dev);
799                 return ret;
800         }
801         dev->driver_data = priv;
802         priv->device = dev;
803         return 0;
804 }
805
806
807 static int
808 vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
809         class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
810         if (priv->device != NULL) {
811                 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
812                 device_unregister(priv->device);
813                 priv->device=NULL;
814         }
815         return 0;
816 }
817
818
819 static int
820 vmlogrdr_register_cdev(dev_t dev) {
821         int rc = 0;
822         vmlogrdr_cdev = cdev_alloc();
823         if (!vmlogrdr_cdev) {
824                 return -ENOMEM;
825         }
826         vmlogrdr_cdev->owner = THIS_MODULE;
827         vmlogrdr_cdev->ops = &vmlogrdr_fops;
828         vmlogrdr_cdev->dev = dev;
829         rc = cdev_add(vmlogrdr_cdev, vmlogrdr_cdev->dev, MAXMINOR);
830         if (!rc)
831                 return 0;
832
833         // cleanup: cdev is not fully registered, no cdev_del here!
834         kobject_put(&vmlogrdr_cdev->kobj);
835         vmlogrdr_cdev=NULL;
836         return rc;
837 }
838
839
840 static void
841 vmlogrdr_cleanup(void) {
842         int i;
843         if (vmlogrdr_cdev) {
844                 cdev_del(vmlogrdr_cdev);
845                 vmlogrdr_cdev=NULL;
846         }
847         for (i=0; i < MAXMINOR; ++i ) {
848                 vmlogrdr_unregister_device(&sys_ser[i]);
849                 free_page((unsigned long)sys_ser[i].buffer);
850         }
851         vmlogrdr_unregister_driver();
852         if (vmlogrdr_major) {
853                 unregister_chrdev_region(MKDEV(vmlogrdr_major, 0), MAXMINOR);
854                 vmlogrdr_major=0;
855         }
856 }
857
858
859 static int
860 vmlogrdr_init(void)
861 {
862         int rc;
863         int i;
864         dev_t dev;
865
866         if (! MACHINE_IS_VM) {
867                 printk (KERN_ERR "vmlogrdr: not running under VM, "
868                                 "driver not loaded.\n");
869                 return -ENODEV;
870         }
871
872         recording_class_AB = vmlogrdr_get_recording_class_AB();
873
874         rc = alloc_chrdev_region(&dev, 0, MAXMINOR, "vmlogrdr");
875         if (rc)
876                 return rc;
877         vmlogrdr_major = MAJOR(dev);
878
879         rc=vmlogrdr_register_driver();
880         if (rc)
881                 goto cleanup;
882
883         for (i=0; i < MAXMINOR; ++i ) {
884                 sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
885                 if (!sys_ser[i].buffer) {
886                         rc = ENOMEM;
887                         break;
888                 }
889                 sys_ser[i].current_position = sys_ser[i].buffer;
890                 rc=vmlogrdr_register_device(&sys_ser[i]);
891                 if (rc)
892                         break;
893         }
894         if (rc)
895                 goto cleanup;
896
897         rc = vmlogrdr_register_cdev(dev);
898         if (rc)
899                 goto cleanup;
900         printk (KERN_INFO "vmlogrdr: driver loaded\n");
901         return 0;
902
903 cleanup:
904         vmlogrdr_cleanup();
905         printk (KERN_ERR "vmlogrdr: driver not loaded.\n");
906         return rc;
907 }
908
909
910 static void
911 vmlogrdr_exit(void)
912 {
913         vmlogrdr_cleanup();
914         printk (KERN_INFO "vmlogrdr: driver unloaded\n");
915         return;
916 }
917
918
919 module_init(vmlogrdr_init);
920 module_exit(vmlogrdr_exit);