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