blob: 89c83fa9aacb1fd91e6be04a2ae0a5a8c2c44065 [file] [log] [blame]
Johannes Berg370121e2006-01-04 16:32:16 +01001/*
2 * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
Johannes Berg4855d252006-01-12 21:12:59 +01003 *
Johannes Berg79859052006-01-31 19:31:41 +01004 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
Johannes Berg4855d252006-01-12 21:12:59 +01009 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
Johannes Berg370121e2006-01-04 16:32:16 +010025 */
26
27#include "ieee80211softmac_priv.h"
28
29#include <net/iw_handler.h>
Johannes Berg818667f2006-04-20 20:02:03 +020030/* for is_broadcast_ether_addr and is_zero_ether_addr */
31#include <linux/etherdevice.h>
Johannes Berg370121e2006-01-04 16:32:16 +010032
33int
34ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
35 struct iw_request_info *info,
36 union iwreq_data *data,
37 char *extra)
38{
39 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
40 return ieee80211softmac_start_scan(sm);
41}
42EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
43
44
johannes@sipsolutions.netba2f8c12006-04-11 10:58:06 +020045/* if we're still scanning, return -EAGAIN so that userspace tools
46 * can get the complete scan results, otherwise return 0. */
Johannes Berg370121e2006-01-04 16:32:16 +010047int
48ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
49 struct iw_request_info *info,
50 union iwreq_data *data,
51 char *extra)
52{
johannes@sipsolutions.netba2f8c12006-04-11 10:58:06 +020053 unsigned long flags;
Johannes Berg370121e2006-01-04 16:32:16 +010054 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
johannes@sipsolutions.netba2f8c12006-04-11 10:58:06 +020055
56 spin_lock_irqsave(&sm->lock, flags);
57 if (sm->scanning) {
58 spin_unlock_irqrestore(&sm->lock, flags);
59 return -EAGAIN;
60 }
61 spin_unlock_irqrestore(&sm->lock, flags);
Johannes Berg370121e2006-01-04 16:32:16 +010062 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
63}
64EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
65
66int
67ieee80211softmac_wx_set_essid(struct net_device *net_dev,
68 struct iw_request_info *info,
69 union iwreq_data *data,
70 char *extra)
71{
72 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
Joseph Jezakcb74c432006-06-11 12:00:37 -040073 struct ieee80211softmac_network *n;
74 struct ieee80211softmac_auth_queue_item *authptr;
Johannes Berg370121e2006-01-04 16:32:16 +010075 int length = 0;
Michael Buesch7c28ad22006-09-27 15:26:33 +030076
77 mutex_lock(&sm->associnfo.mutex);
Joseph Jezakcb74c432006-06-11 12:00:37 -040078
79 /* Check if we're already associating to this or another network
80 * If it's another network, cancel and start over with our new network
81 * If it's our network, ignore the change, we're already doing it!
82 */
Michael Buesch7c28ad22006-09-27 15:26:33 +030083 if((sm->associnfo.associating || sm->associnfo.associated) &&
Larry Fingerb978d022006-08-31 10:01:39 -050084 (data->essid.flags && data->essid.length)) {
Joseph Jezakcb74c432006-06-11 12:00:37 -040085 /* Get the associating network */
86 n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
Larry Fingerb978d022006-08-31 10:01:39 -050087 if(n && n->essid.len == data->essid.length &&
Joseph Jezakcb74c432006-06-11 12:00:37 -040088 !memcmp(n->essid.data, extra, n->essid.len)) {
89 dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
90 MAC_ARG(sm->associnfo.bssid));
Michael Buesch7c28ad22006-09-27 15:26:33 +030091 goto out;
Joseph Jezakcb74c432006-06-11 12:00:37 -040092 } else {
93 dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
Joseph Jezakcb74c432006-06-11 12:00:37 -040094 /* Cancel assoc work */
95 cancel_delayed_work(&sm->associnfo.work);
96 /* We don't have to do this, but it's a little cleaner */
97 list_for_each_entry(authptr, &sm->auth_queue, list)
98 cancel_delayed_work(&authptr->work);
99 sm->associnfo.bssvalid = 0;
100 sm->associnfo.bssfixed = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400101 flush_scheduled_work();
Michael Buesch7c28ad22006-09-27 15:26:33 +0300102 sm->associnfo.associating = 0;
103 sm->associnfo.associated = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400104 }
105 }
106
107
Johannes Berg370121e2006-01-04 16:32:16 +0100108 sm->associnfo.static_essid = 0;
Joseph Jezakcb74c432006-06-11 12:00:37 -0400109 sm->associnfo.assoc_wait = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100110
Larry Fingerb978d022006-08-31 10:01:39 -0500111 if (data->essid.flags && data->essid.length) {
112 length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
Johannes Berg370121e2006-01-04 16:32:16 +0100113 if (length) {
114 memcpy(sm->associnfo.req_essid.data, extra, length);
115 sm->associnfo.static_essid = 1;
116 }
117 }
Johannes Berg370121e2006-01-04 16:32:16 +0100118
119 /* set our requested ESSID length.
120 * If applicable, we have already copied the data in */
121 sm->associnfo.req_essid.len = length;
122
Michael Buesch7c28ad22006-09-27 15:26:33 +0300123 sm->associnfo.associating = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100124 /* queue lower level code to do work (if necessary) */
David Howellsc4028952006-11-22 14:57:56 +0000125 schedule_delayed_work(&sm->associnfo.work, 0);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300126out:
127 mutex_unlock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100128
Johannes Berg370121e2006-01-04 16:32:16 +0100129 return 0;
130}
131EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
132
133int
134ieee80211softmac_wx_get_essid(struct net_device *net_dev,
135 struct iw_request_info *info,
136 union iwreq_data *data,
137 char *extra)
138{
139 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100140
Michael Buesch7c28ad22006-09-27 15:26:33 +0300141 mutex_lock(&sm->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100142 /* If all fails, return ANY (empty) */
143 data->essid.length = 0;
144 data->essid.flags = 0; /* active */
145
146 /* If we have a statically configured ESSID then return it */
147 if (sm->associnfo.static_essid) {
148 data->essid.length = sm->associnfo.req_essid.len;
149 data->essid.flags = 1; /* active */
150 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
151 }
152
153 /* If we're associating/associated, return that */
Michael Buesch7c28ad22006-09-27 15:26:33 +0300154 if (sm->associnfo.associated || sm->associnfo.associating) {
Johannes Berg370121e2006-01-04 16:32:16 +0100155 data->essid.length = sm->associnfo.associate_essid.len;
156 data->essid.flags = 1; /* active */
157 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
158 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300159 mutex_unlock(&sm->associnfo.mutex);
160
Johannes Berg370121e2006-01-04 16:32:16 +0100161 return 0;
162}
163EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
164
165int
166ieee80211softmac_wx_set_rate(struct net_device *net_dev,
167 struct iw_request_info *info,
168 union iwreq_data *data,
169 char *extra)
170{
171 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
172 struct ieee80211_device *ieee = mac->ieee;
173 unsigned long flags;
174 s32 in_rate = data->bitrate.value;
175 u8 rate;
176 int is_ofdm = 0;
177 int err = -EINVAL;
178
179 if (in_rate == -1) {
Larry Fingerbb52a652007-02-13 18:58:03 -0600180 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
181 in_rate = 24000000;
David Woodhouse2638fed2006-03-23 22:43:38 +0000182 else
Larry Fingerbb52a652007-02-13 18:58:03 -0600183 in_rate = 11000000;
Johannes Berg370121e2006-01-04 16:32:16 +0100184 }
185
186 switch (in_rate) {
187 case 1000000:
188 rate = IEEE80211_CCK_RATE_1MB;
189 break;
190 case 2000000:
191 rate = IEEE80211_CCK_RATE_2MB;
192 break;
193 case 5500000:
194 rate = IEEE80211_CCK_RATE_5MB;
195 break;
196 case 11000000:
197 rate = IEEE80211_CCK_RATE_11MB;
198 break;
199 case 6000000:
200 rate = IEEE80211_OFDM_RATE_6MB;
201 is_ofdm = 1;
202 break;
203 case 9000000:
204 rate = IEEE80211_OFDM_RATE_9MB;
205 is_ofdm = 1;
206 break;
207 case 12000000:
208 rate = IEEE80211_OFDM_RATE_12MB;
209 is_ofdm = 1;
210 break;
211 case 18000000:
212 rate = IEEE80211_OFDM_RATE_18MB;
213 is_ofdm = 1;
214 break;
215 case 24000000:
216 rate = IEEE80211_OFDM_RATE_24MB;
217 is_ofdm = 1;
218 break;
219 case 36000000:
220 rate = IEEE80211_OFDM_RATE_36MB;
221 is_ofdm = 1;
222 break;
223 case 48000000:
224 rate = IEEE80211_OFDM_RATE_48MB;
225 is_ofdm = 1;
226 break;
227 case 54000000:
228 rate = IEEE80211_OFDM_RATE_54MB;
229 is_ofdm = 1;
230 break;
231 default:
232 goto out;
233 }
234
235 spin_lock_irqsave(&mac->lock, flags);
236
237 /* Check if correct modulation for this PHY. */
238 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
239 goto out_unlock;
240
Daniel Drake8462fe32006-05-01 22:45:50 +0100241 mac->txrates.user_rate = rate;
242 ieee80211softmac_recalc_txrates(mac);
Johannes Berg370121e2006-01-04 16:32:16 +0100243 err = 0;
244
245out_unlock:
246 spin_unlock_irqrestore(&mac->lock, flags);
247out:
248 return err;
249}
250EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
251
252int
253ieee80211softmac_wx_get_rate(struct net_device *net_dev,
254 struct iw_request_info *info,
255 union iwreq_data *data,
256 char *extra)
257{
258 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
259 unsigned long flags;
260 int err = -EINVAL;
261
262 spin_lock_irqsave(&mac->lock, flags);
263 switch (mac->txrates.default_rate) {
264 case IEEE80211_CCK_RATE_1MB:
265 data->bitrate.value = 1000000;
266 break;
267 case IEEE80211_CCK_RATE_2MB:
268 data->bitrate.value = 2000000;
269 break;
270 case IEEE80211_CCK_RATE_5MB:
271 data->bitrate.value = 5500000;
272 break;
273 case IEEE80211_CCK_RATE_11MB:
274 data->bitrate.value = 11000000;
275 break;
276 case IEEE80211_OFDM_RATE_6MB:
277 data->bitrate.value = 6000000;
278 break;
279 case IEEE80211_OFDM_RATE_9MB:
280 data->bitrate.value = 9000000;
281 break;
282 case IEEE80211_OFDM_RATE_12MB:
283 data->bitrate.value = 12000000;
284 break;
285 case IEEE80211_OFDM_RATE_18MB:
286 data->bitrate.value = 18000000;
287 break;
288 case IEEE80211_OFDM_RATE_24MB:
289 data->bitrate.value = 24000000;
290 break;
291 case IEEE80211_OFDM_RATE_36MB:
292 data->bitrate.value = 36000000;
293 break;
294 case IEEE80211_OFDM_RATE_48MB:
295 data->bitrate.value = 48000000;
296 break;
297 case IEEE80211_OFDM_RATE_54MB:
298 data->bitrate.value = 54000000;
299 break;
300 default:
301 assert(0);
302 goto out_unlock;
303 }
304 err = 0;
305out_unlock:
306 spin_unlock_irqrestore(&mac->lock, flags);
307
308 return err;
309}
310EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
311
312int
313ieee80211softmac_wx_get_wap(struct net_device *net_dev,
314 struct iw_request_info *info,
315 union iwreq_data *data,
316 char *extra)
317{
318 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
319 int err = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100320
Michael Buesch7c28ad22006-09-27 15:26:33 +0300321 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100322 if (mac->associnfo.bssvalid)
323 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
324 else
325 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
326 data->ap_addr.sa_family = ARPHRD_ETHER;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300327 mutex_unlock(&mac->associnfo.mutex);
328
Johannes Berg370121e2006-01-04 16:32:16 +0100329 return err;
330}
331EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
332
333int
334ieee80211softmac_wx_set_wap(struct net_device *net_dev,
335 struct iw_request_info *info,
336 union iwreq_data *data,
337 char *extra)
338{
339 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
Johannes Berg370121e2006-01-04 16:32:16 +0100340
341 /* sanity check */
342 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
343 return -EINVAL;
344 }
345
Michael Buesch7c28ad22006-09-27 15:26:33 +0300346 mutex_lock(&mac->associnfo.mutex);
Johannes Berg818667f2006-04-20 20:02:03 +0200347 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
348 /* the bssid we have is not to be fixed any longer,
349 * and we should reassociate to the best AP. */
350 mac->associnfo.bssfixed = 0;
351 /* force reassociation */
352 mac->associnfo.bssvalid = 0;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300353 if (mac->associnfo.associated)
David Howellsc4028952006-11-22 14:57:56 +0000354 schedule_delayed_work(&mac->associnfo.work, 0);
Johannes Berg818667f2006-04-20 20:02:03 +0200355 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
356 /* the bssid we have is no longer fixed */
357 mac->associnfo.bssfixed = 0;
Johannes Berg370121e2006-01-04 16:32:16 +0100358 } else {
359 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
Michael Buesch7c28ad22006-09-27 15:26:33 +0300360 if (mac->associnfo.associating || mac->associnfo.associated) {
Johannes Berg370121e2006-01-04 16:32:16 +0100361 /* bssid unchanged and associated or associating - just return */
362 goto out;
363 }
364 } else {
365 /* copy new value in data->ap_addr.sa_data to bssid */
366 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
Johannes Berg818667f2006-04-20 20:02:03 +0200367 }
368 /* tell the other code that this bssid should be used no matter what */
369 mac->associnfo.bssfixed = 1;
Johannes Berg370121e2006-01-04 16:32:16 +0100370 /* queue associate if new bssid or (old one again and not associated) */
David Howellsc4028952006-11-22 14:57:56 +0000371 schedule_delayed_work(&mac->associnfo.work, 0);
Johannes Berg370121e2006-01-04 16:32:16 +0100372 }
373
Johannes Berg818667f2006-04-20 20:02:03 +0200374 out:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300375 mutex_unlock(&mac->associnfo.mutex);
376
Johannes Berg370121e2006-01-04 16:32:16 +0100377 return 0;
378}
379EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
380
381int
382ieee80211softmac_wx_set_genie(struct net_device *dev,
383 struct iw_request_info *info,
384 union iwreq_data *wrqu,
385 char *extra)
386{
387 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
388 unsigned long flags;
389 int err = 0;
390 char *buf;
391 int i;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300392
393 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100394 spin_lock_irqsave(&mac->lock, flags);
395 /* bleh. shouldn't be locked for that kmalloc... */
396
397 if (wrqu->data.length) {
398 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
399 /* this is an IE, so the length must be
400 * correct. Is it possible though that
401 * more than one IE is passed in?
402 */
403 err = -EINVAL;
404 goto out;
405 }
406 if (mac->wpa.IEbuflen <= wrqu->data.length) {
407 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
408 if (!buf) {
409 err = -ENOMEM;
410 goto out;
411 }
412 kfree(mac->wpa.IE);
413 mac->wpa.IE = buf;
414 mac->wpa.IEbuflen = wrqu->data.length;
415 }
416 memcpy(mac->wpa.IE, extra, wrqu->data.length);
417 dprintk(KERN_INFO PFX "generic IE set to ");
418 for (i=0;i<wrqu->data.length;i++)
Larry Finger7bd6b912006-06-08 09:47:42 -0500419 dprintk("%.2x", (u8)mac->wpa.IE[i]);
Johannes Berg370121e2006-01-04 16:32:16 +0100420 dprintk("\n");
421 mac->wpa.IElen = wrqu->data.length;
422 } else {
423 kfree(mac->wpa.IE);
424 mac->wpa.IE = NULL;
425 mac->wpa.IElen = 0;
426 mac->wpa.IEbuflen = 0;
427 }
428
429 out:
430 spin_unlock_irqrestore(&mac->lock, flags);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300431 mutex_unlock(&mac->associnfo.mutex);
432
Johannes Berg370121e2006-01-04 16:32:16 +0100433 return err;
434}
435EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
436
437int
438ieee80211softmac_wx_get_genie(struct net_device *dev,
439 struct iw_request_info *info,
440 union iwreq_data *wrqu,
441 char *extra)
442{
443 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
444 unsigned long flags;
445 int err = 0;
446 int space = wrqu->data.length;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300447
448 mutex_lock(&mac->associnfo.mutex);
Johannes Berg370121e2006-01-04 16:32:16 +0100449 spin_lock_irqsave(&mac->lock, flags);
450
451 wrqu->data.length = 0;
452
453 if (mac->wpa.IE && mac->wpa.IElen) {
454 wrqu->data.length = mac->wpa.IElen;
455 if (mac->wpa.IElen <= space)
456 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
457 else
458 err = -E2BIG;
459 }
460 spin_unlock_irqrestore(&mac->lock, flags);
Ulrich Kunitz0c234ae2006-12-10 18:27:01 +0100461 mutex_unlock(&mac->associnfo.mutex);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300462
Johannes Berg370121e2006-01-04 16:32:16 +0100463 return err;
464}
465EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
466
Johannes Berg9a1771e2006-04-20 20:02:02 +0200467int
468ieee80211softmac_wx_set_mlme(struct net_device *dev,
469 struct iw_request_info *info,
470 union iwreq_data *wrqu,
471 char *extra)
472{
473 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
474 struct iw_mlme *mlme = (struct iw_mlme *)extra;
475 u16 reason = cpu_to_le16(mlme->reason_code);
476 struct ieee80211softmac_network *net;
Michael Buesch7c28ad22006-09-27 15:26:33 +0300477 int err = -EINVAL;
478
479 mutex_lock(&mac->associnfo.mutex);
Johannes Berg9a1771e2006-04-20 20:02:02 +0200480
481 if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
482 printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
Michael Buesch7c28ad22006-09-27 15:26:33 +0300483 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200484 }
485
486 switch (mlme->cmd) {
487 case IW_MLME_DEAUTH:
488 net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
489 if (!net) {
490 printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
Michael Buesch7c28ad22006-09-27 15:26:33 +0300491 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200492 }
Maxime Austruycc8ce992006-12-03 10:40:01 -0600493 err = ieee80211softmac_deauth_req(mac, net, reason);
494 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200495 case IW_MLME_DISASSOC:
Daniel Drake6d92f832006-05-01 22:23:27 +0100496 ieee80211softmac_send_disassoc_req(mac, reason);
Michael Buesch7c28ad22006-09-27 15:26:33 +0300497 mac->associnfo.associated = 0;
498 mac->associnfo.associating = 0;
499 err = 0;
500 goto out;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200501 default:
Michael Buesch7c28ad22006-09-27 15:26:33 +0300502 err = -EOPNOTSUPP;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200503 }
Michael Buesch7c28ad22006-09-27 15:26:33 +0300504
505out:
506 mutex_unlock(&mac->associnfo.mutex);
507
508 return err;
Johannes Berg9a1771e2006-04-20 20:02:02 +0200509}
510EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);