aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/char/monwriter.c98
1 files changed, 92 insertions, 6 deletions
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index c7d7483bab9a..66fb8eba93f4 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -1,9 +1,7 @@
1/* 1/*
2 * drivers/s390/char/monwriter.c
3 *
4 * Character device driver for writing z/VM *MONITOR service records. 2 * Character device driver for writing z/VM *MONITOR service records.
5 * 3 *
6 * Copyright (C) IBM Corp. 2006 4 * Copyright IBM Corp. 2006, 2009
7 * 5 *
8 * Author(s): Melissa Howland <Melissa.Howland@us.ibm.com> 6 * Author(s): Melissa Howland <Melissa.Howland@us.ibm.com>
9 */ 7 */
@@ -22,6 +20,7 @@
22#include <linux/ctype.h> 20#include <linux/ctype.h>
23#include <linux/poll.h> 21#include <linux/poll.h>
24#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/platform_device.h>
25#include <asm/uaccess.h> 24#include <asm/uaccess.h>
26#include <asm/ebcdic.h> 25#include <asm/ebcdic.h>
27#include <asm/io.h> 26#include <asm/io.h>
@@ -40,7 +39,10 @@ struct mon_buf {
40 char *data; 39 char *data;
41}; 40};
42 41
42static LIST_HEAD(mon_priv_list);
43
43struct mon_private { 44struct mon_private {
45 struct list_head priv_list;
44 struct list_head list; 46 struct list_head list;
45 struct monwrite_hdr hdr; 47 struct monwrite_hdr hdr;
46 size_t hdr_to_read; 48 size_t hdr_to_read;
@@ -188,6 +190,7 @@ static int monwrite_open(struct inode *inode, struct file *filp)
188 monpriv->hdr_to_read = sizeof(monpriv->hdr); 190 monpriv->hdr_to_read = sizeof(monpriv->hdr);
189 mutex_init(&monpriv->thread_mutex); 191 mutex_init(&monpriv->thread_mutex);
190 filp->private_data = monpriv; 192 filp->private_data = monpriv;
193 list_add_tail(&monpriv->priv_list, &mon_priv_list);
191 unlock_kernel(); 194 unlock_kernel();
192 return nonseekable_open(inode, filp); 195 return nonseekable_open(inode, filp);
193} 196}
@@ -206,6 +209,7 @@ static int monwrite_close(struct inode *inode, struct file *filp)
206 kfree(entry->data); 209 kfree(entry->data);
207 kfree(entry); 210 kfree(entry);
208 } 211 }
212 list_del(&monpriv->priv_list);
209 kfree(monpriv); 213 kfree(monpriv);
210 return 0; 214 return 0;
211} 215}
@@ -281,20 +285,102 @@ static struct miscdevice mon_dev = {
281}; 285};
282 286
283/* 287/*
288 * suspend/resume
289 */
290
291static int monwriter_freeze(struct device *dev)
292{
293 struct mon_private *monpriv;
294 struct mon_buf *monbuf;
295
296 list_for_each_entry(monpriv, &mon_priv_list, priv_list) {
297 list_for_each_entry(monbuf, &monpriv->list, list) {
298 if (monbuf->hdr.mon_function != MONWRITE_GEN_EVENT)
299 monwrite_diag(&monbuf->hdr, monbuf->data,
300 APPLDATA_STOP_REC);
301 }
302 }
303 return 0;
304}
305
306static int monwriter_restore(struct device *dev)
307{
308 struct mon_private *monpriv;
309 struct mon_buf *monbuf;
310
311 list_for_each_entry(monpriv, &mon_priv_list, priv_list) {
312 list_for_each_entry(monbuf, &monpriv->list, list) {
313 if (monbuf->hdr.mon_function == MONWRITE_START_INTERVAL)
314 monwrite_diag(&monbuf->hdr, monbuf->data,
315 APPLDATA_START_INTERVAL_REC);
316 if (monbuf->hdr.mon_function == MONWRITE_START_CONFIG)
317 monwrite_diag(&monbuf->hdr, monbuf->data,
318 APPLDATA_START_CONFIG_REC);
319 }
320 }
321 return 0;
322}
323
324static int monwriter_thaw(struct device *dev)
325{
326 return monwriter_restore(dev);
327}
328
329static struct dev_pm_ops monwriter_pm_ops = {
330 .freeze = monwriter_freeze,
331 .thaw = monwriter_thaw,
332 .restore = monwriter_restore,
333};
334
335static struct platform_driver monwriter_pdrv = {
336 .driver = {
337 .name = "monwriter",
338 .owner = THIS_MODULE,
339 .pm = &monwriter_pm_ops,
340 },
341};
342
343static struct platform_device *monwriter_pdev;
344
345/*
284 * module init/exit 346 * module init/exit
285 */ 347 */
286 348
287static int __init mon_init(void) 349static int __init mon_init(void)
288{ 350{
289 if (MACHINE_IS_VM) 351 int rc;
290 return misc_register(&mon_dev); 352
291 else 353 if (!MACHINE_IS_VM)
292 return -ENODEV; 354 return -ENODEV;
355
356 rc = platform_driver_register(&monwriter_pdrv);
357 if (rc)
358 return rc;
359
360 monwriter_pdev = platform_device_register_simple("monwriter", -1, NULL,
361 0);
362 if (IS_ERR(monwriter_pdev)) {
363 rc = PTR_ERR(monwriter_pdev);
364 goto out_driver;
365 }
366
367 rc = misc_register(&mon_dev);
368 if (rc)
369 goto out_device;
370 return 0;
371
372out_device:
373 platform_device_unregister(monwriter_pdev);
374out_driver:
375 platform_driver_unregister(&monwriter_pdrv);
376 return rc;
293} 377}
294 378
295static void __exit mon_exit(void) 379static void __exit mon_exit(void)
296{ 380{
297 WARN_ON(misc_deregister(&mon_dev) != 0); 381 WARN_ON(misc_deregister(&mon_dev) != 0);
382 platform_device_unregister(monwriter_pdev);
383 platform_driver_unregister(&monwriter_pdrv);
298} 384}
299 385
300module_init(mon_init); 386module_init(mon_init);