.. | .. |
---|
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); |
---|
.. | .. |
---|
330 | 378 | } |
---|
331 | 379 | EXPORT_SYMBOL_GPL(debugfs_attr_read); |
---|
332 | 380 | |
---|
333 | | -ssize_t debugfs_attr_write(struct file *file, const char __user *buf, |
---|
334 | | - size_t len, loff_t *ppos) |
---|
| 381 | +static ssize_t debugfs_attr_write_xsigned(struct file *file, const char __user *buf, |
---|
| 382 | + size_t len, loff_t *ppos, bool is_signed) |
---|
335 | 383 | { |
---|
336 | 384 | struct dentry *dentry = F_DENTRY(file); |
---|
337 | 385 | ssize_t ret; |
---|
.. | .. |
---|
339 | 387 | ret = debugfs_file_get(dentry); |
---|
340 | 388 | if (unlikely(ret)) |
---|
341 | 389 | return ret; |
---|
342 | | - ret = simple_attr_write(file, buf, len, ppos); |
---|
| 390 | + if (is_signed) |
---|
| 391 | + ret = simple_attr_write_signed(file, buf, len, ppos); |
---|
| 392 | + else |
---|
| 393 | + ret = simple_attr_write(file, buf, len, ppos); |
---|
343 | 394 | debugfs_file_put(dentry); |
---|
344 | 395 | return ret; |
---|
345 | 396 | } |
---|
| 397 | + |
---|
| 398 | +ssize_t debugfs_attr_write(struct file *file, const char __user *buf, |
---|
| 399 | + size_t len, loff_t *ppos) |
---|
| 400 | +{ |
---|
| 401 | + return debugfs_attr_write_xsigned(file, buf, len, ppos, false); |
---|
| 402 | +} |
---|
346 | 403 | EXPORT_SYMBOL_GPL(debugfs_attr_write); |
---|
| 404 | + |
---|
| 405 | +ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf, |
---|
| 406 | + size_t len, loff_t *ppos) |
---|
| 407 | +{ |
---|
| 408 | + return debugfs_attr_write_xsigned(file, buf, len, ppos, true); |
---|
| 409 | +} |
---|
| 410 | +EXPORT_SYMBOL_GPL(debugfs_attr_write_signed); |
---|
347 | 411 | |
---|
348 | 412 | static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, |
---|
349 | 413 | struct dentry *parent, void *value, |
---|
.. | .. |
---|
390 | 454 | * This function creates a file in debugfs with the given name that |
---|
391 | 455 | * contains the value of the variable @value. If the @mode variable is so |
---|
392 | 456 | * 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 | 457 | */ |
---|
404 | | -struct dentry *debugfs_create_u8(const char *name, umode_t mode, |
---|
405 | | - struct dentry *parent, u8 *value) |
---|
| 458 | +void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, |
---|
| 459 | + u8 *value) |
---|
406 | 460 | { |
---|
407 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8, |
---|
| 461 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8, |
---|
408 | 462 | &fops_u8_ro, &fops_u8_wo); |
---|
409 | 463 | } |
---|
410 | 464 | EXPORT_SYMBOL_GPL(debugfs_create_u8); |
---|
.. | .. |
---|
436 | 490 | * This function creates a file in debugfs with the given name that |
---|
437 | 491 | * contains the value of the variable @value. If the @mode variable is so |
---|
438 | 492 | * 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 | 493 | */ |
---|
450 | | -struct dentry *debugfs_create_u16(const char *name, umode_t mode, |
---|
451 | | - struct dentry *parent, u16 *value) |
---|
| 494 | +void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, |
---|
| 495 | + u16 *value) |
---|
452 | 496 | { |
---|
453 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16, |
---|
| 497 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16, |
---|
454 | 498 | &fops_u16_ro, &fops_u16_wo); |
---|
455 | 499 | } |
---|
456 | 500 | EXPORT_SYMBOL_GPL(debugfs_create_u16); |
---|
.. | .. |
---|
482 | 526 | * This function creates a file in debugfs with the given name that |
---|
483 | 527 | * contains the value of the variable @value. If the @mode variable is so |
---|
484 | 528 | * 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 | 529 | */ |
---|
496 | | -struct dentry *debugfs_create_u32(const char *name, umode_t mode, |
---|
497 | | - struct dentry *parent, u32 *value) |
---|
| 530 | +void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, |
---|
| 531 | + u32 *value) |
---|
498 | 532 | { |
---|
499 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, |
---|
| 533 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, |
---|
500 | 534 | &fops_u32_ro, &fops_u32_wo); |
---|
501 | 535 | } |
---|
502 | 536 | EXPORT_SYMBOL_GPL(debugfs_create_u32); |
---|
.. | .. |
---|
529 | 563 | * This function creates a file in debugfs with the given name that |
---|
530 | 564 | * contains the value of the variable @value. If the @mode variable is so |
---|
531 | 565 | * 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 | 566 | */ |
---|
543 | | -struct dentry *debugfs_create_u64(const char *name, umode_t mode, |
---|
544 | | - struct dentry *parent, u64 *value) |
---|
| 567 | +void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, |
---|
| 568 | + u64 *value) |
---|
545 | 569 | { |
---|
546 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64, |
---|
| 570 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64, |
---|
547 | 571 | &fops_u64_ro, &fops_u64_wo); |
---|
548 | 572 | } |
---|
549 | 573 | EXPORT_SYMBOL_GPL(debugfs_create_u64); |
---|
.. | .. |
---|
582 | 606 | * This function will return a pointer to a dentry if it succeeds. This |
---|
583 | 607 | * pointer must be passed to the debugfs_remove() function when the file is |
---|
584 | 608 | * 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. |
---|
| 609 | + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be |
---|
| 610 | + * returned. |
---|
586 | 611 | * |
---|
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. |
---|
| 612 | + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will |
---|
| 613 | + * be returned. |
---|
591 | 614 | */ |
---|
592 | 615 | struct dentry *debugfs_create_ulong(const char *name, umode_t mode, |
---|
593 | 616 | struct dentry *parent, unsigned long *value) |
---|
.. | .. |
---|
635 | 658 | * @value: a pointer to the variable that the file should read to and write |
---|
636 | 659 | * from. |
---|
637 | 660 | */ |
---|
638 | | -struct dentry *debugfs_create_x8(const char *name, umode_t mode, |
---|
639 | | - struct dentry *parent, u8 *value) |
---|
| 661 | +void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, |
---|
| 662 | + u8 *value) |
---|
640 | 663 | { |
---|
641 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8, |
---|
| 664 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8, |
---|
642 | 665 | &fops_x8_ro, &fops_x8_wo); |
---|
643 | 666 | } |
---|
644 | 667 | EXPORT_SYMBOL_GPL(debugfs_create_x8); |
---|
.. | .. |
---|
653 | 676 | * @value: a pointer to the variable that the file should read to and write |
---|
654 | 677 | * from. |
---|
655 | 678 | */ |
---|
656 | | -struct dentry *debugfs_create_x16(const char *name, umode_t mode, |
---|
657 | | - struct dentry *parent, u16 *value) |
---|
| 679 | +void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, |
---|
| 680 | + u16 *value) |
---|
658 | 681 | { |
---|
659 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16, |
---|
| 682 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16, |
---|
660 | 683 | &fops_x16_ro, &fops_x16_wo); |
---|
661 | 684 | } |
---|
662 | 685 | EXPORT_SYMBOL_GPL(debugfs_create_x16); |
---|
.. | .. |
---|
671 | 694 | * @value: a pointer to the variable that the file should read to and write |
---|
672 | 695 | * from. |
---|
673 | 696 | */ |
---|
674 | | -struct dentry *debugfs_create_x32(const char *name, umode_t mode, |
---|
675 | | - struct dentry *parent, u32 *value) |
---|
| 697 | +void debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, |
---|
| 698 | + u32 *value) |
---|
676 | 699 | { |
---|
677 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32, |
---|
| 700 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32, |
---|
678 | 701 | &fops_x32_ro, &fops_x32_wo); |
---|
679 | 702 | } |
---|
680 | 703 | EXPORT_SYMBOL_GPL(debugfs_create_x32); |
---|
.. | .. |
---|
689 | 712 | * @value: a pointer to the variable that the file should read to and write |
---|
690 | 713 | * from. |
---|
691 | 714 | */ |
---|
692 | | -struct dentry *debugfs_create_x64(const char *name, umode_t mode, |
---|
693 | | - struct dentry *parent, u64 *value) |
---|
| 715 | +void debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, |
---|
| 716 | + u64 *value) |
---|
694 | 717 | { |
---|
695 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64, |
---|
| 718 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64, |
---|
696 | 719 | &fops_x64_ro, &fops_x64_wo); |
---|
697 | 720 | } |
---|
698 | 721 | EXPORT_SYMBOL_GPL(debugfs_create_x64); |
---|
.. | .. |
---|
723 | 746 | * @value: a pointer to the variable that the file should read to and write |
---|
724 | 747 | * from. |
---|
725 | 748 | */ |
---|
726 | | -struct dentry *debugfs_create_size_t(const char *name, umode_t mode, |
---|
727 | | - struct dentry *parent, size_t *value) |
---|
| 749 | +void debugfs_create_size_t(const char *name, umode_t mode, |
---|
| 750 | + struct dentry *parent, size_t *value) |
---|
728 | 751 | { |
---|
729 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, |
---|
730 | | - &fops_size_t, &fops_size_t_ro, |
---|
731 | | - &fops_size_t_wo); |
---|
| 752 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_size_t, |
---|
| 753 | + &fops_size_t_ro, &fops_size_t_wo); |
---|
732 | 754 | } |
---|
733 | 755 | EXPORT_SYMBOL_GPL(debugfs_create_size_t); |
---|
734 | 756 | |
---|
.. | .. |
---|
742 | 764 | *val = atomic_read((atomic_t *)data); |
---|
743 | 765 | return 0; |
---|
744 | 766 | } |
---|
745 | | -DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, |
---|
| 767 | +DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t, debugfs_atomic_t_get, |
---|
746 | 768 | debugfs_atomic_t_set, "%lld\n"); |
---|
747 | | -DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, |
---|
| 769 | +DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, |
---|
748 | 770 | "%lld\n"); |
---|
749 | | -DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, |
---|
| 771 | +DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, |
---|
750 | 772 | "%lld\n"); |
---|
751 | 773 | |
---|
752 | 774 | /** |
---|
.. | .. |
---|
760 | 782 | * @value: a pointer to the variable that the file should read to and write |
---|
761 | 783 | * from. |
---|
762 | 784 | */ |
---|
763 | | -struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode, |
---|
764 | | - struct dentry *parent, atomic_t *value) |
---|
| 785 | +void debugfs_create_atomic_t(const char *name, umode_t mode, |
---|
| 786 | + struct dentry *parent, atomic_t *value) |
---|
765 | 787 | { |
---|
766 | | - return debugfs_create_mode_unsafe(name, mode, parent, value, |
---|
767 | | - &fops_atomic_t, &fops_atomic_t_ro, |
---|
768 | | - &fops_atomic_t_wo); |
---|
| 788 | + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_atomic_t, |
---|
| 789 | + &fops_atomic_t_ro, &fops_atomic_t_wo); |
---|
769 | 790 | } |
---|
770 | 791 | EXPORT_SYMBOL_GPL(debugfs_create_atomic_t); |
---|
771 | 792 | |
---|
.. | .. |
---|
850 | 871 | * This function will return a pointer to a dentry if it succeeds. This |
---|
851 | 872 | * pointer must be passed to the debugfs_remove() function when the file is |
---|
852 | 873 | * 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. |
---|
| 874 | + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be |
---|
| 875 | + * returned. |
---|
854 | 876 | * |
---|
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. |
---|
| 877 | + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will |
---|
| 878 | + * be returned. |
---|
859 | 879 | */ |
---|
860 | 880 | struct dentry *debugfs_create_bool(const char *name, umode_t mode, |
---|
861 | 881 | struct dentry *parent, bool *value) |
---|
.. | .. |
---|
904 | 924 | * This function will return a pointer to a dentry if it succeeds. This |
---|
905 | 925 | * pointer must be passed to the debugfs_remove() function when the file is |
---|
906 | 926 | * 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. |
---|
| 927 | + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be |
---|
| 928 | + * returned. |
---|
908 | 929 | * |
---|
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. |
---|
| 930 | + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will |
---|
| 931 | + * be returned. |
---|
913 | 932 | */ |
---|
914 | 933 | struct dentry *debugfs_create_blob(const char *name, umode_t mode, |
---|
915 | 934 | struct dentry *parent, |
---|
.. | .. |
---|
918 | 937 | return debugfs_create_file_unsafe(name, mode, parent, blob, &fops_blob); |
---|
919 | 938 | } |
---|
920 | 939 | EXPORT_SYMBOL_GPL(debugfs_create_blob); |
---|
921 | | - |
---|
922 | | -struct array_data { |
---|
923 | | - void *array; |
---|
924 | | - u32 elements; |
---|
925 | | -}; |
---|
926 | 940 | |
---|
927 | 941 | static size_t u32_format_array(char *buf, size_t bufsize, |
---|
928 | 942 | u32 *array, int array_size) |
---|
.. | .. |
---|
944 | 958 | |
---|
945 | 959 | static int u32_array_open(struct inode *inode, struct file *file) |
---|
946 | 960 | { |
---|
947 | | - struct array_data *data = inode->i_private; |
---|
948 | | - int size, elements = data->elements; |
---|
| 961 | + struct debugfs_u32_array *data = inode->i_private; |
---|
| 962 | + int size, elements = data->n_elements; |
---|
949 | 963 | char *buf; |
---|
950 | 964 | |
---|
951 | 965 | /* |
---|
.. | .. |
---|
960 | 974 | buf[size] = 0; |
---|
961 | 975 | |
---|
962 | 976 | 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); |
---|
| 977 | + u32_format_array(buf, size, data->array, data->n_elements); |
---|
1004 | 978 | |
---|
1005 | 979 | return nonseekable_open(inode, file); |
---|
1006 | 980 | } |
---|
.. | .. |
---|
1029 | 1003 | .llseek = no_llseek, |
---|
1030 | 1004 | }; |
---|
1031 | 1005 | |
---|
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 | 1006 | /** |
---|
1041 | 1007 | * debugfs_create_u32_array - create a debugfs file that is used to read u32 |
---|
1042 | 1008 | * array. |
---|
.. | .. |
---|
1045 | 1011 | * @parent: a pointer to the parent dentry for this file. This should be a |
---|
1046 | 1012 | * directory dentry if set. If this parameter is %NULL, then the |
---|
1047 | 1013 | * 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. |
---|
| 1014 | + * @array: wrapper struct containing data pointer and size of the array. |
---|
1050 | 1015 | * |
---|
1051 | 1016 | * This function creates a file in debugfs with the given name that exports |
---|
1052 | 1017 | * @array as data. If the @mode variable is so set it can be read from. |
---|
1053 | 1018 | * Writing is not supported. Seek within the file is also not supported. |
---|
1054 | 1019 | * 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 | 1020 | */ |
---|
1059 | | -struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, |
---|
1060 | | - struct dentry *parent, |
---|
1061 | | - u32 *array, u32 elements) |
---|
| 1021 | +void debugfs_create_u32_array(const char *name, umode_t mode, |
---|
| 1022 | + struct dentry *parent, |
---|
| 1023 | + struct debugfs_u32_array *array) |
---|
1062 | 1024 | { |
---|
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); |
---|
| 1025 | + debugfs_create_file_unsafe(name, mode, parent, array, &u32_array_fops); |
---|
1073 | 1026 | } |
---|
1074 | 1027 | 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 | 1028 | |
---|
1093 | 1029 | #ifdef CONFIG_HAS_IOMEM |
---|
1094 | 1030 | |
---|
.. | .. |
---|
1133 | 1069 | { |
---|
1134 | 1070 | struct debugfs_regset32 *regset = s->private; |
---|
1135 | 1071 | |
---|
| 1072 | + if (regset->dev) |
---|
| 1073 | + pm_runtime_get_sync(regset->dev); |
---|
| 1074 | + |
---|
1136 | 1075 | debugfs_print_regs32(s, regset->regs, regset->nregs, regset->base, ""); |
---|
| 1076 | + |
---|
| 1077 | + if (regset->dev) |
---|
| 1078 | + pm_runtime_put(regset->dev); |
---|
| 1079 | + |
---|
1137 | 1080 | return 0; |
---|
1138 | 1081 | } |
---|
1139 | 1082 | |
---|
.. | .. |
---|
1163 | 1106 | * This function creates a file in debugfs with the given name that reports |
---|
1164 | 1107 | * the names and values of a set of 32-bit registers. If the @mode variable |
---|
1165 | 1108 | * 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 | 1109 | */ |
---|
1177 | | -struct dentry *debugfs_create_regset32(const char *name, umode_t mode, |
---|
1178 | | - struct dentry *parent, |
---|
1179 | | - struct debugfs_regset32 *regset) |
---|
| 1110 | +void debugfs_create_regset32(const char *name, umode_t mode, |
---|
| 1111 | + struct dentry *parent, |
---|
| 1112 | + struct debugfs_regset32 *regset) |
---|
1180 | 1113 | { |
---|
1181 | | - return debugfs_create_file(name, mode, parent, regset, &fops_regset32); |
---|
| 1114 | + debugfs_create_file(name, mode, parent, regset, &fops_regset32); |
---|
1182 | 1115 | } |
---|
1183 | 1116 | EXPORT_SYMBOL_GPL(debugfs_create_regset32); |
---|
1184 | 1117 | |
---|
.. | .. |
---|
1214 | 1147 | * file will be created in the root of the debugfs filesystem. |
---|
1215 | 1148 | * @read_fn: function pointer called to print the seq_file content. |
---|
1216 | 1149 | */ |
---|
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)) |
---|
| 1150 | +void debugfs_create_devm_seqfile(struct device *dev, const char *name, |
---|
| 1151 | + struct dentry *parent, |
---|
| 1152 | + int (*read_fn)(struct seq_file *s, void *data)) |
---|
1221 | 1153 | { |
---|
1222 | 1154 | struct debugfs_devm_entry *entry; |
---|
1223 | 1155 | |
---|
1224 | 1156 | if (IS_ERR(parent)) |
---|
1225 | | - return ERR_PTR(-ENOENT); |
---|
| 1157 | + return; |
---|
1226 | 1158 | |
---|
1227 | 1159 | entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); |
---|
1228 | 1160 | if (!entry) |
---|
1229 | | - return ERR_PTR(-ENOMEM); |
---|
| 1161 | + return; |
---|
1230 | 1162 | |
---|
1231 | 1163 | entry->read = read_fn; |
---|
1232 | 1164 | entry->dev = dev; |
---|
1233 | 1165 | |
---|
1234 | | - return debugfs_create_file(name, S_IRUGO, parent, entry, |
---|
1235 | | - &debugfs_devm_entry_ops); |
---|
| 1166 | + debugfs_create_file(name, S_IRUGO, parent, entry, |
---|
| 1167 | + &debugfs_devm_entry_ops); |
---|
1236 | 1168 | } |
---|
1237 | 1169 | EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile); |
---|
1238 | | - |
---|