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 = sysfs_emit(buf, "0 (No Interference Mitigation)\n"); 57 break; 58 case B43_INTERFMODE_NONWLAN: 59 count = sysfs_emit(buf, 60 "1 (Non-WLAN Interference Mitigation)\n"); 61 break; 62 case B43_INTERFMODE_MANUALWLAN: 63 count = sysfs_emit(buf, "2 (WLAN Interference Mitigation)\n"); 64 break; 65 default: 66 B43_WARN_ON(1); 67 } 68 69 mutex_unlock(&wldev->wl->mutex); 70 71 return count; 72 } 73 74 static ssize_t b43_attr_interfmode_store(struct device *dev, 75 struct device_attribute *attr, 76 const char *buf, size_t count) 77 { 78 struct b43_wldev *wldev = dev_to_b43_wldev(dev); 79 int err; 80 int mode; 81 82 if (!capable(CAP_NET_ADMIN)) 83 return -EPERM; 84 85 mode = get_integer(buf, count); 86 switch (mode) { 87 case 0: 88 mode = B43_INTERFMODE_NONE; 89 break; 90 case 1: 91 mode = B43_INTERFMODE_NONWLAN; 92 break; 93 case 2: 94 mode = B43_INTERFMODE_MANUALWLAN; 95 break; 96 case 3: 97 mode = B43_INTERFMODE_AUTOWLAN; 98 break; 99 default: 100 return -EINVAL; 101 } 102 103 mutex_lock(&wldev->wl->mutex); 104 105 if (wldev->phy.ops->interf_mitigation) { 106 err = wldev->phy.ops->interf_mitigation(wldev, mode); 107 if (err) { 108 b43err(wldev->wl, "Interference Mitigation not " 109 "supported by device\n"); 110 } 111 } else 112 err = -ENOSYS; 113 114 mutex_unlock(&wldev->wl->mutex); 115 116 return err ? err : count; 117 } 118 119 static DEVICE_ATTR(interference, 0644, 120 b43_attr_interfmode_show, b43_attr_interfmode_store); 121 122 int b43_sysfs_register(struct b43_wldev *wldev) 123 { 124 struct device *dev = wldev->dev->dev; 125 126 B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); 127 128 return device_create_file(dev, &dev_attr_interference); 129 } 130 131 void b43_sysfs_unregister(struct b43_wldev *wldev) 132 { 133 struct device *dev = wldev->dev->dev; 134 135 device_remove_file(dev, &dev_attr_interference); 136 } 137