• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ---------------------------------------------------------------------------
3  * FILE:     sme_mgt_blocking.c
4  *
5  * PURPOSE:
6  *      This file contains the driver specific implementation of
7  *      the WEXT <==> SME MGT interface for all SME builds that support WEXT.
8  *
9  * Copyright (C) 2009 by Cambridge Silicon Radio Ltd.
10  *
11  * Refer to LICENSE.txt included with this source code for details on
12  * the license terms.
13  *
14  * ---------------------------------------------------------------------------
15  */
16 
17 #include "unifi_priv.h"
18 
19 
20 /*
21  * This file also contains the implementation of the asynchronous
22  * requests to the SME.
23  *
24  * Before calling an asynchronous SME function, we call sme_init_request()
25  * which gets hold of the SME semaphore and updates the request status.
26  * The semaphore makes sure that there is only one pending request to
27  * the SME at a time.
28  *
29  * Now we are ready to call the SME function, but only if
30  * sme_init_request() has returned 0.
31  *
32  * When the SME function returns, we need to wait
33  * for the reply. This is done in sme_wait_for_reply().
34  * If the request times-out, the request status is set to SME_REQUEST_TIMEDOUT
35  * and the sme_wait_for_reply() returns.
36  *
37  * If the SME replies in time, we call sme_complete_request().
38  * There we change the request status to SME_REQUEST_RECEIVED. This will
39  * wake up the process waiting on sme_wait_for_reply().
40  * It is important that we copy the reply data in priv->sme_reply
41  * before calling sme_complete_request().
42  *
43  * Handling the wext requests, we need to block
44  * until the SME sends the response to our request.
45  * We use the sme_init_request() and sme_wait_for_reply()
46  * to implement this behavior in the following functions:
47  * sme_mgt_wifi_on()
48  * sme_mgt_wifi_off()
49  * sme_mgt_scan_full()
50  * sme_mgt_scan_results_get_async()
51  * sme_mgt_connect()
52  * unifi_mgt_media_status_ind()
53  * sme_mgt_disconnect()
54  * sme_mgt_pmkid()
55  * sme_mgt_key()
56  * sme_mgt_mib_get()
57  * sme_mgt_mib_set()
58  * sme_mgt_versions_get()
59  * sme_mgt_set_value()
60  * sme_mgt_get_value()
61  * sme_mgt_set_value_async()
62  * sme_mgt_get_value_async()
63  * sme_mgt_packet_filter_set()
64  * sme_mgt_tspec()
65  */
66 
67 
68 /*
69  * Handling the suspend and resume system events, we need to block
70  * until the SME sends the response to our indication.
71  * We use the sme_init_request() and sme_wait_for_reply()
72  * to implement this behavior in the following functions:
73  * sme_sys_suspend()
74  * sme_sys_resume()
75  */
76 
77 #define UNIFI_SME_MGT_SHORT_TIMEOUT    10000
78 #define UNIFI_SME_MGT_LONG_TIMEOUT     19000
79 #define UNIFI_SME_SYS_LONG_TIMEOUT     10000
80 
81 #ifdef UNIFI_DEBUG
82 # define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, __func__)
83 #else
84 # define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, NULL)
85 #endif
86 
87 static int
sme_init_request(unifi_priv_t * priv)88 sme_init_request(unifi_priv_t *priv)
89 {
90     if (priv == NULL) {
91         unifi_error(priv, "sme_init_request: Invalid priv\n");
92         return -EIO;
93     }
94 
95     unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n");
96 
97     /* Grab the SME semaphore until the reply comes, or timeout */
98     if (down_interruptible(&priv->sme_sem)) {
99         unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n");
100         return -EIO;
101     }
102     unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n");
103 
104     priv->sme_reply.request_status = SME_REQUEST_PENDING;
105 
106     return 0;
107 
108 } /* sme_init_request() */
109 
110 
111 void
uf_sme_complete_request(unifi_priv_t * priv,CsrResult reply_status,const char * func)112 uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func)
113 {
114     if (priv == NULL) {
115         unifi_error(priv, "sme_complete_request: Invalid priv\n");
116         return;
117     }
118 
119     if (priv->sme_reply.request_status != SME_REQUEST_PENDING) {
120         unifi_notice(priv,
121                     "sme_complete_request: request not pending %s (s:%d)\n",
122                     (func ? func : ""), priv->sme_reply.request_status);
123         return;
124     }
125     unifi_trace(priv, UDBG5,
126                 "sme_complete_request: completed %s (s:%d)\n",
127                 (func ? func : ""), priv->sme_reply.request_status);
128 
129     priv->sme_reply.request_status = SME_REQUEST_RECEIVED;
130     priv->sme_reply.reply_status = reply_status;
131 
132     wake_up_interruptible(&priv->sme_request_wq);
133 
134     return;
135 }
136 
137 
138 void
uf_sme_cancel_request(unifi_priv_t * priv,CsrResult reply_status)139 uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status)
140 {
141     /* Check for a blocking SME request in progress, and cancel the wait.
142      * This should be used when the character device is closed.
143      */
144 
145     if (priv == NULL) {
146         unifi_error(priv, "sme_cancel_request: Invalid priv\n");
147         return;
148     }
149 
150     /* If no request is pending, nothing to wake up */
151     if (priv->sme_reply.request_status != SME_REQUEST_PENDING) {
152         unifi_trace(priv, UDBG5,
153                     "sme_cancel_request: no request was pending (s:%d)\n",
154                     priv->sme_reply.request_status);
155         /* Nothing to do */
156         return;
157     }
158     unifi_trace(priv, UDBG5,
159                 "sme_cancel_request: request cancelled (s:%d)\n",
160                 priv->sme_reply.request_status);
161 
162     /* Wake up the wait with an error status */
163     priv->sme_reply.request_status = SME_REQUEST_CANCELLED;
164     priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */
165 
166     wake_up_interruptible(&priv->sme_request_wq);
167 
168     return;
169 }
170 
171 
172 static int
_sme_wait_for_reply(unifi_priv_t * priv,unsigned long timeout,const char * func)173 _sme_wait_for_reply(unifi_priv_t *priv,
174         unsigned long timeout, const char *func)
175 {
176     long r;
177 
178     unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : "");
179     r = wait_event_interruptible_timeout(priv->sme_request_wq,
180                                          (priv->sme_reply.request_status != SME_REQUEST_PENDING),
181                                          msecs_to_jiffies(timeout));
182     unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r);
183 
184     if (r == -ERESTARTSYS) {
185         /* The thread was killed */
186         unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n");
187         up(&priv->sme_sem);
188         return r;
189     }
190     if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) {
191         unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n",
192                     (func ? func : ""), priv->sme_reply.request_status, timeout, r);
193 
194         /* Release the SME semaphore that was downed in sme_init_request() */
195         up(&priv->sme_sem);
196         return -EIO; /* fail the ioctl */
197     }
198     if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) {
199         unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n",
200                      (func ? func : ""), priv->sme_reply.request_status, timeout);
201 
202         priv->sme_reply.request_status = SME_REQUEST_TIMEDOUT;
203 
204         /* Release the SME semaphore that was downed in sme_init_request() */
205         up(&priv->sme_sem);
206 
207         return -ETIMEDOUT;
208     }
209 
210     unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n",
211                 func ? func : "", r);
212 
213     /* Release the SME semaphore that was downed in sme_init_request() */
214     up(&priv->sme_sem);
215 
216     return 0;
217 } /* sme_wait_for_reply() */
218 
219 
220 
221 
222 #ifdef CSR_SUPPORT_WEXT
sme_mgt_wifi_on(unifi_priv_t * priv)223 int sme_mgt_wifi_on(unifi_priv_t *priv)
224 {
225     u16 numElements;
226     CsrWifiSmeDataBlock* dataList;
227 #ifdef CSR_SUPPORT_WEXT_AP
228     int r;
229 #endif
230 
231     if (priv->smepriv == NULL) {
232         unifi_error(priv, "sme_mgt_wifi_on: invalid smepriv\n");
233         return -EIO;
234     }
235 
236     if (priv->mib_data.length) {
237         numElements = 1;
238         dataList = &priv->mib_data;
239     } else {
240         numElements = 0;
241         dataList = NULL;
242     }
243     /* Start the SME */
244 #ifdef CSR_SUPPORT_WEXT_AP
245     r = sme_init_request(priv);
246     if (r) {
247         return -EIO;
248     }
249 #endif
250     CsrWifiSmeWifiOnReqSend(0, priv->sta_mac_address, numElements, dataList);
251 #ifdef CSR_SUPPORT_WEXT_AP
252     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
253     unifi_trace(priv, UDBG4,
254                 "sme_mgt_wifi_on: unifi_mgt_wifi_oo_req <-- (r=%d, status=%d)\n",
255                 r, priv->sme_reply.reply_status);
256     return convert_sme_error(priv->sme_reply.reply_status);
257 #else
258     return 0;
259 #endif
260 } /* sme_mgt_wifi_on() */
261 
262 
sme_mgt_wifi_off(unifi_priv_t * priv)263 int sme_mgt_wifi_off(unifi_priv_t *priv)
264 {
265     int r;
266 
267     if (priv->smepriv == NULL) {
268         unifi_error(priv, "sme_mgt_wifi_off: invalid smepriv\n");
269         return -EIO;
270     }
271 
272     r = sme_init_request(priv);
273     if (r)
274         return -EIO;
275 
276     /* Stop the SME */
277     CsrWifiSmeWifiOffReqSend(0);
278 
279     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
280     if (r)
281         return r;
282 
283     unifi_trace(priv, UDBG4,
284                 "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n",
285                 r, priv->sme_reply.reply_status);
286     return convert_sme_error(priv->sme_reply.reply_status);
287 
288 } /* sme_mgt_wifi_off */
289 
sme_mgt_key(unifi_priv_t * priv,CsrWifiSmeKey * sme_key,CsrWifiSmeListAction action)290 int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key,
291         CsrWifiSmeListAction action)
292 {
293     int r;
294 
295     if (priv->smepriv == NULL) {
296         unifi_error(priv, "sme_mgt_key: invalid smepriv\n");
297         return -EIO;
298     }
299 
300     r = sme_init_request(priv);
301     if (r)
302         return -EIO;
303 
304     CsrWifiSmeKeyReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, *sme_key);
305 
306     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
307     if (r)
308         return r;
309 
310     return convert_sme_error(priv->sme_reply.reply_status);
311 }
312 
313 
sme_mgt_scan_full(unifi_priv_t * priv,CsrWifiSsid * specific_ssid,int num_channels,unsigned char * channel_list)314 int sme_mgt_scan_full(unifi_priv_t *priv,
315         CsrWifiSsid *specific_ssid,
316         int num_channels,
317         unsigned char *channel_list)
318 {
319     CsrWifiMacAddress bcastAddress = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
320     u8 is_active = (num_channels > 0) ? TRUE : FALSE;
321     int r;
322 
323     if (priv->smepriv == NULL) {
324         unifi_error(priv, "sme_mgt_scan_full: invalid smepriv\n");
325         return -EIO;
326     }
327 
328     unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n");
329 
330     r = sme_init_request(priv);
331     if (r)
332         return -EIO;
333 
334     /* If a channel list is provided, do an active scan */
335     if (is_active) {
336         unifi_trace(priv, UDBG1,
337                     "channel list - num_channels: %d, active scan\n",
338                     num_channels);
339     }
340 
341     CsrWifiSmeScanFullReqSend(0,
342                               specific_ssid->length?1:0, /* 0 or 1 SSIDS */
343                               specific_ssid,
344                               bcastAddress,
345                               is_active,
346                               CSR_WIFI_SME_BSS_TYPE_ANY_BSS,
347                               CSR_WIFI_SME_SCAN_TYPE_ALL,
348                               (u16)num_channels, channel_list,
349                               0, NULL);
350 
351     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
352     if (r)
353         return r;
354 
355     unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status);
356     if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE)
357         return 0; /* initial scan already underway */
358     else
359         return convert_sme_error(priv->sme_reply.reply_status);
360 }
361 
362 
sme_mgt_scan_results_get_async(unifi_priv_t * priv,struct iw_request_info * info,char * scan_results,long scan_results_len)363 int sme_mgt_scan_results_get_async(unifi_priv_t *priv,
364         struct iw_request_info *info,
365         char *scan_results,
366         long scan_results_len)
367 {
368     u16 scan_result_list_count;
369     CsrWifiSmeScanResult *scan_result_list;
370     CsrWifiSmeScanResult *scan_result;
371     int r;
372     int i;
373     char *current_ev = scan_results;
374 
375     if (priv->smepriv == NULL) {
376         unifi_error(priv, "sme_mgt_scan_results_get_async: invalid smepriv\n");
377         return -EIO;
378     }
379 
380     r = sme_init_request(priv);
381     if (r)
382         return -EIO;
383 
384     CsrWifiSmeScanResultsGetReqSend(0);
385     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
386     if (r)
387         return r;
388 
389     scan_result_list_count = priv->sme_reply.reply_scan_results_count;
390     scan_result_list = priv->sme_reply.reply_scan_results;
391     unifi_trace(priv, UDBG2,
392                 "scan_results: Scan returned %d, numElements=%d\n",
393                 r, scan_result_list_count);
394 
395     /* OK, now we have the scan results */
396     for (i = 0; i < scan_result_list_count; ++i) {
397         scan_result = &scan_result_list[i];
398 
399         unifi_trace(priv, UDBG2, "Scan Result: %.*s\n",
400                     scan_result->ssid.length,
401                     scan_result->ssid.ssid);
402 
403         r = unifi_translate_scan(priv->netdev[0], info,
404                                  current_ev,
405                                  scan_results + scan_results_len,
406                                  scan_result, i+1);
407 
408         if (r < 0) {
409             kfree(scan_result_list);
410             priv->sme_reply.reply_scan_results_count = 0;
411             priv->sme_reply.reply_scan_results = NULL;
412             return r;
413         }
414 
415         current_ev += r;
416     }
417 
418     /*
419      * Free the scan results allocated in unifi_mgt_scan_results_get_cfm()
420      * and invalidate the reply_scan_results to avoid re-using
421      * the freed pointers.
422      */
423     kfree(scan_result_list);
424     priv->sme_reply.reply_scan_results_count = 0;
425     priv->sme_reply.reply_scan_results = NULL;
426 
427     unifi_trace(priv, UDBG2,
428                 "scan_results: Scan translated to %d bytes\n",
429                 current_ev - scan_results);
430     return (current_ev - scan_results);
431 }
432 
433 
sme_mgt_connect(unifi_priv_t * priv)434 int sme_mgt_connect(unifi_priv_t *priv)
435 {
436     int r;
437 
438     if (priv->smepriv == NULL) {
439         unifi_error(priv, "sme_mgt_connect: invalid smepriv\n");
440         return -EIO;
441     }
442 
443     unifi_trace(priv, UDBG2, "sme_mgt_connect: %.*s\n",
444                 priv->connection_config.ssid.length,
445                 priv->connection_config.ssid.ssid);
446 
447     r = sme_init_request(priv);
448     if (r)
449         return -EIO;
450 
451     CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config);
452     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
453     if (r)
454         return r;
455 
456     if (priv->sme_reply.reply_status)
457         unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n",
458                     priv->sme_reply.reply_status);
459 
460     return convert_sme_error(priv->sme_reply.reply_status);
461 }
462 
463 
sme_mgt_disconnect(unifi_priv_t * priv)464 int sme_mgt_disconnect(unifi_priv_t *priv)
465 {
466     int r;
467 
468     if (priv->smepriv == NULL) {
469         unifi_error(priv, "sme_mgt_disconnect: invalid smepriv\n");
470         return -EIO;
471     }
472 
473     r = sme_init_request(priv);
474     if (r)
475         return -EIO;
476 
477     CsrWifiSmeDisconnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
478     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
479     if (r)
480         return r;
481 
482     unifi_trace(priv, UDBG4, "sme_mgt_disconnect: <-- (status=%d)\n", priv->sme_reply.reply_status);
483     return convert_sme_error(priv->sme_reply.reply_status);
484 }
485 
486 
sme_mgt_pmkid(unifi_priv_t * priv,CsrWifiSmeListAction action,CsrWifiSmePmkidList * pmkid_list)487 int sme_mgt_pmkid(unifi_priv_t *priv,
488         CsrWifiSmeListAction action,
489         CsrWifiSmePmkidList *pmkid_list)
490 {
491     int r;
492 
493     if (priv->smepriv == NULL) {
494         unifi_error(priv, "sme_mgt_pmkid: invalid smepriv\n");
495         return -EIO;
496     }
497 
498     r = sme_init_request(priv);
499     if (r)
500         return -EIO;
501 
502     CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action,
503                         pmkid_list->pmkidsCount, pmkid_list->pmkids);
504     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
505     if (r)
506         return r;
507 
508     unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status);
509     return convert_sme_error(priv->sme_reply.reply_status);
510 }
511 
512 
sme_mgt_mib_get(unifi_priv_t * priv,unsigned char * varbind,int * length)513 int sme_mgt_mib_get(unifi_priv_t *priv,
514         unsigned char *varbind, int *length)
515 {
516     int r;
517 
518     if (priv->smepriv == NULL) {
519         unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n");
520         return -EIO;
521     }
522 
523     r = sme_init_request(priv);
524     if (r)
525         return -EIO;
526 
527     priv->mib_cfm_buffer = varbind;
528     priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH;
529 
530     CsrWifiSmeMibGetReqSend(0, *length, varbind);
531     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
532     if (r) {
533         priv->mib_cfm_buffer_length = 0;
534         priv->mib_cfm_buffer = NULL;
535         return r;
536     }
537 
538     *length = priv->mib_cfm_buffer_length;
539 
540     priv->mib_cfm_buffer_length = 0;
541     priv->mib_cfm_buffer = NULL;
542     unifi_trace(priv, UDBG4, "sme_mgt_mib_get: <-- (status=%d)\n", priv->sme_reply.reply_status);
543     return convert_sme_error(priv->sme_reply.reply_status);
544 }
545 
sme_mgt_mib_set(unifi_priv_t * priv,unsigned char * varbind,int length)546 int sme_mgt_mib_set(unifi_priv_t *priv,
547         unsigned char *varbind, int length)
548 {
549     int r;
550 
551     if (priv->smepriv == NULL) {
552         unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n");
553         return -EIO;
554     }
555 
556     r = sme_init_request(priv);
557     if (r)
558         return -EIO;
559 
560     CsrWifiSmeMibSetReqSend(0, length, varbind);
561     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
562     if (r)
563         return r;
564 
565     unifi_trace(priv, UDBG4, "sme_mgt_mib_set: <-- (status=%d)\n", priv->sme_reply.reply_status);
566     return convert_sme_error(priv->sme_reply.reply_status);
567 }
568 
569 #endif /* CSR_SUPPORT_WEXT */
570 
sme_mgt_power_config_set(unifi_priv_t * priv,CsrWifiSmePowerConfig * powerConfig)571 int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig)
572 {
573 #ifdef CSR_SME_USERSPACE
574     int r;
575 
576     if (priv->smepriv == NULL) {
577         unifi_error(priv, "sme_mgt_set_value_async: invalid smepriv\n");
578         return -EIO;
579     }
580 
581     r = sme_init_request(priv);
582     if (r)
583         return -EIO;
584 
585     CsrWifiSmePowerConfigSetReqSend(0, *powerConfig);
586 
587     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
588     if (r)
589         return r;
590 
591     unifi_trace(priv, UDBG4,
592                 "sme_mgt_set_value_async: unifi_mgt_set_value_req <-- (r=%d status=%d)\n",
593                 r, priv->sme_reply.reply_status);
594     return convert_sme_error(priv->sme_reply.reply_status);
595 #else
596     CsrResult status;
597     if (priv->smepriv == NULL) {
598         unifi_error(priv, "sme_mgt_set_value: invalid smepriv\n");
599         return -EIO;
600     }
601     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
602     status = CsrWifiSmeMgtPowerConfigSetReq(priv->smepriv, *powerConfig);
603     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
604     return convert_sme_error(status);
605 #endif
606 }
607 
sme_mgt_sme_config_set(unifi_priv_t * priv,CsrWifiSmeStaConfig * staConfig,CsrWifiSmeDeviceConfig * deviceConfig)608 int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig)
609 {
610 #ifdef CSR_SME_USERSPACE
611     int r;
612 
613     if (priv->smepriv == NULL) {
614         unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n");
615         return -EIO;
616     }
617 
618     r = sme_init_request(priv);
619     if (r)
620         return -EIO;
621 
622     CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig);
623     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
624     if (r)
625         return r;
626 
627     unifi_trace(priv, UDBG4,
628                 "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n",
629                 r, priv->sme_reply.reply_status);
630 
631     r = sme_init_request(priv);
632     if (r)
633         return -EIO;
634 
635     CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig);
636     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
637     if (r)
638         return r;
639 
640     unifi_trace(priv, UDBG4,
641                 "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n",
642                 r, priv->sme_reply.reply_status);
643 
644     return convert_sme_error(priv->sme_reply.reply_status);
645 #else
646     CsrResult status;
647     if (priv->smepriv == NULL) {
648         unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n");
649         return -EIO;
650     }
651     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
652     status = CsrWifiSmeMgtSmeConfigSetReq(priv->smepriv, *staConfig);
653     status = CsrWifiSmeMgtDeviceConfigSetReq(priv->smepriv, *deviceConfig);
654     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
655     return convert_sme_error(status);
656 #endif
657 }
658 
659 #ifdef CSR_SUPPORT_WEXT
660 
sme_mgt_mib_config_set(unifi_priv_t * priv,CsrWifiSmeMibConfig * mibConfig)661 int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
662 {
663 #ifdef CSR_SME_USERSPACE
664     int r;
665 
666     if (priv->smepriv == NULL) {
667         unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n");
668         return -EIO;
669     }
670 
671     r = sme_init_request(priv);
672     if (r)
673         return -EIO;
674 
675     CsrWifiSmeMibConfigSetReqSend(0, *mibConfig);
676 
677     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
678     if (r)
679         return r;
680 
681     unifi_trace(priv, UDBG4,
682                 "sme_mgt_mib_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
683                 r, priv->sme_reply.reply_status);
684     return convert_sme_error(priv->sme_reply.reply_status);
685 #else
686     CsrResult status;
687     if (priv->smepriv == NULL) {
688         unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n");
689         return -EIO;
690     }
691     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
692     status = CsrWifiSmeMgtMibConfigSetReq(priv->smepriv, *mibConfig);
693     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
694     return convert_sme_error(status);
695 #endif
696 }
697 
sme_mgt_coex_config_set(unifi_priv_t * priv,CsrWifiSmeCoexConfig * coexConfig)698 int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig)
699 {
700 #ifdef CSR_SME_USERSPACE
701     int r;
702 
703     if (priv->smepriv == NULL) {
704         unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n");
705         return -EIO;
706     }
707 
708     r = sme_init_request(priv);
709     if (r)
710         return -EIO;
711 
712     CsrWifiSmeCoexConfigSetReqSend(0, *coexConfig);
713 
714     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
715     if (r)
716         return r;
717 
718     unifi_trace(priv, UDBG4,
719                 "sme_mgt_coex_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
720                 r, priv->sme_reply.reply_status);
721     return convert_sme_error(priv->sme_reply.reply_status);
722 #else
723     CsrResult status;
724     if (priv->smepriv == NULL) {
725         unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n");
726         return -EIO;
727     }
728     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
729     status = CsrWifiSmeMgtCoexConfigSetReq(priv->smepriv, *coexConfig);
730     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
731     return convert_sme_error(status);
732 #endif
733 }
734 
735 #endif /* CSR_SUPPORT_WEXT */
736 
sme_mgt_host_config_set(unifi_priv_t * priv,CsrWifiSmeHostConfig * hostConfig)737 int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig)
738 {
739 #ifdef CSR_SME_USERSPACE
740     int r;
741 
742     if (priv->smepriv == NULL) {
743         unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n");
744         return -EIO;
745     }
746 
747     r = sme_init_request(priv);
748     if (r)
749         return -EIO;
750 
751     CsrWifiSmeHostConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *hostConfig);
752 
753     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
754     if (r)
755         return r;
756 
757     unifi_trace(priv, UDBG4,
758                 "sme_mgt_host_config_set: unifi_mgt_set_host_config_req <-- (r=%d status=%d)\n",
759                 r, priv->sme_reply.reply_status);
760     return convert_sme_error(priv->sme_reply.reply_status);
761 #else
762     CsrResult status;
763     if (priv->smepriv == NULL) {
764         unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n");
765         return -EIO;
766     }
767     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
768     status = CsrWifiSmeMgtHostConfigSetReq(priv->smepriv, *hostConfig);
769     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
770     return convert_sme_error(status);
771 #endif
772 }
773 
774 #ifdef CSR_SUPPORT_WEXT
775 
sme_mgt_versions_get(unifi_priv_t * priv,CsrWifiSmeVersions * versions)776 int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions)
777 {
778 #ifdef CSR_SME_USERSPACE
779     int r;
780 
781     if (priv->smepriv == NULL) {
782         unifi_error(priv, "sme_mgt_versions_get: invalid smepriv\n");
783         return -EIO;
784     }
785 
786     unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n");
787     r = sme_init_request(priv);
788     if (r)
789         return -EIO;
790 
791     CsrWifiSmeVersionsGetReqSend(0);
792 
793     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
794     if (r)
795         return r;
796 
797     /* store the reply */
798     if (versions != NULL) {
799         memcpy((unsigned char*)versions,
800                (unsigned char*)&priv->sme_reply.versions,
801                sizeof(CsrWifiSmeVersions));
802     }
803 
804     unifi_trace(priv, UDBG4,
805                 "sme_mgt_versions_get: unifi_mgt_versions_get_req <-- (r=%d status=%d)\n",
806                 r, priv->sme_reply.reply_status);
807 
808     return convert_sme_error(priv->sme_reply.reply_status);
809 #else
810     CsrResult status;
811     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
812     status = CsrWifiSmeMgtVersionsGetReq(priv->smepriv, versions);
813     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
814     return convert_sme_error(status);
815 #endif
816 }
817 
818 #endif /* CSR_SUPPORT_WEXT */
819 
sme_mgt_power_config_get(unifi_priv_t * priv,CsrWifiSmePowerConfig * powerConfig)820 int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig)
821 {
822 #ifdef CSR_SME_USERSPACE
823     int r;
824 
825     if (priv->smepriv == NULL) {
826         unifi_error(priv, "sme_mgt_power_config_get: invalid smepriv\n");
827         return -EIO;
828     }
829 
830     unifi_trace(priv, UDBG4, "sme_mgt_power_config_get: unifi_mgt_power_config_req -->\n");
831     r = sme_init_request(priv);
832     if (r)
833         return -EIO;
834 
835     CsrWifiSmePowerConfigGetReqSend(0);
836 
837     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
838     if (r)
839         return r;
840 
841     /* store the reply */
842     if (powerConfig != NULL) {
843         memcpy((unsigned char*)powerConfig,
844                (unsigned char*)&priv->sme_reply.powerConfig,
845                sizeof(CsrWifiSmePowerConfig));
846     }
847 
848     unifi_trace(priv, UDBG4,
849                 "sme_mgt_get_versions: unifi_mgt_power_config_req <-- (r=%d status=%d)\n",
850                 r, priv->sme_reply.reply_status);
851 
852     return convert_sme_error(priv->sme_reply.reply_status);
853 #else
854     CsrResult status;
855     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
856     status = CsrWifiSmeMgtPowerConfigGetReq(priv->smepriv, powerConfig);
857     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
858     return convert_sme_error(status);
859 #endif
860 }
861 
sme_mgt_host_config_get(unifi_priv_t * priv,CsrWifiSmeHostConfig * hostConfig)862 int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig)
863 {
864 #ifdef CSR_SME_USERSPACE
865     int r;
866 
867     if (priv->smepriv == NULL) {
868         unifi_error(priv, "sme_mgt_host_config_get: invalid smepriv\n");
869         return -EIO;
870     }
871 
872     unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n");
873     r = sme_init_request(priv);
874     if (r)
875         return -EIO;
876 
877     CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
878 
879     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
880     if (r)
881         return r;
882 
883     /* store the reply */
884     if (hostConfig != NULL)
885         memcpy((unsigned char*)hostConfig,
886                (unsigned char*)&priv->sme_reply.hostConfig,
887                sizeof(CsrWifiSmeHostConfig));
888 
889     unifi_trace(priv, UDBG4,
890                 "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n",
891                 r, priv->sme_reply.reply_status);
892 
893     return convert_sme_error(priv->sme_reply.reply_status);
894 #else
895     CsrResult status;
896     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
897     status = CsrWifiSmeMgtHostConfigGetReq(priv->smepriv, hostConfig);
898     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
899     return convert_sme_error(status);
900 #endif
901 }
902 
sme_mgt_sme_config_get(unifi_priv_t * priv,CsrWifiSmeStaConfig * staConfig,CsrWifiSmeDeviceConfig * deviceConfig)903 int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig)
904 {
905 #ifdef CSR_SME_USERSPACE
906     int r;
907 
908     if (priv->smepriv == NULL) {
909         unifi_error(priv, "sme_mgt_sme_config_get: invalid smepriv\n");
910         return -EIO;
911     }
912 
913     unifi_trace(priv, UDBG4, "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req -->\n");
914 
915     /* Common device config */
916     r = sme_init_request(priv);
917     if (r)
918         return -EIO;
919 
920     CsrWifiSmeSmeCommonConfigGetReqSend(0);
921     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
922     if (r)
923         return r;
924 
925     /* store the reply */
926     if (deviceConfig != NULL)
927         memcpy((unsigned char*)deviceConfig,
928                (unsigned char*)&priv->sme_reply.deviceConfig,
929                sizeof(CsrWifiSmeDeviceConfig));
930 
931     /* STA config */
932     r = sme_init_request(priv);
933     if (r)
934         return -EIO;
935 
936     CsrWifiSmeSmeStaConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
937     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
938     if (r)
939         return r;
940 
941     /* store the reply */
942     if (staConfig != NULL)
943         memcpy((unsigned char*)staConfig,
944                (unsigned char*)&priv->sme_reply.staConfig,
945                sizeof(CsrWifiSmeStaConfig));
946 
947     unifi_trace(priv, UDBG4,
948                 "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req <-- (r=%d status=%d)\n",
949                 r, priv->sme_reply.reply_status);
950 
951     return convert_sme_error(priv->sme_reply.reply_status);
952 #else
953     CsrResult status;
954     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
955     status = CsrWifiSmeMgtSmeConfigGetReq(priv->smepriv, staConfig);
956     status = CsrWifiSmeMgtDeviceConfigGetReq(priv->smepriv, deviceConfig);
957     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
958     return convert_sme_error(status);
959 #endif
960 }
961 
sme_mgt_coex_info_get(unifi_priv_t * priv,CsrWifiSmeCoexInfo * coexInfo)962 int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo)
963 {
964 #ifdef CSR_SME_USERSPACE
965     int r;
966 
967     if (priv->smepriv == NULL) {
968         unifi_error(priv, "sme_mgt_coex_info_get: invalid smepriv\n");
969         return -EIO;
970     }
971 
972     unifi_trace(priv, UDBG4, "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req -->\n");
973     r = sme_init_request(priv);
974     if (r)
975         return -EIO;
976 
977     CsrWifiSmeCoexInfoGetReqSend(0);
978 
979     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
980     if (r)
981         return r;
982 
983     /* store the reply */
984     if (coexInfo != NULL)
985         memcpy((unsigned char*)coexInfo,
986                (unsigned char*)&priv->sme_reply.coexInfo,
987                sizeof(CsrWifiSmeCoexInfo));
988 
989     unifi_trace(priv, UDBG4,
990                 "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req <-- (r=%d status=%d)\n",
991                 r, priv->sme_reply.reply_status);
992 
993     return convert_sme_error(priv->sme_reply.reply_status);
994 #else
995     CsrResult status;
996     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
997     status = CsrWifiSmeMgtCoexInfoGetReq(priv->smepriv, coexInfo);
998     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
999     return convert_sme_error(status);
1000 #endif
1001 }
1002 
1003 #ifdef CSR_SUPPORT_WEXT
1004 
sme_mgt_coex_config_get(unifi_priv_t * priv,CsrWifiSmeCoexConfig * coexConfig)1005 int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig)
1006 {
1007 #ifdef CSR_SME_USERSPACE
1008     int r;
1009 
1010     if (priv->smepriv == NULL) {
1011         unifi_error(priv, "sme_mgt_coex_config_get: invalid smepriv\n");
1012         return -EIO;
1013     }
1014 
1015     unifi_trace(priv, UDBG4, "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req -->\n");
1016     r = sme_init_request(priv);
1017     if (r)
1018         return -EIO;
1019 
1020     CsrWifiSmeCoexConfigGetReqSend(0);
1021 
1022     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1023     if (r)
1024         return r;
1025 
1026     /* store the reply */
1027     if (coexConfig != NULL)
1028         memcpy((unsigned char*)coexConfig,
1029                (unsigned char*)&priv->sme_reply.coexConfig,
1030                sizeof(CsrWifiSmeCoexConfig));
1031 
1032     unifi_trace(priv, UDBG4,
1033                 "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req <-- (r=%d status=%d)\n",
1034                 r, priv->sme_reply.reply_status);
1035 
1036     return convert_sme_error(priv->sme_reply.reply_status);
1037 #else
1038     CsrResult status;
1039     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1040     status = CsrWifiSmeMgtCoexConfigGetReq(priv->smepriv, coexConfig);
1041     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1042     return convert_sme_error(status);
1043 #endif
1044 }
1045 
sme_mgt_mib_config_get(unifi_priv_t * priv,CsrWifiSmeMibConfig * mibConfig)1046 int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
1047 {
1048 #ifdef CSR_SME_USERSPACE
1049     int r;
1050 
1051     if (priv->smepriv == NULL) {
1052         unifi_error(priv, "sme_mgt_mib_config_get: invalid smepriv\n");
1053         return -EIO;
1054     }
1055 
1056     unifi_trace(priv, UDBG4, "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req -->\n");
1057     r = sme_init_request(priv);
1058     if (r)
1059         return -EIO;
1060 
1061     CsrWifiSmeMibConfigGetReqSend(0);
1062 
1063     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1064     if (r)
1065         return r;
1066 
1067     /* store the reply */
1068     if (mibConfig != NULL)
1069         memcpy((unsigned char*)mibConfig,
1070                (unsigned char*)&priv->sme_reply.mibConfig,
1071                sizeof(CsrWifiSmeMibConfig));
1072 
1073     unifi_trace(priv, UDBG4,
1074                 "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req <-- (r=%d status=%d)\n",
1075                 r, priv->sme_reply.reply_status);
1076 
1077     return convert_sme_error(priv->sme_reply.reply_status);
1078 #else
1079     CsrResult status;
1080     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1081     status = CsrWifiSmeMgtMibConfigGetReq(priv->smepriv, mibConfig);
1082     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1083     return convert_sme_error(status);
1084 #endif
1085 }
1086 
sme_mgt_connection_info_get(unifi_priv_t * priv,CsrWifiSmeConnectionInfo * connectionInfo)1087 int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo)
1088 {
1089 #ifdef CSR_SME_USERSPACE
1090     int r;
1091 
1092     if (priv->smepriv == NULL) {
1093         unifi_error(priv, "sme_mgt_connection_info_get: invalid smepriv\n");
1094         return -EIO;
1095     }
1096 
1097     unifi_trace(priv, UDBG4, "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req -->\n");
1098     r = sme_init_request(priv);
1099     if (r)
1100         return -EIO;
1101 
1102     CsrWifiSmeConnectionInfoGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1103 
1104     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1105     if (r)
1106         return r;
1107 
1108     /* store the reply */
1109     if (connectionInfo != NULL)
1110         memcpy((unsigned char*)connectionInfo,
1111                (unsigned char*)&priv->sme_reply.connectionInfo,
1112                sizeof(CsrWifiSmeConnectionInfo));
1113 
1114     unifi_trace(priv, UDBG4,
1115                 "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req <-- (r=%d status=%d)\n",
1116                 r, priv->sme_reply.reply_status);
1117 
1118     return convert_sme_error(priv->sme_reply.reply_status);
1119 #else
1120     CsrResult status;
1121     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1122     status = CsrWifiSmeMgtConnectionInfoGetReq(priv->smepriv, connectionInfo);
1123     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1124     return convert_sme_error(status);
1125 #endif
1126 }
1127 
sme_mgt_connection_config_get(unifi_priv_t * priv,CsrWifiSmeConnectionConfig * connectionConfig)1128 int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig)
1129 {
1130 #ifdef CSR_SME_USERSPACE
1131     int r;
1132 
1133     if (priv->smepriv == NULL) {
1134         unifi_error(priv, "sme_mgt_connection_config_get: invalid smepriv\n");
1135         return -EIO;
1136     }
1137 
1138     unifi_trace(priv, UDBG4, "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req -->\n");
1139     r = sme_init_request(priv);
1140     if (r)
1141         return -EIO;
1142 
1143     CsrWifiSmeConnectionConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1144 
1145     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1146     if (r)
1147         return r;
1148 
1149     /* store the reply */
1150     if (connectionConfig != NULL)
1151         memcpy((unsigned char*)connectionConfig,
1152                (unsigned char*)&priv->sme_reply.connectionConfig,
1153                sizeof(CsrWifiSmeConnectionConfig));
1154 
1155     unifi_trace(priv, UDBG4,
1156                 "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req <-- (r=%d status=%d)\n",
1157                 r, priv->sme_reply.reply_status);
1158 
1159     return convert_sme_error(priv->sme_reply.reply_status);
1160 #else
1161     CsrResult status;
1162     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1163     status = CsrWifiSmeMgtConnectionConfigGetReq(priv->smepriv, connectionConfig);
1164     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1165     return convert_sme_error(status);
1166 #endif
1167 }
1168 
sme_mgt_connection_stats_get(unifi_priv_t * priv,CsrWifiSmeConnectionStats * connectionStats)1169 int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats)
1170 {
1171 #ifdef CSR_SME_USERSPACE
1172     int r;
1173 
1174     if (priv->smepriv == NULL) {
1175         unifi_error(priv, "sme_mgt_connection_stats_get: invalid smepriv\n");
1176         return -EIO;
1177     }
1178 
1179     unifi_trace(priv, UDBG4, "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req -->\n");
1180     r = sme_init_request(priv);
1181     if (r)
1182         return -EIO;
1183 
1184     CsrWifiSmeConnectionStatsGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1185 
1186     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1187     if (r)
1188         return r;
1189 
1190     /* store the reply */
1191     if (connectionStats != NULL)
1192         memcpy((unsigned char*)connectionStats,
1193                (unsigned char*)&priv->sme_reply.connectionStats,
1194                sizeof(CsrWifiSmeConnectionStats));
1195 
1196     unifi_trace(priv, UDBG4,
1197                 "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req <-- (r=%d status=%d)\n",
1198                 r, priv->sme_reply.reply_status);
1199 
1200     return convert_sme_error(priv->sme_reply.reply_status);
1201 #else
1202     CsrResult status;
1203     CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1204     status = CsrWifiSmeMgtConnectionStatsGetReq(priv->smepriv, connectionStats);
1205     CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1206     return convert_sme_error(status);
1207 #endif
1208 }
1209 
1210 #endif /* CSR_SUPPORT_WEXT */
1211 
sme_mgt_packet_filter_set(unifi_priv_t * priv)1212 int sme_mgt_packet_filter_set(unifi_priv_t *priv)
1213 {
1214 	CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }};
1215 	if (priv->smepriv == NULL) {
1216 		unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n");
1217 		return -EIO;
1218 	}
1219 	if (priv->packet_filters.arp_filter) {
1220 		ipAddress.a[0] = (priv->sta_ip_address      ) & 0xFF;
1221 		ipAddress.a[1] = (priv->sta_ip_address >>  8) & 0xFF;
1222 		ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF;
1223 		ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF;
1224 	}
1225 
1226 	unifi_trace(priv, UDBG5,
1227 		"sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n",
1228 		ipAddress.a[0], ipAddress.a[1],
1229 		ipAddress.a[2], ipAddress.a[3]);
1230 
1231 	/* Doesn't block for a confirm */
1232 	CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
1233 				     priv->packet_filters.tclas_ies_length,
1234 				     priv->filter_tclas_ies,
1235 				     priv->packet_filters.filter_mode,
1236 				     ipAddress);
1237 	return 0;
1238 }
1239 
sme_mgt_tspec(unifi_priv_t * priv,CsrWifiSmeListAction action,u32 tid,CsrWifiSmeDataBlock * tspec,CsrWifiSmeDataBlock * tclas)1240 int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action,
1241         u32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas)
1242 {
1243 	int r;
1244 
1245 	if (priv->smepriv == NULL) {
1246 		unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n");
1247 		return -EIO;
1248 	}
1249 
1250 	r = sme_init_request(priv);
1251 	if (r)
1252 		return -EIO;
1253 
1254 	CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
1255 			      action, tid, TRUE, 0,
1256 			      tspec->length, tspec->data,
1257 			      tclas->length, tclas->data);
1258 	r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1259 	if (r)
1260 		return r;
1261 
1262 	unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status);
1263 	return convert_sme_error(priv->sme_reply.reply_status);
1264 }
1265 
1266 
1267 
sme_sys_suspend(unifi_priv_t * priv)1268 int sme_sys_suspend(unifi_priv_t *priv)
1269 {
1270     int r;
1271     CsrResult csrResult;
1272 
1273     if (priv->smepriv == NULL) {
1274         unifi_error(priv, "sme_sys_suspend: invalid smepriv\n");
1275         return -EIO;
1276     }
1277 
1278     r = sme_init_request(priv);
1279     if (r)
1280         return -EIO;
1281 
1282     /* Suspend the SME, which MAY cause it to power down UniFi */
1283     CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
1284     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
1285     if (r) {
1286         /* No reply - forcibly power down in case the request wasn't processed */
1287         unifi_notice(priv,
1288                      "suspend: SME did not reply %s, ",
1289                      (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n");
1290 
1291         /* Leave power on for production test, though */
1292         if (!priv->ptest_mode) {
1293             /* Put UniFi to deep sleep, in case we can not power it off */
1294             CsrSdioClaim(priv->sdio);
1295             unifi_trace(priv, UDBG1, "Force deep sleep");
1296             csrResult = unifi_force_low_power_mode(priv->card);
1297 
1298             /* For WOL, the UniFi must stay powered */
1299             if (!priv->wol_suspend) {
1300                 unifi_trace(priv, UDBG1, "Power off\n");
1301                 CsrSdioPowerOff(priv->sdio);
1302             }
1303             CsrSdioRelease(priv->sdio);
1304         }
1305     }
1306 
1307     if (priv->wol_suspend) {
1308         unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n");
1309 
1310         /* Remove the IRQ, which also disables the card SDIO interrupt.
1311          * Disabling the card SDIO interrupt enables the PIO WOL source.
1312          * Removal of the of the handler ensures that in both SDIO and PIO cases
1313          * the card interrupt only wakes the host. The card will be polled
1314          * after resume to handle any pending data.
1315          */
1316         if (csr_sdio_linux_remove_irq(priv->sdio)) {
1317             unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
1318         }
1319 
1320         if (enable_wol == UNIFI_WOL_SDIO) {
1321             /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt,
1322              * it must be left enabled to wake-on-SDIO.
1323              */
1324             unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n");
1325 
1326             CsrSdioClaim(priv->sdio);
1327             csrResult = CsrSdioInterruptEnable(priv->sdio);
1328             CsrSdioRelease(priv->sdio);
1329 
1330             if (csrResult != CSR_RESULT_SUCCESS) {
1331                 unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult);
1332             }
1333         } else {
1334             unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n");
1335         }
1336 
1337         /* Prevent the BH thread from running during the suspend.
1338          * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause
1339          * the BH thread to be re-enabled and reinstall the ISR.
1340          */
1341         priv->bh_thread.block_thread = 1;
1342 
1343         unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH");
1344     }
1345 
1346     /* Consider UniFi to be uninitialised */
1347     priv->init_progress = UNIFI_INIT_NONE;
1348 
1349     unifi_trace(priv, UDBG1, "sme_sys_suspend: <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status);
1350     return convert_sme_error(priv->sme_reply.reply_status);
1351 }
1352 
1353 
sme_sys_resume(unifi_priv_t * priv)1354 int sme_sys_resume(unifi_priv_t *priv)
1355 {
1356     int r;
1357 
1358     unifi_trace(priv, UDBG1, "sme_sys_resume %s\n", priv->wol_suspend ? "warm" : "");
1359 
1360     if (priv->smepriv == NULL) {
1361         unifi_error(priv, "sme_sys_resume: invalid smepriv\n");
1362         return -EIO;
1363     }
1364 
1365     r = sme_init_request(priv);
1366     if (r)
1367         return -EIO;
1368 
1369     CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend);
1370 
1371     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
1372     if (r)
1373         unifi_notice(priv,
1374                 "resume: SME did not reply, return success anyway\n");
1375 
1376     return 0;
1377 }
1378 
1379 #ifdef CSR_SUPPORT_WEXT_AP
sme_ap_stop(unifi_priv_t * priv,u16 interface_tag)1380 int sme_ap_stop(unifi_priv_t *priv,u16 interface_tag)
1381 {
1382     int r;
1383 
1384     if (priv->smepriv == NULL) {
1385         unifi_error(priv, "sme_ap_stop: invalid smepriv\n");
1386         return -EIO;
1387     }
1388 
1389     r = sme_init_request(priv);
1390     if (r)
1391         return -EIO;
1392 
1393     CsrWifiNmeApStopReqSend(0,interface_tag);
1394 
1395     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1396     if (r)
1397         return r;
1398 
1399     unifi_trace(priv, UDBG4,
1400                 "sme_ap_stop <-- (r=%d status=%d)\n",
1401                 r, priv->sme_reply.reply_status);
1402     return convert_sme_error(priv->sme_reply.reply_status);
1403 
1404 }
1405 
sme_ap_start(unifi_priv_t * priv,u16 interface_tag,CsrWifiSmeApConfig_t * ap_config)1406 int sme_ap_start(unifi_priv_t *priv,u16 interface_tag,
1407                  CsrWifiSmeApConfig_t * ap_config)
1408 {
1409     int r;
1410     CsrWifiSmeApP2pGoConfig p2p_go_param;
1411     memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig));
1412 
1413     if (priv->smepriv == NULL) {
1414         unifi_error(priv, "sme_ap_start: invalid smepriv\n");
1415         return -EIO;
1416     }
1417 
1418     r = sme_init_request(priv);
1419     if (r)
1420         return -EIO;
1421 
1422     CsrWifiNmeApStartReqSend(0,interface_tag,CSR_WIFI_AP_TYPE_LEGACY,FALSE,
1423                              ap_config->ssid,1,ap_config->channel,
1424                              ap_config->credentials,ap_config->max_connections,
1425                              p2p_go_param,FALSE);
1426 
1427     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1428     if (r)
1429         return r;
1430 
1431     unifi_trace(priv, UDBG4,
1432                 "sme_ap_start <-- (r=%d status=%d)\n",
1433                 r, priv->sme_reply.reply_status);
1434     return convert_sme_error(priv->sme_reply.reply_status);
1435 }
1436 
sme_ap_config(unifi_priv_t * priv,CsrWifiSmeApMacConfig * ap_mac_config,CsrWifiNmeApConfig * group_security_config)1437 int sme_ap_config(unifi_priv_t *priv,
1438                   CsrWifiSmeApMacConfig *ap_mac_config,
1439                   CsrWifiNmeApConfig *group_security_config)
1440 {
1441     int r;
1442     CsrWifiSmeApP2pGoConfig p2p_go_param;
1443     memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig));
1444 
1445     if (priv->smepriv == NULL) {
1446         unifi_error(priv, "sme_ap_config: invalid smepriv\n");
1447         return -EIO;
1448     }
1449 
1450     r = sme_init_request(priv);
1451     if (r)
1452         return -EIO;
1453 
1454     CsrWifiNmeApConfigSetReqSend(0,*group_security_config,
1455                                  *ap_mac_config);
1456 
1457     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1458 	if (r)
1459 		return r;
1460 
1461     unifi_trace(priv, UDBG4,
1462                 "sme_ap_config <-- (r=%d status=%d)\n",
1463                 r, priv->sme_reply.reply_status);
1464     return convert_sme_error(priv->sme_reply.reply_status);
1465 }
1466 #endif
1467