1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * IBM ASM Service Processor Device Driver 4 * 5 * Copyright (C) IBM Corporation, 2004 6 * 7 * Author: Max Asböck <amax@us.ibm.com> 8 */ 9 10 /* 11 * Parts of this code are based on an article by Jonathan Corbet 12 * that appeared in Linux Weekly News. 13 */ 14 15 16 /* 17 * The IBMASM file virtual filesystem. It creates the following hierarchy 18 * dynamically when mounted from user space: 19 * 20 * /ibmasm 21 * |-- 0 22 * | |-- command 23 * | |-- event 24 * | |-- reverse_heartbeat 25 * | `-- remote_video 26 * | |-- depth 27 * | |-- height 28 * | `-- width 29 * . 30 * . 31 * . 32 * `-- n 33 * |-- command 34 * |-- event 35 * |-- reverse_heartbeat 36 * `-- remote_video 37 * |-- depth 38 * |-- height 39 * `-- width 40 * 41 * For each service processor the following files are created: 42 * 43 * command: execute dot commands 44 * write: execute a dot command on the service processor 45 * read: return the result of a previously executed dot command 46 * 47 * events: listen for service processor events 48 * read: sleep (interruptible) until an event occurs 49 * write: wakeup sleeping event listener 50 * 51 * reverse_heartbeat: send a heartbeat to the service processor 52 * read: sleep (interruptible) until the reverse heartbeat fails 53 * write: wakeup sleeping heartbeat listener 54 * 55 * remote_video/width 56 * remote_video/height 57 * remote_video/width: control remote display settings 58 * write: set value 59 * read: read value 60 */ 61 62 #include <linux/fs.h> 63 #include <linux/fs_context.h> 64 #include <linux/pagemap.h> 65 #include <linux/slab.h> 66 #include <linux/uaccess.h> 67 #include <asm/io.h> 68 #include "ibmasm.h" 69 #include "remote.h" 70 #include "dot_command.h" 71 72 #define IBMASMFS_MAGIC 0x66726f67 73 74 static LIST_HEAD(service_processors); 75 76 static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode); 77 static void ibmasmfs_create_files (struct super_block *sb); 78 static int ibmasmfs_fill_super(struct super_block *sb, struct fs_context *fc); 79 80 static int ibmasmfs_get_tree(struct fs_context *fc) 81 { 82 return get_tree_single(fc, ibmasmfs_fill_super); 83 } 84 85 static const struct fs_context_operations ibmasmfs_context_ops = { 86 .get_tree = ibmasmfs_get_tree, 87 }; 88 89 static int ibmasmfs_init_fs_context(struct fs_context *fc) 90 { 91 fc->ops = &ibmasmfs_context_ops; 92 return 0; 93 } 94 95 static const struct super_operations ibmasmfs_s_ops = { 96 .statfs = simple_statfs, 97 .drop_inode = inode_just_drop, 98 }; 99 100 static struct file_system_type ibmasmfs_type = { 101 .owner = THIS_MODULE, 102 .name = "ibmasmfs", 103 .init_fs_context = ibmasmfs_init_fs_context, 104 .kill_sb = kill_anon_super, 105 }; 106 MODULE_ALIAS_FS("ibmasmfs"); 107 108 static int ibmasmfs_fill_super(struct super_block *sb, struct fs_context *fc) 109 { 110 struct inode *root; 111 112 sb->s_blocksize = PAGE_SIZE; 113 sb->s_blocksize_bits = PAGE_SHIFT; 114 sb->s_magic = IBMASMFS_MAGIC; 115 sb->s_op = &ibmasmfs_s_ops; 116 sb->s_time_gran = 1; 117 118 root = ibmasmfs_make_inode (sb, S_IFDIR | 0500); 119 if (!root) 120 return -ENOMEM; 121 122 root->i_op = &simple_dir_inode_operations; 123 root->i_fop = &simple_dir_operations; 124 125 sb->s_root = d_make_root(root); 126 if (!sb->s_root) 127 return -ENOMEM; 128 129 ibmasmfs_create_files(sb); 130 return 0; 131 } 132 133 static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode) 134 { 135 struct inode *ret = new_inode(sb); 136 137 if (ret) { 138 ret->i_ino = get_next_ino(); 139 ret->i_mode = mode; 140 simple_inode_init_ts(ret); 141 } 142 return ret; 143 } 144 145 static int ibmasmfs_create_file(struct dentry *parent, 146 const char *name, 147 const struct file_operations *fops, 148 void *data, 149 int mode) 150 { 151 struct dentry *dentry; 152 struct inode *inode; 153 154 dentry = d_alloc_name(parent, name); 155 if (!dentry) 156 return -ENOMEM; 157 158 inode = ibmasmfs_make_inode(parent->d_sb, S_IFREG | mode); 159 if (!inode) { 160 dput(dentry); 161 return -ENOMEM; 162 } 163 164 inode->i_fop = fops; 165 inode->i_private = data; 166 167 d_make_persistent(dentry, inode); 168 dput(dentry); 169 return 0; 170 } 171 172 static struct dentry *ibmasmfs_create_dir(struct dentry *parent, 173 const char *name) 174 { 175 struct dentry *dentry; 176 struct inode *inode; 177 178 dentry = d_alloc_name(parent, name); 179 if (!dentry) 180 return NULL; 181 182 inode = ibmasmfs_make_inode(parent->d_sb, S_IFDIR | 0500); 183 if (!inode) { 184 dput(dentry); 185 return NULL; 186 } 187 188 inode->i_op = &simple_dir_inode_operations; 189 inode->i_fop = &simple_dir_operations; 190 191 d_make_persistent(dentry, inode); 192 dput(dentry); 193 return dentry; // borrowed 194 } 195 196 int ibmasmfs_register(void) 197 { 198 return register_filesystem(&ibmasmfs_type); 199 } 200 201 void ibmasmfs_unregister(void) 202 { 203 unregister_filesystem(&ibmasmfs_type); 204 } 205 206 void ibmasmfs_add_sp(struct service_processor *sp) 207 { 208 list_add(&sp->node, &service_processors); 209 } 210 211 /* struct to save state between command file operations */ 212 struct ibmasmfs_command_data { 213 struct service_processor *sp; 214 struct command *command; 215 }; 216 217 /* struct to save state between event file operations */ 218 struct ibmasmfs_event_data { 219 struct service_processor *sp; 220 struct event_reader reader; 221 int active; 222 }; 223 224 /* struct to save state between reverse heartbeat file operations */ 225 struct ibmasmfs_heartbeat_data { 226 struct service_processor *sp; 227 struct reverse_heartbeat heartbeat; 228 int active; 229 }; 230 231 static int command_file_open(struct inode *inode, struct file *file) 232 { 233 struct ibmasmfs_command_data *command_data; 234 235 if (!inode->i_private) 236 return -ENODEV; 237 238 command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL); 239 if (!command_data) 240 return -ENOMEM; 241 242 command_data->command = NULL; 243 command_data->sp = inode->i_private; 244 file->private_data = command_data; 245 return 0; 246 } 247 248 static int command_file_close(struct inode *inode, struct file *file) 249 { 250 struct ibmasmfs_command_data *command_data = file->private_data; 251 252 if (command_data->command) 253 command_put(command_data->command); 254 255 kfree(command_data); 256 return 0; 257 } 258 259 static ssize_t command_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 260 { 261 struct ibmasmfs_command_data *command_data = file->private_data; 262 struct command *cmd; 263 int len; 264 unsigned long flags; 265 266 if (*offset < 0) 267 return -EINVAL; 268 if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE) 269 return 0; 270 if (*offset != 0) 271 return 0; 272 273 spin_lock_irqsave(&command_data->sp->lock, flags); 274 cmd = command_data->command; 275 if (cmd == NULL) { 276 spin_unlock_irqrestore(&command_data->sp->lock, flags); 277 return 0; 278 } 279 command_data->command = NULL; 280 spin_unlock_irqrestore(&command_data->sp->lock, flags); 281 282 if (cmd->status != IBMASM_CMD_COMPLETE) { 283 command_put(cmd); 284 return -EIO; 285 } 286 len = min(count, cmd->buffer_size); 287 if (copy_to_user(buf, cmd->buffer, len)) { 288 command_put(cmd); 289 return -EFAULT; 290 } 291 command_put(cmd); 292 293 return len; 294 } 295 296 static ssize_t command_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) 297 { 298 struct ibmasmfs_command_data *command_data = file->private_data; 299 struct command *cmd; 300 unsigned long flags; 301 302 if (*offset < 0) 303 return -EINVAL; 304 if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE) 305 return 0; 306 if (*offset != 0) 307 return 0; 308 309 /* commands are executed sequentially, only one command at a time */ 310 if (command_data->command) 311 return -EAGAIN; 312 313 cmd = ibmasm_new_command(command_data->sp, count); 314 if (!cmd) 315 return -ENOMEM; 316 317 if (copy_from_user(cmd->buffer, ubuff, count)) { 318 command_put(cmd); 319 return -EFAULT; 320 } 321 322 spin_lock_irqsave(&command_data->sp->lock, flags); 323 if (command_data->command) { 324 spin_unlock_irqrestore(&command_data->sp->lock, flags); 325 command_put(cmd); 326 return -EAGAIN; 327 } 328 command_data->command = cmd; 329 spin_unlock_irqrestore(&command_data->sp->lock, flags); 330 331 ibmasm_exec_command(command_data->sp, cmd); 332 ibmasm_wait_for_response(cmd, get_dot_command_timeout(cmd->buffer)); 333 334 return count; 335 } 336 337 static int event_file_open(struct inode *inode, struct file *file) 338 { 339 struct ibmasmfs_event_data *event_data; 340 struct service_processor *sp; 341 342 if (!inode->i_private) 343 return -ENODEV; 344 345 sp = inode->i_private; 346 347 event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL); 348 if (!event_data) 349 return -ENOMEM; 350 351 ibmasm_event_reader_register(sp, &event_data->reader); 352 353 event_data->sp = sp; 354 event_data->active = 0; 355 file->private_data = event_data; 356 return 0; 357 } 358 359 static int event_file_close(struct inode *inode, struct file *file) 360 { 361 struct ibmasmfs_event_data *event_data = file->private_data; 362 363 ibmasm_event_reader_unregister(event_data->sp, &event_data->reader); 364 kfree(event_data); 365 return 0; 366 } 367 368 static ssize_t event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 369 { 370 struct ibmasmfs_event_data *event_data = file->private_data; 371 struct event_reader *reader = &event_data->reader; 372 struct service_processor *sp = event_data->sp; 373 int ret; 374 unsigned long flags; 375 376 if (*offset < 0) 377 return -EINVAL; 378 if (count == 0 || count > IBMASM_EVENT_MAX_SIZE) 379 return 0; 380 if (*offset != 0) 381 return 0; 382 383 spin_lock_irqsave(&sp->lock, flags); 384 if (event_data->active) { 385 spin_unlock_irqrestore(&sp->lock, flags); 386 return -EBUSY; 387 } 388 event_data->active = 1; 389 spin_unlock_irqrestore(&sp->lock, flags); 390 391 ret = ibmasm_get_next_event(sp, reader); 392 if (ret <= 0) 393 goto out; 394 395 if (count < reader->data_size) { 396 ret = -EINVAL; 397 goto out; 398 } 399 400 if (copy_to_user(buf, reader->data, reader->data_size)) { 401 ret = -EFAULT; 402 goto out; 403 } 404 ret = reader->data_size; 405 406 out: 407 event_data->active = 0; 408 return ret; 409 } 410 411 static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 412 { 413 struct ibmasmfs_event_data *event_data = file->private_data; 414 415 if (*offset < 0) 416 return -EINVAL; 417 if (count != 1) 418 return 0; 419 if (*offset != 0) 420 return 0; 421 422 ibmasm_cancel_next_event(&event_data->reader); 423 return 0; 424 } 425 426 static int r_heartbeat_file_open(struct inode *inode, struct file *file) 427 { 428 struct ibmasmfs_heartbeat_data *rhbeat; 429 430 if (!inode->i_private) 431 return -ENODEV; 432 433 rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL); 434 if (!rhbeat) 435 return -ENOMEM; 436 437 rhbeat->sp = inode->i_private; 438 rhbeat->active = 0; 439 ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); 440 file->private_data = rhbeat; 441 return 0; 442 } 443 444 static int r_heartbeat_file_close(struct inode *inode, struct file *file) 445 { 446 struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; 447 448 kfree(rhbeat); 449 return 0; 450 } 451 452 static ssize_t r_heartbeat_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 453 { 454 struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; 455 unsigned long flags; 456 int result; 457 458 if (*offset < 0) 459 return -EINVAL; 460 if (count == 0 || count > 1024) 461 return 0; 462 if (*offset != 0) 463 return 0; 464 465 /* allow only one reverse heartbeat per process */ 466 spin_lock_irqsave(&rhbeat->sp->lock, flags); 467 if (rhbeat->active) { 468 spin_unlock_irqrestore(&rhbeat->sp->lock, flags); 469 return -EBUSY; 470 } 471 rhbeat->active = 1; 472 spin_unlock_irqrestore(&rhbeat->sp->lock, flags); 473 474 result = ibmasm_start_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); 475 rhbeat->active = 0; 476 477 return result; 478 } 479 480 static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 481 { 482 struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; 483 484 if (*offset < 0) 485 return -EINVAL; 486 if (count != 1) 487 return 0; 488 if (*offset != 0) 489 return 0; 490 491 if (rhbeat->active) 492 ibmasm_stop_reverse_heartbeat(&rhbeat->heartbeat); 493 494 return 1; 495 } 496 497 static int remote_settings_file_close(struct inode *inode, struct file *file) 498 { 499 return 0; 500 } 501 502 static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 503 { 504 void __iomem *address = (void __iomem *)file->private_data; 505 int len = 0; 506 unsigned int value; 507 char lbuf[20]; 508 509 value = readl(address); 510 len = snprintf(lbuf, sizeof(lbuf), "%d\n", value); 511 512 return simple_read_from_buffer(buf, count, offset, lbuf, len); 513 } 514 515 static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) 516 { 517 void __iomem *address = (void __iomem *)file->private_data; 518 char *buff; 519 unsigned int value; 520 521 if (*offset < 0) 522 return -EINVAL; 523 if (count == 0 || count > 1024) 524 return 0; 525 if (*offset != 0) 526 return 0; 527 528 buff = memdup_user_nul(ubuff, count); 529 if (IS_ERR(buff)) 530 return PTR_ERR(buff); 531 532 value = simple_strtoul(buff, NULL, 10); 533 writel(value, address); 534 kfree(buff); 535 536 return count; 537 } 538 539 static const struct file_operations command_fops = { 540 .open = command_file_open, 541 .release = command_file_close, 542 .read = command_file_read, 543 .write = command_file_write, 544 .llseek = generic_file_llseek, 545 }; 546 547 static const struct file_operations event_fops = { 548 .open = event_file_open, 549 .release = event_file_close, 550 .read = event_file_read, 551 .write = event_file_write, 552 .llseek = generic_file_llseek, 553 }; 554 555 static const struct file_operations r_heartbeat_fops = { 556 .open = r_heartbeat_file_open, 557 .release = r_heartbeat_file_close, 558 .read = r_heartbeat_file_read, 559 .write = r_heartbeat_file_write, 560 .llseek = generic_file_llseek, 561 }; 562 563 static const struct file_operations remote_settings_fops = { 564 .open = simple_open, 565 .release = remote_settings_file_close, 566 .read = remote_settings_file_read, 567 .write = remote_settings_file_write, 568 .llseek = generic_file_llseek, 569 }; 570 571 572 static void ibmasmfs_create_files (struct super_block *sb) 573 { 574 struct list_head *entry; 575 struct service_processor *sp; 576 577 list_for_each(entry, &service_processors) { 578 struct dentry *dir; 579 struct dentry *remote_dir; 580 sp = list_entry(entry, struct service_processor, node); 581 dir = ibmasmfs_create_dir(sb->s_root, sp->dirname); 582 if (!dir) 583 continue; 584 585 ibmasmfs_create_file(dir, "command", &command_fops, sp, S_IRUSR|S_IWUSR); 586 ibmasmfs_create_file(dir, "event", &event_fops, sp, S_IRUSR|S_IWUSR); 587 ibmasmfs_create_file(dir, "reverse_heartbeat", &r_heartbeat_fops, sp, S_IRUSR|S_IWUSR); 588 589 remote_dir = ibmasmfs_create_dir(dir, "remote_video"); 590 if (!remote_dir) 591 continue; 592 593 ibmasmfs_create_file(remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR); 594 ibmasmfs_create_file(remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR); 595 ibmasmfs_create_file(remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR); 596 } 597 } 598