sysfs.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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 <[email protected]>
  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 =
  42. snprintf(buf, PAGE_SIZE,
  43. "0 (No Interference Mitigation)\n");
  44. break;
  45. case B43_INTERFMODE_NONWLAN:
  46. count =
  47. snprintf(buf, PAGE_SIZE,
  48. "1 (Non-WLAN Interference Mitigation)\n");
  49. break;
  50. case B43_INTERFMODE_MANUALWLAN:
  51. count =
  52. snprintf(buf, PAGE_SIZE,
  53. "2 (WLAN Interference Mitigation)\n");
  54. break;
  55. default:
  56. B43_WARN_ON(1);
  57. }
  58. mutex_unlock(&wldev->wl->mutex);
  59. return count;
  60. }
  61. static ssize_t b43_attr_interfmode_store(struct device *dev,
  62. struct device_attribute *attr,
  63. const char *buf, size_t count)
  64. {
  65. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  66. int err;
  67. int mode;
  68. if (!capable(CAP_NET_ADMIN))
  69. return -EPERM;
  70. mode = get_integer(buf, count);
  71. switch (mode) {
  72. case 0:
  73. mode = B43_INTERFMODE_NONE;
  74. break;
  75. case 1:
  76. mode = B43_INTERFMODE_NONWLAN;
  77. break;
  78. case 2:
  79. mode = B43_INTERFMODE_MANUALWLAN;
  80. break;
  81. case 3:
  82. mode = B43_INTERFMODE_AUTOWLAN;
  83. break;
  84. default:
  85. return -EINVAL;
  86. }
  87. mutex_lock(&wldev->wl->mutex);
  88. if (wldev->phy.ops->interf_mitigation) {
  89. err = wldev->phy.ops->interf_mitigation(wldev, mode);
  90. if (err) {
  91. b43err(wldev->wl, "Interference Mitigation not "
  92. "supported by device\n");
  93. }
  94. } else
  95. err = -ENOSYS;
  96. mutex_unlock(&wldev->wl->mutex);
  97. return err ? err : count;
  98. }
  99. static DEVICE_ATTR(interference, 0644,
  100. b43_attr_interfmode_show, b43_attr_interfmode_store);
  101. int b43_sysfs_register(struct b43_wldev *wldev)
  102. {
  103. struct device *dev = wldev->dev->dev;
  104. B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
  105. return device_create_file(dev, &dev_attr_interference);
  106. }
  107. void b43_sysfs_unregister(struct b43_wldev *wldev)
  108. {
  109. struct device *dev = wldev->dev->dev;
  110. device_remove_file(dev, &dev_attr_interference);
  111. }