Root/drivers/staging/csr/sme_blocking.c

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 asyncronous
22 * requests to the SME.
23 *
24 * Before calling an asyncronous 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
87static int
88sme_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
111void
112uf_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
138void
139uf_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
172static int
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
223int 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
263int 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
277    /* Stop the SME */
278    CsrWifiSmeWifiOffReqSend(0);
279
280    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
281    if (r) {
282        return r;
283    }
284
285    unifi_trace(priv, UDBG4,
286                "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n",
287                r, priv->sme_reply.reply_status);
288    return convert_sme_error(priv->sme_reply.reply_status);
289
290} /* sme_mgt_wifi_off */
291
292int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key,
293        CsrWifiSmeListAction action)
294{
295    int r;
296
297    if (priv->smepriv == NULL) {
298        unifi_error(priv, "sme_mgt_key: invalid smepriv\n");
299        return -EIO;
300    }
301
302    r = sme_init_request(priv);
303    if (r) {
304        return -EIO;
305    }
306
307    CsrWifiSmeKeyReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, *sme_key);
308
309    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
310    if (r) {
311        return r;
312    }
313
314    return convert_sme_error(priv->sme_reply.reply_status);
315}
316
317
318int sme_mgt_scan_full(unifi_priv_t *priv,
319        CsrWifiSsid *specific_ssid,
320        int num_channels,
321        unsigned char *channel_list)
322{
323    CsrWifiMacAddress bcastAddress = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
324    u8 is_active = (num_channels > 0) ? TRUE : FALSE;
325    int r;
326
327    if (priv->smepriv == NULL) {
328        unifi_error(priv, "sme_mgt_scan_full: invalid smepriv\n");
329        return -EIO;
330    }
331
332    unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n");
333
334    r = sme_init_request(priv);
335    if (r) {
336        return -EIO;
337    }
338
339    /* If a channel list is provided, do an active scan */
340    if (is_active) {
341        unifi_trace(priv, UDBG1,
342                    "channel list - num_channels: %d, active scan\n",
343                    num_channels);
344    }
345
346    CsrWifiSmeScanFullReqSend(0,
347                              specific_ssid->length?1:0, /* 0 or 1 SSIDS */
348                              specific_ssid,
349                              bcastAddress,
350                              is_active,
351                              CSR_WIFI_SME_BSS_TYPE_ANY_BSS,
352                              CSR_WIFI_SME_SCAN_TYPE_ALL,
353                              (u16)num_channels, channel_list,
354                              0, NULL);
355
356    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
357    if (r) {
358        return r;
359    }
360
361    unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status);
362    if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE) {
363        return 0; /* initial scan already underway */
364    } else {
365        return convert_sme_error(priv->sme_reply.reply_status);
366    }
367}
368
369
370int sme_mgt_scan_results_get_async(unifi_priv_t *priv,
371        struct iw_request_info *info,
372        char *scan_results,
373        long scan_results_len)
374{
375    u16 scan_result_list_count;
376    CsrWifiSmeScanResult *scan_result_list;
377    CsrWifiSmeScanResult *scan_result;
378    int r;
379    int i;
380    char *current_ev = scan_results;
381
382    if (priv->smepriv == NULL) {
383        unifi_error(priv, "sme_mgt_scan_results_get_async: invalid smepriv\n");
384        return -EIO;
385    }
386
387    r = sme_init_request(priv);
388    if (r) {
389        return -EIO;
390    }
391
392    CsrWifiSmeScanResultsGetReqSend(0);
393    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
394    if (r) {
395        return r;
396    }
397
398    scan_result_list_count = priv->sme_reply.reply_scan_results_count;
399    scan_result_list = priv->sme_reply.reply_scan_results;
400    unifi_trace(priv, UDBG2,
401                "scan_results: Scan returned %d, numElements=%d\n",
402                r, scan_result_list_count);
403
404    /* OK, now we have the scan results */
405    for (i = 0; i < scan_result_list_count; ++i) {
406        scan_result = &scan_result_list[i];
407
408        unifi_trace(priv, UDBG2, "Scan Result: %.*s\n",
409                    scan_result->ssid.length,
410                    scan_result->ssid.ssid);
411
412        r = unifi_translate_scan(priv->netdev[0], info,
413                                 current_ev,
414                                 scan_results + scan_results_len,
415                                 scan_result, i+1);
416
417        if (r < 0) {
418            kfree(scan_result_list);
419            priv->sme_reply.reply_scan_results_count = 0;
420            priv->sme_reply.reply_scan_results = NULL;
421            return r;
422        }
423
424        current_ev += r;
425    }
426
427    /*
428     * Free the scan results allocated in unifi_mgt_scan_results_get_cfm()
429     * and invalidate the reply_scan_results to avoid re-using
430     * the freed pointers.
431     */
432    kfree(scan_result_list);
433    priv->sme_reply.reply_scan_results_count = 0;
434    priv->sme_reply.reply_scan_results = NULL;
435
436    unifi_trace(priv, UDBG2,
437                "scan_results: Scan translated to %d bytes\n",
438                current_ev - scan_results);
439    return (current_ev - scan_results);
440}
441
442
443int sme_mgt_connect(unifi_priv_t *priv)
444{
445    int r;
446
447    if (priv->smepriv == NULL) {
448        unifi_error(priv, "sme_mgt_connect: invalid smepriv\n");
449        return -EIO;
450    }
451
452    unifi_trace(priv, UDBG2, "sme_mgt_connect: %.*s\n",
453                priv->connection_config.ssid.length,
454                priv->connection_config.ssid.ssid);
455
456    r = sme_init_request(priv);
457    if (r) {
458        return -EIO;
459    }
460
461    CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config);
462    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
463    if (r) {
464        return r;
465    }
466
467    if (priv->sme_reply.reply_status) {
468        unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n",
469                    priv->sme_reply.reply_status);
470    }
471
472    return convert_sme_error(priv->sme_reply.reply_status);
473}
474
475
476int sme_mgt_disconnect(unifi_priv_t *priv)
477{
478    int r;
479
480    if (priv->smepriv == NULL) {
481        unifi_error(priv, "sme_mgt_disconnect: invalid smepriv\n");
482        return -EIO;
483    }
484
485    r = sme_init_request(priv);
486    if (r) {
487        return -EIO;
488    }
489
490    CsrWifiSmeDisconnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
491    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
492    if (r) {
493        return r;
494    }
495
496    unifi_trace(priv, UDBG4, "sme_mgt_disconnect: <-- (status=%d)\n", priv->sme_reply.reply_status);
497    return convert_sme_error(priv->sme_reply.reply_status);
498}
499
500
501int sme_mgt_pmkid(unifi_priv_t *priv,
502        CsrWifiSmeListAction action,
503        CsrWifiSmePmkidList *pmkid_list)
504{
505    int r;
506
507    if (priv->smepriv == NULL) {
508        unifi_error(priv, "sme_mgt_pmkid: invalid smepriv\n");
509        return -EIO;
510    }
511
512    r = sme_init_request(priv);
513    if (r) {
514        return -EIO;
515    }
516
517    CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action,
518                        pmkid_list->pmkidsCount, pmkid_list->pmkids);
519    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
520    if (r) {
521        return r;
522    }
523
524    unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status);
525    return convert_sme_error(priv->sme_reply.reply_status);
526}
527
528
529int sme_mgt_mib_get(unifi_priv_t *priv,
530        unsigned char *varbind, int *length)
531{
532    int r;
533
534    if (priv->smepriv == NULL) {
535        unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n");
536        return -EIO;
537    }
538
539    r = sme_init_request(priv);
540    if (r) {
541        return -EIO;
542    }
543
544    priv->mib_cfm_buffer = varbind;
545    priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH;
546
547    CsrWifiSmeMibGetReqSend(0, *length, varbind);
548    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
549    if (r) {
550        priv->mib_cfm_buffer_length = 0;
551        priv->mib_cfm_buffer = NULL;
552        return r;
553    }
554
555    *length = priv->mib_cfm_buffer_length;
556
557    priv->mib_cfm_buffer_length = 0;
558    priv->mib_cfm_buffer = NULL;
559    unifi_trace(priv, UDBG4, "sme_mgt_mib_get: <-- (status=%d)\n", priv->sme_reply.reply_status);
560    return convert_sme_error(priv->sme_reply.reply_status);
561}
562
563int sme_mgt_mib_set(unifi_priv_t *priv,
564        unsigned char *varbind, int length)
565{
566    int r;
567
568    if (priv->smepriv == NULL) {
569        unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n");
570        return -EIO;
571    }
572
573    r = sme_init_request(priv);
574    if (r) {
575        return -EIO;
576    }
577
578    CsrWifiSmeMibSetReqSend(0, length, varbind);
579    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
580    if (r) {
581        return r;
582    }
583
584    unifi_trace(priv, UDBG4, "sme_mgt_mib_set: <-- (status=%d)\n", priv->sme_reply.reply_status);
585    return convert_sme_error(priv->sme_reply.reply_status);
586}
587
588#endif /* CSR_SUPPORT_WEXT */
589
590int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig)
591{
592#ifdef CSR_SME_USERSPACE
593    int r;
594
595    if (priv->smepriv == NULL) {
596        unifi_error(priv, "sme_mgt_set_value_async: invalid smepriv\n");
597        return -EIO;
598    }
599
600    r = sme_init_request(priv);
601    if (r) {
602        return -EIO;
603    }
604
605    CsrWifiSmePowerConfigSetReqSend(0, *powerConfig);
606
607    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
608    if (r) {
609        return r;
610    }
611
612    unifi_trace(priv, UDBG4,
613                "sme_mgt_set_value_async: unifi_mgt_set_value_req <-- (r=%d status=%d)\n",
614                r, priv->sme_reply.reply_status);
615    return convert_sme_error(priv->sme_reply.reply_status);
616#else
617    CsrResult status;
618    if (priv->smepriv == NULL) {
619        unifi_error(priv, "sme_mgt_set_value: invalid smepriv\n");
620        return -EIO;
621    }
622    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
623    status = CsrWifiSmeMgtPowerConfigSetReq(priv->smepriv, *powerConfig);
624    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
625    return convert_sme_error(status);
626#endif
627}
628
629int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig)
630{
631#ifdef CSR_SME_USERSPACE
632    int r;
633
634    if (priv->smepriv == NULL) {
635        unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n");
636        return -EIO;
637    }
638
639    r = sme_init_request(priv);
640    if (r) {
641        return -EIO;
642    }
643
644    CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig);
645    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
646    if (r) {
647        return r;
648    }
649    unifi_trace(priv, UDBG4,
650                "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n",
651                r, priv->sme_reply.reply_status);
652
653    r = sme_init_request(priv);
654    if (r) {
655        return -EIO;
656    }
657
658    CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig);
659    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
660    if (r) {
661        return r;
662    }
663
664    unifi_trace(priv, UDBG4,
665                "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n",
666                r, priv->sme_reply.reply_status);
667
668    return convert_sme_error(priv->sme_reply.reply_status);
669#else
670    CsrResult status;
671    if (priv->smepriv == NULL) {
672        unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n");
673        return -EIO;
674    }
675    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
676    status = CsrWifiSmeMgtSmeConfigSetReq(priv->smepriv, *staConfig);
677    status = CsrWifiSmeMgtDeviceConfigSetReq(priv->smepriv, *deviceConfig);
678    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
679    return convert_sme_error(status);
680#endif
681}
682
683#ifdef CSR_SUPPORT_WEXT
684
685int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
686{
687#ifdef CSR_SME_USERSPACE
688    int r;
689
690    if (priv->smepriv == NULL) {
691        unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n");
692        return -EIO;
693    }
694
695    r = sme_init_request(priv);
696    if (r) {
697        return -EIO;
698    }
699
700    CsrWifiSmeMibConfigSetReqSend(0, *mibConfig);
701
702    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
703    if (r) {
704        return r;
705    }
706
707    unifi_trace(priv, UDBG4,
708                "sme_mgt_mib_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
709                r, priv->sme_reply.reply_status);
710    return convert_sme_error(priv->sme_reply.reply_status);
711#else
712    CsrResult status;
713    if (priv->smepriv == NULL) {
714        unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n");
715        return -EIO;
716    }
717    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
718    status = CsrWifiSmeMgtMibConfigSetReq(priv->smepriv, *mibConfig);
719    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
720    return convert_sme_error(status);
721#endif
722}
723
724int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig)
725{
726#ifdef CSR_SME_USERSPACE
727    int r;
728
729    if (priv->smepriv == NULL) {
730        unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n");
731        return -EIO;
732    }
733
734    r = sme_init_request(priv);
735    if (r) {
736        return -EIO;
737    }
738
739    CsrWifiSmeCoexConfigSetReqSend(0, *coexConfig);
740
741    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
742    if (r) {
743        return r;
744    }
745
746    unifi_trace(priv, UDBG4,
747                "sme_mgt_coex_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
748                r, priv->sme_reply.reply_status);
749    return convert_sme_error(priv->sme_reply.reply_status);
750#else
751    CsrResult status;
752    if (priv->smepriv == NULL) {
753        unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n");
754        return -EIO;
755    }
756    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
757    status = CsrWifiSmeMgtCoexConfigSetReq(priv->smepriv, *coexConfig);
758    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
759    return convert_sme_error(status);
760#endif
761}
762
763#endif /* CSR_SUPPORT_WEXT */
764
765int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig)
766{
767#ifdef CSR_SME_USERSPACE
768    int r;
769
770    if (priv->smepriv == NULL) {
771        unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n");
772        return -EIO;
773    }
774
775    r = sme_init_request(priv);
776    if (r) {
777        return -EIO;
778    }
779
780    CsrWifiSmeHostConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *hostConfig);
781
782    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
783    if (r) {
784        return r;
785    }
786
787    unifi_trace(priv, UDBG4,
788                "sme_mgt_host_config_set: unifi_mgt_set_host_config_req <-- (r=%d status=%d)\n",
789                r, priv->sme_reply.reply_status);
790    return convert_sme_error(priv->sme_reply.reply_status);
791#else
792    CsrResult status;
793    if (priv->smepriv == NULL) {
794        unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n");
795        return -EIO;
796    }
797    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
798    status = CsrWifiSmeMgtHostConfigSetReq(priv->smepriv, *hostConfig);
799    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
800    return convert_sme_error(status);
801#endif
802}
803
804#ifdef CSR_SUPPORT_WEXT
805
806int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions)
807{
808#ifdef CSR_SME_USERSPACE
809    int r;
810
811    if (priv->smepriv == NULL) {
812        unifi_error(priv, "sme_mgt_versions_get: invalid smepriv\n");
813        return -EIO;
814    }
815
816    unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n");
817    r = sme_init_request(priv);
818    if (r) {
819        return -EIO;
820    }
821
822    CsrWifiSmeVersionsGetReqSend(0);
823
824    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
825    if (r) {
826        return r;
827    }
828
829    /* store the reply */
830    if (versions != NULL) {
831        memcpy((unsigned char*)versions,
832               (unsigned char*)&priv->sme_reply.versions,
833               sizeof(CsrWifiSmeVersions));
834    }
835
836    unifi_trace(priv, UDBG4,
837                "sme_mgt_versions_get: unifi_mgt_versions_get_req <-- (r=%d status=%d)\n",
838                r, priv->sme_reply.reply_status);
839
840    return convert_sme_error(priv->sme_reply.reply_status);
841#else
842    CsrResult status;
843    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
844    status = CsrWifiSmeMgtVersionsGetReq(priv->smepriv, versions);
845    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
846    return convert_sme_error(status);
847#endif
848}
849
850#endif /* CSR_SUPPORT_WEXT */
851
852int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig)
853{
854#ifdef CSR_SME_USERSPACE
855    int r;
856
857    if (priv->smepriv == NULL) {
858        unifi_error(priv, "sme_mgt_power_config_get: invalid smepriv\n");
859        return -EIO;
860    }
861
862    unifi_trace(priv, UDBG4, "sme_mgt_power_config_get: unifi_mgt_power_config_req -->\n");
863    r = sme_init_request(priv);
864    if (r) {
865        return -EIO;
866    }
867
868    CsrWifiSmePowerConfigGetReqSend(0);
869
870    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
871    if (r) {
872        return r;
873    }
874
875    /* store the reply */
876    if (powerConfig != NULL) {
877        memcpy((unsigned char*)powerConfig,
878               (unsigned char*)&priv->sme_reply.powerConfig,
879               sizeof(CsrWifiSmePowerConfig));
880    }
881
882    unifi_trace(priv, UDBG4,
883                "sme_mgt_get_versions: unifi_mgt_power_config_req <-- (r=%d status=%d)\n",
884                r, priv->sme_reply.reply_status);
885
886    return convert_sme_error(priv->sme_reply.reply_status);
887#else
888    CsrResult status;
889    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
890    status = CsrWifiSmeMgtPowerConfigGetReq(priv->smepriv, powerConfig);
891    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
892    return convert_sme_error(status);
893#endif
894}
895
896int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig)
897{
898#ifdef CSR_SME_USERSPACE
899    int r;
900
901    if (priv->smepriv == NULL) {
902        unifi_error(priv, "sme_mgt_host_config_get: invalid smepriv\n");
903        return -EIO;
904    }
905
906    unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n");
907    r = sme_init_request(priv);
908    if (r) {
909        return -EIO;
910    }
911
912    CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
913
914    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
915    if (r) {
916        return r;
917    }
918
919    /* store the reply */
920    if (hostConfig != NULL) {
921        memcpy((unsigned char*)hostConfig,
922               (unsigned char*)&priv->sme_reply.hostConfig,
923               sizeof(CsrWifiSmeHostConfig));
924    }
925
926    unifi_trace(priv, UDBG4,
927                "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n",
928                r, priv->sme_reply.reply_status);
929
930    return convert_sme_error(priv->sme_reply.reply_status);
931#else
932    CsrResult status;
933    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
934    status = CsrWifiSmeMgtHostConfigGetReq(priv->smepriv, hostConfig);
935    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
936    return convert_sme_error(status);
937#endif
938}
939
940int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig)
941{
942#ifdef CSR_SME_USERSPACE
943    int r;
944
945    if (priv->smepriv == NULL) {
946        unifi_error(priv, "sme_mgt_sme_config_get: invalid smepriv\n");
947        return -EIO;
948    }
949
950    unifi_trace(priv, UDBG4, "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req -->\n");
951
952    /* Common device config */
953    r = sme_init_request(priv);
954    if (r) {
955        return -EIO;
956    }
957
958    CsrWifiSmeSmeCommonConfigGetReqSend(0);
959    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
960    if (r) {
961        return r;
962    }
963
964    /* store the reply */
965    if (deviceConfig != NULL) {
966        memcpy((unsigned char*)deviceConfig,
967               (unsigned char*)&priv->sme_reply.deviceConfig,
968               sizeof(CsrWifiSmeDeviceConfig));
969    }
970
971    /* STA config */
972    r = sme_init_request(priv);
973    if (r) {
974        return -EIO;
975    }
976
977    CsrWifiSmeSmeStaConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
978    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
979    if (r) {
980        return r;
981    }
982
983    /* store the reply */
984    if (staConfig != NULL) {
985        memcpy((unsigned char*)staConfig,
986               (unsigned char*)&priv->sme_reply.staConfig,
987               sizeof(CsrWifiSmeStaConfig));
988    }
989
990    unifi_trace(priv, UDBG4,
991                "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req <-- (r=%d status=%d)\n",
992                r, priv->sme_reply.reply_status);
993
994    return convert_sme_error(priv->sme_reply.reply_status);
995#else
996    CsrResult status;
997    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
998    status = CsrWifiSmeMgtSmeConfigGetReq(priv->smepriv, staConfig);
999    status = CsrWifiSmeMgtDeviceConfigGetReq(priv->smepriv, deviceConfig);
1000    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1001    return convert_sme_error(status);
1002#endif
1003}
1004
1005int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo)
1006{
1007#ifdef CSR_SME_USERSPACE
1008    int r;
1009
1010    if (priv->smepriv == NULL) {
1011        unifi_error(priv, "sme_mgt_coex_info_get: invalid smepriv\n");
1012        return -EIO;
1013    }
1014
1015    unifi_trace(priv, UDBG4, "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req -->\n");
1016    r = sme_init_request(priv);
1017    if (r) {
1018        return -EIO;
1019    }
1020
1021    CsrWifiSmeCoexInfoGetReqSend(0);
1022
1023    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1024    if (r) {
1025        return r;
1026    }
1027
1028    /* store the reply */
1029    if (coexInfo != NULL) {
1030        memcpy((unsigned char*)coexInfo,
1031               (unsigned char*)&priv->sme_reply.coexInfo,
1032               sizeof(CsrWifiSmeCoexInfo));
1033    }
1034
1035    unifi_trace(priv, UDBG4,
1036                "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req <-- (r=%d status=%d)\n",
1037                r, priv->sme_reply.reply_status);
1038
1039    return convert_sme_error(priv->sme_reply.reply_status);
1040#else
1041    CsrResult status;
1042    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1043    status = CsrWifiSmeMgtCoexInfoGetReq(priv->smepriv, coexInfo);
1044    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1045    return convert_sme_error(status);
1046#endif
1047}
1048
1049#ifdef CSR_SUPPORT_WEXT
1050
1051int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig)
1052{
1053#ifdef CSR_SME_USERSPACE
1054    int r;
1055
1056    if (priv->smepriv == NULL) {
1057        unifi_error(priv, "sme_mgt_coex_config_get: invalid smepriv\n");
1058        return -EIO;
1059    }
1060
1061    unifi_trace(priv, UDBG4, "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req -->\n");
1062    r = sme_init_request(priv);
1063    if (r) {
1064        return -EIO;
1065    }
1066
1067    CsrWifiSmeCoexConfigGetReqSend(0);
1068
1069    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1070    if (r) {
1071        return r;
1072    }
1073
1074    /* store the reply */
1075    if (coexConfig != NULL) {
1076        memcpy((unsigned char*)coexConfig,
1077               (unsigned char*)&priv->sme_reply.coexConfig,
1078               sizeof(CsrWifiSmeCoexConfig));
1079    }
1080
1081    unifi_trace(priv, UDBG4,
1082                "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req <-- (r=%d status=%d)\n",
1083                r, priv->sme_reply.reply_status);
1084
1085    return convert_sme_error(priv->sme_reply.reply_status);
1086#else
1087    CsrResult status;
1088    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1089    status = CsrWifiSmeMgtCoexConfigGetReq(priv->smepriv, coexConfig);
1090    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1091    return convert_sme_error(status);
1092#endif
1093}
1094
1095int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
1096{
1097#ifdef CSR_SME_USERSPACE
1098    int r;
1099
1100    if (priv->smepriv == NULL) {
1101        unifi_error(priv, "sme_mgt_mib_config_get: invalid smepriv\n");
1102        return -EIO;
1103    }
1104
1105    unifi_trace(priv, UDBG4, "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req -->\n");
1106    r = sme_init_request(priv);
1107    if (r) {
1108        return -EIO;
1109    }
1110
1111    CsrWifiSmeMibConfigGetReqSend(0);
1112
1113    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1114    if (r) {
1115        return r;
1116    }
1117
1118    /* store the reply */
1119    if (mibConfig != NULL) {
1120        memcpy((unsigned char*)mibConfig,
1121               (unsigned char*)&priv->sme_reply.mibConfig,
1122               sizeof(CsrWifiSmeMibConfig));
1123    }
1124
1125    unifi_trace(priv, UDBG4,
1126                "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req <-- (r=%d status=%d)\n",
1127                r, priv->sme_reply.reply_status);
1128
1129    return convert_sme_error(priv->sme_reply.reply_status);
1130#else
1131    CsrResult status;
1132    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1133    status = CsrWifiSmeMgtMibConfigGetReq(priv->smepriv, mibConfig);
1134    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1135    return convert_sme_error(status);
1136#endif
1137}
1138
1139int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo)
1140{
1141#ifdef CSR_SME_USERSPACE
1142    int r;
1143
1144    if (priv->smepriv == NULL) {
1145        unifi_error(priv, "sme_mgt_connection_info_get: invalid smepriv\n");
1146        return -EIO;
1147    }
1148
1149    unifi_trace(priv, UDBG4, "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req -->\n");
1150    r = sme_init_request(priv);
1151    if (r) {
1152        return -EIO;
1153    }
1154
1155    CsrWifiSmeConnectionInfoGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1156
1157    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1158    if (r) {
1159        return r;
1160    }
1161
1162    /* store the reply */
1163    if (connectionInfo != NULL) {
1164        memcpy((unsigned char*)connectionInfo,
1165               (unsigned char*)&priv->sme_reply.connectionInfo,
1166               sizeof(CsrWifiSmeConnectionInfo));
1167    }
1168
1169    unifi_trace(priv, UDBG4,
1170                "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req <-- (r=%d status=%d)\n",
1171                r, priv->sme_reply.reply_status);
1172
1173    return convert_sme_error(priv->sme_reply.reply_status);
1174#else
1175    CsrResult status;
1176    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1177    status = CsrWifiSmeMgtConnectionInfoGetReq(priv->smepriv, connectionInfo);
1178    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1179    return convert_sme_error(status);
1180#endif
1181}
1182
1183int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig)
1184{
1185#ifdef CSR_SME_USERSPACE
1186    int r;
1187
1188    if (priv->smepriv == NULL) {
1189        unifi_error(priv, "sme_mgt_connection_config_get: invalid smepriv\n");
1190        return -EIO;
1191    }
1192
1193    unifi_trace(priv, UDBG4, "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req -->\n");
1194    r = sme_init_request(priv);
1195    if (r) {
1196        return -EIO;
1197    }
1198
1199    CsrWifiSmeConnectionConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1200
1201    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1202    if (r) {
1203        return r;
1204    }
1205
1206    /* store the reply */
1207    if (connectionConfig != NULL) {
1208        memcpy((unsigned char*)connectionConfig,
1209               (unsigned char*)&priv->sme_reply.connectionConfig,
1210               sizeof(CsrWifiSmeConnectionConfig));
1211    }
1212
1213    unifi_trace(priv, UDBG4,
1214                "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req <-- (r=%d status=%d)\n",
1215                r, priv->sme_reply.reply_status);
1216
1217    return convert_sme_error(priv->sme_reply.reply_status);
1218#else
1219    CsrResult status;
1220    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1221    status = CsrWifiSmeMgtConnectionConfigGetReq(priv->smepriv, connectionConfig);
1222    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1223    return convert_sme_error(status);
1224#endif
1225}
1226
1227int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats)
1228{
1229#ifdef CSR_SME_USERSPACE
1230    int r;
1231
1232    if (priv->smepriv == NULL) {
1233        unifi_error(priv, "sme_mgt_connection_stats_get: invalid smepriv\n");
1234        return -EIO;
1235    }
1236
1237    unifi_trace(priv, UDBG4, "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req -->\n");
1238    r = sme_init_request(priv);
1239    if (r) {
1240        return -EIO;
1241    }
1242
1243    CsrWifiSmeConnectionStatsGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1244
1245    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1246    if (r) {
1247        return r;
1248    }
1249
1250    /* store the reply */
1251    if (connectionStats != NULL) {
1252        memcpy((unsigned char*)connectionStats,
1253               (unsigned char*)&priv->sme_reply.connectionStats,
1254               sizeof(CsrWifiSmeConnectionStats));
1255    }
1256
1257    unifi_trace(priv, UDBG4,
1258                "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req <-- (r=%d status=%d)\n",
1259                r, priv->sme_reply.reply_status);
1260
1261    return convert_sme_error(priv->sme_reply.reply_status);
1262#else
1263    CsrResult status;
1264    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1265    status = CsrWifiSmeMgtConnectionStatsGetReq(priv->smepriv, connectionStats);
1266    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1267    return convert_sme_error(status);
1268#endif
1269}
1270
1271#endif /* CSR_SUPPORT_WEXT */
1272
1273int sme_mgt_packet_filter_set(unifi_priv_t *priv)
1274{
1275    CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }};
1276    if (priv->smepriv == NULL) {
1277        unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n");
1278        return -EIO;
1279    }
1280    if (priv->packet_filters.arp_filter) {
1281        ipAddress.a[0] = (priv->sta_ip_address ) & 0xFF;
1282        ipAddress.a[1] = (priv->sta_ip_address >> 8) & 0xFF;
1283        ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF;
1284        ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF;
1285    }
1286
1287    unifi_trace(priv, UDBG5,
1288                "sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n",
1289                ipAddress.a[0], ipAddress.a[1],
1290                ipAddress.a[2], ipAddress.a[3]);
1291
1292    /* Doesn't block for a confirm */
1293    CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
1294                                     priv->packet_filters.tclas_ies_length,
1295                                     priv->filter_tclas_ies,
1296                                     priv->packet_filters.filter_mode,
1297                                     ipAddress);
1298    return 0;
1299}
1300
1301int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action,
1302        u32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas)
1303{
1304    int r;
1305
1306    if (priv->smepriv == NULL) {
1307        unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n");
1308        return -EIO;
1309    }
1310
1311    r = sme_init_request(priv);
1312    if (r) {
1313        return -EIO;
1314    }
1315
1316    CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
1317                           action, tid, TRUE, 0,
1318                           tspec->length, tspec->data,
1319                           tclas->length, tclas->data);
1320    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1321    if (r) {
1322        return r;
1323    }
1324
1325    unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status);
1326    return convert_sme_error(priv->sme_reply.reply_status);
1327}
1328
1329
1330
1331int sme_sys_suspend(unifi_priv_t *priv)
1332{
1333    int r;
1334    CsrResult csrResult;
1335
1336    if (priv->smepriv == NULL) {
1337        unifi_error(priv, "sme_sys_suspend: invalid smepriv\n");
1338        return -EIO;
1339    }
1340
1341    r = sme_init_request(priv);
1342    if (r) {
1343        return -EIO;
1344    }
1345
1346    /* Suspend the SME, which MAY cause it to power down UniFi */
1347    CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
1348    r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
1349    if (r) {
1350        /* No reply - forcibly power down in case the request wasn't processed */
1351        unifi_notice(priv,
1352                     "suspend: SME did not reply %s, ",
1353                     (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n");
1354
1355        /* Leave power on for production test, though */
1356        if (!priv->ptest_mode) {
1357            /* Put UniFi to deep sleep, in case we can not power it off */
1358            CsrSdioClaim(priv->sdio);
1359            unifi_trace(priv, UDBG1, "Force deep sleep");
1360            csrResult = unifi_force_low_power_mode(priv->card);
1361
1362            /* For WOL, the UniFi must stay powered */
1363            if (!priv->wol_suspend) {
1364                unifi_trace(priv, UDBG1, "Power off\n");
1365                CsrSdioPowerOff(priv->sdio);
1366            }
1367            CsrSdioRelease(priv->sdio);
1368        }
1369    }
1370
1371    if (priv->wol_suspend) {
1372        unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n");
1373
1374        /* Remove the IRQ, which also disables the card SDIO interrupt.
1375         * Disabling the card SDIO interrupt enables the PIO WOL source.
1376         * Removal of the of the handler ensures that in both SDIO and PIO cases
1377         * the card interrupt only wakes the host. The card will be polled
1378         * after resume to handle any pending data.
1379         */
1380        if (csr_sdio_linux_remove_irq(priv->sdio)) {
1381            unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
1382        }
1383
1384        if (enable_wol == UNIFI_WOL_SDIO) {
1385            /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt,
1386             * it must be left enabled to wake-on-SDIO.
1387             */
1388            unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n");
1389
1390            CsrSdioClaim(priv->sdio);
1391            csrResult = CsrSdioInterruptEnable(priv->sdio);
1392            CsrSdioRelease(priv->sdio);
1393
1394            if (csrResult != CSR_RESULT_SUCCESS) {
1395                unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult);
1396            }
1397        } else {
1398            unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n");
1399        }
1400
1401        /* Prevent the BH thread from running during the suspend.
1402         * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause
1403         * the BH thread to be re-enabled and reinstall the ISR.
1404         */
1405        priv->bh_thread.block_thread = 1;
1406
1407        unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH");
1408    }
1409
1410    /* Consider UniFi to be uninitialised */
1411    priv->init_progress = UNIFI_INIT_NONE;
1412
1413    unifi_trace(priv, UDBG1, "sme_sys_suspend: <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status);
1414    return convert_sme_error(priv->sme_reply.reply_status);
1415}
1416
1417
1418int sme_sys_resume(unifi_priv_t *priv)
1419{
1420    int r;
1421
1422    unifi_trace(priv, UDBG1, "sme_sys_resume %s\n", priv->wol_suspend ? "warm" : "");
1423
1424    if (priv->smepriv == NULL) {
1425        unifi_error(priv, "sme_sys_resume: invalid smepriv\n");
1426        return -EIO;
1427    }
1428
1429    r = sme_init_request(priv);
1430    if (r) {
1431        return -EIO;
1432    }
1433
1434    CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend);
1435
1436    r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
1437    if (r) {
1438        unifi_notice(priv,
1439                "resume: SME did not reply, return success anyway\n");
1440    }
1441
1442    return 0;
1443}
1444
1445#ifdef CSR_SUPPORT_WEXT_AP
1446int sme_ap_stop(unifi_priv_t *priv,u16 interface_tag)
1447{
1448    int r;
1449
1450    if (priv->smepriv == NULL) {
1451        unifi_error(priv, "sme_ap_stop: invalid smepriv\n");
1452        return -EIO;
1453    }
1454
1455    r = sme_init_request(priv);
1456    if (r) {
1457        return -EIO;
1458    }
1459
1460    CsrWifiNmeApStopReqSend(0,interface_tag);
1461
1462    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1463    if (r) {
1464        return r;
1465    }
1466
1467    unifi_trace(priv, UDBG4,
1468                "sme_ap_stop <-- (r=%d status=%d)\n",
1469                r, priv->sme_reply.reply_status);
1470    return convert_sme_error(priv->sme_reply.reply_status);
1471
1472}
1473
1474int sme_ap_start(unifi_priv_t *priv,u16 interface_tag,
1475                 CsrWifiSmeApConfig_t * ap_config)
1476{
1477    int r;
1478    CsrWifiSmeApP2pGoConfig p2p_go_param;
1479    memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig));
1480
1481    if (priv->smepriv == NULL) {
1482        unifi_error(priv, "sme_ap_start: invalid smepriv\n");
1483        return -EIO;
1484    }
1485
1486    r = sme_init_request(priv);
1487    if (r) {
1488        return -EIO;
1489    }
1490
1491    CsrWifiNmeApStartReqSend(0,interface_tag,CSR_WIFI_AP_TYPE_LEGACY,FALSE,
1492                             ap_config->ssid,1,ap_config->channel,
1493                             ap_config->credentials,ap_config->max_connections,
1494                             p2p_go_param,FALSE);
1495
1496    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1497    if (r) {
1498        return r;
1499    }
1500
1501    unifi_trace(priv, UDBG4,
1502                "sme_ap_start <-- (r=%d status=%d)\n",
1503                r, priv->sme_reply.reply_status);
1504    return convert_sme_error(priv->sme_reply.reply_status);
1505}
1506
1507int sme_ap_config(unifi_priv_t *priv,
1508                  CsrWifiSmeApMacConfig *ap_mac_config,
1509                  CsrWifiNmeApConfig *group_security_config)
1510{
1511    int r;
1512    CsrWifiSmeApP2pGoConfig p2p_go_param;
1513    memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig));
1514
1515    if (priv->smepriv == NULL) {
1516        unifi_error(priv, "sme_ap_config: invalid smepriv\n");
1517        return -EIO;
1518    }
1519
1520    r = sme_init_request(priv);
1521    if (r) {
1522        return -EIO;
1523    }
1524
1525    CsrWifiNmeApConfigSetReqSend(0,*group_security_config,
1526                                 *ap_mac_config);
1527
1528    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1529
1530    unifi_trace(priv, UDBG4,
1531                "sme_ap_config <-- (r=%d status=%d)\n",
1532                r, priv->sme_reply.reply_status);
1533    return convert_sme_error(priv->sme_reply.reply_status);
1534}
1535#endif
1536

Archive Download this file



interactive