1*ca47d344SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 258619b14SKalle Valo /* 358619b14SKalle Valo 458619b14SKalle Valo Broadcom B43 wireless driver 558619b14SKalle Valo 658619b14SKalle Valo SYSFS support routines 758619b14SKalle Valo 858619b14SKalle Valo Copyright (c) 2006 Michael Buesch <m@bues.ch> 958619b14SKalle Valo 1058619b14SKalle Valo 1158619b14SKalle Valo */ 1258619b14SKalle Valo 1358619b14SKalle Valo #include <linux/capability.h> 1458619b14SKalle Valo #include <linux/io.h> 1558619b14SKalle Valo 1658619b14SKalle Valo #include "b43.h" 1758619b14SKalle Valo #include "sysfs.h" 1858619b14SKalle Valo #include "main.h" 1958619b14SKalle Valo #include "phy_common.h" 2058619b14SKalle Valo 2158619b14SKalle Valo #define GENERIC_FILESIZE 64 2258619b14SKalle Valo 2358619b14SKalle Valo static int get_integer(const char *buf, size_t count) 2458619b14SKalle Valo { 2558619b14SKalle Valo char tmp[10 + 1] = { 0 }; 2658619b14SKalle Valo int ret = -EINVAL; 2758619b14SKalle Valo 2858619b14SKalle Valo if (count == 0) 2958619b14SKalle Valo goto out; 3058619b14SKalle Valo count = min_t(size_t, count, 10); 3158619b14SKalle Valo memcpy(tmp, buf, count); 3258619b14SKalle Valo ret = simple_strtol(tmp, NULL, 10); 3358619b14SKalle Valo out: 3458619b14SKalle Valo return ret; 3558619b14SKalle Valo } 3658619b14SKalle Valo 3758619b14SKalle Valo static ssize_t b43_attr_interfmode_show(struct device *dev, 3858619b14SKalle Valo struct device_attribute *attr, 3958619b14SKalle Valo char *buf) 4058619b14SKalle Valo { 4158619b14SKalle Valo struct b43_wldev *wldev = dev_to_b43_wldev(dev); 4258619b14SKalle Valo ssize_t count = 0; 4358619b14SKalle Valo 4458619b14SKalle Valo if (!capable(CAP_NET_ADMIN)) 4558619b14SKalle Valo return -EPERM; 4658619b14SKalle Valo 4758619b14SKalle Valo mutex_lock(&wldev->wl->mutex); 4858619b14SKalle Valo 4958619b14SKalle Valo if (wldev->phy.type != B43_PHYTYPE_G) { 5058619b14SKalle Valo mutex_unlock(&wldev->wl->mutex); 5158619b14SKalle Valo return -ENOSYS; 5258619b14SKalle Valo } 5358619b14SKalle Valo 5458619b14SKalle Valo switch (wldev->phy.g->interfmode) { 5558619b14SKalle Valo case B43_INTERFMODE_NONE: 5658619b14SKalle Valo count = 5758619b14SKalle Valo snprintf(buf, PAGE_SIZE, 5858619b14SKalle Valo "0 (No Interference Mitigation)\n"); 5958619b14SKalle Valo break; 6058619b14SKalle Valo case B43_INTERFMODE_NONWLAN: 6158619b14SKalle Valo count = 6258619b14SKalle Valo snprintf(buf, PAGE_SIZE, 6358619b14SKalle Valo "1 (Non-WLAN Interference Mitigation)\n"); 6458619b14SKalle Valo break; 6558619b14SKalle Valo case B43_INTERFMODE_MANUALWLAN: 6658619b14SKalle Valo count = 6758619b14SKalle Valo snprintf(buf, PAGE_SIZE, 6858619b14SKalle Valo "2 (WLAN Interference Mitigation)\n"); 6958619b14SKalle Valo break; 7058619b14SKalle Valo default: 7158619b14SKalle Valo B43_WARN_ON(1); 7258619b14SKalle Valo } 7358619b14SKalle Valo 7458619b14SKalle Valo mutex_unlock(&wldev->wl->mutex); 7558619b14SKalle Valo 7658619b14SKalle Valo return count; 7758619b14SKalle Valo } 7858619b14SKalle Valo 7958619b14SKalle Valo static ssize_t b43_attr_interfmode_store(struct device *dev, 8058619b14SKalle Valo struct device_attribute *attr, 8158619b14SKalle Valo const char *buf, size_t count) 8258619b14SKalle Valo { 8358619b14SKalle Valo struct b43_wldev *wldev = dev_to_b43_wldev(dev); 8458619b14SKalle Valo int err; 8558619b14SKalle Valo int mode; 8658619b14SKalle Valo 8758619b14SKalle Valo if (!capable(CAP_NET_ADMIN)) 8858619b14SKalle Valo return -EPERM; 8958619b14SKalle Valo 9058619b14SKalle Valo mode = get_integer(buf, count); 9158619b14SKalle Valo switch (mode) { 9258619b14SKalle Valo case 0: 9358619b14SKalle Valo mode = B43_INTERFMODE_NONE; 9458619b14SKalle Valo break; 9558619b14SKalle Valo case 1: 9658619b14SKalle Valo mode = B43_INTERFMODE_NONWLAN; 9758619b14SKalle Valo break; 9858619b14SKalle Valo case 2: 9958619b14SKalle Valo mode = B43_INTERFMODE_MANUALWLAN; 10058619b14SKalle Valo break; 10158619b14SKalle Valo case 3: 10258619b14SKalle Valo mode = B43_INTERFMODE_AUTOWLAN; 10358619b14SKalle Valo break; 10458619b14SKalle Valo default: 10558619b14SKalle Valo return -EINVAL; 10658619b14SKalle Valo } 10758619b14SKalle Valo 10858619b14SKalle Valo mutex_lock(&wldev->wl->mutex); 10958619b14SKalle Valo 11058619b14SKalle Valo if (wldev->phy.ops->interf_mitigation) { 11158619b14SKalle Valo err = wldev->phy.ops->interf_mitigation(wldev, mode); 11258619b14SKalle Valo if (err) { 11358619b14SKalle Valo b43err(wldev->wl, "Interference Mitigation not " 11458619b14SKalle Valo "supported by device\n"); 11558619b14SKalle Valo } 11658619b14SKalle Valo } else 11758619b14SKalle Valo err = -ENOSYS; 11858619b14SKalle Valo 11958619b14SKalle Valo mutex_unlock(&wldev->wl->mutex); 12058619b14SKalle Valo 12158619b14SKalle Valo return err ? err : count; 12258619b14SKalle Valo } 12358619b14SKalle Valo 12458619b14SKalle Valo static DEVICE_ATTR(interference, 0644, 12558619b14SKalle Valo b43_attr_interfmode_show, b43_attr_interfmode_store); 12658619b14SKalle Valo 12758619b14SKalle Valo int b43_sysfs_register(struct b43_wldev *wldev) 12858619b14SKalle Valo { 12958619b14SKalle Valo struct device *dev = wldev->dev->dev; 13058619b14SKalle Valo 13158619b14SKalle Valo B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); 13258619b14SKalle Valo 13358619b14SKalle Valo return device_create_file(dev, &dev_attr_interference); 13458619b14SKalle Valo } 13558619b14SKalle Valo 13658619b14SKalle Valo void b43_sysfs_unregister(struct b43_wldev *wldev) 13758619b14SKalle Valo { 13858619b14SKalle Valo struct device *dev = wldev->dev->dev; 13958619b14SKalle Valo 14058619b14SKalle Valo device_remove_file(dev, &dev_attr_interference); 14158619b14SKalle Valo } 142