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