| .. | .. |
|---|
| 18 | 18 | #include <linux/slab.h> |
|---|
| 19 | 19 | #include <linux/atomic.h> |
|---|
| 20 | 20 | #include <linux/device.h> |
|---|
| 21 | +#include <linux/pm_runtime.h> |
|---|
| 21 | 22 | #include <linux/poll.h> |
|---|
| 23 | +#include <linux/security.h> |
|---|
| 22 | 24 | |
|---|
| 23 | 25 | #include "internal.h" |
|---|
| 24 | 26 | |
|---|
| .. | .. |
|---|
| 136 | 138 | } |
|---|
| 137 | 139 | EXPORT_SYMBOL_GPL(debugfs_file_put); |
|---|
| 138 | 140 | |
|---|
| 141 | +/* |
|---|
| 142 | + * Only permit access to world-readable files when the kernel is locked down. |
|---|
| 143 | + * We also need to exclude any file that has ways to write or alter it as root |
|---|
| 144 | + * can bypass the permissions check. |
|---|
| 145 | + */ |
|---|
| 146 | +static int debugfs_locked_down(struct inode *inode, |
|---|
| 147 | + struct file *filp, |
|---|
| 148 | + const struct file_operations *real_fops) |
|---|
| 149 | +{ |
|---|
| 150 | + if ((inode->i_mode & 07777 & ~0444) == 0 && |
|---|
| 151 | + !(filp->f_mode & FMODE_WRITE) && |
|---|
| 152 | + !real_fops->unlocked_ioctl && |
|---|
| 153 | + !real_fops->compat_ioctl && |
|---|
| 154 | + !real_fops->mmap) |
|---|
| 155 | + return 0; |
|---|
| 156 | + |
|---|
| 157 | + if (security_locked_down(LOCKDOWN_DEBUGFS)) |
|---|
| 158 | + return -EPERM; |
|---|
| 159 | + |
|---|
| 160 | + return 0; |
|---|
| 161 | +} |
|---|
| 162 | + |
|---|
| 139 | 163 | static int open_proxy_open(struct inode *inode, struct file *filp) |
|---|
| 140 | 164 | { |
|---|
| 141 | 165 | struct dentry *dentry = F_DENTRY(filp); |
|---|
| .. | .. |
|---|
| 147 | 171 | return r == -EIO ? -ENOENT : r; |
|---|
| 148 | 172 | |
|---|
| 149 | 173 | real_fops = debugfs_real_fops(filp); |
|---|
| 150 | | - real_fops = fops_get(real_fops); |
|---|
| 151 | | - if (!real_fops) { |
|---|
| 174 | + |
|---|
| 175 | + r = debugfs_locked_down(inode, filp, real_fops); |
|---|
| 176 | + if (r) |
|---|
| 177 | + goto out; |
|---|
| 178 | + |
|---|
| 179 | + if (!fops_get(real_fops)) { |
|---|
| 180 | +#ifdef CONFIG_MODULES |
|---|
| 181 | + if (real_fops->owner && |
|---|
| 182 | + real_fops->owner->state == MODULE_STATE_GOING) { |
|---|
| 183 | + r = -ENXIO; |
|---|
| 184 | + goto out; |
|---|
| 185 | + } |
|---|
| 186 | +#endif |
|---|
| 187 | + |
|---|
| 152 | 188 | /* Huh? Module did not clean up after itself at exit? */ |
|---|
| 153 | 189 | WARN(1, "debugfs file owner did not clean up at exit: %pd", |
|---|
| 154 | 190 | dentry); |
|---|
| .. | .. |
|---|
| 239 | 275 | r = real_fops->release(inode, filp); |
|---|
| 240 | 276 | |
|---|
| 241 | 277 | replace_fops(filp, d_inode(dentry)->i_fop); |
|---|
| 242 | | - kfree((void *)proxy_fops); |
|---|
| 278 | + kfree(proxy_fops); |
|---|
| 243 | 279 | fops_put(real_fops); |
|---|
| 244 | 280 | return r; |
|---|
| 245 | 281 | } |
|---|
| .. | .. |
|---|
| 272 | 308 | return r == -EIO ? -ENOENT : r; |
|---|
| 273 | 309 | |
|---|
| 274 | 310 | real_fops = debugfs_real_fops(filp); |
|---|
| 275 | | - real_fops = fops_get(real_fops); |
|---|
| 276 | | - if (!real_fops) { |
|---|
| 311 | + |
|---|
| 312 | + r = debugfs_locked_down(inode, filp, real_fops); |
|---|
| 313 | + if (r) |
|---|
| 314 | + goto out; |
|---|
| 315 | + |
|---|
| 316 | + if (!fops_get(real_fops)) { |
|---|
| 317 | +#ifdef CONFIG_MODULES |
|---|
| 318 | + if (real_fops->owner && |
|---|
| 319 | + real_fops->owner->state == MODULE_STATE_GOING) { |
|---|
| 320 | + r = -ENXIO; |
|---|
| 321 | + goto out; |
|---|
| 322 | + } |
|---|
| 323 | +#endif |
|---|
| 324 | + |
|---|
| 277 | 325 | /* Huh? Module did not cleanup after itself at exit? */ |
|---|
| 278 | 326 | WARN(1, "debugfs file owner did not clean up at exit: %pd", |
|---|
| 279 | 327 | dentry); |
|---|
| .. | .. |
|---|
| 390 | 438 | * This function creates a file in debugfs with the given name that |
|---|
| 391 | 439 | * contains the value of the variable @value. If the @mode variable is so |
|---|
| 392 | 440 | * set, it can be read from, and written to. |
|---|
| 393 | | - * |
|---|
| 394 | | - * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 395 | | - * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 396 | | - * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 397 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 398 | | - * |
|---|
| 399 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 400 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 401 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 402 | | - * code. |
|---|
| 403 | 441 | */ |
|---|
| 404 | | -struct dentry *debugfs_create_u8(const char *name, umode_t mode, |
|---|
| 405 | | - struct dentry *parent, u8 *value) |
|---|
| 442 | +void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 443 | + u8 *value) |
|---|
| 406 | 444 | { |
|---|
| 407 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8, |
|---|
| 445 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8, |
|---|
| 408 | 446 | &fops_u8_ro, &fops_u8_wo); |
|---|
| 409 | 447 | } |
|---|
| 410 | 448 | EXPORT_SYMBOL_GPL(debugfs_create_u8); |
|---|
| .. | .. |
|---|
| 436 | 474 | * This function creates a file in debugfs with the given name that |
|---|
| 437 | 475 | * contains the value of the variable @value. If the @mode variable is so |
|---|
| 438 | 476 | * set, it can be read from, and written to. |
|---|
| 439 | | - * |
|---|
| 440 | | - * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 441 | | - * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 442 | | - * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 443 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 444 | | - * |
|---|
| 445 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 446 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 447 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 448 | | - * code. |
|---|
| 449 | 477 | */ |
|---|
| 450 | | -struct dentry *debugfs_create_u16(const char *name, umode_t mode, |
|---|
| 451 | | - struct dentry *parent, u16 *value) |
|---|
| 478 | +void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 479 | + u16 *value) |
|---|
| 452 | 480 | { |
|---|
| 453 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16, |
|---|
| 481 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16, |
|---|
| 454 | 482 | &fops_u16_ro, &fops_u16_wo); |
|---|
| 455 | 483 | } |
|---|
| 456 | 484 | EXPORT_SYMBOL_GPL(debugfs_create_u16); |
|---|
| .. | .. |
|---|
| 482 | 510 | * This function creates a file in debugfs with the given name that |
|---|
| 483 | 511 | * contains the value of the variable @value. If the @mode variable is so |
|---|
| 484 | 512 | * set, it can be read from, and written to. |
|---|
| 485 | | - * |
|---|
| 486 | | - * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 487 | | - * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 488 | | - * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 489 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 490 | | - * |
|---|
| 491 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 492 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 493 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 494 | | - * code. |
|---|
| 495 | 513 | */ |
|---|
| 496 | | -struct dentry *debugfs_create_u32(const char *name, umode_t mode, |
|---|
| 497 | | - struct dentry *parent, u32 *value) |
|---|
| 514 | +void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 515 | + u32 *value) |
|---|
| 498 | 516 | { |
|---|
| 499 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, |
|---|
| 517 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, |
|---|
| 500 | 518 | &fops_u32_ro, &fops_u32_wo); |
|---|
| 501 | 519 | } |
|---|
| 502 | 520 | EXPORT_SYMBOL_GPL(debugfs_create_u32); |
|---|
| .. | .. |
|---|
| 529 | 547 | * This function creates a file in debugfs with the given name that |
|---|
| 530 | 548 | * contains the value of the variable @value. If the @mode variable is so |
|---|
| 531 | 549 | * set, it can be read from, and written to. |
|---|
| 532 | | - * |
|---|
| 533 | | - * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 534 | | - * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 535 | | - * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 536 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 537 | | - * |
|---|
| 538 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 539 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 540 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 541 | | - * code. |
|---|
| 542 | 550 | */ |
|---|
| 543 | | -struct dentry *debugfs_create_u64(const char *name, umode_t mode, |
|---|
| 544 | | - struct dentry *parent, u64 *value) |
|---|
| 551 | +void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 552 | + u64 *value) |
|---|
| 545 | 553 | { |
|---|
| 546 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64, |
|---|
| 554 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64, |
|---|
| 547 | 555 | &fops_u64_ro, &fops_u64_wo); |
|---|
| 548 | 556 | } |
|---|
| 549 | 557 | EXPORT_SYMBOL_GPL(debugfs_create_u64); |
|---|
| .. | .. |
|---|
| 582 | 590 | * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 583 | 591 | * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 584 | 592 | * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 585 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 593 | + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be |
|---|
| 594 | + * returned. |
|---|
| 586 | 595 | * |
|---|
| 587 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 588 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 589 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 590 | | - * code. |
|---|
| 596 | + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will |
|---|
| 597 | + * be returned. |
|---|
| 591 | 598 | */ |
|---|
| 592 | 599 | struct dentry *debugfs_create_ulong(const char *name, umode_t mode, |
|---|
| 593 | 600 | struct dentry *parent, unsigned long *value) |
|---|
| .. | .. |
|---|
| 635 | 642 | * @value: a pointer to the variable that the file should read to and write |
|---|
| 636 | 643 | * from. |
|---|
| 637 | 644 | */ |
|---|
| 638 | | -struct dentry *debugfs_create_x8(const char *name, umode_t mode, |
|---|
| 639 | | - struct dentry *parent, u8 *value) |
|---|
| 645 | +void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 646 | + u8 *value) |
|---|
| 640 | 647 | { |
|---|
| 641 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8, |
|---|
| 648 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8, |
|---|
| 642 | 649 | &fops_x8_ro, &fops_x8_wo); |
|---|
| 643 | 650 | } |
|---|
| 644 | 651 | EXPORT_SYMBOL_GPL(debugfs_create_x8); |
|---|
| .. | .. |
|---|
| 653 | 660 | * @value: a pointer to the variable that the file should read to and write |
|---|
| 654 | 661 | * from. |
|---|
| 655 | 662 | */ |
|---|
| 656 | | -struct dentry *debugfs_create_x16(const char *name, umode_t mode, |
|---|
| 657 | | - struct dentry *parent, u16 *value) |
|---|
| 663 | +void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 664 | + u16 *value) |
|---|
| 658 | 665 | { |
|---|
| 659 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16, |
|---|
| 666 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16, |
|---|
| 660 | 667 | &fops_x16_ro, &fops_x16_wo); |
|---|
| 661 | 668 | } |
|---|
| 662 | 669 | EXPORT_SYMBOL_GPL(debugfs_create_x16); |
|---|
| .. | .. |
|---|
| 671 | 678 | * @value: a pointer to the variable that the file should read to and write |
|---|
| 672 | 679 | * from. |
|---|
| 673 | 680 | */ |
|---|
| 674 | | -struct dentry *debugfs_create_x32(const char *name, umode_t mode, |
|---|
| 675 | | - struct dentry *parent, u32 *value) |
|---|
| 681 | +void debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 682 | + u32 *value) |
|---|
| 676 | 683 | { |
|---|
| 677 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32, |
|---|
| 684 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32, |
|---|
| 678 | 685 | &fops_x32_ro, &fops_x32_wo); |
|---|
| 679 | 686 | } |
|---|
| 680 | 687 | EXPORT_SYMBOL_GPL(debugfs_create_x32); |
|---|
| .. | .. |
|---|
| 689 | 696 | * @value: a pointer to the variable that the file should read to and write |
|---|
| 690 | 697 | * from. |
|---|
| 691 | 698 | */ |
|---|
| 692 | | -struct dentry *debugfs_create_x64(const char *name, umode_t mode, |
|---|
| 693 | | - struct dentry *parent, u64 *value) |
|---|
| 699 | +void debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, |
|---|
| 700 | + u64 *value) |
|---|
| 694 | 701 | { |
|---|
| 695 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64, |
|---|
| 702 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64, |
|---|
| 696 | 703 | &fops_x64_ro, &fops_x64_wo); |
|---|
| 697 | 704 | } |
|---|
| 698 | 705 | EXPORT_SYMBOL_GPL(debugfs_create_x64); |
|---|
| .. | .. |
|---|
| 723 | 730 | * @value: a pointer to the variable that the file should read to and write |
|---|
| 724 | 731 | * from. |
|---|
| 725 | 732 | */ |
|---|
| 726 | | -struct dentry *debugfs_create_size_t(const char *name, umode_t mode, |
|---|
| 727 | | - struct dentry *parent, size_t *value) |
|---|
| 733 | +void debugfs_create_size_t(const char *name, umode_t mode, |
|---|
| 734 | + struct dentry *parent, size_t *value) |
|---|
| 728 | 735 | { |
|---|
| 729 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, |
|---|
| 730 | | - &fops_size_t, &fops_size_t_ro, |
|---|
| 731 | | - &fops_size_t_wo); |
|---|
| 736 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_size_t, |
|---|
| 737 | + &fops_size_t_ro, &fops_size_t_wo); |
|---|
| 732 | 738 | } |
|---|
| 733 | 739 | EXPORT_SYMBOL_GPL(debugfs_create_size_t); |
|---|
| 734 | 740 | |
|---|
| .. | .. |
|---|
| 760 | 766 | * @value: a pointer to the variable that the file should read to and write |
|---|
| 761 | 767 | * from. |
|---|
| 762 | 768 | */ |
|---|
| 763 | | -struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode, |
|---|
| 764 | | - struct dentry *parent, atomic_t *value) |
|---|
| 769 | +void debugfs_create_atomic_t(const char *name, umode_t mode, |
|---|
| 770 | + struct dentry *parent, atomic_t *value) |
|---|
| 765 | 771 | { |
|---|
| 766 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, |
|---|
| 767 | | - &fops_atomic_t, &fops_atomic_t_ro, |
|---|
| 768 | | - &fops_atomic_t_wo); |
|---|
| 772 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_atomic_t, |
|---|
| 773 | + &fops_atomic_t_ro, &fops_atomic_t_wo); |
|---|
| 769 | 774 | } |
|---|
| 770 | 775 | EXPORT_SYMBOL_GPL(debugfs_create_atomic_t); |
|---|
| 771 | 776 | |
|---|
| .. | .. |
|---|
| 850 | 855 | * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 851 | 856 | * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 852 | 857 | * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 853 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 858 | + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be |
|---|
| 859 | + * returned. |
|---|
| 854 | 860 | * |
|---|
| 855 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 856 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 857 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 858 | | - * code. |
|---|
| 861 | + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will |
|---|
| 862 | + * be returned. |
|---|
| 859 | 863 | */ |
|---|
| 860 | 864 | struct dentry *debugfs_create_bool(const char *name, umode_t mode, |
|---|
| 861 | 865 | struct dentry *parent, bool *value) |
|---|
| .. | .. |
|---|
| 904 | 908 | * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 905 | 909 | * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 906 | 910 | * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 907 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 911 | + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be |
|---|
| 912 | + * returned. |
|---|
| 908 | 913 | * |
|---|
| 909 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 910 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 911 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 912 | | - * code. |
|---|
| 914 | + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will |
|---|
| 915 | + * be returned. |
|---|
| 913 | 916 | */ |
|---|
| 914 | 917 | struct dentry *debugfs_create_blob(const char *name, umode_t mode, |
|---|
| 915 | 918 | struct dentry *parent, |
|---|
| .. | .. |
|---|
| 918 | 921 | return debugfs_create_file_unsafe(name, mode, parent, blob, &fops_blob); |
|---|
| 919 | 922 | } |
|---|
| 920 | 923 | EXPORT_SYMBOL_GPL(debugfs_create_blob); |
|---|
| 921 | | - |
|---|
| 922 | | -struct array_data { |
|---|
| 923 | | - void *array; |
|---|
| 924 | | - u32 elements; |
|---|
| 925 | | -}; |
|---|
| 926 | 924 | |
|---|
| 927 | 925 | static size_t u32_format_array(char *buf, size_t bufsize, |
|---|
| 928 | 926 | u32 *array, int array_size) |
|---|
| .. | .. |
|---|
| 944 | 942 | |
|---|
| 945 | 943 | static int u32_array_open(struct inode *inode, struct file *file) |
|---|
| 946 | 944 | { |
|---|
| 947 | | - struct array_data *data = inode->i_private; |
|---|
| 948 | | - int size, elements = data->elements; |
|---|
| 945 | + struct debugfs_u32_array *data = inode->i_private; |
|---|
| 946 | + int size, elements = data->n_elements; |
|---|
| 949 | 947 | char *buf; |
|---|
| 950 | 948 | |
|---|
| 951 | 949 | /* |
|---|
| .. | .. |
|---|
| 960 | 958 | buf[size] = 0; |
|---|
| 961 | 959 | |
|---|
| 962 | 960 | file->private_data = buf; |
|---|
| 963 | | - u32_format_array(buf, size, data->array, data->elements); |
|---|
| 964 | | - |
|---|
| 965 | | - return nonseekable_open(inode, file); |
|---|
| 966 | | -} |
|---|
| 967 | | - |
|---|
| 968 | | -static size_t u32_format_array_hex(char *buf, size_t bufsize, u32 *array, int array_size) |
|---|
| 969 | | -{ |
|---|
| 970 | | - int i = 0; |
|---|
| 971 | | - |
|---|
| 972 | | - while (--array_size >= 0) { |
|---|
| 973 | | - size_t len; |
|---|
| 974 | | - char term = (array_size && (++i % 8)) ? ' ' : '\n'; |
|---|
| 975 | | - |
|---|
| 976 | | - len = snprintf(buf, bufsize, "%08X%c", *array++, term); |
|---|
| 977 | | - buf += len; |
|---|
| 978 | | - bufsize -= len; |
|---|
| 979 | | - } |
|---|
| 980 | | - |
|---|
| 981 | | - return 0; |
|---|
| 982 | | -} |
|---|
| 983 | | - |
|---|
| 984 | | -static int u32_array_open_hex(struct inode *inode, struct file *file) |
|---|
| 985 | | -{ |
|---|
| 986 | | - struct array_data *data = inode->i_private; |
|---|
| 987 | | - int size, elements = data->elements; |
|---|
| 988 | | - char *buf; |
|---|
| 989 | | - |
|---|
| 990 | | - /* |
|---|
| 991 | | - * Max size: |
|---|
| 992 | | - * - 8 digits + ' '/'\n' = 9 bytes per number |
|---|
| 993 | | - * - terminating NUL character |
|---|
| 994 | | - */ |
|---|
| 995 | | - size = elements * 9; |
|---|
| 996 | | - buf = kmalloc(size + 1, GFP_KERNEL); |
|---|
| 997 | | - if (!buf) |
|---|
| 998 | | - return -ENOMEM; |
|---|
| 999 | | - |
|---|
| 1000 | | - buf[size] = 0; |
|---|
| 1001 | | - |
|---|
| 1002 | | - file->private_data = buf; |
|---|
| 1003 | | - u32_format_array_hex(buf, size, data->array, data->elements); |
|---|
| 961 | + u32_format_array(buf, size, data->array, data->n_elements); |
|---|
| 1004 | 962 | |
|---|
| 1005 | 963 | return nonseekable_open(inode, file); |
|---|
| 1006 | 964 | } |
|---|
| .. | .. |
|---|
| 1029 | 987 | .llseek = no_llseek, |
|---|
| 1030 | 988 | }; |
|---|
| 1031 | 989 | |
|---|
| 1032 | | -static const struct file_operations u32_array_hex_fops = { |
|---|
| 1033 | | - .owner = THIS_MODULE, |
|---|
| 1034 | | - .open = u32_array_open_hex, |
|---|
| 1035 | | - .release = u32_array_release, |
|---|
| 1036 | | - .read = u32_array_read, |
|---|
| 1037 | | - .llseek = no_llseek, |
|---|
| 1038 | | -}; |
|---|
| 1039 | | - |
|---|
| 1040 | 990 | /** |
|---|
| 1041 | 991 | * debugfs_create_u32_array - create a debugfs file that is used to read u32 |
|---|
| 1042 | 992 | * array. |
|---|
| .. | .. |
|---|
| 1045 | 995 | * @parent: a pointer to the parent dentry for this file. This should be a |
|---|
| 1046 | 996 | * directory dentry if set. If this parameter is %NULL, then the |
|---|
| 1047 | 997 | * file will be created in the root of the debugfs filesystem. |
|---|
| 1048 | | - * @array: u32 array that provides data. |
|---|
| 1049 | | - * @elements: total number of elements in the array. |
|---|
| 998 | + * @array: wrapper struct containing data pointer and size of the array. |
|---|
| 1050 | 999 | * |
|---|
| 1051 | 1000 | * This function creates a file in debugfs with the given name that exports |
|---|
| 1052 | 1001 | * @array as data. If the @mode variable is so set it can be read from. |
|---|
| 1053 | 1002 | * Writing is not supported. Seek within the file is also not supported. |
|---|
| 1054 | 1003 | * Once array is created its size can not be changed. |
|---|
| 1055 | | - * |
|---|
| 1056 | | - * The function returns a pointer to dentry on success. If debugfs is not |
|---|
| 1057 | | - * enabled in the kernel, the value -%ENODEV will be returned. |
|---|
| 1058 | 1004 | */ |
|---|
| 1059 | | -struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, |
|---|
| 1060 | | - struct dentry *parent, |
|---|
| 1061 | | - u32 *array, u32 elements) |
|---|
| 1005 | +void debugfs_create_u32_array(const char *name, umode_t mode, |
|---|
| 1006 | + struct dentry *parent, |
|---|
| 1007 | + struct debugfs_u32_array *array) |
|---|
| 1062 | 1008 | { |
|---|
| 1063 | | - struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL); |
|---|
| 1064 | | - |
|---|
| 1065 | | - if (data == NULL) |
|---|
| 1066 | | - return NULL; |
|---|
| 1067 | | - |
|---|
| 1068 | | - data->array = array; |
|---|
| 1069 | | - data->elements = elements; |
|---|
| 1070 | | - |
|---|
| 1071 | | - return debugfs_create_file_unsafe(name, mode, parent, data, |
|---|
| 1072 | | - &u32_array_fops); |
|---|
| 1009 | + debugfs_create_file_unsafe(name, mode, parent, array, &u32_array_fops); |
|---|
| 1073 | 1010 | } |
|---|
| 1074 | 1011 | EXPORT_SYMBOL_GPL(debugfs_create_u32_array); |
|---|
| 1075 | | - |
|---|
| 1076 | | -struct dentry *debugfs_create_u32_array_hex(const char *name, umode_t mode, |
|---|
| 1077 | | - struct dentry *parent, |
|---|
| 1078 | | - u32 *array, u32 elements) |
|---|
| 1079 | | -{ |
|---|
| 1080 | | - struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL); |
|---|
| 1081 | | - |
|---|
| 1082 | | - if (data == NULL) |
|---|
| 1083 | | - return NULL; |
|---|
| 1084 | | - |
|---|
| 1085 | | - data->array = array; |
|---|
| 1086 | | - data->elements = elements; |
|---|
| 1087 | | - |
|---|
| 1088 | | - return debugfs_create_file_unsafe(name, mode, parent, data, |
|---|
| 1089 | | - &u32_array_hex_fops); |
|---|
| 1090 | | -} |
|---|
| 1091 | | -EXPORT_SYMBOL_GPL(debugfs_create_u32_array_hex); |
|---|
| 1092 | 1012 | |
|---|
| 1093 | 1013 | #ifdef CONFIG_HAS_IOMEM |
|---|
| 1094 | 1014 | |
|---|
| .. | .. |
|---|
| 1133 | 1053 | { |
|---|
| 1134 | 1054 | struct debugfs_regset32 *regset = s->private; |
|---|
| 1135 | 1055 | |
|---|
| 1056 | + if (regset->dev) |
|---|
| 1057 | + pm_runtime_get_sync(regset->dev); |
|---|
| 1058 | + |
|---|
| 1136 | 1059 | debugfs_print_regs32(s, regset->regs, regset->nregs, regset->base, ""); |
|---|
| 1060 | + |
|---|
| 1061 | + if (regset->dev) |
|---|
| 1062 | + pm_runtime_put(regset->dev); |
|---|
| 1063 | + |
|---|
| 1137 | 1064 | return 0; |
|---|
| 1138 | 1065 | } |
|---|
| 1139 | 1066 | |
|---|
| .. | .. |
|---|
| 1163 | 1090 | * This function creates a file in debugfs with the given name that reports |
|---|
| 1164 | 1091 | * the names and values of a set of 32-bit registers. If the @mode variable |
|---|
| 1165 | 1092 | * is so set it can be read from. Writing is not supported. |
|---|
| 1166 | | - * |
|---|
| 1167 | | - * This function will return a pointer to a dentry if it succeeds. This |
|---|
| 1168 | | - * pointer must be passed to the debugfs_remove() function when the file is |
|---|
| 1169 | | - * to be removed (no automatic cleanup happens if your module is unloaded, |
|---|
| 1170 | | - * you are responsible here.) If an error occurs, %NULL will be returned. |
|---|
| 1171 | | - * |
|---|
| 1172 | | - * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
|---|
| 1173 | | - * returned. It is not wise to check for this value, but rather, check for |
|---|
| 1174 | | - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
|---|
| 1175 | | - * code. |
|---|
| 1176 | 1093 | */ |
|---|
| 1177 | | -struct dentry *debugfs_create_regset32(const char *name, umode_t mode, |
|---|
| 1178 | | - struct dentry *parent, |
|---|
| 1179 | | - struct debugfs_regset32 *regset) |
|---|
| 1094 | +void debugfs_create_regset32(const char *name, umode_t mode, |
|---|
| 1095 | + struct dentry *parent, |
|---|
| 1096 | + struct debugfs_regset32 *regset) |
|---|
| 1180 | 1097 | { |
|---|
| 1181 | | - return debugfs_create_file(name, mode, parent, regset, &fops_regset32); |
|---|
| 1098 | + debugfs_create_file(name, mode, parent, regset, &fops_regset32); |
|---|
| 1182 | 1099 | } |
|---|
| 1183 | 1100 | EXPORT_SYMBOL_GPL(debugfs_create_regset32); |
|---|
| 1184 | 1101 | |
|---|
| .. | .. |
|---|
| 1214 | 1131 | * file will be created in the root of the debugfs filesystem. |
|---|
| 1215 | 1132 | * @read_fn: function pointer called to print the seq_file content. |
|---|
| 1216 | 1133 | */ |
|---|
| 1217 | | -struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, |
|---|
| 1218 | | - struct dentry *parent, |
|---|
| 1219 | | - int (*read_fn)(struct seq_file *s, |
|---|
| 1220 | | - void *data)) |
|---|
| 1134 | +void debugfs_create_devm_seqfile(struct device *dev, const char *name, |
|---|
| 1135 | + struct dentry *parent, |
|---|
| 1136 | + int (*read_fn)(struct seq_file *s, void *data)) |
|---|
| 1221 | 1137 | { |
|---|
| 1222 | 1138 | struct debugfs_devm_entry *entry; |
|---|
| 1223 | 1139 | |
|---|
| 1224 | 1140 | if (IS_ERR(parent)) |
|---|
| 1225 | | - return ERR_PTR(-ENOENT); |
|---|
| 1141 | + return; |
|---|
| 1226 | 1142 | |
|---|
| 1227 | 1143 | entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); |
|---|
| 1228 | 1144 | if (!entry) |
|---|
| 1229 | | - return ERR_PTR(-ENOMEM); |
|---|
| 1145 | + return; |
|---|
| 1230 | 1146 | |
|---|
| 1231 | 1147 | entry->read = read_fn; |
|---|
| 1232 | 1148 | entry->dev = dev; |
|---|
| 1233 | 1149 | |
|---|
| 1234 | | - return debugfs_create_file(name, S_IRUGO, parent, entry, |
|---|
| 1235 | | - &debugfs_devm_entry_ops); |
|---|
| 1150 | + debugfs_create_file(name, S_IRUGO, parent, entry, |
|---|
| 1151 | + &debugfs_devm_entry_ops); |
|---|
| 1236 | 1152 | } |
|---|
| 1237 | 1153 | EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile); |
|---|
| 1238 | | - |
|---|