xref: /openbmc/linux/drivers/net/wireless/broadcom/b43/sysfs.c (revision 58e16d792a6a8c6b750f637a4649967fcac853dc)
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