staging: ath6kl: Convert (status != A_OK) to (status)
[firefly-linux-kernel-4.4.55.git] / drivers / staging / ath6kl / os / linux / wireless_ext.c
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
4 //
5 // 
6 //
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
10 //
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 //
19 //
20 //
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
23
24 #include "ar6000_drv.h"
25
26 #define IWE_STREAM_ADD_EVENT(p1, p2, p3, p4, p5) \
27     iwe_stream_add_event((p1), (p2), (p3), (p4), (p5))
28
29 #define IWE_STREAM_ADD_POINT(p1, p2, p3, p4, p5) \
30     iwe_stream_add_point((p1), (p2), (p3), (p4), (p5))
31
32 #define IWE_STREAM_ADD_VALUE(p1, p2, p3, p4, p5, p6) \
33     iwe_stream_add_value((p1), (p2), (p3), (p4), (p5), (p6))
34
35 static void ar6000_set_quality(struct iw_quality *iq, s8 rssi);
36 extern unsigned int wmitimeout;
37 extern A_WAITQUEUE_HEAD arEvent;
38
39 #if WIRELESS_EXT > 14
40 /*
41  * Encode a WPA or RSN information element as a custom
42  * element using the hostap format.
43  */
44 static u_int
45 encode_ie(void *buf, size_t bufsize,
46     const u_int8_t *ie, size_t ielen,
47     const char *leader, size_t leader_len)
48 {
49     u_int8_t *p;
50     int i;
51
52     if (bufsize < leader_len)
53         return 0;
54     p = buf;
55     memcpy(p, leader, leader_len);
56     bufsize -= leader_len;
57     p += leader_len;
58     for (i = 0; i < ielen && bufsize > 2; i++)
59     {
60         p += sprintf((char*)p, "%02x", ie[i]);
61         bufsize -= 2;
62     }
63     return (i == ielen ? p - (u_int8_t *)buf : 0);
64 }
65 #endif /* WIRELESS_EXT > 14 */
66
67 static u8 get_bss_phy_capability(bss_t *bss)
68 {
69     u8 capability = 0;
70     struct ieee80211_common_ie *cie = &bss->ni_cie;
71 #define CHAN_IS_11A(x)              (!((x >= 2412) && (x <= 2484)))
72     if (CHAN_IS_11A(cie->ie_chan)) {
73         if (cie->ie_htcap) {
74             capability = WMI_11NA_CAPABILITY;
75         } else {
76             capability = WMI_11A_CAPABILITY;
77         }
78     } else if ((cie->ie_erp) || (cie->ie_xrates)) {
79         if (cie->ie_htcap) {
80             capability = WMI_11NG_CAPABILITY;
81         } else {
82             capability = WMI_11G_CAPABILITY;
83         }
84     }
85     return capability;
86 }
87
88 void
89 ar6000_scan_node(void *arg, bss_t *ni)
90 {
91     struct iw_event iwe;
92 #if WIRELESS_EXT > 14
93     char buf[256];
94 #endif
95     struct ar_giwscan_param *param;
96     char *current_ev;
97     char *end_buf;
98     struct ieee80211_common_ie  *cie;
99     char *current_val;
100     s32 j;
101     u32 rate_len, data_len = 0;
102
103     param = (struct ar_giwscan_param *)arg;
104
105     current_ev = param->current_ev;
106     end_buf = param->end_buf;
107
108     cie = &ni->ni_cie;
109
110     if ((end_buf - current_ev) > IW_EV_ADDR_LEN)
111     {
112         A_MEMZERO(&iwe, sizeof(iwe));
113         iwe.cmd = SIOCGIWAP;
114         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
115         A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
116         current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
117                                           &iwe, IW_EV_ADDR_LEN);
118     }
119     param->bytes_needed += IW_EV_ADDR_LEN;
120
121     data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN;
122     if ((end_buf - current_ev) > data_len)
123     {
124         A_MEMZERO(&iwe, sizeof(iwe));
125         iwe.cmd = SIOCGIWESSID;
126         iwe.u.data.flags = 1;
127         iwe.u.data.length = cie->ie_ssid[1];
128         current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
129                                           &iwe, (char*)&cie->ie_ssid[2]);
130     }
131     param->bytes_needed += data_len;
132
133     if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
134         if ((end_buf - current_ev) > IW_EV_UINT_LEN)
135         {
136             A_MEMZERO(&iwe, sizeof(iwe));
137             iwe.cmd = SIOCGIWMODE;
138             iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
139                          IW_MODE_MASTER : IW_MODE_ADHOC;
140             current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
141                                               &iwe, IW_EV_UINT_LEN);
142         }
143         param->bytes_needed += IW_EV_UINT_LEN;
144     }
145
146     if ((end_buf - current_ev) > IW_EV_FREQ_LEN)
147     {
148         A_MEMZERO(&iwe, sizeof(iwe));
149         iwe.cmd = SIOCGIWFREQ;
150         iwe.u.freq.m = cie->ie_chan * 100000;
151         iwe.u.freq.e = 1;
152         current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
153                                           &iwe, IW_EV_FREQ_LEN);
154     }
155     param->bytes_needed += IW_EV_FREQ_LEN;
156
157     if ((end_buf - current_ev) > IW_EV_QUAL_LEN)
158     {
159         A_MEMZERO(&iwe, sizeof(iwe));
160         iwe.cmd = IWEVQUAL;
161         ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
162         current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
163                                           &iwe, IW_EV_QUAL_LEN);
164     }
165     param->bytes_needed += IW_EV_QUAL_LEN;
166
167     if ((end_buf - current_ev) > IW_EV_POINT_LEN)
168     {
169         A_MEMZERO(&iwe, sizeof(iwe));
170         iwe.cmd = SIOCGIWENCODE;
171         if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
172             iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
173         } else {
174             iwe.u.data.flags = IW_ENCODE_DISABLED;
175         }
176         iwe.u.data.length = 0;
177         current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
178                                           &iwe, "");
179     }
180     param->bytes_needed += IW_EV_POINT_LEN;
181
182     /* supported bit rate */
183     A_MEMZERO(&iwe, sizeof(iwe));
184     iwe.cmd = SIOCGIWRATE;
185     iwe.u.bitrate.fixed = 0;
186     iwe.u.bitrate.disabled = 0;
187     iwe.u.bitrate.value = 0;
188     current_val = current_ev + IW_EV_LCP_LEN;
189     param->bytes_needed += IW_EV_LCP_LEN;
190
191     if (cie->ie_rates != NULL) {
192         rate_len = cie->ie_rates[1];
193         data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
194         if ((end_buf - current_ev) > data_len)
195         {
196             for (j = 0; j < rate_len; j++) {
197                     unsigned char val;
198                     val = cie->ie_rates[2 + j];
199                     iwe.u.bitrate.value =
200                         (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
201                     current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
202                                                        current_val, end_buf,
203                                                        &iwe, IW_EV_PARAM_LEN);
204             }
205         }
206         param->bytes_needed += data_len;
207     }
208
209     if (cie->ie_xrates != NULL) {
210         rate_len = cie->ie_xrates[1];
211         data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
212         if ((end_buf - current_ev) > data_len)
213         {
214             for (j = 0; j < rate_len; j++) {
215                     unsigned char val;
216                     val = cie->ie_xrates[2 + j];
217                     iwe.u.bitrate.value =
218                         (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
219                     current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
220                                                        current_val, end_buf,
221                                                        &iwe, IW_EV_PARAM_LEN);
222             }
223         }
224         param->bytes_needed += data_len;
225     }
226     /* remove fixed header if no rates were added */
227     if ((current_val - current_ev) > IW_EV_LCP_LEN)
228         current_ev = current_val;
229
230 #if WIRELESS_EXT >= 18
231     /* IE */
232     if (cie->ie_wpa != NULL) {
233         data_len = cie->ie_wpa[1] + 2 + IW_EV_POINT_LEN;
234         if ((end_buf - current_ev) > data_len)
235         {
236             A_MEMZERO(&iwe, sizeof(iwe));
237             iwe.cmd = IWEVGENIE;
238             iwe.u.data.length = cie->ie_wpa[1] + 2;
239             current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
240                                               &iwe, (char*)cie->ie_wpa);
241         }
242         param->bytes_needed += data_len;
243     }
244
245     if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
246         data_len = cie->ie_rsn[1] + 2 + IW_EV_POINT_LEN;
247         if ((end_buf - current_ev) > data_len)
248         {
249             A_MEMZERO(&iwe, sizeof(iwe));
250             iwe.cmd = IWEVGENIE;
251             iwe.u.data.length = cie->ie_rsn[1] + 2;
252             current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
253                                               &iwe, (char*)cie->ie_rsn);
254         }
255         param->bytes_needed += data_len;
256     }
257
258 #endif /* WIRELESS_EXT >= 18 */
259
260     if ((end_buf - current_ev) > IW_EV_CHAR_LEN)
261     {
262         /* protocol */
263         A_MEMZERO(&iwe, sizeof(iwe));
264         iwe.cmd = SIOCGIWNAME;
265         switch (get_bss_phy_capability(ni)) {
266         case WMI_11A_CAPABILITY:
267             snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
268             break;
269         case WMI_11G_CAPABILITY:
270             snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
271             break;
272         case WMI_11NA_CAPABILITY:
273             snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11na");
274             break;
275         case WMI_11NG_CAPABILITY:
276             snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11ng");
277             break;
278         default:
279             snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
280             break;
281         }
282         current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
283                                           &iwe, IW_EV_CHAR_LEN);
284     }
285     param->bytes_needed += IW_EV_CHAR_LEN;
286
287 #if WIRELESS_EXT > 14
288     A_MEMZERO(&iwe, sizeof(iwe));
289     iwe.cmd = IWEVCUSTOM;
290     iwe.u.data.length = snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
291     data_len = iwe.u.data.length + IW_EV_POINT_LEN;
292     if ((end_buf - current_ev) > data_len)
293     {
294         current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
295                                           &iwe, buf);
296     }
297     param->bytes_needed += data_len;
298
299 #if WIRELESS_EXT < 18
300     if (cie->ie_wpa != NULL) {
301         static const char wpa_leader[] = "wpa_ie=";
302         data_len = (sizeof(wpa_leader) - 1) + ((cie->ie_wpa[1]+2) * 2) + IW_EV_POINT_LEN;
303         if ((end_buf - current_ev) > data_len)
304         {
305             A_MEMZERO(&iwe, sizeof(iwe));
306             iwe.cmd = IWEVCUSTOM;
307             iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
308                                           cie->ie_wpa[1]+2,
309                                           wpa_leader, sizeof(wpa_leader)-1);
310
311             if (iwe.u.data.length != 0) {
312                 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, 
313                                                   end_buf, &iwe, buf);
314             }
315         }
316         param->bytes_needed += data_len;
317     }
318
319     if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
320         static const char rsn_leader[] = "rsn_ie=";
321         data_len = (sizeof(rsn_leader) - 1) + ((cie->ie_rsn[1]+2) * 2) + IW_EV_POINT_LEN;
322         if ((end_buf - current_ev) > data_len)
323         {
324             A_MEMZERO(&iwe, sizeof(iwe));
325             iwe.cmd = IWEVCUSTOM;
326             iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
327                                           cie->ie_rsn[1]+2,
328                                           rsn_leader, sizeof(rsn_leader)-1);
329
330             if (iwe.u.data.length != 0) {
331                 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, 
332                                                   end_buf, &iwe, buf);
333             }
334         }
335         param->bytes_needed += data_len;
336     }
337 #endif /* WIRELESS_EXT < 18 */
338
339     if (cie->ie_wmm != NULL) {
340         static const char wmm_leader[] = "wmm_ie=";
341         data_len = (sizeof(wmm_leader) - 1) + ((cie->ie_wmm[1]+2) * 2) + IW_EV_POINT_LEN;
342         if ((end_buf - current_ev) > data_len)
343         {
344             A_MEMZERO(&iwe, sizeof(iwe));
345             iwe.cmd = IWEVCUSTOM;
346             iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
347                                           cie->ie_wmm[1]+2,
348                                           wmm_leader, sizeof(wmm_leader)-1);
349             if (iwe.u.data.length != 0) {
350                 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
351                                                   end_buf, &iwe, buf);
352             }
353         }
354         param->bytes_needed += data_len;
355     }
356
357     if (cie->ie_ath != NULL) {
358         static const char ath_leader[] = "ath_ie=";
359         data_len = (sizeof(ath_leader) - 1) + ((cie->ie_ath[1]+2) * 2) + IW_EV_POINT_LEN;
360         if ((end_buf - current_ev) > data_len)
361         {
362             A_MEMZERO(&iwe, sizeof(iwe));
363             iwe.cmd = IWEVCUSTOM;
364             iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
365                                           cie->ie_ath[1]+2,
366                                           ath_leader, sizeof(ath_leader)-1);
367             if (iwe.u.data.length != 0) {
368                 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
369                                                   end_buf, &iwe, buf);
370             }
371         }
372         param->bytes_needed += data_len;
373     }
374
375 #ifdef WAPI_ENABLE
376     if (cie->ie_wapi != NULL) {
377         static const char wapi_leader[] = "wapi_ie=";
378         data_len = (sizeof(wapi_leader) - 1) + ((cie->ie_wapi[1] + 2) * 2) + IW_EV_POINT_LEN;
379         if ((end_buf - current_ev) > data_len) {
380             A_MEMZERO(&iwe, sizeof(iwe));
381             iwe.cmd = IWEVCUSTOM;
382             iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wapi,
383                                       cie->ie_wapi[1] + 2,
384                                       wapi_leader, sizeof(wapi_leader) - 1);
385             if (iwe.u.data.length != 0) {
386                 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
387                                                   end_buf, &iwe, buf);
388             }
389         }
390         param->bytes_needed += data_len;
391     }
392 #endif /* WAPI_ENABLE */
393
394 #endif /* WIRELESS_EXT > 14 */
395
396 #if WIRELESS_EXT >= 18
397     if (cie->ie_wsc != NULL) {
398         data_len = (cie->ie_wsc[1] + 2) + IW_EV_POINT_LEN;
399         if ((end_buf - current_ev) > data_len)
400         {
401             A_MEMZERO(&iwe, sizeof(iwe));
402             iwe.cmd = IWEVGENIE;
403             iwe.u.data.length = cie->ie_wsc[1] + 2;
404             current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
405                                               &iwe, (char*)cie->ie_wsc);
406         }
407         param->bytes_needed += data_len;
408     }
409 #endif /* WIRELESS_EXT >= 18 */
410
411     param->current_ev = current_ev;
412 }
413
414 int
415 ar6000_ioctl_giwscan(struct net_device *dev,
416             struct iw_request_info *info,
417             struct iw_point *data, char *extra)
418 {
419     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
420     struct ar_giwscan_param param;
421
422     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
423         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
424         return -EOPNOTSUPP;
425     }
426
427     if (ar->arWlanState == WLAN_DISABLED) {
428         return -EIO;
429     }
430
431     if (ar->arWmiReady == false) {
432         return -EIO;
433     }
434
435     param.current_ev = extra;
436     param.end_buf = extra + data->length;
437     param.bytes_needed = 0;
438     param.info = info;
439
440     /* Translate data to WE format */
441     wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
442
443     /* check if bytes needed is greater than bytes consumed */
444     if (param.bytes_needed > (param.current_ev - extra))
445     {
446         /* Request one byte more than needed, because when "data->length" equals bytes_needed,
447         it is not possible to add the last event data as all iwe_stream_add_xxxxx() functions
448         checks whether (cur_ptr + ev_len) < end_ptr, due to this one more retry would happen*/
449         data->length = param.bytes_needed + 1;
450
451         return -E2BIG;
452     }
453
454     return 0;
455 }
456
457 extern int reconnect_flag;
458 /* SIOCSIWESSID */
459 static int
460 ar6000_ioctl_siwessid(struct net_device *dev,
461                      struct iw_request_info *info,
462                      struct iw_point *data, char *ssid)
463 {
464     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
465     int status;
466     u8 arNetworkType;
467     u8 prevMode = ar->arNetworkType;
468
469     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
470         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
471         return -EOPNOTSUPP;
472     }
473
474     if (ar->bIsDestroyProgress) {
475         return -EBUSY;
476     }
477
478     if (ar->arWlanState == WLAN_DISABLED) {
479         return -EIO;
480     }
481
482     if (ar->arWmiReady == false) {
483         return -EIO;
484     }
485
486 #if defined(WIRELESS_EXT)
487     if (WIRELESS_EXT >= 20) {
488         data->length += 1;
489     }
490 #endif
491
492     /*
493      * iwconfig passes a null terminated string with length including this
494      * so we need to account for this
495      */
496     if (data->flags && (!data->length || (data->length == 1) ||
497         ((data->length - 1) > sizeof(ar->arSsid))))
498     {
499         /*
500          * ssid is invalid
501          */
502         return -EINVAL;
503     }
504
505     if (ar->arNextMode == AP_NETWORK) {
506         /* SSID change for AP network - Will take effect on commit */
507         if(A_MEMCMP(ar->arSsid,ssid,32) != 0) {
508              ar->arSsidLen = data->length - 1;
509             A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
510             ar->ap_profile_flag = 1; /* There is a change in profile */
511         }
512         return 0;
513     } else if(ar->arNetworkType == AP_NETWORK) {
514         u8 ctr;
515         struct sk_buff *skb;
516
517         /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
518         for (ctr=0; ctr < AP_MAX_NUM_STA; ctr++) {
519             remove_sta(ar, ar->sta_list[ctr].mac, 0);
520         }
521         A_MUTEX_LOCK(&ar->mcastpsqLock);
522         while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
523             skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
524             A_NETBUF_FREE(skb);
525         }
526         A_MUTEX_UNLOCK(&ar->mcastpsqLock);
527     }
528
529     /* Added for bug 25178, return an IOCTL error instead of target returning
530        Illegal parameter error when either the BSSID or channel is missing
531        and we cannot scan during connect.
532      */
533     if (data->flags) {
534         if (ar->arSkipScan == true &&
535             (ar->arChannelHint == 0 ||
536              (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
537               !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
538         {
539             return -EINVAL;
540         }
541     }
542
543     if (down_interruptible(&ar->arSem)) {
544         return -ERESTARTSYS;
545     }
546
547     if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
548         up(&ar->arSem);
549         return -EBUSY;
550     }
551
552     if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
553         /*
554          * sleep until the command queue drains
555          */
556         wait_event_interruptible_timeout(arEvent,
557             ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ);
558         if (signal_pending(current)) {
559             return -EINTR;
560         }
561     }
562
563     if (!data->flags) {
564         arNetworkType = ar->arNetworkType;
565 #ifdef ATH6K_CONFIG_CFG80211
566         if (ar->arConnected) {
567 #endif /* ATH6K_CONFIG_CFG80211 */
568             ar6000_init_profile_info(ar);
569 #ifdef ATH6K_CONFIG_CFG80211
570         }
571 #endif /* ATH6K_CONFIG_CFG80211 */
572         ar->arNetworkType = arNetworkType;
573     }
574
575     /* Update the arNetworkType */
576     ar->arNetworkType = ar->arNextMode;
577
578
579     if ((prevMode != AP_NETWORK) &&
580         ((ar->arSsidLen) || ((ar->arSsidLen == 0) && ar->arConnected) || (!data->flags)))
581     {
582         if ((!data->flags) ||
583             (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
584             (ar->arSsidLen != (data->length - 1)))
585         {
586             /*
587              * SSID set previously or essid off has been issued.
588              *
589              * Disconnect Command is issued in two cases after wmi is ready
590              * (1) ssid is different from the previous setting
591              * (2) essid off has been issued
592              *
593              */
594             if (ar->arWmiReady == true) {
595                 reconnect_flag = 0;
596                 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
597                 status = wmi_disconnect_cmd(ar->arWmi);
598                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
599                 ar->arSsidLen = 0;
600                 if (ar->arSkipScan == false) {
601                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
602                 }
603                 if (!data->flags) {
604                     up(&ar->arSem);
605                     return 0;
606                 }
607             } else {
608                  up(&ar->arSem);
609             }
610         }
611         else
612         {
613             /*
614              * SSID is same, so we assume profile hasn't changed.
615              * If the interface is up and wmi is ready, we issue
616              * a reconnect cmd. Issue a reconnect only we are already
617              * connected.
618              */
619             if((ar->arConnected == true) && (ar->arWmiReady == true))
620             {
621                 reconnect_flag = true;
622                 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
623                                            ar->arChannelHint);
624                 up(&ar->arSem);
625                 if (status) {
626                     return -EIO;
627                 }
628                 return 0;
629             }
630             else{
631                 /*
632                  * Dont return if connect is pending.
633                  */
634                 if(!(ar->arConnectPending)) {
635                     up(&ar->arSem);
636                     return 0;
637                 }
638             }
639         }
640     }
641
642     ar->arSsidLen = data->length - 1;
643     A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
644
645     if (ar6000_connect_to_ap(ar)!= A_OK) {
646         up(&ar->arSem);
647         return -EIO;
648     }else{
649       up(&ar->arSem);
650     }
651     return 0;
652 }
653
654 /* SIOCGIWESSID */
655 static int
656 ar6000_ioctl_giwessid(struct net_device *dev,
657                      struct iw_request_info *info,
658                      struct iw_point *data, char *essid)
659 {
660     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
661
662     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
663         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
664         return -EOPNOTSUPP;
665     }
666
667     if (ar->arWlanState == WLAN_DISABLED) {
668         return -EIO;
669     }
670
671     if (!ar->arSsidLen) {
672         return -EINVAL;
673     }
674
675     data->flags = 1;
676     data->length = ar->arSsidLen;
677     A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
678
679     return 0;
680 }
681
682
683 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
684 {
685     u8 index;
686     u8 keyUsage;
687
688     for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
689         if (ar->arWepKeyList[index].arKeyLen) {
690             keyUsage = GROUP_USAGE;
691             if (index == ar->arDefTxKeyIndex) {
692                 keyUsage |= TX_USAGE;
693             }
694             wmi_addKey_cmd(ar->arWmi,
695                            index,
696                            WEP_CRYPT,
697                            keyUsage,
698                            ar->arWepKeyList[index].arKeyLen,
699                            NULL,
700                            ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
701                            NO_SYNC_WMIFLAG);
702         }
703     }
704 }
705
706 /*
707  * SIOCSIWRATE
708  */
709 int
710 ar6000_ioctl_siwrate(struct net_device *dev,
711             struct iw_request_info *info,
712             struct iw_param *rrq, char *extra)
713 {
714     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
715     u32 kbps;
716     s8 rate_idx;
717
718     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
719         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
720         return -EOPNOTSUPP;
721     }
722
723     if (rrq->fixed) {
724         kbps = rrq->value / 1000;           /* rrq->value is in bps */
725     } else {
726         kbps = -1;                          /* -1 indicates auto rate */
727     }
728     if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != A_OK)
729     {
730         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
731         return -EINVAL;
732     }
733     ar->arBitRate = kbps;
734     if(ar->arWmiReady == true)
735     {
736         if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) {
737             return -EINVAL;
738         }
739     }
740     return 0;
741 }
742
743 /*
744  * SIOCGIWRATE
745  */
746 int
747 ar6000_ioctl_giwrate(struct net_device *dev,
748             struct iw_request_info *info,
749             struct iw_param *rrq, char *extra)
750 {
751     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
752     int ret = 0;
753
754     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
755         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
756         return -EOPNOTSUPP;
757     }
758
759     if (ar->bIsDestroyProgress) {
760         return -EBUSY;
761     }
762
763     if (ar->arWlanState == WLAN_DISABLED) {
764         return -EIO;
765     }
766
767     if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == false) {
768         rrq->value = 1000 * 1000;       
769         return 0;
770     }
771
772     if (down_interruptible(&ar->arSem)) {
773         return -ERESTARTSYS;
774     }
775
776     if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
777         up(&ar->arSem);
778         return -EBUSY;
779     }
780
781     ar->arBitRate = 0xFFFF;
782     if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
783         up(&ar->arSem);
784         return -EIO;
785     }
786     wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
787     if (signal_pending(current)) {
788         ret = -EINTR;
789     }
790     /* If the interface is down or wmi is not ready or the target is not
791        connected - return the value stored in the device structure */
792     if (!ret) {
793         if (ar->arBitRate == -1) {
794             rrq->fixed = true;
795             rrq->value = 0;
796         } else {
797             rrq->value = ar->arBitRate * 1000;
798         }
799     }
800
801     up(&ar->arSem);
802
803     return ret;
804 }
805
806 /*
807  * SIOCSIWTXPOW
808  */
809 static int
810 ar6000_ioctl_siwtxpow(struct net_device *dev,
811              struct iw_request_info *info,
812              struct iw_param *rrq, char *extra)
813 {
814     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
815     u8 dbM;
816
817     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
818         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
819         return -EOPNOTSUPP;
820     }
821
822     if (ar->arWlanState == WLAN_DISABLED) {
823         return -EIO;
824     }
825
826     if (rrq->disabled) {
827         return -EOPNOTSUPP;
828     }
829
830     if (rrq->fixed) {
831         if (rrq->flags != IW_TXPOW_DBM) {
832             return -EOPNOTSUPP;
833         }
834         ar->arTxPwr= dbM = rrq->value;
835         ar->arTxPwrSet = true;
836     } else {
837         ar->arTxPwr = dbM = 0;
838         ar->arTxPwrSet = false;
839     }
840     if(ar->arWmiReady == true)
841     {
842         AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
843         wmi_set_txPwr_cmd(ar->arWmi, dbM);
844     }
845     return 0;
846 }
847
848 /*
849  * SIOCGIWTXPOW
850  */
851 int
852 ar6000_ioctl_giwtxpow(struct net_device *dev,
853             struct iw_request_info *info,
854             struct iw_param *rrq, char *extra)
855 {
856     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
857     int ret = 0;
858
859     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
860         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
861         return -EOPNOTSUPP;
862     }
863
864     if (ar->bIsDestroyProgress) {
865         return -EBUSY;
866     }
867
868     if (ar->arWlanState == WLAN_DISABLED) {
869         return -EIO;
870     }
871
872     if (down_interruptible(&ar->arSem)) {
873         return -ERESTARTSYS;
874     }
875
876     if (ar->bIsDestroyProgress) {
877         up(&ar->arSem);
878         return -EBUSY;
879     }
880
881     if((ar->arWmiReady == true) && (ar->arConnected == true))
882     {
883         ar->arTxPwr = 0;
884
885         if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
886             up(&ar->arSem);
887             return -EIO;
888         }
889
890         wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
891
892         if (signal_pending(current)) {
893             ret = -EINTR;
894          }
895     }
896    /* If the interace is down or wmi is not ready or target is not connected
897       then return value stored in the device structure */
898
899     if (!ret) {
900          if (ar->arTxPwrSet == true) {
901             rrq->fixed = true;
902         }
903         rrq->value = ar->arTxPwr;
904         rrq->flags = IW_TXPOW_DBM;
905         //
906         // IWLIST need this flag to get TxPower
907         //
908         rrq->disabled = 0;
909     }
910
911     up(&ar->arSem);
912
913     return ret;
914 }
915
916 /*
917  * SIOCSIWRETRY
918  * since iwconfig only provides us with one max retry value, we use it
919  * to apply to data frames of the BE traffic class.
920  */
921 static int
922 ar6000_ioctl_siwretry(struct net_device *dev,
923              struct iw_request_info *info,
924              struct iw_param *rrq, char *extra)
925 {
926     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
927
928     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
929         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
930         return -EOPNOTSUPP;
931     }
932
933     if (ar->arWlanState == WLAN_DISABLED) {
934         return -EIO;
935     }
936
937     if (rrq->disabled) {
938         return -EOPNOTSUPP;
939     }
940
941     if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
942         return -EOPNOTSUPP;
943     }
944
945     if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
946             return - EINVAL;
947     }
948     if(ar->arWmiReady == true)
949     {
950         if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
951                                      rrq->value, 0) != A_OK){
952             return -EINVAL;
953         }
954     }
955     ar->arMaxRetries = rrq->value;
956     return 0;
957 }
958
959 /*
960  * SIOCGIWRETRY
961  */
962 static int
963 ar6000_ioctl_giwretry(struct net_device *dev,
964              struct iw_request_info *info,
965              struct iw_param *rrq, char *extra)
966 {
967     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
968
969     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
970         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
971         return -EOPNOTSUPP;
972     }
973
974     if (ar->arWlanState == WLAN_DISABLED) {
975         return -EIO;
976     }
977
978     rrq->disabled = 0;
979     switch (rrq->flags & IW_RETRY_TYPE) {
980     case IW_RETRY_LIFETIME:
981         return -EOPNOTSUPP;
982         break;
983     case IW_RETRY_LIMIT:
984         rrq->flags = IW_RETRY_LIMIT;
985         switch (rrq->flags & IW_RETRY_MODIFIER) {
986         case IW_RETRY_MIN:
987             rrq->flags |= IW_RETRY_MIN;
988             rrq->value = WMI_MIN_RETRIES;
989             break;
990         case IW_RETRY_MAX:
991             rrq->flags |= IW_RETRY_MAX;
992             rrq->value = ar->arMaxRetries;
993             break;
994         }
995         break;
996     }
997     return 0;
998 }
999
1000 /*
1001  * SIOCSIWENCODE
1002  */
1003 static int
1004 ar6000_ioctl_siwencode(struct net_device *dev,
1005               struct iw_request_info *info,
1006               struct iw_point *erq, char *keybuf)
1007 {
1008     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1009     int index;
1010     s32 auth = 0;
1011
1012     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1013         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1014         return -EOPNOTSUPP;
1015     }
1016
1017     if(ar->arNextMode != AP_NETWORK) {
1018     /*
1019      *  Static WEP Keys should be configured before setting the SSID
1020      */
1021     if (ar->arSsid[0] && erq->length) {
1022         return -EIO;
1023     }
1024     }
1025
1026     if (ar->arWlanState == WLAN_DISABLED) {
1027         return -EIO;
1028     }
1029
1030     index = erq->flags & IW_ENCODE_INDEX;
1031
1032     if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1033                   ((index - 1) > WMI_MAX_KEY_INDEX)))
1034     {
1035         return -EIO;
1036     }
1037
1038     if (erq->flags & IW_ENCODE_DISABLED) {
1039         /*
1040          * Encryption disabled
1041          */
1042         if (index) {
1043             /*
1044              * If key index was specified then clear the specified key
1045              */
1046             index--;
1047             A_MEMZERO(ar->arWepKeyList[index].arKey,
1048                       sizeof(ar->arWepKeyList[index].arKey));
1049             ar->arWepKeyList[index].arKeyLen = 0;
1050         }
1051         ar->arDot11AuthMode       = OPEN_AUTH;
1052         ar->arPairwiseCrypto      = NONE_CRYPT;
1053         ar->arGroupCrypto         = NONE_CRYPT;
1054         ar->arAuthMode            = NONE_AUTH;
1055     } else {
1056         /*
1057          * Enabling WEP encryption
1058          */
1059         if (index) {
1060             index--;                /* keyindex is off base 1 in iwconfig */
1061         }
1062
1063         if (erq->flags & IW_ENCODE_OPEN) {
1064             auth |= OPEN_AUTH;
1065             ar->arDefTxKeyIndex = index;
1066         }
1067         if (erq->flags & IW_ENCODE_RESTRICTED) {
1068             auth |= SHARED_AUTH;
1069         }
1070
1071         if (!auth) {
1072             auth = OPEN_AUTH;
1073         }
1074
1075         if (erq->length) {
1076             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
1077                 return -EIO;
1078             }
1079
1080             A_MEMZERO(ar->arWepKeyList[index].arKey,
1081                       sizeof(ar->arWepKeyList[index].arKey));
1082             A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
1083             ar->arWepKeyList[index].arKeyLen = erq->length;
1084             ar->arDot11AuthMode       = auth;
1085         } else {
1086             if (ar->arWepKeyList[index].arKeyLen == 0) {
1087                 return -EIO;
1088             }
1089             ar->arDefTxKeyIndex = index;
1090
1091             if(ar->arSsidLen && ar->arWepKeyList[index].arKeyLen) {
1092                 wmi_addKey_cmd(ar->arWmi,
1093                                index,
1094                                WEP_CRYPT,
1095                                GROUP_USAGE | TX_USAGE,
1096                                ar->arWepKeyList[index].arKeyLen,
1097                                NULL,
1098                                ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
1099                                NO_SYNC_WMIFLAG);
1100             }
1101         }
1102
1103         ar->arPairwiseCrypto      = WEP_CRYPT;
1104         ar->arGroupCrypto         = WEP_CRYPT;
1105         ar->arAuthMode            = NONE_AUTH;
1106     }
1107
1108     if(ar->arNextMode != AP_NETWORK) {
1109     /*
1110      * profile has changed.  Erase ssid to signal change
1111      */
1112         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1113         ar->arSsidLen = 0;
1114     }
1115     ar->ap_profile_flag = 1; /* There is a change in profile */
1116     return 0;
1117 }
1118
1119 static int
1120 ar6000_ioctl_giwencode(struct net_device *dev,
1121               struct iw_request_info *info,
1122               struct iw_point *erq, char *key)
1123 {
1124     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1125     u8 keyIndex;
1126     struct ar_wep_key *wk;
1127
1128     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1129         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1130         return -EOPNOTSUPP;
1131     }
1132
1133     if (ar->arWlanState == WLAN_DISABLED) {
1134         return -EIO;
1135     }
1136
1137     if (ar->arPairwiseCrypto == NONE_CRYPT) {
1138         erq->length = 0;
1139         erq->flags = IW_ENCODE_DISABLED;
1140     } else {
1141         if (ar->arPairwiseCrypto == WEP_CRYPT) {
1142             /* get the keyIndex */
1143             keyIndex = erq->flags & IW_ENCODE_INDEX;
1144             if (0 == keyIndex) {
1145                 keyIndex = ar->arDefTxKeyIndex;
1146             } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
1147                        (keyIndex - 1 > WMI_MAX_KEY_INDEX))
1148             {
1149                 keyIndex = WMI_MIN_KEY_INDEX;
1150             } else {
1151                 keyIndex--;
1152             }
1153             erq->flags = keyIndex + 1;
1154             erq->flags &= ~IW_ENCODE_DISABLED;
1155             wk = &ar->arWepKeyList[keyIndex];
1156             if (erq->length > wk->arKeyLen) {
1157                 erq->length = wk->arKeyLen;
1158             }
1159             if (wk->arKeyLen) {
1160                 A_MEMCPY(key, wk->arKey, erq->length);
1161             }
1162         } else {
1163             erq->flags &= ~IW_ENCODE_DISABLED;
1164             if (ar->user_saved_keys.keyOk) {
1165                 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen;
1166                 if (erq->length) {
1167                     A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
1168                 }
1169             } else {
1170                 erq->length = 1;    // not really printing any key but let iwconfig know enc is on
1171             }
1172         }
1173
1174         if (ar->arDot11AuthMode & OPEN_AUTH) {
1175             erq->flags |= IW_ENCODE_OPEN;
1176         }
1177         if (ar->arDot11AuthMode & SHARED_AUTH) {
1178             erq->flags |= IW_ENCODE_RESTRICTED;
1179         }
1180     }
1181
1182     return 0;
1183 }
1184
1185 #if WIRELESS_EXT >= 18
1186 /*
1187  * SIOCSIWGENIE
1188  */
1189 static int
1190 ar6000_ioctl_siwgenie(struct net_device *dev,
1191               struct iw_request_info *info,
1192               struct iw_point *erq, char *extra)
1193 {
1194     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1195
1196 #ifdef WAPI_ENABLE
1197     u8 *ie = erq->pointer;
1198     u8 ie_type = ie[0];
1199     u16 ie_length = erq->length;
1200     u8 wapi_ie[128];
1201 #endif
1202
1203     if (ar->arWmiReady == false) {
1204         return -EIO;
1205     }
1206 #ifdef WAPI_ENABLE
1207     if (ie_type == IEEE80211_ELEMID_WAPI) {
1208         if (ie_length > 0) {
1209             if (copy_from_user(wapi_ie, ie, ie_length)) {
1210                 return -EIO;
1211             }
1212         }
1213         wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1214     } else if (ie_length == 0) {
1215         wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1216     }
1217 #endif
1218     return 0;
1219 }
1220
1221
1222 /*
1223  * SIOCGIWGENIE
1224  */
1225 static int
1226 ar6000_ioctl_giwgenie(struct net_device *dev,
1227               struct iw_request_info *info,
1228               struct iw_point *erq, char *extra)
1229 {
1230     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1231
1232     if (ar->arWmiReady == false) {
1233         return -EIO;
1234     }
1235     erq->length = 0;
1236     erq->flags = 0;
1237
1238     return 0;
1239 }
1240
1241 /*
1242  * SIOCSIWAUTH
1243  */
1244 static int
1245 ar6000_ioctl_siwauth(struct net_device *dev,
1246               struct iw_request_info *info,
1247               struct iw_param *data, char *extra)
1248 {
1249     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1250
1251     bool profChanged;
1252     u16 param;
1253     s32 ret;
1254     s32 value;
1255
1256     if (ar->arWmiReady == false) {
1257         return -EIO;
1258     }
1259
1260     if (ar->arWlanState == WLAN_DISABLED) {
1261         return -EIO;
1262     }
1263
1264     param = data->flags & IW_AUTH_INDEX;
1265     value = data->value;
1266     profChanged = true;
1267     ret = 0;
1268
1269     switch (param) {
1270         case IW_AUTH_WPA_VERSION:
1271             if (value & IW_AUTH_WPA_VERSION_DISABLED) {
1272                 ar->arAuthMode = NONE_AUTH;
1273             } else if (value & IW_AUTH_WPA_VERSION_WPA) {
1274                     ar->arAuthMode = WPA_AUTH;
1275             } else if (value & IW_AUTH_WPA_VERSION_WPA2) {
1276                     ar->arAuthMode = WPA2_AUTH;
1277             } else {
1278                 ret = -1;
1279                 profChanged    = false;
1280             }
1281             break;
1282         case IW_AUTH_CIPHER_PAIRWISE:
1283             if (value & IW_AUTH_CIPHER_NONE) {
1284                 ar->arPairwiseCrypto = NONE_CRYPT;
1285                 ar->arPairwiseCryptoLen = 0;
1286             } else if (value & IW_AUTH_CIPHER_WEP40) {
1287                 ar->arPairwiseCrypto = WEP_CRYPT;
1288                 ar->arPairwiseCryptoLen = 5;
1289             } else if (value & IW_AUTH_CIPHER_TKIP) {
1290                 ar->arPairwiseCrypto = TKIP_CRYPT;
1291                 ar->arPairwiseCryptoLen = 0;
1292             } else if (value & IW_AUTH_CIPHER_CCMP) {
1293                 ar->arPairwiseCrypto = AES_CRYPT;
1294                 ar->arPairwiseCryptoLen = 0;
1295             } else if (value & IW_AUTH_CIPHER_WEP104) {
1296                 ar->arPairwiseCrypto = WEP_CRYPT;
1297                 ar->arPairwiseCryptoLen = 13;
1298             } else {
1299                 ret = -1;
1300                 profChanged    = false;
1301             }
1302             break;
1303         case IW_AUTH_CIPHER_GROUP:
1304             if (value & IW_AUTH_CIPHER_NONE) {
1305                 ar->arGroupCrypto = NONE_CRYPT;
1306                 ar->arGroupCryptoLen = 0;
1307             } else if (value & IW_AUTH_CIPHER_WEP40) {
1308                 ar->arGroupCrypto = WEP_CRYPT;
1309                 ar->arGroupCryptoLen = 5;
1310             } else if (value & IW_AUTH_CIPHER_TKIP) {
1311                 ar->arGroupCrypto = TKIP_CRYPT;
1312                 ar->arGroupCryptoLen = 0;
1313             } else if (value & IW_AUTH_CIPHER_CCMP) {
1314                 ar->arGroupCrypto = AES_CRYPT;
1315                 ar->arGroupCryptoLen = 0;
1316             } else if (value & IW_AUTH_CIPHER_WEP104) {
1317                 ar->arGroupCrypto = WEP_CRYPT;
1318                 ar->arGroupCryptoLen = 13;
1319             } else {
1320                 ret = -1;
1321                 profChanged    = false;
1322             }
1323             break;
1324         case IW_AUTH_KEY_MGMT:
1325             if (value & IW_AUTH_KEY_MGMT_PSK) {
1326                 if (WPA_AUTH == ar->arAuthMode) {
1327                     ar->arAuthMode = WPA_PSK_AUTH;
1328                 } else if (WPA2_AUTH == ar->arAuthMode) {
1329                     ar->arAuthMode = WPA2_PSK_AUTH;
1330                 } else {
1331                     ret = -1;
1332                 }
1333             } else if (!(value & IW_AUTH_KEY_MGMT_802_1X)) {
1334                 ar->arAuthMode = NONE_AUTH;
1335             }
1336             break;
1337         case IW_AUTH_TKIP_COUNTERMEASURES:
1338             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1339             profChanged    = false;
1340             break;
1341         case IW_AUTH_DROP_UNENCRYPTED:
1342             profChanged    = false;
1343             break;
1344         case IW_AUTH_80211_AUTH_ALG:
1345             ar->arDot11AuthMode = 0;
1346             if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
1347                 ar->arDot11AuthMode  |= OPEN_AUTH;
1348             }
1349             if (value & IW_AUTH_ALG_SHARED_KEY) {
1350                 ar->arDot11AuthMode  |= SHARED_AUTH;
1351             }
1352             if (value & IW_AUTH_ALG_LEAP) {
1353                 ar->arDot11AuthMode   = LEAP_AUTH;
1354             }
1355             if(ar->arDot11AuthMode == 0) {
1356                 ret = -1;
1357                 profChanged    = false;
1358             }
1359             break;
1360         case IW_AUTH_WPA_ENABLED:
1361             if (!value) {
1362                 ar->arAuthMode = NONE_AUTH;
1363                 /* when the supplicant is stopped, it calls this
1364                  * handler with value=0. The followings need to be
1365                  * reset if the STA were to connect again
1366                  * without security
1367                  */
1368                 ar->arDot11AuthMode = OPEN_AUTH;
1369                 ar->arPairwiseCrypto = NONE_CRYPT;
1370                 ar->arPairwiseCryptoLen = 0;
1371                 ar->arGroupCrypto = NONE_CRYPT;
1372                 ar->arGroupCryptoLen = 0;
1373             }
1374             break;
1375         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1376             profChanged    = false;
1377             break;
1378         case IW_AUTH_ROAMING_CONTROL:
1379             profChanged    = false;
1380             break;
1381         case IW_AUTH_PRIVACY_INVOKED:
1382             if (!value) {
1383                 ar->arPairwiseCrypto = NONE_CRYPT;
1384                 ar->arPairwiseCryptoLen = 0;
1385                 ar->arGroupCrypto = NONE_CRYPT;
1386                 ar->arGroupCryptoLen = 0;
1387             }
1388             break;
1389 #ifdef WAPI_ENABLE
1390         case IW_AUTH_WAPI_ENABLED:
1391             ar->arWapiEnable = value;
1392             break;
1393 #endif
1394         default:
1395            ret = -1;
1396            profChanged    = false;
1397            break;
1398     }
1399
1400     if (profChanged == true) {
1401         /*
1402          * profile has changed.  Erase ssid to signal change
1403          */
1404         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1405         ar->arSsidLen = 0;
1406     }
1407
1408     return ret;
1409 }
1410
1411
1412 /*
1413  * SIOCGIWAUTH
1414  */
1415 static int
1416 ar6000_ioctl_giwauth(struct net_device *dev,
1417               struct iw_request_info *info,
1418               struct iw_param *data, char *extra)
1419 {
1420     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1421     u16 param;
1422     s32 ret;
1423
1424     if (ar->arWmiReady == false) {
1425         return -EIO;
1426     }
1427
1428     if (ar->arWlanState == WLAN_DISABLED) {
1429         return -EIO;
1430     }
1431
1432     param = data->flags & IW_AUTH_INDEX;
1433     ret = 0;
1434     data->value = 0;
1435
1436
1437     switch (param) {
1438         case IW_AUTH_WPA_VERSION:
1439             if (ar->arAuthMode == NONE_AUTH) {
1440                 data->value |= IW_AUTH_WPA_VERSION_DISABLED;
1441             } else if (ar->arAuthMode == WPA_AUTH) {
1442                 data->value |= IW_AUTH_WPA_VERSION_WPA;
1443             } else if (ar->arAuthMode == WPA2_AUTH) {
1444                 data->value |= IW_AUTH_WPA_VERSION_WPA2;
1445             } else {
1446                 ret = -1;
1447             }
1448             break;
1449         case IW_AUTH_CIPHER_PAIRWISE:
1450             if (ar->arPairwiseCrypto == NONE_CRYPT) {
1451                 data->value |= IW_AUTH_CIPHER_NONE;
1452             } else if (ar->arPairwiseCrypto == WEP_CRYPT) {
1453                 if (ar->arPairwiseCryptoLen == 13) {
1454                     data->value |= IW_AUTH_CIPHER_WEP104;
1455                 } else {
1456                     data->value |= IW_AUTH_CIPHER_WEP40;
1457                 }
1458             } else if (ar->arPairwiseCrypto == TKIP_CRYPT) {
1459                 data->value |= IW_AUTH_CIPHER_TKIP;
1460             } else if (ar->arPairwiseCrypto == AES_CRYPT) {
1461                 data->value |= IW_AUTH_CIPHER_CCMP;
1462             } else {
1463                 ret = -1;
1464             }
1465             break;
1466         case IW_AUTH_CIPHER_GROUP:
1467             if (ar->arGroupCrypto == NONE_CRYPT) {
1468                     data->value |= IW_AUTH_CIPHER_NONE;
1469             } else if (ar->arGroupCrypto == WEP_CRYPT) {
1470                 if (ar->arGroupCryptoLen == 13) {
1471                     data->value |= IW_AUTH_CIPHER_WEP104;
1472                 } else {
1473                     data->value |= IW_AUTH_CIPHER_WEP40;
1474                 }
1475             } else if (ar->arGroupCrypto == TKIP_CRYPT) {
1476                 data->value |= IW_AUTH_CIPHER_TKIP;
1477             } else if (ar->arGroupCrypto == AES_CRYPT) {
1478                 data->value |= IW_AUTH_CIPHER_CCMP;
1479             } else {
1480                 ret = -1;
1481             }
1482             break;
1483         case IW_AUTH_KEY_MGMT:
1484             if ((ar->arAuthMode == WPA_PSK_AUTH) ||
1485                 (ar->arAuthMode == WPA2_PSK_AUTH)) {
1486                 data->value |= IW_AUTH_KEY_MGMT_PSK;
1487             } else if ((ar->arAuthMode == WPA_AUTH) ||
1488                        (ar->arAuthMode == WPA2_AUTH)) {
1489                 data->value |= IW_AUTH_KEY_MGMT_802_1X;
1490             }
1491             break;
1492         case IW_AUTH_TKIP_COUNTERMEASURES:
1493             // TODO. Save countermeassure enable/disable
1494             data->value = 0;
1495             break;
1496         case IW_AUTH_DROP_UNENCRYPTED:
1497             break;
1498         case IW_AUTH_80211_AUTH_ALG:
1499             if (ar->arDot11AuthMode == OPEN_AUTH) {
1500                 data->value |= IW_AUTH_ALG_OPEN_SYSTEM;
1501             } else if (ar->arDot11AuthMode == SHARED_AUTH) {
1502                 data->value |= IW_AUTH_ALG_SHARED_KEY;
1503             } else if (ar->arDot11AuthMode == LEAP_AUTH) {
1504                 data->value |= IW_AUTH_ALG_LEAP;
1505             } else {
1506                 ret = -1;
1507             }
1508             break;
1509         case IW_AUTH_WPA_ENABLED:
1510             if (ar->arAuthMode == NONE_AUTH) {
1511                 data->value = 0;
1512             } else {
1513                 data->value = 1;
1514             }
1515             break;
1516         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1517             break;
1518         case IW_AUTH_ROAMING_CONTROL:
1519             break;
1520         case IW_AUTH_PRIVACY_INVOKED:
1521             if (ar->arPairwiseCrypto == NONE_CRYPT) {
1522                 data->value = 0;
1523             } else {
1524                 data->value = 1;
1525             }
1526             break;
1527 #ifdef WAPI_ENABLE
1528         case IW_AUTH_WAPI_ENABLED:
1529             data->value = ar->arWapiEnable;
1530             break;
1531 #endif
1532         default:
1533            ret = -1;
1534            break;
1535     }
1536
1537     return 0;
1538 }
1539
1540 /*
1541  * SIOCSIWPMKSA
1542  */
1543 static int
1544 ar6000_ioctl_siwpmksa(struct net_device *dev,
1545               struct iw_request_info *info,
1546               struct iw_point *data, char *extra)
1547 {
1548     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1549     s32 ret;
1550     int status;
1551     struct iw_pmksa *pmksa;
1552
1553     pmksa = (struct iw_pmksa *)extra;
1554
1555     if (ar->arWmiReady == false) {
1556         return -EIO;
1557     }
1558
1559     ret = 0;
1560     status = A_OK;
1561
1562     switch (pmksa->cmd) {
1563         case IW_PMKSA_ADD:
1564             status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, true);
1565             break;
1566         case IW_PMKSA_REMOVE:
1567             status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, false);
1568             break;
1569         case IW_PMKSA_FLUSH:
1570             if (ar->arConnected == true) {
1571                 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
1572             }
1573             break;
1574         default:
1575             ret=-1;
1576             break;
1577     }
1578     if (status) {
1579         ret = -1;
1580     }
1581
1582     return ret;
1583 }
1584
1585 #ifdef WAPI_ENABLE
1586
1587 #define PN_INIT 0x5c365c36
1588
1589 static int ar6000_set_wapi_key(struct net_device *dev,
1590               struct iw_request_info *info,
1591               struct iw_point *erq, char *extra)
1592 {
1593     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1594     struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1595     KEY_USAGE   keyUsage = 0;
1596     s32 keyLen;
1597     u8 *keyData;
1598     s32 index;
1599     u32 *PN;
1600     s32 i;
1601     int    status;
1602     u8 wapiKeyRsc[16];
1603     CRYPTO_TYPE keyType = WAPI_CRYPT;
1604     const u8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1605
1606     index = erq->flags & IW_ENCODE_INDEX;
1607     if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1608                 ((index - 1) > WMI_MAX_KEY_INDEX))) {
1609         return -EIO;
1610     }
1611
1612     index--;
1613     if (index < 0 || index > 4) {
1614         return -EIO;
1615     }
1616     keyData = (u8 *)(ext + 1);
1617     keyLen = erq->length - sizeof(struct iw_encode_ext);
1618     A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
1619
1620     if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
1621         keyUsage |= GROUP_USAGE;
1622         PN = (u32 *)wapiKeyRsc;
1623         for (i = 0; i < 4; i++) {
1624             PN[i] = PN_INIT;
1625         }
1626     } else {
1627         keyUsage |= PAIRWISE_USAGE;
1628     }
1629     status = wmi_addKey_cmd(ar->arWmi,
1630                             index,
1631                             keyType,
1632                             keyUsage,
1633                             keyLen,
1634                             wapiKeyRsc,
1635                             keyData,
1636                             KEY_OP_INIT_WAPIPN,
1637                             NULL,
1638                             SYNC_BEFORE_WMIFLAG);
1639     if (A_OK != status) {
1640         return -EIO;
1641     }
1642     return 0;
1643 }
1644
1645 #endif
1646
1647 /*
1648  * SIOCSIWENCODEEXT
1649  */
1650 static int
1651 ar6000_ioctl_siwencodeext(struct net_device *dev,
1652               struct iw_request_info *info,
1653               struct iw_point *erq, char *extra)
1654 {
1655     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1656     s32 index;
1657     struct iw_encode_ext *ext;
1658     KEY_USAGE keyUsage;
1659     s32 keyLen;
1660     u8 *keyData;
1661     u8 keyRsc[8];
1662     int status;
1663     CRYPTO_TYPE keyType;
1664 #ifdef USER_KEYS
1665     struct ieee80211req_key ik;
1666 #endif /* USER_KEYS */
1667
1668     if (ar->arWlanState == WLAN_DISABLED) {
1669         return -EIO;
1670     }
1671
1672 #ifdef USER_KEYS
1673     ar->user_saved_keys.keyOk = false;
1674 #endif /* USER_KEYS */
1675
1676     index = erq->flags & IW_ENCODE_INDEX;
1677
1678     if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1679                   ((index - 1) > WMI_MAX_KEY_INDEX)))
1680     {
1681         return -EIO;
1682     }
1683
1684     ext = (struct iw_encode_ext *)extra;
1685     if (erq->flags & IW_ENCODE_DISABLED) {
1686         /*
1687          * Encryption disabled
1688          */
1689         if (index) {
1690             /*
1691              * If key index was specified then clear the specified key
1692              */
1693             index--;
1694             A_MEMZERO(ar->arWepKeyList[index].arKey,
1695                       sizeof(ar->arWepKeyList[index].arKey));
1696             ar->arWepKeyList[index].arKeyLen = 0;
1697         }
1698     } else {
1699         /*
1700          * Enabling WEP encryption
1701          */
1702         if (index) {
1703             index--;                /* keyindex is off base 1 in iwconfig */
1704         }
1705
1706         keyUsage = 0;
1707         keyLen = erq->length - sizeof(struct iw_encode_ext);
1708
1709         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1710             keyUsage = TX_USAGE;
1711             ar->arDefTxKeyIndex = index;
1712             // Just setting the key index
1713             if (keyLen == 0) {
1714                 return 0;
1715             }
1716         }
1717
1718         if (keyLen <= 0) {
1719             return -EIO;
1720         }
1721
1722         /* key follows iw_encode_ext */
1723         keyData = (u8 *)(ext + 1);
1724
1725         switch (ext->alg) {
1726             case IW_ENCODE_ALG_WEP:
1727                 keyType = WEP_CRYPT;
1728 #ifdef USER_KEYS
1729                 ik.ik_type = IEEE80211_CIPHER_WEP;
1730 #endif /* USER_KEYS */
1731                 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(keyLen)) {
1732                     return -EIO;
1733                 }
1734
1735                 /* Check whether it is static wep. */
1736                 if (!ar->arConnected) {
1737                     A_MEMZERO(ar->arWepKeyList[index].arKey,
1738                           sizeof(ar->arWepKeyList[index].arKey));
1739                     A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen);
1740                     ar->arWepKeyList[index].arKeyLen = keyLen;
1741
1742                     return 0;
1743                 }
1744                 break;
1745             case IW_ENCODE_ALG_TKIP:
1746                 keyType = TKIP_CRYPT;
1747 #ifdef USER_KEYS
1748                 ik.ik_type = IEEE80211_CIPHER_TKIP;
1749 #endif /* USER_KEYS */
1750                 break;
1751             case IW_ENCODE_ALG_CCMP:
1752                 keyType = AES_CRYPT;
1753 #ifdef USER_KEYS
1754                 ik.ik_type = IEEE80211_CIPHER_AES_CCM;
1755 #endif /* USER_KEYS */
1756                 break;
1757 #ifdef WAPI_ENABLE
1758             case IW_ENCODE_ALG_SM4:
1759                 if (ar->arWapiEnable) {
1760                     return ar6000_set_wapi_key(dev, info, erq, extra);
1761                 } else {
1762                     return -EIO;
1763                 }
1764 #endif
1765             case IW_ENCODE_ALG_PMK:
1766                 ar->arConnectCtrlFlags |= CONNECT_DO_WPA_OFFLOAD;
1767                 return wmi_set_pmk_cmd(ar->arWmi, keyData);
1768             default:
1769                 return -EIO;
1770         }
1771
1772
1773         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1774             keyUsage |= GROUP_USAGE;
1775         } else {
1776             keyUsage |= PAIRWISE_USAGE;
1777         }
1778
1779         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1780             A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc));
1781         } else {
1782             A_MEMZERO(keyRsc, sizeof(keyRsc));
1783         }
1784
1785         if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
1786             (GROUP_USAGE & keyUsage))
1787         {
1788             A_UNTIMEOUT(&ar->disconnect_timer);
1789         }
1790
1791          status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage,
1792                             keyLen, keyRsc,
1793                             keyData, KEY_OP_INIT_VAL,
1794                             (u8 *)ext->addr.sa_data,
1795                             SYNC_BOTH_WMIFLAG);
1796          if (status) {
1797             return -EIO;
1798          }
1799
1800 #ifdef USER_KEYS
1801         ik.ik_keyix = index;
1802         ik.ik_keylen = keyLen;
1803         memcpy(ik.ik_keydata, keyData, keyLen);
1804         memcpy(&ik.ik_keyrsc, keyRsc, sizeof(keyRsc));
1805         memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
1806         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1807             memcpy(&ar->user_saved_keys.bcast_ik, &ik,
1808                        sizeof(struct ieee80211req_key));
1809         } else {
1810             memcpy(&ar->user_saved_keys.ucast_ik, &ik,
1811                       sizeof(struct ieee80211req_key));
1812         }
1813         ar->user_saved_keys.keyOk = true;
1814 #endif /* USER_KEYS */
1815     }
1816
1817
1818     return 0;
1819 }
1820
1821 /*
1822  * SIOCGIWENCODEEXT
1823  */
1824 static int
1825 ar6000_ioctl_giwencodeext(struct net_device *dev,
1826               struct iw_request_info *info,
1827               struct iw_point *erq, char *extra)
1828 {
1829     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1830
1831     if (ar->arWlanState == WLAN_DISABLED) {
1832         return -EIO;
1833     }
1834
1835     if (ar->arPairwiseCrypto == NONE_CRYPT) {
1836         erq->length = 0;
1837         erq->flags = IW_ENCODE_DISABLED;
1838     } else {
1839         erq->length = 0;
1840     }
1841
1842     return 0;
1843 }
1844 #endif // WIRELESS_EXT >= 18
1845
1846 #if WIRELESS_EXT > 20
1847 static int ar6000_ioctl_siwpower(struct net_device *dev,
1848                  struct iw_request_info *info,
1849                  union iwreq_data *wrqu, char *extra)
1850 {
1851 #ifndef ATH6K_CONFIG_OTA_MODE
1852     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1853     WMI_POWER_MODE power_mode;
1854
1855     if (ar->arWmiReady == false) {
1856         return -EIO;
1857     }
1858
1859     if (ar->arWlanState == WLAN_DISABLED) {
1860         return -EIO;
1861     }
1862
1863     if (wrqu->power.disabled)
1864         power_mode = MAX_PERF_POWER;
1865     else
1866         power_mode = REC_POWER;
1867
1868     if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
1869         return -EIO;
1870 #endif
1871     return 0;
1872 }
1873
1874 static int ar6000_ioctl_giwpower(struct net_device *dev,
1875                  struct iw_request_info *info,
1876                  union iwreq_data *wrqu, char *extra)
1877 {
1878     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1879     WMI_POWER_MODE power_mode;
1880
1881     if (ar->arWmiReady == false) {
1882         return -EIO;
1883     }
1884
1885     if (ar->arWlanState == WLAN_DISABLED) {
1886         return -EIO;
1887     }
1888
1889     power_mode = wmi_get_power_mode_cmd(ar->arWmi);
1890
1891     if (power_mode == MAX_PERF_POWER)
1892         wrqu->power.disabled = 1;
1893     else
1894         wrqu->power.disabled = 0;
1895
1896     return 0;
1897 }
1898 #endif // WIRELESS_EXT > 20
1899
1900 /*
1901  * SIOCGIWNAME
1902  */
1903 int
1904 ar6000_ioctl_giwname(struct net_device *dev,
1905            struct iw_request_info *info,
1906            char *name, char *extra)
1907 {
1908     u8 capability;
1909     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1910
1911     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1912         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1913         return -EOPNOTSUPP;
1914     }
1915
1916     if (ar->arWlanState == WLAN_DISABLED) {
1917         return -EIO;
1918     }
1919
1920     capability = ar->arPhyCapability;
1921     if(ar->arNetworkType == INFRA_NETWORK && ar->arConnected) {
1922         bss_t *bss = wmi_find_node(ar->arWmi, ar->arBssid);
1923         if (bss) {
1924             capability = get_bss_phy_capability(bss);
1925             wmi_node_return(ar->arWmi, bss);
1926         }
1927     }
1928     switch (capability) {
1929     case (WMI_11A_CAPABILITY):
1930         strncpy(name, "AR6000 802.11a", IFNAMSIZ);
1931         break;
1932     case (WMI_11G_CAPABILITY):
1933         strncpy(name, "AR6000 802.11g", IFNAMSIZ);
1934         break;
1935     case (WMI_11AG_CAPABILITY):
1936         strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
1937         break;
1938     case (WMI_11NA_CAPABILITY):
1939         strncpy(name, "AR6000 802.11na", IFNAMSIZ);
1940         break;
1941     case (WMI_11NG_CAPABILITY):
1942         strncpy(name, "AR6000 802.11ng", IFNAMSIZ);
1943         break;
1944     case (WMI_11NAG_CAPABILITY):
1945         strncpy(name, "AR6000 802.11nag", IFNAMSIZ);
1946         break;
1947     default:
1948         strncpy(name, "AR6000 802.11b", IFNAMSIZ);
1949         break;
1950     }
1951
1952     return 0;
1953 }
1954
1955 /*
1956  * SIOCSIWFREQ
1957  */
1958 int
1959 ar6000_ioctl_siwfreq(struct net_device *dev,
1960             struct iw_request_info *info,
1961             struct iw_freq *freq, char *extra)
1962 {
1963     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1964
1965     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
1966         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1967         return -EOPNOTSUPP;
1968     }
1969
1970     if (ar->arWlanState == WLAN_DISABLED) {
1971         return -EIO;
1972     }
1973
1974     /*
1975      * We support limiting the channels via wmiconfig.
1976      *
1977      * We use this command to configure the channel hint for the connect cmd
1978      * so it is possible the target will end up connecting to a different
1979      * channel.
1980      */
1981     if (freq->e > 1) {
1982         return -EINVAL;
1983     } else if (freq->e == 1) {
1984         ar->arChannelHint = freq->m / 100000;
1985     } else {
1986         if(freq->m) {
1987             ar->arChannelHint = wlan_ieee2freq(freq->m);
1988         } else {
1989             /* Auto Channel Selection */
1990             ar->arChannelHint = 0;
1991         }
1992     }
1993
1994     ar->ap_profile_flag = 1; /* There is a change in profile */
1995
1996     A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
1997     return 0;
1998 }
1999
2000 /*
2001  * SIOCGIWFREQ
2002  */
2003 int
2004 ar6000_ioctl_giwfreq(struct net_device *dev,
2005                 struct iw_request_info *info,
2006                 struct iw_freq *freq, char *extra)
2007 {
2008     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2009
2010     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2011         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2012         return -EOPNOTSUPP;
2013     }
2014
2015     if (ar->arWlanState == WLAN_DISABLED) {
2016         return -EIO;
2017     }
2018
2019     if (ar->arNetworkType == AP_NETWORK) {
2020         if(ar->arChannelHint) {
2021             freq->m = ar->arChannelHint * 100000;
2022         } else if(ar->arACS) {
2023             freq->m = ar->arACS * 100000;
2024         } else {
2025             return -EINVAL;
2026         }
2027     } else {
2028         if (ar->arConnected != true) {
2029             return -EINVAL;
2030         } else {
2031             freq->m = ar->arBssChannel * 100000;
2032         }
2033     }
2034
2035     freq->e = 1;
2036
2037     return 0;
2038 }
2039
2040 /*
2041  * SIOCSIWMODE
2042  */
2043 int
2044 ar6000_ioctl_siwmode(struct net_device *dev,
2045             struct iw_request_info *info,
2046             __u32 *mode, char *extra)
2047 {
2048     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2049
2050     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2051         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2052         return -EOPNOTSUPP;
2053     }
2054
2055     if (ar->arWlanState == WLAN_DISABLED) {
2056         return -EIO;
2057     }
2058
2059     /*
2060      * clear SSID during mode switch in connected state
2061      */
2062     if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == true) ){
2063         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2064         ar->arSsidLen = 0;
2065     }
2066
2067     switch (*mode) {
2068     case IW_MODE_INFRA:
2069         ar->arNextMode = INFRA_NETWORK;
2070         break;
2071     case IW_MODE_ADHOC:
2072         ar->arNextMode = ADHOC_NETWORK;
2073         break;
2074     case IW_MODE_MASTER:
2075         ar->arNextMode = AP_NETWORK;
2076         break;
2077     default:
2078         return -EINVAL;
2079     }
2080
2081     /* clear all shared parameters between AP and STA|IBSS modes when we
2082      * switch between them. Switch between STA & IBSS modes does'nt clear
2083      * the shared profile. This is as per the original design for switching
2084      * between STA & IBSS.
2085      */
2086     if (ar->arNetworkType == AP_NETWORK || ar->arNextMode == AP_NETWORK) {
2087         ar->arDot11AuthMode      = OPEN_AUTH;
2088         ar->arAuthMode           = NONE_AUTH;
2089         ar->arPairwiseCrypto     = NONE_CRYPT;
2090         ar->arPairwiseCryptoLen  = 0;
2091         ar->arGroupCrypto        = NONE_CRYPT;
2092         ar->arGroupCryptoLen     = 0;
2093         ar->arChannelHint        = 0;
2094         ar->arBssChannel         = 0;
2095         A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2096         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2097         ar->arSsidLen = 0;
2098     }
2099
2100     /* SSID has to be cleared to trigger a profile change while switching
2101      * between STA & IBSS modes having the same SSID
2102      */
2103     if (ar->arNetworkType != ar->arNextMode) {
2104         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2105         ar->arSsidLen = 0;
2106     }
2107
2108     return 0;
2109 }
2110
2111 /*
2112  * SIOCGIWMODE
2113  */
2114 int
2115 ar6000_ioctl_giwmode(struct net_device *dev,
2116             struct iw_request_info *info,
2117             __u32 *mode, char *extra)
2118 {
2119     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2120
2121     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2122         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2123         return -EOPNOTSUPP;
2124     }
2125
2126     if (ar->arWlanState == WLAN_DISABLED) {
2127         return -EIO;
2128     }
2129
2130     switch (ar->arNetworkType) {
2131     case INFRA_NETWORK:
2132         *mode = IW_MODE_INFRA;
2133         break;
2134     case ADHOC_NETWORK:
2135         *mode = IW_MODE_ADHOC;
2136         break;
2137     case AP_NETWORK:
2138         *mode = IW_MODE_MASTER;
2139         break;
2140     default:
2141         return -EIO;
2142     }
2143     return 0;
2144 }
2145
2146 /*
2147  * SIOCSIWSENS
2148  */
2149 int
2150 ar6000_ioctl_siwsens(struct net_device *dev,
2151             struct iw_request_info *info,
2152             struct iw_param *sens, char *extra)
2153 {
2154     return 0;
2155 }
2156
2157 /*
2158  * SIOCGIWSENS
2159  */
2160 int
2161 ar6000_ioctl_giwsens(struct net_device *dev,
2162             struct iw_request_info *info,
2163             struct iw_param *sens, char *extra)
2164 {
2165     sens->value = 0;
2166     sens->fixed = 1;
2167
2168     return 0;
2169 }
2170
2171 /*
2172  * SIOCGIWRANGE
2173  */
2174 int
2175 ar6000_ioctl_giwrange(struct net_device *dev,
2176              struct iw_request_info *info,
2177              struct iw_point *data, char *extra)
2178 {
2179     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2180     struct iw_range *range = (struct iw_range *) extra;
2181     int i, ret = 0;
2182
2183     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2184         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2185         return -EOPNOTSUPP;
2186     }
2187
2188     if (ar->bIsDestroyProgress) {
2189         return -EBUSY;
2190     }
2191
2192     if (ar->arWmiReady == false) {
2193         return -EIO;
2194     }
2195
2196     if (down_interruptible(&ar->arSem)) {
2197         return -ERESTARTSYS;
2198     }
2199
2200     if (ar->bIsDestroyProgress) {
2201         up(&ar->arSem);
2202         return -EBUSY;
2203     }
2204
2205     ar->arNumChannels = -1;
2206     A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
2207
2208     if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
2209         up(&ar->arSem);
2210         return -EIO;
2211     }
2212
2213     wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
2214
2215     if (signal_pending(current)) {
2216         up(&ar->arSem);
2217         return -EINTR;
2218     }
2219
2220     data->length = sizeof(struct iw_range);
2221     A_MEMZERO(range, sizeof(struct iw_range));
2222
2223     range->txpower_capa = 0;
2224
2225     range->min_pmp = 1 * 1024;
2226     range->max_pmp = 65535 * 1024;
2227     range->min_pmt = 1 * 1024;
2228     range->max_pmt = 1000 * 1024;
2229     range->pmp_flags = IW_POWER_PERIOD;
2230     range->pmt_flags = IW_POWER_TIMEOUT;
2231     range->pm_capa = 0;
2232
2233     range->we_version_compiled = WIRELESS_EXT;
2234     range->we_version_source = 13;
2235
2236     range->retry_capa = IW_RETRY_LIMIT;
2237     range->retry_flags = IW_RETRY_LIMIT;
2238     range->min_retry = 0;
2239     range->max_retry = 255;
2240
2241     range->num_frequency = range->num_channels = ar->arNumChannels;
2242     for (i = 0; i < ar->arNumChannels; i++) {
2243         range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
2244         range->freq[i].m = ar->arChannelList[i] * 100000;
2245         range->freq[i].e = 1;
2246          /*
2247          * Linux supports max of 32 channels, bail out once you
2248          * reach the max.
2249          */
2250         if (i == IW_MAX_FREQUENCIES) {
2251             break;
2252         }
2253     }
2254
2255     /* Max quality is max field value minus noise floor */
2256     range->max_qual.qual  = 0xff - 161;
2257
2258     /*
2259      * In order to use dBm measurements, 'level' must be lower
2260      * than any possible measurement (see iw_print_stats() in
2261      * wireless tools).  It's unclear how this is meant to be
2262      * done, but setting zero in these values forces dBm and
2263      * the actual numbers are not used.
2264      */
2265     range->max_qual.level = 0;
2266     range->max_qual.noise = 0;
2267
2268     range->sensitivity = 3;
2269
2270     range->max_encoding_tokens = 4;
2271     /* XXX query driver to find out supported key sizes */
2272     range->num_encoding_sizes = 3;
2273     range->encoding_size[0] = 5;        /* 40-bit */
2274     range->encoding_size[1] = 13;       /* 104-bit */
2275     range->encoding_size[2] = 16;       /* 128-bit */
2276
2277     range->num_bitrates = 0;
2278
2279     /* estimated maximum TCP throughput values (bps) */
2280     range->throughput = 22000000;
2281
2282     range->min_rts = 0;
2283     range->max_rts = 2347;
2284     range->min_frag = 256;
2285     range->max_frag = 2346;
2286
2287     up(&ar->arSem);
2288
2289     return ret;
2290 }
2291
2292
2293 /*
2294  * SIOCSIWAP
2295  * This ioctl is used to set the desired bssid for the connect command.
2296  */
2297 int
2298 ar6000_ioctl_siwap(struct net_device *dev,
2299               struct iw_request_info *info,
2300               struct sockaddr *ap_addr, char *extra)
2301 {
2302     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2303
2304     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2305         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2306         return -EOPNOTSUPP;
2307     }
2308
2309     if (ar->arWlanState == WLAN_DISABLED) {
2310         return -EIO;
2311     }
2312
2313     if (ap_addr->sa_family != ARPHRD_ETHER) {
2314         return -EIO;
2315     }
2316
2317     if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
2318         A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2319     } else {
2320         A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data,  sizeof(ar->arReqBssid));
2321     }
2322
2323     return 0;
2324 }
2325
2326 /*
2327  * SIOCGIWAP
2328  */
2329 int
2330 ar6000_ioctl_giwap(struct net_device *dev,
2331               struct iw_request_info *info,
2332               struct sockaddr *ap_addr, char *extra)
2333 {
2334     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2335
2336     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2337         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2338         return -EOPNOTSUPP;
2339     }
2340
2341     if (ar->arWlanState == WLAN_DISABLED) {
2342         return -EIO;
2343     }
2344
2345     if (ar->arNetworkType == AP_NETWORK) {
2346         A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
2347         ap_addr->sa_family = ARPHRD_ETHER;
2348         return 0;
2349     }
2350
2351     if (ar->arConnected != true) {
2352         return -EINVAL;
2353     }
2354
2355     A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
2356     ap_addr->sa_family = ARPHRD_ETHER;
2357
2358     return 0;
2359 }
2360
2361 #if (WIRELESS_EXT >= 18)
2362 /*
2363  * SIOCSIWMLME
2364  */
2365 int
2366 ar6000_ioctl_siwmlme(struct net_device *dev,
2367             struct iw_request_info *info,
2368             struct iw_point *data, char *extra)
2369 {
2370     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2371
2372     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2373         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2374         return -EOPNOTSUPP;
2375     }
2376
2377     if (ar->bIsDestroyProgress) {
2378         return -EBUSY;
2379     }
2380
2381     if (ar->arWlanState == WLAN_DISABLED) {
2382         return -EIO;
2383     }
2384
2385     if (ar->arWmiReady == false) {
2386         return -EIO;
2387     }
2388
2389     if (down_interruptible(&ar->arSem)) {
2390         return -ERESTARTSYS;
2391     }
2392
2393     if (data->pointer && data->length == sizeof(struct iw_mlme)) {
2394
2395         u8 arNetworkType;
2396         struct iw_mlme mlme;
2397
2398         if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
2399             return -EIO;
2400
2401         switch (mlme.cmd) {
2402
2403             case IW_MLME_DEAUTH:
2404                 /* fall through */
2405             case IW_MLME_DISASSOC:
2406                 if ((ar->arConnected != true) ||
2407                     (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) {
2408
2409                     up(&ar->arSem);
2410                     return -EINVAL;
2411                 }
2412                 wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
2413                 arNetworkType = ar->arNetworkType;
2414                 ar6000_init_profile_info(ar);
2415                 ar->arNetworkType = arNetworkType;
2416                 reconnect_flag = 0;
2417                 wmi_disconnect_cmd(ar->arWmi);
2418                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2419                 ar->arSsidLen = 0;
2420                 if (ar->arSkipScan == false) {
2421                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2422                 }
2423                 break;
2424
2425             case IW_MLME_AUTH:
2426                 /* fall through */
2427             case IW_MLME_ASSOC:
2428                 /* fall through */
2429             default:
2430                 up(&ar->arSem);
2431                 return -EOPNOTSUPP;
2432         }
2433     }
2434
2435     up(&ar->arSem);
2436     return 0;
2437 }
2438 #endif /* WIRELESS_EXT >= 18 */
2439
2440 /*
2441  * SIOCGIWAPLIST
2442  */
2443 int
2444 ar6000_ioctl_iwaplist(struct net_device *dev,
2445             struct iw_request_info *info,
2446             struct iw_point *data, char *extra)
2447 {
2448     return -EIO;            /* for now */
2449 }
2450
2451 /*
2452  * SIOCSIWSCAN
2453  */
2454 int
2455 ar6000_ioctl_siwscan(struct net_device *dev,
2456                      struct iw_request_info *info,
2457                      struct iw_point *data, char *extra)
2458 {
2459 #define ACT_DWELLTIME_DEFAULT   105
2460 #define HOME_TXDRAIN_TIME       100
2461 #define SCAN_INT                HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
2462     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2463     int ret = 0;
2464
2465     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2466         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2467         return -EOPNOTSUPP;
2468     }
2469
2470     if (ar->arWmiReady == false) {
2471         return -EIO;
2472     }
2473
2474     if (ar->arWlanState == WLAN_DISABLED) {
2475         return -EIO;
2476     }
2477
2478     /* If scan is issued in the middle of ongoing scan or connect,
2479        dont issue another one */
2480     if ( ar->scan_triggered > 0 ) {
2481         ++ar->scan_triggered;
2482         if (ar->scan_triggered < 5) {
2483             return 0;
2484         } else {
2485             AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("Scan request is triggered over 5 times. Not scan complete event\n"));
2486         }
2487     } 
2488
2489     if (!ar->arUserBssFilter) {
2490         if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
2491             return -EIO;
2492         }
2493     }
2494
2495     if (ar->arConnected) {
2496         if  (wmi_get_stats_cmd(ar->arWmi) != A_OK) {
2497             return -EIO;
2498         }
2499     }
2500
2501 #ifdef ANDROID_ENV
2502 #if WIRELESS_EXT >= 18
2503     if (data->pointer && (data->length == sizeof(struct iw_scan_req)))
2504     {
2505         if ((data->flags & IW_SCAN_THIS_ESSID) == IW_SCAN_THIS_ESSID)
2506         {
2507             struct iw_scan_req req;
2508             if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req)))
2509                 return -EIO;
2510             if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != A_OK)
2511                 return -EIO;
2512             ar->scanSpecificSsid = true;
2513         }
2514         else
2515         {
2516             if (ar->scanSpecificSsid) {
2517                 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2518                     return -EIO;
2519                  ar->scanSpecificSsid = false;
2520             }
2521         }
2522     }
2523     else
2524     {
2525         if (ar->scanSpecificSsid) {
2526             if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2527                 return -EIO;
2528              ar->scanSpecificSsid = false;
2529         }
2530     }
2531 #endif
2532 #endif /* ANDROID_ENV */
2533
2534     if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, false, false, \
2535                           0, 0, 0, NULL) != A_OK) {
2536         ret = -EIO;
2537     }
2538
2539     if (ret == 0) {
2540         ar->scan_triggered = 1;
2541     }
2542
2543     return ret;
2544 #undef  ACT_DWELLTIME_DEFAULT
2545 #undef HOME_TXDRAIN_TIME
2546 #undef SCAN_INT
2547 }
2548
2549
2550 /*
2551  * Units are in db above the noise floor. That means the
2552  * rssi values reported in the tx/rx descriptors in the
2553  * driver are the SNR expressed in db.
2554  *
2555  * If you assume that the noise floor is -95, which is an
2556  * excellent assumption 99.5 % of the time, then you can
2557  * derive the absolute signal level (i.e. -95 + rssi).
2558  * There are some other slight factors to take into account
2559  * depending on whether the rssi measurement is from 11b,
2560  * 11g, or 11a.   These differences are at most 2db and
2561  * can be documented.
2562  *
2563  * NB: various calculations are based on the orinoco/wavelan
2564  *     drivers for compatibility
2565  */
2566 static void
2567 ar6000_set_quality(struct iw_quality *iq, s8 rssi)
2568 {
2569     if (rssi < 0) {
2570         iq->qual = 0;
2571     } else {
2572         iq->qual = rssi;
2573     }
2574
2575     /* NB: max is 94 because noise is hardcoded to 161 */
2576     if (iq->qual > 94)
2577         iq->qual = 94;
2578
2579     iq->noise = 161;        /* -95dBm */
2580     iq->level = iq->noise + iq->qual;
2581     iq->updated = 7;
2582 }
2583
2584
2585 int
2586 ar6000_ioctl_siwcommit(struct net_device *dev,
2587                      struct iw_request_info *info,
2588                      struct iw_point *data, char *extra)
2589 {
2590     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2591
2592     if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2593         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2594         return -EOPNOTSUPP;
2595     }
2596
2597     if (ar->arWmiReady == false) {
2598         return -EIO;
2599     }
2600
2601     if (ar->arWlanState == WLAN_DISABLED) {
2602         return -EIO;
2603     }
2604
2605     AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AP: SSID %s freq %d authmode %d dot11 auth %d"\
2606                     " PW crypto %d GRP crypto %d\n",
2607                     ar->arSsid, ar->arChannelHint,
2608                     ar->arAuthMode, ar->arDot11AuthMode,
2609                     ar->arPairwiseCrypto, ar->arGroupCrypto));
2610
2611     ar6000_ap_mode_profile_commit(ar);
2612
2613     /* if there is a profile switch from STA|IBSS mode to AP mode,
2614      * update the host driver association state for the STA|IBSS mode.
2615      */
2616     if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) {
2617         ar->arConnectPending = false;
2618         ar->arConnected = false;
2619         /* Stop getting pkts from upper stack */
2620         netif_stop_queue(ar->arNetDev);
2621         A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2622         ar->arBssChannel = 0;
2623         ar->arBeaconInterval = 0;
2624
2625         /* Flush the Tx queues */
2626         ar6000_TxDataCleanup(ar);
2627
2628         /* Start getting pkts from upper stack */
2629         netif_wake_queue(ar->arNetDev);
2630     }
2631
2632     return 0;
2633 }
2634
2635 #define W_PROTO(_x) wait_ ## _x
2636 #define WAIT_HANDLER_IMPL(_x, type) \
2637 int wait_ ## _x (struct net_device *dev, struct iw_request_info *info, type wrqu, char *extra) {\
2638     int ret; \
2639     dev_hold(dev); \
2640     rtnl_unlock(); \
2641     ret = _x(dev, info, wrqu, extra); \
2642     rtnl_lock(); \
2643     dev_put(dev); \
2644     return ret;\
2645 }
2646
2647 WAIT_HANDLER_IMPL(ar6000_ioctl_siwessid, struct iw_point *)
2648 WAIT_HANDLER_IMPL(ar6000_ioctl_giwrate, struct iw_param *)
2649 WAIT_HANDLER_IMPL(ar6000_ioctl_giwtxpow, struct iw_param *)
2650 WAIT_HANDLER_IMPL(ar6000_ioctl_giwrange, struct iw_point*)
2651
2652 /* Structures to export the Wireless Handlers */
2653 static const iw_handler ath_handlers[] = {
2654     (iw_handler) ar6000_ioctl_siwcommit,        /* SIOCSIWCOMMIT */
2655     (iw_handler) ar6000_ioctl_giwname,          /* SIOCGIWNAME */
2656     (iw_handler) NULL,                          /* SIOCSIWNWID */
2657     (iw_handler) NULL,                          /* SIOCGIWNWID */
2658     (iw_handler) ar6000_ioctl_siwfreq,          /* SIOCSIWFREQ */
2659     (iw_handler) ar6000_ioctl_giwfreq,          /* SIOCGIWFREQ */
2660     (iw_handler) ar6000_ioctl_siwmode,          /* SIOCSIWMODE */
2661     (iw_handler) ar6000_ioctl_giwmode,          /* SIOCGIWMODE */
2662     (iw_handler) ar6000_ioctl_siwsens,          /* SIOCSIWSENS */
2663     (iw_handler) ar6000_ioctl_giwsens,          /* SIOCGIWSENS */
2664     (iw_handler) NULL /* not _used */,          /* SIOCSIWRANGE */
2665     (iw_handler) W_PROTO(ar6000_ioctl_giwrange),/* SIOCGIWRANGE */
2666     (iw_handler) NULL /* not used */,           /* SIOCSIWPRIV */
2667     (iw_handler) NULL /* kernel code */,        /* SIOCGIWPRIV */
2668     (iw_handler) NULL /* not used */,           /* SIOCSIWSTATS */
2669     (iw_handler) NULL /* kernel code */,        /* SIOCGIWSTATS */
2670     (iw_handler) NULL,                          /* SIOCSIWSPY */
2671     (iw_handler) NULL,                          /* SIOCGIWSPY */
2672     (iw_handler) NULL,                          /* SIOCSIWTHRSPY */
2673     (iw_handler) NULL,                          /* SIOCGIWTHRSPY */
2674     (iw_handler) ar6000_ioctl_siwap,            /* SIOCSIWAP */
2675     (iw_handler) ar6000_ioctl_giwap,            /* SIOCGIWAP */
2676 #if (WIRELESS_EXT >= 18)
2677     (iw_handler) ar6000_ioctl_siwmlme,          /* SIOCSIWMLME */
2678 #else
2679     (iw_handler) NULL,                          /* -- hole -- */
2680 #endif  /* WIRELESS_EXT >= 18 */
2681     (iw_handler) ar6000_ioctl_iwaplist,         /* SIOCGIWAPLIST */
2682     (iw_handler) ar6000_ioctl_siwscan,          /* SIOCSIWSCAN */
2683     (iw_handler) ar6000_ioctl_giwscan,          /* SIOCGIWSCAN */
2684     (iw_handler) W_PROTO(ar6000_ioctl_siwessid),/* SIOCSIWESSID */
2685     (iw_handler) ar6000_ioctl_giwessid,         /* SIOCGIWESSID */
2686     (iw_handler) NULL,                          /* SIOCSIWNICKN */
2687     (iw_handler) NULL,                          /* SIOCGIWNICKN */
2688     (iw_handler) NULL,                          /* -- hole -- */
2689     (iw_handler) NULL,                          /* -- hole -- */
2690     (iw_handler) ar6000_ioctl_siwrate,          /* SIOCSIWRATE */
2691     (iw_handler) W_PROTO(ar6000_ioctl_giwrate), /* SIOCGIWRATE */
2692     (iw_handler) NULL,                          /* SIOCSIWRTS */
2693     (iw_handler) NULL,                          /* SIOCGIWRTS */
2694     (iw_handler) NULL,                          /* SIOCSIWFRAG */
2695     (iw_handler) NULL,                          /* SIOCGIWFRAG */
2696     (iw_handler) ar6000_ioctl_siwtxpow,         /* SIOCSIWTXPOW */
2697     (iw_handler) W_PROTO(ar6000_ioctl_giwtxpow),/* SIOCGIWTXPOW */
2698     (iw_handler) ar6000_ioctl_siwretry,         /* SIOCSIWRETRY */
2699     (iw_handler) ar6000_ioctl_giwretry,         /* SIOCGIWRETRY */
2700     (iw_handler) ar6000_ioctl_siwencode,        /* SIOCSIWENCODE */
2701     (iw_handler) ar6000_ioctl_giwencode,        /* SIOCGIWENCODE */
2702 #if WIRELESS_EXT > 20
2703     (iw_handler) ar6000_ioctl_siwpower,         /* SIOCSIWPOWER */
2704     (iw_handler) ar6000_ioctl_giwpower,         /* SIOCGIWPOWER */
2705 #endif // WIRELESS_EXT > 20
2706 #if WIRELESS_EXT >= 18
2707     (iw_handler) NULL,                          /* -- hole -- */
2708     (iw_handler) NULL,                          /* -- hole -- */
2709     (iw_handler) ar6000_ioctl_siwgenie,         /* SIOCSIWGENIE */
2710     (iw_handler) ar6000_ioctl_giwgenie,         /* SIOCGIWGENIE */
2711     (iw_handler) ar6000_ioctl_siwauth,          /* SIOCSIWAUTH */
2712     (iw_handler) ar6000_ioctl_giwauth,          /* SIOCGIWAUTH */
2713     (iw_handler) ar6000_ioctl_siwencodeext,     /* SIOCSIWENCODEEXT */
2714     (iw_handler) ar6000_ioctl_giwencodeext,     /* SIOCGIWENCODEEXT */
2715     (iw_handler) ar6000_ioctl_siwpmksa,         /* SIOCSIWPMKSA */
2716 #endif // WIRELESS_EXT >= 18
2717 };
2718
2719 struct iw_handler_def ath_iw_handler_def = {
2720     .standard         = (iw_handler *)ath_handlers,
2721     .num_standard     = ARRAY_SIZE(ath_handlers),
2722     .private          = NULL,
2723     .num_private      = 0,
2724 };