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