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