1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
This adds a bwmode debugfs file which can be used to set alternate
channel operating bandwidths. Only tested with AR5413 and only at
5 and 20 mhz channels.
Signed-off-by: Pat Erley <pat-lkml at erley.org>
---
Other devices will need to be added to the switch in write_file_bwmode
drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++
1 files changed, 86 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 8c5ce8b..bb41066 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -815,6 +815,89 @@ static const struct file_operations fops_ani = {
.llseek = default_llseek,
};
+/* debugfs: bwmode */
+
+static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_hw *ah = file->private_data;
+ char buf[15];
+ unsigned int len = 0;
+
+ int cur_ah_bwmode = ah->ah_bwmode;
+
+#define print_selected(MODE, LABEL) \
+ if (cur_ah_bwmode == MODE) \
+ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
+ else \
+ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
+ len += snprintf(buf+len, sizeof(buf)-len, " ");
+
+ print_selected(AR5K_BWMODE_5MHZ, "5");
+ print_selected(AR5K_BWMODE_10MHZ, "10");
+ print_selected(AR5K_BWMODE_DEFAULT, "20");
+ print_selected(AR5K_BWMODE_40MHZ, "40");
+#undef print_selected
+
+ len += snprintf(buf+len, sizeof(buf)-len, "\n");
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_bwmode(struct file *file,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_hw *ah = file->private_data;
+ char buf[3];
+ int bw = 20;
+ int tobwmode = AR5K_BWMODE_DEFAULT;
+
+ if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+ return -EFAULT;
+
+ /* TODO: Add check for active interface */
+
+ if(strncmp(buf, "5", 1) == 0 ) {
+ tobwmode = AR5K_BWMODE_5MHZ;
+ bw = 5;
+ } else if ( strncmp(buf, "10", 2) == 0 ) {
+ tobwmode = AR5K_BWMODE_10MHZ;
+ bw = 10;
+ } else if ( strncmp(buf, "20", 2) == 0 ) {
+ tobwmode = AR5K_BWMODE_DEFAULT;
+ bw = 20;
+ } else if ( strncmp(buf, "40", 2) == 0 ) {
+ tobwmode = AR5K_BWMODE_40MHZ;
+ bw = 40;
+ } else
+ return -EINVAL;
+
+ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
+ bw, tobwmode);
+
+ switch (ah->ah_radio) {
+ /* TODO: only define radios that actually support 5/10mhz channels */
+ case AR5K_RF5413: case AR5K_RF5110: case AR5K_RF5111: case AR5K_RF5112: case AR5K_RF2413: case AR5K_RF2316: case AR5K_RF2317: case AR5K_RF2425:
+ if(ah->ah_bwmode != tobwmode) {
+ mutex_lock(&ah->lock);
+ ah->ah_bwmode = tobwmode;
+ mutex_unlock(&ah->lock);
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return count;
+}
+
+static const struct file_operations fops_bwmode = {
+ .read = read_file_bwmode,
+ .write = write_file_bwmode,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
/* debugfs: queues etc */
@@ -906,6 +989,9 @@ ath5k_debug_init_device(struct ath5k_hw *ah)
debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
&fops_beacon);
+ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
+ &fops_bwmode);
+
debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
--
|