const: constify remaining dev_pm_ops
[safe/jmp/linux-2.6] / drivers / s390 / char / monwriter.c
1 /*
2  * Character device driver for writing z/VM *MONITOR service records.
3  *
4  * Copyright IBM Corp. 2006, 2009
5  *
6  * Author(s): Melissa Howland <Melissa.Howland@us.ibm.com>
7  */
8
9 #define KMSG_COMPONENT "monwriter"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/types.h>
17 #include <linux/kernel.h>
18 #include <linux/miscdevice.h>
19 #include <linux/ctype.h>
20 #include <linux/poll.h>
21 #include <linux/mutex.h>
22 #include <linux/platform_device.h>
23 #include <asm/uaccess.h>
24 #include <asm/ebcdic.h>
25 #include <asm/io.h>
26 #include <asm/appldata.h>
27 #include <asm/monwriter.h>
28
29 #define MONWRITE_MAX_DATALEN    4010
30
31 static int mon_max_bufs = 255;
32 static int mon_buf_count;
33
34 struct mon_buf {
35         struct list_head list;
36         struct monwrite_hdr hdr;
37         int diag_done;
38         char *data;
39 };
40
41 static LIST_HEAD(mon_priv_list);
42
43 struct mon_private {
44         struct list_head priv_list;
45         struct list_head list;
46         struct monwrite_hdr hdr;
47         size_t hdr_to_read;
48         size_t data_to_read;
49         struct mon_buf *current_buf;
50         struct mutex thread_mutex;
51 };
52
53 /*
54  * helper functions
55  */
56
57 static int monwrite_diag(struct monwrite_hdr *myhdr, char *buffer, int fcn)
58 {
59         struct appldata_product_id id;
60         int rc;
61
62         strcpy(id.prod_nr, "LNXAPPL");
63         id.prod_fn = myhdr->applid;
64         id.record_nr = myhdr->record_num;
65         id.version_nr = myhdr->version;
66         id.release_nr = myhdr->release;
67         id.mod_lvl = myhdr->mod_level;
68         rc = appldata_asm(&id, fcn, (void *) buffer, myhdr->datalen);
69         if (rc <= 0)
70                 return rc;
71         pr_err("Writing monitor data failed with rc=%i\n", rc);
72         if (rc == 5)
73                 return -EPERM;
74         return -EINVAL;
75 }
76
77 static struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv,
78                                          struct monwrite_hdr *monhdr)
79 {
80         struct mon_buf *entry, *next;
81
82         list_for_each_entry_safe(entry, next, &monpriv->list, list)
83                 if ((entry->hdr.mon_function == monhdr->mon_function ||
84                      monhdr->mon_function == MONWRITE_STOP_INTERVAL) &&
85                     entry->hdr.applid == monhdr->applid &&
86                     entry->hdr.record_num == monhdr->record_num &&
87                     entry->hdr.version == monhdr->version &&
88                     entry->hdr.release == monhdr->release &&
89                     entry->hdr.mod_level == monhdr->mod_level)
90                         return entry;
91
92         return NULL;
93 }
94
95 static int monwrite_new_hdr(struct mon_private *monpriv)
96 {
97         struct monwrite_hdr *monhdr = &monpriv->hdr;
98         struct mon_buf *monbuf;
99         int rc;
100
101         if (monhdr->datalen > MONWRITE_MAX_DATALEN ||
102             monhdr->mon_function > MONWRITE_START_CONFIG ||
103             monhdr->hdrlen != sizeof(struct monwrite_hdr))
104                 return -EINVAL;
105         monbuf = NULL;
106         if (monhdr->mon_function != MONWRITE_GEN_EVENT)
107                 monbuf = monwrite_find_hdr(monpriv, monhdr);
108         if (monbuf) {
109                 if (monhdr->mon_function == MONWRITE_STOP_INTERVAL) {
110                         monhdr->datalen = monbuf->hdr.datalen;
111                         rc = monwrite_diag(monhdr, monbuf->data,
112                                            APPLDATA_STOP_REC);
113                         list_del(&monbuf->list);
114                         mon_buf_count--;
115                         kfree(monbuf->data);
116                         kfree(monbuf);
117                         monbuf = NULL;
118                 }
119         } else if (monhdr->mon_function != MONWRITE_STOP_INTERVAL) {
120                 if (mon_buf_count >= mon_max_bufs)
121                         return -ENOSPC;
122                 monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL);
123                 if (!monbuf)
124                         return -ENOMEM;
125                 monbuf->data = kzalloc(monhdr->datalen,
126                                        GFP_KERNEL | GFP_DMA);
127                 if (!monbuf->data) {
128                         kfree(monbuf);
129                         return -ENOMEM;
130                 }
131                 monbuf->hdr = *monhdr;
132                 list_add_tail(&monbuf->list, &monpriv->list);
133                 if (monhdr->mon_function != MONWRITE_GEN_EVENT)
134                         mon_buf_count++;
135         }
136         monpriv->current_buf = monbuf;
137         return 0;
138 }
139
140 static int monwrite_new_data(struct mon_private *monpriv)
141 {
142         struct monwrite_hdr *monhdr = &monpriv->hdr;
143         struct mon_buf *monbuf = monpriv->current_buf;
144         int rc = 0;
145
146         switch (monhdr->mon_function) {
147         case MONWRITE_START_INTERVAL:
148                 if (!monbuf->diag_done) {
149                         rc = monwrite_diag(monhdr, monbuf->data,
150                                            APPLDATA_START_INTERVAL_REC);
151                         monbuf->diag_done = 1;
152                 }
153                 break;
154         case MONWRITE_START_CONFIG:
155                 if (!monbuf->diag_done) {
156                         rc = monwrite_diag(monhdr, monbuf->data,
157                                            APPLDATA_START_CONFIG_REC);
158                         monbuf->diag_done = 1;
159                 }
160                 break;
161         case MONWRITE_GEN_EVENT:
162                 rc = monwrite_diag(monhdr, monbuf->data,
163                                    APPLDATA_GEN_EVENT_REC);
164                 list_del(&monpriv->current_buf->list);
165                 kfree(monpriv->current_buf->data);
166                 kfree(monpriv->current_buf);
167                 monpriv->current_buf = NULL;
168                 break;
169         default:
170                 /* monhdr->mon_function is checked in monwrite_new_hdr */
171                 BUG();
172         }
173         return rc;
174 }
175
176 /*
177  * file operations
178  */
179
180 static int monwrite_open(struct inode *inode, struct file *filp)
181 {
182         struct mon_private *monpriv;
183
184         monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
185         if (!monpriv)
186                 return -ENOMEM;
187         INIT_LIST_HEAD(&monpriv->list);
188         monpriv->hdr_to_read = sizeof(monpriv->hdr);
189         mutex_init(&monpriv->thread_mutex);
190         filp->private_data = monpriv;
191         list_add_tail(&monpriv->priv_list, &mon_priv_list);
192         return nonseekable_open(inode, filp);
193 }
194
195 static int monwrite_close(struct inode *inode, struct file *filp)
196 {
197         struct mon_private *monpriv = filp->private_data;
198         struct mon_buf *entry, *next;
199
200         list_for_each_entry_safe(entry, next, &monpriv->list, list) {
201                 if (entry->hdr.mon_function != MONWRITE_GEN_EVENT)
202                         monwrite_diag(&entry->hdr, entry->data,
203                                       APPLDATA_STOP_REC);
204                 mon_buf_count--;
205                 list_del(&entry->list);
206                 kfree(entry->data);
207                 kfree(entry);
208         }
209         list_del(&monpriv->priv_list);
210         kfree(monpriv);
211         return 0;
212 }
213
214 static ssize_t monwrite_write(struct file *filp, const char __user *data,
215                               size_t count, loff_t *ppos)
216 {
217         struct mon_private *monpriv = filp->private_data;
218         size_t len, written;
219         void *to;
220         int rc;
221
222         mutex_lock(&monpriv->thread_mutex);
223         for (written = 0; written < count; ) {
224                 if (monpriv->hdr_to_read) {
225                         len = min(count - written, monpriv->hdr_to_read);
226                         to = (char *) &monpriv->hdr +
227                                 sizeof(monpriv->hdr) - monpriv->hdr_to_read;
228                         if (copy_from_user(to, data + written, len)) {
229                                 rc = -EFAULT;
230                                 goto out_error;
231                         }
232                         monpriv->hdr_to_read -= len;
233                         written += len;
234                         if (monpriv->hdr_to_read > 0)
235                                 continue;
236                         rc = monwrite_new_hdr(monpriv);
237                         if (rc)
238                                 goto out_error;
239                         monpriv->data_to_read = monpriv->current_buf ?
240                                 monpriv->current_buf->hdr.datalen : 0;
241                 }
242
243                 if (monpriv->data_to_read) {
244                         len = min(count - written, monpriv->data_to_read);
245                         to = monpriv->current_buf->data +
246                                 monpriv->hdr.datalen - monpriv->data_to_read;
247                         if (copy_from_user(to, data + written, len)) {
248                                 rc = -EFAULT;
249                                 goto out_error;
250                         }
251                         monpriv->data_to_read -= len;
252                         written += len;
253                         if (monpriv->data_to_read > 0)
254                                 continue;
255                         rc = monwrite_new_data(monpriv);
256                         if (rc)
257                                 goto out_error;
258                 }
259                 monpriv->hdr_to_read = sizeof(monpriv->hdr);
260         }
261         mutex_unlock(&monpriv->thread_mutex);
262         return written;
263
264 out_error:
265         monpriv->data_to_read = 0;
266         monpriv->hdr_to_read = sizeof(struct monwrite_hdr);
267         mutex_unlock(&monpriv->thread_mutex);
268         return rc;
269 }
270
271 static const struct file_operations monwrite_fops = {
272         .owner   = THIS_MODULE,
273         .open    = &monwrite_open,
274         .release = &monwrite_close,
275         .write   = &monwrite_write,
276 };
277
278 static struct miscdevice mon_dev = {
279         .name   = "monwriter",
280         .fops   = &monwrite_fops,
281         .minor  = MISC_DYNAMIC_MINOR,
282 };
283
284 /*
285  * suspend/resume
286  */
287
288 static int monwriter_freeze(struct device *dev)
289 {
290         struct mon_private *monpriv;
291         struct mon_buf *monbuf;
292
293         list_for_each_entry(monpriv, &mon_priv_list, priv_list) {
294                 list_for_each_entry(monbuf, &monpriv->list, list) {
295                         if (monbuf->hdr.mon_function != MONWRITE_GEN_EVENT)
296                                 monwrite_diag(&monbuf->hdr, monbuf->data,
297                                               APPLDATA_STOP_REC);
298                 }
299         }
300         return 0;
301 }
302
303 static int monwriter_restore(struct device *dev)
304 {
305         struct mon_private *monpriv;
306         struct mon_buf *monbuf;
307
308         list_for_each_entry(monpriv, &mon_priv_list, priv_list) {
309                 list_for_each_entry(monbuf, &monpriv->list, list) {
310                         if (monbuf->hdr.mon_function == MONWRITE_START_INTERVAL)
311                                 monwrite_diag(&monbuf->hdr, monbuf->data,
312                                               APPLDATA_START_INTERVAL_REC);
313                         if (monbuf->hdr.mon_function == MONWRITE_START_CONFIG)
314                                 monwrite_diag(&monbuf->hdr, monbuf->data,
315                                               APPLDATA_START_CONFIG_REC);
316                 }
317         }
318         return 0;
319 }
320
321 static int monwriter_thaw(struct device *dev)
322 {
323         return monwriter_restore(dev);
324 }
325
326 static const struct dev_pm_ops monwriter_pm_ops = {
327         .freeze         = monwriter_freeze,
328         .thaw           = monwriter_thaw,
329         .restore        = monwriter_restore,
330 };
331
332 static struct platform_driver monwriter_pdrv = {
333         .driver = {
334                 .name   = "monwriter",
335                 .owner  = THIS_MODULE,
336                 .pm     = &monwriter_pm_ops,
337         },
338 };
339
340 static struct platform_device *monwriter_pdev;
341
342 /*
343  * module init/exit
344  */
345
346 static int __init mon_init(void)
347 {
348         int rc;
349
350         if (!MACHINE_IS_VM)
351                 return -ENODEV;
352
353         rc = platform_driver_register(&monwriter_pdrv);
354         if (rc)
355                 return rc;
356
357         monwriter_pdev = platform_device_register_simple("monwriter", -1, NULL,
358                                                         0);
359         if (IS_ERR(monwriter_pdev)) {
360                 rc = PTR_ERR(monwriter_pdev);
361                 goto out_driver;
362         }
363
364         /*
365          * misc_register() has to be the last action in module_init(), because
366          * file operations will be available right after this.
367          */
368         rc = misc_register(&mon_dev);
369         if (rc)
370                 goto out_device;
371         return 0;
372
373 out_device:
374         platform_device_unregister(monwriter_pdev);
375 out_driver:
376         platform_driver_unregister(&monwriter_pdrv);
377         return rc;
378 }
379
380 static void __exit mon_exit(void)
381 {
382         WARN_ON(misc_deregister(&mon_dev) != 0);
383         platform_device_unregister(monwriter_pdev);
384         platform_driver_unregister(&monwriter_pdrv);
385 }
386
387 module_init(mon_init);
388 module_exit(mon_exit);
389
390 module_param_named(max_bufs, mon_max_bufs, int, 0644);
391 MODULE_PARM_DESC(max_bufs, "Maximum number of sample monitor data buffers "
392                  "that can be active at one time");
393
394 MODULE_AUTHOR("Melissa Howland <Melissa.Howland@us.ibm.com>");
395 MODULE_DESCRIPTION("Character device driver for writing z/VM "
396                    "APPLDATA monitor records.");
397 MODULE_LICENSE("GPL");