xref: /openbmc/linux/drivers/s390/char/vmlogrdr.c (revision 87c2ce3b)
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 = kmalloc(sizeof(struct device), GFP_KERNEL);
763 	if (dev) {
764 		memset(dev, 0, sizeof(struct device));
765 		snprintf(dev->bus_id, BUS_ID_SIZE, "%s",
766 			 priv->internal_name);
767 		dev->bus = &iucv_bus;
768 		dev->parent = iucv_root;
769 		dev->driver = &vmlogrdr_driver;
770 		/*
771 		 * The release function could be called after the
772 		 * module has been unloaded. It's _only_ task is to
773 		 * free the struct. Therefore, we specify kfree()
774 		 * directly here. (Probably a little bit obfuscating
775 		 * but legitime ...).
776 		 */
777 		dev->release = (void (*)(struct device *))kfree;
778 	} else
779 		return -ENOMEM;
780 	ret = device_register(dev);
781 	if (ret)
782 		return ret;
783 
784 	ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group);
785 	if (ret) {
786 		device_unregister(dev);
787 		return ret;
788 	}
789 	priv->class_device = class_device_create(
790 				vmlogrdr_class,
791 				NULL,
792 				MKDEV(vmlogrdr_major, priv->minor_num),
793 				dev,
794 				"%s", dev->bus_id );
795 	if (IS_ERR(priv->class_device)) {
796 		ret = PTR_ERR(priv->class_device);
797 		priv->class_device=NULL;
798 		sysfs_remove_group(&dev->kobj, &vmlogrdr_attr_group);
799 		device_unregister(dev);
800 		return ret;
801 	}
802 	dev->driver_data = priv;
803 	priv->device = dev;
804 	return 0;
805 }
806 
807 
808 static int
809 vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
810 	class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
811 	if (priv->device != NULL) {
812 		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
813 		device_unregister(priv->device);
814 		priv->device=NULL;
815 	}
816 	return 0;
817 }
818 
819 
820 static int
821 vmlogrdr_register_cdev(dev_t dev) {
822 	int rc = 0;
823 	vmlogrdr_cdev = cdev_alloc();
824 	if (!vmlogrdr_cdev) {
825 		return -ENOMEM;
826 	}
827 	vmlogrdr_cdev->owner = THIS_MODULE;
828 	vmlogrdr_cdev->ops = &vmlogrdr_fops;
829 	vmlogrdr_cdev->dev = dev;
830 	rc = cdev_add(vmlogrdr_cdev, vmlogrdr_cdev->dev, MAXMINOR);
831 	if (!rc)
832 		return 0;
833 
834 	// cleanup: cdev is not fully registered, no cdev_del here!
835 	kobject_put(&vmlogrdr_cdev->kobj);
836 	vmlogrdr_cdev=NULL;
837 	return rc;
838 }
839 
840 
841 static void
842 vmlogrdr_cleanup(void) {
843         int i;
844 	if (vmlogrdr_cdev) {
845 		cdev_del(vmlogrdr_cdev);
846 		vmlogrdr_cdev=NULL;
847 	}
848 	for (i=0; i < MAXMINOR; ++i ) {
849 		vmlogrdr_unregister_device(&sys_ser[i]);
850 		free_page((unsigned long)sys_ser[i].buffer);
851 	}
852 	vmlogrdr_unregister_driver();
853 	if (vmlogrdr_major) {
854 		unregister_chrdev_region(MKDEV(vmlogrdr_major, 0), MAXMINOR);
855 		vmlogrdr_major=0;
856 	}
857 }
858 
859 
860 static int
861 vmlogrdr_init(void)
862 {
863 	int rc;
864 	int i;
865 	dev_t dev;
866 
867 	if (! MACHINE_IS_VM) {
868 		printk (KERN_ERR "vmlogrdr: not running under VM, "
869 				"driver not loaded.\n");
870 		return -ENODEV;
871 	}
872 
873         recording_class_AB = vmlogrdr_get_recording_class_AB();
874 
875 	rc = alloc_chrdev_region(&dev, 0, MAXMINOR, "vmlogrdr");
876 	if (rc)
877 		return rc;
878 	vmlogrdr_major = MAJOR(dev);
879 
880 	rc=vmlogrdr_register_driver();
881 	if (rc)
882 		goto cleanup;
883 
884 	for (i=0; i < MAXMINOR; ++i ) {
885 		sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
886 		if (!sys_ser[i].buffer) {
887 			rc = ENOMEM;
888 			break;
889 		}
890 		sys_ser[i].current_position = sys_ser[i].buffer;
891 		rc=vmlogrdr_register_device(&sys_ser[i]);
892 		if (rc)
893 			break;
894 	}
895 	if (rc)
896 		goto cleanup;
897 
898 	rc = vmlogrdr_register_cdev(dev);
899 	if (rc)
900 		goto cleanup;
901 	printk (KERN_INFO "vmlogrdr: driver loaded\n");
902 	return 0;
903 
904 cleanup:
905 	vmlogrdr_cleanup();
906 	printk (KERN_ERR "vmlogrdr: driver not loaded.\n");
907 	return rc;
908 }
909 
910 
911 static void
912 vmlogrdr_exit(void)
913 {
914 	vmlogrdr_cleanup();
915 	printk (KERN_INFO "vmlogrdr: driver unloaded\n");
916 	return;
917 }
918 
919 
920 module_init(vmlogrdr_init);
921 module_exit(vmlogrdr_exit);
922