aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/ath6kl/wmi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/ath6kl/wmi')
-rw-r--r--drivers/staging/ath6kl/wmi/wmi.c6444
-rw-r--r--drivers/staging/ath6kl/wmi/wmi_host.h102
2 files changed, 6546 insertions, 0 deletions
diff --git a/drivers/staging/ath6kl/wmi/wmi.c b/drivers/staging/ath6kl/wmi/wmi.c
new file mode 100644
index 00000000000..c7b5e5cf9df
--- /dev/null
+++ b/drivers/staging/ath6kl/wmi/wmi.c
@@ -0,0 +1,6444 @@
1//------------------------------------------------------------------------------
2// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
3//
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16//
17//
18//------------------------------------------------------------------------------
19//==============================================================================
20// This module implements the hardware independent layer of the
21// Wireless Module Interface (WMI) protocol.
22//
23// Author(s): ="Atheros"
24//==============================================================================
25
26#include <a_config.h>
27#include <athdefs.h>
28#include <a_osapi.h>
29#include "htc.h"
30#include "htc_api.h"
31#include "wmi.h"
32#include <wlan_api.h>
33#include <wmi_api.h>
34#include <ieee80211.h>
35#include <ieee80211_node.h>
36#include "dset_api.h"
37#include "wmi_host.h"
38#include "a_drv.h"
39#include "a_drv_api.h"
40#define ATH_MODULE_NAME wmi
41#include "a_debug.h"
42#include "dbglog_api.h"
43#include "roaming.h"
44#include "cfg80211.h"
45
46#define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0)
47
48#ifdef ATH_DEBUG_MODULE
49
50static struct ath_debug_mask_description wmi_debug_desc[] = {
51 { ATH_DEBUG_WMI , "General WMI Tracing"},
52};
53
54ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi,
55 "wmi",
56 "Wireless Module Interface",
57 ATH_DEBUG_MASK_DEFAULTS,
58 ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc),
59 wmi_debug_desc);
60
61#endif
62
63#ifndef REXOS
64#define DBGARG _A_FUNCNAME_
65#define DBGFMT "%s() : "
66#define DBG_WMI ATH_DEBUG_WMI
67#define DBG_ERROR ATH_DEBUG_ERR
68#define DBG_WMI2 ATH_DEBUG_WMI
69#define A_DPRINTF AR_DEBUG_PRINTF
70#endif
71
72static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
73
74static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
75 int len);
76static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
77 int len);
78
79static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
80 int len);
81static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
82 int len);
83static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
84 int len);
85static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
86 int len);
87static int wmi_sync_point(struct wmi_t *wmip);
88
89static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
90 int len);
91static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
92 int len);
93static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
94 int len);
95static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
96 int len);
97static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
98static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
99 int len);
100
101static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
102 int len);
103#ifdef CONFIG_HOST_DSET_SUPPORT
104static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
105static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
106 int len);
107#endif /* CONFIG_HOST_DSET_SUPPORT */
108
109
110static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
111 int len);
112static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
113static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
114static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
115static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
116static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
117static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
118static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
119static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
120 int len);
121static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
122 int len);
123static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
124 int len);
125static int
126wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
127
128static int
129wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
130
131
132#ifdef CONFIG_HOST_TCMD_SUPPORT
133static int
134wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
135#endif
136
137static int
138wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
139
140static int
141wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
142
143static int
144wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
145
146static bool
147wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
148
149static int
150wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
151
152static int
153wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
154
155static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
156
157int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
158 WMI_SYNC_FLAG syncflag);
159
160u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
161u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
162
163void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
164void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
165static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
166 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
167static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
168 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
169#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
170static int
171wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
172#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
173
174static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
175 int len);
176static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
177 int len);
178
179static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
180 int len);
181static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
182static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
183static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
184static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
185static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
186static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
187
188#ifdef WAPI_ENABLE
189static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
190 int len);
191#endif
192
193#if defined(UNDER_CE)
194#if defined(NDIS51_MINIPORT)
195unsigned int processDot11Hdr = 0;
196#else
197unsigned int processDot11Hdr = 1;
198#endif
199#else
200extern unsigned int processDot11Hdr;
201#endif
202
203int wps_enable;
204static const s32 wmi_rateTable[][2] = {
205 //{W/O SGI, with SGI}
206 {1000, 1000},
207 {2000, 2000},
208 {5500, 5500},
209 {11000, 11000},
210 {6000, 6000},
211 {9000, 9000},
212 {12000, 12000},
213 {18000, 18000},
214 {24000, 24000},
215 {36000, 36000},
216 {48000, 48000},
217 {54000, 54000},
218 {6500, 7200},
219 {13000, 14400},
220 {19500, 21700},
221 {26000, 28900},
222 {39000, 43300},
223 {52000, 57800},
224 {58500, 65000},
225 {65000, 72200},
226 {13500, 15000},
227 {27000, 30000},
228 {40500, 45000},
229 {54000, 60000},
230 {81000, 90000},
231 {108000, 120000},
232 {121500, 135000},
233 {135000, 150000},
234 {0, 0}};
235
236#define MODE_A_SUPPORT_RATE_START ((s32) 4)
237#define MODE_A_SUPPORT_RATE_STOP ((s32) 11)
238
239#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
240#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
241
242#define MODE_B_SUPPORT_RATE_START ((s32) 0)
243#define MODE_B_SUPPORT_RATE_STOP ((s32) 3)
244
245#define MODE_G_SUPPORT_RATE_START ((s32) 0)
246#define MODE_G_SUPPORT_RATE_STOP ((s32) 11)
247
248#define MODE_GHT20_SUPPORT_RATE_START ((s32) 0)
249#define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19)
250
251#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1)
252
253/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
254const u8 up_to_ac[]= {
255 WMM_AC_BE,
256 WMM_AC_BK,
257 WMM_AC_BK,
258 WMM_AC_BE,
259 WMM_AC_VI,
260 WMM_AC_VI,
261 WMM_AC_VO,
262 WMM_AC_VO,
263 };
264
265/* This stuff is used when we want a simple layer-3 visibility */
266typedef PREPACK struct _iphdr {
267 u8 ip_ver_hdrlen; /* version and hdr length */
268 u8 ip_tos; /* type of service */
269 u16 ip_len; /* total length */
270 u16 ip_id; /* identification */
271 s16 ip_off; /* fragment offset field */
272#define IP_DF 0x4000 /* dont fragment flag */
273#define IP_MF 0x2000 /* more fragments flag */
274#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
275 u8 ip_ttl; /* time to live */
276 u8 ip_p; /* protocol */
277 u16 ip_sum; /* checksum */
278 u8 ip_src[4]; /* source and dest address */
279 u8 ip_dst[4];
280} POSTPACK iphdr;
281
282static s16 rssi_event_value = 0;
283static s16 snr_event_value = 0;
284
285bool is_probe_ssid = false;
286
287void *
288wmi_init(void *devt)
289{
290 struct wmi_t *wmip;
291
292 A_REGISTER_MODULE_DEBUG_INFO(wmi);
293
294 wmip = A_MALLOC (sizeof(struct wmi_t));
295 if (wmip == NULL) {
296 return (NULL);
297 }
298 A_MEMZERO(wmip, sizeof(struct wmi_t ));
299#ifdef THREAD_X
300 INIT_WMI_LOCK(wmip);
301#else
302 A_MUTEX_INIT(&wmip->wmi_lock);
303#endif
304 wmip->wmi_devt = devt;
305 wlan_node_table_init(wmip, &wmip->wmi_scan_table);
306 wmi_qos_state_init(wmip);
307
308 wmip->wmi_powerMode = REC_POWER;
309 wmip->wmi_phyMode = WMI_11G_MODE;
310
311 wmip->wmi_pair_crypto_type = NONE_CRYPT;
312 wmip->wmi_grp_crypto_type = NONE_CRYPT;
313
314 wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1;
315 wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1;
316
317 return (wmip);
318}
319
320void
321wmi_qos_state_init(struct wmi_t *wmip)
322{
323 u8 i;
324
325 if (wmip == NULL) {
326 return;
327 }
328 LOCK_WMI(wmip);
329
330 /* Initialize QoS States */
331 wmip->wmi_numQoSStream = 0;
332
333 wmip->wmi_fatPipeExists = 0;
334
335 for (i=0; i < WMM_NUM_AC; i++) {
336 wmip->wmi_streamExistsForAC[i]=0;
337 }
338
339 UNLOCK_WMI(wmip);
340
341 A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
342}
343
344void
345wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid)
346{
347 A_ASSERT( eid != ENDPOINT_UNUSED);
348 wmip->wmi_endpoint_id = eid;
349}
350
351HTC_ENDPOINT_ID
352wmi_get_control_ep(struct wmi_t * wmip)
353{
354 return(wmip->wmi_endpoint_id);
355}
356
357void
358wmi_shutdown(struct wmi_t *wmip)
359{
360 if (wmip != NULL) {
361 wlan_node_table_cleanup(&wmip->wmi_scan_table);
362 if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
363#ifdef THREAD_X
364 DELETE_WMI_LOCK(&wmip);
365#else
366 A_MUTEX_DELETE(&wmip->wmi_lock);
367#endif
368 }
369 kfree(wmip);
370 }
371}
372
373/*
374 * performs DIX to 802.3 encapsulation for transmit packets.
375 * uses passed in buffer. Returns buffer or NULL if failed.
376 * Assumes the entire DIX header is contigous and that there is
377 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
378 */
379int
380wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
381{
382 u8 *datap;
383 u16 typeorlen;
384 ATH_MAC_HDR macHdr;
385 ATH_LLC_SNAP_HDR *llcHdr;
386
387 A_ASSERT(osbuf != NULL);
388
389 if (A_NETBUF_HEADROOM(osbuf) <
390 (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
391 {
392 return A_NO_MEMORY;
393 }
394
395 datap = A_NETBUF_DATA(osbuf);
396
397 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
398
399 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
400 /*
401 * packet is already in 802.3 format - return success
402 */
403 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
404 return (0);
405 }
406
407 /*
408 * Save mac fields and length to be inserted later
409 */
410 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
411 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
412 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
413 sizeof(ATH_LLC_SNAP_HDR));
414
415 /*
416 * Make room for LLC+SNAP headers
417 */
418 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
419 return A_NO_MEMORY;
420 }
421 datap = A_NETBUF_DATA(osbuf);
422
423 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
424
425 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
426 llcHdr->dsap = 0xAA;
427 llcHdr->ssap = 0xAA;
428 llcHdr->cntl = 0x03;
429 llcHdr->orgCode[0] = 0x0;
430 llcHdr->orgCode[1] = 0x0;
431 llcHdr->orgCode[2] = 0x0;
432 llcHdr->etherType = typeorlen;
433
434 return (0);
435}
436
437int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
438{
439 switch(*pVersion){
440 case 0:
441 return (0);
442 case WMI_META_VERSION_1:
443 {
444 WMI_TX_META_V1 *pV1= NULL;
445 A_ASSERT(osbuf != NULL);
446 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
447 return A_NO_MEMORY;
448 }
449
450 pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf);
451 /* the pktID is used in conjunction with txComplete messages
452 * allowing the target to notify which tx requests have been
453 * completed and how. */
454 pV1->pktID = 0;
455 /* the ratePolicyID allows the host to specify which rate policy
456 * to use for transmitting this packet. 0 means use default behavior. */
457 pV1->ratePolicyID = 0;
458 A_ASSERT(pVersion != NULL);
459 /* the version must be used to populate the meta field of the WMI_DATA_HDR */
460 *pVersion = WMI_META_VERSION_1;
461 return (0);
462 }
463 case WMI_META_VERSION_2:
464 {
465 WMI_TX_META_V2 *pV2 ;
466 A_ASSERT(osbuf != NULL);
467 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
468 return A_NO_MEMORY;
469 }
470 pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
471 memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
472 return (0);
473 }
474 default:
475 return (0);
476 }
477}
478
479/* Adds a WMI data header */
480int
481wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
482 WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
483{
484 WMI_DATA_HDR *dtHdr;
485// u8 metaVersion = 0;
486 int status;
487
488 A_ASSERT(osbuf != NULL);
489
490 /* adds the meta data field after the wmi data hdr. If metaVersion
491 * is returns 0 then no meta field was added. */
492 if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
493 return status;
494 }
495
496 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
497 return A_NO_MEMORY;
498 }
499
500 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
501 A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR));
502
503 WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType);
504 WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type);
505
506 if (bMoreData) {
507 WMI_DATA_HDR_SET_MORE_BIT(dtHdr);
508 }
509
510 WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
511
512 dtHdr->info3 = 0;
513
514 return (0);
515}
516
517
518u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
519{
520 u8 *datap;
521 u8 trafficClass = WMM_AC_BE;
522 u16 ipType = IP_ETHERTYPE;
523 WMI_DATA_HDR *dtHdr;
524 u8 streamExists = 0;
525 u8 userPriority;
526 u32 hdrsize, metasize;
527 ATH_LLC_SNAP_HDR *llcHdr;
528
529 WMI_CREATE_PSTREAM_CMD cmd;
530
531 A_ASSERT(osbuf != NULL);
532
533 //
534 // Initialize header size
535 //
536 hdrsize = 0;
537
538 datap = A_NETBUF_DATA(osbuf);
539 dtHdr = (WMI_DATA_HDR *)datap;
540 metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0;
541
542 if (!wmmEnabled)
543 {
544 /* If WMM is disabled all traffic goes as BE traffic */
545 userPriority = 0;
546 }
547 else
548 {
549 if (processDot11Hdr)
550 {
551 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
552 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
553 hdrsize);
554
555
556 }
557 else
558 {
559 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
560 sizeof(ATH_MAC_HDR));
561 }
562
563 if (llcHdr->etherType == A_CPU2BE16(ipType))
564 {
565 /* Extract the endpoint info from the TOS field in the IP header */
566
567 userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
568 }
569 else
570 {
571 userPriority = layer2Priority & 0x7;
572 }
573 }
574
575
576 /* workaround for WMM S5 */
577 if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority)))
578 {
579 userPriority = 1;
580 }
581
582 trafficClass = convert_userPriority_to_trafficClass(userPriority);
583
584 WMI_DATA_HDR_SET_UP(dtHdr, userPriority);
585 /* lower 3-bits are 802.1d priority */
586 //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT;
587
588 LOCK_WMI(wmip);
589 streamExists = wmip->wmi_fatPipeExists;
590 UNLOCK_WMI(wmip);
591
592 if (!(streamExists & (1 << trafficClass)))
593 {
594
595 A_MEMZERO(&cmd, sizeof(cmd));
596 cmd.trafficClass = trafficClass;
597 cmd.userPriority = userPriority;
598 cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
599 /* Implicit streams are created with TSID 0xFF */
600
601 cmd.tsid = WMI_IMPLICIT_PSTREAM;
602 wmi_create_pstream_cmd(wmip, &cmd);
603 }
604
605 return trafficClass;
606}
607
608int
609wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
610{
611 u8 *datap;
612 u16 typeorlen;
613 ATH_MAC_HDR macHdr;
614 ATH_LLC_SNAP_HDR *llcHdr;
615 struct ieee80211_frame *wh;
616 u32 hdrsize;
617
618 A_ASSERT(osbuf != NULL);
619
620 if (A_NETBUF_HEADROOM(osbuf) <
621 (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
622 {
623 return A_NO_MEMORY;
624 }
625
626 datap = A_NETBUF_DATA(osbuf);
627
628 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
629
630 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
631/*
632 * packet is already in 802.3 format - return success
633 */
634 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
635 goto AddDot11Hdr;
636 }
637
638 /*
639 * Save mac fields and length to be inserted later
640 */
641 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
642 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
643 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
644 sizeof(ATH_LLC_SNAP_HDR));
645
646 // Remove the Ethernet hdr
647 A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR));
648 /*
649 * Make room for LLC+SNAP headers
650 */
651 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
652 return A_NO_MEMORY;
653 }
654 datap = A_NETBUF_DATA(osbuf);
655
656 llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
657 llcHdr->dsap = 0xAA;
658 llcHdr->ssap = 0xAA;
659 llcHdr->cntl = 0x03;
660 llcHdr->orgCode[0] = 0x0;
661 llcHdr->orgCode[1] = 0x0;
662 llcHdr->orgCode[2] = 0x0;
663 llcHdr->etherType = typeorlen;
664
665AddDot11Hdr:
666 /* Make room for 802.11 hdr */
667 if (wmip->wmi_is_wmm_enabled)
668 {
669 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
670 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
671 {
672 return A_NO_MEMORY;
673 }
674 wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
675 wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS;
676 }
677 else
678 {
679 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
680 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
681 {
682 return A_NO_MEMORY;
683 }
684 wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
685 wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA;
686 }
687 /* Setup the SA & DA */
688 IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac);
689
690 if (mode == INFRA_NETWORK) {
691 IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac);
692 }
693 else if (mode == ADHOC_NETWORK) {
694 IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
695 }
696
697 return (0);
698}
699
700int
701wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
702{
703 u8 *datap;
704 struct ieee80211_frame *pwh,wh;
705 u8 type,subtype;
706 ATH_LLC_SNAP_HDR *llcHdr;
707 ATH_MAC_HDR macHdr;
708 u32 hdrsize;
709
710 A_ASSERT(osbuf != NULL);
711 datap = A_NETBUF_DATA(osbuf);
712
713 pwh = (struct ieee80211_frame *)datap;
714 type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
715 subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
716
717 memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
718
719 /* strip off the 802.11 hdr*/
720 if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
721 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
722 A_NETBUF_PULL(osbuf, hdrsize);
723 } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
724 A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
725 }
726
727 datap = A_NETBUF_DATA(osbuf);
728 llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
729
730 macHdr.typeOrLen = llcHdr->etherType;
731 A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac));
732 A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac));
733
734 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
735 case IEEE80211_FC1_DIR_NODS:
736 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
737 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
738 break;
739 case IEEE80211_FC1_DIR_TODS:
740 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3);
741 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
742 break;
743 case IEEE80211_FC1_DIR_FROMDS:
744 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
745 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3);
746 break;
747 case IEEE80211_FC1_DIR_DSTODS:
748 break;
749 }
750
751 // Remove the LLC Hdr.
752 A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR));
753
754 // Insert the ATH MAC hdr.
755
756 A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
757 datap = A_NETBUF_DATA(osbuf);
758
759 memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
760
761 return 0;
762}
763
764/*
765 * performs 802.3 to DIX encapsulation for received packets.
766 * Assumes the entire 802.3 header is contigous.
767 */
768int
769wmi_dot3_2_dix(void *osbuf)
770{
771 u8 *datap;
772 ATH_MAC_HDR macHdr;
773 ATH_LLC_SNAP_HDR *llcHdr;
774
775 A_ASSERT(osbuf != NULL);
776 datap = A_NETBUF_DATA(osbuf);
777
778 memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
779 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
780 macHdr.typeOrLen = llcHdr->etherType;
781
782 if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
783 return A_NO_MEMORY;
784 }
785
786 datap = A_NETBUF_DATA(osbuf);
787
788 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
789
790 return (0);
791}
792
793/*
794 * Removes a WMI data header
795 */
796int
797wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
798{
799 A_ASSERT(osbuf != NULL);
800
801 return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
802}
803
804void
805wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
806{
807 wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
808}
809
810/*
811 * WMI Extended Event received from Target.
812 */
813int
814wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
815{
816 WMIX_CMD_HDR *cmd;
817 u16 id;
818 u8 *datap;
819 u32 len;
820 int status = 0;
821
822 if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
823 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
824 wmip->wmi_stats.cmd_len_err++;
825 return A_ERROR;
826 }
827
828 cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
829 id = cmd->commandId;
830
831 if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
832 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
833 wmip->wmi_stats.cmd_len_err++;
834 return A_ERROR;
835 }
836
837 datap = A_NETBUF_DATA(osbuf);
838 len = A_NETBUF_LEN(osbuf);
839
840 switch (id) {
841 case (WMIX_DSETOPENREQ_EVENTID):
842 status = wmi_dset_open_req_rx(wmip, datap, len);
843 break;
844#ifdef CONFIG_HOST_DSET_SUPPORT
845 case (WMIX_DSETCLOSE_EVENTID):
846 status = wmi_dset_close_rx(wmip, datap, len);
847 break;
848 case (WMIX_DSETDATAREQ_EVENTID):
849 status = wmi_dset_data_req_rx(wmip, datap, len);
850 break;
851#endif /* CONFIG_HOST_DSET_SUPPORT */
852 case (WMIX_HB_CHALLENGE_RESP_EVENTID):
853 wmi_hbChallengeResp_rx(wmip, datap, len);
854 break;
855 case (WMIX_DBGLOG_EVENTID):
856 wmi_dbglog_event_rx(wmip, datap, len);
857 break;
858#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
859 case (WMIX_PROF_COUNT_EVENTID):
860 wmi_prof_count_rx(wmip, datap, len);
861 break;
862#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
863 default:
864 A_DPRINTF(DBG_WMI|DBG_ERROR,
865 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
866 wmip->wmi_stats.cmd_id_err++;
867 status = A_ERROR;
868 break;
869 }
870
871 return status;
872}
873
874/*
875 * Control Path
876 */
877u32 cmdRecvNum;
878
879int
880wmi_control_rx(struct wmi_t *wmip, void *osbuf)
881{
882 WMI_CMD_HDR *cmd;
883 u16 id;
884 u8 *datap;
885 u32 len, i, loggingReq;
886 int status = 0;
887
888 A_ASSERT(osbuf != NULL);
889 if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
890 A_NETBUF_FREE(osbuf);
891 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
892 wmip->wmi_stats.cmd_len_err++;
893 return A_ERROR;
894 }
895
896 cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
897 id = cmd->commandId;
898
899 if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
900 A_NETBUF_FREE(osbuf);
901 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
902 wmip->wmi_stats.cmd_len_err++;
903 return A_ERROR;
904 }
905
906 datap = A_NETBUF_DATA(osbuf);
907 len = A_NETBUF_LEN(osbuf);
908
909 loggingReq = 0;
910
911 ar6000_get_driver_cfg(wmip->wmi_devt,
912 AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
913 &loggingReq);
914
915 if(loggingReq) {
916 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
917 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
918 for(i = 0; i < len; i++)
919 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
920 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
921 }
922
923 LOCK_WMI(wmip);
924 cmdRecvNum++;
925 UNLOCK_WMI(wmip);
926
927 switch (id) {
928 case (WMI_GET_BITRATE_CMDID):
929 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
930 status = wmi_bitrate_reply_rx(wmip, datap, len);
931 break;
932 case (WMI_GET_CHANNEL_LIST_CMDID):
933 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
934 status = wmi_channelList_reply_rx(wmip, datap, len);
935 break;
936 case (WMI_GET_TX_PWR_CMDID):
937 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
938 status = wmi_txPwr_reply_rx(wmip, datap, len);
939 break;
940 case (WMI_READY_EVENTID):
941 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
942 status = wmi_ready_event_rx(wmip, datap, len);
943 A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
944 break;
945 case (WMI_CONNECT_EVENTID):
946 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
947 status = wmi_connect_event_rx(wmip, datap, len);
948 break;
949 case (WMI_DISCONNECT_EVENTID):
950 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
951 status = wmi_disconnect_event_rx(wmip, datap, len);
952 break;
953 case (WMI_PEER_NODE_EVENTID):
954 A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG));
955 status = wmi_peer_node_event_rx(wmip, datap, len);
956 break;
957 case (WMI_TKIP_MICERR_EVENTID):
958 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
959 status = wmi_tkip_micerr_event_rx(wmip, datap, len);
960 break;
961 case (WMI_BSSINFO_EVENTID):
962 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
963 {
964 /*
965 * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR
966 * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer
967 * and reconstruct the WMI_BSS_INFO_HDR in its place
968 */
969 WMI_BSS_INFO_HDR2 bih2;
970 WMI_BSS_INFO_HDR *bih;
971 memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
972
973 A_NETBUF_PUSH(osbuf, 4);
974 datap = A_NETBUF_DATA(osbuf);
975 len = A_NETBUF_LEN(osbuf);
976 bih = (WMI_BSS_INFO_HDR *)datap;
977
978 bih->channel = bih2.channel;
979 bih->frameType = bih2.frameType;
980 bih->snr = bih2.snr;
981 bih->rssi = bih2.snr - 95;
982 bih->ieMask = bih2.ieMask;
983 memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
984
985 status = wmi_bssInfo_event_rx(wmip, datap, len);
986 }
987 break;
988 case (WMI_REGDOMAIN_EVENTID):
989 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
990 status = wmi_regDomain_event_rx(wmip, datap, len);
991 break;
992 case (WMI_PSTREAM_TIMEOUT_EVENTID):
993 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
994 status = wmi_pstream_timeout_event_rx(wmip, datap, len);
995 break;
996 case (WMI_NEIGHBOR_REPORT_EVENTID):
997 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
998 status = wmi_neighborReport_event_rx(wmip, datap, len);
999 break;
1000 case (WMI_SCAN_COMPLETE_EVENTID):
1001 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
1002 status = wmi_scanComplete_rx(wmip, datap, len);
1003 break;
1004 case (WMI_CMDERROR_EVENTID):
1005 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
1006 status = wmi_errorEvent_rx(wmip, datap, len);
1007 break;
1008 case (WMI_REPORT_STATISTICS_EVENTID):
1009 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
1010 status = wmi_statsEvent_rx(wmip, datap, len);
1011 break;
1012 case (WMI_RSSI_THRESHOLD_EVENTID):
1013 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
1014 status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
1015 break;
1016 case (WMI_ERROR_REPORT_EVENTID):
1017 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
1018 status = wmi_reportErrorEvent_rx(wmip, datap, len);
1019 break;
1020 case (WMI_OPT_RX_FRAME_EVENTID):
1021 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
1022 status = wmi_opt_frame_event_rx(wmip, datap, len);
1023 break;
1024 case (WMI_REPORT_ROAM_TBL_EVENTID):
1025 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
1026 status = wmi_roam_tbl_event_rx(wmip, datap, len);
1027 break;
1028 case (WMI_EXTENSION_EVENTID):
1029 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
1030 status = wmi_control_rx_xtnd(wmip, osbuf);
1031 break;
1032 case (WMI_CAC_EVENTID):
1033 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
1034 status = wmi_cac_event_rx(wmip, datap, len);
1035 break;
1036 case (WMI_CHANNEL_CHANGE_EVENTID):
1037 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG));
1038 status = wmi_channel_change_event_rx(wmip, datap, len);
1039 break;
1040 case (WMI_REPORT_ROAM_DATA_EVENTID):
1041 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
1042 status = wmi_roam_data_event_rx(wmip, datap, len);
1043 break;
1044#ifdef CONFIG_HOST_TCMD_SUPPORT
1045 case (WMI_TEST_EVENTID):
1046 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
1047 status = wmi_tcmd_test_report_rx(wmip, datap, len);
1048 break;
1049#endif
1050 case (WMI_GET_FIXRATES_CMDID):
1051 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
1052 status = wmi_ratemask_reply_rx(wmip, datap, len);
1053 break;
1054 case (WMI_TX_RETRY_ERR_EVENTID):
1055 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
1056 status = wmi_txRetryErrEvent_rx(wmip, datap, len);
1057 break;
1058 case (WMI_SNR_THRESHOLD_EVENTID):
1059 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
1060 status = wmi_snrThresholdEvent_rx(wmip, datap, len);
1061 break;
1062 case (WMI_LQ_THRESHOLD_EVENTID):
1063 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
1064 status = wmi_lqThresholdEvent_rx(wmip, datap, len);
1065 break;
1066 case (WMI_APLIST_EVENTID):
1067 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
1068 status = wmi_aplistEvent_rx(wmip, datap, len);
1069 break;
1070 case (WMI_GET_KEEPALIVE_CMDID):
1071 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
1072 status = wmi_keepalive_reply_rx(wmip, datap, len);
1073 break;
1074 case (WMI_GET_WOW_LIST_EVENTID):
1075 status = wmi_get_wow_list_event_rx(wmip, datap, len);
1076 break;
1077 case (WMI_GET_PMKID_LIST_EVENTID):
1078 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
1079 status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
1080 break;
1081 case (WMI_PSPOLL_EVENTID):
1082 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG));
1083 status = wmi_pspoll_event_rx(wmip, datap, len);
1084 break;
1085 case (WMI_DTIMEXPIRY_EVENTID):
1086 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG));
1087 status = wmi_dtimexpiry_event_rx(wmip, datap, len);
1088 break;
1089 case (WMI_SET_PARAMS_REPLY_EVENTID):
1090 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
1091 status = wmi_set_params_event_rx(wmip, datap, len);
1092 break;
1093 case (WMI_ADDBA_REQ_EVENTID):
1094 status = wmi_addba_req_event_rx(wmip, datap, len);
1095 break;
1096 case (WMI_ADDBA_RESP_EVENTID):
1097 status = wmi_addba_resp_event_rx(wmip, datap, len);
1098 break;
1099 case (WMI_DELBA_REQ_EVENTID):
1100 status = wmi_delba_req_event_rx(wmip, datap, len);
1101 break;
1102 case (WMI_REPORT_BTCOEX_CONFIG_EVENTID):
1103 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG));
1104 status = wmi_btcoex_config_event_rx(wmip, datap, len);
1105 break;
1106 case (WMI_REPORT_BTCOEX_STATS_EVENTID):
1107 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG));
1108 status = wmi_btcoex_stats_event_rx(wmip, datap, len);
1109 break;
1110 case (WMI_TX_COMPLETE_EVENTID):
1111 {
1112 int index;
1113 TX_COMPLETE_MSG_V1 *pV1;
1114 WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap;
1115 A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType);
1116
1117 for(index = 0 ; index < pEv->numMessages ; index++) {
1118 pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1));
1119 A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures);
1120 }
1121 }
1122 break;
1123 case (WMI_HCI_EVENT_EVENTID):
1124 status = wmi_hci_event_rx(wmip, datap, len);
1125 break;
1126#ifdef WAPI_ENABLE
1127 case (WMI_WAPI_REKEY_EVENTID):
1128 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG));
1129 status = wmi_wapi_rekey_event_rx(wmip, datap, len);
1130 break;
1131#endif
1132 default:
1133 A_DPRINTF(DBG_WMI|DBG_ERROR,
1134 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
1135 wmip->wmi_stats.cmd_id_err++;
1136 status = A_ERROR;
1137 break;
1138 }
1139
1140 A_NETBUF_FREE(osbuf);
1141
1142 return status;
1143}
1144
1145/* Send a "simple" wmi command -- one with no arguments */
1146static int
1147wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
1148{
1149 void *osbuf;
1150
1151 osbuf = A_NETBUF_ALLOC(0);
1152 if (osbuf == NULL) {
1153 return A_NO_MEMORY;
1154 }
1155
1156 return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1157}
1158
1159/* Send a "simple" extended wmi command -- one with no arguments.
1160 Enabling this command only if GPIO or profiling support is enabled.
1161 This is to suppress warnings on some platforms */
1162#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1163static int
1164wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
1165{
1166 void *osbuf;
1167
1168 osbuf = A_NETBUF_ALLOC(0);
1169 if (osbuf == NULL) {
1170 return A_NO_MEMORY;
1171 }
1172
1173 return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1174}
1175#endif
1176
1177static int
1178wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1179{
1180 WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
1181
1182 if (len < sizeof(WMI_READY_EVENT)) {
1183 return A_EINVAL;
1184 }
1185 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1186 wmip->wmi_ready = true;
1187 A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
1188 ev->sw_version, ev->abi_version);
1189
1190 return 0;
1191}
1192
1193#define LE_READ_4(p) \
1194 ((u32) \
1195 ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \
1196 (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
1197
1198static int __inline
1199iswmmoui(const u8 *frm)
1200{
1201 return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
1202}
1203
1204static int __inline
1205iswmmparam(const u8 *frm)
1206{
1207 return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
1208}
1209
1210
1211static int
1212wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1213{
1214 WMI_CONNECT_EVENT *ev;
1215 u8 *pie,*peie;
1216
1217 if (len < sizeof(WMI_CONNECT_EVENT))
1218 {
1219 return A_EINVAL;
1220 }
1221 ev = (WMI_CONNECT_EVENT *)datap;
1222
1223 A_DPRINTF(DBG_WMI,
1224 (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
1225 DBGARG, ev->channel,
1226 ev->bssid[0], ev->bssid[1], ev->bssid[2],
1227 ev->bssid[3], ev->bssid[4], ev->bssid[5]));
1228
1229 memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
1230
1231 /* initialize pointer to start of assoc rsp IEs */
1232 pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
1233 sizeof(u16) + /* capinfo*/
1234 sizeof(u16) + /* status Code */
1235 sizeof(u16) ; /* associd */
1236
1237 /* initialize pointer to end of assoc rsp IEs */
1238 peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
1239
1240 while (pie < peie)
1241 {
1242 switch (*pie)
1243 {
1244 case IEEE80211_ELEMID_VENDOR:
1245 if (iswmmoui(pie))
1246 {
1247 if(iswmmparam (pie))
1248 {
1249 wmip->wmi_is_wmm_enabled = true;
1250 }
1251 }
1252 break;
1253 }
1254
1255 if (wmip->wmi_is_wmm_enabled)
1256 {
1257 break;
1258 }
1259 pie += pie[1] + 2;
1260 }
1261
1262 A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
1263 ev->listenInterval, ev->beaconInterval,
1264 (NETWORK_TYPE) ev->networkType, ev->beaconIeLen,
1265 ev->assocReqLen, ev->assocRespLen,
1266 ev->assocInfo);
1267
1268 return 0;
1269}
1270
1271static int
1272wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1273{
1274 WMI_REG_DOMAIN_EVENT *ev;
1275
1276 if (len < sizeof(*ev)) {
1277 return A_EINVAL;
1278 }
1279 ev = (WMI_REG_DOMAIN_EVENT *)datap;
1280
1281 A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
1282
1283 return 0;
1284}
1285
1286static int
1287wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1288{
1289 WMI_NEIGHBOR_REPORT_EVENT *ev;
1290 int numAps;
1291
1292 if (len < sizeof(*ev)) {
1293 return A_EINVAL;
1294 }
1295 ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
1296 numAps = ev->numberOfAps;
1297
1298 if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
1299 return A_EINVAL;
1300 }
1301
1302 A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
1303
1304 return 0;
1305}
1306
1307static int
1308wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1309{
1310 WMI_DISCONNECT_EVENT *ev;
1311 wmip->wmi_traffic_class = 100;
1312
1313 if (len < sizeof(WMI_DISCONNECT_EVENT)) {
1314 return A_EINVAL;
1315 }
1316 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1317
1318 ev = (WMI_DISCONNECT_EVENT *)datap;
1319
1320 A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
1321
1322 wmip->wmi_is_wmm_enabled = false;
1323 wmip->wmi_pair_crypto_type = NONE_CRYPT;
1324 wmip->wmi_grp_crypto_type = NONE_CRYPT;
1325
1326 A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
1327 ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
1328
1329 return 0;
1330}
1331
1332static int
1333wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1334{
1335 WMI_PEER_NODE_EVENT *ev;
1336
1337 if (len < sizeof(WMI_PEER_NODE_EVENT)) {
1338 return A_EINVAL;
1339 }
1340 ev = (WMI_PEER_NODE_EVENT *)datap;
1341 if (ev->eventCode == PEER_NODE_JOIN_EVENT) {
1342 A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG));
1343 } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) {
1344 A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG));
1345 }
1346
1347 A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
1348
1349 return 0;
1350}
1351
1352static int
1353wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1354{
1355 WMI_TKIP_MICERR_EVENT *ev;
1356
1357 if (len < sizeof(*ev)) {
1358 return A_EINVAL;
1359 }
1360 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1361
1362 ev = (WMI_TKIP_MICERR_EVENT *)datap;
1363 A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
1364
1365 return 0;
1366}
1367
1368static int
1369wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1370{
1371 bss_t *bss = NULL;
1372 WMI_BSS_INFO_HDR *bih;
1373 u8 *buf;
1374 u32 nodeCachingAllowed = 1;
1375 u8 cached_ssid_len = 0;
1376 u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
1377 u8 beacon_ssid_len = 0;
1378
1379 if (len <= sizeof(WMI_BSS_INFO_HDR)) {
1380 return A_EINVAL;
1381 }
1382
1383 bih = (WMI_BSS_INFO_HDR *)datap;
1384 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1385
1386 if (bih->rssi > 0) {
1387 if (NULL == bss)
1388 return 0; //no node found in the table, just drop the node with incorrect RSSI
1389 else
1390 bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
1391 }
1392
1393 A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
1394 /* What is driver config for wlan node caching? */
1395 if(ar6000_get_driver_cfg(wmip->wmi_devt,
1396 AR6000_DRIVER_CFG_GET_WLANNODECACHING,
1397 &nodeCachingAllowed) != 0) {
1398 wmi_node_return(wmip, bss);
1399 return A_EINVAL;
1400 }
1401
1402 if(!nodeCachingAllowed) {
1403 wmi_node_return(wmip, bss);
1404 return 0;
1405 }
1406
1407 buf = datap + sizeof(WMI_BSS_INFO_HDR);
1408 len -= sizeof(WMI_BSS_INFO_HDR);
1409
1410 A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
1411 "bssid \"%pM\"\n", DBGARG, bih->channel,
1412 (unsigned char) bih->rssi, bih->bssid));
1413
1414 if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
1415 wmi_node_return(wmip, bss);
1416 return 0;
1417 }
1418
1419 if (bss != NULL) {
1420 /*
1421 * Free up the node. Not the most efficient process given
1422 * we are about to allocate a new node but it is simple and should be
1423 * adequate.
1424 */
1425
1426 /* In case of hidden AP, beacon will not have ssid,
1427 * but a directed probe response will have it,
1428 * so cache the probe-resp-ssid if already present. */
1429 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
1430 {
1431 u8 *ie_ssid;
1432
1433 ie_ssid = bss->ni_cie.ie_ssid;
1434 if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
1435 {
1436 cached_ssid_len = ie_ssid[1];
1437 memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len);
1438 }
1439 }
1440
1441 /*
1442 * Use the current average rssi of associated AP base on assumpiton
1443 * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically
1444 * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...)
1445 * The average value of RSSI give end-user better feeling for instance value of scan result
1446 * It also sync up RSSI info in GUI between scan result and RSSI signal icon
1447 */
1448 if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) {
1449 bih->rssi = bss->ni_rssi;
1450 bih->snr = bss->ni_snr;
1451 }
1452
1453 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1454 }
1455
1456 /* beacon/probe response frame format
1457 * [8] time stamp
1458 * [2] beacon interval
1459 * [2] capability information
1460 * [tlv] ssid */
1461 beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
1462
1463 /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
1464 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1465 (0 != cached_ssid_len) &&
1466 (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1467 {
1468 len += (cached_ssid_len - beacon_ssid_len);
1469 }
1470
1471 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1472 if (bss == NULL) {
1473 return A_NO_MEMORY;
1474 }
1475
1476 bss->ni_snr = bih->snr;
1477 bss->ni_rssi = bih->rssi;
1478 A_ASSERT(bss->ni_buf != NULL);
1479
1480 /* In case of hidden AP, beacon will not have ssid,
1481 * but a directed probe response will have it,
1482 * so place the cached-ssid(probe-resp) in the bssinfo. */
1483 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1484 (0 != cached_ssid_len) &&
1485 (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1486 {
1487 u8 *ni_buf = bss->ni_buf;
1488 int buf_len = len;
1489
1490 /* copy the first 14 bytes such as
1491 * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
1492 memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
1493
1494 ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
1495 ni_buf += (SSID_IE_LEN_INDEX + 1);
1496
1497 buf += (SSID_IE_LEN_INDEX + 1);
1498 buf_len -= (SSID_IE_LEN_INDEX + 1);
1499
1500 /* copy the cached ssid */
1501 memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
1502 ni_buf += cached_ssid_len;
1503
1504 buf += beacon_ssid_len;
1505 buf_len -= beacon_ssid_len;
1506
1507 if (cached_ssid_len > beacon_ssid_len)
1508 buf_len -= (cached_ssid_len - beacon_ssid_len);
1509
1510 /* now copy the rest of bytes */
1511 memcpy(ni_buf, buf, buf_len);
1512 }
1513 else
1514 memcpy(bss->ni_buf, buf, len);
1515
1516 bss->ni_framelen = len;
1517 if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
1518 wlan_node_free(bss);
1519 return A_EINVAL;
1520 }
1521
1522 /*
1523 * Update the frequency in ie_chan, overwriting of channel number
1524 * which is done in wlan_parse_beacon
1525 */
1526 bss->ni_cie.ie_chan = bih->channel;
1527 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1528
1529 return 0;
1530}
1531
1532static int
1533wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1534{
1535 bss_t *bss;
1536 WMI_OPT_RX_INFO_HDR *bih;
1537 u8 *buf;
1538
1539 if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
1540 return A_EINVAL;
1541 }
1542
1543 bih = (WMI_OPT_RX_INFO_HDR *)datap;
1544 buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
1545 len -= sizeof(WMI_OPT_RX_INFO_HDR);
1546
1547 A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
1548 bih->bssid[4], bih->bssid[5]));
1549
1550 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1551 if (bss != NULL) {
1552 /*
1553 * Free up the node. Not the most efficient process given
1554 * we are about to allocate a new node but it is simple and should be
1555 * adequate.
1556 */
1557 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1558 }
1559
1560 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1561 if (bss == NULL) {
1562 return A_NO_MEMORY;
1563 }
1564
1565 bss->ni_snr = bih->snr;
1566 bss->ni_cie.ie_chan = bih->channel;
1567 A_ASSERT(bss->ni_buf != NULL);
1568 memcpy(bss->ni_buf, buf, len);
1569 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1570
1571 return 0;
1572}
1573
1574 /* This event indicates inactivity timeout of a fatpipe(pstream)
1575 * at the target
1576 */
1577static int
1578wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1579{
1580 WMI_PSTREAM_TIMEOUT_EVENT *ev;
1581
1582 if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
1583 return A_EINVAL;
1584 }
1585
1586 A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
1587
1588 ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
1589
1590 /* When the pstream (fat pipe == AC) timesout, it means there were no
1591 * thinStreams within this pstream & it got implicitly created due to
1592 * data flow on this AC. We start the inactivity timer only for
1593 * implicitly created pstream. Just reset the host state.
1594 */
1595 /* Set the activeTsids for this AC to 0 */
1596 LOCK_WMI(wmip);
1597 wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
1598 wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
1599 UNLOCK_WMI(wmip);
1600
1601 /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
1602 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
1603
1604 return 0;
1605}
1606
1607static int
1608wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1609{
1610 WMI_BIT_RATE_REPLY *reply;
1611 s32 rate;
1612 u32 sgi,index;
1613 /* 54149:
1614 * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
1615 * since there is difference in the length and to avoid returning
1616 * error value.
1617 */
1618 if (len < sizeof(WMI_BIT_RATE_REPLY)) {
1619 return A_EINVAL;
1620 }
1621 reply = (WMI_BIT_RATE_REPLY *)datap;
1622 A_DPRINTF(DBG_WMI,
1623 (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
1624
1625 if (reply->rateIndex == (s8) RATE_AUTO) {
1626 rate = RATE_AUTO;
1627 } else {
1628 // the SGI state is stored as the MSb of the rateIndex
1629 index = reply->rateIndex & 0x7f;
1630 sgi = (reply->rateIndex & 0x80)? 1:0;
1631 rate = wmi_rateTable[index][sgi];
1632 }
1633
1634 A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
1635 return 0;
1636}
1637
1638static int
1639wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1640{
1641 WMI_FIX_RATES_REPLY *reply;
1642
1643 if (len < sizeof(WMI_FIX_RATES_REPLY)) {
1644 return A_EINVAL;
1645 }
1646 reply = (WMI_FIX_RATES_REPLY *)datap;
1647 A_DPRINTF(DBG_WMI,
1648 (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
1649
1650 A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
1651
1652 return 0;
1653}
1654
1655static int
1656wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1657{
1658 WMI_CHANNEL_LIST_REPLY *reply;
1659
1660 if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
1661 return A_EINVAL;
1662 }
1663 reply = (WMI_CHANNEL_LIST_REPLY *)datap;
1664 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1665
1666 A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
1667 reply->channelList);
1668
1669 return 0;
1670}
1671
1672static int
1673wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1674{
1675 WMI_TX_PWR_REPLY *reply;
1676
1677 if (len < sizeof(*reply)) {
1678 return A_EINVAL;
1679 }
1680 reply = (WMI_TX_PWR_REPLY *)datap;
1681 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1682
1683 A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
1684
1685 return 0;
1686}
1687static int
1688wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1689{
1690 WMI_GET_KEEPALIVE_CMD *reply;
1691
1692 if (len < sizeof(*reply)) {
1693 return A_EINVAL;
1694 }
1695 reply = (WMI_GET_KEEPALIVE_CMD *)datap;
1696 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1697
1698 A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
1699
1700 return 0;
1701}
1702
1703
1704static int
1705wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1706{
1707 WMIX_DSETOPENREQ_EVENT *dsetopenreq;
1708
1709 if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
1710 return A_EINVAL;
1711 }
1712 dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
1713 A_DPRINTF(DBG_WMI,
1714 (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
1715 A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
1716 dsetopenreq->dset_id,
1717 dsetopenreq->targ_dset_handle,
1718 dsetopenreq->targ_reply_fn,
1719 dsetopenreq->targ_reply_arg);
1720
1721 return 0;
1722}
1723
1724#ifdef CONFIG_HOST_DSET_SUPPORT
1725static int
1726wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
1727{
1728 WMIX_DSETCLOSE_EVENT *dsetclose;
1729
1730 if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
1731 return A_EINVAL;
1732 }
1733 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1734
1735 dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
1736 A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
1737
1738 return 0;
1739}
1740
1741static int
1742wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1743{
1744 WMIX_DSETDATAREQ_EVENT *dsetdatareq;
1745
1746 if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
1747 return A_EINVAL;
1748 }
1749 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1750
1751 dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
1752 A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
1753 dsetdatareq->access_cookie,
1754 dsetdatareq->offset,
1755 dsetdatareq->length,
1756 dsetdatareq->targ_buf,
1757 dsetdatareq->targ_reply_fn,
1758 dsetdatareq->targ_reply_arg);
1759
1760 return 0;
1761}
1762#endif /* CONFIG_HOST_DSET_SUPPORT */
1763
1764static int
1765wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
1766{
1767 WMI_SCAN_COMPLETE_EVENT *ev;
1768
1769 ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
1770 if ((int)ev->status == 0) {
1771 wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
1772 }
1773 A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
1774 is_probe_ssid = false;
1775
1776 return 0;
1777}
1778
1779/*
1780 * Target is reporting a programming error. This is for
1781 * developer aid only. Target only checks a few common violations
1782 * and it is responsibility of host to do all error checking.
1783 * Behavior of target after wmi error event is undefined.
1784 * A reset is recommended.
1785 */
1786static int
1787wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1788{
1789 WMI_CMD_ERROR_EVENT *ev;
1790
1791 ev = (WMI_CMD_ERROR_EVENT *)datap;
1792 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
1793 switch (ev->errorCode) {
1794 case (INVALID_PARAM):
1795 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
1796 break;
1797 case (ILLEGAL_STATE):
1798 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
1799 break;
1800 case (INTERNAL_ERROR):
1801 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
1802 break;
1803 }
1804
1805 return 0;
1806}
1807
1808
1809static int
1810wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1811{
1812 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1813
1814 A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
1815
1816 return 0;
1817}
1818
1819static int
1820wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1821{
1822 WMI_RSSI_THRESHOLD_EVENT *reply;
1823 WMI_RSSI_THRESHOLD_VAL newThreshold;
1824 WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
1825 SQ_THRESHOLD_PARAMS *sq_thresh =
1826 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
1827 u8 upper_rssi_threshold, lower_rssi_threshold;
1828 s16 rssi;
1829
1830 if (len < sizeof(*reply)) {
1831 return A_EINVAL;
1832 }
1833 reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
1834 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1835 newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range;
1836 rssi = reply->rssi;
1837
1838 /*
1839 * Identify the threshold breached and communicate that to the app. After
1840 * that install a new set of thresholds based on the signal quality
1841 * reported by the target
1842 */
1843 if (newThreshold) {
1844 /* Upper threshold breached */
1845 if (rssi < sq_thresh->upper_threshold[0]) {
1846 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: "
1847 " %d\n", DBGARG, rssi));
1848 } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1849 (rssi >= sq_thresh->upper_threshold[0]))
1850 {
1851 newThreshold = WMI_RSSI_THRESHOLD1_ABOVE;
1852 } else if ((rssi < sq_thresh->upper_threshold[2]) &&
1853 (rssi >= sq_thresh->upper_threshold[1]))
1854 {
1855 newThreshold = WMI_RSSI_THRESHOLD2_ABOVE;
1856 } else if ((rssi < sq_thresh->upper_threshold[3]) &&
1857 (rssi >= sq_thresh->upper_threshold[2]))
1858 {
1859 newThreshold = WMI_RSSI_THRESHOLD3_ABOVE;
1860 } else if ((rssi < sq_thresh->upper_threshold[4]) &&
1861 (rssi >= sq_thresh->upper_threshold[3]))
1862 {
1863 newThreshold = WMI_RSSI_THRESHOLD4_ABOVE;
1864 } else if ((rssi < sq_thresh->upper_threshold[5]) &&
1865 (rssi >= sq_thresh->upper_threshold[4]))
1866 {
1867 newThreshold = WMI_RSSI_THRESHOLD5_ABOVE;
1868 } else if (rssi >= sq_thresh->upper_threshold[5]) {
1869 newThreshold = WMI_RSSI_THRESHOLD6_ABOVE;
1870 }
1871 } else {
1872 /* Lower threshold breached */
1873 if (rssi > sq_thresh->lower_threshold[0]) {
1874 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: "
1875 "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0]));
1876 } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1877 (rssi <= sq_thresh->lower_threshold[0]))
1878 {
1879 newThreshold = WMI_RSSI_THRESHOLD6_BELOW;
1880 } else if ((rssi > sq_thresh->lower_threshold[2]) &&
1881 (rssi <= sq_thresh->lower_threshold[1]))
1882 {
1883 newThreshold = WMI_RSSI_THRESHOLD5_BELOW;
1884 } else if ((rssi > sq_thresh->lower_threshold[3]) &&
1885 (rssi <= sq_thresh->lower_threshold[2]))
1886 {
1887 newThreshold = WMI_RSSI_THRESHOLD4_BELOW;
1888 } else if ((rssi > sq_thresh->lower_threshold[4]) &&
1889 (rssi <= sq_thresh->lower_threshold[3]))
1890 {
1891 newThreshold = WMI_RSSI_THRESHOLD3_BELOW;
1892 } else if ((rssi > sq_thresh->lower_threshold[5]) &&
1893 (rssi <= sq_thresh->lower_threshold[4]))
1894 {
1895 newThreshold = WMI_RSSI_THRESHOLD2_BELOW;
1896 } else if (rssi <= sq_thresh->lower_threshold[5]) {
1897 newThreshold = WMI_RSSI_THRESHOLD1_BELOW;
1898 }
1899 }
1900 /* Calculate and install the next set of thresholds */
1901 lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh,
1902 sq_thresh->lower_threshold_valid_count);
1903 upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh,
1904 sq_thresh->upper_threshold_valid_count);
1905 /* Issue a wmi command to install the thresholds */
1906 cmd.thresholdAbove1_Val = upper_rssi_threshold;
1907 cmd.thresholdBelow1_Val = lower_rssi_threshold;
1908 cmd.weight = sq_thresh->weight;
1909 cmd.pollTime = sq_thresh->polling_interval;
1910
1911 rssi_event_value = rssi;
1912
1913 if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
1914 A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
1915 DBGARG));
1916 }
1917
1918 A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
1919
1920 return 0;
1921}
1922
1923
1924static int
1925wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1926{
1927 WMI_TARGET_ERROR_REPORT_EVENT *reply;
1928
1929 if (len < sizeof(*reply)) {
1930 return A_EINVAL;
1931 }
1932 reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
1933 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1934
1935 A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
1936
1937 return 0;
1938}
1939
1940static int
1941wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1942{
1943 WMI_CAC_EVENT *reply;
1944 WMM_TSPEC_IE *tspec_ie;
1945 u16 activeTsids;
1946
1947 if (len < sizeof(*reply)) {
1948 return A_EINVAL;
1949 }
1950 reply = (WMI_CAC_EVENT *)datap;
1951
1952 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1953
1954 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
1955 (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) {
1956 tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1957
1958 wmi_delete_pstream_cmd(wmip, reply->ac,
1959 (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1960 }
1961 else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1962 u8 i;
1963
1964 /* following assumes that there is only one outstanding ADDTS request
1965 when this event is received */
1966 LOCK_WMI(wmip);
1967 activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
1968 UNLOCK_WMI(wmip);
1969
1970 for (i = 0; i < sizeof(activeTsids) * 8; i++) {
1971 if ((activeTsids >> i) & 1) {
1972 break;
1973 }
1974 }
1975 if (i < (sizeof(activeTsids) * 8)) {
1976 wmi_delete_pstream_cmd(wmip, reply->ac, i);
1977 }
1978 }
1979 /*
1980 * Ev#72990: Clear active tsids and Add missing handling
1981 * for delete qos stream from AP
1982 */
1983 else if (reply->cac_indication == CAC_INDICATION_DELETE) {
1984 u8 tsid = 0;
1985
1986 tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1987 tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1988 LOCK_WMI(wmip);
1989 wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid);
1990 activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
1991 UNLOCK_WMI(wmip);
1992
1993
1994 /* Indicate stream inactivity to driver layer only if all tsids
1995 * within this AC are deleted.
1996 */
1997 if (!activeTsids) {
1998 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac);
1999 wmip->wmi_fatPipeExists &= ~(1 << reply->ac);
2000 }
2001 }
2002
2003 A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
2004 reply->cac_indication, reply->statusCode,
2005 reply->tspecSuggestion);
2006
2007 return 0;
2008}
2009
2010static int
2011wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2012{
2013 WMI_CHANNEL_CHANGE_EVENT *reply;
2014
2015 if (len < sizeof(*reply)) {
2016 return A_EINVAL;
2017 }
2018 reply = (WMI_CHANNEL_CHANGE_EVENT *)datap;
2019 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2020
2021 A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
2022 reply->newChannel);
2023
2024 return 0;
2025}
2026
2027static int
2028wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
2029{
2030 WMIX_HB_CHALLENGE_RESP_EVENT *reply;
2031
2032 if (len < sizeof(*reply)) {
2033 return A_EINVAL;
2034 }
2035 reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
2036 A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
2037
2038 A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
2039
2040 return 0;
2041}
2042
2043static int
2044wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2045{
2046 WMI_TARGET_ROAM_TBL *reply;
2047
2048 if (len < sizeof(*reply)) {
2049 return A_EINVAL;
2050 }
2051 reply = (WMI_TARGET_ROAM_TBL *)datap;
2052 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2053
2054 A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
2055
2056 return 0;
2057}
2058
2059static int
2060wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2061{
2062 WMI_TARGET_ROAM_DATA *reply;
2063
2064 if (len < sizeof(*reply)) {
2065 return A_EINVAL;
2066 }
2067 reply = (WMI_TARGET_ROAM_DATA *)datap;
2068 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2069
2070 A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
2071
2072 return 0;
2073}
2074
2075static int
2076wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2077{
2078 if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
2079 return A_EINVAL;
2080 }
2081 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2082
2083 A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
2084
2085 return 0;
2086}
2087
2088static int
2089wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2090{
2091 WMI_SNR_THRESHOLD_EVENT *reply;
2092 SQ_THRESHOLD_PARAMS *sq_thresh =
2093 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
2094 WMI_SNR_THRESHOLD_VAL newThreshold;
2095 WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
2096 u8 upper_snr_threshold, lower_snr_threshold;
2097 s16 snr;
2098
2099 if (len < sizeof(*reply)) {
2100 return A_EINVAL;
2101 }
2102 reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
2103 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2104
2105 newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range;
2106 snr = reply->snr;
2107 /*
2108 * Identify the threshold breached and communicate that to the app. After
2109 * that install a new set of thresholds based on the signal quality
2110 * reported by the target
2111 */
2112 if (newThreshold) {
2113 /* Upper threshold breached */
2114 if (snr < sq_thresh->upper_threshold[0]) {
2115 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: "
2116 "%d\n", DBGARG, snr));
2117 } else if ((snr < sq_thresh->upper_threshold[1]) &&
2118 (snr >= sq_thresh->upper_threshold[0]))
2119 {
2120 newThreshold = WMI_SNR_THRESHOLD1_ABOVE;
2121 } else if ((snr < sq_thresh->upper_threshold[2]) &&
2122 (snr >= sq_thresh->upper_threshold[1]))
2123 {
2124 newThreshold = WMI_SNR_THRESHOLD2_ABOVE;
2125 } else if ((snr < sq_thresh->upper_threshold[3]) &&
2126 (snr >= sq_thresh->upper_threshold[2]))
2127 {
2128 newThreshold = WMI_SNR_THRESHOLD3_ABOVE;
2129 } else if (snr >= sq_thresh->upper_threshold[3]) {
2130 newThreshold = WMI_SNR_THRESHOLD4_ABOVE;
2131 }
2132 } else {
2133 /* Lower threshold breached */
2134 if (snr > sq_thresh->lower_threshold[0]) {
2135 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: "
2136 "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0]));
2137 } else if ((snr > sq_thresh->lower_threshold[1]) &&
2138 (snr <= sq_thresh->lower_threshold[0]))
2139 {
2140 newThreshold = WMI_SNR_THRESHOLD4_BELOW;
2141 } else if ((snr > sq_thresh->lower_threshold[2]) &&
2142 (snr <= sq_thresh->lower_threshold[1]))
2143 {
2144 newThreshold = WMI_SNR_THRESHOLD3_BELOW;
2145 } else if ((snr > sq_thresh->lower_threshold[3]) &&
2146 (snr <= sq_thresh->lower_threshold[2]))
2147 {
2148 newThreshold = WMI_SNR_THRESHOLD2_BELOW;
2149 } else if (snr <= sq_thresh->lower_threshold[3]) {
2150 newThreshold = WMI_SNR_THRESHOLD1_BELOW;
2151 }
2152 }
2153
2154 /* Calculate and install the next set of thresholds */
2155 lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh,
2156 sq_thresh->lower_threshold_valid_count);
2157 upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh,
2158 sq_thresh->upper_threshold_valid_count);
2159
2160 /* Issue a wmi command to install the thresholds */
2161 cmd.thresholdAbove1_Val = upper_snr_threshold;
2162 cmd.thresholdBelow1_Val = lower_snr_threshold;
2163 cmd.weight = sq_thresh->weight;
2164 cmd.pollTime = sq_thresh->polling_interval;
2165
2166 A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n"
2167 ,DBGARG, snr, newThreshold, lower_snr_threshold,
2168 upper_snr_threshold));
2169
2170 snr_event_value = snr;
2171
2172 if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
2173 A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
2174 DBGARG));
2175 }
2176 A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
2177
2178 return 0;
2179}
2180
2181static int
2182wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2183{
2184 WMI_LQ_THRESHOLD_EVENT *reply;
2185
2186 if (len < sizeof(*reply)) {
2187 return A_EINVAL;
2188 }
2189 reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
2190 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2191
2192 A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt,
2193 (WMI_LQ_THRESHOLD_VAL) reply->range,
2194 reply->lq);
2195
2196 return 0;
2197}
2198
2199static int
2200wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2201{
2202 u16 ap_info_entry_size;
2203 WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
2204 WMI_AP_INFO_V1 *ap_info_v1;
2205 u8 i;
2206
2207 if (len < sizeof(WMI_APLIST_EVENT)) {
2208 return A_EINVAL;
2209 }
2210
2211 if (ev->apListVer == APLIST_VER1) {
2212 ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
2213 ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
2214 } else {
2215 return A_EINVAL;
2216 }
2217
2218 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
2219 if (len < (int)(sizeof(WMI_APLIST_EVENT) +
2220 (ev->numAP - 1) * ap_info_entry_size))
2221 {
2222 return A_EINVAL;
2223 }
2224
2225 /*
2226 * AP List Ver1 Contents
2227 */
2228 for (i = 0; i < ev->numAP; i++) {
2229 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
2230 "Channel %d\n", i,
2231 ap_info_v1->bssid[0], ap_info_v1->bssid[1],
2232 ap_info_v1->bssid[2], ap_info_v1->bssid[3],
2233 ap_info_v1->bssid[4], ap_info_v1->bssid[5],
2234 ap_info_v1->channel));
2235 ap_info_v1++;
2236 }
2237 return 0;
2238}
2239
2240static int
2241wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2242{
2243 u32 dropped;
2244
2245 dropped = *((u32 *)datap);
2246 datap += sizeof(dropped);
2247 len -= sizeof(dropped);
2248 A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
2249 return 0;
2250}
2251
2252/*
2253 * Called to send a wmi command. Command specific data is already built
2254 * on osbuf and current osbuf->data points to it.
2255 */
2256int
2257wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
2258 WMI_SYNC_FLAG syncflag)
2259{
2260 int status;
2261#define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
2262 WMI_CMD_HDR *cHdr;
2263 HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id;
2264
2265 A_ASSERT(osbuf != NULL);
2266
2267 if (syncflag >= END_WMIFLAG) {
2268 A_NETBUF_FREE(osbuf);
2269 return A_EINVAL;
2270 }
2271
2272 if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2273 /*
2274 * We want to make sure all data currently queued is transmitted before
2275 * the cmd execution. Establish a new sync point.
2276 */
2277 wmi_sync_point(wmip);
2278 }
2279
2280 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
2281 A_NETBUF_FREE(osbuf);
2282 return A_NO_MEMORY;
2283 }
2284
2285 cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
2286 cHdr->commandId = (u16) cmdId;
2287 cHdr->info1 = 0; // added for virtual interface
2288
2289 /*
2290 * Only for OPT_TX_CMD, use BE endpoint.
2291 */
2292 if (IS_OPT_TX_CMD(cmdId)) {
2293 if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
2294 A_NETBUF_FREE(osbuf);
2295 return status;
2296 }
2297 eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE);
2298 }
2299 A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid);
2300
2301 if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2302 /*
2303 * We want to make sure all new data queued waits for the command to
2304 * execute. Establish a new sync point.
2305 */
2306 wmi_sync_point(wmip);
2307 }
2308 return (0);
2309#undef IS_OPT_TX_CMD
2310}
2311
2312int
2313wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
2314 WMI_SYNC_FLAG syncflag)
2315{
2316 WMIX_CMD_HDR *cHdr;
2317
2318 if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
2319 A_NETBUF_FREE(osbuf);
2320 return A_NO_MEMORY;
2321 }
2322
2323 cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
2324 cHdr->commandId = (u32) cmdId;
2325
2326 return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
2327}
2328
2329int
2330wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
2331 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
2332 CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
2333 CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
2334 int ssidLength, u8 *ssid,
2335 u8 *bssid, u16 channel, u32 ctrl_flags)
2336{
2337 void *osbuf;
2338 WMI_CONNECT_CMD *cc;
2339 wmip->wmi_traffic_class = 100;
2340
2341 if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
2342 return A_EINVAL;
2343 }
2344 if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
2345 return A_EINVAL;
2346 }
2347
2348 osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
2349 if (osbuf == NULL) {
2350 return A_NO_MEMORY;
2351 }
2352
2353 A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
2354
2355 cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2356 A_MEMZERO(cc, sizeof(*cc));
2357
2358 if (ssidLength)
2359 {
2360 memcpy(cc->ssid, ssid, ssidLength);
2361 }
2362
2363 cc->ssidLength = ssidLength;
2364 cc->networkType = netType;
2365 cc->dot11AuthMode = dot11AuthMode;
2366 cc->authMode = authMode;
2367 cc->pairwiseCryptoType = pairwiseCrypto;
2368 cc->pairwiseCryptoLen = pairwiseCryptoLen;
2369 cc->groupCryptoType = groupCrypto;
2370 cc->groupCryptoLen = groupCryptoLen;
2371 cc->channel = channel;
2372 cc->ctrl_flags = ctrl_flags;
2373
2374 if (bssid != NULL) {
2375 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2376 }
2377
2378 wmip->wmi_pair_crypto_type = pairwiseCrypto;
2379 wmip->wmi_grp_crypto_type = groupCrypto;
2380
2381 return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
2382}
2383
2384int
2385wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
2386{
2387 void *osbuf;
2388 WMI_RECONNECT_CMD *cc;
2389 wmip->wmi_traffic_class = 100;
2390
2391 osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
2392 if (osbuf == NULL) {
2393 return A_NO_MEMORY;
2394 }
2395
2396 A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
2397
2398 cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2399 A_MEMZERO(cc, sizeof(*cc));
2400
2401 cc->channel = channel;
2402
2403 if (bssid != NULL) {
2404 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2405 }
2406
2407 return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
2408}
2409
2410int
2411wmi_disconnect_cmd(struct wmi_t *wmip)
2412{
2413 int status;
2414 wmip->wmi_traffic_class = 100;
2415
2416 /* Bug fix for 24817(elevator bug) - the disconnect command does not
2417 need to do a SYNC before.*/
2418 status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID);
2419
2420 return status;
2421}
2422
2423int
2424wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
2425 u32 forceFgScan, u32 isLegacy,
2426 u32 homeDwellTime, u32 forceScanInterval,
2427 s8 numChan, u16 *channelList)
2428{
2429 void *osbuf;
2430 WMI_START_SCAN_CMD *sc;
2431 s8 size;
2432
2433 size = sizeof (*sc);
2434
2435 if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
2436 return A_EINVAL;
2437 }
2438
2439 if (numChan) {
2440 if (numChan > WMI_MAX_CHANNELS) {
2441 return A_EINVAL;
2442 }
2443 size += sizeof(u16) * (numChan - 1);
2444 }
2445
2446 osbuf = A_NETBUF_ALLOC(size);
2447 if (osbuf == NULL) {
2448 return A_NO_MEMORY;
2449 }
2450
2451 A_NETBUF_PUT(osbuf, size);
2452
2453 sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
2454 sc->scanType = scanType;
2455 sc->forceFgScan = forceFgScan;
2456 sc->isLegacy = isLegacy;
2457 sc->homeDwellTime = homeDwellTime;
2458 sc->forceScanInterval = forceScanInterval;
2459 sc->numChannels = numChan;
2460 if (numChan) {
2461 memcpy(sc->channelList, channelList, numChan * sizeof(u16));
2462 }
2463
2464 return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
2465}
2466
2467int
2468wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
2469 u16 fg_end_sec, u16 bg_sec,
2470 u16 minact_chdw_msec, u16 maxact_chdw_msec,
2471 u16 pas_chdw_msec,
2472 u8 shScanRatio, u8 scanCtrlFlags,
2473 u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
2474{
2475 void *osbuf;
2476 WMI_SCAN_PARAMS_CMD *sc;
2477
2478 osbuf = A_NETBUF_ALLOC(sizeof(*sc));
2479 if (osbuf == NULL) {
2480 return A_NO_MEMORY;
2481 }
2482
2483 A_NETBUF_PUT(osbuf, sizeof(*sc));
2484
2485 sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2486 A_MEMZERO(sc, sizeof(*sc));
2487 sc->fg_start_period = fg_start_sec;
2488 sc->fg_end_period = fg_end_sec;
2489 sc->bg_period = bg_sec;
2490 sc->minact_chdwell_time = minact_chdw_msec;
2491 sc->maxact_chdwell_time = maxact_chdw_msec;
2492 sc->pas_chdwell_time = pas_chdw_msec;
2493 sc->shortScanRatio = shScanRatio;
2494 sc->scanCtrlFlags = scanCtrlFlags;
2495 sc->max_dfsch_act_time = max_dfsch_act_time;
2496 sc->maxact_scan_per_ssid = maxact_scan_per_ssid;
2497
2498 return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
2499 NO_SYNC_WMIFLAG));
2500}
2501
2502int
2503wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
2504{
2505 void *osbuf;
2506 WMI_BSS_FILTER_CMD *cmd;
2507
2508 if (filter >= LAST_BSS_FILTER) {
2509 return A_EINVAL;
2510 }
2511
2512 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2513 if (osbuf == NULL) {
2514 return A_NO_MEMORY;
2515 }
2516
2517 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2518
2519 cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
2520 A_MEMZERO(cmd, sizeof(*cmd));
2521 cmd->bssFilter = filter;
2522 cmd->ieMask = ieMask;
2523
2524 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
2525 NO_SYNC_WMIFLAG));
2526}
2527
2528int
2529wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
2530 u8 ssidLength, u8 *ssid)
2531{
2532 void *osbuf;
2533 WMI_PROBED_SSID_CMD *cmd;
2534
2535 if (index > MAX_PROBED_SSID_INDEX) {
2536 return A_EINVAL;
2537 }
2538 if (ssidLength > sizeof(cmd->ssid)) {
2539 return A_EINVAL;
2540 }
2541 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
2542 return A_EINVAL;
2543 }
2544 if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
2545 return A_EINVAL;
2546 }
2547
2548 if (flag & SPECIFIC_SSID_FLAG) {
2549 is_probe_ssid = true;
2550 }
2551
2552 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2553 if (osbuf == NULL) {
2554 return A_NO_MEMORY;
2555 }
2556
2557 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2558
2559 cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
2560 A_MEMZERO(cmd, sizeof(*cmd));
2561 cmd->entryIndex = index;
2562 cmd->flag = flag;
2563 cmd->ssidLength = ssidLength;
2564 memcpy(cmd->ssid, ssid, ssidLength);
2565
2566 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
2567 NO_SYNC_WMIFLAG));
2568}
2569
2570int
2571wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
2572{
2573 void *osbuf;
2574 WMI_LISTEN_INT_CMD *cmd;
2575
2576 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2577 if (osbuf == NULL) {
2578 return A_NO_MEMORY;
2579 }
2580
2581 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2582
2583 cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
2584 A_MEMZERO(cmd, sizeof(*cmd));
2585 cmd->listenInterval = listenInterval;
2586 cmd->numBeacons = listenBeacons;
2587
2588 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
2589 NO_SYNC_WMIFLAG));
2590}
2591
2592int
2593wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
2594{
2595 void *osbuf;
2596 WMI_BMISS_TIME_CMD *cmd;
2597
2598 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2599 if (osbuf == NULL) {
2600 return A_NO_MEMORY;
2601 }
2602
2603 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2604
2605 cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
2606 A_MEMZERO(cmd, sizeof(*cmd));
2607 cmd->bmissTime = bmissTime;
2608 cmd->numBeacons = bmissBeacons;
2609
2610 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
2611 NO_SYNC_WMIFLAG));
2612}
2613
2614int
2615wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
2616 u8 ieLen, u8 *ieInfo)
2617{
2618 void *osbuf;
2619 WMI_SET_ASSOC_INFO_CMD *cmd;
2620 u16 cmdLen;
2621
2622 cmdLen = sizeof(*cmd) + ieLen - 1;
2623 osbuf = A_NETBUF_ALLOC(cmdLen);
2624 if (osbuf == NULL) {
2625 return A_NO_MEMORY;
2626 }
2627
2628 A_NETBUF_PUT(osbuf, cmdLen);
2629
2630 cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
2631 A_MEMZERO(cmd, cmdLen);
2632 cmd->ieType = ieType;
2633 cmd->bufferSize = ieLen;
2634 memcpy(cmd->assocInfo, ieInfo, ieLen);
2635
2636 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
2637 NO_SYNC_WMIFLAG));
2638}
2639
2640int
2641wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
2642{
2643 void *osbuf;
2644 WMI_POWER_MODE_CMD *cmd;
2645
2646 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2647 if (osbuf == NULL) {
2648 return A_NO_MEMORY;
2649 }
2650
2651 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2652
2653 cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
2654 A_MEMZERO(cmd, sizeof(*cmd));
2655 cmd->powerMode = powerMode;
2656 wmip->wmi_powerMode = powerMode;
2657
2658 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
2659 NO_SYNC_WMIFLAG));
2660}
2661
2662int
2663wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
2664 u16 atim_windows, u16 timeout_value)
2665{
2666 void *osbuf;
2667 WMI_IBSS_PM_CAPS_CMD *cmd;
2668
2669 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2670 if (osbuf == NULL) {
2671 return A_NO_MEMORY;
2672 }
2673
2674 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2675
2676 cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
2677 A_MEMZERO(cmd, sizeof(*cmd));
2678 cmd->power_saving = pmEnable;
2679 cmd->ttl = ttl;
2680 cmd->atim_windows = atim_windows;
2681 cmd->timeout_value = timeout_value;
2682
2683 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
2684 NO_SYNC_WMIFLAG));
2685}
2686
2687int
2688wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
2689 u32 ps_period, u8 sleep_period)
2690{
2691 void *osbuf;
2692 WMI_AP_PS_CMD *cmd;
2693
2694 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2695 if (osbuf == NULL) {
2696 return A_NO_MEMORY;
2697 }
2698
2699 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2700
2701 cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf));
2702 A_MEMZERO(cmd, sizeof(*cmd));
2703 cmd->psType = psType;
2704 cmd->idle_time = idle_time;
2705 cmd->ps_period = ps_period;
2706 cmd->sleep_period = sleep_period;
2707
2708 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID,
2709 NO_SYNC_WMIFLAG));
2710}
2711
2712int
2713wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
2714 u16 psPollNum, u16 dtimPolicy,
2715 u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
2716 u16 ps_fail_event_policy)
2717{
2718 void *osbuf;
2719 WMI_POWER_PARAMS_CMD *pm;
2720
2721 osbuf = A_NETBUF_ALLOC(sizeof(*pm));
2722 if (osbuf == NULL) {
2723 return A_NO_MEMORY;
2724 }
2725
2726 A_NETBUF_PUT(osbuf, sizeof(*pm));
2727
2728 pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2729 A_MEMZERO(pm, sizeof(*pm));
2730 pm->idle_period = idlePeriod;
2731 pm->pspoll_number = psPollNum;
2732 pm->dtim_policy = dtimPolicy;
2733 pm->tx_wakeup_policy = tx_wakeup_policy;
2734 pm->num_tx_to_wakeup = num_tx_to_wakeup;
2735 pm->ps_fail_event_policy = ps_fail_event_policy;
2736
2737 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
2738 NO_SYNC_WMIFLAG));
2739}
2740
2741int
2742wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
2743{
2744 void *osbuf;
2745 WMI_DISC_TIMEOUT_CMD *cmd;
2746
2747 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2748 if (osbuf == NULL) {
2749 return A_NO_MEMORY;
2750 }
2751
2752 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2753
2754 cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
2755 A_MEMZERO(cmd, sizeof(*cmd));
2756 cmd->disconnectTimeout = timeout;
2757
2758 return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
2759 NO_SYNC_WMIFLAG));
2760}
2761
2762int
2763wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
2764 u8 keyUsage, u8 keyLength, u8 *keyRSC,
2765 u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
2766 WMI_SYNC_FLAG sync_flag)
2767{
2768 void *osbuf;
2769 WMI_ADD_CIPHER_KEY_CMD *cmd;
2770
2771 if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
2772 (keyMaterial == NULL))
2773 {
2774 return A_EINVAL;
2775 }
2776
2777 if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
2778 return A_EINVAL;
2779 }
2780
2781 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2782 if (osbuf == NULL) {
2783 return A_NO_MEMORY;
2784 }
2785
2786 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2787
2788 cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2789 A_MEMZERO(cmd, sizeof(*cmd));
2790 cmd->keyIndex = keyIndex;
2791 cmd->keyType = keyType;
2792 cmd->keyUsage = keyUsage;
2793 cmd->keyLength = keyLength;
2794 memcpy(cmd->key, keyMaterial, keyLength);
2795#ifdef WAPI_ENABLE
2796 if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
2797#else
2798 if (NULL != keyRSC) {
2799#endif // WAPI_ENABLE
2800 memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
2801 }
2802 cmd->key_op_ctrl = key_op_ctrl;
2803
2804 if(macAddr) {
2805 memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
2806 }
2807
2808 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
2809}
2810
2811int
2812wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
2813{
2814 void *osbuf;
2815 WMI_ADD_KRK_CMD *cmd;
2816
2817 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2818 if (osbuf == NULL) {
2819 return A_NO_MEMORY;
2820 }
2821
2822 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2823
2824 cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
2825 A_MEMZERO(cmd, sizeof(*cmd));
2826 memcpy(cmd->krk, krk, WMI_KRK_LEN);
2827
2828 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
2829}
2830
2831int
2832wmi_delete_krk_cmd(struct wmi_t *wmip)
2833{
2834 return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
2835}
2836
2837int
2838wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
2839{
2840 void *osbuf;
2841 WMI_DELETE_CIPHER_KEY_CMD *cmd;
2842
2843 if (keyIndex > WMI_MAX_KEY_INDEX) {
2844 return A_EINVAL;
2845 }
2846
2847 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2848 if (osbuf == NULL) {
2849 return A_NO_MEMORY;
2850 }
2851
2852 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2853
2854 cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2855 A_MEMZERO(cmd, sizeof(*cmd));
2856 cmd->keyIndex = keyIndex;
2857
2858 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
2859 NO_SYNC_WMIFLAG));
2860}
2861
2862int
2863wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
2864 bool set)
2865{
2866 void *osbuf;
2867 WMI_SET_PMKID_CMD *cmd;
2868
2869 if (bssid == NULL) {
2870 return A_EINVAL;
2871 }
2872
2873 if ((set == true) && (pmkId == NULL)) {
2874 return A_EINVAL;
2875 }
2876
2877 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2878 if (osbuf == NULL) {
2879 return A_NO_MEMORY;
2880 }
2881
2882 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2883
2884 cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
2885 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
2886 if (set == true) {
2887 memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
2888 cmd->enable = PMKID_ENABLE;
2889 } else {
2890 A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
2891 cmd->enable = PMKID_DISABLE;
2892 }
2893
2894 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
2895}
2896
2897int
2898wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
2899{
2900 void *osbuf;
2901 WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
2902
2903 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2904 if (osbuf == NULL) {
2905 return A_NO_MEMORY;
2906 }
2907
2908 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2909
2910 cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
2911 cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
2912
2913 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
2914 NO_SYNC_WMIFLAG));
2915}
2916
2917int
2918wmi_set_akmp_params_cmd(struct wmi_t *wmip,
2919 WMI_SET_AKMP_PARAMS_CMD *akmpParams)
2920{
2921 void *osbuf;
2922 WMI_SET_AKMP_PARAMS_CMD *cmd;
2923
2924 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2925 if (osbuf == NULL) {
2926 return A_NO_MEMORY;
2927 }
2928
2929 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2930 cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2931 cmd->akmpInfo = akmpParams->akmpInfo;
2932
2933 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
2934 NO_SYNC_WMIFLAG));
2935}
2936
2937int
2938wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
2939 WMI_SET_PMKID_LIST_CMD *pmkInfo)
2940{
2941 void *osbuf;
2942 WMI_SET_PMKID_LIST_CMD *cmd;
2943 u16 cmdLen;
2944 u8 i;
2945
2946 cmdLen = sizeof(pmkInfo->numPMKID) +
2947 pmkInfo->numPMKID * sizeof(WMI_PMKID);
2948
2949 osbuf = A_NETBUF_ALLOC(cmdLen);
2950 if (osbuf == NULL) {
2951 return A_NO_MEMORY;
2952 }
2953
2954 A_NETBUF_PUT(osbuf, cmdLen);
2955 cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
2956 cmd->numPMKID = pmkInfo->numPMKID;
2957
2958 for (i = 0; i < cmd->numPMKID; i++) {
2959 memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
2960 WMI_PMKID_LEN);
2961 }
2962
2963 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
2964 NO_SYNC_WMIFLAG));
2965}
2966
2967int
2968wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
2969{
2970 return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
2971}
2972
2973int
2974wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
2975{
2976 WMI_DATA_HDR *dtHdr;
2977
2978 A_ASSERT( eid != wmip->wmi_endpoint_id);
2979 A_ASSERT(osbuf != NULL);
2980
2981 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
2982 return A_NO_MEMORY;
2983 }
2984
2985 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
2986 dtHdr->info =
2987 (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
2988
2989 dtHdr->info3 = 0;
2990 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid));
2991
2992 return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid));
2993}
2994
2995typedef struct _WMI_DATA_SYNC_BUFS {
2996 u8 trafficClass;
2997 void *osbuf;
2998}WMI_DATA_SYNC_BUFS;
2999
3000static int
3001wmi_sync_point(struct wmi_t *wmip)
3002{
3003 void *cmd_osbuf;
3004 WMI_SYNC_CMD *cmd;
3005 WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
3006 u8 i,numPriStreams=0;
3007 int status = 0;
3008
3009 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3010
3011 memset(dataSyncBufs,0,sizeof(dataSyncBufs));
3012
3013 /* lock out while we walk through the priority list and assemble our local array */
3014 LOCK_WMI(wmip);
3015
3016 for (i=0; i < WMM_NUM_AC ; i++) {
3017 if (wmip->wmi_fatPipeExists & (1 << i)) {
3018 numPriStreams++;
3019 dataSyncBufs[numPriStreams-1].trafficClass = i;
3020 }
3021 }
3022
3023 UNLOCK_WMI(wmip);
3024
3025 /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
3026
3027 do {
3028 /*
3029 * We allocate all network buffers needed so we will be able to
3030 * send all required frames.
3031 */
3032 cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3033 if (cmd_osbuf == NULL) {
3034 status = A_NO_MEMORY;
3035 break;
3036 }
3037
3038 A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd));
3039
3040 cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf));
3041 A_MEMZERO(cmd, sizeof(*cmd));
3042
3043 /* In the SYNC cmd sent on the control Ep, send a bitmap of the data
3044 * eps on which the Data Sync will be sent
3045 */
3046 cmd->dataSyncMap = wmip->wmi_fatPipeExists;
3047
3048 for (i=0; i < numPriStreams ; i++) {
3049 dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
3050 if (dataSyncBufs[i].osbuf == NULL) {
3051 status = A_NO_MEMORY;
3052 break;
3053 }
3054 } //end for
3055
3056 /* if Buffer allocation for any of the dataSync fails, then do not
3057 * send the Synchronize cmd on the control ep
3058 */
3059 if (status) {
3060 break;
3061 }
3062
3063 /*
3064 * Send sync cmd followed by sync data messages on all endpoints being
3065 * used
3066 */
3067 status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
3068 NO_SYNC_WMIFLAG);
3069
3070 if (status) {
3071 break;
3072 }
3073 /* cmd buffer sent, we no longer own it */
3074 cmd_osbuf = NULL;
3075
3076 for(i=0; i < numPriStreams; i++) {
3077 A_ASSERT(dataSyncBufs[i].osbuf != NULL);
3078 status = wmi_dataSync_send(wmip,
3079 dataSyncBufs[i].osbuf,
3080 A_WMI_Ac2EndpointID(wmip->wmi_devt,
3081 dataSyncBufs[i].
3082 trafficClass)
3083 );
3084
3085 if (status) {
3086 break;
3087 }
3088 /* we don't own this buffer anymore, NULL it out of the array so it
3089 * won't get cleaned up */
3090 dataSyncBufs[i].osbuf = NULL;
3091 } //end for
3092
3093 } while(false);
3094
3095 /* free up any resources left over (possibly due to an error) */
3096
3097 if (cmd_osbuf != NULL) {
3098 A_NETBUF_FREE(cmd_osbuf);
3099 }
3100
3101 for (i = 0; i < numPriStreams; i++) {
3102 if (dataSyncBufs[i].osbuf != NULL) {
3103 A_NETBUF_FREE(dataSyncBufs[i].osbuf);
3104 }
3105 }
3106
3107 return (status);
3108}
3109
3110int
3111wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
3112{
3113 void *osbuf;
3114 WMI_CREATE_PSTREAM_CMD *cmd;
3115 u8 fatPipeExistsForAC=0;
3116 s32 minimalPHY = 0;
3117 s32 nominalPHY = 0;
3118
3119 /* Validate all the parameters. */
3120 if( !((params->userPriority < 8) &&
3121 (params->userPriority <= 0x7) &&
3122 (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) &&
3123 (params->trafficDirection == UPLINK_TRAFFIC ||
3124 params->trafficDirection == DNLINK_TRAFFIC ||
3125 params->trafficDirection == BIDIR_TRAFFIC) &&
3126 (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
3127 params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
3128 (params->voicePSCapability == DISABLE_FOR_THIS_AC ||
3129 params->voicePSCapability == ENABLE_FOR_THIS_AC ||
3130 params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
3131 (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
3132 {
3133 return A_EINVAL;
3134 }
3135
3136 //
3137 // check nominal PHY rate is >= minimalPHY, so that DUT
3138 // can allow TSRS IE
3139 //
3140
3141 // get the physical rate
3142 minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps
3143
3144 // check minimal phy < nominal phy rate
3145 //
3146 if (params->nominalPHY >= minimalPHY)
3147 {
3148 nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps
3149 A_DPRINTF(DBG_WMI,
3150 (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG,
3151 minimalPHY, nominalPHY));
3152
3153 params->nominalPHY = nominalPHY;
3154 }
3155 else
3156 {
3157 params->nominalPHY = 0;
3158 }
3159
3160 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3161 if (osbuf == NULL) {
3162 return A_NO_MEMORY;
3163 }
3164
3165 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3166
3167 A_DPRINTF(DBG_WMI,
3168 (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
3169 params->trafficClass, params->tsid));
3170
3171 cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3172 A_MEMZERO(cmd, sizeof(*cmd));
3173 memcpy(cmd, params, sizeof(*cmd));
3174
3175 /* this is an implicitly created Fat pipe */
3176 if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
3177 LOCK_WMI(wmip);
3178 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3179 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3180 UNLOCK_WMI(wmip);
3181 } else {
3182 /* this is an explicitly created thin stream within a fat pipe */
3183 LOCK_WMI(wmip);
3184 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3185 wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
3186 /* if a thinstream becomes active, the fat pipe automatically
3187 * becomes active
3188 */
3189 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3190 UNLOCK_WMI(wmip);
3191 }
3192
3193 /* Indicate activty change to driver layer only if this is the
3194 * first TSID to get created in this AC explicitly or an implicit
3195 * fat pipe is getting created.
3196 */
3197 if (!fatPipeExistsForAC) {
3198 A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
3199 }
3200
3201 /* mike: should be SYNC_BEFORE_WMIFLAG */
3202 return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
3203 NO_SYNC_WMIFLAG));
3204}
3205
3206int
3207wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
3208{
3209 void *osbuf;
3210 WMI_DELETE_PSTREAM_CMD *cmd;
3211 int status;
3212 u16 activeTsids=0;
3213
3214 /* validate the parameters */
3215 if (trafficClass > 3) {
3216 A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass));
3217 return A_EINVAL;
3218 }
3219
3220 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3221 if (osbuf == NULL) {
3222 return A_NO_MEMORY;
3223 }
3224
3225 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3226
3227 cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3228 A_MEMZERO(cmd, sizeof(*cmd));
3229
3230 cmd->trafficClass = trafficClass;
3231 cmd->tsid = tsid;
3232
3233 LOCK_WMI(wmip);
3234 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3235 UNLOCK_WMI(wmip);
3236
3237 /* Check if the tsid was created & exists */
3238 if (!(activeTsids & (1<<tsid))) {
3239
3240 A_NETBUF_FREE(osbuf);
3241 A_DPRINTF(DBG_WMI,
3242 (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
3243 /* TODO: return a more appropriate err code */
3244 return A_ERROR;
3245 }
3246
3247 A_DPRINTF(DBG_WMI,
3248 (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
3249
3250 status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
3251 SYNC_BEFORE_WMIFLAG));
3252
3253 LOCK_WMI(wmip);
3254 wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
3255 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3256 UNLOCK_WMI(wmip);
3257
3258
3259 /* Indicate stream inactivity to driver layer only if all tsids
3260 * within this AC are deleted.
3261 */
3262 if(!activeTsids) {
3263 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
3264 wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
3265 }
3266
3267 return status;
3268}
3269
3270int
3271wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
3272{
3273 void *osbuf;
3274 WMI_FRAME_RATES_CMD *cmd;
3275 u8 frameType;
3276
3277 A_DPRINTF(DBG_WMI,
3278 (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
3279
3280 if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) ||
3281 (subType > 15)){
3282
3283 return A_EINVAL;
3284 }
3285
3286 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3287 if (osbuf == NULL) {
3288 return A_NO_MEMORY;
3289 }
3290
3291 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3292
3293 cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3294 A_MEMZERO(cmd, sizeof(*cmd));
3295
3296 frameType = (u8)((subType << 4) | type);
3297
3298 cmd->bEnableMask = bEnable;
3299 cmd->frameType = frameType;
3300 cmd->frameRateMask = rateMask;
3301
3302 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG));
3303}
3304
3305/*
3306 * used to set the bit rate. rate is in Kbps. If rate == -1
3307 * then auto selection is used.
3308 */
3309int
3310wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
3311{
3312 void *osbuf;
3313 WMI_BIT_RATE_CMD *cmd;
3314 s8 drix, mrix, crix, ret_val;
3315
3316 if (dataRate != -1) {
3317 ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
3318 if(ret_val == A_EINVAL){
3319 return A_EINVAL;
3320 }
3321 } else {
3322 drix = -1;
3323 }
3324
3325 if (mgmtRate != -1) {
3326 ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix);
3327 if(ret_val == A_EINVAL){
3328 return A_EINVAL;
3329 }
3330 } else {
3331 mrix = -1;
3332 }
3333 if (ctlRate != -1) {
3334 ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix);
3335 if(ret_val == A_EINVAL){
3336 return A_EINVAL;
3337 }
3338 } else {
3339 crix = -1;
3340 }
3341 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3342 if (osbuf == NULL) {
3343 return A_NO_MEMORY;
3344 }
3345
3346 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3347
3348 cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
3349 A_MEMZERO(cmd, sizeof(*cmd));
3350
3351 cmd->rateIndex = drix;
3352 cmd->mgmtRateIndex = mrix;
3353 cmd->ctlRateIndex = crix;
3354
3355
3356 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
3357}
3358
3359int
3360wmi_get_bitrate_cmd(struct wmi_t *wmip)
3361{
3362 return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
3363}
3364
3365/*
3366 * Returns true iff the given rate index is legal in the current PHY mode.
3367 */
3368bool
3369wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
3370{
3371 WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
3372 bool isValid = true;
3373 switch(phyMode) {
3374 case WMI_11A_MODE:
3375 if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
3376 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3377 isValid = false;
3378 }
3379 } else {
3380 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
3381 isValid = false;
3382 }
3383 }
3384 break;
3385
3386 case WMI_11B_MODE:
3387 if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
3388 isValid = false;
3389 }
3390 break;
3391
3392 case WMI_11GONLY_MODE:
3393 if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3394 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3395 isValid = false;
3396 }
3397 } else {
3398 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
3399 isValid = false;
3400 }
3401 }
3402 break;
3403
3404 case WMI_11G_MODE:
3405 case WMI_11AG_MODE:
3406 if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3407 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3408 isValid = false;
3409 }
3410 } else {
3411 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
3412 isValid = false;
3413 }
3414 }
3415 break;
3416 default:
3417 A_ASSERT(false);
3418 break;
3419 }
3420
3421 return isValid;
3422}
3423
3424s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
3425{
3426 s8 i;
3427
3428 for (i=0;;i++)
3429 {
3430 if (wmi_rateTable[(u32) i][0] == 0) {
3431 return A_EINVAL;
3432 }
3433 if (wmi_rateTable[(u32) i][0] == rate) {
3434 break;
3435 }
3436 }
3437
3438 if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
3439 return A_EINVAL;
3440 }
3441
3442 *rate_idx = i;
3443 return 0;
3444}
3445
3446int
3447wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
3448{
3449 void *osbuf;
3450 WMI_FIX_RATES_CMD *cmd;
3451#if 0
3452 s32 rateIndex;
3453/* This check does not work for AR6003 as the HT modes are enabled only when
3454 * the STA is connected to a HT_BSS and is not based only on channel. It is
3455 * safe to skip this check however because rate control will only use rates
3456 * that are permitted by the valid rate mask and the fix rate mask. Meaning
3457 * the fix rate mask is not sufficient by itself to cause an invalid rate
3458 * to be used. */
3459 /* Make sure all rates in the mask are valid in the current PHY mode */
3460 for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
3461 if((1 << rateIndex) & (u32)fixRatesMask) {
3462 if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
3463 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
3464 return A_EINVAL;
3465 }
3466 }
3467 }
3468#endif
3469
3470
3471 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3472 if (osbuf == NULL) {
3473 return A_NO_MEMORY;
3474 }
3475
3476 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3477
3478 cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3479 A_MEMZERO(cmd, sizeof(*cmd));
3480
3481 cmd->fixRateMask = fixRatesMask;
3482
3483 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
3484}
3485
3486int
3487wmi_get_ratemask_cmd(struct wmi_t *wmip)
3488{
3489 return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
3490}
3491
3492int
3493wmi_get_channelList_cmd(struct wmi_t *wmip)
3494{
3495 return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
3496}
3497
3498/*
3499 * used to generate a wmi sey channel Parameters cmd.
3500 * mode should always be specified and corresponds to the phy mode of the
3501 * wlan.
3502 * numChan should alway sbe specified. If zero indicates that all available
3503 * channels should be used.
3504 * channelList is an array of channel frequencies (in Mhz) which the radio
3505 * should limit its operation to. It should be NULL if numChan == 0. Size of
3506 * array should correspond to numChan entries.
3507 */
3508int
3509wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
3510 WMI_PHY_MODE mode, s8 numChan,
3511 u16 *channelList)
3512{
3513 void *osbuf;
3514 WMI_CHANNEL_PARAMS_CMD *cmd;
3515 s8 size;
3516
3517 size = sizeof (*cmd);
3518
3519 if (numChan) {
3520 if (numChan > WMI_MAX_CHANNELS) {
3521 return A_EINVAL;
3522 }
3523 size += sizeof(u16) * (numChan - 1);
3524 }
3525
3526 osbuf = A_NETBUF_ALLOC(size);
3527 if (osbuf == NULL) {
3528 return A_NO_MEMORY;
3529 }
3530
3531 A_NETBUF_PUT(osbuf, size);
3532
3533 cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3534 A_MEMZERO(cmd, size);
3535
3536 wmip->wmi_phyMode = mode;
3537 cmd->scanParam = scanParam;
3538 cmd->phyMode = mode;
3539 cmd->numChannels = numChan;
3540 memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
3541
3542 return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
3543 NO_SYNC_WMIFLAG));
3544}
3545
3546void
3547wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3548{
3549 SQ_THRESHOLD_PARAMS *sq_thresh =
3550 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
3551 /*
3552 * Parse the command and store the threshold values here. The checks
3553 * for valid values can be put here
3554 */
3555 sq_thresh->weight = rssiCmd->weight;
3556 sq_thresh->polling_interval = rssiCmd->pollTime;
3557
3558 sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3559 sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3560 sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3561 sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3562 sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3563 sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3564 sq_thresh->upper_threshold_valid_count = 6;
3565
3566 /* List sorted in descending order */
3567 sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3568 sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3569 sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3570 sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3571 sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3572 sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3573 sq_thresh->lower_threshold_valid_count = 6;
3574
3575 if (!rssi_event_value) {
3576 /*
3577 * Configuring the thresholds to their extremes allows the host to get an
3578 * event from the target which is used for the configuring the correct
3579 * thresholds
3580 */
3581 rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0];
3582 rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0];
3583 } else {
3584 /*
3585 * In case the user issues multiple times of rssi_threshold_setting,
3586 * we should not use the extreames anymore, the target does not expect that.
3587 */
3588 rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh,
3589 sq_thresh->upper_threshold_valid_count);
3590 rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh,
3591 sq_thresh->lower_threshold_valid_count);
3592}
3593}
3594
3595int
3596wmi_set_rssi_threshold_params(struct wmi_t *wmip,
3597 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3598{
3599
3600 /* Check these values are in ascending order */
3601 if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
3602 rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
3603 rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
3604 rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
3605 rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
3606 rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
3607 rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
3608 rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
3609 rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
3610 rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val)
3611 {
3612 return A_EINVAL;
3613 }
3614
3615 wmi_cache_configure_rssithreshold(wmip, rssiCmd);
3616
3617 return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
3618}
3619
3620int
3621wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
3622{
3623 void *osbuf;
3624 WMI_SET_IP_CMD *cmd;
3625
3626 /* Multicast address are not valid */
3627 if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
3628 (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
3629 return A_EINVAL;
3630 }
3631
3632 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD));
3633 if (osbuf == NULL) {
3634 return A_NO_MEMORY;
3635 }
3636
3637 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
3638 cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
3639 memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
3640
3641 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
3642 NO_SYNC_WMIFLAG));
3643}
3644
3645int
3646wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
3647 WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
3648{
3649 void *osbuf;
3650 s8 size;
3651 WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
3652 u16 activeTsids=0;
3653 u8 streamExists=0;
3654 u8 i;
3655
3656 if( hostModeCmd->awake == hostModeCmd->asleep) {
3657 return A_EINVAL;
3658 }
3659
3660 size = sizeof (*cmd);
3661
3662 osbuf = A_NETBUF_ALLOC(size);
3663 if (osbuf == NULL) {
3664 return A_NO_MEMORY;
3665 }
3666
3667 A_NETBUF_PUT(osbuf, size);
3668
3669 cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3670 A_MEMZERO(cmd, size);
3671 memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
3672
3673 if(hostModeCmd->asleep) {
3674 /*
3675 * Relinquish credits from all implicitly created pstreams since when we
3676 * go to sleep. If user created explicit thinstreams exists with in a
3677 * fatpipe leave them intact for the user to delete
3678 */
3679 LOCK_WMI(wmip);
3680 streamExists = wmip->wmi_fatPipeExists;
3681 UNLOCK_WMI(wmip);
3682
3683 for(i=0;i< WMM_NUM_AC;i++) {
3684 if (streamExists & (1<<i)) {
3685 LOCK_WMI(wmip);
3686 activeTsids = wmip->wmi_streamExistsForAC[i];
3687 UNLOCK_WMI(wmip);
3688 /* If there are no user created thin streams delete the fatpipe */
3689 if(!activeTsids) {
3690 streamExists &= ~(1<<i);
3691 /*Indicate inactivity to drv layer for this fatpipe(pstream)*/
3692 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i);
3693 }
3694 }
3695 }
3696
3697 /* Update the fatpipes that exists*/
3698 LOCK_WMI(wmip);
3699 wmip->wmi_fatPipeExists = streamExists;
3700 UNLOCK_WMI(wmip);
3701 }
3702
3703 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
3704 NO_SYNC_WMIFLAG));
3705}
3706
3707int
3708wmi_set_wow_mode_cmd(struct wmi_t *wmip,
3709 WMI_SET_WOW_MODE_CMD *wowModeCmd)
3710{
3711 void *osbuf;
3712 s8 size;
3713 WMI_SET_WOW_MODE_CMD *cmd;
3714
3715 size = sizeof (*cmd);
3716
3717 osbuf = A_NETBUF_ALLOC(size);
3718 if (osbuf == NULL) {
3719 return A_NO_MEMORY;
3720 }
3721
3722 A_NETBUF_PUT(osbuf, size);
3723
3724 cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3725 A_MEMZERO(cmd, size);
3726 memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
3727
3728 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
3729 NO_SYNC_WMIFLAG));
3730
3731}
3732
3733int
3734wmi_get_wow_list_cmd(struct wmi_t *wmip,
3735 WMI_GET_WOW_LIST_CMD *wowListCmd)
3736{
3737 void *osbuf;
3738 s8 size;
3739 WMI_GET_WOW_LIST_CMD *cmd;
3740
3741 size = sizeof (*cmd);
3742
3743 osbuf = A_NETBUF_ALLOC(size);
3744 if (osbuf == NULL) {
3745 return A_NO_MEMORY;
3746 }
3747
3748 A_NETBUF_PUT(osbuf, size);
3749
3750 cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
3751 A_MEMZERO(cmd, size);
3752 memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
3753
3754 return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
3755 NO_SYNC_WMIFLAG));
3756
3757}
3758
3759static int
3760wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
3761{
3762 WMI_GET_WOW_LIST_REPLY *reply;
3763
3764 if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
3765 return A_EINVAL;
3766 }
3767 reply = (WMI_GET_WOW_LIST_REPLY *)datap;
3768
3769 A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
3770 reply);
3771
3772 return 0;
3773}
3774
3775int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
3776 WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
3777 u8 *pattern, u8 *mask,
3778 u8 pattern_size)
3779{
3780 void *osbuf;
3781 s8 size;
3782 WMI_ADD_WOW_PATTERN_CMD *cmd;
3783 u8 *filter_mask = NULL;
3784
3785 size = sizeof (*cmd);
3786
3787 size += ((2 * addWowCmd->filter_size)* sizeof(u8));
3788 osbuf = A_NETBUF_ALLOC(size);
3789 if (osbuf == NULL) {
3790 return A_NO_MEMORY;
3791 }
3792
3793 A_NETBUF_PUT(osbuf, size);
3794
3795 cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3796 cmd->filter_list_id = addWowCmd->filter_list_id;
3797 cmd->filter_offset = addWowCmd->filter_offset;
3798 cmd->filter_size = addWowCmd->filter_size;
3799
3800 memcpy(cmd->filter, pattern, addWowCmd->filter_size);
3801
3802 filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
3803 memcpy(filter_mask, mask, addWowCmd->filter_size);
3804
3805
3806 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
3807 NO_SYNC_WMIFLAG));
3808}
3809
3810int
3811wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
3812 WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
3813{
3814 void *osbuf;
3815 s8 size;
3816 WMI_DEL_WOW_PATTERN_CMD *cmd;
3817
3818 size = sizeof (*cmd);
3819
3820 osbuf = A_NETBUF_ALLOC(size);
3821 if (osbuf == NULL) {
3822 return A_NO_MEMORY;
3823 }
3824
3825 A_NETBUF_PUT(osbuf, size);
3826
3827 cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3828 A_MEMZERO(cmd, size);
3829 memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
3830
3831 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
3832 NO_SYNC_WMIFLAG));
3833
3834}
3835
3836void
3837wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3838{
3839 SQ_THRESHOLD_PARAMS *sq_thresh =
3840 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
3841 /*
3842 * Parse the command and store the threshold values here. The checks
3843 * for valid values can be put here
3844 */
3845 sq_thresh->weight = snrCmd->weight;
3846 sq_thresh->polling_interval = snrCmd->pollTime;
3847
3848 sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val;
3849 sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val;
3850 sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val;
3851 sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val;
3852 sq_thresh->upper_threshold_valid_count = 4;
3853
3854 /* List sorted in descending order */
3855 sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val;
3856 sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val;
3857 sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val;
3858 sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val;
3859 sq_thresh->lower_threshold_valid_count = 4;
3860
3861 if (!snr_event_value) {
3862 /*
3863 * Configuring the thresholds to their extremes allows the host to get an
3864 * event from the target which is used for the configuring the correct
3865 * thresholds
3866 */
3867 snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
3868 snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
3869 } else {
3870 /*
3871 * In case the user issues multiple times of snr_threshold_setting,
3872 * we should not use the extreames anymore, the target does not expect that.
3873 */
3874 snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh,
3875 sq_thresh->upper_threshold_valid_count);
3876 snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh,
3877 sq_thresh->lower_threshold_valid_count);
3878 }
3879
3880}
3881int
3882wmi_set_snr_threshold_params(struct wmi_t *wmip,
3883 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3884{
3885 if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
3886 snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
3887 snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
3888 snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
3889 snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
3890 snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val)
3891 {
3892 return A_EINVAL;
3893 }
3894 wmi_cache_configure_snrthreshold(wmip, snrCmd);
3895 return (wmi_send_snr_threshold_params(wmip, snrCmd));
3896}
3897
3898int
3899wmi_clr_rssi_snr(struct wmi_t *wmip)
3900{
3901 void *osbuf;
3902
3903 osbuf = A_NETBUF_ALLOC(sizeof(int));
3904 if (osbuf == NULL) {
3905 return A_NO_MEMORY;
3906 }
3907
3908 return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
3909 NO_SYNC_WMIFLAG));
3910}
3911
3912int
3913wmi_set_lq_threshold_params(struct wmi_t *wmip,
3914 WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
3915{
3916 void *osbuf;
3917 s8 size;
3918 WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
3919 /* These values are in ascending order */
3920 if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
3921 lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
3922 lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
3923 lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
3924 lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
3925 lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
3926
3927 return A_EINVAL;
3928 }
3929
3930 size = sizeof (*cmd);
3931
3932 osbuf = A_NETBUF_ALLOC(size);
3933 if (osbuf == NULL) {
3934 return A_NO_MEMORY;
3935 }
3936
3937 A_NETBUF_PUT(osbuf, size);
3938
3939 cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3940 A_MEMZERO(cmd, size);
3941 memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
3942
3943 return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
3944 NO_SYNC_WMIFLAG));
3945}
3946
3947int
3948wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
3949{
3950 void *osbuf;
3951 s8 size;
3952 WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
3953
3954 size = sizeof (*cmd);
3955
3956 osbuf = A_NETBUF_ALLOC(size);
3957 if (osbuf == NULL) {
3958 return A_NO_MEMORY;
3959 }
3960
3961 A_NETBUF_PUT(osbuf, size);
3962
3963 cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
3964 A_MEMZERO(cmd, size);
3965
3966 cmd->bitmask = mask;
3967
3968 return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
3969 NO_SYNC_WMIFLAG));
3970}
3971
3972int
3973wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
3974{
3975 void *osbuf;
3976 WMIX_HB_CHALLENGE_RESP_CMD *cmd;
3977
3978 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3979 if (osbuf == NULL) {
3980 return A_NO_MEMORY;
3981 }
3982
3983 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3984
3985 cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
3986 cmd->cookie = cookie;
3987 cmd->source = source;
3988
3989 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
3990 NO_SYNC_WMIFLAG));
3991}
3992
3993int
3994wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
3995 u16 tsr, bool rep, u16 size,
3996 u32 valid)
3997{
3998 void *osbuf;
3999 WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
4000
4001 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4002 if (osbuf == NULL) {
4003 return A_NO_MEMORY;
4004 }
4005
4006 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4007
4008 cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
4009 cmd->config.cfgmmask = mmask;
4010 cmd->config.cfgtsr = tsr;
4011 cmd->config.cfgrep = rep;
4012 cmd->config.cfgsize = size;
4013 cmd->config.cfgvalid = valid;
4014
4015 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
4016 NO_SYNC_WMIFLAG));
4017}
4018
4019int
4020wmi_get_stats_cmd(struct wmi_t *wmip)
4021{
4022 return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
4023}
4024
4025int
4026wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
4027{
4028 void *osbuf;
4029 WMI_ADD_BAD_AP_CMD *cmd;
4030
4031 if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
4032 return A_EINVAL;
4033 }
4034
4035 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4036 if (osbuf == NULL) {
4037 return A_NO_MEMORY;
4038 }
4039
4040 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4041
4042 cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4043 cmd->badApIndex = apIndex;
4044 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4045
4046 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
4047}
4048
4049int
4050wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
4051{
4052 void *osbuf;
4053 WMI_DELETE_BAD_AP_CMD *cmd;
4054
4055 if (apIndex > WMI_MAX_BAD_AP_INDEX) {
4056 return A_EINVAL;
4057 }
4058
4059 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4060 if (osbuf == NULL) {
4061 return A_NO_MEMORY;
4062 }
4063
4064 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4065
4066 cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4067 cmd->badApIndex = apIndex;
4068
4069 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
4070 NO_SYNC_WMIFLAG));
4071}
4072
4073int
4074wmi_abort_scan_cmd(struct wmi_t *wmip)
4075{
4076 return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
4077}
4078
4079int
4080wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
4081{
4082 void *osbuf;
4083 WMI_SET_TX_PWR_CMD *cmd;
4084
4085 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4086 if (osbuf == NULL) {
4087 return A_NO_MEMORY;
4088 }
4089
4090 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4091
4092 cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
4093 cmd->dbM = dbM;
4094
4095 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
4096}
4097
4098int
4099wmi_get_txPwr_cmd(struct wmi_t *wmip)
4100{
4101 return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
4102}
4103
4104u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
4105{
4106 u16 activeTsids=0;
4107
4108 LOCK_WMI(wmip);
4109 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
4110 UNLOCK_WMI(wmip);
4111
4112 return activeTsids;
4113}
4114
4115int
4116wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
4117{
4118 return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
4119}
4120
4121int
4122wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
4123{
4124 void *osbuf;
4125 u32 size = sizeof(u8);
4126 WMI_TARGET_ROAM_DATA *cmd;
4127
4128 osbuf = A_NETBUF_ALLOC(size); /* no payload */
4129 if (osbuf == NULL) {
4130 return A_NO_MEMORY;
4131 }
4132
4133 A_NETBUF_PUT(osbuf, size);
4134
4135 cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
4136 cmd->roamDataType = roamDataType;
4137
4138 return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
4139 NO_SYNC_WMIFLAG));
4140}
4141
4142int
4143wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
4144 u8 size)
4145{
4146 void *osbuf;
4147 WMI_SET_ROAM_CTRL_CMD *cmd;
4148
4149 osbuf = A_NETBUF_ALLOC(size);
4150 if (osbuf == NULL) {
4151 return A_NO_MEMORY;
4152 }
4153
4154 A_NETBUF_PUT(osbuf, size);
4155
4156 cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
4157 A_MEMZERO(cmd, size);
4158
4159 memcpy(cmd, p, size);
4160
4161 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
4162 NO_SYNC_WMIFLAG));
4163}
4164
4165int
4166wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
4167 WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
4168 u8 size)
4169{
4170 void *osbuf;
4171 WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
4172
4173 /* These timers can't be zero */
4174 if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
4175 !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
4176 pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
4177 !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
4178 pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
4179 return A_EINVAL;
4180
4181 osbuf = A_NETBUF_ALLOC(size);
4182 if (osbuf == NULL) {
4183 return A_NO_MEMORY;
4184 }
4185
4186 A_NETBUF_PUT(osbuf, size);
4187
4188 cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
4189 A_MEMZERO(cmd, size);
4190
4191 memcpy(cmd, pCmd, size);
4192
4193 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
4194 NO_SYNC_WMIFLAG));
4195}
4196
4197int
4198wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin,
4199 u8 eCWmax, u8 aifsn)
4200{
4201 void *osbuf;
4202 WMI_SET_ACCESS_PARAMS_CMD *cmd;
4203
4204 if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
4205 (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC))
4206 {
4207 return A_EINVAL;
4208 }
4209
4210 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4211 if (osbuf == NULL) {
4212 return A_NO_MEMORY;
4213 }
4214
4215 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4216
4217 cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4218 cmd->txop = txop;
4219 cmd->eCWmin = eCWmin;
4220 cmd->eCWmax = eCWmax;
4221 cmd->aifsn = aifsn;
4222 cmd->ac = ac;
4223
4224 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
4225 NO_SYNC_WMIFLAG));
4226}
4227
4228int
4229wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
4230 u8 trafficClass, u8 maxRetries,
4231 u8 enableNotify)
4232{
4233 void *osbuf;
4234 WMI_SET_RETRY_LIMITS_CMD *cmd;
4235
4236 if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
4237 (frameType != DATA_FRAMETYPE))
4238 {
4239 return A_EINVAL;
4240 }
4241
4242 if (maxRetries > WMI_MAX_RETRIES) {
4243 return A_EINVAL;
4244 }
4245
4246 if (frameType != DATA_FRAMETYPE) {
4247 trafficClass = 0;
4248 }
4249
4250 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4251 if (osbuf == NULL) {
4252 return A_NO_MEMORY;
4253 }
4254
4255 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4256
4257 cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
4258 cmd->frameType = frameType;
4259 cmd->trafficClass = trafficClass;
4260 cmd->maxRetries = maxRetries;
4261 cmd->enableNotify = enableNotify;
4262
4263 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
4264 NO_SYNC_WMIFLAG));
4265}
4266
4267void
4268wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
4269{
4270 if (bssid != NULL) {
4271 memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
4272 }
4273}
4274
4275int
4276wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
4277{
4278 void *osbuf;
4279 WMI_SET_OPT_MODE_CMD *cmd;
4280
4281 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4282 if (osbuf == NULL) {
4283 return A_NO_MEMORY;
4284 }
4285
4286 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4287
4288 cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4289 A_MEMZERO(cmd, sizeof(*cmd));
4290 cmd->optMode = optMode;
4291
4292 return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
4293 SYNC_BOTH_WMIFLAG));
4294}
4295
4296int
4297wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
4298 u8 frmType,
4299 u8 *dstMacAddr,
4300 u8 *bssid,
4301 u16 optIEDataLen,
4302 u8 *optIEData)
4303{
4304 void *osbuf;
4305 WMI_OPT_TX_FRAME_CMD *cmd;
4306 osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
4307 if (osbuf == NULL) {
4308 return A_NO_MEMORY;
4309 }
4310
4311 A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
4312
4313 cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
4314 A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
4315
4316 cmd->frmType = frmType;
4317 cmd->optIEDataLen = optIEDataLen;
4318 //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd));
4319 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4320 memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
4321 memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
4322
4323 return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
4324 NO_SYNC_WMIFLAG));
4325}
4326
4327int
4328wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
4329{
4330 void *osbuf;
4331 WMI_BEACON_INT_CMD *cmd;
4332
4333 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4334 if (osbuf == NULL) {
4335 return A_NO_MEMORY;
4336 }
4337
4338 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4339
4340 cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
4341 A_MEMZERO(cmd, sizeof(*cmd));
4342 cmd->beaconInterval = intvl;
4343
4344 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
4345 NO_SYNC_WMIFLAG));
4346}
4347
4348
4349int
4350wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
4351{
4352 void *osbuf;
4353 WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
4354
4355 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4356 if (osbuf == NULL) {
4357 return A_NO_MEMORY;
4358 }
4359
4360 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4361
4362 cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
4363 A_MEMZERO(cmd, sizeof(*cmd));
4364 cmd->voicePktSize = voicePktSize;
4365
4366 return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
4367 NO_SYNC_WMIFLAG));
4368}
4369
4370
4371int
4372wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
4373{
4374 void *osbuf;
4375 WMI_SET_MAX_SP_LEN_CMD *cmd;
4376
4377 /* maxSPLen is a two-bit value. If user trys to set anything
4378 * other than this, then its invalid
4379 */
4380 if(maxSPLen & ~0x03)
4381 return A_EINVAL;
4382
4383 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4384 if (osbuf == NULL) {
4385 return A_NO_MEMORY;
4386 }
4387
4388 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4389
4390 cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
4391 A_MEMZERO(cmd, sizeof(*cmd));
4392 cmd->maxSPLen = maxSPLen;
4393
4394 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
4395 NO_SYNC_WMIFLAG));
4396}
4397
4398u8 wmi_determine_userPriority(
4399 u8 *pkt,
4400 u32 layer2Pri)
4401{
4402 u8 ipPri;
4403 iphdr *ipHdr = (iphdr *)pkt;
4404
4405 /* Determine IPTOS priority */
4406 /*
4407 * IP Tos format :
4408 * (Refer Pg 57 WMM-test-plan-v1.2)
4409 * IP-TOS - 8bits
4410 * : DSCP(6-bits) ECN(2-bits)
4411 * : DSCP - P2 P1 P0 X X X
4412 * where (P2 P1 P0) form 802.1D
4413 */
4414 ipPri = ipHdr->ip_tos >> 5;
4415 ipPri &= 0x7;
4416
4417 if ((layer2Pri & 0x7) > ipPri)
4418 return ((u8)layer2Pri & 0x7);
4419 else
4420 return ipPri;
4421}
4422
4423u8 convert_userPriority_to_trafficClass(u8 userPriority)
4424{
4425 return (up_to_ac[userPriority & 0x7]);
4426}
4427
4428u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
4429{
4430 return wmip->wmi_powerMode;
4431}
4432
4433int
4434wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
4435{
4436 int ret = 0;
4437
4438#define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
4439#define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0
4440#define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0
4441#define TSPEC_DELAY_BOUND_ATHEROS_DEF 0
4442#define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0
4443#define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */
4444
4445 /* Verify TSPEC params for ATHEROS compliance */
4446 if(tspecCompliance == ATHEROS_COMPLIANCE) {
4447 if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) ||
4448 (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) ||
4449 (pCmd->minDataRate != pCmd->meanDataRate) ||
4450 (pCmd->minDataRate != pCmd->peakDataRate) ||
4451 (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) ||
4452 (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) ||
4453 (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) ||
4454 (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) {
4455
4456 A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG));
4457 //A_PRINTF("%s: Invalid TSPEC params\n", __func__);
4458 ret = A_EINVAL;
4459 }
4460 }
4461
4462 return ret;
4463}
4464
4465#ifdef CONFIG_HOST_TCMD_SUPPORT
4466static int
4467wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
4468{
4469 ar6000_testmode_rx_report_event(wmip->wmi_devt, datap, len);
4470
4471 return 0;
4472}
4473
4474#endif /* CONFIG_HOST_TCMD_SUPPORT*/
4475
4476int
4477wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
4478{
4479 void *osbuf;
4480 WMI_SET_AUTH_MODE_CMD *cmd;
4481
4482 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4483 if (osbuf == NULL) {
4484 return A_NO_MEMORY;
4485 }
4486
4487 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4488
4489 cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4490 A_MEMZERO(cmd, sizeof(*cmd));
4491 cmd->mode = mode;
4492
4493 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
4494 NO_SYNC_WMIFLAG));
4495}
4496
4497int
4498wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
4499{
4500 void *osbuf;
4501 WMI_SET_REASSOC_MODE_CMD *cmd;
4502
4503 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4504 if (osbuf == NULL) {
4505 return A_NO_MEMORY;
4506 }
4507
4508 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4509
4510 cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4511 A_MEMZERO(cmd, sizeof(*cmd));
4512 cmd->mode = mode;
4513
4514 return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
4515 NO_SYNC_WMIFLAG));
4516}
4517
4518int
4519wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
4520{
4521 void *osbuf;
4522 WMI_SET_LPREAMBLE_CMD *cmd;
4523
4524 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4525 if (osbuf == NULL) {
4526 return A_NO_MEMORY;
4527 }
4528
4529 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4530
4531 cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
4532 A_MEMZERO(cmd, sizeof(*cmd));
4533 cmd->status = status;
4534 cmd->preamblePolicy = preamblePolicy;
4535
4536 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
4537 NO_SYNC_WMIFLAG));
4538}
4539
4540int
4541wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
4542{
4543 void *osbuf;
4544 WMI_SET_RTS_CMD *cmd;
4545
4546 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4547 if (osbuf == NULL) {
4548 return A_NO_MEMORY;
4549 }
4550
4551 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4552
4553 cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
4554 A_MEMZERO(cmd, sizeof(*cmd));
4555 cmd->threshold = threshold;
4556
4557 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
4558 NO_SYNC_WMIFLAG));
4559}
4560
4561int
4562wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
4563{
4564 void *osbuf;
4565 WMI_SET_WMM_CMD *cmd;
4566
4567 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4568 if (osbuf == NULL) {
4569 return A_NO_MEMORY;
4570 }
4571
4572 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4573
4574 cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
4575 A_MEMZERO(cmd, sizeof(*cmd));
4576 cmd->status = status;
4577
4578 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
4579 NO_SYNC_WMIFLAG));
4580
4581}
4582
4583int
4584wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
4585{
4586 void *osbuf;
4587 WMI_SET_QOS_SUPP_CMD *cmd;
4588
4589 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4590 if (osbuf == NULL) {
4591 return A_NO_MEMORY;
4592 }
4593
4594 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4595
4596 cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf));
4597 A_MEMZERO(cmd, sizeof(*cmd));
4598 cmd->status = status;
4599 return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID,
4600 NO_SYNC_WMIFLAG));
4601}
4602
4603
4604int
4605wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
4606{
4607 void *osbuf;
4608 WMI_SET_WMM_TXOP_CMD *cmd;
4609
4610 if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
4611 return A_EINVAL;
4612
4613 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4614 if (osbuf == NULL) {
4615 return A_NO_MEMORY;
4616 }
4617
4618 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4619
4620 cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
4621 A_MEMZERO(cmd, sizeof(*cmd));
4622 cmd->txopEnable = cfg;
4623
4624 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
4625 NO_SYNC_WMIFLAG));
4626
4627}
4628
4629int
4630wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
4631{
4632 void *osbuf;
4633 WMI_AP_SET_COUNTRY_CMD *cmd;
4634
4635 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4636 if (osbuf == NULL) {
4637 return A_NO_MEMORY;
4638 }
4639
4640 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4641
4642 cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
4643 A_MEMZERO(cmd, sizeof(*cmd));
4644 memcpy(cmd->countryCode,countryCode,3);
4645
4646 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
4647 NO_SYNC_WMIFLAG));
4648}
4649
4650#ifdef CONFIG_HOST_TCMD_SUPPORT
4651/* WMI layer doesn't need to know the data type of the test cmd.
4652 This would be beneficial for customers like Qualcomm, who might
4653 have different test command requirements from different manufacturers
4654 */
4655int
4656wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
4657{
4658 void *osbuf;
4659 char *data;
4660
4661 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4662
4663 osbuf= A_NETBUF_ALLOC(len);
4664 if(osbuf == NULL)
4665 {
4666 return A_NO_MEMORY;
4667 }
4668 A_NETBUF_PUT(osbuf, len);
4669 data = A_NETBUF_DATA(osbuf);
4670 memcpy(data, buf, len);
4671
4672 return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
4673 NO_SYNC_WMIFLAG));
4674}
4675
4676#endif
4677
4678int
4679wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
4680{
4681 void *osbuf;
4682 WMI_SET_BT_STATUS_CMD *cmd;
4683
4684 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status));
4685
4686 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4687 if (osbuf == NULL) {
4688 return A_NO_MEMORY;
4689 }
4690
4691 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4692
4693 cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4694 A_MEMZERO(cmd, sizeof(*cmd));
4695 cmd->streamType = streamType;
4696 cmd->status = status;
4697
4698 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
4699 NO_SYNC_WMIFLAG));
4700}
4701
4702int
4703wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
4704{
4705 void *osbuf;
4706 WMI_SET_BT_PARAMS_CMD* alloc_cmd;
4707
4708 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType));
4709
4710 if (cmd->paramType == BT_PARAM_SCO) {
4711 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger,
4712 cmd->info.scoParams.dataResponseTimeout,
4713 cmd->info.scoParams.stompScoRules,
4714 cmd->info.scoParams.scoOptFlags,
4715 cmd->info.scoParams.stompDutyCyleVal,
4716 cmd->info.scoParams.stompDutyCyleMaxVal,
4717 cmd->info.scoParams.psPollLatencyFraction,
4718 cmd->info.scoParams.noSCOSlots,
4719 cmd->info.scoParams.noIdleSlots,
4720 cmd->info.scoParams.scoOptOffRssi,
4721 cmd->info.scoParams.scoOptOnRssi,
4722 cmd->info.scoParams.scoOptRtsCount));
4723 }
4724 else if (cmd->paramType == BT_PARAM_A2DP) {
4725 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit,
4726 cmd->info.a2dpParams.a2dpBurstCntMin,
4727 cmd->info.a2dpParams.a2dpDataRespTimeout,
4728 cmd->info.a2dpParams.a2dpOptFlags,
4729 cmd->info.a2dpParams.isCoLocatedBtRoleMaster,
4730 cmd->info.a2dpParams.a2dpOptOffRssi,
4731 cmd->info.a2dpParams.a2dpOptOnRssi,
4732 cmd->info.a2dpParams.a2dpOptRtsCount));
4733 }
4734 else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) {
4735 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType));
4736 }
4737 else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) {
4738 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev));
4739 }
4740 else if (cmd->paramType == BT_PARAM_ACLCOEX) {
4741 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime,
4742 cmd->info.aclCoexParams.aclBtMediumUsageTime,
4743 cmd->info.aclCoexParams.aclDataRespTimeout));
4744 }
4745 else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) {
4746 A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG));
4747 }
4748
4749 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4750 if (osbuf == NULL) {
4751 return A_NO_MEMORY;
4752 }
4753
4754 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4755
4756 alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4757 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4758 memcpy(alloc_cmd, cmd, sizeof(*cmd));
4759
4760 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
4761 NO_SYNC_WMIFLAG));
4762}
4763
4764int
4765wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
4766{
4767 void *osbuf;
4768 WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd;
4769
4770 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4771 if (osbuf == NULL) {
4772 return A_NO_MEMORY;
4773 }
4774 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4775 alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
4776 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4777 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
4778 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
4779 NO_SYNC_WMIFLAG));
4780
4781}
4782
4783
4784int
4785wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
4786 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
4787{
4788 void *osbuf;
4789 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd;
4790
4791 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4792 if (osbuf == NULL) {
4793 return A_NO_MEMORY;
4794 }
4795 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4796 alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
4797 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4798 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
4799 A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
4800 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
4801 NO_SYNC_WMIFLAG));
4802
4803}
4804
4805int
4806wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
4807 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
4808{
4809 void *osbuf;
4810 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd;
4811
4812 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4813 if (osbuf == NULL) {
4814 return A_NO_MEMORY;
4815 }
4816 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4817 alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4818 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4819 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
4820 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
4821 NO_SYNC_WMIFLAG));
4822
4823}
4824
4825int
4826wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
4827 WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
4828{
4829 void *osbuf;
4830 WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd;
4831
4832 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4833 if (osbuf == NULL) {
4834 return A_NO_MEMORY;
4835 }
4836 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4837 alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4838 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4839 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
4840 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
4841 NO_SYNC_WMIFLAG));
4842
4843}
4844
4845int
4846wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
4847 WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
4848{
4849 void *osbuf;
4850 WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd;
4851
4852 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4853 if (osbuf == NULL) {
4854 return A_NO_MEMORY;
4855 }
4856 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4857 alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4858 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4859 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
4860 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
4861 NO_SYNC_WMIFLAG));
4862
4863}
4864
4865int
4866wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
4867 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
4868{
4869 void *osbuf;
4870 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd;
4871
4872 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4873 if (osbuf == NULL) {
4874 return A_NO_MEMORY;
4875 }
4876 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4877 alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4878 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4879 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
4880 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
4881 NO_SYNC_WMIFLAG));
4882
4883}
4884
4885int
4886wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
4887{
4888 void *osbuf;
4889 WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd;
4890
4891 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4892 if (osbuf == NULL) {
4893 return A_NO_MEMORY;
4894 }
4895 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4896 alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
4897 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4898 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
4899 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
4900 NO_SYNC_WMIFLAG));
4901
4902}
4903
4904int
4905wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
4906 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
4907{
4908 void *osbuf;
4909 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd;
4910
4911 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4912 if (osbuf == NULL) {
4913 return A_NO_MEMORY;
4914 }
4915 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4916 alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4917 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4918 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
4919 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
4920 NO_SYNC_WMIFLAG));
4921
4922}
4923
4924int
4925wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
4926{
4927 void *osbuf;
4928 WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd;
4929
4930 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4931 if (osbuf == NULL) {
4932 return A_NO_MEMORY;
4933 }
4934 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4935 alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4936 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4937 memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
4938 return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
4939 NO_SYNC_WMIFLAG));
4940
4941}
4942
4943int
4944wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
4945{
4946
4947 return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
4948
4949}
4950
4951int
4952wmi_get_keepalive_configured(struct wmi_t *wmip)
4953{
4954 void *osbuf;
4955 WMI_GET_KEEPALIVE_CMD *cmd;
4956 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4957 if (osbuf == NULL) {
4958 return A_NO_MEMORY;
4959 }
4960 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4961 cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4962 A_MEMZERO(cmd, sizeof(*cmd));
4963 return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
4964 NO_SYNC_WMIFLAG));
4965}
4966
4967u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
4968{
4969 return wmip->wmi_keepaliveInterval;
4970}
4971
4972int
4973wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
4974{
4975 void *osbuf;
4976 WMI_SET_KEEPALIVE_CMD *cmd;
4977
4978 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4979 if (osbuf == NULL) {
4980 return A_NO_MEMORY;
4981 }
4982
4983 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4984
4985 cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4986 A_MEMZERO(cmd, sizeof(*cmd));
4987 cmd->keepaliveInterval = keepaliveInterval;
4988 wmip->wmi_keepaliveInterval = keepaliveInterval;
4989
4990 return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
4991 NO_SYNC_WMIFLAG));
4992}
4993
4994int
4995wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
4996{
4997 void *osbuf;
4998 WMI_SET_PARAMS_CMD *cmd;
4999
5000 osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length);
5001 if (osbuf == NULL) {
5002 return A_NO_MEMORY;
5003 }
5004
5005 A_NETBUF_PUT(osbuf, sizeof(*cmd) + length);
5006
5007 cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5008 A_MEMZERO(cmd, sizeof(*cmd));
5009 cmd->opcode = opcode;
5010 cmd->length = length;
5011 memcpy(cmd->buffer, buffer, length);
5012
5013 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
5014 NO_SYNC_WMIFLAG));
5015}
5016
5017
5018int
5019wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5020{
5021 void *osbuf;
5022 WMI_SET_MCAST_FILTER_CMD *cmd;
5023
5024 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5025 if (osbuf == NULL) {
5026 return A_NO_MEMORY;
5027 }
5028
5029 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5030
5031 cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5032 cmd->multicast_mac[0] = 0x01;
5033 cmd->multicast_mac[1] = 0x00;
5034 cmd->multicast_mac[2] = 0x5e;
5035 cmd->multicast_mac[3] = dot2&0x7F;
5036 cmd->multicast_mac[4] = dot3;
5037 cmd->multicast_mac[5] = dot4;
5038
5039 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID,
5040 NO_SYNC_WMIFLAG));
5041}
5042
5043
5044int
5045wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5046{
5047 void *osbuf;
5048 WMI_SET_MCAST_FILTER_CMD *cmd;
5049
5050 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5051 if (osbuf == NULL) {
5052 return A_NO_MEMORY;
5053 }
5054
5055 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5056
5057 cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5058 cmd->multicast_mac[0] = 0x01;
5059 cmd->multicast_mac[1] = 0x00;
5060 cmd->multicast_mac[2] = 0x5e;
5061 cmd->multicast_mac[3] = dot2&0x7F;
5062 cmd->multicast_mac[4] = dot3;
5063 cmd->multicast_mac[5] = dot4;
5064
5065 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID,
5066 NO_SYNC_WMIFLAG));
5067}
5068
5069int
5070wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
5071{
5072 void *osbuf;
5073 WMI_MCAST_FILTER_CMD *cmd;
5074
5075 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5076 if (osbuf == NULL) {
5077 return A_NO_MEMORY;
5078 }
5079
5080 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5081
5082 cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5083 cmd->enable = enable;
5084
5085 return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID,
5086 NO_SYNC_WMIFLAG));
5087}
5088
5089int
5090wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
5091 u8 *ieInfo)
5092{
5093 void *osbuf;
5094 WMI_SET_APPIE_CMD *cmd;
5095 u16 cmdLen;
5096
5097 cmdLen = sizeof(*cmd) + ieLen - 1;
5098 osbuf = A_NETBUF_ALLOC(cmdLen);
5099 if (osbuf == NULL) {
5100 return A_NO_MEMORY;
5101 }
5102
5103 A_NETBUF_PUT(osbuf, cmdLen);
5104
5105 cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
5106 A_MEMZERO(cmd, cmdLen);
5107
5108 cmd->mgmtFrmType = mgmtFrmType;
5109 cmd->ieLen = ieLen;
5110 memcpy(cmd->ieInfo, ieInfo, ieLen);
5111
5112 return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
5113}
5114
5115int
5116wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
5117{
5118 void *osbuf;
5119 u8 *data;
5120
5121 osbuf = A_NETBUF_ALLOC(dataLen);
5122 if (osbuf == NULL) {
5123 return A_NO_MEMORY;
5124 }
5125
5126 A_NETBUF_PUT(osbuf, dataLen);
5127
5128 data = A_NETBUF_DATA(osbuf);
5129
5130 memcpy(data, cmd, dataLen);
5131
5132 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
5133}
5134
5135s32 wmi_get_rate(s8 rateindex)
5136{
5137 if (rateindex == RATE_AUTO) {
5138 return 0;
5139 } else {
5140 return(wmi_rateTable[(u32) rateindex][0]);
5141 }
5142}
5143
5144void
5145wmi_node_return (struct wmi_t *wmip, bss_t *bss)
5146{
5147 if (NULL != bss)
5148 {
5149 wlan_node_return (&wmip->wmi_scan_table, bss);
5150 }
5151}
5152
5153void
5154wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
5155{
5156 wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
5157}
5158
5159bss_t *
5160wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
5161 u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
5162{
5163 bss_t *node = NULL;
5164 node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
5165 ssidLength, bIsWPA2, bMatchSSID);
5166 return node;
5167}
5168
5169
5170#ifdef THREAD_X
5171void
5172wmi_refresh_scan_table (struct wmi_t *wmip)
5173{
5174 wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
5175}
5176#endif
5177
5178void
5179wmi_free_allnodes(struct wmi_t *wmip)
5180{
5181 wlan_free_allnodes(&wmip->wmi_scan_table);
5182}
5183
5184bss_t *
5185wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
5186{
5187 bss_t *ni=NULL;
5188 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5189 return ni;
5190}
5191
5192void
5193wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
5194{
5195 bss_t *ni=NULL;
5196
5197 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5198 if (ni != NULL) {
5199 wlan_node_reclaim(&wmip->wmi_scan_table, ni);
5200 }
5201
5202 return;
5203}
5204
5205int
5206wmi_dset_open_reply(struct wmi_t *wmip,
5207 u32 status,
5208 u32 access_cookie,
5209 u32 dset_size,
5210 u32 dset_version,
5211 u32 targ_handle,
5212 u32 targ_reply_fn,
5213 u32 targ_reply_arg)
5214{
5215 void *osbuf;
5216 WMIX_DSETOPEN_REPLY_CMD *open_reply;
5217
5218 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip));
5219
5220 osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
5221 if (osbuf == NULL) {
5222 return A_NO_MEMORY;
5223 }
5224
5225 A_NETBUF_PUT(osbuf, sizeof(*open_reply));
5226 open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5227
5228 open_reply->status = status;
5229 open_reply->targ_dset_handle = targ_handle;
5230 open_reply->targ_reply_fn = targ_reply_fn;
5231 open_reply->targ_reply_arg = targ_reply_arg;
5232 open_reply->access_cookie = access_cookie;
5233 open_reply->size = dset_size;
5234 open_reply->version = dset_version;
5235
5236 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
5237 NO_SYNC_WMIFLAG));
5238}
5239
5240static int
5241wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5242{
5243 WMI_PMKID_LIST_REPLY *reply;
5244 u32 expected_len;
5245
5246 if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
5247 return A_EINVAL;
5248 }
5249 reply = (WMI_PMKID_LIST_REPLY *)datap;
5250 expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
5251
5252 if (len < expected_len) {
5253 return A_EINVAL;
5254 }
5255
5256 A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
5257 reply->pmkidList, reply->bssidList[0]);
5258
5259 return 0;
5260}
5261
5262
5263static int
5264wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5265{
5266 WMI_SET_PARAMS_REPLY *reply;
5267
5268 if (len < sizeof(WMI_SET_PARAMS_REPLY)) {
5269 return A_EINVAL;
5270 }
5271 reply = (WMI_SET_PARAMS_REPLY *)datap;
5272
5273 if (0 == reply->status)
5274 {
5275
5276 }
5277 else
5278 {
5279
5280 }
5281
5282 return 0;
5283}
5284
5285
5286#ifdef CONFIG_HOST_DSET_SUPPORT
5287int
5288wmi_dset_data_reply(struct wmi_t *wmip,
5289 u32 status,
5290 u8 *user_buf,
5291 u32 length,
5292 u32 targ_buf,
5293 u32 targ_reply_fn,
5294 u32 targ_reply_arg)
5295{
5296 void *osbuf;
5297 WMIX_DSETDATA_REPLY_CMD *data_reply;
5298 u32 size;
5299
5300 size = sizeof(*data_reply) + length;
5301
5302 if (size <= length) {
5303 return A_ERROR;
5304 }
5305
5306 A_DPRINTF(DBG_WMI,
5307 (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
5308
5309 osbuf = A_NETBUF_ALLOC(size);
5310 if (osbuf == NULL) {
5311 return A_NO_MEMORY;
5312 }
5313 A_NETBUF_PUT(osbuf, size);
5314 data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5315
5316 data_reply->status = status;
5317 data_reply->targ_buf = targ_buf;
5318 data_reply->targ_reply_fn = targ_reply_fn;
5319 data_reply->targ_reply_arg = targ_reply_arg;
5320 data_reply->length = length;
5321
5322 if (status == 0) {
5323 if (a_copy_from_user(data_reply->buf, user_buf, length)) {
5324 A_NETBUF_FREE(osbuf);
5325 return A_ERROR;
5326 }
5327 }
5328
5329 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
5330 NO_SYNC_WMIFLAG));
5331}
5332#endif /* CONFIG_HOST_DSET_SUPPORT */
5333
5334int
5335wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
5336{
5337 void *osbuf;
5338 char *cmd;
5339
5340 wps_enable = status;
5341
5342 osbuf = a_netbuf_alloc(sizeof(1));
5343 if (osbuf == NULL) {
5344 return A_NO_MEMORY;
5345 }
5346
5347 a_netbuf_put(osbuf, sizeof(1));
5348
5349 cmd = (char *)(a_netbuf_to_data(osbuf));
5350
5351 A_MEMZERO(cmd, sizeof(*cmd));
5352 cmd[0] = (status?1:0);
5353 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
5354 NO_SYNC_WMIFLAG));
5355}
5356
5357#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
5358int
5359wmi_prof_cfg_cmd(struct wmi_t *wmip,
5360 u32 period,
5361 u32 nbins)
5362{
5363 void *osbuf;
5364 WMIX_PROF_CFG_CMD *cmd;
5365
5366 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5367 if (osbuf == NULL) {
5368 return A_NO_MEMORY;
5369 }
5370
5371 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5372
5373 cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf));
5374 A_MEMZERO(cmd, sizeof(*cmd));
5375 cmd->period = period;
5376 cmd->nbins = nbins;
5377
5378 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
5379}
5380
5381int
5382wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
5383{
5384 void *osbuf;
5385 WMIX_PROF_ADDR_SET_CMD *cmd;
5386
5387 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5388 if (osbuf == NULL) {
5389 return A_NO_MEMORY;
5390 }
5391
5392 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5393
5394 cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf));
5395 A_MEMZERO(cmd, sizeof(*cmd));
5396 cmd->addr = addr;
5397
5398 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
5399}
5400
5401int
5402wmi_prof_start_cmd(struct wmi_t *wmip)
5403{
5404 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
5405}
5406
5407int
5408wmi_prof_stop_cmd(struct wmi_t *wmip)
5409{
5410 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
5411}
5412
5413int
5414wmi_prof_count_get_cmd(struct wmi_t *wmip)
5415{
5416 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
5417}
5418
5419/* Called to handle WMIX_PROF_CONT_EVENTID */
5420static int
5421wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
5422{
5423 WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
5424
5425 A_DPRINTF(DBG_WMI,
5426 (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG,
5427 prof_data->addr, prof_data->count));
5428
5429 A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
5430
5431 return 0;
5432}
5433#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
5434
5435#ifdef OS_ROAM_MANAGEMENT
5436
5437#define ETHERNET_MAC_ADDRESS_LENGTH 6
5438
5439void
5440wmi_scan_indication (struct wmi_t *wmip)
5441{
5442 struct ieee80211_node_table *nt;
5443 u32 gen;
5444 u32 size;
5445 u32 bsssize;
5446 bss_t *bss;
5447 u32 numbss;
5448 PNDIS_802_11_BSSID_SCAN_INFO psi;
5449 PBYTE pie;
5450 NDIS_802_11_FIXED_IEs *pFixed;
5451 NDIS_802_11_VARIABLE_IEs *pVar;
5452 u32 RateSize;
5453
5454 struct ar6kScanIndication
5455 {
5456 NDIS_802_11_STATUS_INDICATION ind;
5457 NDIS_802_11_BSSID_SCAN_INFO_LIST slist;
5458 } *pAr6kScanIndEvent;
5459
5460 nt = &wmip->wmi_scan_table;
5461
5462 ++nt->nt_si_gen;
5463
5464
5465 gen = nt->nt_si_gen;
5466
5467 size = offsetof(struct ar6kScanIndication, slist) +
5468 offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo);
5469
5470 numbss = 0;
5471
5472 IEEE80211_NODE_LOCK(nt);
5473
5474 //calc size
5475 for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5476 if (bss->ni_si_gen != gen) {
5477 bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs);
5478 bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5479
5480#ifdef SUPPORT_WPA2
5481 if (bss->ni_cie.ie_rsn) {
5482 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5483 }
5484#endif
5485 if (bss->ni_cie.ie_wpa) {
5486 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5487 }
5488
5489 // bsssize must be a multiple of 4 to maintain alignment.
5490 bsssize = (bsssize + 3) & ~3;
5491
5492 size += bsssize;
5493
5494 numbss++;
5495 }
5496 }
5497
5498 if (0 == numbss)
5499 {
5500// RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n"));
5501 ar6000_scan_indication (wmip->wmi_devt, NULL, 0);
5502 IEEE80211_NODE_UNLOCK (nt);
5503 return;
5504 }
5505
5506 pAr6kScanIndEvent = A_MALLOC(size);
5507
5508 if (NULL == pAr6kScanIndEvent)
5509 {
5510 IEEE80211_NODE_UNLOCK(nt);
5511 return;
5512 }
5513
5514 A_MEMZERO(pAr6kScanIndEvent, size);
5515
5516 //copy data
5517 pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList;
5518 pAr6kScanIndEvent->slist.Version = 1;
5519 pAr6kScanIndEvent->slist.NumItems = numbss;
5520
5521 psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0];
5522
5523 for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5524 if (bss->ni_si_gen != gen) {
5525
5526 bss->ni_si_gen = gen;
5527
5528 //Set scan time
5529 psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC;
5530
5531 // Copy data to bssid_ex
5532 bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs);
5533 bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5534
5535#ifdef SUPPORT_WPA2
5536 if (bss->ni_cie.ie_rsn) {
5537 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5538 }
5539#endif
5540 if (bss->ni_cie.ie_wpa) {
5541 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5542 }
5543
5544 // bsssize must be a multiple of 4 to maintain alignment.
5545 bsssize = (bsssize + 3) & ~3;
5546
5547 psi->Bssid.Length = bsssize;
5548
5549 memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH);
5550
5551
5552//if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) ||
5553// ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70)))
5554// RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5]));
5555
5556 psi->Bssid.Ssid.SsidLength = 0;
5557 pie = bss->ni_cie.ie_ssid;
5558
5559 if (pie) {
5560 // Format of SSID IE is:
5561 // Type (1 octet)
5562 // Length (1 octet)
5563 // SSID (Length octets)
5564 //
5565 // Validation of the IE should have occurred within WMI.
5566 //
5567 if (pie[1] <= 32) {
5568 psi->Bssid.Ssid.SsidLength = pie[1];
5569 memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength);
5570 }
5571 }
5572 psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0;
5573
5574 //Post the RSSI value relative to the Standard Noise floor value.
5575 psi->Bssid.Rssi = bss->ni_rssi;
5576
5577 if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) {
5578
5579 if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) {
5580 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24;
5581 }
5582 else {
5583 psi->Bssid.NetworkTypeInUse = Ndis802_11DS;
5584 }
5585 }
5586 else {
5587 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5;
5588 }
5589
5590 psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration);
5591 psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us)
5592 psi->Bssid.Configuration.ATIMWindow = 0;
5593 psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000;
5594 psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS;
5595
5596 RateSize = 0;
5597 pie = bss->ni_cie.ie_rates;
5598 if (pie) {
5599 RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX;
5600 memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize);
5601 }
5602 pie = bss->ni_cie.ie_xrates;
5603 if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) {
5604 memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2],
5605 (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize));
5606 }
5607
5608 // Copy the fixed IEs
5609 psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs);
5610
5611 pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs;
5612 memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp));
5613 pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt;
5614 pFixed->Capabilities = bss->ni_cie.ie_capInfo;
5615
5616 // Copy selected variable IEs
5617
5618 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs));
5619
5620#ifdef SUPPORT_WPA2
5621 // Copy the WPAv2 IE
5622 if (bss->ni_cie.ie_rsn) {
5623 pie = bss->ni_cie.ie_rsn;
5624 psi->Bssid.IELength += pie[1] + 2;
5625 memcpy(pVar, pie, pie[1] + 2);
5626 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5627 }
5628#endif
5629 // Copy the WPAv1 IE
5630 if (bss->ni_cie.ie_wpa) {
5631 pie = bss->ni_cie.ie_wpa;
5632 psi->Bssid.IELength += pie[1] + 2;
5633 memcpy(pVar, pie, pie[1] + 2);
5634 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5635 }
5636
5637 // Advance buffer pointer
5638 psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid));
5639 }
5640 }
5641
5642 IEEE80211_NODE_UNLOCK(nt);
5643
5644// wmi_free_allnodes(wmip);
5645
5646// RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss));
5647
5648 ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size);
5649
5650 kfree(pAr6kScanIndEvent);
5651}
5652#endif
5653
5654u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5655 u32 size)
5656{
5657 u32 index;
5658 u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
5659
5660 /* The list is already in sorted order. Get the next lower value */
5661 for (index = 0; index < size; index ++) {
5662 if (rssi < sq_thresh->upper_threshold[index]) {
5663 threshold = (u8)sq_thresh->upper_threshold[index];
5664 break;
5665 }
5666 }
5667
5668 return threshold;
5669}
5670
5671u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5672 u32 size)
5673{
5674 u32 index;
5675 u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
5676
5677 /* The list is already in sorted order. Get the next lower value */
5678 for (index = 0; index < size; index ++) {
5679 if (rssi > sq_thresh->lower_threshold[index]) {
5680 threshold = (u8)sq_thresh->lower_threshold[index];
5681 break;
5682 }
5683 }
5684
5685 return threshold;
5686}
5687static int
5688wmi_send_rssi_threshold_params(struct wmi_t *wmip,
5689 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
5690{
5691 void *osbuf;
5692 s8 size;
5693 WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
5694
5695 size = sizeof (*cmd);
5696
5697 osbuf = A_NETBUF_ALLOC(size);
5698 if (osbuf == NULL) {
5699 return A_NO_MEMORY;
5700 }
5701
5702 A_NETBUF_PUT(osbuf, size);
5703
5704 cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5705 A_MEMZERO(cmd, size);
5706 memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
5707
5708 return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
5709 NO_SYNC_WMIFLAG));
5710}
5711static int
5712wmi_send_snr_threshold_params(struct wmi_t *wmip,
5713 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
5714{
5715 void *osbuf;
5716 s8 size;
5717 WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
5718
5719 size = sizeof (*cmd);
5720
5721 osbuf = A_NETBUF_ALLOC(size);
5722 if (osbuf == NULL) {
5723 return A_NO_MEMORY;
5724 }
5725
5726 A_NETBUF_PUT(osbuf, size);
5727 cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5728 A_MEMZERO(cmd, size);
5729 memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
5730
5731 return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
5732 NO_SYNC_WMIFLAG));
5733}
5734
5735int
5736wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
5737{
5738 void *osbuf;
5739 WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd;
5740
5741 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5742 if (osbuf == NULL) {
5743 return A_NO_MEMORY;
5744 }
5745
5746 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5747
5748 alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
5749 A_MEMZERO(alloc_cmd, sizeof(*cmd));
5750 memcpy(alloc_cmd, cmd, sizeof(*cmd));
5751
5752 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
5753 NO_SYNC_WMIFLAG));
5754}
5755
5756bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
5757{
5758 wmi_get_current_bssid (wmip, id);
5759 return wlan_node_remove (&wmip->wmi_scan_table, id);
5760}
5761
5762int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
5763{
5764 wlan_setup_node (&wmip->wmi_scan_table, bss, id);
5765 return 0;
5766}
5767
5768static int
5769wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5770{
5771 WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
5772
5773 A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
5774
5775 return 0;
5776}
5777
5778
5779static int
5780wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5781{
5782 WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
5783
5784 A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
5785
5786 return 0;
5787}
5788
5789static int
5790wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5791{
5792 WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
5793
5794 A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
5795
5796 return 0;
5797}
5798
5799int
5800wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5801{
5802 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5803
5804 A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
5805
5806 return 0;
5807}
5808
5809
5810int
5811wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
5812{
5813 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5814
5815 A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
5816
5817 return 0;
5818
5819}
5820
5821static int
5822wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5823{
5824 WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
5825 A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
5826
5827 return 0;
5828}
5829
5830////////////////////////////////////////////////////////////////////////////////
5831//// ////
5832//// AP mode functions ////
5833//// ////
5834////////////////////////////////////////////////////////////////////////////////
5835/*
5836 * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG
5837 *
5838 * When AR6K in AP mode, This command will be called after
5839 * changing ssid, channel etc. It will pass the profile to
5840 * target with a flag which will indicate which parameter changed,
5841 * also if this flag is 0, there was no change in parametes, so
5842 * commit cmd will not be sent to target. Without calling this IOCTL
5843 * the changes will not take effect.
5844 */
5845int
5846wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
5847{
5848 void *osbuf;
5849 WMI_CONNECT_CMD *cm;
5850
5851 osbuf = A_NETBUF_ALLOC(sizeof(*cm));
5852 if (osbuf == NULL) {
5853 return A_NO_MEMORY;
5854 }
5855
5856 A_NETBUF_PUT(osbuf, sizeof(*cm));
5857 cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
5858 A_MEMZERO(cm, sizeof(*cm));
5859
5860 memcpy(cm,p,sizeof(*cm));
5861
5862 return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
5863}
5864
5865/*
5866 * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID
5867 *
5868 * This command will be used to enable/disable hidden ssid functioanlity of
5869 * beacon. If it is enabled, ssid will be NULL in beacon.
5870 */
5871int
5872wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
5873{
5874 void *osbuf;
5875 WMI_AP_HIDDEN_SSID_CMD *hs;
5876
5877 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD));
5878 if (osbuf == NULL) {
5879 return A_NO_MEMORY;
5880 }
5881
5882 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD));
5883 hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf));
5884 A_MEMZERO(hs, sizeof(*hs));
5885
5886 hs->hidden_ssid = hidden_ssid;
5887
5888 A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid));
5889 return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG));
5890}
5891
5892/*
5893 * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA
5894 *
5895 * This command is used to limit max num of STA that can connect
5896 * with this AP. This value should not exceed AP_MAX_NUM_STA (this
5897 * is max num of STA supported by AP). Value was already validated
5898 * in ioctl.c
5899 */
5900int
5901wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
5902{
5903 void *osbuf;
5904 WMI_AP_SET_NUM_STA_CMD *ns;
5905
5906 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD));
5907 if (osbuf == NULL) {
5908 return A_NO_MEMORY;
5909 }
5910
5911 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD));
5912 ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf));
5913 A_MEMZERO(ns, sizeof(*ns));
5914
5915 ns->num_sta = num_sta;
5916
5917 A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta));
5918 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG));
5919}
5920
5921/*
5922 * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC
5923 *
5924 * This command is used to send list of mac of STAs which will
5925 * be allowed to connect with this AP. When this list is empty
5926 * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5927 */
5928int
5929wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
5930{
5931 void *osbuf;
5932 WMI_AP_ACL_MAC_CMD *a;
5933
5934 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD));
5935 if (osbuf == NULL) {
5936 return A_NO_MEMORY;
5937 }
5938
5939 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
5940 a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
5941 A_MEMZERO(a, sizeof(*a));
5942 memcpy(a,acl,sizeof(*acl));
5943
5944 return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
5945}
5946
5947/*
5948 * IOCTL: AR6000_XIOCTL_AP_SET_MLME
5949 *
5950 * This command is used to send list of mac of STAs which will
5951 * be allowed to connect with this AP. When this list is empty
5952 * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5953 */
5954int
5955wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
5956{
5957 void *osbuf;
5958 WMI_AP_SET_MLME_CMD *mlme;
5959
5960 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD));
5961 if (osbuf == NULL) {
5962 return A_NO_MEMORY;
5963 }
5964
5965 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD));
5966 mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf));
5967 A_MEMZERO(mlme, sizeof(*mlme));
5968
5969 mlme->cmd = cmd;
5970 memcpy(mlme->mac, mac, ATH_MAC_LEN);
5971 mlme->reason = reason;
5972
5973 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
5974}
5975
5976static int
5977wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5978{
5979 WMI_PSPOLL_EVENT *ev;
5980
5981 if (len < sizeof(WMI_PSPOLL_EVENT)) {
5982 return A_EINVAL;
5983 }
5984 ev = (WMI_PSPOLL_EVENT *)datap;
5985
5986 A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
5987 return 0;
5988}
5989
5990static int
5991wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
5992{
5993 A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
5994 return 0;
5995}
5996
5997#ifdef WAPI_ENABLE
5998static int
5999wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6000{
6001 u8 *ev;
6002
6003 if (len < 7) {
6004 return A_EINVAL;
6005 }
6006 ev = (u8 *)datap;
6007
6008 A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
6009 return 0;
6010}
6011#endif
6012
6013int
6014wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
6015{
6016 WMI_AP_SET_PVB_CMD *cmd;
6017 void *osbuf = NULL;
6018
6019 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD));
6020 if (osbuf == NULL) {
6021 return A_NO_MEMORY;
6022 }
6023
6024 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD));
6025 cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf));
6026 A_MEMZERO(cmd, sizeof(*cmd));
6027
6028 cmd->aid = aid;
6029 cmd->flag = flag;
6030
6031 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
6032}
6033
6034int
6035wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
6036{
6037 WMI_AP_CONN_INACT_CMD *cmd;
6038 void *osbuf = NULL;
6039
6040 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD));
6041 if (osbuf == NULL) {
6042 return A_NO_MEMORY;
6043 }
6044
6045 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD));
6046 cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf));
6047 A_MEMZERO(cmd, sizeof(*cmd));
6048
6049 cmd->period = period;
6050
6051 return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
6052}
6053
6054int
6055wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
6056{
6057 WMI_AP_PROT_SCAN_TIME_CMD *cmd;
6058 void *osbuf = NULL;
6059
6060 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6061 if (osbuf == NULL) {
6062 return A_NO_MEMORY;
6063 }
6064
6065 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6066 cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf));
6067 A_MEMZERO(cmd, sizeof(*cmd));
6068
6069 cmd->period_min = period;
6070 cmd->dwell_ms = dwell;
6071
6072 return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
6073}
6074
6075int
6076wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
6077{
6078 WMI_AP_SET_DTIM_CMD *cmd;
6079 void *osbuf = NULL;
6080
6081 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD));
6082 if (osbuf == NULL) {
6083 return A_NO_MEMORY;
6084 }
6085
6086 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD));
6087 cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf));
6088 A_MEMZERO(cmd, sizeof(*cmd));
6089
6090 cmd->dtim = dtim;
6091
6092 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG));
6093}
6094
6095/*
6096 * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY
6097 *
6098 * This command is used to set ACL policay. While changing policy, if you
6099 * want to retain the existing MAC addresses in the ACL list, policy should be
6100 * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
6101 * If there is no chage in policy, the list will be intact.
6102 */
6103int
6104wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
6105{
6106 void *osbuf;
6107 WMI_AP_ACL_POLICY_CMD *po;
6108
6109 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD));
6110 if (osbuf == NULL) {
6111 return A_NO_MEMORY;
6112}
6113
6114 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD));
6115 po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
6116 A_MEMZERO(po, sizeof(*po));
6117
6118 po->policy = policy;
6119
6120 return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
6121}
6122
6123int
6124wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
6125{
6126 void *osbuf;
6127 WMI_AP_SET_11BG_RATESET_CMD *rs;
6128
6129 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6130 if (osbuf == NULL) {
6131 return A_NO_MEMORY;
6132 }
6133
6134 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6135 rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf));
6136 A_MEMZERO(rs, sizeof(*rs));
6137
6138 rs->rateset = rateset;
6139
6140 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG));
6141}
6142
6143int
6144wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
6145{
6146 void *osbuf;
6147 WMI_SET_HT_CAP_CMD *htCap;
6148 u8 band;
6149
6150 osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
6151 if (osbuf == NULL) {
6152 return A_NO_MEMORY;
6153 }
6154
6155 A_NETBUF_PUT(osbuf, sizeof(*htCap));
6156
6157 band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ;
6158 wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0;
6159
6160 htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
6161 A_MEMZERO(htCap, sizeof(*htCap));
6162 memcpy(htCap, cmd, sizeof(*htCap));
6163
6164 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
6165 NO_SYNC_WMIFLAG));
6166}
6167
6168int
6169wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
6170{
6171 void *osbuf;
6172 WMI_SET_HT_OP_CMD *htInfo;
6173
6174 osbuf = A_NETBUF_ALLOC(sizeof(*htInfo));
6175 if (osbuf == NULL) {
6176 return A_NO_MEMORY;
6177 }
6178
6179 A_NETBUF_PUT(osbuf, sizeof(*htInfo));
6180
6181 htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf));
6182 A_MEMZERO(htInfo, sizeof(*htInfo));
6183 htInfo->sta_chan_width = sta_chan_width;
6184
6185 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID,
6186 NO_SYNC_WMIFLAG));
6187}
6188
6189int
6190wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
6191{
6192 void *osbuf;
6193 WMI_SET_TX_SELECT_RATES_CMD *pData;
6194
6195 osbuf = A_NETBUF_ALLOC(sizeof(*pData));
6196 if (osbuf == NULL) {
6197 return A_NO_MEMORY;
6198 }
6199
6200 A_NETBUF_PUT(osbuf, sizeof(*pData));
6201
6202 pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
6203 memcpy(pData, pMaskArray, sizeof(*pData));
6204
6205 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
6206 NO_SYNC_WMIFLAG));
6207}
6208
6209
6210int
6211wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
6212{
6213 void *osbuf;
6214 WMI_HCI_CMD *cmd;
6215
6216 osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz);
6217 if (osbuf == NULL) {
6218 return A_NO_MEMORY;
6219 }
6220
6221 A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz);
6222 cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
6223
6224 cmd->cmd_buf_sz = sz;
6225 memcpy(cmd->buf, buf, sz);
6226 return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
6227}
6228
6229int
6230wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
6231{
6232 void *osbuf;
6233 WMI_ALLOW_AGGR_CMD *cmd;
6234
6235 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6236 if (osbuf == NULL) {
6237 return A_NO_MEMORY;
6238 }
6239
6240 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6241
6242 cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf));
6243 cmd->tx_allow_aggr = tx_tidmask;
6244 cmd->rx_allow_aggr = rx_tidmask;
6245
6246 return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
6247}
6248
6249int
6250wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
6251{
6252 void *osbuf;
6253 WMI_ADDBA_REQ_CMD *cmd;
6254
6255 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6256 if (osbuf == NULL) {
6257 return A_NO_MEMORY;
6258 }
6259
6260 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6261
6262 cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6263 cmd->tid = tid;
6264
6265 return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6266}
6267
6268int
6269wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
6270{
6271 void *osbuf;
6272 WMI_DELBA_REQ_CMD *cmd;
6273
6274 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6275 if (osbuf == NULL) {
6276 return A_NO_MEMORY;
6277 }
6278
6279 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6280
6281 cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6282 cmd->tid = tid;
6283 cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */
6284
6285 /* Delete the local aggr state, on host */
6286 return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6287}
6288
6289int
6290wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
6291 bool rxDot11Hdr, bool defragOnHost)
6292{
6293 void *osbuf;
6294 WMI_RX_FRAME_FORMAT_CMD *cmd;
6295
6296 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6297 if (osbuf == NULL) {
6298 return A_NO_MEMORY;
6299 }
6300
6301 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6302
6303 cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
6304 cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
6305 cmd->defragOnHost = (defragOnHost==true)? 1:0;
6306 cmd->metaVersion = rxMetaVersion; /* */
6307
6308 /* Delete the local aggr state, on host */
6309 return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG));
6310}
6311
6312
6313int
6314wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
6315{
6316 void *osbuf;
6317 WMI_SET_THIN_MODE_CMD *cmd;
6318
6319 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6320 if (osbuf == NULL) {
6321 return A_NO_MEMORY;
6322 }
6323
6324 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6325
6326 cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
6327 cmd->enable = (bThinMode==true)? 1:0;
6328
6329 /* Delete the local aggr state, on host */
6330 return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
6331}
6332
6333
6334int
6335wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
6336{
6337 void *osbuf;
6338 WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd;
6339
6340 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6341 if (osbuf == NULL) {
6342 return A_NO_MEMORY;
6343 }
6344
6345 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6346
6347 cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf));
6348 A_MEMZERO(cmd, sizeof(*cmd));
6349 cmd->precedence = precedence;
6350
6351 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
6352 NO_SYNC_WMIFLAG));
6353}
6354
6355int
6356wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
6357{
6358 void *osbuf;
6359 WMI_SET_PMK_CMD *p;
6360
6361 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD));
6362 if (osbuf == NULL) {
6363 return A_NO_MEMORY;
6364 }
6365
6366 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD));
6367
6368 p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
6369 A_MEMZERO(p, sizeof(*p));
6370
6371 memcpy(p->pmk, pmk, WMI_PMK_LEN);
6372
6373 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
6374}
6375
6376int
6377wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
6378{
6379 void *osbuf;
6380 WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
6381
6382 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6383 if (osbuf == NULL) {
6384 return A_NO_MEMORY;
6385 }
6386
6387 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6388
6389 p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
6390 memset(p, 0, sizeof(*p));
6391
6392 p->threshold = cmd->threshold;
6393
6394 return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
6395}
6396
6397int
6398wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
6399{
6400 void *osbuf;
6401 WMI_SET_TX_SGI_PARAM_CMD *cmd;
6402
6403 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6404 if (osbuf == NULL) {
6405 return A_NO_MEMORY ;
6406 }
6407
6408 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6409
6410 cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf));
6411 A_MEMZERO(cmd, sizeof(*cmd));
6412 cmd->sgiMask = sgiMask;
6413 cmd->sgiPERThreshold = sgiPERThreshold;
6414 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID,
6415 NO_SYNC_WMIFLAG));
6416}
6417
6418bss_t *
6419wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
6420 u32 ssidLength,
6421 u32 dot11AuthMode, u32 authMode,
6422 u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
6423{
6424 bss_t *node = NULL;
6425 node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
6426 ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp);
6427
6428 return node;
6429}
6430
6431u16 wmi_ieee2freq (int chan)
6432{
6433 u16 freq = 0;
6434 freq = wlan_ieee2freq (chan);
6435 return freq;
6436
6437}
6438
6439u32 wmi_freq2ieee (u16 freq)
6440{
6441 u16 chan = 0;
6442 chan = wlan_freq2ieee (freq);
6443 return chan;
6444}
diff --git a/drivers/staging/ath6kl/wmi/wmi_host.h b/drivers/staging/ath6kl/wmi/wmi_host.h
new file mode 100644
index 00000000000..53e4f085dfe
--- /dev/null
+++ b/drivers/staging/ath6kl/wmi/wmi_host.h
@@ -0,0 +1,102 @@
1//------------------------------------------------------------------------------
2// <copyright file="wmi_host.h" company="Atheros">
3// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
4//
5//
6// Permission to use, copy, modify, and/or distribute this software for any
7// purpose with or without fee is hereby granted, provided that the above
8// copyright notice and this permission notice appear in all copies.
9//
10// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17//
18//
19//------------------------------------------------------------------------------
20//==============================================================================
21// This file contains local definitios for the wmi host module.
22//
23// Author(s): ="Atheros"
24//==============================================================================
25#ifndef _WMI_HOST_H_
26#define _WMI_HOST_H_
27
28#include "roaming.h"
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33struct wmi_stats {
34 u32 cmd_len_err;
35 u32 cmd_id_err;
36};
37
38#define SSID_IE_LEN_INDEX 13
39
40/* Host side link management data structures */
41#define SIGNAL_QUALITY_THRESHOLD_LEVELS 6
42#define SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
43#define SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
44typedef struct sq_threshold_params_s {
45 s16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS];
46 s16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS];
47 u32 upper_threshold_valid_count;
48 u32 lower_threshold_valid_count;
49 u32 polling_interval;
50 u8 weight;
51 u8 last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target.
52 u8 last_rssi_poll_event; //Not sure if it belongs to host or target
53} SQ_THRESHOLD_PARAMS;
54
55/*
56 * These constants are used with A_WLAN_BAND_SET.
57 */
58#define A_BAND_24GHZ 0
59#define A_BAND_5GHZ 1
60#define A_NUM_BANDS 2
61
62struct wmi_t {
63 bool wmi_ready;
64 bool wmi_numQoSStream;
65 u16 wmi_streamExistsForAC[WMM_NUM_AC];
66 u8 wmi_fatPipeExists;
67 void *wmi_devt;
68 struct wmi_stats wmi_stats;
69 struct ieee80211_node_table wmi_scan_table;
70 u8 wmi_bssid[ATH_MAC_LEN];
71 u8 wmi_powerMode;
72 u8 wmi_phyMode;
73 u8 wmi_keepaliveInterval;
74#ifdef THREAD_X
75 A_CSECT_T wmi_lock;
76#else
77 A_MUTEX_T wmi_lock;
78#endif
79 HTC_ENDPOINT_ID wmi_endpoint_id;
80 SQ_THRESHOLD_PARAMS wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_NUM_MAX];
81 CRYPTO_TYPE wmi_pair_crypto_type;
82 CRYPTO_TYPE wmi_grp_crypto_type;
83 bool wmi_is_wmm_enabled;
84 u8 wmi_ht_allowed[A_NUM_BANDS];
85 u8 wmi_traffic_class;
86};
87
88#ifdef THREAD_X
89#define INIT_WMI_LOCK(w) A_CSECT_INIT(&(w)->wmi_lock)
90#define LOCK_WMI(w) A_CSECT_ENTER(&(w)->wmi_lock);
91#define UNLOCK_WMI(w) A_CSECT_LEAVE(&(w)->wmi_lock);
92#define DELETE_WMI_LOCK(w) A_CSECT_DELETE(&(w)->wmi_lock);
93#else
94#define LOCK_WMI(w) A_MUTEX_LOCK(&(w)->wmi_lock);
95#define UNLOCK_WMI(w) A_MUTEX_UNLOCK(&(w)->wmi_lock);
96#endif
97
98#ifdef __cplusplus
99}
100#endif
101
102#endif /* _WMI_HOST_H_ */