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