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
get_integer(const char * buf,size_t count)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
b43_attr_interfmode_show(struct device * dev,struct device_attribute * attr,char * buf)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
b43_attr_interfmode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
b43_sysfs_register(struct b43_wldev * wldev)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
b43_sysfs_unregister(struct b43_wldev * wldev)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