staging: csr: remove CsrUint16 typedef
[linux-2.6-block.git] / drivers / staging / csr / sme_blocking.c
CommitLineData
635d2b00
GKH
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
95edd09e
GKH
95 unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n");
96
635d2b00
GKH
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 }
95edd09e
GKH
102 unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n");
103
635d2b00
GKH
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 }
95edd09e
GKH
125 unifi_trace(priv, UDBG5,
126 "sme_complete_request: completed %s (s:%d)\n",
127 (func ? func : ""), priv->sme_reply.request_status);
128
635d2b00
GKH
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
95edd09e
GKH
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
635d2b00
GKH
172static int
173_sme_wait_for_reply(unifi_priv_t *priv,
174 unsigned long timeout, const char *func)
175{
176 long r;
177
95edd09e 178 unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : "");
635d2b00
GKH
179 r = wait_event_interruptible_timeout(priv->sme_request_wq,
180 (priv->sme_reply.request_status != SME_REQUEST_PENDING),
181 msecs_to_jiffies(timeout));
95edd09e 182 unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r);
635d2b00
GKH
183
184 if (r == -ERESTARTSYS) {
185 /* The thread was killed */
95edd09e 186 unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n");
635d2b00
GKH
187 up(&priv->sme_sem);
188 return r;
189 }
95edd09e
GKH
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 }
635d2b00
GKH
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
95edd09e
GKH
210 unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n",
211 func ? func : "", r);
212
635d2b00
GKH
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{
8c87f69a 225 u16 numElements;
635d2b00
GKH
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 CsrBool 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,
8c87f69a 353 (u16)num_channels, channel_list,
635d2b00
GKH
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{
8c87f69a 375 u16 scan_result_list_count;
635d2b00
GKH
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 CsrPmemFree(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 CsrPmemFree(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 CsrUint32 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
95edd09e 1346 /* Suspend the SME, which MAY cause it to power down UniFi */
635d2b00
GKH
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, ",
95edd09e 1353 (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n");
635d2b00
GKH
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);
95edd09e 1359 unifi_trace(priv, UDBG1, "Force deep sleep");
635d2b00
GKH
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
95edd09e
GKH
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);
635d2b00 1396 }
95edd09e
GKH
1397 } else {
1398 unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n");
635d2b00 1399 }
95edd09e
GKH
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");
635d2b00
GKH
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
95edd09e
GKH
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");
635d2b00
GKH
1440 }
1441
1442 return 0;
1443}
1444
1445#ifdef CSR_SUPPORT_WEXT_AP
8c87f69a 1446int sme_ap_stop(unifi_priv_t *priv,u16 interface_tag)
635d2b00
GKH
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
8c87f69a 1474int sme_ap_start(unifi_priv_t *priv,u16 interface_tag,
635d2b00
GKH
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