1 /* 2 3 Broadcom B43 wireless driver 4 5 SYSFS support routines 6 7 Copyright (c) 2006 Michael Buesch <m@bues.ch> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; see the file COPYING. If not, write to 21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 22 Boston, MA 02110-1301, USA. 23 24 */ 25 26 #include <linux/capability.h> 27 #include <linux/io.h> 28 29 #include "b43.h" 30 #include "sysfs.h" 31 #include "main.h" 32 #include "phy_common.h" 33 34 #define GENERIC_FILESIZE 64 35 36 static int get_integer(const char *buf, size_t count) 37 { 38 char tmp[10 + 1] = { 0 }; 39 int ret = -EINVAL; 40 41 if (count == 0) 42 goto out; 43 count = min_t(size_t, count, 10); 44 memcpy(tmp, buf, count); 45 ret = simple_strtol(tmp, NULL, 10); 46 out: 47 return ret; 48 } 49 50 static ssize_t b43_attr_interfmode_show(struct device *dev, 51 struct device_attribute *attr, 52 char *buf) 53 { 54 struct b43_wldev *wldev = dev_to_b43_wldev(dev); 55 ssize_t count = 0; 56 57 if (!capable(CAP_NET_ADMIN)) 58 return -EPERM; 59 60 mutex_lock(&wldev->wl->mutex); 61 62 if (wldev->phy.type != B43_PHYTYPE_G) { 63 mutex_unlock(&wldev->wl->mutex); 64 return -ENOSYS; 65 } 66 67 switch (wldev->phy.g->interfmode) { 68 case B43_INTERFMODE_NONE: 69 count = 70 snprintf(buf, PAGE_SIZE, 71 "0 (No Interference Mitigation)\n"); 72 break; 73 case B43_INTERFMODE_NONWLAN: 74 count = 75 snprintf(buf, PAGE_SIZE, 76 "1 (Non-WLAN Interference Mitigation)\n"); 77 break; 78 case B43_INTERFMODE_MANUALWLAN: 79 count = 80 snprintf(buf, PAGE_SIZE, 81 "2 (WLAN Interference Mitigation)\n"); 82 break; 83 default: 84 B43_WARN_ON(1); 85 } 86 87 mutex_unlock(&wldev->wl->mutex); 88 89 return count; 90 } 91 92 static ssize_t b43_attr_interfmode_store(struct device *dev, 93 struct device_attribute *attr, 94 const char *buf, size_t count) 95 { 96 struct b43_wldev *wldev = dev_to_b43_wldev(dev); 97 int err; 98 int mode; 99 100 if (!capable(CAP_NET_ADMIN)) 101 return -EPERM; 102 103 mode = get_integer(buf, count); 104 switch (mode) { 105 case 0: 106 mode = B43_INTERFMODE_NONE; 107 break; 108 case 1: 109 mode = B43_INTERFMODE_NONWLAN; 110 break; 111 case 2: 112 mode = B43_INTERFMODE_MANUALWLAN; 113 break; 114 case 3: 115 mode = B43_INTERFMODE_AUTOWLAN; 116 break; 117 default: 118 return -EINVAL; 119 } 120 121 mutex_lock(&wldev->wl->mutex); 122 123 if (wldev->phy.ops->interf_mitigation) { 124 err = wldev->phy.ops->interf_mitigation(wldev, mode); 125 if (err) { 126 b43err(wldev->wl, "Interference Mitigation not " 127 "supported by device\n"); 128 } 129 } else 130 err = -ENOSYS; 131 132 mmiowb(); 133 mutex_unlock(&wldev->wl->mutex); 134 135 return err ? err : count; 136 } 137 138 static DEVICE_ATTR(interference, 0644, 139 b43_attr_interfmode_show, b43_attr_interfmode_store); 140 141 int b43_sysfs_register(struct b43_wldev *wldev) 142 { 143 struct device *dev = wldev->dev->dev; 144 145 B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); 146 147 return device_create_file(dev, &dev_attr_interference); 148 } 149 150 void b43_sysfs_unregister(struct b43_wldev *wldev) 151 { 152 struct device *dev = wldev->dev->dev; 153 154 device_remove_file(dev, &dev_attr_interference); 155 } 156