]> Pileus Git - ~andy/linux/blob - drivers/staging/csr/sme_blocking.c
Merge tag 'kvm-3.7-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[~andy/linux] / 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 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
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
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
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
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
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
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
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
292 int 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
318 int 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
370 int 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
443 int 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
476 int 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
501 int 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
529 int 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
563 int 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
590 int 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
629 int 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
685 int 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
724 int 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
765 int 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
806 int 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
852 int 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
896 int 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
940 int 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
1005 int 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
1051 int 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
1095 int 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
1139 int 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
1183 int 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
1227 int 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
1273 int 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
1301 int 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
1331 int 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
1418 int 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
1446 int 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
1474 int 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
1507 int 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