xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/broadcom/b43legacy/sysfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun   Broadcom B43legacy wireless driver
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun   SYSFS support routines
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun   Copyright (c) 2006 Michael Buesch <m@bues.ch>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "sysfs.h"
14*4882a593Smuzhiyun #include "b43legacy.h"
15*4882a593Smuzhiyun #include "main.h"
16*4882a593Smuzhiyun #include "phy.h"
17*4882a593Smuzhiyun #include "radio.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <linux/capability.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define GENERIC_FILESIZE	64
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 
get_integer(const char * buf,size_t count)25*4882a593Smuzhiyun static int get_integer(const char *buf, size_t count)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	char tmp[10 + 1] = { 0 };
28*4882a593Smuzhiyun 	int ret = -EINVAL, res;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if (count == 0)
31*4882a593Smuzhiyun 		goto out;
32*4882a593Smuzhiyun 	count = min_t(size_t, count, 10);
33*4882a593Smuzhiyun 	memcpy(tmp, buf, count);
34*4882a593Smuzhiyun 	ret = kstrtoint(tmp, 10, &res);
35*4882a593Smuzhiyun 	if (!ret)
36*4882a593Smuzhiyun 		return res;
37*4882a593Smuzhiyun out:
38*4882a593Smuzhiyun 	return ret;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
get_boolean(const char * buf,size_t count)41*4882a593Smuzhiyun static int get_boolean(const char *buf, size_t count)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	if (count != 0) {
44*4882a593Smuzhiyun 		if (buf[0] == '1')
45*4882a593Smuzhiyun 			return 1;
46*4882a593Smuzhiyun 		if (buf[0] == '0')
47*4882a593Smuzhiyun 			return 0;
48*4882a593Smuzhiyun 		if (count >= 4 && memcmp(buf, "true", 4) == 0)
49*4882a593Smuzhiyun 			return 1;
50*4882a593Smuzhiyun 		if (count >= 5 && memcmp(buf, "false", 5) == 0)
51*4882a593Smuzhiyun 			return 0;
52*4882a593Smuzhiyun 		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
53*4882a593Smuzhiyun 			return 1;
54*4882a593Smuzhiyun 		if (count >= 2 && memcmp(buf, "no", 2) == 0)
55*4882a593Smuzhiyun 			return 0;
56*4882a593Smuzhiyun 		if (count >= 2 && memcmp(buf, "on", 2) == 0)
57*4882a593Smuzhiyun 			return 1;
58*4882a593Smuzhiyun 		if (count >= 3 && memcmp(buf, "off", 3) == 0)
59*4882a593Smuzhiyun 			return 0;
60*4882a593Smuzhiyun 	}
61*4882a593Smuzhiyun 	return -EINVAL;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
b43legacy_attr_interfmode_show(struct device * dev,struct device_attribute * attr,char * buf)64*4882a593Smuzhiyun static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
65*4882a593Smuzhiyun 					      struct device_attribute *attr,
66*4882a593Smuzhiyun 					      char *buf)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
69*4882a593Smuzhiyun 	ssize_t count = 0;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	if (!capable(CAP_NET_ADMIN))
72*4882a593Smuzhiyun 		return -EPERM;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	mutex_lock(&wldev->wl->mutex);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	switch (wldev->phy.interfmode) {
77*4882a593Smuzhiyun 	case B43legacy_INTERFMODE_NONE:
78*4882a593Smuzhiyun 		count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
79*4882a593Smuzhiyun 				 " Mitigation)\n");
80*4882a593Smuzhiyun 		break;
81*4882a593Smuzhiyun 	case B43legacy_INTERFMODE_NONWLAN:
82*4882a593Smuzhiyun 		count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
83*4882a593Smuzhiyun 				 " Mitigation)\n");
84*4882a593Smuzhiyun 		break;
85*4882a593Smuzhiyun 	case B43legacy_INTERFMODE_MANUALWLAN:
86*4882a593Smuzhiyun 		count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
87*4882a593Smuzhiyun 				 " Mitigation)\n");
88*4882a593Smuzhiyun 		break;
89*4882a593Smuzhiyun 	default:
90*4882a593Smuzhiyun 		B43legacy_WARN_ON(1);
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	mutex_unlock(&wldev->wl->mutex);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	return count;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
b43legacy_attr_interfmode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)98*4882a593Smuzhiyun static ssize_t b43legacy_attr_interfmode_store(struct device *dev,
99*4882a593Smuzhiyun 					       struct device_attribute *attr,
100*4882a593Smuzhiyun 					       const char *buf, size_t count)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
103*4882a593Smuzhiyun 	unsigned long flags;
104*4882a593Smuzhiyun 	int err;
105*4882a593Smuzhiyun 	int mode;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (!capable(CAP_NET_ADMIN))
108*4882a593Smuzhiyun 		return -EPERM;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	mode = get_integer(buf, count);
111*4882a593Smuzhiyun 	switch (mode) {
112*4882a593Smuzhiyun 	case 0:
113*4882a593Smuzhiyun 		mode = B43legacy_INTERFMODE_NONE;
114*4882a593Smuzhiyun 		break;
115*4882a593Smuzhiyun 	case 1:
116*4882a593Smuzhiyun 		mode = B43legacy_INTERFMODE_NONWLAN;
117*4882a593Smuzhiyun 		break;
118*4882a593Smuzhiyun 	case 2:
119*4882a593Smuzhiyun 		mode = B43legacy_INTERFMODE_MANUALWLAN;
120*4882a593Smuzhiyun 		break;
121*4882a593Smuzhiyun 	case 3:
122*4882a593Smuzhiyun 		mode = B43legacy_INTERFMODE_AUTOWLAN;
123*4882a593Smuzhiyun 		break;
124*4882a593Smuzhiyun 	default:
125*4882a593Smuzhiyun 		return -EINVAL;
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	mutex_lock(&wldev->wl->mutex);
129*4882a593Smuzhiyun 	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	err = b43legacy_radio_set_interference_mitigation(wldev, mode);
132*4882a593Smuzhiyun 	if (err)
133*4882a593Smuzhiyun 		b43legacyerr(wldev->wl, "Interference Mitigation not "
134*4882a593Smuzhiyun 		       "supported by device\n");
135*4882a593Smuzhiyun 	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
136*4882a593Smuzhiyun 	mutex_unlock(&wldev->wl->mutex);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	return err ? err : count;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static DEVICE_ATTR(interference, 0644,
142*4882a593Smuzhiyun 		   b43legacy_attr_interfmode_show,
143*4882a593Smuzhiyun 		   b43legacy_attr_interfmode_store);
144*4882a593Smuzhiyun 
b43legacy_attr_preamble_show(struct device * dev,struct device_attribute * attr,char * buf)145*4882a593Smuzhiyun static ssize_t b43legacy_attr_preamble_show(struct device *dev,
146*4882a593Smuzhiyun 					    struct device_attribute *attr,
147*4882a593Smuzhiyun 					    char *buf)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
150*4882a593Smuzhiyun 	ssize_t count;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (!capable(CAP_NET_ADMIN))
153*4882a593Smuzhiyun 		return -EPERM;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	mutex_lock(&wldev->wl->mutex);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (wldev->short_preamble)
158*4882a593Smuzhiyun 		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
159*4882a593Smuzhiyun 				 " enabled)\n");
160*4882a593Smuzhiyun 	else
161*4882a593Smuzhiyun 		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
162*4882a593Smuzhiyun 				 " disabled)\n");
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	mutex_unlock(&wldev->wl->mutex);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return count;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
b43legacy_attr_preamble_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)169*4882a593Smuzhiyun static ssize_t b43legacy_attr_preamble_store(struct device *dev,
170*4882a593Smuzhiyun 					     struct device_attribute *attr,
171*4882a593Smuzhiyun 					     const char *buf, size_t count)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
174*4882a593Smuzhiyun 	unsigned long flags;
175*4882a593Smuzhiyun 	int value;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (!capable(CAP_NET_ADMIN))
178*4882a593Smuzhiyun 		return -EPERM;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	value = get_boolean(buf, count);
181*4882a593Smuzhiyun 	if (value < 0)
182*4882a593Smuzhiyun 		return value;
183*4882a593Smuzhiyun 	mutex_lock(&wldev->wl->mutex);
184*4882a593Smuzhiyun 	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	wldev->short_preamble = !!value;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
189*4882a593Smuzhiyun 	mutex_unlock(&wldev->wl->mutex);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	return count;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun static DEVICE_ATTR(shortpreamble, 0644,
195*4882a593Smuzhiyun 		   b43legacy_attr_preamble_show,
196*4882a593Smuzhiyun 		   b43legacy_attr_preamble_store);
197*4882a593Smuzhiyun 
b43legacy_sysfs_register(struct b43legacy_wldev * wldev)198*4882a593Smuzhiyun int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	struct device *dev = wldev->dev->dev;
201*4882a593Smuzhiyun 	int err;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	B43legacy_WARN_ON(b43legacy_status(wldev) !=
204*4882a593Smuzhiyun 			  B43legacy_STAT_INITIALIZED);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	err = device_create_file(dev, &dev_attr_interference);
207*4882a593Smuzhiyun 	if (err)
208*4882a593Smuzhiyun 		goto out;
209*4882a593Smuzhiyun 	err = device_create_file(dev, &dev_attr_shortpreamble);
210*4882a593Smuzhiyun 	if (err)
211*4882a593Smuzhiyun 		goto err_remove_interfmode;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun out:
214*4882a593Smuzhiyun 	return err;
215*4882a593Smuzhiyun err_remove_interfmode:
216*4882a593Smuzhiyun 	device_remove_file(dev, &dev_attr_interference);
217*4882a593Smuzhiyun 	goto out;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
b43legacy_sysfs_unregister(struct b43legacy_wldev * wldev)220*4882a593Smuzhiyun void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	struct device *dev = wldev->dev->dev;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	device_remove_file(dev, &dev_attr_shortpreamble);
225*4882a593Smuzhiyun 	device_remove_file(dev, &dev_attr_interference);
226*4882a593Smuzhiyun }
227