267dd0b3e6ece67a4b208f67775b188d55e099f0
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 330-nl80211_ht40.patch
1 This patch adds new NL80211_CMD_SET_WIPHY attributes
2 NL80211_ATTR_WIPHY_FREQ and NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET to allow
3 userspace to set the operating channel (e.g., hostapd for AP mode).
4
5 Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
6 Acked-by: Johannes Berg <johannes@sipsolutions.net>
7
8
9 Index: wireless-testing/include/linux/nl80211.h
10 ===================================================================
11 --- wireless-testing.orig/include/linux/nl80211.h 2008-11-26 15:15:31.000000000 +0200
12 +++ wireless-testing/include/linux/nl80211.h 2008-11-26 15:16:59.000000000 +0200
13 @@ -26,8 +26,9 @@
14 * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
15 * to get a list of all present wiphys.
16 * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
17 - * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME
18 - * and/or %NL80211_ATTR_WIPHY_TXQ_PARAMS.
19 + * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
20 + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or
21 + * %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET.
22 * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
23 * or rename notification. Has attributes %NL80211_ATTR_WIPHY and
24 * %NL80211_ATTR_WIPHY_NAME.
25 @@ -180,6 +181,14 @@
26 * /sys/class/ieee80211/<phyname>/index
27 * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
28 * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
29 + * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
30 + * @NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET: included with NL80211_ATTR_WIPHY_FREQ
31 + * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
32 + * NL80211_SEC_CHAN_NO_HT = HT not allowed (i.e., same as not including
33 + * this attribute)
34 + * NL80211_SEC_CHAN_DISABLED = HT20 only
35 + * NL80211_SEC_CHAN_BELOW = secondary channel is below the primary channel
36 + * NL80211_SEC_CHAN_ABOVE = secondary channel is above the primary channel
37 *
38 * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
39 * @NL80211_ATTR_IFNAME: network interface name
40 @@ -315,6 +324,8 @@
41 NL80211_ATTR_BSS_BASIC_RATES,
42
43 NL80211_ATTR_WIPHY_TXQ_PARAMS,
44 + NL80211_ATTR_WIPHY_FREQ,
45 + NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET,
46
47 /* add attributes here, update the policy in nl80211.c */
48
49 @@ -329,6 +340,8 @@
50 #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
51 #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
52 #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
53 +#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ
54 +#define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET
55
56 #define NL80211_MAX_SUPP_RATES 32
57 #define NL80211_MAX_SUPP_REG_RULES 32
58 @@ -742,4 +755,10 @@
59 NL80211_TXQ_Q_BK
60 };
61
62 +enum nl80211_sec_chan_offset {
63 + NL80211_SEC_CHAN_NO_HT /* No HT */,
64 + NL80211_SEC_CHAN_DISABLED /* HT20 only */,
65 + NL80211_SEC_CHAN_BELOW /* HT40- */,
66 + NL80211_SEC_CHAN_ABOVE /* HT40+ */
67 +};
68 #endif /* __LINUX_NL80211_H */
69 Index: wireless-testing/include/net/cfg80211.h
70 ===================================================================
71 --- wireless-testing.orig/include/net/cfg80211.h 2008-11-26 15:15:31.000000000 +0200
72 +++ wireless-testing/include/net/cfg80211.h 2008-11-26 15:29:50.000000000 +0200
73 @@ -392,6 +392,9 @@
74 /* from net/wireless.h */
75 struct wiphy;
76
77 +/* from net/ieee80211.h */
78 +struct ieee80211_channel;
79 +
80 /**
81 * struct cfg80211_ops - backend description for wireless configuration
82 *
83 @@ -450,6 +453,8 @@
84 * @change_bss: Modify parameters for a given BSS.
85 *
86 * @set_txq_params: Set TX queue parameters
87 + *
88 + * @set_channel: Set channel
89 */
90 struct cfg80211_ops {
91 int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
92 @@ -513,6 +518,10 @@
93
94 int (*set_txq_params)(struct wiphy *wiphy,
95 struct ieee80211_txq_params *params);
96 +
97 + int (*set_channel)(struct wiphy *wiphy,
98 + struct ieee80211_channel *chan,
99 + enum nl80211_sec_chan_offset);
100 };
101
102 #endif /* __NET_CFG80211_H */
103 Index: wireless-testing/net/mac80211/cfg.c
104 ===================================================================
105 --- wireless-testing.orig/net/mac80211/cfg.c 2008-11-26 15:15:31.000000000 +0200
106 +++ wireless-testing/net/mac80211/cfg.c 2008-11-26 15:19:34.000000000 +0200
107 @@ -1095,6 +1095,18 @@
108 return 0;
109 }
110
111 +static int ieee80211_set_channel(struct wiphy *wiphy,
112 + struct ieee80211_channel *chan,
113 + enum nl80211_sec_chan_offset sec_chan_offset)
114 +{
115 + struct ieee80211_local *local = wiphy_priv(wiphy);
116 +
117 + local->oper_channel = chan;
118 + local->oper_sec_chan_offset = sec_chan_offset;
119 +
120 + return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
121 +}
122 +
123 struct cfg80211_ops mac80211_config_ops = {
124 .add_virtual_intf = ieee80211_add_iface,
125 .del_virtual_intf = ieee80211_del_iface,
126 @@ -1122,4 +1134,5 @@
127 #endif
128 .change_bss = ieee80211_change_bss,
129 .set_txq_params = ieee80211_set_txq_params,
130 + .set_channel = ieee80211_set_channel,
131 };
132 Index: wireless-testing/net/wireless/nl80211.c
133 ===================================================================
134 --- wireless-testing.orig/net/wireless/nl80211.c 2008-11-26 15:15:31.000000000 +0200
135 +++ wireless-testing/net/wireless/nl80211.c 2008-11-26 15:31:31.000000000 +0200
136 @@ -59,6 +59,8 @@
137 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
138 .len = BUS_ID_SIZE-1 },
139 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
140 + [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
141 + [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 },
142
143 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
144 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
145 @@ -359,6 +361,61 @@
146 }
147 }
148
149 + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
150 + enum nl80211_sec_chan_offset sec_chan_offset =
151 + NL80211_SEC_CHAN_NO_HT;
152 + struct ieee80211_channel *chan;
153 + u32 freq, sec_freq;
154 +
155 + if (!rdev->ops->set_channel) {
156 + result = -EOPNOTSUPP;
157 + goto bad_res;
158 + }
159 +
160 + if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) {
161 + sec_chan_offset = nla_get_u32(
162 + info->attrs[
163 + NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]);
164 + if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT &&
165 + sec_chan_offset != NL80211_SEC_CHAN_DISABLED &&
166 + sec_chan_offset != NL80211_SEC_CHAN_BELOW &&
167 + sec_chan_offset != NL80211_SEC_CHAN_ABOVE) {
168 + result = -EINVAL;
169 + goto bad_res;
170 + }
171 + }
172 +
173 + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
174 + chan = ieee80211_get_channel(&rdev->wiphy, freq);
175 + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
176 + /* Primary channel not allowed */
177 + result = -EINVAL;
178 + goto bad_res;
179 + }
180 + if (sec_chan_offset == NL80211_SEC_CHAN_BELOW)
181 + sec_freq = freq - 20;
182 + else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE)
183 + sec_freq = freq + 20;
184 + else
185 + sec_freq = 0;
186 +
187 + if (sec_freq) {
188 + struct ieee80211_channel *schan;
189 + schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
190 + if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) {
191 + /* Secondary channel not allowed */
192 + result = -EINVAL;
193 + goto bad_res;
194 + }
195 + }
196 +
197 + result = rdev->ops->set_channel(&rdev->wiphy, chan,
198 + sec_chan_offset);
199 + if (result)
200 + goto bad_res;
201 + }
202 +
203 +
204 bad_res:
205 cfg80211_put_dev(rdev);
206 return result;
207 Index: wireless-testing/include/net/mac80211.h
208 ===================================================================
209 --- wireless-testing.orig/include/net/mac80211.h 2008-11-26 15:15:31.000000000 +0200
210 +++ wireless-testing/include/net/mac80211.h 2008-11-26 15:15:47.000000000 +0200
211 @@ -507,6 +507,9 @@
212
213 struct ieee80211_ht_conf {
214 bool enabled;
215 + int sec_chan_offset; /* 0 = HT40 disabled; -1 = HT40 enabled, secondary
216 + * channel below primary; 1 = HT40 enabled,
217 + * secondary channel above primary */
218 };
219
220 /**
221 Index: wireless-testing/net/mac80211/util.c
222 ===================================================================
223 --- wireless-testing.orig/net/mac80211/util.c 2008-11-26 15:15:31.000000000 +0200
224 +++ wireless-testing/net/mac80211/util.c 2008-11-26 15:20:26.000000000 +0200
225 @@ -641,6 +641,7 @@
226 chan->flags & IEEE80211_CHAN_NO_IBSS)
227 return ret;
228 local->oper_channel = chan;
229 + local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT;
230
231 if (local->sw_scanning || local->hw_scanning)
232 ret = 0;
233 Index: wireless-testing/net/mac80211/ieee80211_i.h
234 ===================================================================
235 --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2008-11-26 15:15:31.000000000 +0200
236 +++ wireless-testing/net/mac80211/ieee80211_i.h 2008-11-26 15:20:12.000000000 +0200
237 @@ -626,6 +626,7 @@
238 struct delayed_work scan_work;
239 struct ieee80211_sub_if_data *scan_sdata;
240 struct ieee80211_channel *oper_channel, *scan_channel;
241 + enum nl80211_sec_chan_offset oper_sec_chan_offset;
242 u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
243 size_t scan_ssid_len;
244 struct list_head bss_list;
245 Index: wireless-testing/net/mac80211/main.c
246 ===================================================================
247 --- wireless-testing.orig/net/mac80211/main.c 2008-11-26 15:15:31.000000000 +0200
248 +++ wireless-testing/net/mac80211/main.c 2008-11-26 15:29:09.000000000 +0200
249 @@ -195,20 +195,42 @@
250 struct ieee80211_channel *chan;
251 int ret = 0;
252 int power;
253 + enum nl80211_sec_chan_offset sec_chan_offset;
254
255 might_sleep();
256
257 - if (local->sw_scanning)
258 + if (local->sw_scanning) {
259 chan = local->scan_channel;
260 - else
261 + sec_chan_offset = NL80211_SEC_CHAN_NO_HT;
262 + } else {
263 chan = local->oper_channel;
264 + sec_chan_offset = local->oper_sec_chan_offset;
265 + }
266
267 - if (chan != local->hw.conf.channel) {
268 + if (chan != local->hw.conf.channel ||
269 + sec_chan_offset != local->hw.conf.ht.sec_chan_offset) {
270 local->hw.conf.channel = chan;
271 + switch (sec_chan_offset) {
272 + case NL80211_SEC_CHAN_NO_HT:
273 + local->hw.conf.ht.enabled = false;
274 + local->hw.conf.ht.sec_chan_offset = 0;
275 + break;
276 + case NL80211_SEC_CHAN_DISABLED:
277 + local->hw.conf.ht.enabled = true;
278 + local->hw.conf.ht.sec_chan_offset = 0;
279 + break;
280 + case NL80211_SEC_CHAN_BELOW:
281 + local->hw.conf.ht.enabled = true;
282 + local->hw.conf.ht.sec_chan_offset = -1;
283 + break;
284 + case NL80211_SEC_CHAN_ABOVE:
285 + local->hw.conf.ht.enabled = true;
286 + local->hw.conf.ht.sec_chan_offset = 1;
287 + break;
288 + }
289 changed |= IEEE80211_CONF_CHANGE_CHANNEL;
290 }
291
292 -
293 if (!local->hw.conf.power_level)
294 power = chan->max_power;
295 else
296
297 --
298 Jouni Malinen PGP id EFC895FA
299 --
300 To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
301 the body of a message to majordomo@vger.kernel.org
302 More majordomo info at http://vger.kernel.org/majordomo-info.html
303