sysfs.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. Broadcom B43 wireless driver
  4. SYSFS support routines
  5. Copyright (c) 2006 Michael Buesch <m@bues.ch>
  6. */
  7. #include <linux/capability.h>
  8. #include <linux/io.h>
  9. #include "b43.h"
  10. #include "sysfs.h"
  11. #include "main.h"
  12. #include "phy_common.h"
  13. #define GENERIC_FILESIZE 64
  14. static int get_integer(const char *buf, size_t count)
  15. {
  16. char tmp[10 + 1] = { 0 };
  17. int ret = -EINVAL;
  18. if (count == 0)
  19. goto out;
  20. count = min_t(size_t, count, 10);
  21. memcpy(tmp, buf, count);
  22. ret = simple_strtol(tmp, NULL, 10);
  23. out:
  24. return ret;
  25. }
  26. static ssize_t b43_attr_interfmode_show(struct device *dev,
  27. struct device_attribute *attr,
  28. char *buf)
  29. {
  30. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  31. ssize_t count = 0;
  32. if (!capable(CAP_NET_ADMIN))
  33. return -EPERM;
  34. mutex_lock(&wldev->wl->mutex);
  35. if (wldev->phy.type != B43_PHYTYPE_G) {
  36. mutex_unlock(&wldev->wl->mutex);
  37. return -ENOSYS;
  38. }
  39. switch (wldev->phy.g->interfmode) {
  40. case B43_INTERFMODE_NONE:
  41. count = sysfs_emit(buf, "0 (No Interference Mitigation)\n");
  42. break;
  43. case B43_INTERFMODE_NONWLAN:
  44. count = sysfs_emit(buf,
  45. "1 (Non-WLAN Interference Mitigation)\n");
  46. break;
  47. case B43_INTERFMODE_MANUALWLAN:
  48. count = sysfs_emit(buf, "2 (WLAN Interference Mitigation)\n");
  49. break;
  50. default:
  51. B43_WARN_ON(1);
  52. }
  53. mutex_unlock(&wldev->wl->mutex);
  54. return count;
  55. }
  56. static ssize_t b43_attr_interfmode_store(struct device *dev,
  57. struct device_attribute *attr,
  58. const char *buf, size_t count)
  59. {
  60. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  61. int err;
  62. int mode;
  63. if (!capable(CAP_NET_ADMIN))
  64. return -EPERM;
  65. mode = get_integer(buf, count);
  66. switch (mode) {
  67. case 0:
  68. mode = B43_INTERFMODE_NONE;
  69. break;
  70. case 1:
  71. mode = B43_INTERFMODE_NONWLAN;
  72. break;
  73. case 2:
  74. mode = B43_INTERFMODE_MANUALWLAN;
  75. break;
  76. case 3:
  77. mode = B43_INTERFMODE_AUTOWLAN;
  78. break;
  79. default:
  80. return -EINVAL;
  81. }
  82. mutex_lock(&wldev->wl->mutex);
  83. if (wldev->phy.ops->interf_mitigation) {
  84. err = wldev->phy.ops->interf_mitigation(wldev, mode);
  85. if (err) {
  86. b43err(wldev->wl, "Interference Mitigation not "
  87. "supported by device\n");
  88. }
  89. } else
  90. err = -ENOSYS;
  91. mutex_unlock(&wldev->wl->mutex);
  92. return err ? err : count;
  93. }
  94. static DEVICE_ATTR(interference, 0644,
  95. b43_attr_interfmode_show, b43_attr_interfmode_store);
  96. int b43_sysfs_register(struct b43_wldev *wldev)
  97. {
  98. struct device *dev = wldev->dev->dev;
  99. B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
  100. return device_create_file(dev, &dev_attr_interference);
  101. }
  102. void b43_sysfs_unregister(struct b43_wldev *wldev)
  103. {
  104. struct device *dev = wldev->dev->dev;
  105. device_remove_file(dev, &dev_attr_interference);
  106. }