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