xref: /linux/drivers/s390/char/vmlogrdr.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
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 *data, size_t count,
90 			       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 *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);
921