DEBUG: Disable unused function in wave300 firmware
[wave300.git] / wireless / driver / linux / core_ext.c
blobe2a1cf056015073f152e93890711751779d32ffb
1 /******************************************************************************
3 Copyright (c) 2012
4 Lantiq Deutschland GmbH
6 For licensing information, see the file 'LICENSE' in the root folder of
7 this software module.
9 ******************************************************************************/
12 * $Id$
16 * Core functionality (extension)
20 #define LOG_LOCAL_GID GID_CORE
22 #undef LOG_LOCAL_FID
23 #define LOG_LOCAL_FID 5
25 /* 802.11w begin */
27 static int
28 _mtlk_core_set_dot11w_pmf (mtlk_core_t *core, mtlk_pdb_id_t param_id, uint32 param_value)
30 int res = MTLK_ERR_OK;
32 MTLK_ASSERT(core != NULL);
34 if (param_value > 1) {
35 ELOG_D("Incorrect value: %d. Must be 0 or 1.", param_value);
36 res = MTLK_ERR_PARAMS;
37 goto end;
40 MTLK_CORE_PDB_SET_INT(core, param_id, param_value);
42 end:
44 return res;
47 static int
48 _mtlk_core_set_dot11w_saq_tmout (mtlk_core_t *core, mtlk_pdb_id_t param_id, uint32 param_value, uint16 obj_id)
50 int res = MTLK_ERR_OK;
51 mtlk_core_t *core_master = NULL;
53 MTLK_ASSERT(core != NULL);
55 core_master = mtlk_core_get_master(core);
56 MTLK_ASSERT(core_master != NULL);
58 if (param_value == 0) {
59 ELOG_D("Incorrect value: %d. Must be 1..4294967295", param_value);
60 res = MTLK_ERR_PARAMS;
61 goto end;
64 res = mtlk_set_mib_value_uint32(mtlk_vap_get_txmm(core_master->vap_handle), obj_id, param_value);
66 if(res != MTLK_ERR_OK)
68 ELOG_DD("Failed to set MIB id %d value %d", obj_id, param_value);
69 goto end;
72 MTLK_CORE_PDB_SET_INT(core_master, param_id, param_value);
74 end:
76 return res;
79 static int
80 _mtlk_core_set_dot11w_cfg (mtlk_handle_t hcore, const void* data, uint32 data_size)
82 uint32 res = MTLK_ERR_OK;
83 uint32 _dot11w_cfg_size;
84 mtlk_core_t *core = (mtlk_core_t*)hcore;
85 mtlk_dot11w_cfg_t *_dot11w_cfg = NULL;
86 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
88 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
90 _dot11w_cfg = mtlk_clpb_enum_get_next(clpb, &_dot11w_cfg_size);
91 MTLK_ASSERT(NULL != _dot11w_cfg);
92 MTLK_ASSERT(sizeof(*_dot11w_cfg) == _dot11w_cfg_size);
94 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
95 MTLK_CFG_CHECK_ITEM_AND_CALL(_dot11w_cfg, pmf_activated, _mtlk_core_set_dot11w_pmf,
96 (core, PARAM_DB_CORE_PMF_ACTIVATED, _dot11w_cfg->pmf_activated), res);
97 MTLK_CFG_CHECK_ITEM_AND_CALL(_dot11w_cfg, pmf_required, _mtlk_core_set_dot11w_pmf,
98 (core, PARAM_DB_CORE_PMF_REQUIRED, _dot11w_cfg->pmf_required), res);
99 MTLK_CFG_CHECK_ITEM_AND_CALL(_dot11w_cfg, saq_retr_tmout, _mtlk_core_set_dot11w_saq_tmout,
100 (core, PARAM_DB_CORE_SAQ_RETR_TMOUT,
101 _dot11w_cfg->saq_retr_tmout, MIB_SAQUERY_RETRY_TIMEOUT), res);
102 MTLK_CFG_CHECK_ITEM_AND_CALL(_dot11w_cfg, saq_max_tmout, _mtlk_core_set_dot11w_saq_tmout,
103 (core, PARAM_DB_CORE_SAQ_MAX_TMOUT,
104 _dot11w_cfg->saq_max_tmout, MIB_SAQUERY_MAX_TIMEOUT), res);
105 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
107 return mtlk_clpb_push(clpb, &res, sizeof(res));
110 static int
111 _mtlk_core_get_dot11w_cfg (mtlk_handle_t hcore, const void* data, uint32 data_size)
113 uint32 res = MTLK_ERR_OK;
114 mtlk_dot11w_cfg_t _dot11w_cfg;
115 mtlk_core_t *core = (mtlk_core_t*)hcore;
116 mtlk_core_t *core_master = mtlk_core_get_master(core);
117 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
118 mtlk_txmm_t *txmm;
120 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
122 txmm = mtlk_vap_get_txmm(core_master->vap_handle);
123 memset(&_dot11w_cfg, 0, sizeof(_dot11w_cfg));
125 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
126 MTLK_CFG_SET_ITEM(&_dot11w_cfg, pmf_activated,
127 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_PMF_ACTIVATED));
128 MTLK_CFG_SET_ITEM(&_dot11w_cfg, pmf_required,
129 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_PMF_REQUIRED));
130 MTLK_CFG_SET_ITEM_BY_FUNC(&_dot11w_cfg, saq_retr_tmout, mtlk_get_mib_value_uint32,
131 (txmm, MIB_SAQUERY_RETRY_TIMEOUT, &_dot11w_cfg.saq_retr_tmout), res);
132 MTLK_CFG_SET_ITEM_BY_FUNC(&_dot11w_cfg, saq_max_tmout, mtlk_get_mib_value_uint32,
133 (txmm, MIB_SAQUERY_MAX_TIMEOUT, &_dot11w_cfg.saq_max_tmout), res);
134 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
136 res = mtlk_clpb_push(clpb, &res, sizeof(res));
137 if (MTLK_ERR_OK == res) {
138 res = mtlk_clpb_push(clpb, &_dot11w_cfg, sizeof(_dot11w_cfg));
141 return res;
144 /* 802.11w end */
146 static int
147 _mtlk_core_set_recovery_cfg (mtlk_handle_t hcore, const void *data, uint32 data_size)
149 uint32 res = MTLK_ERR_OK;
150 mtlk_core_t *core = (mtlk_core_t*)hcore;
151 mtlk_rcvry_cfg_t *_rcvry_cfg = NULL;
152 uint32 _rcvry_cfg_size;
153 mtlk_clpb_t *clpb = *(mtlk_clpb_t **)data;
155 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
157 _rcvry_cfg = mtlk_clpb_enum_get_next(clpb, &_rcvry_cfg_size);
158 MTLK_ASSERT(NULL != _rcvry_cfg);
159 MTLK_ASSERT(sizeof(*_rcvry_cfg) == _rcvry_cfg_size);
161 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
162 MTLK_CFG_CHECK_ITEM_AND_CALL(_rcvry_cfg, recovery_cfg, mtlk_rcvry_set_cfg,
163 (mtlk_vap_manager_get_rcvry(mtlk_vap_get_manager(core->vap_handle)),
164 &_rcvry_cfg->recovery_cfg), res);
165 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
167 return mtlk_clpb_push(clpb, &res, sizeof(res));
170 static int
171 _mtlk_core_get_recovery_cfg (mtlk_handle_t hcore, const void *data, uint32 data_size)
173 uint32 res = MTLK_ERR_OK;
174 mtlk_rcvry_cfg_t _rcvry_cfg;
175 mtlk_core_t *core = (mtlk_core_t*)hcore;
176 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
178 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
180 memset(&_rcvry_cfg, 0, sizeof(_rcvry_cfg));
182 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
183 MTLK_CFG_SET_ITEM_BY_FUNC(&_rcvry_cfg, recovery_cfg, mtlk_rcvry_get_cfg,
184 (mtlk_vap_manager_get_rcvry(mtlk_vap_get_manager(core->vap_handle)),
185 &_rcvry_cfg.recovery_cfg), res);
186 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
188 res = mtlk_clpb_push(clpb, &res, sizeof(res));
189 if (MTLK_ERR_OK == res) {
190 res = mtlk_clpb_push(clpb, &_rcvry_cfg, sizeof(_rcvry_cfg));
192 return res;
195 static int
196 _mtlk_core_stop_lm(mtlk_handle_t hcore, const void* data, uint32 data_size)
198 int res = MTLK_ERR_OK;
199 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
201 mtlk_txmm_msg_t man_msg;
202 mtlk_txmm_data_t *man_entry = NULL;
204 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), &res);
205 if (!man_entry) {
206 ELOG_D("CID-%04x: Can't stop lower MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
207 res = MTLK_ERR_NO_MEM;
208 goto end;
211 man_entry->id = UM_LM_STOP_REQ;
212 man_entry->payload_size = 0;
214 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
215 if (MTLK_ERR_OK != res) {
216 ELOG_D("CID-%04x: Can't stop lower MAC, timed-out", mtlk_vap_get_oid(core->vap_handle));
219 mtlk_txmm_msg_cleanup(&man_msg);
220 end:
221 return res;
224 static int
225 _mtlk_core_mac_calibrate(mtlk_handle_t hcore, const void* data, uint32 data_size)
227 int res = MTLK_ERR_OK;
228 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
230 mtlk_txmm_msg_t man_msg;
231 mtlk_txmm_data_t *man_entry = NULL;
233 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), &res);
234 if (!man_entry) {
235 ELOG_D("CID-%04x: Can't calibrate due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
236 res = MTLK_ERR_NO_MEM;
237 goto end;
240 man_entry->id = UM_PER_CHANNEL_CALIBR_REQ;
241 man_entry->payload_size = 0;
243 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
244 if (MTLK_ERR_OK != res) {
245 ELOG_D("CID-%04x: Can't calibrate, timed-out", mtlk_vap_get_oid(core->vap_handle));
248 mtlk_txmm_msg_cleanup(&man_msg);
249 end:
250 return res;
253 static int
254 _mtlk_core_get_iw_generic(mtlk_handle_t hcore, const void* data, uint32 data_size)
256 int res = MTLK_ERR_OK;
258 UMI_GENERIC_MAC_REQUEST *req_df_cfg = NULL;
259 UMI_GENERIC_MAC_REQUEST *pdata = NULL;
260 uint32 req_df_cfg_size;
261 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
262 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
264 mtlk_txmm_msg_t man_msg;
265 mtlk_txmm_data_t *man_entry = NULL;
267 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
269 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), &res);
270 if (!man_entry) {
271 ELOG_D("CID-%04x: Can't send request to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
272 res = MTLK_ERR_NO_MEM;
273 goto end;
276 req_df_cfg = mtlk_clpb_enum_get_next(clpb, &req_df_cfg_size);
278 MTLK_ASSERT(NULL != req_df_cfg);
279 MTLK_ASSERT(sizeof(*req_df_cfg) == req_df_cfg_size);
281 pdata = (UMI_GENERIC_MAC_REQUEST*)man_entry->payload;
282 man_entry->id = UM_MAN_GENERIC_MAC_REQ;
283 man_entry->payload_size = sizeof(*pdata);
285 pdata->opcode= cpu_to_le32(req_df_cfg->opcode);
286 pdata->size= cpu_to_le32(req_df_cfg->size);
287 pdata->action= cpu_to_le32(req_df_cfg->action);
288 pdata->res0= cpu_to_le32(req_df_cfg->res0);
289 pdata->res1= cpu_to_le32(req_df_cfg->res1);
290 pdata->res2= cpu_to_le32(req_df_cfg->res2);
291 pdata->retStatus= cpu_to_le32(req_df_cfg->retStatus);
293 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
294 if (MTLK_ERR_OK != res) {
295 ELOG_D("CID-%04x: Can't send generic request to MAC, timed-out", mtlk_vap_get_oid(core->vap_handle));
296 goto err_send;
299 /* Send response to DF user */
300 pdata->opcode= cpu_to_le32(pdata->opcode);
301 pdata->size= cpu_to_le32(pdata->size);
302 pdata->action= cpu_to_le32(pdata->action);
303 pdata->res0= cpu_to_le32(pdata->res0);
304 pdata->res1= cpu_to_le32(pdata->res1);
305 pdata->res2= cpu_to_le32(pdata->res2);
306 pdata->retStatus= cpu_to_le32(pdata->retStatus);
308 res = mtlk_clpb_push(clpb, pdata, sizeof(*pdata));
310 err_send:
311 mtlk_txmm_msg_cleanup(&man_msg);
312 end:
313 return res;
316 static int
317 _mtlk_core_set_leds_cfg(mtlk_core_t *core, UMI_SET_LED *leds_cfg)
319 int res = MTLK_ERR_OK;
320 mtlk_txmm_msg_t man_msg;
321 mtlk_txmm_data_t *man_entry = NULL;
322 UMI_SET_LED* pdata = NULL;
324 MTLK_ASSERT(NULL != leds_cfg);
326 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), &res);
327 if (!man_entry) {
328 ELOG_D("CID-%04x: No man entry to set MAC leds cfg (GPIO)", mtlk_vap_get_oid(core->vap_handle));
329 res = MTLK_ERR_NO_MEM;
330 goto end;
333 pdata = (UMI_SET_LED*)man_entry->payload;
334 man_entry->id = UM_MAN_SET_LED_REQ;
335 man_entry->payload_size = sizeof(*leds_cfg);
337 pdata->u8BasebLed = leds_cfg->u8BasebLed;
338 pdata->u8LedStatus = leds_cfg->u8LedStatus;
340 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
341 if (MTLK_ERR_OK != res) {
342 ELOG_D("CID-%04x: MAC Control GPIO set timeout", mtlk_vap_get_oid(core->vap_handle));
345 mtlk_txmm_msg_cleanup(&man_msg);
347 end:
348 return res;
351 static int
352 _mtlk_core_ctrl_mac_gpio(mtlk_handle_t hcore, const void* data, uint32 data_size)
354 UMI_SET_LED *leds_cfg = NULL;
355 uint32 leds_cfg_size;
356 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
357 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
359 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
361 leds_cfg = mtlk_clpb_enum_get_next(clpb, &leds_cfg_size);
363 MTLK_ASSERT(NULL != leds_cfg);
364 MTLK_ASSERT(sizeof(*leds_cfg) == leds_cfg_size);
366 return _mtlk_core_set_leds_cfg(core, leds_cfg);
369 static int
370 _mtlk_core_gen_dataex_get_connection_stats (mtlk_core_t *core,
371 WE_GEN_DATAEX_REQUEST *preq,
372 mtlk_clpb_t *clpb)
374 int res = MTLK_ERR_OK;
375 WE_GEN_DATAEX_CONNECTION_STATUS dataex_conn_status;
376 WE_GEN_DATAEX_RESPONSE resp;
377 int nof_connected;
378 const sta_entry *sta = NULL;
379 mtlk_stadb_iterator_t iter;
381 memset(&resp, 0, sizeof(resp));
382 memset(&dataex_conn_status, 0, sizeof(dataex_conn_status));
384 resp.ver = WE_GEN_DATAEX_PROTO_VER;
385 resp.status = WE_GEN_DATAEX_SUCCESS;
386 resp.datalen = sizeof(WE_GEN_DATAEX_CONNECTION_STATUS);
388 if (preq->datalen < resp.datalen) {
389 return MTLK_ERR_NO_MEM;
392 memset(&dataex_conn_status, 0, sizeof(WE_GEN_DATAEX_CONNECTION_STATUS));
394 nof_connected = 0;
396 sta = mtlk_stadb_iterate_first(&core->slow_ctx->stadb, &iter);
397 if (sta) {
398 do {
399 WE_GEN_DATAEX_DEVICE_STATUS dataex_dev_status;
400 dataex_dev_status.u32RxCount = mtlk_sta_get_cnt(sta, MTLK_STAI_CNT_PACKETS_RECEIVED);
401 dataex_dev_status.u32TxCount = mtlk_sta_get_cnt(sta, MTLK_STAI_CNT_PACKETS_SENT);
403 resp.datalen += sizeof(WE_GEN_DATAEX_DEVICE_STATUS);
404 if (preq->datalen < resp.datalen) {
405 res = MTLK_ERR_NO_MEM;
406 break;
409 res = mtlk_clpb_push(clpb, &dataex_dev_status, sizeof(WE_GEN_DATAEX_DEVICE_STATUS));
410 if (MTLK_ERR_OK != res) {
411 break;
414 nof_connected++;
416 sta = mtlk_stadb_iterate_next(&iter);
417 } while (sta);
418 mtlk_stadb_iterate_done(&iter);
421 if (MTLK_ERR_OK == res) {
422 dataex_conn_status.u32NumOfConnections = nof_connected;
423 res = mtlk_clpb_push(clpb, &dataex_conn_status, sizeof(WE_GEN_DATAEX_CONNECTION_STATUS));
426 if (MTLK_ERR_OK == res) {
427 res = mtlk_clpb_push(clpb, &resp, sizeof(resp));
429 return res;
432 static int
433 _mtlk_core_gen_dataex_get_status (mtlk_core_t *core,
434 WE_GEN_DATAEX_REQUEST *preq,
435 mtlk_clpb_t *clpb)
437 int res = MTLK_ERR_OK;
438 const sta_entry *sta;
439 WE_GEN_DATAEX_RESPONSE resp;
440 WE_GEN_DATAEX_STATUS status;
441 mtlk_stadb_iterator_t iter;
443 memset(&resp, 0, sizeof(resp));
444 memset(&status, 0, sizeof(status));
446 if (preq->datalen < sizeof(status)) {
447 resp.status = WE_GEN_DATAEX_DATABUF_TOO_SMALL;
448 resp.datalen = sizeof(status);
449 goto end;
452 resp.ver = WE_GEN_DATAEX_PROTO_VER;
453 resp.status = WE_GEN_DATAEX_SUCCESS;
454 resp.datalen = sizeof(status);
456 memset(&status, 0, sizeof(status));
458 status.security_on = 0;
459 status.wep_enabled = 0;
461 sta = mtlk_stadb_iterate_first(&core->slow_ctx->stadb, &iter);
462 if (sta) {
463 do {
464 /* Check global WEP enabled flag only if some STA connected */
465 if ((mtlk_sta_get_cipher(sta) != IW_ENCODE_ALG_NONE) || core->slow_ctx->wep_enabled) {
466 status.security_on = 1;
467 if (core->slow_ctx->wep_enabled) {
468 status.wep_enabled = 1;
470 break;
472 sta = mtlk_stadb_iterate_next(&iter);
473 } while (sta);
474 mtlk_stadb_iterate_done(&iter);
477 status.scan_started = mtlk_core_scan_is_running(core);
478 if (!mtlk_vap_is_slave_ap(core->vap_handle) && (mtlk_scan_is_initialized(&core->slow_ctx->scan))) {
479 status.frequency_band = mtlk_core_get_freq_band_cur(core);
481 else {
482 status.frequency_band = MTLK_HW_BAND_NONE;
484 status.link_up = (mtlk_core_get_net_state(core) == NET_STATE_CONNECTED) ? 1 : 0;
486 res = mtlk_clpb_push(clpb, &status, sizeof(status));
487 if (MTLK_ERR_OK == res) {
488 res = mtlk_clpb_push(clpb, &resp, sizeof(resp));
491 end:
492 return res;
495 static int
496 _mtlk_core_gen_dataex_send_mac_leds (mtlk_core_t *core,
497 mtlk_core_ui_gen_data_t *req,
498 mtlk_clpb_t *clpb)
500 int res = 0;
501 WE_GEN_DATAEX_RESPONSE resp;
502 UMI_SET_LED leds_cfg;
503 WE_GEN_DATAEX_LED *leds_status = NULL;
505 MTLK_ASSERT(NULL != req);
507 memset(&resp, 0, sizeof(resp));
508 memset(&leds_cfg, 0, sizeof(leds_cfg));
510 leds_status = &req->leds_status;
512 resp.ver = WE_GEN_DATAEX_PROTO_VER;
513 if (req->request.datalen < sizeof(WE_GEN_DATAEX_LED)) {
514 resp.status = WE_GEN_DATAEX_DATABUF_TOO_SMALL;
515 resp.datalen = sizeof(WE_GEN_DATAEX_LED);
516 goto end;
519 ILOG2_DD("u8BasebLed = %d, u8LedStatus = %d", req->leds_status.u8BasebLed,
520 req->leds_status.u8LedStatus);
522 resp.datalen = sizeof(leds_status);
524 leds_cfg.u8LedStatus = req->leds_status.u8LedStatus;
525 leds_cfg.u8BasebLed = req->leds_status.u8BasebLed;
527 res = _mtlk_core_set_leds_cfg(core, &leds_cfg);
528 if (MTLK_ERR_OK != res) {
529 resp.status = WE_GEN_DATAEX_FAIL;
531 else {
532 resp.status = WE_GEN_DATAEX_SUCCESS;
535 res = mtlk_clpb_push(clpb, &resp, sizeof(resp));
537 end:
538 return res;
541 static int
542 _mtlk_core_gen_data_exchange(mtlk_handle_t hcore, const void* data, uint32 data_size)
544 int res = MTLK_ERR_OK;
546 mtlk_core_ui_gen_data_t *req = NULL;
547 uint32 req_size;
548 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
549 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
551 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
553 req = mtlk_clpb_enum_get_next(clpb, &req_size);
555 MTLK_ASSERT(NULL != req);
556 MTLK_ASSERT(sizeof(*req) == req_size);
558 switch (req->request.cmd_id) {
559 case WE_GEN_DATAEX_CMD_CONNECTION_STATS:
560 res = _mtlk_core_gen_dataex_get_connection_stats(core, &req->request, clpb);
561 break;
562 case WE_GEN_DATAEX_CMD_STATUS:
563 res = _mtlk_core_gen_dataex_get_status(core, &req->request, clpb);
564 break;
565 case WE_GEN_DATAEX_CMD_LEDS_MAC:
566 res = _mtlk_core_gen_dataex_send_mac_leds(core, req, clpb);
567 break;
568 default:
569 MTLK_ASSERT(0);
572 return res;
575 uint32
576 mtlk_core_get_available_bitrates (struct nic *nic)
578 uint8 net_mode;
579 uint32 mask = 0;
581 /* Get all needed MIBs */
582 if (nic->net_state == NET_STATE_CONNECTED)
583 net_mode = mtlk_core_get_network_mode_cur(nic);
584 else
585 net_mode = mtlk_core_get_network_mode_cfg(nic);
586 mask = get_operate_rate_set(net_mode);
587 ILOG3_D("Configuration mask: 0x%08x", mask);
589 return mask;
592 static int
593 _mtlk_core_store_gen_ie (struct nic *nic, u8 *ie, u16 ie_len, u8 ie_type)
595 if (ie_type >= UMI_WPS_IE_NUM) {
596 return MTLK_ERR_NOT_SUPPORTED;
599 memset(nic->slow_ctx->gen_ie[ie_type], 0, sizeof(nic->slow_ctx->gen_ie[ie_type]));
600 nic->slow_ctx->gen_ie_len[ie_type] = ie_len;
602 if (ie && ie_len) {
603 memcpy(nic->slow_ctx->gen_ie[ie_type], ie, ie_len);
606 return MTLK_ERR_OK;
610 mtlk_core_set_gen_ie (struct nic *nic, u8 *ie, u16 ie_len, u8 ie_type)
612 int res = 0;
613 mtlk_txmm_msg_t man_msg;
614 mtlk_txmm_data_t *man_entry;
615 UMI_GENERIC_IE *ie_req;
617 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg,
618 mtlk_vap_get_txmm(nic->vap_handle),
619 NULL);
620 if (!man_entry) {
621 ELOG_D("CID-%04x: No man entry available", mtlk_vap_get_oid(nic->vap_handle));
622 res = -EAGAIN;
623 goto end;
626 man_entry->id = UM_MAN_SET_IE_REQ;
627 man_entry->payload_size = sizeof(UMI_GENERIC_IE);
628 ie_req = (UMI_GENERIC_IE*) man_entry->payload;
629 memset(ie_req, 0, sizeof(*ie_req));
631 ie_req->u8Type = ie_type;
633 if (ie_len > sizeof(ie_req->au8IE)) {
634 ELOG_DDD("CID-%04x: invalid IE length (%i > %i)", mtlk_vap_get_oid(nic->vap_handle),
635 ie_len, (int)sizeof(ie_req->au8IE));
636 res = -EINVAL;
637 goto end;
639 if (ie && ie_len)
640 memcpy(ie_req->au8IE, ie, ie_len);
641 ie_req->u16Length = cpu_to_le16(ie_len);
643 if (mtlk_txmm_msg_send_blocked(&man_msg,
644 MTLK_MM_BLOCKED_SEND_TIMEOUT) != MTLK_ERR_OK) {
645 ELOG_D("CID-%04x: cannot set IE to MAC", mtlk_vap_get_oid(nic->vap_handle));
646 res = -EINVAL;
649 end:
650 if (man_entry)
651 mtlk_txmm_msg_cleanup(&man_msg);
653 return res;
656 static int
657 mtlk_core_is_band_supported(mtlk_core_t *nic, unsigned band)
659 if (band == MTLK_HW_BAND_BOTH && mtlk_vap_is_ap(nic->vap_handle)) // AP can't be dual-band
660 return MTLK_ERR_UNKNOWN;
662 return mtlk_eeprom_is_band_supported(mtlk_core_get_eeprom(nic), band);
666 mtlk_core_update_network_mode(mtlk_core_t* nic, uint8 net_mode)
668 mtlk_core_t *core = nic;
669 uint8 band_new = net_mode_to_band(net_mode);
671 MTLK_ASSERT(NULL != nic);
673 if (mtlk_core_is_band_supported(core, band_new) != MTLK_ERR_OK) {
674 if (band_new == MTLK_HW_BAND_BOTH) {
676 * Just in case of single-band hardware
677 * continue to use `default' frequency band,
678 * which is de facto correct.
680 ELOG_D("CID-%04x: dualband isn't supported", mtlk_vap_get_oid(core->vap_handle));
681 return MTLK_ERR_OK;
682 } else {
683 ELOG_DS("CID-%04x: %s band isn't supported", mtlk_vap_get_oid(core->vap_handle),
684 mtlk_eeprom_band_to_string(net_mode_to_band(net_mode)));
685 return MTLK_ERR_NOT_SUPPORTED;
689 ILOG1_S("Set Network Mode to %s", net_mode_to_string(net_mode));
691 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_NET_MODE_CUR, net_mode);
692 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_NET_MODE_CFG, net_mode);
694 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_IS_HT_CUR, is_ht_net_mode(net_mode));
695 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_IS_HT_CFG, is_ht_net_mode(net_mode));
697 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_FREQ_BAND_CFG, band_new);
698 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_FREQ_BAND_CUR, band_new);
700 /* The set of supported bands may be changed by this request. */
701 /* Scan cache to be cleared to throw out BSS from unsupported now bands */
702 mtlk_cache_clear(&core->slow_ctx->cache);
703 return MTLK_ERR_OK;
706 static int __MTLK_IFUNC
707 _mtlk_core_get_ta_cfg (mtlk_handle_t hcore,
708 const void* data, uint32 data_size)
710 uint32 res = MTLK_ERR_OK;
711 mtlk_ta_cfg_t *ta_cfg;
712 mtlk_core_t *core = (mtlk_core_t*)hcore;
713 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
715 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
717 ta_cfg = mtlk_osal_mem_alloc(sizeof(*ta_cfg), MTLK_MEM_TAG_CLPB);
718 if(ta_cfg == NULL) {
719 ELOG_V("Can't allocate clipboard data");
720 return MTLK_ERR_NO_MEM;
723 memset(ta_cfg, 0, sizeof(*ta_cfg));
725 MTLK_CFG_SET_ITEM(ta_cfg, timer_resolution,
726 mtlk_ta_get_timer_resolution_ticks(mtlk_vap_get_ta(core->vap_handle)));
728 MTLK_CFG_SET_ITEM_BY_FUNC_VOID(ta_cfg, debug_info, mtlk_ta_get_debug_info,
729 (mtlk_vap_get_ta(core->vap_handle), &ta_cfg->debug_info));
731 res = mtlk_clpb_push(clpb, &res, sizeof(res));
732 if (MTLK_ERR_OK == res) {
733 res = mtlk_clpb_push_nocopy(clpb, ta_cfg, sizeof(*ta_cfg));
734 if(MTLK_ERR_OK != res) {
735 mtlk_osal_mem_free(ta_cfg);
739 return res;
742 static int __MTLK_IFUNC
743 _mtlk_core_set_ta_cfg (mtlk_handle_t hcore,
744 const void* data, uint32 data_size)
746 uint32 res = MTLK_ERR_OK;
747 mtlk_ta_cfg_t *ta_cfg;
748 uint32 ta_cfg_size;
749 mtlk_core_t *core = (mtlk_core_t*)hcore;
750 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
752 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
754 ta_cfg = mtlk_clpb_enum_get_next(clpb, &ta_cfg_size);
756 MTLK_ASSERT(NULL != ta_cfg);
757 MTLK_ASSERT(sizeof(*ta_cfg) == ta_cfg_size);
759 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
761 MTLK_CFG_CHECK_ITEM_AND_CALL(ta_cfg, timer_resolution, mtlk_ta_set_timer_resolution_ticks,
762 (mtlk_vap_get_ta(core->vap_handle), ta_cfg->timer_resolution), res);
764 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
766 return mtlk_clpb_push(clpb, &res, sizeof(res));
770 static int __MTLK_IFUNC
771 _mtlk_core_get_uapsd_mode (mtlk_handle_t hcore,
772 const void* data, uint32 data_size)
774 uint32 res = MTLK_ERR_OK;
775 mtlk_uapsd_mode_cfg_t uapsd_mode_cfg;
776 mtlk_core_t *core = (mtlk_core_t*)hcore;
777 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
779 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
781 memset(&uapsd_mode_cfg, 0, sizeof(uapsd_mode_cfg));
783 MTLK_CFG_SET_ITEM(&uapsd_mode_cfg, uapsd_enabled, core->uapsd_enabled);
785 res = mtlk_clpb_push(clpb, &res, sizeof(res));
786 if (MTLK_ERR_OK == res) {
787 res = mtlk_clpb_push(clpb, &uapsd_mode_cfg, sizeof(uapsd_mode_cfg));
790 return res;
793 static int __MTLK_IFUNC
794 _mtlk_core_set_uapsd_mode (mtlk_handle_t hcore,
795 const void* data, uint32 data_size)
797 uint32 res = MTLK_ERR_OK;
798 mtlk_uapsd_mode_cfg_t *uapsd_mode_cfg;
799 uint32 uapsd_mode_cfg_size;
800 mtlk_core_t *core = (mtlk_core_t*)hcore;
801 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
803 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
805 uapsd_mode_cfg = mtlk_clpb_enum_get_next(clpb, &uapsd_mode_cfg_size);
807 MTLK_ASSERT(NULL != uapsd_mode_cfg);
808 MTLK_ASSERT(sizeof(*uapsd_mode_cfg) == uapsd_mode_cfg_size);
810 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
812 MTLK_CFG_GET_ITEM(uapsd_mode_cfg, uapsd_enabled, core->uapsd_enabled);
814 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
816 return mtlk_clpb_push(clpb, &res, sizeof(res));
820 static int __MTLK_IFUNC
821 _mtlk_core_get_uapsd_cfg (mtlk_handle_t hcore,
822 const void* data, uint32 data_size)
824 uint32 res = MTLK_ERR_OK;
825 mtlk_uapsd_cfg_t uapsd_cfg;
826 mtlk_core_t *core = (mtlk_core_t*)hcore;
827 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
829 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
831 memset(&uapsd_cfg, 0, sizeof(uapsd_cfg));
833 MTLK_CFG_SET_ITEM(&uapsd_cfg, uapsd_max_sp, core->uapsd_max_sp);
835 res = mtlk_clpb_push(clpb, &res, sizeof(res));
836 if (MTLK_ERR_OK == res) {
837 res = mtlk_clpb_push(clpb, &uapsd_cfg, sizeof(uapsd_cfg));
840 return res;
843 static int __MTLK_IFUNC
844 _mtlk_core_set_uapsd_cfg (mtlk_handle_t hcore,
845 const void* data, uint32 data_size)
847 uint32 res = MTLK_ERR_OK;
848 mtlk_uapsd_cfg_t *uapsd_cfg;
849 uint32 uapsd_cfg_size;
850 mtlk_core_t *core = (mtlk_core_t*)hcore;
851 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
853 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
855 uapsd_cfg = mtlk_clpb_enum_get_next(clpb, &uapsd_cfg_size);
857 MTLK_ASSERT(NULL != uapsd_cfg);
858 MTLK_ASSERT(sizeof(*uapsd_cfg) == uapsd_cfg_size);
860 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
862 MTLK_CFG_CHECK_ITEM_AND_CALL(uapsd_cfg, uapsd_max_sp, mtlk_core_set_uapsd_max_sp,
863 (core, uapsd_cfg->uapsd_max_sp), res);
865 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
867 return mtlk_clpb_push(clpb, &res, sizeof(res));
872 mtlk_handle_bar (mtlk_handle_t context, uint8 *ta, uint8 tid, uint16 ssn)
874 struct nic *nic = (struct nic *)context;
875 int res;
876 sta_entry *sta = NULL;
878 nic->pstats.bars_cnt++;
880 if (tid >= NTS_TIDS) {
881 ELOG_DD("CID-%04x: Received BAR with wrong TID (%u)", mtlk_vap_get_oid(nic->vap_handle), tid);
882 return -1;
885 sta = mtlk_stadb_find_sta(&nic->slow_ctx->stadb, ta);
886 if (sta == NULL) {
887 ELOG_DY("CID-%04x: Received BAR from unknown peer %Y", mtlk_vap_get_oid(nic->vap_handle), ta);
888 return -1;
891 ILOG2_YD("Received BAR from %Y TID %u", ta, tid);
893 res = mtlk_sta_process_bar(sta, tid, ssn);
895 mtlk_sta_decref(sta); /* De-reference of find */
897 if(res != 0) {
898 ELOG_DYD("CID-%04x: Failed to process BAR (STA %Y TID %u)", mtlk_vap_get_oid(nic->vap_handle), ta, tid);
901 return res;
904 #ifdef MTCFG_RF_MANAGEMENT_MTLK
905 mtlk_rf_mgmt_t* __MTLK_IFUNC
906 mtlk_get_rf_mgmt (mtlk_handle_t context)
908 struct nic *nic = (struct nic *)context;
910 return nic->rf_mgmt;
912 #endif
914 static void
915 _mtlk_update_prev_sub_nbuf(mtlk_nbuf_t * nbuf, mtlk_nbuf_t **sub_nbuf_stored, mtlk_nbuf_t **sub_nbuf_fisrt)
917 mtlk_nbuf_t *sub_nbuf = *sub_nbuf_stored;
919 if(sub_nbuf)
920 mtlk_nbuf_priv_set_sub_frame(mtlk_nbuf_priv(sub_nbuf), nbuf);
921 else
922 *sub_nbuf_fisrt = nbuf;
924 *sub_nbuf_stored = nbuf;
927 static int
928 mtlk_parse_a_msdu(mtlk_core_t* nic, mtlk_nbuf_t *nbuf, int a_msdu_len, mtlk_nbuf_t **sub_nbuf_fisrt)
930 int msdu_len, subpacket_len, pad;
931 struct ethhdr *ether_header;
932 mtlk_nbuf_t *sub_nbuf;
933 mtlk_nbuf_t *sub_nbuf_stored = NULL;
934 int res = MTLK_ERR_NOT_IN_USE;
935 const int AMSDU_MAX_MSDU_SIZE = 2304; /* See IEEE Std 802.11-2012, p. 417 */
937 *sub_nbuf_fisrt = nbuf;
939 ILOG5_D("Parsing A-MSDU: length %d", a_msdu_len);
941 while (a_msdu_len) {
943 if(a_msdu_len < sizeof(struct ethhdr))
945 WLOG_D("Invalid A-MSDU: subpacket header too short: %d", a_msdu_len);
946 goto on_error;
949 ether_header = (struct ethhdr *)nbuf->data;
950 msdu_len = ntohs(ether_header->h_proto);
952 if(msdu_len > AMSDU_MAX_MSDU_SIZE)
954 WLOG_DD("Invalid A-MSDU: MSDU length > %d, a_msdu_len = %d",
955 AMSDU_MAX_MSDU_SIZE, a_msdu_len);
956 goto on_error;
959 subpacket_len = msdu_len + sizeof(struct ethhdr);
961 ILOG5_D("A-MSDU subpacket: length = %d", subpacket_len);
963 a_msdu_len -= subpacket_len;
964 if (a_msdu_len < 0) {
965 WLOG_DD("Invalid A-MSDU: subpacket too long (%d > %d)",
966 subpacket_len, a_msdu_len + subpacket_len);
967 goto on_error;
968 } else if (a_msdu_len == 0) {
969 /* The last MSDU in A-MSDU. Use original nbuf. */
970 sub_nbuf = nbuf;
971 pad = 0;
972 } else {
973 /* Not the last MSDU in A-MSDU. Clone original nbuf. */
974 sub_nbuf = mtlk_df_nbuf_clone_no_priv(mtlk_vap_get_manager(nic->vap_handle), nbuf);
975 /* skip padding */
976 pad = (4 - (subpacket_len & 0x03)) & 0x03;
977 a_msdu_len -= pad;
978 if (sub_nbuf) {
979 mtlk_nbuf_priv_set_src_sta(mtlk_nbuf_priv(sub_nbuf),
980 mtlk_nbuf_priv_get_src_sta(mtlk_nbuf_priv(nbuf)));
982 else {
983 WLOG_D("Cannot clone A-MSDU (len=%d)", a_msdu_len);
984 goto on_error;
986 mtlk_df_nbuf_pull(nbuf, subpacket_len + pad);
989 /* cut everything after data */
990 mtlk_df_nbuf_trim(sub_nbuf, subpacket_len);
991 /* for A-MSDU case we need to skip LLC/SNAP header */
992 memmove(sub_nbuf->data + sizeof(mtlk_snap_hdr_t) + sizeof(mtlk_llc_hdr_t),
993 ether_header, ETH_ALEN * 2);
994 mtlk_df_nbuf_pull(sub_nbuf, sizeof(mtlk_snap_hdr_t) + sizeof(mtlk_llc_hdr_t));
995 analyze_rx_packet(nic, sub_nbuf);
996 mtlk_mc_parse(nic, sub_nbuf);
997 /* Link this nbuf (clone or original) to previous clone (if any) */
998 _mtlk_update_prev_sub_nbuf(sub_nbuf, &sub_nbuf_stored, sub_nbuf_fisrt);
1001 return MTLK_ERR_OK;
1003 on_error:
1005 /* Have we made any clone so far? */
1006 if(*sub_nbuf_fisrt != nbuf)
1008 /* Link first cloned nbuf to original nbuf
1009 because they will be freed in this order */
1010 mtlk_nbuf_priv_set_sub_frame(mtlk_nbuf_priv(nbuf), *sub_nbuf_fisrt);
1013 return res;
1017 * Definitions and macros below are used only for the packet's header transformation
1018 * For more information, please see following documents:
1019 * - IEEE 802.1H standard
1020 * - IETF RFC 1042
1021 * - IEEE 802.11n standard draft 5 Annex M
1022 * */
1024 #define _8021H_LLC_HI4BYTES 0xAAAA0300
1025 #define _8021H_LLC_LO2BYTES_CONVERT 0x0000
1026 #define RFC1042_LLC_LO2BYTES_TUNNEL 0x00F8
1028 /* Default ISO/IEC conversion
1029 * we need to keep full LLC header and store packet length in the T/L subfield */
1030 #define _8021H_CONVERT(ether_header, nbuf, data_offset) \
1031 data_offset -= sizeof(struct ethhdr); \
1032 ether_header = (struct ethhdr *)(nbuf->data + data_offset); \
1033 ether_header->h_proto = htons(nbuf->len - data_offset - sizeof(struct ethhdr))
1035 /* 802.1H encapsulation
1036 * we need to remove LLC header except the 'type' field */
1037 #define _8021H_DECAPSULATE(ether_header, nbuf, data_offset) \
1038 data_offset -= sizeof(struct ethhdr) - (sizeof(mtlk_snap_hdr_t) + sizeof(mtlk_llc_hdr_t)); \
1039 ether_header = (struct ethhdr *)(nbuf->data + data_offset)
1041 static int
1042 handle_rx_ind (mtlk_core_t *nic, mtlk_nbuf_t *nbuf, uint16 msdulen,
1043 const MAC_RX_ADDITIONAL_INFO_T *mac_rx_info)
1045 int res = MTLK_ERR_OK; /* Do not free nbuf */
1046 int off;
1047 mtlk_nbuf_priv_t *nbuf_priv;
1048 unsigned char fromDS, toDS;
1049 uint16 seq = 0, frame_ctl;
1050 uint16 frame_subtype;
1051 uint16 priority = 0, qos = 0;
1052 unsigned int a_msdu = 0;
1053 unsigned char *cp, *addr1, *addr2;
1054 sta_entry *sta = NULL;
1055 uint8 key_idx;
1056 int bridge_mode;
1058 ILOG4_V("Rx indication");
1059 bridge_mode = MTLK_CORE_HOT_PATH_PDB_GET_INT(nic, CORE_DB_CORE_BRIDGE_MODE);;
1061 // Set the size of the nbuff data
1063 if (msdulen > mtlk_df_nbuf_get_tail_room_size(nbuf)) {
1064 ELOG_DDD("CID-%04x: msdulen > nbuf size ->> %d > %d", mtlk_vap_get_oid(nic->vap_handle),
1065 msdulen,
1066 mtlk_df_nbuf_get_tail_room_size(nbuf));
1069 mtlk_df_nbuf_put(nbuf, msdulen);
1071 // Get pointer to private area
1072 nbuf_priv = mtlk_nbuf_priv(nbuf);
1074 /* store vap index in private data,
1075 * Each packet must be aligned with the corresponding VAP */
1076 mtlk_nbuf_priv_set_vap_handle(nbuf_priv, nic->vap_handle);
1081 802.11n data frame from AP:
1083 |----------------------------------------------------------------|
1084 Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 6? | 2? | 0..2312 | 4 |
1085 |------|-------|-----|-----|-----|-----|-----|-----|---------|---|
1086 Descr. | Ctl |Dur/ID |Addr1|Addr2|Addr3| Seq |Addr4| QoS | Frame |fcs|
1087 | | | | | | Ctl | | Ctl | data | |
1088 |----------------------------------------------------------------|
1089 Total: 28-2346 bytes
1091 Existance of Addr4 in frame is optional and depends on To_DS From_DS flags.
1092 Existance of QoS_Ctl is also optional and depends on Ctl flags.
1093 (802.11n-D1.0 describes also HT Control (0 or 4 bytes) field after QoS_Ctl
1094 but we don't support this for now.)
1096 Interpretation of Addr1/2/3/4 depends on To_DS From_DS flags:
1098 To DS From DS Addr1 Addr2 Addr3 Addr4
1099 ---------------------------------------------
1100 0 0 DA SA BSSID N/A
1101 0 1 DA BSSID SA N/A
1102 1 0 BSSID SA DA N/A
1103 1 1 RA TA DA SA
1106 frame data begins with 8 bytes of LLC/SNAP:
1108 |-----------------------------------|
1109 Bytes | 1 | 1 | 1 | 3 | 2 |
1110 |-----------------------------------|
1111 Descr. | LLC | SNAP |
1112 |-----------------------------------+
1113 | DSAP | SSAP | Ctrl | OUI | T |
1114 |-----------------------------------|
1115 | AA | AA | 03 | 000000 | |
1116 |-----------------------------------|
1118 From 802.11 data frame that we receive from MAC we are making
1119 Ethernet DIX (II) frame.
1121 Ethernet DIX (II) frame format:
1123 |------------------------------------------------------|
1124 Bytes | 6 | 6 | 2 | 46 - 1500 | 4 |
1125 |------------------------------------------------------|
1126 Descr. | DA | SA | T | Data | FCS|
1127 |------------------------------------------------------|
1129 So we overwrite 6 bytes of LLC/SNAP with SA.
1133 ILOG4_V("Munging IEEE 802.11 header to be Ethernet DIX (II), irreversible!");
1134 cp = (unsigned char *) nbuf->data;
1136 mtlk_dump(4, cp, 112, "dump of recvd .11n packet");
1138 // Chop the last four bytes (FCS)
1139 mtlk_df_nbuf_trim(nbuf, nbuf->len-4);
1141 frame_ctl = mtlk_wlan_pkt_get_frame_ctl(cp);
1142 addr1 = WLAN_GET_ADDR1(cp);
1143 addr2 = WLAN_GET_ADDR2(cp);
1145 ILOG4_D("frame control - %04x", frame_ctl);
1147 /* Try to find source MAC of transmitter */
1148 sta = mtlk_stadb_find_sta(&nic->slow_ctx->stadb, addr2);
1149 mtlk_nbuf_priv_set_src_sta(nbuf_priv, sta);
1150 mtlk_nbuf_priv_set_rcn_bits(nbuf_priv, mac_rx_info->u8RSN);
1153 Excerpts from "IEEE P802.11e/D13.0, January 2005" p.p. 22-23
1154 Type Subtype Description
1155 -------------------------------------------------------------
1156 00 Management 0000 Association request
1157 00 Management 0001 Association response
1158 00 Management 0010 Reassociation request
1159 00 Management 0011 Reassociation response
1160 00 Management 0100 Probe request
1161 00 Management 0101 Probe response
1162 00 Management 0110-0111 Reserved
1163 00 Management 1000 Beacon
1164 00 Management 1001 Announcement traffic indication message (ATIM)
1165 00 Management 1010 Disassociation
1166 00 Management 1011 Authentication
1167 00 Management 1100 Deauthentication
1168 00 Management 1101 Action
1169 00 Management 1101-1111 Reserved
1170 01 Control 0000-0111 Reserved
1171 01 Control 1000 Block Acknowledgement Request (BlockAckReq)
1172 01 Control 1001 Block Acknowledgement (BlockAck)
1173 01 Control 1010 Power Save Poll (PS-Poll)
1174 01 Control 1011 Request To Send (RTS)
1175 01 Control 1100 Clear To Send (CTS)
1176 01 Control 1101 Acknowledgement (ACK)
1177 01 Control 1110 Contention-Free (CF)-End
1178 01 Control 1111 CF-End + CF-Ack
1179 10 Data 0000 Data
1180 10 Data 0001 Data + CF-Ack
1181 10 Data 0010 Data + CF-Poll
1182 10 Data 0011 Data + CF-Ack + CF-Poll
1183 10 Data 0100 Null function (no data)
1184 10 Data 0101 CF-Ack (no data)
1185 10 Data 0110 CF-Poll (no data)
1186 10 Data 0111 CF-Ack + CF-Poll (no data)
1187 10 Data 1000 QoS Data
1188 10 Data 1001 QoS Data + CF-Ack
1189 10 Data 1010 QoS Data + CF-Poll
1190 10 Data 1011 QoS Data + CF-Ack + CF-Poll
1191 10 Data 1100 QoS Null (no data)
1192 10 Data 1101 Reserved
1193 10 Data 1110 QoS CF-Poll (no data)
1194 10 Data 1111 QoS CF-Ack + CF-Poll (no data)
1195 11 Reserved 0000-1111 Reserved
1198 // FIXME: ADD DEFINITIONS!!!!
1199 // XXX, klogg: see frame.h
1201 switch(WLAN_FC_GET_TYPE(frame_ctl))
1203 case IEEE80211_FTYPE_DATA:
1204 CPU_STAT_SPECIFY_TRACK(CPU_STAT_ID_RX_DAT);
1205 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_DAT_FRAMES_RECEIVED);
1206 // Normal data
1207 break;
1208 case IEEE80211_FTYPE_MGMT:
1209 res = mtlk_process_man_frame(HANDLE_T(nic), sta, &nic->slow_ctx->scan, &nic->slow_ctx->cache,
1210 nic->slow_ctx->aocs, nbuf, mac_rx_info);
1211 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_MAN_FRAMES_RECEIVED);
1213 if(res != MTLK_ERR_OK)
1215 goto end;
1218 frame_subtype = (frame_ctl & FRAME_SUBTYPE_MASK) >> FRAME_SUBTYPE_SHIFT;
1219 ILOG4_D("Subtype is %d", frame_subtype);
1221 if ((frame_subtype == MAN_TYPE_BEACON && !mtlk_vap_is_ap(nic->vap_handle)) ||
1222 frame_subtype == MAN_TYPE_PROBE_RES ||
1223 frame_subtype == MAN_TYPE_PROBE_REQ) {
1225 // Workaraund for WPS (wsc-1.7.0) - send channel instead of the Dur/ID field */
1226 *(uint16 *)(nbuf->data + 2) = mac_rx_info->u8Channel;
1228 mtlk_nl_send_brd_msg(nbuf->data, nbuf->len, GFP_ATOMIC,
1229 NETLINK_SIMPLE_CONFIG_GROUP, NL_DRV_CMD_MAN_FRAME);
1232 res = MTLK_ERR_NOT_IN_USE;
1233 goto end;
1234 case IEEE80211_FTYPE_CTL:
1235 CPU_STAT_SPECIFY_TRACK(CPU_STAT_ID_RX_CTL);
1236 mtlk_process_ctl_frame(HANDLE_T(nic), nbuf->data, nbuf->len);
1237 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_CTL_FRAMES_RECEIVED);
1238 res = MTLK_ERR_NOT_IN_USE; /* Free nbuf */
1239 goto end;
1240 default:
1241 ILOG2_D("Unknown header type, frame_ctl %04x", frame_ctl);
1242 res = MTLK_ERR_NOT_IN_USE; /* Free nbuf */
1243 goto end;
1246 ILOG4_Y("802.11n rx TA: %Y", addr2);
1247 ILOG4_Y("802.11n rx RA: %Y", addr1);
1249 if (sta == NULL) {
1250 ILOG2_V("SOURCE of RX packet not found!");
1251 res = MTLK_ERR_NOT_IN_USE; /* Free nbuf */
1252 goto end;
1254 mtlk_sta_update_rx_rate(sta, mac_rx_info);
1256 /* Peers are updated on any data packet including NULL */
1257 mtlk_sta_on_frame_arrived(sta, mac_rx_info->aRssi);
1259 seq = mtlk_wlan_pkt_get_seq(cp);
1260 ILOG3_D("seq %d", seq);
1262 if (WLAN_FC_IS_NULL_PKT(frame_ctl)) {
1263 ILOG3_D("Null data packet, frame ctl - 0x%04x", frame_ctl);
1264 res = MTLK_ERR_NOT_IN_USE; /* Free nbuf */
1265 goto end;
1268 off = mtlk_wlan_get_hdrlen(frame_ctl);
1269 ILOG3_D("80211_hdrlen - %d", off);
1270 if (WLAN_FC_IS_QOS_PKT(frame_ctl)) {
1271 u16 qos_ctl = mtlk_wlan_pkt_get_qos_ctl(cp, off);
1272 priority = WLAN_QOS_GET_PRIORITY(qos_ctl);
1273 a_msdu = WLAN_QOS_GET_MSDU(qos_ctl);
1276 qos = mtlk_qos_get_ac_by_tid(priority);
1277 #ifdef MTLK_DEBUG_CHARIOT_OOO
1278 nbuf_priv->seq_qos = qos;
1279 #endif
1281 #ifndef MBSS_FORCE_NO_CHANNEL_SWITCH
1282 if (mtlk_vap_is_ap(nic->vap_handle)) {
1283 mtlk_aocs_on_rx_msdu(mtlk_core_get_master(nic)->slow_ctx->aocs, qos);
1285 #endif
1287 fromDS = WLAN_FC_GET_FROMDS(frame_ctl);
1288 toDS = WLAN_FC_GET_TODS(frame_ctl);
1289 ILOG3_DD("FromDS %d, ToDS %d", fromDS, toDS);
1291 /* Check if packet was directed to us */
1292 if (0 == MTLK_CORE_HOT_PATH_PDB_CMP_MAC(nic, CORE_DB_CORE_MAC_ADDR, addr1)) {
1293 mtlk_nbuf_priv_set_flags(nbuf_priv, MTLK_NBUFF_DIRECTED);
1296 nic->pstats.ac_rx_counter[qos]++;
1297 nic->pstats.sta_session_rx_packets++;
1299 /* data offset should account also security info if it is there */
1300 off += _get_rsc_buf(nic, nbuf, off);
1301 /* See CCMP/TKIP frame header in standard - 8.3.2.2/8.3.3.2 clause */
1302 key_idx = (mtlk_nbuf_priv_get_rsc_buf_byte(nbuf_priv, 3) & 0300) >> 6;
1304 /* process regular MSDU */
1305 if (likely(!a_msdu)) {
1306 struct ethhdr *ether_header;
1307 /* Raw LLC header split into 3 parts to make processing more convenient */
1308 struct llc_hdr_raw_t {
1309 uint32 hi4bytes;
1310 uint16 lo2bytes;
1311 uint16 ether_type;
1312 } *llc_hdr_raw = (struct llc_hdr_raw_t *)(nbuf->data + off);
1314 if (llc_hdr_raw->hi4bytes == __constant_htonl(_8021H_LLC_HI4BYTES)) {
1315 switch (llc_hdr_raw->lo2bytes) {
1316 case __constant_htons(_8021H_LLC_LO2BYTES_CONVERT):
1317 switch (llc_hdr_raw->ether_type) {
1318 /* AppleTalk and IPX encapsulation - integration service STT (see table M.1) */
1319 case __constant_htons(ETH_P_AARP):
1320 case __constant_htons(ETH_P_IPX):
1321 _8021H_CONVERT(ether_header, nbuf, off);
1322 break;
1323 /* default encapsulation
1324 * TODO: make sure it will be the shortest path */
1325 default:
1326 _8021H_DECAPSULATE(ether_header, nbuf, off);
1327 break;
1329 break;
1330 case __constant_htons(RFC1042_LLC_LO2BYTES_TUNNEL):
1331 _8021H_DECAPSULATE(ether_header, nbuf, off);
1332 break;
1333 default:
1334 _8021H_CONVERT(ether_header, nbuf, off);
1335 break;
1337 } else {
1338 _8021H_CONVERT(ether_header, nbuf, off);
1340 mtlk_df_nbuf_pull(nbuf, off);
1341 ether_header = (struct ethhdr *)nbuf->data;
1343 /* save SRC/DST MAC addresses from 802.11 header to 802.3 header */
1344 mtlk_wlan_get_mac_addrs(cp, fromDS, toDS, ether_header->h_source, ether_header->h_dest);
1346 /* Check if packet received from WDS HOST
1347 * (HOST mac address is not equal to sender's MAC address) */
1348 if ((bridge_mode == BR_MODE_WDS) &&
1349 memcmp(ether_header->h_source, mtlk_sta_get_addr(sta)->au8Addr, ETH_ALEN)) {
1351 /* On AP we need to update HOST's entry in database of registered
1352 * HOSTs behind connected STAs */
1353 if (mtlk_vap_is_ap(nic->vap_handle)) {
1354 mtlk_hstdb_update_host(&nic->slow_ctx->hstdb, ether_header->h_source, sta);
1356 /* On STA we search if this HOST registered in STA's database of
1357 * connected HOSTs (that are behind this STA) */
1358 } else if (mtlk_hstdb_find_sta(&nic->slow_ctx->hstdb, ether_header->h_source) != NULL) {
1359 ILOG4_V("Packet from our own host received from AP");
1360 res = MTLK_ERR_NOT_IN_USE; /* Free nbuf */
1361 goto end;
1365 #ifdef MTLK_DEBUG_IPERF_PAYLOAD_RX
1366 debug_ooo_analyze_packet(TRUE, nbuf, seq);
1367 #endif
1369 analyze_rx_packet(nic, nbuf);
1370 mtlk_mc_parse(nic, nbuf);
1372 /* try to reorder packet */
1373 if (mtlk_nbuf_priv_check_flags(nbuf_priv, MTLK_NBUFF_DIRECTED) &&
1374 (mtlk_vap_is_ap(nic->vap_handle) || WLAN_FC_IS_QOS_PKT(frame_ctl))) {
1375 if(!mtlk_sta_reorder_packet(sta, priority, seq, nbuf))
1377 /* We have received QoS packet while reordering is not open */
1378 if(MTLK_BFIELD_GET(mac_rx_info->u8HwInfo, HW_INFO_AGGR))
1380 /* This is aggregated packet. We should send DELBA. */
1381 mtlk_sta_on_qos_without_reord(sta, priority);
1384 } else {
1385 mtlk_detect_replay_or_sendup(nic, nbuf, nic->group_rsc[key_idx]);
1388 /* process A-MSDU */
1389 } else {
1390 mtlk_nbuf_t *nbuf_first;
1392 mtlk_df_nbuf_pull(nbuf, off);
1393 /* parse A-MSDU return first packet to send to OS */
1394 res = mtlk_parse_a_msdu(nic, nbuf, nbuf->len, &nbuf_first);
1395 if (MTLK_ERR_OK != res) {
1396 goto end;
1399 /* try to reorder packet */
1400 if (mtlk_nbuf_priv_check_flags(mtlk_nbuf_priv(nbuf_first), MTLK_NBUFF_DIRECTED) &&
1401 (mtlk_vap_is_ap(nic->vap_handle) || WLAN_FC_IS_QOS_PKT(frame_ctl))) {
1402 mtlk_sta_reorder_packet(sta, priority, seq, nbuf_first);
1403 } else {
1404 mtlk_detect_replay_or_sendup(nic, nbuf_first, nic->group_rsc[key_idx]);
1408 end:
1409 if (sta) {
1410 mtlk_sta_decref(sta); /* De-reference of find */
1412 return res;
1415 static int __MTLK_IFUNC
1416 _handle_bss_created(mtlk_handle_t core_object, const void *payload, uint32 size)
1418 struct nic *nic = HANDLE_T_PTR(struct nic, core_object);
1419 MTLK_ASSERT(size == sizeof(UMI_NETWORK_EVENT));
1421 ILOG1_Y("Network created, BSSID %Y", ((UMI_NETWORK_EVENT *)payload)->sBSSID.au8Addr);
1422 _mtlk_core_trigger_connect_complete_event(nic, TRUE);
1424 return MTLK_ERR_OK;
1427 static int __MTLK_IFUNC
1428 _handle_bss_connecting(mtlk_handle_t core_object, const void *payload, uint32 size)
1430 MTLK_UNREFERENCED_PARAM(core_object);
1431 MTLK_UNREFERENCED_PARAM(payload);
1432 MTLK_UNREFERENCED_PARAM(size);
1433 ILOG1_V("Connecting to network...");
1435 return MTLK_ERR_OK;
1438 static int __MTLK_IFUNC
1439 _handle_bss_connected(mtlk_handle_t core_object, const void *payload, uint32 size)
1441 MTLK_UNREFERENCED_PARAM(core_object);
1442 MTLK_ASSERT(size == sizeof(UMI_NETWORK_EVENT));
1444 ILOG1_Y("Network created, BSSID %Y", ((UMI_NETWORK_EVENT *)payload)->sBSSID.au8Addr);
1446 return MTLK_ERR_OK;
1449 static int __MTLK_IFUNC
1450 _handle_bss_failed(mtlk_handle_t core_object, const void *payload, uint32 size)
1452 struct nic *nic = HANDLE_T_PTR(struct nic, core_object);
1453 const UMI_NETWORK_EVENT *network_event = (const UMI_NETWORK_EVENT *)payload;
1454 uint16 reason;
1455 MTLK_ASSERT(size == sizeof(UMI_NETWORK_EVENT));
1457 reason = network_event->u8Reason;
1458 WLOG_DD("CID-%04x: Failed to create/connect to network, reason %d",
1459 mtlk_vap_get_oid(nic->vap_handle), reason);
1461 // AP is dead? Force user to rescan to see this BSS again
1462 if (reason == UMI_BSS_JOIN_FAILED) {
1463 MTLK_ASSERT(!mtlk_vap_is_ap(nic->vap_handle));
1464 mtlk_cache_remove_bss_by_bssid(&nic->slow_ctx->cache,
1465 network_event->sBSSID.au8Addr);
1468 _mtlk_core_trigger_connect_complete_event(nic, FALSE);
1470 return MTLK_ERR_OK;
1473 static int __MTLK_IFUNC
1474 _mtlk_handle_unknown_network_ind(mtlk_handle_t core_object, const void *payload, uint32 size)
1476 MTLK_ASSERT(size == sizeof(uint16));
1478 ELOG_DD("CID-%04x: Unrecognised network event %d",
1479 mtlk_vap_get_oid(HANDLE_T_PTR(mtlk_core_t, core_object)->vap_handle), *(uint16 *)payload);
1480 return MTLK_ERR_OK;
1483 static void
1484 _handle_network_event (struct nic *nic, UMI_NETWORK_EVENT *psNetwork)
1486 uint16 id = MAC_TO_HOST16(psNetwork->u16BSSstatus);
1488 switch (id)
1490 case UMI_BSS_CREATED:
1491 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_bss_created,
1492 HANDLE_T(nic), psNetwork, sizeof(UMI_NETWORK_EVENT));
1493 break;
1495 case UMI_BSS_CONNECTING:
1496 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_bss_connecting,
1497 HANDLE_T(nic), psNetwork, sizeof(UMI_NETWORK_EVENT));
1498 break;
1500 case UMI_BSS_CONNECTED:
1501 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_bss_connected,
1502 HANDLE_T(nic), psNetwork, sizeof(UMI_NETWORK_EVENT));
1503 break;
1505 case UMI_BSS_FAILED:
1506 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_bss_failed,
1507 HANDLE_T(nic), psNetwork, sizeof(UMI_NETWORK_EVENT));
1508 break;
1510 case UMI_BSS_CHANNEL_SWITCH_DONE:
1511 _mtlk_process_hw_task(nic, SYNCHRONOUS, mtlk_dot11h_handle_channel_switch_done,
1512 HANDLE_T(mtlk_core_get_dfs(nic)), psNetwork, sizeof(UMI_NETWORK_EVENT));
1513 break;
1515 case UMI_BSS_CHANNEL_PRE_SWITCH_DONE:
1516 MTLK_ASSERT(!mtlk_vap_is_slave_ap(nic->vap_handle));
1517 _mtlk_process_hw_task(nic, SYNCHRONOUS, mtlk_dot11h_handle_channel_pre_switch_done,
1518 HANDLE_T(mtlk_core_get_dfs(nic)), psNetwork, sizeof(UMI_NETWORK_EVENT));
1519 break;
1521 case UMI_BSS_CHANNEL_SWITCH_NORMAL:
1522 case UMI_BSS_CHANNEL_SWITCH_SILENT:
1523 MTLK_ASSERT(!mtlk_vap_is_slave_ap(nic->vap_handle));
1524 _mtlk_process_hw_task(nic, SYNCHRONOUS, mtlk_dot11h_handle_channel_switch_ind,
1525 HANDLE_T(mtlk_core_get_dfs(nic)), psNetwork, sizeof(UMI_NETWORK_EVENT));
1526 break;
1528 case UMI_BSS_RADAR_NORM:
1529 case UMI_BSS_RADAR_HOP:
1530 MTLK_ASSERT(!mtlk_vap_is_slave_ap(nic->vap_handle));
1531 _mtlk_process_hw_task(nic, SYNCHRONOUS, mtlk_dot11h_handle_radar_ind,
1532 HANDLE_T(mtlk_core_get_dfs(nic)), psNetwork, sizeof(UMI_NETWORK_EVENT));
1533 break;
1535 default:
1536 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_unknown_network_ind,
1537 HANDLE_T(nic), &id, sizeof(uint16));
1538 break;
1542 static int
1543 _mtlk_core_set_wep_key_blocked (struct nic *nic,
1544 const IEEE_ADDR *addr,
1545 uint16 key_idx)
1547 int res = MTLK_ERR_UNKNOWN;
1548 mtlk_txmm_msg_t man_msg;
1549 mtlk_txmm_data_t *man_entry = NULL;
1550 UMI_SET_KEY *umi_key;
1552 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg,
1553 mtlk_vap_get_txmm(nic->vap_handle),
1554 &res);
1555 if (!man_entry) {
1556 ELOG_DD("CID-%04x: No man entry available (res = %d)", mtlk_vap_get_oid(nic->vap_handle), res);
1557 goto end;
1560 umi_key = (UMI_SET_KEY*)man_entry->payload;
1561 memset(umi_key, 0, sizeof(*umi_key));
1563 man_entry->id = UM_MAN_SET_KEY_REQ;
1564 man_entry->payload_size = sizeof(*umi_key);
1566 umi_key->u16CipherSuite = HOST_TO_MAC16(UMI_RSN_CIPHER_SUITE_WEP40);
1567 umi_key->sStationID = *addr;
1568 if (mtlk_osal_eth_is_broadcast(addr->au8Addr))
1569 umi_key->u16KeyType = cpu_to_le16(UMI_RSN_GROUP_KEY);
1570 else
1571 umi_key->u16KeyType = cpu_to_le16(UMI_RSN_PAIRWISE_KEY);
1572 umi_key->u16DefaultKeyIndex = HOST_TO_MAC16(key_idx);
1574 memcpy(umi_key->au8Tk1,
1575 nic->slow_ctx->wep_keys.sKey[key_idx].au8KeyData,
1576 nic->slow_ctx->wep_keys.sKey[key_idx].u8KeyLength);
1578 mtlk_dump(4, umi_key, sizeof(*umi_key), "dump of UMI_SET_KEY");
1580 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
1581 if (res != MTLK_ERR_OK) {
1582 ELOG_DD("CID-%04x: mtlk_mm_send failed: %d", mtlk_vap_get_oid(nic->vap_handle), res);
1583 goto end;
1586 umi_key->u16Status = MAC_TO_HOST16(umi_key->u16Status);
1588 if (umi_key->u16Status != UMI_OK) {
1589 ELOG_DYD("CID-%04x: %Y: status is %d", mtlk_vap_get_oid(nic->vap_handle), addr, umi_key->u16Status);
1590 res = MTLK_ERR_MAC;
1591 goto end;
1594 res = MTLK_ERR_OK;
1596 end:
1597 if (man_entry) {
1598 mtlk_txmm_msg_cleanup(&man_msg);
1601 return res;
1604 static void
1605 _mtlk_core_notify_ap_of_station_connection(struct nic *nic,
1606 const IEEE_ADDR *addr,
1607 const UMI_RSN_IE *rsn_ie,
1608 BOOL supports_20_40,
1609 BOOL received_scan_exemption,
1610 BOOL is_intolerant,
1611 BOOL is_legacy)
1614 const uint8 *rsnie = rsn_ie->au8RsnIe;
1615 uint8 rsnie_id = rsnie[0];
1618 * WARNING! When there is RSN IE, we send address
1619 * in IWEVREGISTERED event not in wrqu.addr.sa_data as usual,
1620 * but in extra along with RSN IE data.
1621 * Why? Because iwreq_data is union and there is no other way
1622 * to send address and RSN IE in one event.
1623 * IWEVREGISTERED event is handled in hostAPd only
1624 * so there might be not any collessions with such non-standart
1625 * implementation of it.
1627 mtlk_dump(4, rsnie, sizeof(rsn_ie->au8RsnIe), "dump of RSNIE:");
1629 mtlk_20_40_register_station(mtlk_core_get_coex_sm(nic),
1630 addr,
1631 supports_20_40,
1632 received_scan_exemption,
1633 is_intolerant,
1634 FALSE); /* Temporary fix. Legacy flag shouldn't be considered by coex. module.
1635 see WAVE400_SW-194 for more details.
1636 AV TODO: Remove legacy flag from Coex. if no problem will be detected on QA */
1638 if (rsnie_id) {
1639 mtlk_df_ui_notify_secure_node_connect(
1640 mtlk_vap_get_df(nic->vap_handle),
1641 addr->au8Addr, rsnie, rsnie[1] + 2);
1642 } else {
1643 mtlk_df_ui_notify_node_connect(mtlk_vap_get_df(nic->vap_handle), addr->au8Addr);
1647 static void
1648 _mtlk_core_notify_ap_of_station_disconnection (struct nic *nic,
1649 const IEEE_ADDR *addr)
1651 mtlk_20_40_unregister_station(mtlk_core_get_coex_sm(nic), addr);
1652 mtlk_df_ui_notify_node_disconect(mtlk_vap_get_df(nic->vap_handle), addr->au8Addr);
1655 static void
1656 _mtlk_core_connect_sta_blocked (struct nic *nic,
1657 const UMI_CONNECTION_EVENT *psConnect,
1658 BOOL reconnect)
1660 sta_entry *sta;
1661 const IEEE_ADDR *addr = &psConnect->sStationID;
1662 const IEEE_ADDR *prev_bssid = &psConnect->sPrevBSSID;
1663 const UMI_RSN_IE *rsn_ie = &psConnect->sRSNie;
1664 BOOL is_ht_capable = FALSE;
1665 BOOL intolerant = FALSE;
1666 BOOL is_tkip = FALSE;
1667 struct wpa_ie_data d;
1668 uint32 sta_id = (uint32) MAC_TO_HOST16(psConnect->u16Sid);
1670 MTLK_UNREFERENCED_PARAM(prev_bssid);
1672 MTLK_ASSERT(mtlk_vap_is_ap(nic->vap_handle) || !_mtlk_core_has_connections(nic));
1674 /* check TKIP */
1675 if (rsn_ie->au8RsnIe[0]) {
1676 if (wpa_parse_wpa_ie(rsn_ie->au8RsnIe, rsn_ie->au8RsnIe[1] + 2, &d) == MTLK_ERR_OK) {
1677 if (d.pairwise_cipher == UMI_RSN_CIPHER_SUITE_TKIP) {
1678 ILOG1_DY("CID-%04x: Station %Y connecting in TKIP", mtlk_vap_get_oid(nic->vap_handle), addr);
1679 mtlk_dump(2, rsn_ie->au8RsnIe, sizeof(rsn_ie->au8RsnIe), "Content of UMI_CONNECTED RSN IE");
1680 is_tkip = TRUE;
1683 else{
1684 ELOG_D("CID-%04x: Can not parse WPA/RSN IE", mtlk_vap_get_oid(nic->vap_handle));
1685 mtlk_dump(0, rsn_ie->au8RsnIe, sizeof(rsn_ie->au8RsnIe), "Content of UMI_CONNECTED RSN IE");
1689 if(psConnect->u8HTmode && (psConnect->u32SupportedRates & LM_PHY_11N_RATE_MSK) && (!is_tkip))
1691 is_ht_capable = TRUE;
1693 else
1695 is_ht_capable = FALSE;
1698 /* Remove MAC addr from switch MAC table before adding to stadb */
1699 mtlk_df_user_ppa_remove_mac_addr(mtlk_vap_get_df(nic->vap_handle), addr->au8Addr);
1701 sta = mtlk_stadb_add_sta(&nic->slow_ctx->stadb, addr->au8Addr,
1702 (mtlk_core_get_is_ht_cur(nic) && is_ht_capable), sta_id);
1704 if (sta == NULL)
1705 goto add_sta_fail;
1707 if (mtlk_vap_is_ap(nic->vap_handle))
1709 sta_capabilities sta_capabilities;
1711 if (!reconnect) {
1712 ILOG1_DYS("CID-%04x: Station %Y (%sN) has connected",
1713 mtlk_vap_get_oid(nic->vap_handle),
1714 addr,
1715 is_ht_capable ? "" : "non-");
1717 else {
1718 ILOG1_DYSY("CID-%04x: Station %Y (%sN) has reconnected. Previous BSS was %Y",
1719 mtlk_vap_get_oid(nic->vap_handle),
1720 addr, is_ht_capable ? "" : "non-",
1721 prev_bssid);
1724 if (psConnect->u8PeerAP) {
1725 /* Peer AP */
1726 sta->peer_ap = 1;
1728 if (nic->slow_ctx->peerAPs_key_idx) {
1729 mtlk_sta_set_cipher(sta, IW_ENCODE_ALG_WEP);
1730 _mtlk_core_set_wep_key_blocked(nic, addr, nic->slow_ctx->peerAPs_key_idx - 1);
1733 else {
1734 /* Regular STA */
1735 if (nic->slow_ctx->wep_enabled && !nic->slow_ctx->wps_in_progress) {
1736 mtlk_sta_set_cipher(sta, IW_ENCODE_ALG_WEP);
1737 _mtlk_core_set_wep_key_blocked(nic, addr, nic->slow_ctx->default_key);
1740 if ((psConnect->fortyMHzIntolerant == TRUE) || (psConnect->twentyMHzBssWidthRequest == TRUE)) {
1741 intolerant = TRUE;
1744 _mtlk_core_notify_ap_of_station_connection(nic, addr, rsn_ie, psConnect->twentyFortyBssCoexistenceManagementSupport, psConnect->obssScanningExemptionGrant, intolerant, !is_ht_capable);
1747 mtlk_frame_process_sta_capabilities(&sta_capabilities,
1748 psConnect->sPeersCapabilities.u8LantiqProprietry,
1749 MAC_TO_HOST16(psConnect->sPeersCapabilities.u16HTCapabilityInfo),
1750 psConnect->sPeersCapabilities.AMPDU_Parameters,
1751 MAC_TO_HOST32(psConnect->sPeersCapabilities.tx_bf_capabilities),
1752 psConnect->boWMEsupported,
1753 MAC_TO_HOST32(psConnect->u32SupportedRates),
1754 mtlk_core_get_freq_band_cur(nic));
1756 mtlk_sta_set_capabilities(sta, &sta_capabilities);
1758 if (nic->uapsd_enabled) {
1759 BOOL uapsd_enabled = FALSE;
1760 mtlk_sq_peer_ctx_t *ppeer = &sta->sq_peer_ctx;
1762 ppeer->uapsd_max_sp = MTLK_BFIELD_GET(psConnect->uapsdParams, IND_UAPSD_MAX_SP_LENGTH);
1763 if (0 == ppeer->uapsd_max_sp) {
1764 ppeer->uapsd_max_sp = UAPSD_MAX_SP_USER_MAX;
1766 ppeer->uapsd_max_sp = MIN(ppeer->uapsd_max_sp, nic->uapsd_max_sp) + UAPSD_MAX_SP_ADDITION;
1768 UAPSD_SET_AC_LIMIT_AND_UAPSD_ENABLED(VO, ppeer->uapsd_max_sp);
1769 UAPSD_SET_AC_LIMIT_AND_UAPSD_ENABLED(VI, ppeer->uapsd_max_sp);
1770 UAPSD_SET_AC_LIMIT_AND_UAPSD_ENABLED(BK, ppeer->uapsd_max_sp);
1771 UAPSD_SET_AC_LIMIT_AND_UAPSD_ENABLED(BE, ppeer->uapsd_max_sp);
1773 if(!uapsd_enabled)
1775 ppeer->uapsd_max_sp = 0;
1779 } // End of is AP
1780 else // STA
1782 mtlk_pdb_set_mac(mtlk_vap_get_param_db(nic->vap_handle), PARAM_DB_CORE_BSSID,
1783 addr->au8Addr);
1785 if (!reconnect) {
1786 ILOG1_YS("connected to %Y (%sN)",
1787 addr,
1788 is_ht_capable ? "" : "non-");
1789 nic->pstats.sta_session_rx_packets = 0;
1790 nic->pstats.sta_session_tx_packets = 0;
1792 else {
1793 ILOG1_YY("connected to %Y, previous BSSID was %Y",
1794 addr,
1795 prev_bssid);
1798 mtlk_df_ui_notify_association(mtlk_vap_get_df(nic->vap_handle), addr->au8Addr);
1799 if (mtlk_core_is_20_40_active(nic))
1801 mtlk_20_40_sta_notify_connection_to_ap(mtlk_core_get_coex_sm(nic), psConnect->fortyMHzMode, psConnect->twentyFortyBssCoexistenceManagementSupport, psConnect->obssScanningExemptionGrant);
1803 mtlk_scan_set_load_progmodel_policy(&nic->slow_ctx->scan, mtlk_core_is_20_40_active(nic) ? FALSE : TRUE);
1805 #ifdef PHASE_3
1806 mtlk_start_cache_update(nic);
1807 #endif
1809 // make BSS we've connected to persistent in cache until we're disconnected
1810 mtlk_cache_set_persistent(&nic->slow_ctx->cache,
1811 addr->au8Addr,
1812 TRUE);
1815 if (nic->slow_ctx->rsnie.au8RsnIe[0] && !sta->peer_ap) {
1816 /* Filter is already enabled by default */
1817 } else if (!mtlk_vap_is_ap(nic->vap_handle) && nic->slow_ctx->wps_in_progress) {
1818 mtlk_sta_set_packets_filter(sta, MTLK_PCKT_FLTR_ALLOW_802_1X);
1819 ILOG1_Y("%Y: turn on 802.1x filtering due to WPS", mtlk_sta_get_addr(sta));
1820 } else {
1821 mtlk_sta_set_packets_filter(sta, MTLK_PCKT_FLTR_ALLOW_ALL);
1822 ILOG1_Y("%Y: turn off 802.1x filtering", mtlk_sta_get_addr(sta));
1823 mtlk_sta_on_security_negotiated(sta);
1826 mtlk_qos_reset_acm_bits(&nic->qos);
1828 if ( BR_MODE_WDS == MTLK_CORE_HOT_PATH_PDB_GET_INT(nic, CORE_DB_CORE_BRIDGE_MODE)){
1829 mtlk_hstdb_start_all_by_sta(&nic->slow_ctx->hstdb, sta);
1832 mtlk_hstdb_remove_host_by_addr(&nic->slow_ctx->hstdb, addr);
1834 if (mtlk_vap_is_ap(nic->vap_handle) &&
1835 BR_MODE_WDS == MTLK_CORE_HOT_PATH_PDB_GET_INT(nic, CORE_DB_CORE_BRIDGE_MODE)){
1836 wds_peer_connect(&nic->slow_ctx->wds_mng, sta, addr);
1839 /* notify Traffic Analyzer about new STA */
1840 mtlk_ta_on_connect(mtlk_vap_get_ta(nic->vap_handle), sta);
1842 mtlk_sta_decref(sta); /* De-reference by creator */
1844 return;
1846 add_sta_fail:
1848 if (mtlk_vap_is_ap(nic->vap_handle) &&
1849 BR_MODE_WDS == MTLK_CORE_HOT_PATH_PDB_GET_INT(nic, CORE_DB_CORE_BRIDGE_MODE)){
1850 wds_peer_connect(&nic->slow_ctx->wds_mng, NULL, addr);
1853 return;
1856 static int
1857 _mtlk_core_disconnect_sta_blocked (struct nic *nic,
1858 const IEEE_ADDR *addr,
1859 uint16 reason,
1860 uint16 fail_reason,
1861 uint16 reason_code)
1864 uint32 net_state = mtlk_core_get_net_state(nic);
1866 MTLK_ASSERT(addr != NULL);
1868 /* Check is STA is a peer AP */
1869 if (mtlk_vap_is_ap(nic->vap_handle) &&
1870 BR_MODE_WDS == MTLK_CORE_HOT_PATH_PDB_GET_INT(nic, CORE_DB_CORE_BRIDGE_MODE)){
1871 int res, terminate;
1872 res = wds_peer_disconnect(&nic->slow_ctx->wds_mng, addr, &terminate);
1873 if (terminate) return res;
1876 if (net_state != NET_STATE_CONNECTED) {
1877 ILOG1_DYDDD("CID-%04x: Failed to connect to %Y for reason %d fail_reason %d reason_code %d",
1878 mtlk_vap_get_oid(nic->vap_handle),
1879 addr, reason, fail_reason, reason_code);
1881 /* This is wrong variable to check. Must be "reason", not "fail_reason".
1882 I will leave this place as-is to not break present logic */
1883 if (fail_reason == UMI_BSS_JOIN_FAILED) {
1884 /* AP is dead? Force user to rescan to see this BSS again */
1885 mtlk_cache_remove_bss_by_bssid(&nic->slow_ctx->cache, addr->au8Addr);
1888 _mtlk_core_trigger_connect_complete_event(nic, FALSE);
1890 else {
1891 if (mtlk_vap_is_ap(nic->vap_handle)) {
1892 ILOG1_DYDDD("CID-%04x: STA %Y disconnected for reason %d fail_reason %d reason_code %d",
1893 mtlk_vap_get_oid(nic->vap_handle),
1894 addr, reason, fail_reason, reason_code);
1895 } else {
1896 ILOG1_DYDDD("CID-%04x: Disconnected from BSS %Y for reason %d fail_reason %d reason_code %d",
1897 mtlk_vap_get_oid(nic->vap_handle),
1898 addr, reason, fail_reason, reason_code);
1900 if (!mtlk_vap_is_slave_ap(nic->vap_handle)) {
1901 /* We could have BG scan doing right now.
1902 It must be terminated because scan module
1903 is not ready for background scan to normal scan
1904 mode switch on the fly.
1906 scan_terminate(&nic->slow_ctx->scan);
1908 /* Since we disconnected switch scan mode to normal */
1909 mtlk_scan_set_background(&nic->slow_ctx->scan, FALSE);
1914 /* send disconnect request */
1915 return _mtlk_core_send_disconnect_req_blocked(nic, addr, reason, fail_reason, reason_code);
1919 static int __MTLK_IFUNC
1920 _mtlk_core_ap_disconnect_sta(mtlk_handle_t hcore, const void* data, uint32 data_size)
1922 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
1923 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
1924 int res = MTLK_ERR_PARAMS;
1925 mtlk_core_ui_mlme_cfg_t *mlme_cfg;
1926 uint32 size;
1928 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
1930 if (!mtlk_vap_is_ap(nic->vap_handle)) {
1931 res = MTLK_ERR_NOT_SUPPORTED;
1932 goto finish;
1935 mlme_cfg = mtlk_clpb_enum_get_next(clpb, &size);
1936 if ( (NULL == mlme_cfg) || (sizeof(*mlme_cfg) != size) ) {
1937 ELOG_D("CID-%04x: Failed to get MLME configuration parameters from CLPB", mtlk_vap_get_oid(nic->vap_handle));
1938 res = MTLK_ERR_UNKNOWN;
1939 goto finish;
1942 if (mtlk_core_get_net_state(nic) != NET_STATE_CONNECTED) {
1943 ILOG1_Y("STA (%Y), not connected - request rejected", mlme_cfg->sta_addr.au8Addr);
1944 res = MTLK_ERR_NOT_READY;
1945 goto finish;
1948 res = _mtlk_core_disconnect_sta_blocked(nic,
1949 (const IEEE_ADDR *)mlme_cfg->sta_addr.au8Addr,
1950 UMI_BSS_UNSPECIFIED,
1951 FM_STATUSCODE_USER_REQUEST,
1952 mlme_cfg->reason_code);
1953 finish:
1954 return res;
1957 static int __MTLK_IFUNC
1958 _mtlk_core_ap_disconnect_all (mtlk_handle_t hcore, const void* data, uint32 data_size)
1960 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
1961 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
1962 int res = MTLK_ERR_OK;
1963 const sta_entry *sta = NULL;
1964 mtlk_stadb_iterator_t iter;
1965 mtlk_core_ui_mlme_cfg_t *mlme_cfg;
1966 uint32 size;
1969 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
1970 MTLK_ASSERT(mtlk_vap_is_ap(nic->vap_handle));
1972 if (mtlk_core_get_net_state(nic) != NET_STATE_CONNECTED) {
1973 ILOG1_V("AP is down - request rejected");
1974 res = MTLK_ERR_NOT_READY;
1975 goto finish;
1978 mlme_cfg = mtlk_clpb_enum_get_next(clpb, &size);
1979 if ( (NULL == mlme_cfg) || (sizeof(*mlme_cfg) != size) ) {
1980 ELOG_D("CID-%04x: Failed to get MLME configuration parameters from CLPB", mtlk_vap_get_oid(nic->vap_handle));
1981 res = MTLK_ERR_UNKNOWN;
1982 goto finish;
1985 sta = mtlk_stadb_iterate_first(&nic->slow_ctx->stadb, &iter);
1986 if (sta) {
1987 do {
1988 if (!sta->peer_ap){
1989 res = _mtlk_core_disconnect_sta_blocked(nic,
1990 mtlk_sta_get_addr(sta),
1991 UMI_BSS_UNSPECIFIED,
1992 FM_STATUSCODE_USER_REQUEST,
1993 mlme_cfg->reason_code);
1994 if (res != MTLK_ERR_OK) {
1995 ELOG_YD("STA (%Y) disconnection failed (%d)", mtlk_sta_get_addr(sta), res);
1996 break;
1999 sta = mtlk_stadb_iterate_next(&iter);
2000 } while (sta);
2001 mtlk_stadb_iterate_done(&iter);
2004 finish:
2005 return res;
2008 static int _mtlk_core_on_association_event(mtlk_vap_handle_t vap_handle,
2009 IEEE_ADDR mac_addr,
2010 uint16 fail_reason)
2012 mtlk_association_event_t assoc_event;
2014 memset(&assoc_event, 0, sizeof(mtlk_association_event_t));
2015 mtlk_osal_copy_eth_addresses((uint8*)&assoc_event.mac_addr, mac_addr.au8Addr);
2016 assoc_event.status = fail_reason;
2018 return mtlk_wssd_send_event(mtlk_vap_get_irbd(vap_handle),
2019 MTLK_WSSA_DRV_EVENT_ASSOCIATION,
2020 &assoc_event,
2021 sizeof(mtlk_association_event_t));
2024 static int _mtlk_core_on_authentication_event(mtlk_vap_handle_t vap_handle,
2025 IEEE_ADDR mac_addr,
2026 uint16 reason,
2027 uint16 fail_reason)
2029 mtlk_authentication_event_t auth_event;
2031 memset(&auth_event, 0, sizeof(mtlk_authentication_event_t));
2033 mtlk_osal_copy_eth_addresses((uint8*)&auth_event.mac_addr, mac_addr.au8Addr);
2034 auth_event.auth_type = reason;
2035 auth_event.status = fail_reason;
2037 return mtlk_wssd_send_event(mtlk_vap_get_irbd(vap_handle),
2038 MTLK_WSSA_DRV_EVENT_AUTHENTICATION,
2039 &auth_event,
2040 sizeof(mtlk_authentication_event_t));
2043 static int _mtlk_core_on_peer_disconnect(mtlk_core_t *core,
2044 sta_entry *sta,
2045 uint16 reason,
2046 uint16 fail_reason)
2048 mtlk_disconnection_event_t disconnect_event;
2049 BOOL ap_mode;
2051 MTLK_ASSERT(core != NULL);
2052 MTLK_ASSERT(sta != NULL);
2054 ap_mode = mtlk_vap_is_ap(core->vap_handle);
2056 memset(&disconnect_event, 0, sizeof(disconnect_event));
2057 memcpy(&disconnect_event.mac_addr, mtlk_sta_get_addr(sta), sizeof(disconnect_event.mac_addr));
2059 disconnect_event.reason = fail_reason;
2060 disconnect_event.initiator = ap_mode ? MTLK_DI_AP : MTLK_DI_STA;
2062 switch (fail_reason)
2064 case FM_STATUSCODE_AGED_OUT:
2065 case FM_STATUSCODE_INACTIVITY:
2066 case FM_STATUSCODE_USER_REQUEST:
2067 case FM_STATUSCODE_PEER_PARAMS_CHANGED:
2068 /* Disconnect initiated by this side */
2069 break;
2071 case FM_STATUSCODE_MAC_ADDRESS_FILTER:
2072 if (UMI_BSS_DEAUTHENTICATED == reason)
2074 break;
2076 /* Drop down to default */
2078 default:
2079 /* Disconnect initiated by other side */
2080 disconnect_event.initiator = ap_mode ? MTLK_DI_STA : MTLK_DI_AP;
2083 mtlk_sta_get_peer_stats(sta, &disconnect_event.peer_stats);
2084 mtlk_sta_get_peer_capabilities(sta, &disconnect_event.peer_capabilities);
2086 return mtlk_wssd_send_event(mtlk_vap_get_irbd(core->vap_handle),
2087 MTLK_WSSA_DRV_EVENT_DISCONNECTION,
2088 &disconnect_event,
2089 sizeof(disconnect_event));
2092 static int __MTLK_IFUNC
2093 _handle_sta_connection_event (mtlk_handle_t core_object, const void *payload, uint32 size)
2095 struct nic *nic = HANDLE_T_PTR(struct nic, core_object);
2096 const UMI_CONNECTION_EVENT *psConnect =
2097 (const UMI_CONNECTION_EVENT *)payload;
2098 uint16 reason = MAC_TO_HOST16(psConnect->u16Reason);
2099 uint16 fail_reason = MAC_TO_HOST16(psConnect->u16FailReason);
2100 uint16 event = MAC_TO_HOST16(psConnect->u16Event);
2102 MTLK_ASSERT(size == sizeof(*psConnect));
2104 mtlk_dump(5, psConnect, sizeof(UMI_CONNECTION_EVENT), "UMI_CONNECTION_EVENT:");
2106 if (nic->is_stopped) {
2107 ILOG5_V("Connection event while core is down");
2108 return MTLK_ERR_OK; // do not process
2111 switch (event) {
2112 case UMI_CONNECTED:
2113 ILOG2_DDY("CID-%04x: UMI_CONNECTED. Reason %d, %Y",
2114 mtlk_vap_get_oid(nic->vap_handle), reason, psConnect->sStationID.au8Addr);
2116 _mtlk_core_connect_sta_blocked(nic, psConnect, FALSE);
2117 if (FM_STATUSCODE_ASSOCIATED == reason) {
2118 _mtlk_core_on_association_event(nic->vap_handle, psConnect->sStationID,
2119 FM_STATUSCODE_SUCCESSFUL);
2121 break;
2122 case UMI_RECONNECTED:
2123 ILOG2_DDY("CID-%04x: UMI_RECONNECTED. Reason %d, %Y",
2124 mtlk_vap_get_oid(nic->vap_handle), reason, psConnect->sStationID.au8Addr);
2126 _mtlk_core_connect_sta_blocked(nic, psConnect, TRUE);
2127 break;
2128 case UMI_DISCONNECTED:
2129 ILOG2_DDDY("CID-%04x: UMI_DISCONNECTED. Reason %d, FailReason %d, %Y",
2130 mtlk_vap_get_oid(nic->vap_handle), reason, fail_reason, psConnect->sStationID.au8Addr);
2132 if((fail_reason == FM_STATUSCODE_RESERVED) && (reason == UMI_BSS_DISASSOCIATED))
2134 /* Do not send UMI_DISCONNECT back to FW */
2136 else if((fail_reason == FM_STATUSCODE_MAC_ADDRESS_FILTER) && (reason == UMI_BSS_AUTH_FAILED))
2138 /* Blacklisted station tried to connect */
2140 else
2142 _mtlk_core_disconnect_sta_blocked(nic, &psConnect->sStationID,
2143 reason, fail_reason, FRAME_REASON_UNSPECIFIED);
2146 if ((UMI_BSS_ASSOC_FAILED == reason) ||
2147 ((fail_reason == FM_STATUSCODE_MAC_ADDRESS_FILTER) && (reason == UMI_BSS_AUTH_FAILED))) {
2148 _mtlk_core_on_association_event(nic->vap_handle, psConnect->sStationID, fail_reason);
2150 break;
2151 case UMI_AUTHENTICATION:
2152 _mtlk_core_on_authentication_event(nic->vap_handle, psConnect->sStationID,
2153 reason,
2154 fail_reason);
2155 break;
2156 case UMI_ASSOCIATION:
2157 MTLK_ASSERT(UMI_BSS_ASSOC_FAILED == reason);
2158 _mtlk_core_on_association_event(nic->vap_handle,
2159 psConnect->sStationID,
2160 fail_reason);
2161 break;
2162 default:
2163 ELOG_DD("CID-%04x: Unrecognized connection event %d", mtlk_vap_get_oid(nic->vap_handle), event);
2164 break;
2167 return MTLK_ERR_OK;
2170 static int __MTLK_IFUNC
2171 _handle_fw_connection_event_indication(mtlk_handle_t core_object, const void *payload, uint32 size)
2173 struct nic *nic = HANDLE_T_PTR(struct nic, core_object);
2175 if(!mtlk_vap_is_ap(nic->vap_handle)) {
2176 _mtlk_core_trigger_connect_complete_event(nic, TRUE);
2178 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_sta_connection_event,
2179 core_object, payload, size);
2181 return MTLK_ERR_OK;
2184 static int __MTLK_IFUNC
2185 _handle_vap_removed_ind (mtlk_handle_t core_object, const void *payload, uint32 size)
2187 struct nic *nic = HANDLE_T_PTR(struct nic, core_object);
2189 MTLK_UNREFERENCED_PARAM(payload);
2190 ILOG1_V("VAP removal indication received");
2191 mtlk_osal_event_set(&nic->slow_ctx->vap_removed_event);
2193 return MTLK_ERR_OK;
2196 static int __MTLK_IFUNC
2197 handleDisconnectSta (mtlk_handle_t core_object, const void *payload, uint32 size)
2199 struct nic *nic = HANDLE_T_PTR(struct nic, core_object);
2200 int res;
2201 struct mtlk_core_disconnect_sta_data *data =
2202 (struct mtlk_core_disconnect_sta_data *)payload;
2204 MTLK_ASSERT(size == sizeof(*data));
2206 res = _mtlk_core_disconnect_sta_blocked(nic, &data->addr, UMI_BSS_UNSPECIFIED, data->fail_reason, data->reason_code);
2208 if (data->res) {
2209 *data->res = res;
2211 if (data->done_evt) {
2212 mtlk_osal_event_set(data->done_evt);
2215 return MTLK_ERR_OK;
2218 static int
2219 _handle_dynamic_param_ind(mtlk_handle_t object, const void *data, uint32 data_size)
2221 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
2222 UMI_DYNAMIC_PARAM_TABLE *param_table = (UMI_DYNAMIC_PARAM_TABLE *) data;
2223 int i;
2225 MTLK_ASSERT(sizeof(UMI_DYNAMIC_PARAM_TABLE) == data_size);
2227 for (i = 0; i < NTS_PRIORITIES; i++)
2228 ILOG5_DD("Set ACM bit for priority %d: %d", i, param_table->ACM_StateTable[i]);
2230 mtlk_qos_set_acm_bits(&nic->qos, param_table->ACM_StateTable);
2231 return MTLK_ERR_OK;
2234 static int
2235 _handle_security_alert_ind(mtlk_handle_t object, const void *data, uint32 data_size)
2237 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
2238 UMI_SECURITY_ALERT *usa = (UMI_SECURITY_ALERT*)data;
2239 MTLK_ASSERT(sizeof(UMI_SECURITY_ALERT) == data_size);
2241 switch (usa->u16EventCode) {
2242 case UMI_RSN_EVENT_TKIP_MIC_FAILURE:
2244 mtlk_df_ui_mic_fail_type_t mic_fail_type =
2245 (UMI_RSN_PAIRWISE_KEY == usa->u16KeyType) ? MIC_FAIL_PAIRWISE : MIC_FAIL_GROUP;
2247 mtlk_df_ui_notify_mic_failure(
2248 mtlk_vap_get_df(nic->vap_handle), usa->sStationID.au8Addr, mic_fail_type);
2250 _mtlk_core_on_mic_failure(nic, mic_fail_type);
2252 break;
2254 return MTLK_ERR_OK;
2257 /* steps for init and cleanup */
2258 MTLK_INIT_STEPS_LIST_BEGIN(core_slow_ctx)
2259 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, DFS)
2260 #ifdef EEPROM_DATA_VALIDATION
2261 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, EEPROM)
2262 #endif /* EEPROM_DATA_VALIDATION */
2263 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, SERIALIZER)
2264 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, SET_NIC_CFG)
2265 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, WATCHDOG_TIMER_INIT)
2266 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, CONNECT_EVENT_INIT)
2267 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, VAP_REMOVED_EVENT_INIT)
2268 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, STADB_INIT)
2269 MTLK_INIT_STEPS_LIST_ENTRY(core_slow_ctx, HSTDB_INIT)
2270 MTLK_INIT_INNER_STEPS_BEGIN(core_slow_ctx)
2271 MTLK_INIT_STEPS_LIST_END(core_slow_ctx);
2273 static void __MTLK_IFUNC
2274 _mtlk_slow_ctx_cleanup(struct nic_slow_ctx *slow_ctx, struct nic* nic)
2276 MTLK_ASSERT(NULL != slow_ctx);
2277 MTLK_ASSERT(NULL != nic);
2279 MTLK_CLEANUP_BEGIN(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
2281 MTLK_CLEANUP_STEP(core_slow_ctx, HSTDB_INIT, MTLK_OBJ_PTR(slow_ctx),
2282 mtlk_hstdb_cleanup, (&slow_ctx->hstdb));
2284 MTLK_CLEANUP_STEP(core_slow_ctx, STADB_INIT, MTLK_OBJ_PTR(slow_ctx),
2285 mtlk_stadb_cleanup, (&slow_ctx->stadb));
2287 MTLK_CLEANUP_STEP(core_slow_ctx, VAP_REMOVED_EVENT_INIT, MTLK_OBJ_PTR(slow_ctx),
2288 mtlk_osal_event_cleanup, (&slow_ctx->vap_removed_event));
2290 MTLK_CLEANUP_STEP(core_slow_ctx, CONNECT_EVENT_INIT, MTLK_OBJ_PTR(slow_ctx),
2291 mtlk_osal_event_cleanup, (&slow_ctx->connect_event));
2293 MTLK_CLEANUP_STEP(core_slow_ctx, WATCHDOG_TIMER_INIT, MTLK_OBJ_PTR(slow_ctx),
2294 mtlk_osal_timer_cleanup, (&slow_ctx->mac_watchdog_timer));
2296 MTLK_CLEANUP_STEP(core_slow_ctx, SET_NIC_CFG, MTLK_OBJ_PTR(slow_ctx),
2297 MTLK_NOACTION, ());
2299 MTLK_CLEANUP_STEP(core_slow_ctx, SERIALIZER, MTLK_OBJ_PTR(slow_ctx),
2300 mtlk_serializer_cleanup, (&slow_ctx->serializer));
2302 #ifdef EEPROM_DATA_VALIDATION
2303 MTLK_CLEANUP_STEP(core_slow_ctx, EEPROM, MTLK_OBJ_PTR(slow_ctx),
2304 mtlk_eeprom_fw_access_cleanup, (nic->vap_handle));
2305 #endif /* EEPROM_DATA_VALIDATION */
2307 MTLK_CLEANUP_STEP(core_slow_ctx, DFS, MTLK_OBJ_PTR(slow_ctx),
2308 mtlk_dfs_delete, (slow_ctx->dot11h) )
2310 MTLK_CLEANUP_END(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx));
2313 static int __MTLK_IFUNC
2314 _mtlk_slow_ctx_init(struct nic_slow_ctx *slow_ctx, struct nic* nic)
2316 MTLK_ASSERT(NULL != slow_ctx);
2317 MTLK_ASSERT(NULL != nic);
2319 memset(slow_ctx, 0, sizeof(struct nic_slow_ctx));
2320 slow_ctx->nic = nic;
2322 MTLK_INIT_TRY(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
2324 MTLK_INIT_STEP_EX_IF(!mtlk_vap_is_slave_ap(nic->vap_handle), core_slow_ctx, DFS, MTLK_OBJ_PTR(slow_ctx),
2325 mtlk_dfs_create, (),
2326 slow_ctx->dot11h, NULL != slow_ctx->dot11h, MTLK_ERR_NO_MEM);
2328 #ifdef EEPROM_DATA_VALIDATION
2329 MTLK_INIT_STEP_IF(!mtlk_vap_is_slave_ap(nic->vap_handle), core_slow_ctx, EEPROM, MTLK_OBJ_PTR(slow_ctx),
2330 mtlk_eeprom_fw_access_init, (nic->vap_handle));
2331 #endif /* EEPROM_DATA_VALIDATION */
2333 MTLK_INIT_STEP(core_slow_ctx, SERIALIZER, MTLK_OBJ_PTR(slow_ctx),
2334 mtlk_serializer_init, (&slow_ctx->serializer, _MTLK_CORE_NUM_PRIORITIES));
2336 MTLK_INIT_STEP_VOID(core_slow_ctx, SET_NIC_CFG, MTLK_OBJ_PTR(slow_ctx),
2337 mtlk_mib_set_nic_cfg, (nic));
2339 MTLK_INIT_STEP_IF(!mtlk_vap_is_slave_ap(nic->vap_handle), core_slow_ctx, WATCHDOG_TIMER_INIT, MTLK_OBJ_PTR(slow_ctx),
2340 mtlk_osal_timer_init, (&slow_ctx->mac_watchdog_timer,
2341 mac_watchdog_timer_handler,
2342 HANDLE_T(nic)));
2344 MTLK_INIT_STEP(core_slow_ctx, CONNECT_EVENT_INIT, MTLK_OBJ_PTR(slow_ctx),
2345 mtlk_osal_event_init, (&slow_ctx->connect_event));
2347 MTLK_INIT_STEP(core_slow_ctx, VAP_REMOVED_EVENT_INIT, MTLK_OBJ_PTR(slow_ctx),
2348 mtlk_osal_event_init, (&slow_ctx->vap_removed_event));
2350 MTLK_INIT_STEP(core_slow_ctx, STADB_INIT, MTLK_OBJ_PTR(slow_ctx),
2351 mtlk_stadb_init, (&slow_ctx->stadb, nic->vap_handle));
2353 MTLK_INIT_STEP(core_slow_ctx, HSTDB_INIT, MTLK_OBJ_PTR(slow_ctx),
2354 mtlk_hstdb_init, (&slow_ctx->hstdb, nic->vap_handle));
2356 slow_ctx->last_pm_spectrum = -1;
2357 slow_ctx->last_pm_freq = MTLK_HW_BAND_NONE;
2359 /* Initialize WEP keys */
2360 slow_ctx->wep_keys.sKey[0].u8KeyLength =
2361 slow_ctx->wep_keys.sKey[1].u8KeyLength =
2362 slow_ctx->wep_keys.sKey[2].u8KeyLength =
2363 slow_ctx->wep_keys.sKey[3].u8KeyLength =
2364 MIB_WEP_KEY_WEP1_LENGTH;
2366 nic->slow_ctx->tx_limits.num_tx_antennas = DEFAULT_NUM_TX_ANTENNAS;
2367 nic->slow_ctx->tx_limits.num_rx_antennas = DEFAULT_NUM_RX_ANTENNAS;
2369 nic->slow_ctx->deactivate_ts = INVALID_DEACTIVATE_TIMESTAMP;
2371 MTLK_INIT_FINALLY(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
2372 MTLK_INIT_RETURN(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx), _mtlk_slow_ctx_cleanup, (nic->slow_ctx, nic))
2375 static int
2376 _mtlk_core_sq_init(mtlk_core_t *core)
2378 MTLK_ASSERT(NULL != core);
2379 /* in case if it is Virtual AP, we get Master SQ from outside, otherwise, create it */
2380 if (mtlk_vap_is_slave_ap(core->vap_handle)) {
2381 mtlk_core_t *master_nic = mtlk_core_get_master(core);
2382 core->sq = master_nic->sq;
2383 core->sq_flush_tasklet = master_nic->sq_flush_tasklet;
2384 return MTLK_ERR_OK;
2386 return sq_init(core);
2389 static void
2390 _mtlk_core_sq_cleanup(mtlk_core_t *core)
2392 /* do nothing in case of slave core */
2393 if (mtlk_vap_is_slave_ap(core->vap_handle)) {
2394 core->sq = NULL;
2395 core->sq_flush_tasklet = NULL;
2397 else {
2398 sq_cleanup(core);
2402 static void
2403 _mtlk_core_ps_init(mtlk_core_t *core)
2405 MTLK_ASSERT(NULL != core);
2407 mtlk_osal_atomic_set(&core->stas_in_ps_mode, 0);
2408 core->uapsd_enabled = UAPSD_ENABLED_DEFAULT;
2409 core->uapsd_max_sp = UAPSD_MAX_SP_USER_DEFAULT;
2412 static void
2413 _mtlk_core_hw_flctrl_delete(mtlk_core_t *core)
2415 MTLK_ASSERT(NULL != core);
2417 if(!mtlk_vap_is_slave_ap(core->vap_handle)) {
2418 MTLK_ASSERT(core->hw_tx_flctrl != NULL);
2419 mtlk_flctrl_cleanup(core->hw_tx_flctrl);
2420 mtlk_osal_mem_free(core->hw_tx_flctrl);
2422 core->hw_tx_flctrl = NULL;
2425 static void __MTLK_IFUNC
2426 _mtlk_core_hw_flctrl_start_data (mtlk_handle_t ctx)
2428 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, ctx);
2430 mtlk_sq_tx_enable(core->sq);
2431 mtlk_sq_schedule_flush(core);
2434 static void __MTLK_IFUNC
2435 _mtlk_core_hw_flctrl_stop_data (mtlk_handle_t ctx)
2437 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, ctx);
2439 mtlk_sq_tx_disable(core->sq);
2442 static int
2443 _mtlk_core_hw_flctrl_create(mtlk_core_t *core)
2445 int result = MTLK_ERR_OK;
2446 MTLK_ASSERT(NULL != core);
2448 /* Allocate and init Flow Control object only for Master AP or STA */
2449 if(!mtlk_vap_is_slave_ap(core->vap_handle)) {
2450 mtlk_flctrl_api_t hw_flctrl_cfg;
2452 core->hw_tx_flctrl = mtlk_osal_mem_alloc(sizeof(mtlk_flctrl_t), MTLK_MEM_TAG_FLCTRL);
2453 if (NULL == core->hw_tx_flctrl) {
2454 result = MTLK_ERR_NO_MEM;
2455 goto err_flctrl_alloc;
2458 hw_flctrl_cfg.ctx = HANDLE_T(core);
2459 hw_flctrl_cfg.start_data = _mtlk_core_hw_flctrl_start_data;
2460 hw_flctrl_cfg.stop_data = _mtlk_core_hw_flctrl_stop_data;
2461 result = mtlk_flctrl_init(core->hw_tx_flctrl, &hw_flctrl_cfg);
2462 if (MTLK_ERR_OK != result) {
2463 goto err_flctrl_init;
2466 else {
2467 /* In case of Slave AP, use Master AP Flow Control Object */
2468 core->hw_tx_flctrl = mtlk_core_get_master(core)->hw_tx_flctrl;
2471 return MTLK_ERR_OK;
2473 err_flctrl_init:
2474 mtlk_osal_mem_free(core->hw_tx_flctrl);
2475 core->hw_tx_flctrl = NULL;
2476 err_flctrl_alloc:
2477 return result;
2480 /* steps for init and cleanup */
2481 MTLK_INIT_STEPS_LIST_BEGIN(core)
2482 MTLK_INIT_STEPS_LIST_ENTRY(core, CORE_PDB_INIT)
2483 MTLK_INIT_STEPS_LIST_ENTRY(core, SLOW_CTX_ALLOC)
2484 MTLK_INIT_STEPS_LIST_ENTRY(core, SLOW_CTX_INIT)
2485 MTLK_INIT_STEPS_LIST_ENTRY(core, SQ_INIT)
2486 MTLK_INIT_STEPS_LIST_ENTRY(core, SQ_BROADCAST_CTX_INIT)
2487 MTLK_INIT_STEPS_LIST_ENTRY(core, L2NAT_INIT)
2488 MTLK_INIT_STEPS_LIST_ENTRY(core, NET_STATE_LOCK_INIT)
2489 MTLK_INIT_STEPS_LIST_ENTRY(core, QOS_INIT)
2490 #ifdef MTCFG_RF_MANAGEMENT_MTLK
2491 MTLK_INIT_STEPS_LIST_ENTRY(core, RF_MGMT_CREATE)
2492 #endif
2493 MTLK_INIT_STEPS_LIST_ENTRY(core, FLCTRL_CREATE)
2494 MTLK_INIT_STEPS_LIST_ENTRY(core, TXMM_EEPROM_ASYNC_MSGS_INIT)
2495 MTLK_INIT_STEPS_LIST_ENTRY(core, PS_INIT)
2496 MTLK_INIT_INNER_STEPS_BEGIN(core)
2497 MTLK_INIT_STEPS_LIST_END(core);
2499 static void __MTLK_IFUNC
2500 _mtlk_core_cleanup(struct nic* nic)
2502 int i;
2504 MTLK_ASSERT(NULL != nic);
2505 MTLK_CLEANUP_BEGIN(core, MTLK_OBJ_PTR(nic))
2506 MTLK_CLEANUP_STEP(core, PS_INIT, MTLK_OBJ_PTR(nic),
2507 MTLK_NOACTION, ())
2509 for (i = 0; i < ARRAY_SIZE(nic->txmm_async_eeprom_msgs); i++) {
2510 MTLK_CLEANUP_STEP_LOOP(core, TXMM_EEPROM_ASYNC_MSGS_INIT, MTLK_OBJ_PTR(nic),
2511 mtlk_txmm_msg_cleanup, (&nic->txmm_async_eeprom_msgs[i]));
2514 MTLK_CLEANUP_STEP(core, FLCTRL_CREATE, MTLK_OBJ_PTR(nic),
2515 _mtlk_core_hw_flctrl_delete, (nic))
2517 #ifdef MTCFG_RF_MANAGEMENT_MTLK
2518 MTLK_CLEANUP_STEP(core, RF_MGMT_CREATE, MTLK_OBJ_PTR(nic),
2519 mtlk_rf_mgmt_delete, (nic->rf_mgmt))
2520 #endif
2522 MTLK_CLEANUP_STEP(core, QOS_INIT, MTLK_OBJ_PTR(nic),
2523 mtlk_qos_cleanup, (&nic->qos, nic->vap_handle));
2525 MTLK_CLEANUP_STEP(core, NET_STATE_LOCK_INIT, MTLK_OBJ_PTR(nic),
2526 mtlk_osal_lock_cleanup, (&nic->net_state_lock));
2528 MTLK_CLEANUP_STEP(core, L2NAT_INIT, MTLK_OBJ_PTR(nic),
2529 mtlk_l2nat_cleanup, (&nic->l2nat, nic));
2531 MTLK_CLEANUP_STEP(core, SQ_BROADCAST_CTX_INIT, MTLK_OBJ_PTR(nic),
2532 mtlk_sq_peer_ctx_cleanup, (nic->sq, &nic->sq_broadcast_ctx));
2534 MTLK_CLEANUP_STEP(core, SQ_INIT, MTLK_OBJ_PTR(nic),
2535 _mtlk_core_sq_cleanup, (nic));
2537 MTLK_CLEANUP_STEP(core, SLOW_CTX_INIT, MTLK_OBJ_PTR(nic),
2538 _mtlk_slow_ctx_cleanup, (nic->slow_ctx, nic));
2540 MTLK_CLEANUP_STEP(core, SLOW_CTX_ALLOC, MTLK_OBJ_PTR(nic),
2541 kfree_tag, (nic->slow_ctx));
2543 MTLK_CLEANUP_STEP(core, CORE_PDB_INIT, MTLK_OBJ_PTR(nic),
2544 mtlk_core_pdb_fast_handles_close, (nic->pdb_hot_path_handles));
2546 MTLK_CLEANUP_END(core, MTLK_OBJ_PTR(nic));
2549 static int __MTLK_IFUNC
2550 _mtlk_core_init(struct nic* nic, mtlk_vap_handle_t vap_handle, mtlk_df_t* df)
2552 int txem_cnt = 0;
2554 MTLK_ASSERT(NULL != nic);
2556 MTLK_INIT_TRY(core, MTLK_OBJ_PTR(nic))
2557 /* set initial net state */
2558 nic->net_state = NET_STATE_HALTED;
2559 nic->vap_handle = vap_handle;
2561 MTLK_INIT_STEP(core, CORE_PDB_INIT, MTLK_OBJ_PTR(nic),
2562 mtlk_core_pdb_fast_handles_open, (mtlk_vap_get_param_db(nic->vap_handle), nic->pdb_hot_path_handles));
2564 MTLK_INIT_STEP_EX(core, SLOW_CTX_ALLOC, MTLK_OBJ_PTR(nic),
2565 kmalloc_tag, (sizeof(struct nic_slow_ctx), GFP_KERNEL, MTLK_MEM_TAG_CORE),
2566 nic->slow_ctx, NULL != nic->slow_ctx, MTLK_ERR_NO_MEM);
2568 MTLK_INIT_STEP(core, SLOW_CTX_INIT, MTLK_OBJ_PTR(nic),
2569 _mtlk_slow_ctx_init, (nic->slow_ctx, nic));
2571 MTLK_INIT_STEP(core, SQ_INIT, MTLK_OBJ_PTR(nic),
2572 _mtlk_core_sq_init, (nic));
2574 MTLK_INIT_STEP_VOID(core, SQ_BROADCAST_CTX_INIT, MTLK_OBJ_PTR(nic),
2575 mtlk_sq_peer_ctx_init, (nic->sq, &nic->sq_broadcast_ctx, MTLK_SQ_TX_LIMIT_DEFAULT, vap_handle));
2577 MTLK_INIT_STEP(core, L2NAT_INIT, MTLK_OBJ_PTR(nic),
2578 mtlk_l2nat_init, (&nic->l2nat, nic));
2580 MTLK_INIT_STEP(core, NET_STATE_LOCK_INIT, MTLK_OBJ_PTR(nic),
2581 mtlk_osal_lock_init, (&nic->net_state_lock));
2583 MTLK_INIT_STEP(core, QOS_INIT, MTLK_OBJ_PTR(nic),
2584 mtlk_qos_init, (&nic->qos, nic->vap_handle));
2586 #ifdef MTCFG_RF_MANAGEMENT_MTLK
2587 MTLK_INIT_STEP_EX(core, RF_MGMT_CREATE, MTLK_OBJ_PTR(nic),
2588 mtlk_rf_mgmt_create, (), nic->rf_mgmt,
2589 nic->rf_mgmt != NULL, MTLK_ERR_UNKNOWN);
2590 #endif
2592 MTLK_INIT_STEP(core, FLCTRL_CREATE, MTLK_OBJ_PTR(nic),
2593 _mtlk_core_hw_flctrl_create, (nic))
2595 for (txem_cnt = 0; txem_cnt < ARRAY_SIZE(nic->txmm_async_eeprom_msgs); txem_cnt++) {
2596 MTLK_INIT_STEP_LOOP(core, TXMM_EEPROM_ASYNC_MSGS_INIT, MTLK_OBJ_PTR(nic),
2597 mtlk_txmm_msg_init, (&nic->txmm_async_eeprom_msgs[txem_cnt]));
2600 MTLK_INIT_STEP_VOID(core, PS_INIT, MTLK_OBJ_PTR(nic),
2601 _mtlk_core_ps_init, (nic))
2603 nic->is_stopped = TRUE;
2605 MTLK_INIT_FINALLY(core, MTLK_OBJ_PTR(nic))
2606 MTLK_INIT_RETURN(core, MTLK_OBJ_PTR(nic), _mtlk_core_cleanup, (nic))
2609 static int _mtlk_core_update_param_db(struct nic* nic)
2611 /* reset TWO_ANT_TX_ENABLE if antenna limits is not 3x3 */
2612 if (!_mtlk_core_tx_limits_antennas_is_3x3(nic)) {
2613 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_TWO_ANT_TX_ENABLE, 0);
2616 return MTLK_ERR_OK;
2619 static int _mtlk_core_create_20_40(struct nic* nic)
2621 mtlk_20_40_csm_xfaces_t xfaces;
2622 struct _mtlk_20_40_coexistence_sm *coex_sm;
2623 BOOL is_ap;
2624 uint32 max_number_of_connected_stations;
2625 int ret_val = MTLK_ERR_NO_MEM;
2627 xfaces.context = (mtlk_handle_t)nic;
2628 xfaces.vap_handle = nic->vap_handle;
2629 xfaces.switch_cb_mode = &_mtlk_core_switch_cb_mode_callback;
2630 xfaces.send_ce = &_mtlk_core_send_ce_callback;
2631 xfaces.send_cmf = &_mtlk_core_send_cmf_callback;
2632 xfaces.send_exempt_policy = &_mtlk_core_send_exemption_policy_callback;
2633 xfaces.scan_async = &_mtlk_core_scan_async_callback;
2634 xfaces.scan_set_background = &_mtlk_core_scan_set_obss_callback;
2635 xfaces.register_scan_completion_notification_callback = &_mtlk_core_register_scan_completion_notification_callback;
2636 #ifdef BT_ACS_DEBUG
2637 xfaces.enumerate_bss_info = (mtlk_core_get_freq_band_cfg(nic) == MTLK_HW_BAND_2_4_GHZ)
2638 ? &_mtlk_core_enumerate_bss_info_by_aocs_callback : &_mtlk_core_enumerate_bss_info_callback;
2639 #else
2640 xfaces.enumerate_bss_info = &_mtlk_core_enumerate_bss_info_callback;
2641 #endif /* BT_ACS_DEBUG */
2642 xfaces.ability_control = &_mtlk_core_ability_control_callback;
2643 xfaces.get_cur_channels = &_mtlk_core_get_cur_channels_callback;
2644 xfaces.modify_cache_expire_time = &_mtlk_core_modify_cache_expire_callback;
2645 xfaces.update_fw_obss_scan_params = &_mtlk_core_update_fw_obss_scan_parameters_callback;
2647 is_ap = mtlk_vap_is_ap(nic->vap_handle);
2648 if (is_ap) {
2649 max_number_of_connected_stations = mtlk_core_get_max_stas_supported_by_fw(nic);
2650 } else {
2651 max_number_of_connected_stations = 0;
2653 coex_sm = mtlk_20_40_create(&xfaces, is_ap, max_number_of_connected_stations);
2655 if (coex_sm) {
2656 mtlk_core_set_coex_sm(nic, coex_sm);
2657 ret_val = MTLK_ERR_OK;
2660 return ret_val;
2663 static void _mtlk_core_delete_20_40(struct nic* nic)
2665 struct _mtlk_20_40_coexistence_sm *coex_sm = mtlk_core_get_coex_sm(nic);
2666 if (coex_sm)
2668 mtlk_20_40_delete(coex_sm);
2669 mtlk_core_set_coex_sm(nic, NULL);
2673 struct _mtlk_20_40_coexistence_sm * mtlk_core_get_coex_sm(mtlk_core_t *core)
2675 return mtlk_core_get_master(core)->coex_20_40_sm;
2678 BOOL mtlk_core_is_20_40_active(struct nic* nic)
2680 BOOL res = FALSE;
2682 if(mtlk_vap_is_ap(nic->vap_handle))
2684 res = (mtlk_20_40_is_feature_enabled(mtlk_core_get_coex_sm(nic)) && (mtlk_core_get_freq_band_cfg(nic) == MTLK_HW_BAND_2_4_GHZ)) ? TRUE : FALSE;
2686 else
2688 if (mtlk_core_get_net_state(nic) == NET_STATE_CONNECTED)
2690 res = (mtlk_20_40_is_feature_enabled(mtlk_core_get_coex_sm(nic)) && (mtlk_core_get_freq_band_cur(nic) == MTLK_HW_BAND_2_4_GHZ)) ? TRUE : FALSE;
2692 else
2694 res = mtlk_20_40_is_feature_enabled(mtlk_core_get_coex_sm(nic)) ? TRUE : FALSE;
2699 return res;
2702 void __MTLK_IFUNC
2703 mtlk_core_interfdet_enable (struct nic *core, BOOL enable_flag)
2705 MTLK_ASSERT(mtlk_vap_is_master_ap(core->vap_handle));
2706 core->is_interfdet_enabled = enable_flag;
2709 BOOL __MTLK_IFUNC
2710 mtlk_core_is_interfdet_enabled (struct nic *core)
2712 BOOL res = FALSE;
2714 MTLK_ASSERT(core != NULL);
2716 if (mtlk_vap_is_master_ap(core->vap_handle)) {
2717 res = (BOOL)mtlk_core_get_master(core)->is_interfdet_enabled;
2720 return res;
2723 int __MTLK_IFUNC
2724 mtlk_core_api_init (mtlk_vap_handle_t vap_handle, mtlk_core_api_t *core_api, mtlk_df_t* df)
2726 int res;
2727 mtlk_core_t *core;
2729 MTLK_ASSERT(NULL != core_api);
2731 /* initialize function table */
2732 core_api->vft = &core_vft;
2734 core = mtlk_fast_mem_alloc(MTLK_FM_USER_CORE, sizeof(mtlk_core_t));
2735 if(NULL == core) {
2736 return MTLK_ERR_NO_MEM;
2739 memset(core, 0, sizeof(mtlk_core_t));
2741 res = _mtlk_core_init(core, vap_handle, df);
2742 if (MTLK_ERR_OK != res) {
2743 mtlk_fast_mem_free(core);
2744 return res;
2747 core_api->core_handle = HANDLE_T(core);
2749 return MTLK_ERR_OK;
2752 static int
2753 mtlk_core_master_set_default_band(struct nic *nic)
2755 uint8 freq_band_cfg = MTLK_HW_BAND_NONE;
2756 MTLK_ASSERT(!mtlk_vap_is_slave_ap(nic->vap_handle));
2758 if (mtlk_core_is_band_supported(nic, MTLK_HW_BAND_BOTH) == MTLK_ERR_OK) {
2759 freq_band_cfg = MTLK_HW_BAND_BOTH;
2760 } else if (mtlk_core_is_band_supported(nic, MTLK_HW_BAND_5_2_GHZ) == MTLK_ERR_OK) {
2761 freq_band_cfg = MTLK_HW_BAND_5_2_GHZ;
2762 } else if (mtlk_core_is_band_supported(nic, MTLK_HW_BAND_2_4_GHZ) == MTLK_ERR_OK) {
2763 freq_band_cfg = MTLK_HW_BAND_2_4_GHZ;
2764 } else {
2765 ELOG_D("CID-%04x: None of the bands is supported", mtlk_vap_get_oid(nic->vap_handle));
2766 return MTLK_ERR_UNKNOWN;
2769 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_FREQ_BAND_CFG, freq_band_cfg);
2770 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_FREQ_BAND_CUR, freq_band_cfg);
2772 return MTLK_ERR_OK;
2775 static int
2776 mtlk_core_set_default_net_mode(struct nic *nic)
2778 uint8 freq_band_cfg = MTLK_HW_BAND_NONE;
2779 uint8 net_mode = NUM_OF_NETWORK_MODES;
2780 mtlk_core_t *core_master = NULL;
2782 MTLK_ASSERT(nic != NULL);
2784 if(!mtlk_vap_is_slave_ap(nic->vap_handle))
2786 /* Set default mode based on band
2787 * for Master AP or STA */
2788 freq_band_cfg = mtlk_core_get_freq_band_cfg(nic);
2789 net_mode = get_net_mode(freq_band_cfg, TRUE);
2791 else
2793 /* Copy default mode from Master VAP.
2794 * This is important while scripts
2795 * are not ready for network mode per VAP. */
2796 core_master = mtlk_core_get_master(nic);
2797 MTLK_ASSERT(core_master != NULL);
2798 net_mode = mtlk_core_get_network_mode_cfg(core_master);
2801 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_NET_MODE_CUR, net_mode);
2802 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_NET_MODE_CFG, net_mode);
2804 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_IS_HT_CUR, is_ht_net_mode(net_mode));
2805 MTLK_CORE_PDB_SET_INT(nic, PARAM_DB_CORE_IS_HT_CFG, is_ht_net_mode(net_mode));
2807 return MTLK_ERR_OK;
2810 static int
2811 _mtlk_core_process_antennas_configuration(mtlk_core_t *nic)
2813 int err = MTLK_ERR_OK;
2814 uint8 tx_val_array[MTLK_NUM_ANTENNAS_BUFSIZE] = {1, 2, 3, 0};
2815 uint8 rx_val_array[MTLK_NUM_ANTENNAS_BUFSIZE] = {1, 2, 3, 0};
2817 uint8 num_tx_antennas = nic->slow_ctx->tx_limits.num_tx_antennas;
2818 uint8 num_rx_antennas = nic->slow_ctx->tx_limits.num_rx_antennas;
2820 /* determine number of TX antennas */
2821 if (2 == num_tx_antennas)
2823 tx_val_array[2] = 0;
2825 else if (3 != num_tx_antennas)
2827 MTLK_ASSERT(!"Wrong number of TX antennas");
2828 return MTLK_ERR_UNKNOWN;
2831 /* determine number of RX antennas */
2832 if (2 == num_rx_antennas)
2834 rx_val_array[2] = 0;
2836 else if (3 != num_rx_antennas)
2838 MTLK_ASSERT(!"Wrong number of RX antennas");
2839 return MTLK_ERR_UNKNOWN;
2842 err = MTLK_CORE_PDB_SET_BINARY(nic, PARAM_DB_CORE_TX_ANTENNAS, tx_val_array, MTLK_NUM_ANTENNAS_BUFSIZE);
2843 if (MTLK_ERR_OK != err)
2845 ILOG2_V("Can not save TX antennas configuration in to the PDB");
2846 return err;
2849 err = MTLK_CORE_PDB_SET_BINARY(nic, PARAM_DB_CORE_RX_ANTENNAS, rx_val_array, MTLK_NUM_ANTENNAS_BUFSIZE);
2850 if (MTLK_ERR_OK != err)
2852 ILOG2_V("Can not save RX antennas configuration in to the PDB");
2853 return err;
2856 return MTLK_ERR_OK;
2859 static void
2860 _mtlk_core_aocs_on_channel_change(mtlk_vap_handle_t vap_handle, int channel)
2862 mtlk_pdb_set_int(mtlk_vap_get_param_db(vap_handle), PARAM_DB_CORE_CHANNEL_CUR, channel);
2863 ILOG3_D("Channel changed to %d", channel);
2866 static void
2867 _mtlk_core_aocs_on_bonding_change(mtlk_vap_handle_t vap_handle, uint8 bonding)
2869 mtlk_core_set_cur_bonding(mtlk_vap_get_core(vap_handle), bonding);
2872 static void
2873 _mtlk_core_aocs_on_spectrum_change(mtlk_vap_handle_t vap_handle, int spectrum)
2875 mtlk_core_t *nic = mtlk_vap_get_core(vap_handle);
2876 mtlk_pdb_t *pdb = mtlk_vap_get_param_db(vap_handle);
2878 if (mtlk_pdb_get_int(pdb, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE) != spectrum) {
2879 ILOG0_DS("CID-%04x: Spectrum changed to %s0MHz", mtlk_vap_get_oid(vap_handle), spectrum == SPECTRUM_20MHZ ? "2" : "4");
2882 mtlk_pdb_set_int(pdb, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE, spectrum);
2884 mtlk_dot11h_set_spectrum_mode(mtlk_core_get_dfs(nic), spectrum);
2887 MTLK_START_STEPS_LIST_BEGIN(core_slow_ctx)
2888 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, SERIALIZER_START)
2889 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, SET_MAC_MAC_ADDR)
2890 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, PARSE_EE_DATA)
2891 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, CACHE_INIT)
2892 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, INIT_TX_LIMIT_TABLES)
2893 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, PROCESS_ANTENNA_CFG)
2894 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, PROCESS_COC)
2895 #ifdef MTCFG_PMCU_SUPPORT
2896 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, PROCESS_PCOC)
2897 #endif /*MTCFG_PMCU_SUPPORT*/
2898 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, AOCS_INIT)
2899 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, SCAN_INIT)
2900 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, DOT11H_INIT)
2901 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, ADDBA_AGGR_LIM_INIT)
2902 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, ADDBA_REORD_LIM_INIT)
2903 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, ADDBA_INIT)
2904 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, WDS_INIT)
2905 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, SET_DEFAULT_BAND)
2906 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, SET_DEFAULT_NET_MODE)
2907 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, WATCHDOG_TIMER_START)
2908 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, SERIALIZER_ACTIVATE)
2909 MTLK_START_STEPS_LIST_ENTRY(core_slow_ctx, CORE_STAT_REQ_HANDLER)
2910 MTLK_START_INNER_STEPS_BEGIN(core_slow_ctx)
2911 MTLK_START_STEPS_LIST_END(core_slow_ctx);
2913 static void
2914 _mtlk_core_get_wlan_stats(mtlk_core_t* core, mtlk_wssa_drv_wlan_stats_t* stats)
2916 /* minimal statistic */
2917 stats->TxPacketsSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_PACKETS_SENT);
2918 stats->RxPacketsSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_PACKETS_RECEIVED);
2919 stats->TxBytesSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BYTES_SENT);
2920 stats->RxBytesSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BYTES_RECEIVED);
2921 stats->UnicastPacketsSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_UNICAST_PACKETS_SENT);
2922 stats->UnicastPacketsReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_UNICAST_PACKETS_RECEIVED);
2923 stats->MulticastPacketsSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_PACKETS_SENT);
2924 stats->MulticastPacketsReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_PACKETS_RECEIVED);
2925 stats->BroadcastPacketsSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BROADCAST_PACKETS_SENT);
2926 stats->BroadcastPacketsReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BROADCAST_PACKETS_RECEIVED);
2929 #if MTLK_MTIDL_WLAN_STAT_FULL
2930 static void
2931 _mtlk_core_get_debug_wlan_stats(mtlk_core_t* core, mtlk_wssa_drv_debug_wlan_stats_t* stats)
2933 /* minimal statistic */
2934 stats->TxPacketsSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_PACKETS_SENT);
2935 stats->RxPacketsSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_PACKETS_RECEIVED);
2936 stats->TxBytesSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BYTES_SENT);
2937 stats->RxBytesSucceeded = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BYTES_RECEIVED);
2938 stats->UnicastPacketsSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_UNICAST_PACKETS_SENT);
2939 stats->UnicastPacketsReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_UNICAST_PACKETS_RECEIVED);
2940 stats->MulticastPacketsSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_PACKETS_SENT);
2941 stats->MulticastPacketsReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_PACKETS_RECEIVED);
2942 stats->BroadcastPacketsSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BROADCAST_PACKETS_SENT);
2943 stats->BroadcastPacketsReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BROADCAST_PACKETS_RECEIVED);
2945 /* full statistic */
2946 stats->RxPacketsDiscardedDrvTooOld = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_PACKETS_DISCARDED_DRV_TOO_OLD);
2947 stats->RxPacketsDiscardedDrvDuplicate = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_PACKETS_DISCARDED_DRV_DUPLICATE);
2948 stats->TxPacketsDiscardedDrvNoPeers = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_NO_PEERS);
2949 stats->TxPacketsDiscardedDrvACM = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_DRV_ACM);
2950 stats->TxPacketsDiscardedEapolCloned = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_EAPOL_CLONED);
2951 stats->TxPacketsDiscardedDrvUnknownDestinationDirected = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_DRV_UNKNOWN_DESTINATION_DIRECTED);
2952 stats->TxPacketsDiscardedDrvUnknownDestinationMcast = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_DRV_UNKNOWN_DESTINATION_MCAST);
2953 stats->TxPacketsDiscardedDrvNoResources = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_DRV_NO_RESOURCES);
2954 stats->TxPacketsDiscardedDrvSQOverflow = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_SQ_OVERFLOW);
2955 stats->TxPacketsDiscardedDrvEAPOLFilter = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_EAPOL_FILTER);
2956 stats->TxPacketsDiscardedDrvDropAllFilter = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_DROP_ALL_FILTER);
2957 stats->TxPacketsDiscardedDrvTXQueueOverflow = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_TX_QUEUE_OVERFLOW);
2958 stats->RxPackets802_1x = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_802_1X_PACKETS_RECEIVED);
2959 stats->TxPackets802_1x = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_802_1X_PACKETS_SENT);
2960 stats->PairwiseMICFailurePackets = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_PAIRWISE_MIC_FAILURE_PACKETS);
2961 stats->GroupMICFailurePackets = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_GROUP_MIC_FAILURE_PACKETS);
2962 stats->UnicastReplayedPackets = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_UNICAST_REPLAYED_PACKETS);
2963 stats->MulticastReplayedPackets = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_REPLAYED_PACKETS);
2964 stats->FwdRxPackets = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_FWD_RX_PACKETS);
2965 stats->FwdRxBytes = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_FWD_RX_BYTES);
2966 stats->MulticastBytesSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_BYTES_SENT);
2967 stats->MulticastBytesReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MULTICAST_BYTES_RECEIVED);
2968 stats->BroadcastBytesSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BROADCAST_BYTES_SENT);
2969 stats->BroadcastBytesReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_BROADCAST_BYTES_RECEIVED);
2970 stats->DATFramesReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_DAT_FRAMES_RECEIVED);
2971 stats->CTLFramesReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_CTL_FRAMES_RECEIVED);
2972 stats->MANFramesReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_MAN_FRAMES_RECEIVED);
2974 stats->CoexElReceived = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_COEX_EL_RECEIVED);
2975 stats->ScanExRequested = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_COEX_EL_SCAN_EXEMPTION_REQUESTED);
2976 stats->ScanExGranted = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_COEX_EL_SCAN_EXEMPTION_GRANTED);
2977 stats->ScanExGrantCancelled = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_COEX_EL_SCAN_EXEMPTION_GRANT_CANCELLED);
2978 stats->SwitchChannel20To40 = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_CHANNEL_SWITCH_20_TO_40);
2979 stats->SwitchChannel40To20 = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_CHANNEL_SWITCH_40_TO_20);
2980 stats->SwitchChannel40To40 = _mtlk_core_get_cnt(mtlk_core_get_master(core), MTLK_CORE_CNT_CHANNEL_SWITCH_40_TO_40);
2982 /* Aggregation info */
2983 stats->Aggregation.AggrActive = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_AGGR_ACTIVE);
2984 stats->Aggregation.ReordActive = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_REORD_ACTIVE);
2985 stats->Aggregation.RxAddbaReqReceived = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_REQ_RECEIVED);
2986 stats->Aggregation.RxAddbaResCfmdFail = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_CFMD_FAIL);
2987 stats->Aggregation.RxAddbaResCfmdSuccess = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_CFMD_SUCCESS);
2988 stats->Aggregation.RxAddbaResLost = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_LOST);
2989 stats->Aggregation.RxAddbaResNegativeSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_NEGATIVE_SENT);
2990 stats->Aggregation.RxAddbaResNotCfmd = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_NOT_CFMD);
2991 stats->Aggregation.RxAddbaResPositiveSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_POSITIVE_SENT);
2992 stats->Aggregation.RxAddbaResReached = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_REACHED);
2993 stats->Aggregation.RxAddbaResRetransmissions = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_ADDBA_RES_RETRANSMISSIONS);
2994 stats->Aggregation.RxBarWithoutReordering = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_BAR_WITHOUT_REORDERING);
2995 stats->Aggregation.RxPktWithoutReordering = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_AGGR_PKT_WITHOUT_REORDERING);
2996 stats->Aggregation.RxDelbaReqCfmdFail = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_CFMD_FAIL);
2997 stats->Aggregation.RxDelbaReqCfmdSuccess = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_CFMD_SUCCESS);
2998 stats->Aggregation.RxDelbaReqLost = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_LOST);
2999 stats->Aggregation.RxDelbaReqNotCfmd = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_NOT_CFMD);
3000 stats->Aggregation.RxDelbaReqRcv = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_RCV);
3001 stats->Aggregation.RxDelbaReqReached = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_REACHED);
3002 stats->Aggregation.RxDelbaReqRetransmissions = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_RETRANSMISSIONS);
3003 stats->Aggregation.RxDelbaReqSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_REQ_SENT);
3004 stats->Aggregation.RxDelbaSentByTimeout = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_RX_DELBA_SENT_BY_TIMEOUT);
3006 stats->Aggregation.TxAckOnBarDetected = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ACK_ON_BAR_DETECTED);
3007 stats->Aggregation.TxAddbaReqCfmdFail = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_REQ_CFMD_FAIL);
3008 stats->Aggregation.TxAddbaReqCfmdSuccess = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_REQ_CFMD_SUCCESS);
3009 stats->Aggregation.TxAddbaReqNotCfmd = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_REQ_NOT_CFMD);
3010 stats->Aggregation.TxAddbaReqSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_REQ_SENT);
3011 stats->Aggregation.TxAddbaResRcvNegative = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_RES_RCV_NEGATIVE);
3012 stats->Aggregation.TxAddbaResRcvPositive = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_RES_RCV_POSITIVE);
3013 stats->Aggregation.TxAddbaResTimeout = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_ADDBA_RES_TIMEOUT);
3014 stats->Aggregation.TxCloseAggrCfmdFail = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_CLOSE_AGGR_CFMD_FAIL);
3015 stats->Aggregation.TxCloseAggrCfmdSuccess = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_CLOSE_AGGR_CFMD_SUCCESS);
3016 stats->Aggregation.TxCloseAggrNotCfmd = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_CLOSE_AGGR_NOT_CFMD);
3017 stats->Aggregation.TxCloseAggrSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_CLOSE_AGGR_SENT);
3018 stats->Aggregation.TxDelbaReqCfmdFail = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_CFMD_FAIL);
3019 stats->Aggregation.TxDelbaReqCfmdSuccess = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_CFMD_SUCCESS);
3020 stats->Aggregation.TxDelbaReqLost = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_LOST);
3021 stats->Aggregation.TxDelbaReqNotCfmd = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_NOT_CFMD);
3022 stats->Aggregation.TxDelbaReqRcv = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_RCV);
3023 stats->Aggregation.TxDelbaReqReached = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_REACHED);
3024 stats->Aggregation.TxDelbaReqRetransmissions = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_RETRANSMISSIONS);
3025 stats->Aggregation.TxDelbaReqSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_DELBA_REQ_SENT);
3026 stats->Aggregation.TxOpenAggrCfmdFail = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_OPEN_AGGR_CFMD_FAIL);
3027 stats->Aggregation.TxOpenAggrCfmdSuccess = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_OPEN_AGGR_CFMD_SUCCESS);
3028 stats->Aggregation.TxOpenAggrNotCfmd = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_OPEN_AGGR_NOT_CFMD);
3029 stats->Aggregation.TxOpenAggrSent = _mtlk_core_get_cnt(core, MTLK_CORE_CNT_TX_OPEN_AGGR_SENT);
3031 #endif /* MTLK_MTIDL_WLAN_STAT_FULL */
3033 static void __MTLK_IFUNC
3034 _mtlk_core_stat_handle_request(mtlk_irbd_t *irbd,
3035 mtlk_handle_t context,
3036 const mtlk_guid_t *evt,
3037 void *buffer,
3038 uint32 *size)
3040 struct nic_slow_ctx *slow_ctx = HANDLE_T_PTR(struct nic_slow_ctx, context);
3041 mtlk_wssa_info_hdr_t *hdr = (mtlk_wssa_info_hdr_t *) buffer;
3043 MTLK_UNREFERENCED_PARAM(evt);
3045 if(sizeof(mtlk_wssa_info_hdr_t) > *size)
3046 return;
3048 if(MTIDL_SRC_DRV == hdr->info_source)
3050 switch(hdr->info_id)
3052 case MTLK_WSSA_DRV_STATUS_WLAN:
3054 if(sizeof(mtlk_wssa_drv_wlan_stats_t) + sizeof(mtlk_wssa_info_hdr_t) > *size)
3056 hdr->processing_result = MTLK_ERR_BUF_TOO_SMALL;
3058 else
3060 _mtlk_core_get_wlan_stats(slow_ctx->nic, (mtlk_wssa_drv_wlan_stats_t*) &hdr[1]);
3061 hdr->processing_result = MTLK_ERR_OK;
3062 *size = sizeof(mtlk_wssa_drv_wlan_stats_t) + sizeof(mtlk_wssa_info_hdr_t);
3065 break;
3066 #if MTLK_MTIDL_WLAN_STAT_FULL
3067 case MTLK_WSSA_DRV_DEBUG_STATUS_WLAN:
3069 if(sizeof(mtlk_wssa_drv_debug_wlan_stats_t) + sizeof(mtlk_wssa_info_hdr_t) > *size)
3071 hdr->processing_result = MTLK_ERR_BUF_TOO_SMALL;
3073 else
3075 _mtlk_core_get_debug_wlan_stats(slow_ctx->nic, (mtlk_wssa_drv_debug_wlan_stats_t*) &hdr[1]);
3076 hdr->processing_result = MTLK_ERR_OK;
3077 *size = sizeof(mtlk_wssa_drv_debug_wlan_stats_t) + sizeof(mtlk_wssa_info_hdr_t);
3080 break;
3081 #endif /* MTLK_MTIDL_WLAN_STAT_FULL */
3082 default:
3084 hdr->processing_result = MTLK_ERR_NO_ENTRY;
3085 *size = sizeof(mtlk_wssa_info_hdr_t);
3089 else
3091 hdr->processing_result = MTLK_ERR_NO_ENTRY;
3092 *size = sizeof(mtlk_wssa_info_hdr_t);
3096 static void __MTLK_IFUNC
3097 _mtlk_slow_ctx_stop(struct nic_slow_ctx *slow_ctx, struct nic* nic)
3099 MTLK_ASSERT(NULL != slow_ctx);
3100 MTLK_ASSERT(NULL != nic);
3102 MTLK_STOP_BEGIN(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
3103 MTLK_STOP_STEP(core_slow_ctx, CORE_STAT_REQ_HANDLER, MTLK_OBJ_PTR(slow_ctx),
3104 mtlk_wssd_unregister_request_handler, (mtlk_vap_get_irbd(nic->vap_handle), slow_ctx->stat_irb_handle));
3106 MTLK_STOP_STEP(core_slow_ctx, SERIALIZER_ACTIVATE, MTLK_OBJ_PTR(slow_ctx),
3107 mtlk_serializer_stop, (&slow_ctx->serializer))
3109 MTLK_STOP_STEP(core_slow_ctx, WATCHDOG_TIMER_START, MTLK_OBJ_PTR(slow_ctx),
3110 mtlk_osal_timer_cancel_sync, (&slow_ctx->mac_watchdog_timer))
3112 MTLK_STOP_STEP(core_slow_ctx, SET_DEFAULT_NET_MODE, MTLK_OBJ_PTR(slow_ctx),
3113 MTLK_NOACTION, ())
3115 MTLK_STOP_STEP(core_slow_ctx, SET_DEFAULT_BAND, MTLK_OBJ_PTR(slow_ctx),
3116 MTLK_NOACTION, ())
3118 MTLK_STOP_STEP(core_slow_ctx, WDS_INIT, MTLK_OBJ_PTR(slow_ctx),
3119 wds_cleanup, (&slow_ctx->wds_mng))
3121 MTLK_STOP_STEP(core_slow_ctx, ADDBA_INIT, MTLK_OBJ_PTR(slow_ctx),
3122 mtlk_addba_cleanup, (&slow_ctx->addba))
3124 MTLK_STOP_STEP(core_slow_ctx, ADDBA_REORD_LIM_INIT, MTLK_OBJ_PTR(slow_ctx),
3125 mtlk_reflim_cleanup, (&slow_ctx->addba_lim_reord))
3127 MTLK_STOP_STEP(core_slow_ctx, ADDBA_AGGR_LIM_INIT, MTLK_OBJ_PTR(slow_ctx),
3128 mtlk_reflim_cleanup, (&slow_ctx->addba_lim_aggr))
3130 MTLK_STOP_STEP(core_slow_ctx, DOT11H_INIT, MTLK_OBJ_PTR(slow_ctx),
3131 mtlk_dot11h_cleanup, (mtlk_core_get_dfs(nic)))
3133 MTLK_STOP_STEP(core_slow_ctx, SCAN_INIT, MTLK_OBJ_PTR(slow_ctx),
3134 mtlk_scan_cleanup, (&slow_ctx->scan))
3136 MTLK_STOP_STEP(core_slow_ctx, AOCS_INIT, MTLK_OBJ_PTR(slow_ctx),
3137 mtlk_aocs_delete, (slow_ctx->aocs))
3139 #ifdef MTCFG_PMCU_SUPPORT
3140 MTLK_STOP_STEP(core_slow_ctx, PROCESS_PCOC, MTLK_OBJ_PTR(slow_ctx),
3141 mtlk_pcoc_delete, (slow_ctx->pcoc_mngmt))
3142 #endif /*MTCFG_PMCU_SUPPORT*/
3144 MTLK_STOP_STEP(core_slow_ctx, PROCESS_COC, MTLK_OBJ_PTR(slow_ctx),
3145 mtlk_coc_delete, (slow_ctx->coc_mngmt))
3147 MTLK_STOP_STEP(core_slow_ctx, PROCESS_ANTENNA_CFG, MTLK_OBJ_PTR(slow_ctx),
3148 MTLK_NOACTION, ())
3150 MTLK_STOP_STEP(core_slow_ctx, INIT_TX_LIMIT_TABLES, MTLK_OBJ_PTR(slow_ctx),
3151 mtlk_cleanup_tx_limit_tables, (&slow_ctx->tx_limits))
3153 MTLK_STOP_STEP(core_slow_ctx, CACHE_INIT, MTLK_OBJ_PTR(slow_ctx),
3154 mtlk_cache_cleanup, (&slow_ctx->cache))
3156 MTLK_STOP_STEP(core_slow_ctx, PARSE_EE_DATA, MTLK_OBJ_PTR(slow_ctx),
3157 MTLK_NOACTION, ())
3159 MTLK_STOP_STEP(core_slow_ctx, SET_MAC_MAC_ADDR, MTLK_OBJ_PTR(slow_ctx),
3160 MTLK_NOACTION, ())
3162 MTLK_STOP_STEP(core_slow_ctx, SERIALIZER_START, MTLK_OBJ_PTR(slow_ctx),
3163 MTLK_NOACTION, ())
3164 MTLK_STOP_END(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
3167 static int __MTLK_IFUNC
3168 _mtlk_slow_ctx_start(struct nic_slow_ctx *slow_ctx, struct nic* nic)
3170 int cache_param;
3171 struct mtlk_scan_config scan_cfg;
3172 mtlk_aocs_wrap_api_t aocs_api;
3173 mtlk_aocs_init_t aocs_ini_data;
3174 mtlk_dot11h_wrap_api_t dot11h_api;
3175 mtlk_coc_cfg_t coc_cfg;
3176 #ifdef MTCFG_PMCU_SUPPORT
3177 mtlk_pcoc_cfg_t pcoc_cfg;
3178 BOOL pcoc_required = FALSE;
3179 #endif /*MTCFG_PMCU_SUPPORT*/
3180 mtlk_txmm_t *txmm = mtlk_vap_get_txmm(nic->vap_handle);
3181 mtlk_reflim_t *addba_lim_aggr = NULL;
3182 mtlk_reflim_t *addba_lim_reord = NULL;
3183 mtlk_eeprom_data_t *eeprom_data;
3184 BOOL is_dut = mtlk_vap_is_dut(nic->vap_handle);
3185 BOOL is_slave_ap = mtlk_vap_is_slave_ap(nic->vap_handle);
3187 MTLK_ASSERT(NULL != slow_ctx);
3188 MTLK_ASSERT(NULL != nic);
3190 MTLK_START_TRY(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
3191 MTLK_START_STEP(core_slow_ctx, SERIALIZER_START, MTLK_OBJ_PTR(slow_ctx),
3192 mtlk_serializer_start, (&slow_ctx->serializer))
3194 eeprom_data = mtlk_core_get_eeprom(nic);
3196 MTLK_START_STEP_IF(!is_dut && !is_slave_ap, core_slow_ctx, SET_MAC_MAC_ADDR, MTLK_OBJ_PTR(slow_ctx),
3197 _mtlk_core_set_mac_addr, (nic, (char *)mtlk_eeprom_get_nic_mac_addr(eeprom_data)))
3199 MTLK_START_STEP_IF(!is_dut && !is_slave_ap, core_slow_ctx, PARSE_EE_DATA, MTLK_OBJ_PTR(slow_ctx),
3200 mtlk_eeprom_check_ee_data, (eeprom_data, txmm, mtlk_vap_is_ap(nic->vap_handle)))
3202 _mtlk_core_country_code_set_default(nic);
3204 if (mtlk_vap_is_ap(nic->vap_handle)) {
3205 cache_param = 0;
3206 } else {
3207 cache_param = SCAN_CACHE_AGEING;
3210 MTLK_START_STEP(core_slow_ctx, CACHE_INIT, MTLK_OBJ_PTR(slow_ctx),
3211 mtlk_cache_init, (&slow_ctx->cache, cache_param))
3213 MTLK_START_STEP_IF(!is_dut && !is_slave_ap, core_slow_ctx, INIT_TX_LIMIT_TABLES, MTLK_OBJ_PTR(slow_ctx),
3214 mtlk_init_tx_limit_tables,
3215 (&slow_ctx->tx_limits,
3216 MAC_TO_HOST16( mtlk_eeprom_get_vendor_id(eeprom_data) ),
3217 MAC_TO_HOST16( mtlk_eeprom_get_device_id(eeprom_data) ),
3218 mtlk_eeprom_get_nic_type(eeprom_data),
3219 mtlk_eeprom_get_nic_revision(eeprom_data) ) )
3221 MTLK_START_STEP_IF(!is_dut && !is_slave_ap, core_slow_ctx, PROCESS_ANTENNA_CFG, MTLK_OBJ_PTR(slow_ctx),
3222 _mtlk_core_process_antennas_configuration, (nic));
3224 coc_cfg.hw_antenna_cfg.num_tx_antennas = nic->slow_ctx->tx_limits.num_tx_antennas;
3225 coc_cfg.hw_antenna_cfg.num_rx_antennas = nic->slow_ctx->tx_limits.num_rx_antennas;
3226 coc_cfg.default_auto_cfg.interval_1x1 = 10; /* 1s */
3227 coc_cfg.default_auto_cfg.interval_2x2 = 50; /* 5s */
3228 coc_cfg.default_auto_cfg.interval_3x3 = 50; /* 5s */
3229 coc_cfg.default_auto_cfg.high_limit_1x1 = 1000; /* byte/sec */
3230 coc_cfg.default_auto_cfg.low_limit_2x2 = 5000; /* byte/sec */
3231 coc_cfg.default_auto_cfg.high_limit_2x2 = 5000; /* byte/sec */
3232 coc_cfg.default_auto_cfg.low_limit_3x3 = 5000; /* byte/sec */
3233 coc_cfg.txmm = txmm;
3234 coc_cfg.vap_handle = nic->vap_handle;
3236 MTLK_START_STEP_EX_IF(!is_slave_ap, core_slow_ctx, PROCESS_COC, MTLK_OBJ_PTR(slow_ctx),
3237 mtlk_coc_create, (&coc_cfg),
3238 slow_ctx->coc_mngmt, slow_ctx->coc_mngmt != NULL, MTLK_ERR_NO_MEM);
3239 #ifdef MTCFG_PMCU_SUPPORT
3241 if (_mtlk_core_is_master_on_g35(nic))
3243 pcoc_required = TRUE;
3244 pcoc_cfg.default_params.interval = 10; /* 1s */
3245 pcoc_cfg.default_params.limit_lower = 1000; /* kbps */
3246 pcoc_cfg.default_params.limit_upper = 2000; /* kbps */
3247 pcoc_cfg.vap_handle = nic->vap_handle;
3250 MTLK_START_STEP_EX_IF((!is_slave_ap) && pcoc_required, core_slow_ctx, PROCESS_PCOC, MTLK_OBJ_PTR(slow_ctx),
3251 mtlk_pcoc_create, (&pcoc_cfg),
3252 slow_ctx->pcoc_mngmt, slow_ctx->pcoc_mngmt != NULL, MTLK_ERR_NO_MEM);
3253 #endif /*MTCFG_PMCU_SUPPORT*/
3255 aocs_api.on_channel_change = _mtlk_core_aocs_on_channel_change;
3256 aocs_api.on_bonding_change = _mtlk_core_aocs_on_bonding_change;
3257 aocs_api.on_spectrum_change = _mtlk_core_aocs_on_spectrum_change;
3259 aocs_ini_data.api = &aocs_api;
3260 aocs_ini_data.scan_data = &slow_ctx->scan;
3261 aocs_ini_data.cache = &slow_ctx->cache;
3262 aocs_ini_data.dot11h = mtlk_core_get_dfs(nic);
3263 aocs_ini_data.txmm = txmm;
3264 aocs_ini_data.disable_sm_channels = mtlk_eeprom_get_disable_sm_channels(mtlk_core_get_eeprom(nic));
3266 slow_ctx->aocs = NULL;
3268 MTLK_START_STEP_EX_IF(mtlk_vap_is_master_ap(nic->vap_handle), core_slow_ctx, AOCS_INIT, MTLK_OBJ_PTR(slow_ctx),
3269 mtlk_aocs_create, (&aocs_ini_data, nic->vap_handle),
3270 slow_ctx->aocs, slow_ctx->aocs != NULL, MTLK_ERR_NO_MEM)
3272 scan_cfg.txmm = txmm;
3273 scan_cfg.aocs = slow_ctx->aocs;
3274 scan_cfg.hw_tx_flctrl = nic->hw_tx_flctrl;
3275 scan_cfg.bss_cache = &slow_ctx->cache;
3276 scan_cfg.bss_data = &slow_ctx->bss_data;
3278 MTLK_START_STEP_IF(!is_slave_ap, core_slow_ctx, SCAN_INIT, MTLK_OBJ_PTR(slow_ctx),
3279 mtlk_scan_init, (&slow_ctx->scan, scan_cfg, nic->vap_handle))
3281 dot11h_api.aocs = slow_ctx->aocs;
3282 dot11h_api.txmm = txmm;
3283 dot11h_api.hw_tx_flctrl = nic->hw_tx_flctrl;
3285 MTLK_START_STEP_IF(!is_slave_ap, core_slow_ctx, DOT11H_INIT, MTLK_OBJ_PTR(slow_ctx),
3286 mtlk_dot11h_init, (mtlk_core_get_dfs(nic), NULL, &dot11h_api, nic->vap_handle))
3288 MTLK_START_STEP_VOID_IF(mtlk_vap_is_master(nic->vap_handle), core_slow_ctx, ADDBA_AGGR_LIM_INIT, MTLK_OBJ_PTR(slow_ctx),
3289 mtlk_reflim_init, (&slow_ctx->addba_lim_aggr, MTLK_ADDBA_DEF_MAX_AGGR_SUPPORTED))
3291 MTLK_START_STEP_VOID_IF(mtlk_vap_is_master(nic->vap_handle), core_slow_ctx, ADDBA_REORD_LIM_INIT, MTLK_OBJ_PTR(slow_ctx),
3292 mtlk_reflim_init, (&slow_ctx->addba_lim_reord, MTLK_ADDBA_DEF_MAX_REORD_SUPPORTED))
3294 if (mtlk_vap_is_master(nic->vap_handle)) {
3295 addba_lim_aggr = &slow_ctx->addba_lim_aggr;
3296 addba_lim_reord = &slow_ctx->addba_lim_reord;
3298 else {
3299 /* Limits are shared for all the VAPs on same HW */
3300 addba_lim_aggr = &mtlk_core_get_master(nic)->slow_ctx->addba_lim_aggr;
3301 addba_lim_reord = &mtlk_core_get_master(nic)->slow_ctx->addba_lim_reord;
3304 MTLK_START_STEP(core_slow_ctx, ADDBA_INIT, MTLK_OBJ_PTR(slow_ctx),
3305 mtlk_addba_init, (&slow_ctx->addba, txmm, addba_lim_aggr, addba_lim_reord, &slow_ctx->cfg.addba, nic->vap_handle))
3307 MTLK_START_STEP_IF(mtlk_vap_is_ap(nic->vap_handle), core_slow_ctx, WDS_INIT, MTLK_OBJ_PTR(slow_ctx),
3308 wds_init, (&slow_ctx->wds_mng, nic->vap_handle))
3310 MTLK_START_STEP_IF(!is_dut && !mtlk_vap_is_slave_ap(nic->vap_handle), core_slow_ctx, SET_DEFAULT_BAND, MTLK_OBJ_PTR(slow_ctx),
3311 mtlk_core_master_set_default_band, (nic))
3313 MTLK_START_STEP(core_slow_ctx, SET_DEFAULT_NET_MODE, MTLK_OBJ_PTR(slow_ctx),
3314 mtlk_core_set_default_net_mode, (nic))
3316 MTLK_START_STEP_IF(!is_slave_ap, core_slow_ctx, WATCHDOG_TIMER_START, MTLK_OBJ_PTR(slow_ctx),
3317 mtlk_osal_timer_set,
3318 (&slow_ctx->mac_watchdog_timer,
3319 MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_MAC_WATCHDOG_TIMER_PERIOD_MS)))
3321 MTLK_START_STEP_VOID(core_slow_ctx, SERIALIZER_ACTIVATE, MTLK_OBJ_PTR(slow_ctx),
3322 MTLK_NOACTION, ())
3324 MTLK_START_STEP_EX(core_slow_ctx, CORE_STAT_REQ_HANDLER, MTLK_OBJ_PTR(slow_ctx),
3325 mtlk_wssd_register_request_handler, (mtlk_vap_get_irbd(nic->vap_handle),
3326 _mtlk_core_stat_handle_request, HANDLE_T(slow_ctx)),
3327 slow_ctx->stat_irb_handle, slow_ctx->stat_irb_handle != NULL, MTLK_ERR_UNKNOWN);
3329 MTLK_START_FINALLY(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx))
3330 MTLK_START_RETURN(core_slow_ctx, MTLK_OBJ_PTR(slow_ctx), _mtlk_slow_ctx_stop, (slow_ctx, nic))
3333 MTLK_START_STEPS_LIST_BEGIN(core)
3334 MTLK_START_STEPS_LIST_ENTRY(core, WSS_CREATE)
3335 MTLK_START_STEPS_LIST_ENTRY(core, WSS_HCTNRs)
3336 MTLK_START_STEPS_LIST_ENTRY(core, SET_NET_STATE_IDLE)
3337 MTLK_START_STEPS_LIST_ENTRY(core, FLCTRL_ID_REGISTER)
3338 MTLK_START_STEPS_LIST_ENTRY(core, SLOW_CTX_START)
3339 MTLK_START_STEPS_LIST_ENTRY(core, DF_USER_SET_MAC_ADDR)
3340 MTLK_START_STEPS_LIST_ENTRY(core, RESET_STATS)
3341 MTLK_START_STEPS_LIST_ENTRY(core, SQ_START)
3342 MTLK_START_STEPS_LIST_ENTRY(core, MC_INIT)
3343 #ifdef MTCFG_RF_MANAGEMENT_MTLK
3344 MTLK_START_STEPS_LIST_ENTRY(core, RF_MGMT_START)
3345 #endif
3346 MTLK_START_STEPS_LIST_ENTRY(core, DUT_REGISTER)
3347 MTLK_START_STEPS_LIST_ENTRY(core, ADD_VAP)
3348 MTLK_START_STEPS_LIST_ENTRY(core, ABILITIES_INIT)
3349 MTLK_START_STEPS_LIST_ENTRY(core, SET_NET_STATE_READY)
3350 MTLK_START_STEPS_LIST_ENTRY(core, COEX_20_40_INIT)
3351 MTLK_START_STEPS_LIST_ENTRY(core, UPDATE_PARAM_DB)
3352 MTLK_START_STEPS_LIST_ENTRY(core, SET_VAP_MIBS)
3353 MTLK_START_INNER_STEPS_BEGIN(core)
3354 MTLK_START_STEPS_LIST_END(core);
3356 static void
3357 _mtlk_core_stop (mtlk_vap_handle_t vap_handle)
3359 mtlk_core_t *nic = mtlk_vap_get_core (vap_handle);
3360 mtlk_hw_state_e hw_state = mtlk_core_get_hw_state(nic);
3361 int i;
3363 ILOG0_D("CID-%04x: stop", mtlk_vap_get_oid(vap_handle));
3365 /*send RMMOD event to application*/
3366 if ((hw_state != MTLK_HW_STATE_EXCEPTION) &&
3367 (hw_state != MTLK_HW_STATE_APPFATAL) &&
3368 (hw_state != MTLK_HW_STATE_MAC_ASSERTED)) {
3369 ILOG4_V("RMMOD send event");
3370 mtlk_df_ui_notify_notify_rmmod(mtlk_df_get_name(mtlk_vap_get_df(vap_handle)));
3373 MTLK_STOP_BEGIN(core, MTLK_OBJ_PTR(nic))
3374 MTLK_STOP_STEP(core, SET_VAP_MIBS, MTLK_OBJ_PTR(nic),
3375 MTLK_NOACTION, ())
3377 MTLK_STOP_STEP(core, UPDATE_PARAM_DB, MTLK_OBJ_PTR(nic),
3378 MTLK_NOACTION, ())
3380 MTLK_STOP_STEP(core, COEX_20_40_INIT, MTLK_OBJ_PTR(nic),
3381 _mtlk_core_delete_20_40, (nic))
3383 MTLK_STOP_STEP(core, SET_NET_STATE_READY, MTLK_OBJ_PTR(nic),
3384 MTLK_NOACTION, ())
3386 MTLK_STOP_STEP(core, ABILITIES_INIT, MTLK_OBJ_PTR(nic),
3387 mtlk_core_abilities_unregister, (nic))
3389 MTLK_STOP_STEP(core, ADD_VAP, MTLK_OBJ_PTR(nic),
3390 mtlk_mbss_send_vap_delete, (nic))
3392 MTLK_STOP_STEP(core, DUT_REGISTER, MTLK_OBJ_PTR(nic),
3393 mtlk_dut_core_unregister, (nic));
3395 #ifdef MTCFG_RF_MANAGEMENT_MTLK
3396 MTLK_STOP_STEP(core, RF_MGMT_START, MTLK_OBJ_PTR(nic),
3397 mtlk_rf_mgmt_stop, (nic->rf_mgmt))
3398 #endif
3400 MTLK_STOP_STEP(core, MC_INIT, MTLK_OBJ_PTR(nic),
3401 MTLK_NOACTION, ())
3403 MTLK_STOP_STEP(core, SQ_START, MTLK_OBJ_PTR(nic),
3404 mtlk_sq_stop, (nic->sq));
3406 MTLK_STOP_STEP(core, RESET_STATS, MTLK_OBJ_PTR(nic),
3407 MTLK_NOACTION, ())
3409 MTLK_STOP_STEP(core, DF_USER_SET_MAC_ADDR, MTLK_OBJ_PTR(nic),
3410 MTLK_NOACTION, ())
3412 MTLK_STOP_STEP(core, SLOW_CTX_START, MTLK_OBJ_PTR(nic),
3413 _mtlk_slow_ctx_stop, (nic->slow_ctx, nic))
3415 MTLK_STOP_STEP(core, FLCTRL_ID_REGISTER, MTLK_OBJ_PTR(nic),
3416 mtlk_flctrl_unregister, (nic->hw_tx_flctrl, nic->flctrl_id))
3418 nic->flctrl_id = 0;
3420 MTLK_STOP_STEP(core, SET_NET_STATE_IDLE, MTLK_OBJ_PTR(nic),
3421 MTLK_NOACTION, ())
3422 MTLK_STOP_STEP(core, WSS_HCTNRs, MTLK_OBJ_PTR(nic),
3423 mtlk_wss_cntrs_close, (nic->wss, nic->wss_hcntrs, ARRAY_SIZE(nic->wss_hcntrs)))
3424 MTLK_STOP_STEP(core, WSS_CREATE, MTLK_OBJ_PTR(nic),
3425 mtlk_wss_delete, (nic->wss));
3426 MTLK_STOP_END(core, MTLK_OBJ_PTR(nic))
3428 for (i = 0; i < ARRAY_SIZE(nic->txmm_async_eeprom_msgs); i++) {
3429 mtlk_txmm_msg_cancel(&nic->txmm_async_eeprom_msgs[i]);
3433 static int
3434 _mtlk_core_start (mtlk_vap_handle_t vap_handle)
3436 mtlk_core_t *nic = mtlk_vap_get_core (vap_handle);
3437 uint8 mac_addr[ETH_ALEN];
3438 #ifdef MTCFG_RF_MANAGEMENT_MTLK
3439 mtlk_rf_mgmt_cfg_t rf_mgmt_cfg = {0};
3440 #endif
3441 MTLK_ASSERT(ARRAY_SIZE(nic->wss_hcntrs) == MTLK_CORE_CNT_LAST);
3442 MTLK_ASSERT(ARRAY_SIZE(_mtlk_core_wss_id_map) == MTLK_CORE_CNT_LAST);
3444 MTLK_START_TRY(core, MTLK_OBJ_PTR(nic))
3445 MTLK_START_STEP_EX(core, WSS_CREATE, MTLK_OBJ_PTR(nic),
3446 mtlk_wss_create, (mtlk_vap_get_hw_wss(vap_handle), _mtlk_core_wss_id_map, ARRAY_SIZE(_mtlk_core_wss_id_map)),
3447 nic->wss, nic->wss != NULL, MTLK_ERR_NO_MEM);
3449 MTLK_START_STEP(core, WSS_HCTNRs, MTLK_OBJ_PTR(nic),
3450 mtlk_wss_cntrs_open, (nic->wss, _mtlk_core_wss_id_map, nic->wss_hcntrs, MTLK_CORE_CNT_LAST));
3451 MTLK_START_STEP(core, SET_NET_STATE_IDLE, MTLK_OBJ_PTR(nic),
3452 mtlk_core_set_net_state, (nic, NET_STATE_IDLE))
3454 nic->flctrl_id = 0;
3456 MTLK_START_STEP(core, FLCTRL_ID_REGISTER, MTLK_OBJ_PTR(nic),
3457 mtlk_flctrl_register, (nic->hw_tx_flctrl, &nic->flctrl_id))
3459 MTLK_START_STEP(core, SLOW_CTX_START, MTLK_OBJ_PTR(nic),
3460 _mtlk_slow_ctx_start, (nic->slow_ctx, nic))
3462 mtlk_pdb_get_mac(
3463 mtlk_vap_get_param_db(vap_handle), PARAM_DB_CORE_MAC_ADDR, mac_addr);
3465 MTLK_START_STEP_VOID(core, DF_USER_SET_MAC_ADDR, MTLK_OBJ_PTR(nic),
3466 mtlk_df_ui_set_mac_addr, (mtlk_vap_get_df(vap_handle), mac_addr))
3468 MTLK_START_STEP_VOID(core, RESET_STATS, MTLK_OBJ_PTR(nic),
3469 _mtlk_core_reset_stats_internal, (nic))
3471 /* The Master DF is always used here */
3472 MTLK_START_STEP_IF(!mtlk_vap_is_slave_ap(vap_handle), core, SQ_START, MTLK_OBJ_PTR(nic),
3473 mtlk_sq_start, (nic->sq, mtlk_vap_get_manager(vap_handle)) );
3475 MTLK_START_STEP_VOID(core, MC_INIT, MTLK_OBJ_PTR(nic),
3476 mtlk_mc_init, (nic))
3478 #ifdef MTCFG_RF_MANAGEMENT_MTLK
3479 rf_mgmt_cfg.txmm = mtlk_vap_get_txmm(vap_handle);
3480 rf_mgmt_cfg.stadb = &nic->slow_ctx->stadb;
3481 rf_mgmt_cfg.irbd = mtlk_vap_get_irbd(vap_handle);
3482 rf_mgmt_cfg.context = HANDLE_T(nic);
3483 rf_mgmt_cfg.device_is_busy = mtlk_core_is_device_busy;
3485 mtlk_rf_mgmt_configure(nic->rf_mgmt, &rf_mgmt_cfg);
3486 MTLK_START_STEP(core, RF_MGMT_START, MTLK_OBJ_PTR(nic),
3487 mtlk_rf_mgmt_start, (nic->rf_mgmt));
3488 #endif
3490 MTLK_START_STEP(core, DUT_REGISTER, MTLK_OBJ_PTR(nic),
3491 mtlk_dut_core_register, (nic));
3493 MTLK_START_STEP_IF(mtlk_vap_is_ap(vap_handle),
3494 core, ADD_VAP, MTLK_OBJ_PTR(nic),
3495 mtlk_mbss_send_vap_add, (nic))
3497 MTLK_START_STEP(core, ABILITIES_INIT, MTLK_OBJ_PTR(nic),
3498 mtlk_core_abilities_register, (nic))
3500 MTLK_START_STEP(core, SET_NET_STATE_READY, MTLK_OBJ_PTR(nic),
3501 mtlk_core_set_net_state, (nic, NET_STATE_READY))
3503 MTLK_START_STEP_IF(mtlk_vap_is_master(nic->vap_handle), core, COEX_20_40_INIT, MTLK_OBJ_PTR(nic),
3504 _mtlk_core_create_20_40, (nic))
3506 MTLK_START_STEP(core, UPDATE_PARAM_DB, MTLK_OBJ_PTR(nic),
3507 _mtlk_core_update_param_db, (nic))
3509 mtlk_core_init_defaults(nic);
3511 MTLK_START_STEP_IF(mtlk_vap_is_ap(vap_handle),
3512 core, SET_VAP_MIBS, MTLK_OBJ_PTR(nic),
3513 mtlk_set_vap_mibs, (nic))
3515 MTLK_START_FINALLY(core, MTLK_OBJ_PTR(nic))
3516 MTLK_START_RETURN(core, MTLK_OBJ_PTR(nic), _mtlk_core_stop, (vap_handle))
3519 static int
3520 _mtlk_core_release_tx_data (mtlk_vap_handle_t vap_handle, const mtlk_core_release_tx_data_t *data)
3522 int res = MTLK_ERR_UNKNOWN;
3523 mtlk_core_t *nic = mtlk_vap_get_core (vap_handle);
3524 mtlk_nbuf_t *nbuf = data->nbuf;
3525 unsigned short qos = 0;
3526 mtlk_nbuf_priv_t *nbuf_priv = mtlk_nbuf_priv(nbuf);
3527 sta_entry *sta = NULL; /* NOTE: nbuf is referencing STA, so it is safe to use this STA
3528 * while nbuf isn't released. */
3529 mtlk_sq_peer_ctx_t *sq_ppeer = NULL;
3531 /* All the packets on AP and non BC packets on STA */
3532 if (mtlk_vap_is_ap(nic->vap_handle) ||
3533 mtlk_nbuf_priv_check_flags(nbuf_priv, MTLK_NBUFF_UNICAST | MTLK_NBUFF_RMCAST)) {
3534 sta = mtlk_nbuf_priv_get_dst_sta(nbuf_priv);
3537 #if defined(MTCFG_PER_PACKET_STATS) && defined (MTCFG_TSF_TIMER_ACCESS_ENABLED)
3538 mtlk_nbuf_priv_stats_set(nbuf_priv, MTLK_NBUF_STATS_TS_FW_OUT, mtlk_hw_get_timestamp(vap_handle));
3539 #endif
3541 // check if NULL packet confirmed
3542 if (data->size == 0) {
3543 ILOG9_V("Confirmation for NULL nbuf");
3544 goto FINISH;
3547 qos = mtlk_qos_get_ac_by_tid(data->access_category);
3549 if ((qos != (uint16)-1) && (nic->pstats.ac_used_counter[qos] > 0))
3550 --nic->pstats.ac_used_counter[qos];
3552 res = MTLK_ERR_OK;
3554 FINISH:
3555 if (data->resources_free) {
3556 if (__UNLIKELY(!mtlk_flctrl_is_data_flowing(nic->hw_tx_flctrl))) {
3557 ILOG2_V("mtlk_flctrl_wake on OS TX queue wake");
3558 mtlk_flctrl_start_data(nic->hw_tx_flctrl, nic->flctrl_id);
3559 } else {
3560 mtlk_sq_schedule_flush(nic);
3564 // If confirmed (or failed) unicast packet to known STA
3565 if (NULL != sta ) {
3566 /* this is unicast or reliable multicast being transmitted */
3567 sq_ppeer = &sta->sq_peer_ctx;
3569 if (__LIKELY(data->status == UMI_OK)) {
3570 /* Update STA's timestamp on successful (confirmed by ACK) TX */
3571 mtlk_sta_on_packet_sent(sta, nbuf, data->nof_retries);
3573 #ifndef MBSS_FORCE_NO_CHANNEL_SWITCH
3574 if (mtlk_vap_is_ap(vap_handle) && (qos != (uint16)-1)) {
3575 mtlk_aocs_on_tx_msdu_returned(mtlk_core_get_master(nic)->slow_ctx->aocs, qos);
3577 #endif
3578 } else {
3579 mtlk_sta_on_packet_dropped(sta, MTLK_TX_DISCARDED_FW);
3581 } else {
3582 MTLK_ASSERT(FALSE == mtlk_nbuf_priv_check_flags(nbuf_priv, MTLK_NBUFF_UNICAST | MTLK_NBUFF_RMCAST));
3583 /* this should be broadcast or non-reliable multicast packet */
3584 sq_ppeer = &nic->sq_broadcast_ctx;
3585 if (__LIKELY(data->status == UMI_OK)) {
3586 if(mtlk_nbuf_priv_check_flags(nbuf_priv, MTLK_NBUFF_MULTICAST)) {
3587 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_MULTICAST_PACKETS_SENT);
3588 mtlk_core_add_cnt(nic, MTLK_CORE_CNT_MULTICAST_BYTES_SENT, mtlk_df_nbuf_get_data_length(nbuf));
3590 else if (mtlk_nbuf_priv_check_flags(nbuf_priv, MTLK_NBUFF_BROADCAST)) {
3591 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_BROADCAST_PACKETS_SENT);
3592 mtlk_core_add_cnt(nic, MTLK_CORE_CNT_BROADCAST_BYTES_SENT, mtlk_df_nbuf_get_data_length(nbuf));
3595 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_PACKETS_SENT);
3596 mtlk_core_add_cnt(nic, MTLK_CORE_CNT_BYTES_SENT, mtlk_df_nbuf_get_data_length(nbuf));
3597 nic->pstats.tx_bcast_nrmcast++;
3598 } else {
3599 mtlk_core_inc_cnt(nic, MTLK_CORE_CNT_TX_PACKETS_DISCARDED_FW);
3603 /* use access_category from nbuf_priv instead of the qos */
3604 mtlk_sq_on_tx_cfm(sq_ppeer, mtlk_nbuf_priv_get_tx_pck_ac(nbuf_priv));
3606 #if defined(MTCFG_PRINT_PER_PACKET_STATS)
3607 mtlk_nbuf_priv_stats_dump(nbuf_priv);
3608 #endif
3610 /* Release net buffer
3611 * WARNING: we can't do it before since we use STA referenced by this packet on FINISH.
3613 mtlk_df_nbuf_free(mtlk_vap_get_manager(nic->vap_handle), nbuf);
3615 /* update used Tx MSDUs counter */
3616 #ifndef MBSS_FORCE_NO_CHANNEL_SWITCH
3617 if (qos != (uint16)-1) {
3618 if(mtlk_vap_is_ap(vap_handle)) {
3619 mtlk_aocs_msdu_tx_dec_nof_used(mtlk_core_get_master(nic)->slow_ctx->aocs, qos);
3622 #endif
3624 return res;
3627 static int
3628 _mtlk_core_handle_rx_data (mtlk_vap_handle_t vap_handle, mtlk_core_handle_rx_data_t *data)
3630 mtlk_nbuf_t *nbuf = data->nbuf;
3631 ASSERT(nbuf != 0);
3633 mtlk_df_nbuf_put(nbuf, data->offset);
3634 mtlk_df_nbuf_pull(nbuf, data->offset);
3636 return handle_rx_ind(mtlk_vap_get_core (vap_handle), nbuf, (uint16)data->size, data->info);
3639 void __MTLK_IFUNC
3640 mtlk_core_set_pm_enabled (mtlk_core_t *core, BOOL enabled)
3642 uint32 limit, stas_in_ps_mode;
3643 mtlk_sq_peer_ctx_t *ppeer;
3645 MTLK_ASSERT(NULL != core);
3647 /* Increase/decrease counter for number of STAs in PS mode */
3648 if (enabled) {
3649 mtlk_osal_atomic_inc(&core->stas_in_ps_mode);
3650 } else {
3651 mtlk_osal_atomic_dec(&core->stas_in_ps_mode);
3654 ppeer = &core->sq_broadcast_ctx;
3655 stas_in_ps_mode = mtlk_osal_atomic_get(&core->stas_in_ps_mode);
3657 /* Calculate queue limit depending of PS mode */
3658 limit = stas_in_ps_mode ? MIN(MTLK_PACKETS_IN_MAC_DURING_PM, ppeer->limit_cfg)
3659 : ppeer->limit_cfg;
3661 mtlk_osal_atomic_set(&ppeer->limit, limit);
3663 mtlk_osal_atomic_set(&ppeer->ps_mode_enabled, (stas_in_ps_mode > 0) ? TRUE : FALSE);
3666 static int __MTLK_IFUNC
3667 _handle_pm_update_event(mtlk_handle_t object, const void *data, uint32 data_size)
3669 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3670 const UMI_PM_UPDATE *pm_update = (const UMI_PM_UPDATE *)data;
3671 sta_entry *sta;
3672 BOOL enabled = pm_update->newPowerMode == UMI_STATION_IN_PS;
3674 MTLK_ASSERT(sizeof(UMI_PM_UPDATE) == data_size);
3676 ILOG2_DY("Power management mode changed to %d for %Y",
3677 pm_update->newPowerMode, pm_update->sStationID.au8Addr);
3679 sta = mtlk_stadb_find_sta(&nic->slow_ctx->stadb, pm_update->sStationID.au8Addr);
3680 if (sta == NULL) {
3681 ILOG2_Y("PM update event received from STA %Y which is not known",
3682 pm_update->sStationID.au8Addr);
3683 return MTLK_ERR_OK;
3686 if (mtlk_osal_atomic_get(&sta->sq_peer_ctx.ps_mode_enabled) != enabled) { /* skip duplicated pm events */
3687 mtlk_sta_set_pm_enabled(sta, enabled);
3688 mtlk_core_set_pm_enabled(nic, enabled);
3691 mtlk_sta_decref(sta); /* De-reference of find */
3693 if (pm_update->newPowerMode == UMI_STATION_ACTIVE)
3694 mtlk_sq_schedule_flush(nic);
3696 return MTLK_ERR_OK;
3699 static int __MTLK_IFUNC
3700 _handle_logger_init_failed_event(mtlk_handle_t object, const void *data, uint32 data_size)
3702 MTLK_UNREFERENCED_PARAM(object);
3703 MTLK_UNREFERENCED_PARAM(data);
3704 MTLK_UNREFERENCED_PARAM(data_size);
3706 MTLK_ASSERT(0 == data_size);
3708 ELOG_V("Firmware log will be unavailable due to firmware logger init failure");
3710 return MTLK_ERR_OK;
3713 static int __MTLK_IFUNC
3714 _handle_fw_debug_trace_event(mtlk_handle_t object, const void *data, uint32 data_size)
3716 UmiDbgTraceInd_t *UmiDbgTraceInd = (UmiDbgTraceInd_t *) data;
3717 MTLK_UNREFERENCED_PARAM(object);
3718 MTLK_ASSERT(sizeof(UmiDbgTraceInd_t) >= data_size);
3719 MTLK_ASSERT(MAX_DBG_TRACE_DATA >= MAC_TO_HOST32(UmiDbgTraceInd->length));
3721 UmiDbgTraceInd->au8Data[MAX_DBG_TRACE_DATA - 1] = 0; // make sure it is NULL-terminated (although it should be without this)
3723 ILOG0_S("DBG TRACE: %s", UmiDbgTraceInd->au8Data);
3725 return MTLK_ERR_OK;
3728 static int
3729 _handle_ba_tx_status_event(mtlk_handle_t object, const void *data, uint32 data_size)
3731 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3732 UMI_BA_TX_STATUS *ba_tx = (UMI_BA_TX_STATUS*)data;
3733 sta_entry *sta;
3735 MTLK_ASSERT(NULL != nic);
3736 MTLK_ASSERT(NULL != data);
3737 MTLK_ASSERT(sizeof(UMI_BA_TX_STATUS) == data_size);
3739 ILOG2_DYDDDD("CID-%04x: BA status received for STA %Y TID=%d UMID=0x%04x I=%d ST=%d",
3740 mtlk_vap_get_oid(nic->vap_handle),
3741 ba_tx->sDA.au8Addr,
3742 MAC_TO_HOST16(ba_tx->u16AccessProtocol),
3743 MAC_TO_HOST16(ba_tx->u16MessageId),
3744 ba_tx->u8Initiator,
3745 ba_tx->u8Status);
3747 /* Try to find source MAC of transmitter */
3748 sta = mtlk_stadb_find_sta(&nic->slow_ctx->stadb, ba_tx->sDA.au8Addr);
3749 if (NULL == sta)
3751 ILOG1_DY("CID-%04x: BA status to unknown STA %Y, ignored",
3752 mtlk_vap_get_oid(nic->vap_handle), ba_tx->sDA.au8Addr);
3753 return MTLK_ERR_OK;
3756 mtlk_addba_peer_on_ba_tx_status(mtlk_sta_get_addb_peer(sta), ba_tx);
3758 mtlk_sta_decref(sta); /* De-reference of find */
3760 return MTLK_ERR_OK;
3763 static int
3764 _handle_ack_on_bar_event (mtlk_handle_t object, const void *data, uint32 data_size)
3766 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3767 uint16 tid;
3768 UMI_ACK_ON_BAR_EVENT *ack_on_bar = (UMI_ACK_ON_BAR_EVENT*)data;
3769 sta_entry *sta;
3771 MTLK_ASSERT(NULL != nic);
3772 MTLK_ASSERT(NULL != data);
3773 MTLK_ASSERT(sizeof(UMI_ACK_ON_BAR_EVENT) == data_size);
3775 tid = MAC_TO_HOST16(ack_on_bar->u16AccessProtocol);
3777 ILOG2_DYD("CID-%04x: ACK on BAR received for STA %Y TID=%d",
3778 mtlk_vap_get_oid(nic->vap_handle), ack_on_bar->sDA.au8Addr, tid);
3780 /* Try to find source MAC of transmitter */
3781 sta = mtlk_stadb_find_sta(&nic->slow_ctx->stadb, ack_on_bar->sDA.au8Addr);
3782 if (NULL == sta)
3784 ILOG1_DY("CID-%04x: ACK on BAR to unknown STA %Y, ignored",
3785 mtlk_vap_get_oid(nic->vap_handle), ack_on_bar->sDA.au8Addr);
3786 return MTLK_ERR_OK;
3789 mtlk_addba_peer_on_ack_on_bar(mtlk_sta_get_addb_peer(sta), tid);
3791 mtlk_sta_decref(sta); /* De-reference of find */
3793 return MTLK_ERR_OK;
3796 static int __MTLK_IFUNC
3797 _handle_aocs_tcp_event(mtlk_handle_t core_object, const void *data, uint32 data_size)
3799 mtlk_core_t* core = HANDLE_T_PTR(mtlk_core_t, core_object);
3801 MTLK_UNREFERENCED_PARAM(data_size);
3803 if (mtlk_vap_is_master_ap(core->vap_handle)) {
3804 mtlk_aocs_indicate_event(core->slow_ctx->aocs,
3805 MTLK_AOCS_EVENT_TCP_IND, (void*) data, data_size);
3808 return MTLK_ERR_OK;
3811 static int __MTLK_IFUNC
3812 _handle_fw_interference_ind (mtlk_handle_t core_object, const void *data, uint32 data_size)
3814 int8 det_threshold;
3815 mtlk_core_t* core = HANDLE_T_PTR(mtlk_core_t, core_object);
3816 const UMI_INTERFERER *interferer_ind = (const UMI_INTERFERER *)data;
3818 MTLK_ASSERT(sizeof(UMI_INTERFERER) == data_size);
3820 if (mtlk_vap_is_master_ap(core->vap_handle)) {
3821 if (core->is_stopped) {
3822 ILOG5_V("UMI_INTERFERER event while core is down");
3823 return MTLK_ERR_OK; /* do not process */
3826 if (!mtlk_core_is_interfdet_enabled(core)) {
3827 ILOG5_V("UMI_INTERFERER event while interference detection is deactivated");
3828 return MTLK_ERR_OK; /* do not process */
3831 if (SPECTRUM_40MHZ == _mtlk_core_get_user_spectrum_mode(core)){
3832 /* Use 40MHz thresold if user choose 40MHz explicitly */
3833 det_threshold = MTLK_CORE_PDB_GET_INT(core, PARAM_DB_INTERFDET_40MHZ_DETECTION_THRESHOLD);
3834 }else{
3835 /* Use 20MHZ threshold for 20MHz and 20/40 Auto and coexistance */
3836 det_threshold = MTLK_CORE_PDB_GET_INT(core, PARAM_DB_INTERFDET_20MHZ_DETECTION_THRESHOLD);
3839 if (interferer_ind->maximumValue > det_threshold) {
3840 ILOG0_DDD("CID-%04x: Interference is detected on channel %d with Metric %d", mtlk_vap_get_oid(core->vap_handle),
3841 interferer_ind->channel, interferer_ind->maximumValue);
3843 bt_acs_send_interf_event(interferer_ind->channel, interferer_ind->maximumValue);
3844 mtlk_aocs_indicate_event(core->slow_ctx->aocs,
3845 MTLK_AOCS_EVENT_INTERF_IND, (void*)data, data_size);
3847 mtlk_aocs_indicate_event(core->slow_ctx->aocs,
3848 MTLK_AOCS_EVENT_INTERF_STAT, (void*)data, data_size);
3851 return MTLK_ERR_OK;
3854 static int __MTLK_IFUNC
3855 _handle_fw_dfs_end (mtlk_handle_t core_object, const void *data, uint32 data_size)
3857 mtlk_core_t* core = HANDLE_T_PTR(mtlk_core_t, core_object);
3859 MTLK_UNREFERENCED_PARAM(data);
3860 MTLK_UNREFERENCED_PARAM(data_size);
3862 mtlk_dot11h_initial_wait_end(mtlk_core_get_dfs(core));
3863 (void)mtlk_coc_set_power_mode(core->slow_ctx->coc_mngmt,
3864 mtlk_coc_get_auto_mode_cfg(core->slow_ctx->coc_mngmt));
3866 return MTLK_ERR_OK;
3869 static int __MTLK_IFUNC
3870 _mtlk_process_mac_hang(mtlk_core_t* nic, mtlk_hw_state_e hw_state, uint32 fw_cpu)
3872 int res = MTLK_ERR_OK;
3874 if(!core_get_is_mac_fatal_pending(nic))
3876 /* Firmware is already recovered */
3877 goto finish;
3880 mtlk_core_set_net_state(nic, NET_STATE_HALTED);
3881 mtlk_set_hw_state(nic, hw_state);
3882 nic->slow_ctx->mac_stuck_detected_by_sw = 0;
3883 WLOG_DD("CID-%04x: MAC Hang detected, event = %d", mtlk_vap_get_oid(nic->vap_handle), hw_state);
3884 mtlk_df_ui_notify_notify_fw_hang(mtlk_vap_get_df(nic->vap_handle), fw_cpu, hw_state);
3886 finish:
3888 return res;
3891 static int
3892 _mtlk_process_mac_fatal_log (mtlk_core_t *nic, APP_FATAL *app_fatal)
3894 int res = MTLK_ERR_OK;
3895 mtlk_log_event_t log_event;
3897 log_event.timestamp = MAC_TO_HOST32(app_fatal->uTimeStamp);
3898 log_event.info = LOG_MAKE_INFO(0, /* version */
3899 MAC_TO_HOST32(app_fatal->OriginId), /* firmware OID */
3900 MAC_TO_HOST32(app_fatal->GroupId)); /* firmware GID */
3901 log_event.info_ex = LOG_MAKE_INFO_EX(MAC_TO_HOST32(app_fatal->FileId), /* firmware FID */
3902 MAC_TO_HOST32(app_fatal->uCauseRegOrLineNum), /* firmware LID */
3903 0, /* data size */
3904 MAC_TO_HOST32(app_fatal->FWinterface)); /* firmware wlanif */
3906 #if (RTLOG_FLAGS & RTLF_REMOTE_ENABLED)
3907 mtlk_vap_get_hw_vft(nic->vap_handle)->set_prop(nic->vap_handle, MTLK_HW_LOG,
3908 &log_event, sizeof(log_event) + 0 /* data size */);
3909 #else
3910 MTLK_UNREFERENCED_PARAM(nic);
3911 MTLK_UNREFERENCED_PARAM(app_fatal);
3912 #endif
3914 res = mtlk_nl_send_brd_msg(&log_event,
3915 sizeof(log_event),
3916 GFP_ATOMIC,
3917 NETLINK_LOGSERVER_GROUP,
3918 NL_DRV_IRBM_NOTIFY);
3920 if (MTLK_ERR_OK != res) {
3921 ELOG_V("Unable to notify LogServer");
3924 return res;
3927 static int __MTLK_IFUNC
3928 _mtlk_handle_mac_exception(mtlk_handle_t object, const void *data, uint32 data_size)
3930 APP_FATAL *app_fatal = (APP_FATAL*)data;
3931 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3932 _mtlk_process_mac_hang(nic, MTLK_HW_STATE_EXCEPTION, MAC_TO_HOST32(app_fatal->uLmOrUm));
3934 return MTLK_ERR_OK;
3937 static int __MTLK_IFUNC
3938 _mtlk_handle_mac_exception_sync(mtlk_handle_t object, const void *data, uint32 data_size)
3940 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3941 MTLK_ASSERT(sizeof(APP_FATAL) == data_size);
3943 core_set_is_mac_fatal_pending(nic, TRUE);
3945 mtlk_cc_handle_mac_exception(nic->vap_handle, (const APP_FATAL*) data);
3946 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_mac_exception, HANDLE_T(nic), data, data_size);
3948 return MTLK_ERR_OK;
3951 static int __MTLK_IFUNC
3952 _mtlk_handle_mac_fatal(mtlk_handle_t object, const void *data, uint32 data_size)
3954 APP_FATAL *app_fatal = (APP_FATAL*)data;
3955 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3956 _mtlk_process_mac_fatal_log(nic, app_fatal);
3957 _mtlk_process_mac_hang(nic, MTLK_HW_STATE_APPFATAL, MAC_TO_HOST32(app_fatal->uLmOrUm));
3959 return MTLK_ERR_OK;
3962 static int __MTLK_IFUNC
3963 _mtlk_handle_mac_fatal_sync(mtlk_handle_t object, const void *data, uint32 data_size)
3965 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3966 MTLK_ASSERT(sizeof(APP_FATAL) == data_size);
3968 core_set_is_mac_fatal_pending(nic, TRUE);
3970 mtlk_cc_handle_mac_fatal(nic->vap_handle, (const APP_FATAL*) data);
3972 if (rcvry_is_in_progress(mtlk_vap_get_rcvry(nic->vap_handle))) {
3973 _mtlk_process_emergency_task(nic, _mtlk_handle_mac_fatal, HANDLE_T(nic), data, data_size);
3975 else {
3976 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_mac_fatal, HANDLE_T(nic), data, data_size);
3979 return MTLK_ERR_OK;
3982 static int __MTLK_IFUNC
3983 _mtlk_handle_eeprom_failure_sync(mtlk_handle_t object, const void *data, uint32 data_size)
3985 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
3986 MTLK_ASSERT(sizeof(EEPROM_FAILURE_EVENT) == data_size);
3988 mtlk_cc_handle_eeprom_failure(nic->vap_handle, (const EEPROM_FAILURE_EVENT*) data);
3990 return MTLK_ERR_OK;
3993 static int __MTLK_IFUNC
3994 _mtlk_handle_generic_event(mtlk_handle_t object, const void *data, uint32 data_size)
3996 MTLK_ASSERT(sizeof(GENERIC_EVENT) == data_size);
3997 mtlk_cc_handle_generic_event(HANDLE_T_PTR(mtlk_core_t, object)->vap_handle, (GENERIC_EVENT*) data);
3998 return MTLK_ERR_OK;
4001 static int __MTLK_IFUNC
4002 _mtlk_handle_algo_failure(mtlk_handle_t object, const void *data, uint32 data_size)
4004 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, object);
4006 MTLK_ASSERT(sizeof(CALIBR_ALGO_EVENT) == data_size);
4008 mtlk_cc_handle_algo_calibration_failure(nic->vap_handle, (const CALIBR_ALGO_EVENT*)data);
4010 return MTLK_ERR_OK;
4013 static int __MTLK_IFUNC
4014 _mtlk_handle_dummy_event(mtlk_handle_t object, const void *data, uint32 data_size)
4016 MTLK_ASSERT(sizeof(DUMMY_EVENT) == data_size);
4017 mtlk_cc_handle_dummy_event(HANDLE_T_PTR(mtlk_core_t, object)->vap_handle, (const DUMMY_EVENT*) data);
4018 return MTLK_ERR_OK;
4021 static int __MTLK_IFUNC
4022 _mtlk_handle_unknown_event(mtlk_handle_t object, const void *data, uint32 data_size)
4024 MTLK_ASSERT(sizeof(uint32) == data_size);
4025 mtlk_cc_handle_unknown_event(HANDLE_T_PTR(mtlk_core_t, object)->vap_handle, *(uint32*)data);
4026 return MTLK_ERR_OK;
4029 static void __MTLK_IFUNC
4030 _mtlk_handle_mac_event(mtlk_core_t *nic,
4031 MAC_EVENT *event)
4033 uint32 event_id = MAC_TO_HOST32(event->u32EventID) & 0xff;
4035 switch(event_id)
4037 case EVENT_EXCEPTION:
4038 _mtlk_process_hw_task(nic, SYNCHRONOUS, _mtlk_handle_mac_exception_sync,
4039 HANDLE_T(nic), &event->u.sAppFatalEvent, sizeof(APP_FATAL));
4040 break;
4041 case EVENT_EEPROM_FAILURE:
4042 _mtlk_process_hw_task(nic, SYNCHRONOUS, _mtlk_handle_eeprom_failure_sync,
4043 HANDLE_T(nic), &event->u.sEepromEvent, sizeof(EEPROM_FAILURE_EVENT));
4044 break;
4045 case EVENT_APP_FATAL:
4046 _mtlk_process_hw_task(nic, SYNCHRONOUS, _mtlk_handle_mac_fatal_sync,
4047 HANDLE_T(nic), &event->u.sAppFatalEvent, sizeof(APP_FATAL));
4048 break;
4049 case EVENT_GENERIC_EVENT:
4050 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_generic_event,
4051 HANDLE_T(nic), &event->u.sGenericData, sizeof(GENERIC_EVENT));
4052 break;
4053 case EVENT_CALIBR_ALGO_FAILURE:
4054 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_algo_failure,
4055 HANDLE_T(nic), &event->u.sCalibrationEvent, sizeof(CALIBR_ALGO_EVENT));
4056 break;
4057 case EVENT_DUMMY:
4058 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_dummy_event,
4059 HANDLE_T(nic), &event->u.sDummyEvent, sizeof(DUMMY_EVENT));
4060 break;
4061 default:
4062 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_unknown_event,
4063 HANDLE_T(nic), &event_id, sizeof(uint32));
4064 break;
4068 static int __MTLK_IFUNC
4069 _mtlk_handle_unknown_ind_type(mtlk_handle_t object, const void *data, uint32 data_size)
4071 MTLK_ASSERT(sizeof(uint32) == data_size);
4073 ILOG0_DD("CID-%04x:Unknown MAC indication type %u", mtlk_vap_get_oid(HANDLE_T_PTR(mtlk_core_t, object)->vap_handle),
4074 *(uint32*)data);
4076 return MTLK_ERR_OK;
4079 static void
4080 _mtlk_core_handle_rx_ctrl (mtlk_vap_handle_t vap_handle,
4081 uint32 id,
4082 void *payload,
4083 uint32 payload_buffer_size)
4085 mtlk_core_t *nic = mtlk_vap_get_core (vap_handle);
4087 MTLK_ASSERT(NULL != nic);
4089 switch(id)
4091 case MC_MAN_DYNAMIC_PARAM_IND:
4092 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_dynamic_param_ind,
4093 HANDLE_T(nic), payload, sizeof(UMI_DYNAMIC_PARAM_TABLE));
4094 break;
4095 case MC_MAN_MAC_EVENT_IND:
4096 _mtlk_handle_mac_event(nic, (MAC_EVENT*)payload);
4097 break;
4098 case MC_MAN_NETWORK_EVENT_IND:
4099 _handle_network_event(nic, (UMI_NETWORK_EVENT*)payload);
4100 break;
4101 case MC_MAN_CONNECTION_EVENT_IND:
4102 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_fw_connection_event_indication,
4103 HANDLE_T(nic), payload, sizeof(UMI_CONNECTION_EVENT));
4104 break;
4105 case MC_MAN_VAP_WAS_REMOVED_IND:
4106 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_vap_removed_ind,
4107 HANDLE_T(nic), payload, sizeof(UMI_DEACTIVATE_VAP));
4108 break;
4109 case MC_MAN_SECURITY_ALERT_IND:
4110 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_security_alert_ind,
4111 HANDLE_T(nic), payload, sizeof(UMI_SECURITY_ALERT));
4112 break;
4113 case MC_MAN_PM_UPDATE_IND:
4114 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_pm_update_event,
4115 HANDLE_T(nic), payload, sizeof(UMI_PM_UPDATE));
4116 break;
4117 case MC_MAN_AOCS_IND:
4118 _mtlk_process_hw_task(nic, SYNCHRONOUS, _handle_aocs_tcp_event,
4119 HANDLE_T(nic), payload, payload_buffer_size);
4120 break;
4121 case MC_DBG_LOGGER_INIT_FAILD_IND:
4122 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_logger_init_failed_event,
4123 HANDLE_T(nic), payload, 0);
4124 break;
4125 case MC_MAN_TRACE_IND:
4126 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_fw_debug_trace_event,
4127 HANDLE_T(nic), payload, sizeof(UmiDbgTraceInd_t));
4128 break;
4129 case MC_MAN_BA_TX_STATUS_IND:
4130 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_ba_tx_status_event,
4131 HANDLE_T(nic), payload, sizeof(UMI_BA_TX_STATUS));
4132 break;
4133 case MC_MAN_ACK_ON_BAR_IND:
4134 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_ack_on_bar_event,
4135 HANDLE_T(nic), payload, sizeof(UMI_ACK_ON_BAR_EVENT));
4136 break;
4137 case MC_MAN_INTERFERER_IND:
4138 if (mtlk_core_scan_is_running(nic)){
4139 /* During scan the floor noise level must be updated directly, without serializer */ /* !!! ATT: please review this !!! */
4140 mtlk_aocs_scan_floor_noise_ind(nic->slow_ctx->aocs, (UMI_INTERFERER*)payload);
4142 else{
4143 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_fw_interference_ind,
4144 HANDLE_T(nic), payload, sizeof(UMI_INTERFERER));
4147 break;
4148 case MC_MAN_DFS_END_IND:
4149 _mtlk_process_hw_task(nic, SERIALIZABLE, _handle_fw_dfs_end,
4150 HANDLE_T(nic), payload, 0);
4151 break;
4152 default:
4153 _mtlk_process_hw_task(nic, SERIALIZABLE, _mtlk_handle_unknown_ind_type,
4154 HANDLE_T(nic), &id, sizeof(uint32));
4155 break;
4159 void __MTLK_IFUNC
4160 mtlk_core_handle_tx_ctrl (mtlk_vap_handle_t vap_handle,
4161 mtlk_user_request_t *req,
4162 uint32 id,
4163 mtlk_clpb_t *data)
4165 #define _MTLK_CORE_REQ_MAP_START(req_id) \
4166 switch (req_id) {
4168 #define _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(req_id, func) \
4169 case (req_id): \
4170 _mtlk_process_user_task(nic, req, SERIALIZABLE, req_id, func, HANDLE_T(nic), data); \
4171 break;
4173 #define _MTLK_CORE_HANDLE_REQ_SYNCHRONOUS(req_id, func) \
4174 case (req_id): \
4175 _mtlk_process_user_task(nic, req, SYNCHRONOUS, req_id, func, HANDLE_T(nic), data); \
4176 break;
4178 #define _MTLK_CORE_HANDLE_REQ_DUMPABLE(req_id, func) \
4179 case (req_id): \
4180 if (rcvry_is_dump_in_progress(mtlk_vap_get_rcvry(vap_handle))) { \
4181 _mtlk_process_user_task(nic, req, SYNCHRONOUS, req_id, func, HANDLE_T(nic), data); \
4183 else { \
4184 _mtlk_process_user_task(nic, req, SERIALIZABLE, req_id, func, HANDLE_T(nic), data); \
4186 break;
4188 #define _MTLK_CORE_REQ_MAP_END() \
4189 default: \
4190 MTLK_ASSERT(FALSE); \
4193 mtlk_core_t *nic = mtlk_vap_get_core(vap_handle);
4195 MTLK_ASSERT(NULL != nic);
4196 MTLK_ASSERT(NULL != req);
4197 MTLK_ASSERT(NULL != data);
4199 _MTLK_CORE_REQ_MAP_START(id)
4200 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AP_CAPABILITIES, _mtlk_core_get_ap_capabilities)
4201 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_ACTIVATE_OPEN, _mtlk_core_activate)
4202 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_CONNECT_STA, _mtlk_core_connect_sta)
4203 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_DISCONNECT_STA, _mtlk_core_hanle_disconnect_sta_req)
4204 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_AP_DISCONNECT_STA, _mtlk_core_ap_disconnect_sta)
4205 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_AP_DISCONNECT_ALL, _mtlk_core_ap_disconnect_all)
4206 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_DEACTIVATE, _mtlk_core_deactivate)
4207 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_START_SCANNING, _mtlk_core_start_scanning);
4208 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_SCANNING_RES, _mtlk_core_get_scanning_res);
4209 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_MAC_ADDR, _mtlk_core_set_mac_addr_wrapper);
4210 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_MAC_ADDR, _mtlk_core_get_mac_addr);
4211 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_STATUS, _mtlk_core_get_status);
4212 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_RESET_STATS, _mtlk_core_reset_stats);
4213 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_DELBA_REQ, _mtlk_core_set_delba_cfg);
4214 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_ADDBA_CFG, _mtlk_core_get_addba_cfg);
4215 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_ADDBA_CFG, _mtlk_core_set_addba_cfg);
4216 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_ADDBA_STATE, _mtlk_core_get_addba_state);
4217 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_WME_BSS_CFG, _mtlk_core_get_wme_bss_cfg);
4218 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_WME_BSS_CFG, _mtlk_core_set_wme_bss_cfg);
4219 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_WME_AP_CFG, _mtlk_core_get_wme_ap_cfg);
4220 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_WME_AP_CFG, _mtlk_core_set_wme_ap_cfg);
4221 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AOCS_CFG, _mtlk_core_get_aocs_cfg);
4222 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_AOCS_CFG, _mtlk_core_set_aocs_cfg);
4223 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_DOT11H_CFG, _mtlk_core_get_dot11h_cfg);
4224 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_DOT11H_CFG, _mtlk_core_set_dot11h_cfg);
4225 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_DOT11H_AP_CFG, _mtlk_core_get_dot11h_ap_cfg);
4226 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_DOT11H_AP_CFG, _mtlk_core_set_dot11h_ap_cfg);
4227 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_L2NAT_CLEAR_TABLE, _mtlk_core_l2nat_clear_table);
4228 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_ANTENNA_GAIN, _mtlk_core_get_ant_gain);
4229 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_MIBS_CFG, _mtlk_core_get_mibs_cfg);
4230 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_MIBS_CFG, _mtlk_core_set_mibs_cfg);
4231 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COUNTRY_CFG, _mtlk_core_get_country_cfg);
4232 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COUNTRY_CFG, _mtlk_core_set_country_cfg);
4233 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_L2NAT_CFG, _mtlk_core_get_l2nat_cfg);
4234 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_L2NAT_CFG, _mtlk_core_set_l2nat_cfg);
4235 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_WDS_CFG, _mtlk_core_set_wds_cfg);
4236 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_WDS_CFG, _mtlk_core_get_wds_cfg);
4237 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_WDS_PEERAP, _mtlk_core_get_wds_peer_ap);
4238 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_WDS_DBG, _mtlk_core_set_wds_dbg);
4239 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_DOT11D_CFG, _mtlk_core_get_dot11d_cfg);
4240 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_DOT11D_CFG, _mtlk_core_set_dot11d_cfg);
4241 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_MAC_WATCHDOG_CFG, _mtlk_core_get_mac_wdog_cfg);
4242 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_MAC_WATCHDOG_CFG, _mtlk_core_set_mac_wdog_cfg);
4243 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_STADB_CFG, _mtlk_core_get_stadb_cfg);
4244 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_STADB_CFG, _mtlk_core_set_stadb_cfg);
4245 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_SQ_CFG, _mtlk_core_get_sq_cfg);
4246 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_SQ_CFG, _mtlk_core_set_sq_cfg);
4247 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_CORE_CFG, _mtlk_core_get_core_cfg);
4248 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_CORE_CFG, _mtlk_core_set_core_cfg);
4249 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_MASTER_CFG, _mtlk_core_get_master_specific_cfg);
4250 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_MASTER_CFG, _mtlk_core_set_master_specific_cfg);
4251 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_EEPROM_CFG, _mtlk_core_get_eeprom_cfg);
4252 #ifdef EEPROM_DATA_VALIDATION
4253 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_EEPROM_FW, _mtlk_core_get_eeprom_fw);
4254 #endif /* EEPROM_DATA_VALIDATION */
4255 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_HSTDB_CFG, _mtlk_core_get_hstdb_cfg);
4256 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_HSTDB_CFG, _mtlk_core_set_hstdb_cfg);
4257 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_SCAN_CFG, _mtlk_core_get_scan_cfg);
4258 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_SCAN_CFG, _mtlk_core_set_scan_cfg);
4259 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_TX_POWER_LIMIT, _mtlk_core_get_tx_power_limit_cfg);
4260 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_HW_DATA_CFG, _mtlk_core_set_hw_data_cfg);
4261 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_QOS_CFG, _mtlk_core_get_qos_cfg);
4262 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_QOS_CFG, _mtlk_core_set_qos_cfg);
4263 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COC_CFG, _mtlk_core_get_coc_cfg);
4264 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COC_CFG, _mtlk_core_set_coc_cfg);
4265 #ifdef MTCFG_PMCU_SUPPORT
4266 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_PCOC_CFG, _mtlk_core_get_pcoc_cfg);
4267 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_PCOC_CFG, _mtlk_core_set_pcoc_cfg);
4268 #endif /*MTCFG_PMCU_SUPPORT*/
4269 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AOCS_TBL, _mtlk_core_get_aocs_table);
4270 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AOCS_CHANNELS_TBL, _mtlk_core_get_aocs_channels);
4271 #ifdef BT_ACS_DEBUG
4272 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_AOCS_CHANNELS_TBL_DBG, _mtlk_core_set_aocs_channels_dbg);
4273 #endif /* BT_ACS_DEBUG */
4274 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AOCS_HISTORY, _mtlk_core_get_aocs_history);
4275 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AOCS_PENALTIES, _mtlk_core_get_aocs_penalties);
4276 #ifdef AOCS_DEBUG
4277 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_AOCS_CL, _mtlk_core_get_aocs_debug_update_cl);
4278 #endif /* AOCS_DEBUG */
4279 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_HW_LIMITS, _mtlk_core_get_hw_limits);
4280 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_REG_LIMITS, _mtlk_core_get_reg_limits);
4281 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_STOP_LM, _mtlk_core_stop_lm);
4282 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_MAC_CALIBRATE, _mtlk_core_mac_calibrate);
4283 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_IW_GENERIC, _mtlk_core_get_iw_generic);
4284 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_CTRL_MAC_GPIO, _mtlk_core_ctrl_mac_gpio);
4285 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GEN_DATA_EXCHANGE, _mtlk_core_gen_data_exchange);
4286 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_EE_CAPS, _mtlk_core_get_ee_caps);
4287 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_L2NAT_STATS, _mtlk_core_get_l2nat_stats);
4288 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_SQ_STATUS, _mtlk_core_get_sq_status);
4289 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_MAC_ASSERT, _mtlk_core_set_mac_assert);
4290 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_MC_IGMP_TBL, _mtlk_core_get_mc_igmp_tbl);
4291 _MTLK_CORE_HANDLE_REQ_DUMPABLE(MTLK_CORE_REQ_GET_BCL_MAC_DATA, _mtlk_core_bcl_mac_data_get);
4292 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_BCL_MAC_DATA, _mtlk_core_bcl_mac_data_set);
4293 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_RANGE_INFO, _mtlk_core_range_info_get);
4294 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_STADB_STATUS, _mtlk_core_get_stadb_sta_list);
4295 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_WEP_ENC_CFG, _mtlk_core_set_wep_enc_cfg);
4296 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_WEP_ENC_CFG, _mtlk_core_get_wep_enc_cfg);
4297 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_AUTH_CFG, _mtlk_core_set_auth_cfg);
4298 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_AUTH_CFG, _mtlk_core_get_auth_cfg);
4299 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_GENIE_CFG, _mtlk_core_set_genie_cfg);
4300 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_ENCEXT_CFG, _mtlk_core_get_enc_ext_cfg);
4301 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_ENCEXT_CFG, _mtlk_core_set_enc_ext_cfg);
4302 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_MBSS_ADD_VAP, _mtlk_core_add_vap);
4303 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_MBSS_DEL_VAP, _mtlk_core_del_vap);
4304 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_MBSS_SET_VARS, _mtlk_core_set_mbss_vars);
4305 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_MBSS_GET_VARS, _mtlk_core_get_mbss_vars);
4306 _MTLK_CORE_HANDLE_REQ_SYNCHRONOUS(MTLK_CORE_REQ_GET_SERIALIZER_INFO, _mtlk_core_get_serializer_info);
4307 /* 20/40 coexistence feature */
4308 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COEX_20_40_RSSI_THR_CFG, _mtlk_core_set_coex_20_40_mode_cfg);
4309 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COEX_20_40_RSSI_THR_CFG, _mtlk_core_get_coex_20_40_mode_cfg);
4310 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COEX_20_40_MODE_CFG, _mtlk_core_set_coex_20_40_mode_cfg);
4311 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COEX_20_40_MODE_CFG, _mtlk_core_get_coex_20_40_mode_cfg);
4312 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COEX_20_40_AP_FORCE_PARAMS_CFG, _mtlk_core_set_coex_20_40_ap_force_params_cfg);
4313 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COEX_20_40_AP_FORCE_PARAMS_CFG, _mtlk_core_get_coex_20_40_ap_force_params_cfg);
4314 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COEX_20_40_STA_EXEMPTION_REQ_CFG, _mtlk_core_set_coex_20_40_exm_req_cfg);
4315 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COEX_20_40_STA_EXEMPTION_REQ_CFG, _mtlk_core_get_coex_20_40_exm_req_cfg);
4316 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COEX_20_40_AP_MIN_NUM_OF_EXM_STA_CFG, _mtlk_core_set_coex_20_40_min_num_exm_sta_cfg);
4317 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COEX_20_40_AP_MIN_NUM_OF_EXM_STA_CFG, _mtlk_core_get_coex_20_40_min_num_exm_sta_cfg);
4318 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_COEX_20_40_TIMES_CFG, _mtlk_core_set_coex_20_40_times_cfg);
4319 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_COEX_20_40_TIMES_CFG, _mtlk_core_get_coex_20_40_times_cfg);
4320 /* Interference Detection */
4321 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_INTERFDET_PARAMS_CFG, _mtlk_core_set_interfdet_cfg);
4322 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_INTERFDET_MODE_CFG, _mtlk_core_get_interfdet_mode_cfg);
4324 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_FW_LED_CFG, _mtlk_core_set_fw_led_cfg);
4325 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_FW_LED_CFG, _mtlk_core_get_fw_led_cfg);
4326 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_DBG_CLI, _mtlk_core_simple_cli);
4327 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_FW_DEBUG, _mtlk_core_fw_debug);
4328 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_FW_LOG_SEVERITY, _mtlk_core_set_fw_log_severity);
4329 /* Traffic Analyzer */
4330 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_TA_CFG, _mtlk_core_set_ta_cfg);
4331 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_TA_CFG, _mtlk_core_get_ta_cfg);
4333 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_ENHANCED11B_CFG, _mtlk_core_set_enhanced11b_cfg);
4334 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_ENHANCED11B_CFG, _mtlk_core_get_enhanced11b_cfg);
4336 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_11B_CFG, _mtlk_core_set_11b_cfg);
4337 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_11B_CFG, _mtlk_core_get_11b_cfg);
4339 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_DOT11W_CFG, _mtlk_core_set_dot11w_cfg);
4340 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_DOT11W_CFG, _mtlk_core_get_dot11w_cfg);
4342 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_RECOVERY_CFG, _mtlk_core_set_recovery_cfg);
4343 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_RECOVERY_CFG, _mtlk_core_get_recovery_cfg);
4345 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_MC_PS_SIZE_CFG, _mtlk_core_set_mc_ps_size_cfg);
4346 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_MC_PS_SIZE_CFG, _mtlk_core_get_mc_ps_size_cfg);
4348 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_UAPSD_MODE, _mtlk_core_get_uapsd_mode);
4349 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_UAPSD_MODE, _mtlk_core_set_uapsd_mode);
4351 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_SET_UAPSD_CFG, _mtlk_core_set_uapsd_cfg);
4352 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_UAPSD_CFG, _mtlk_core_get_uapsd_cfg);
4354 _MTLK_CORE_HANDLE_REQ_SERIALIZABLE(MTLK_CORE_REQ_GET_PS_STATUS, _mtlk_core_get_ps_status);
4355 _MTLK_CORE_REQ_MAP_END()
4357 #undef _MTLK_CORE_REQ_MAP_START
4358 #undef _MTLK_CORE_HANDLE_REQ_SERIALIZABLE
4359 #undef _MTLK_CORE_REQ_MAP_END
4362 static int
4363 _mtlk_core_get_prop (mtlk_vap_handle_t vap_handle, mtlk_core_prop_e prop_id, void* buffer, uint32 size)
4365 int res = MTLK_ERR_NOT_SUPPORTED;
4367 switch (prop_id) {
4368 case MTLK_CORE_PROP_MAC_SW_RESET_ENABLED:
4369 if (buffer && size == sizeof(uint32))
4371 uint32 *mac_sw_reset_enabled = (uint32 *)buffer;
4373 *mac_sw_reset_enabled = MTLK_CORE_PDB_GET_INT(mtlk_vap_get_core (vap_handle), PARAM_DB_CORE_MAC_SOFT_RESET_ENABLE);
4374 res = MTLK_ERR_OK;
4376 case MTLK_CORE_PROP_IS_DUT:
4377 if (buffer && size == sizeof(BOOL))
4379 BOOL *val = (BOOL *)buffer;
4380 *val = mtlk_is_dut_core_active(mtlk_vap_get_core(vap_handle));
4381 res = MTLK_ERR_OK;
4383 break;
4384 case MTLK_CORE_PROP_IS_MAC_FATAL_PENDING:
4385 if (buffer && size == sizeof(BOOL))
4387 BOOL *val = (BOOL *)buffer;
4388 *val = core_get_is_mac_fatal_pending(mtlk_vap_get_core(vap_handle));
4389 res = MTLK_ERR_OK;
4391 break;
4392 default:
4393 break;
4395 return res;
4398 static int
4399 _mtlk_core_set_prop (mtlk_vap_handle_t vap_handle,
4400 mtlk_core_prop_e prop_id,
4401 void *buffer,
4402 uint32 size)
4404 int res = MTLK_ERR_NOT_SUPPORTED;
4405 mtlk_core_t *nic = mtlk_vap_get_core (vap_handle);
4407 switch (prop_id)
4409 case MTLK_CORE_PROP_MAC_STUCK_DETECTED:
4410 if (buffer && size == sizeof(uint32))
4412 uint32 *cpu_no = (uint32 *)buffer;
4413 nic->slow_ctx->mac_stuck_detected_by_sw = 1;
4414 mtlk_set_hw_state(nic, MTLK_HW_STATE_APPFATAL);
4415 mtlk_core_set_net_state(nic, NET_STATE_HALTED);
4416 mtlk_df_ui_notify_notify_fw_hang(mtlk_vap_get_df(nic->vap_handle), *cpu_no, MTLK_HW_STATE_APPFATAL);
4418 break;
4419 case MTLK_CORE_PROP_IS_MAC_FATAL_PENDING:
4420 if (buffer && size == sizeof(BOOL))
4422 BOOL val = *((BOOL*) buffer);
4423 core_set_is_mac_fatal_pending(mtlk_vap_get_core(vap_handle), val);
4424 res = MTLK_ERR_OK;
4426 break;
4427 default:
4428 break;
4431 return res;
4435 void
4436 mtlk_find_and_update_ap(mtlk_handle_t context, uint8 *addr, bss_data_t *bss_data)
4438 uint8 channel, is_ht;
4439 struct nic *nic = (struct nic *)context;
4440 int lost_beacons;
4441 sta_entry *sta = NULL;
4443 /* No updates in not connected state of for non-STA or during scan*/
4444 if (mtlk_vap_is_ap(nic->vap_handle) ||
4445 (mtlk_core_get_net_state(nic) != NET_STATE_CONNECTED) ||
4446 mtlk_core_scan_is_running(nic))
4447 return;
4449 /* Check wrong AP */
4450 sta = mtlk_stadb_find_sta(&nic->slow_ctx->stadb, addr);
4451 ILOG4_YP("Trying to find AP %Y, PTR is %p", addr, sta);
4452 if (sta == NULL) {
4453 nic->pstats.discard_nwi++;
4454 return;
4457 /* Read setings for checks */
4458 is_ht = mtlk_core_get_is_ht_cur(nic);
4459 channel = MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_CHANNEL_CUR);
4461 /* Check channel change */
4462 if (bss_data->channel != channel) {
4463 ILOG0_DYDD("CID-%04x: AP %Y changed its channel! (%u -> %u)", mtlk_vap_get_oid(nic->vap_handle), addr, channel, bss_data->channel);
4464 goto DISCONNECT;
4467 /* Check HT capabilities change (only if HT is allowed in configuration) */
4468 if (mtlk_core_get_is_ht_cfg(nic) && !nic->slow_ctx->is_tkip && !nic->slow_ctx->wep_enabled &&
4469 (!!bss_data->is_ht != is_ht)) {
4470 ILOG0_DYS("CID-%04x: AP %Y changed its HT capabilities! (%s)", mtlk_vap_get_oid(nic->vap_handle),
4471 addr, is_ht ? "HT -> non-HT" : "non-HT -> HT");
4472 goto DISCONNECT;
4475 /* Update lost beacons */
4476 lost_beacons = mtlk_sta_update_beacon_interval(sta, bss_data->beacon_interval);
4477 mtlk_sta_decref(sta); /* De-reference of find */
4478 nic->pstats.missed_beacon += lost_beacons;
4479 return;
4481 DISCONNECT:
4482 mtlk_sta_decref(sta); /* De-reference of find */
4483 ILOG1_Y("Disconnecting AP %Y due to changed parameters", addr);
4484 _mtlk_core_schedule_disconnect_me(nic, FM_STATUSCODE_PEER_PARAMS_CHANGED, FRAME_REASON_UNSPECIFIED);
4487 static signed int
4488 find_acl_entry (IEEE_ADDR *list, IEEE_ADDR *mac, signed int *free_entry)
4490 int i;
4491 signed int idx;
4493 idx = -1;
4494 for (i = 0; i < MAX_ADDRESSES_IN_ACL; i++) {
4495 if (0 == mtlk_osal_compare_eth_addresses(mac->au8Addr, list[i].au8Addr)) {
4496 idx = i;
4497 break;
4500 if (NULL == free_entry)
4501 return idx;
4502 /* find first free entry */
4503 *free_entry = -1;
4504 for (i = 0; i < MAX_ADDRESSES_IN_ACL; i++) {
4505 if (mtlk_osal_is_zero_address(list[i].au8Addr)) {
4506 *free_entry = i;
4507 break;
4510 return idx;
4514 mtlk_core_set_acl(struct nic *nic, IEEE_ADDR *mac, IEEE_ADDR *mac_mask)
4516 signed int idx, free_idx;
4517 IEEE_ADDR addr_tmp;
4519 if (mtlk_osal_is_zero_address(mac->au8Addr)) {
4520 ILOG2_V("Upload ACL list");
4521 return MTLK_ERR_OK;
4524 /* Check pair MAC/MAC-mask consistency : MAC == (MAC & MAC-mask) */
4525 if (NULL != mac_mask) {
4526 mtlk_osal_eth_apply_mask(addr_tmp.au8Addr, mac->au8Addr, mac_mask->au8Addr);
4527 if (0 != mtlk_osal_compare_eth_addresses(addr_tmp.au8Addr, mac->au8Addr)) {
4528 WLOG_V("The ACL rule addition failed: "
4529 "The specified mask parameter is invalid. (MAC & MAC-Mask) != MAC.");
4530 return MTLK_ERR_PARAMS;
4534 idx = find_acl_entry(nic->slow_ctx->acl, mac, &free_idx);
4535 if (idx >= 0) {
4536 /* already on the list */
4537 WLOG_YD("MAC %Y is already on the ACL list at %d", mac->au8Addr, idx);
4538 return MTLK_ERR_OK;
4540 if (free_idx < 0) {
4541 /* list is full */
4542 WLOG_V("ACL list is full");
4543 return MTLK_ERR_NO_RESOURCES;
4545 /* add new entry */
4546 nic->slow_ctx->acl[free_idx] = *mac;
4547 if (NULL != mac_mask) {
4548 nic->slow_ctx->acl_mask[free_idx] = *mac_mask;
4549 } else {
4550 nic->slow_ctx->acl_mask[free_idx] = EMPTY_MAC_MASK;
4553 ILOG2_YD("Added %Y to the ACL list at %d", mac->au8Addr, free_idx);
4554 return MTLK_ERR_OK;
4558 mtlk_core_del_acl(struct nic *nic, IEEE_ADDR *mac)
4560 signed int idx;
4562 if (mtlk_osal_is_zero_address(mac->au8Addr)) {
4563 ILOG2_V("Delete ACL list");
4564 memset(nic->slow_ctx->acl, 0, sizeof(nic->slow_ctx->acl));
4565 return MTLK_ERR_OK;
4567 idx = find_acl_entry(nic->slow_ctx->acl, mac, NULL);
4568 if (idx < 0) {
4569 /* not found on the list */
4570 WLOG_Y("MAC %Y is not on the ACL list", mac->au8Addr);
4571 return MTLK_ERR_PARAMS;
4573 /* del entry */
4574 nic->slow_ctx->acl[idx] = EMPTY_MAC_ADDR;
4575 nic->slow_ctx->acl_mask[idx] = EMPTY_MAC_MASK;
4577 ILOG5_YD("Cleared %Y from the ACL list at %d", mac->au8Addr, idx);
4578 return MTLK_ERR_OK;
4581 mtlk_handle_t __MTLK_IFUNC
4582 mtlk_core_get_tx_limits_handle(mtlk_handle_t nic)
4584 return HANDLE_T(&(((struct nic*)nic)->slow_ctx->tx_limits));
4587 int __MTLK_IFUNC
4588 _mtlk_core_get_aocs_history(mtlk_handle_t hcore, const void* data, uint32 data_size)
4590 int res = MTLK_ERR_OK;
4592 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4593 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4594 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4596 res = mtlk_aocs_get_history(nic->slow_ctx->aocs, clpb);
4598 return res;
4601 int __MTLK_IFUNC
4602 _mtlk_core_get_aocs_table(mtlk_handle_t hcore, const void* data, uint32 data_size)
4604 int res = MTLK_ERR_OK;
4606 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4607 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4608 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4610 res = mtlk_aocs_get_table(nic->slow_ctx->aocs, clpb);
4612 return res;
4615 int __MTLK_IFUNC
4616 _mtlk_core_get_aocs_channels(mtlk_handle_t hcore, const void* data, uint32 data_size)
4618 int res = MTLK_ERR_OK;
4620 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4621 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4622 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4624 res = mtlk_aocs_get_channels(nic->slow_ctx->aocs, clpb);
4626 return res;
4629 #ifdef BT_ACS_DEBUG
4630 int __MTLK_IFUNC
4631 _mtlk_core_set_aocs_channels_dbg(mtlk_handle_t hcore, const void* data, uint32 data_size)
4633 int res = MTLK_ERR_OK;
4634 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4635 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4636 uint32 clpb_data_size;
4637 void* clpb_data;
4638 mtlk_aocs_channel_data_t *entry = NULL;
4640 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4642 clpb_data = mtlk_clpb_enum_get_next(clpb, &clpb_data_size);
4643 MTLK_ASSERT(NULL != clpb_data);
4644 MTLK_ASSERT(sizeof(mtlk_aocs_channel_data_t) == clpb_data_size);
4646 if (((mtlk_aocs_channel_data_t *)clpb_data)->stat.channel) {
4647 entry = (mtlk_aocs_channel_data_t *)mtlk_osal_mem_alloc(sizeof(*entry), MTLK_MEM_TAG_AOCS_ENTRY);
4648 if (NULL == entry) {
4649 res = MTLK_ERR_NO_MEM;
4650 } else {
4651 *entry = * (mtlk_aocs_channel_data_t *) clpb_data;
4654 mtlk_aocs_set_channels_dbg(nic->slow_ctx->aocs, entry);
4656 return res;
4658 #endif /* BT_ACS_DEBUG */
4660 int __MTLK_IFUNC
4661 _mtlk_core_get_aocs_penalties(mtlk_handle_t hcore, const void* data, uint32 data_size)
4663 int res = MTLK_ERR_OK;
4665 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4666 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4667 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4669 res = mtlk_aocs_get_penalties(nic->slow_ctx->aocs, clpb);
4671 return res;
4674 #ifdef AOCS_DEBUG
4675 int __MTLK_IFUNC
4676 _mtlk_core_get_aocs_debug_update_cl(mtlk_handle_t hcore, const void* data, uint32 data_size)
4678 int res = MTLK_ERR_OK;
4679 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4680 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4681 uint32 clpb_data_size;
4682 void* clpb_data;
4683 uint32 cl;
4685 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4687 clpb_data = mtlk_clpb_enum_get_next(clpb, &clpb_data_size);
4688 MTLK_ASSERT(NULL != clpb_data);
4689 MTLK_ASSERT(sizeof(uint32) == clpb_data_size);
4690 cl = *(uint32*) clpb_data;
4692 mtlk_aocs_debug_update_cl(nic->slow_ctx->aocs, cl);
4694 return res;
4696 #endif /*AOCS_DEBUG*/
4698 int __MTLK_IFUNC
4699 _mtlk_core_get_hw_limits(mtlk_handle_t hcore, const void* data, uint32 data_size)
4701 int res = MTLK_ERR_OK;
4703 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4704 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4705 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4707 res = mtlk_channels_get_hw_limits(&nic->slow_ctx->tx_limits, clpb);
4709 return res;
4712 int __MTLK_IFUNC
4713 _mtlk_core_get_reg_limits(mtlk_handle_t hcore, const void* data, uint32 data_size)
4715 int res = MTLK_ERR_OK;
4717 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4718 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4719 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4721 res = mtlk_channels_get_reg_limits(&nic->slow_ctx->tx_limits, clpb);
4723 return res;
4726 int __MTLK_IFUNC
4727 _mtlk_core_get_ant_gain(mtlk_handle_t hcore, const void* data, uint32 data_size)
4729 int res = MTLK_ERR_OK;
4731 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4732 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4733 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4735 res = mtlk_channels_get_ant_gain(&nic->slow_ctx->tx_limits, clpb);
4737 return res;
4740 int __MTLK_IFUNC
4741 _mtlk_core_get_l2nat_stats(mtlk_handle_t hcore, const void* data, uint32 data_size)
4743 int res = MTLK_ERR_OK;
4745 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4746 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4747 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4749 res = mtlk_l2nat_get_stats(nic, clpb);
4751 return res;
4754 int __MTLK_IFUNC
4755 _mtlk_core_get_sq_status(mtlk_handle_t hcore, const void* data, uint32 data_size)
4757 int res = MTLK_ERR_NOT_SUPPORTED;
4759 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4760 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4761 BOOL get_peers_status;
4763 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4765 get_peers_status = (NET_STATE_CONNECTED == mtlk_core_get_net_state(nic));
4767 res = mtlk_sq_get_status(nic->sq, clpb, get_peers_status);
4769 return res;
4772 int __MTLK_IFUNC
4773 _mtlk_core_get_ps_status(mtlk_handle_t hcore, const void* data, uint32 data_size)
4775 int res = MTLK_ERR_NOT_SUPPORTED;
4777 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4778 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4780 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4782 res = mtlk_ps_get_status(&nic->slow_ctx->stadb, clpb);
4784 return res;
4787 int __MTLK_IFUNC
4788 _mtlk_core_set_mac_assert(mtlk_handle_t hcore, const void* data, uint32 data_size)
4790 int res = MTLK_ERR_NOT_SUPPORTED;
4791 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4792 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4793 uint32 clpb_data_size;
4794 void* clpb_data;
4795 uint32 assert_type;
4797 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4799 clpb_data = mtlk_clpb_enum_get_next(clpb, &clpb_data_size);
4800 MTLK_ASSERT(NULL != clpb_data);
4802 MTLK_ASSERT(sizeof(int) == clpb_data_size);
4803 assert_type = *(uint32*) clpb_data;
4805 ILOG0_DD("CID-%04x: Rise MAC assert (assert type=%d)", mtlk_vap_get_oid(nic->vap_handle), assert_type);
4807 switch (assert_type) {
4808 case MTLK_CORE_UI_ASSERT_TYPE_FW_LMIPS:
4809 case MTLK_CORE_UI_ASSERT_TYPE_FW_UMIPS:
4811 uint32 mips_no;
4812 mips_no = (assert_type == MTLK_CORE_UI_ASSERT_TYPE_FW_UMIPS)?UMIPS:LMIPS;
4814 rcvry_set_forced_type(mtlk_vap_get_rcvry(nic->vap_handle), MTLK_CORE_UI_RCVRY_TYPE_NONE);
4816 res = mtlk_vap_get_hw_vft(nic->vap_handle)->set_prop(nic->vap_handle, MTLK_HW_DBG_ASSERT_FW, &mips_no, sizeof(mips_no));
4817 if (res != MTLK_ERR_OK) {
4818 ELOG_DDD("CID-%04x: Can't assert FW MIPS#%d (res=%d)", mtlk_vap_get_oid(nic->vap_handle), mips_no, res);
4821 break;
4823 case MTLK_CORE_UI_ASSERT_TYPE_DRV_DIV0:
4825 volatile int do_bug = 0;
4826 do_bug = 1/do_bug;
4827 ILOG0_D("do_bug = %d", do_bug); /* To avoid compilation optimization */
4828 res = MTLK_ERR_OK;
4830 break;
4832 case MTLK_CORE_UI_ASSERT_TYPE_DRV_BLOOP:
4833 while (1) {;}
4834 break;
4836 case MTLK_CORE_UI_ASSERT_TYPE_NONE:
4837 case MTLK_CORE_UI_ASSERT_TYPE_LAST:
4838 default:
4839 ILOG0_DD("CID-%04x: Unsupported assert type: %d", mtlk_vap_get_oid(nic->vap_handle), assert_type);
4840 res = MTLK_ERR_NOT_SUPPORTED;
4841 break;
4844 return res;
4847 int __MTLK_IFUNC
4848 _mtlk_core_get_mc_igmp_tbl(mtlk_handle_t hcore, const void* data, uint32 data_size)
4850 int res = MTLK_ERR_NOT_SUPPORTED;
4851 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4852 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4854 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4856 res = mtlk_mc_dump_groups(nic, clpb);
4858 return res;
4862 _mtlk_core_get_stadb_sta_list(mtlk_handle_t hcore, const void* data, uint32 data_size)
4864 int res = MTLK_ERR_OK;
4865 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4866 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4867 mtlk_core_ui_get_stadb_status_req_t *get_stadb_status_req;
4868 uint32 size;
4869 hst_db *hstdb = NULL;
4870 uint8 group_cipher = FALSE;
4871 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4873 if ( 0 == (mtlk_core_get_net_state(nic) & (NET_STATE_HALTED | NET_STATE_CONNECTED)) ) {
4874 mtlk_clpb_purge(clpb);
4875 return res;
4878 get_stadb_status_req = mtlk_clpb_enum_get_next(clpb, &size);
4879 if ( (NULL == get_stadb_status_req) || (sizeof(*get_stadb_status_req) != size) ) {
4880 res = MTLK_ERR_UNKNOWN;
4881 goto finish;
4884 if (get_stadb_status_req->get_hostdb) {
4885 hstdb = &nic->slow_ctx->hstdb;
4888 if (get_stadb_status_req->use_cipher) {
4889 group_cipher = nic->group_cipher;
4892 mtlk_clpb_purge(clpb);
4893 res = mtlk_stadb_get_stat(&nic->slow_ctx->stadb, hstdb, clpb, group_cipher);
4895 finish:
4896 return res;
4899 int __MTLK_IFUNC
4900 _mtlk_core_get_ee_caps(mtlk_handle_t hcore, const void* data, uint32 data_size)
4902 int res = MTLK_ERR_OK;
4903 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
4904 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
4905 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
4907 res = mtlk_eeprom_get_caps(mtlk_core_get_eeprom(nic), clpb);
4909 return res;
4912 mtlk_core_t * __MTLK_IFUNC
4913 mtlk_core_get_master (mtlk_core_t *core)
4915 MTLK_ASSERT(core != NULL);
4917 return mtlk_vap_manager_get_master_core(mtlk_vap_get_manager(core->vap_handle));
4920 uint8 __MTLK_IFUNC mtlk_core_is_device_busy(mtlk_handle_t context)
4923 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, context);
4924 return ( MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_DFS_RADAR_DETECTION)
4925 && !mtlk_dot11h_can_switch_now(mtlk_core_get_dfs(nic)));
4928 tx_limit_t* __MTLK_IFUNC
4929 mtlk_core_get_tx_limits(mtlk_core_t *core)
4931 return &core->slow_ctx->tx_limits;
4934 void
4935 mtlk_core_configuration_dump(mtlk_core_t *core)
4937 static char *user_spectrum[] = {"20 MHz", "40 MHz", "Auto "};
4938 ILOG0_DS("CID-%04x: Country : %s", mtlk_vap_get_oid(core->vap_handle), country_code_to_country(mtlk_core_get_country_code(core)));
4939 ILOG0_DD("CID-%04x: Domain : %u", mtlk_vap_get_oid(core->vap_handle), country_code_to_domain(mtlk_core_get_country_code(core)));
4940 ILOG0_DS("CID-%04x: Network mode : %s", mtlk_vap_get_oid(core->vap_handle), net_mode_to_string(mtlk_core_get_network_mode_cfg(core)));
4941 ILOG0_DS("CID-%04x: Band : %s", mtlk_vap_get_oid(core->vap_handle), mtlk_eeprom_band_to_string(net_mode_to_band(mtlk_core_get_network_mode_cfg(core))));
4942 ILOG0_DS("CID-%04x: Prog Model Spectrum : %s MHz", mtlk_vap_get_oid(core->vap_handle), MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_PROG_MODEL_SPECTRUM_MODE) ? "40": "20");
4943 ILOG0_DS("CID-%04x: Selected Spectrum : %s MHz", mtlk_vap_get_oid(core->vap_handle), MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE) ? "40": "20");
4944 ILOG0_DS("CID-%04x: User Sel. Spectrum : %s", mtlk_vap_get_oid(core->vap_handle), user_spectrum[MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_USER_SPECTRUM_MODE)]);
4945 ILOG0_DS("CID-%04x: Bonding : %s", mtlk_vap_get_oid(core->vap_handle), MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_SELECTED_BONDING_MODE) == ALTERNATE_UPPER ? "upper" : (MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_SELECTED_BONDING_MODE) == ALTERNATE_LOWER ? "lower" : "none"));
4946 ILOG0_DS("CID-%04x: HT mode : %s", mtlk_vap_get_oid(core->vap_handle), mtlk_core_get_is_ht_cur(core) ? "enabled" : "disabled");
4947 ILOG0_DS("CID-%04x: SM enabled : %s", mtlk_vap_get_oid(core->vap_handle),
4948 mtlk_eeprom_get_disable_sm_channels(mtlk_core_get_eeprom(core)) ? "disabled" : "enabled");
4952 static void
4953 _mtlk_core_prepare_stop(mtlk_vap_handle_t vap_handle)
4955 mtlk_core_t *nic = mtlk_vap_get_core (vap_handle);
4957 ILOG1_V("Core prepare stopping....");
4958 mtlk_osal_lock_acquire(&nic->net_state_lock);
4959 nic->is_stopping = TRUE;
4960 mtlk_osal_lock_release(&nic->net_state_lock);
4962 if (mtlk_vap_is_slave_ap(vap_handle)) {
4963 return;
4966 rcvry_set_forced_type(mtlk_vap_get_rcvry(vap_handle), MTLK_CORE_UI_RCVRY_TYPE_NONE);
4968 if (NET_STATE_HALTED == mtlk_core_get_net_state(nic)) {
4969 if (mtlk_scan_is_running(&nic->slow_ctx->scan)) {
4970 scan_complete(&nic->slow_ctx->scan);
4972 } else {
4973 scan_terminate_and_wait_completion(&nic->slow_ctx->scan);
4977 BOOL __MTLK_IFUNC
4978 mtlk_core_is_stopping(mtlk_core_t *core)
4980 return (core->is_stopping || core->is_iface_stopping);
4983 void
4984 _mtlk_core_bswap_bcl_request (UMI_BCL_REQUEST *req, BOOL hdr_only)
4986 int i;
4988 req->Size = cpu_to_le32(req->Size);
4989 req->Address = cpu_to_le32(req->Address);
4990 req->Unit = cpu_to_le32(req->Unit);
4992 if (!hdr_only) {
4993 for (i = 0; i < ARRAY_SIZE(req->Data); i++) {
4994 req->Data[i] = cpu_to_le32(req->Data[i]);
4999 int __MTLK_IFUNC
5000 _mtlk_core_bcl_mac_data_get (mtlk_handle_t hcore, const void* data, uint32 data_size)
5002 int res = MTLK_ERR_OK;
5003 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
5004 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5005 mtlk_txmm_msg_t man_msg;
5006 mtlk_txmm_data_t* man_entry = NULL;
5007 int exception;
5008 mtlk_hw_state_e hw_state;
5009 UMI_BCL_REQUEST* preq;
5010 BOOL f_bswap_data = TRUE;
5012 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5014 /* Get BCL request from CLPB */
5015 preq = mtlk_clpb_enum_get_next(clpb, NULL);
5016 if (NULL == preq) {
5017 res = MTLK_ERR_PARAMS;
5018 goto finish;
5021 /* Check MAC state */
5022 hw_state = mtlk_core_get_hw_state(core);
5023 exception = (((hw_state == MTLK_HW_STATE_EXCEPTION) ||
5024 (hw_state == MTLK_HW_STATE_APPFATAL) ||
5025 (hw_state == MTLK_HW_STATE_MAC_ASSERTED)) &&
5026 !core->slow_ctx->mac_stuck_detected_by_sw);
5028 /* if Core got here preq->Unit field wiath value greater or equal to BCL_UNIT_MAX -
5029 * the Core should not convert result data words in host format. */
5030 if (preq->Unit >= BCL_UNIT_MAX) {
5031 preq->Unit -= BCL_UNIT_MAX; /*Restore original field value*/
5032 f_bswap_data = FALSE;
5035 ILOG3_SDDDD("Getting BCL over %s unit(%d) address(0x%x) size(%u) (%x)",
5036 exception ? "io" : "txmm",
5037 (int)preq->Unit,
5038 (unsigned int)preq->Address,
5039 (unsigned int)preq->Size,
5040 (unsigned int)preq->Data[0]);
5042 if (exception)
5044 /* MAC is halted - send BCL request through IO */
5045 _mtlk_core_bswap_bcl_request(preq, TRUE);
5047 res = mtlk_vap_get_hw_vft(core->vap_handle)->get_prop(core->vap_handle, MTLK_HW_BCL_ON_EXCEPTION, preq, sizeof(*preq));
5049 if (MTLK_ERR_OK != res) {
5050 ELOG_D("CID-%04x: Can't get BCL", mtlk_vap_get_oid(core->vap_handle));
5051 goto err_push;
5054 else
5056 /* MAC is in normal state - send BCL request through TXMM */
5057 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), NULL);
5058 if (!man_entry) {
5059 ELOG_D("CID-%04x: Can't send Get BCL request to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
5060 res = MTLK_ERR_NO_RESOURCES;
5061 goto err_push;
5064 _mtlk_core_bswap_bcl_request(preq, TRUE);
5066 memcpy((UMI_BCL_REQUEST*)man_entry->payload, preq, sizeof(*preq));
5068 man_entry->id = UM_MAN_QUERY_BCL_VALUE;
5069 man_entry->payload_size = sizeof(*preq);
5071 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
5073 if (MTLK_ERR_OK != res) {
5074 ELOG_D("CID-%04x: Can't send Get BCL request to MAC, timed-out", mtlk_vap_get_oid(core->vap_handle));
5075 goto err_push;
5078 /* Copy back results */
5079 memcpy(preq, (UMI_BCL_REQUEST*)man_entry->payload, sizeof(*preq));
5081 mtlk_txmm_msg_cleanup(&man_msg);
5084 /* Send back results */
5085 _mtlk_core_bswap_bcl_request(preq, !f_bswap_data);
5087 mtlk_dump(3, preq, sizeof(*preq), "dump of the UM_MAN_QUERY_BCL_VALUE");
5089 res = mtlk_clpb_push(clpb, preq, sizeof(*preq));
5090 if (MTLK_ERR_OK != res) {
5091 goto err_push;
5094 goto finish;
5096 err_push:
5097 mtlk_clpb_purge(clpb);
5098 finish:
5099 return res;
5102 int __MTLK_IFUNC
5103 _mtlk_core_bcl_mac_data_set (mtlk_handle_t hcore, const void* data, uint32 data_size)
5105 int res = MTLK_ERR_OK;
5106 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
5107 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5108 mtlk_txmm_msg_t man_msg;
5109 mtlk_txmm_data_t* man_entry = NULL;
5110 int exception;
5111 mtlk_hw_state_e hw_state;
5112 UMI_BCL_REQUEST* preq = NULL;
5114 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5116 /* Read Set BCL request from CLPB */
5117 preq = mtlk_clpb_enum_get_next(clpb, NULL);
5118 if (NULL == preq) {
5119 res = MTLK_ERR_PARAMS;
5120 goto finish;
5123 /* Check MAC state */
5124 hw_state = mtlk_core_get_hw_state(core);
5125 exception = (((hw_state == MTLK_HW_STATE_EXCEPTION) ||
5126 (hw_state == MTLK_HW_STATE_APPFATAL) ||
5127 (hw_state == MTLK_HW_STATE_MAC_ASSERTED)) &&
5128 !core->slow_ctx->mac_stuck_detected_by_sw);
5130 ILOG2_SDDDD("Setting BCL over %s unit(%d) address(0x%x) size(%u) (%x)",
5131 exception ? "io" : "txmm",
5132 (int)preq->Unit,
5133 (unsigned int)preq->Address,
5134 (unsigned int)preq->Size,
5135 (unsigned int)preq->Data[0]);
5137 mtlk_dump(3, preq, sizeof(*preq), "dump of the UM_MAN_SET_BCL_VALUE");
5139 if (exception)
5141 /* MAC is halted - send BCL request through IO */
5142 _mtlk_core_bswap_bcl_request(preq, FALSE);
5144 res = mtlk_vap_get_hw_vft(core->vap_handle)->set_prop(core->vap_handle, MTLK_HW_BCL_ON_EXCEPTION, preq, sizeof(*preq));
5146 if (MTLK_ERR_OK != res) {
5147 ELOG_D("CID-%04x: Can't set BCL", mtlk_vap_get_oid(core->vap_handle));
5148 goto finish;
5151 else
5153 /* MAC is in normal state - send BCL request through TXMM */
5154 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), NULL);
5155 if (!man_entry) {
5156 ELOG_D("CID-%04x: Can't send Set BCL request to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
5157 res = MTLK_ERR_NO_RESOURCES;
5158 goto finish;
5161 _mtlk_core_bswap_bcl_request(preq, FALSE);
5163 memcpy((UMI_BCL_REQUEST*)man_entry->payload, preq, sizeof(*preq));
5165 man_entry->id = UM_MAN_SET_BCL_VALUE;
5166 man_entry->payload_size = sizeof(*preq);
5168 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
5170 if (MTLK_ERR_OK != res) {
5171 ELOG_D("CID-%04x: Can't send Set BCL request to MAC, timed-out", mtlk_vap_get_oid(core->vap_handle));
5172 goto finish;
5175 mtlk_txmm_msg_cleanup(&man_msg);
5178 finish:
5179 return res;
5182 static int
5183 _mtlk_core_set_channel (mtlk_core_t *core, uint16 channel, uint8 spectrum_mode, BOOL userCfg)
5185 int res = MTLK_ERR_OK;
5186 mtlk_get_channel_data_t param;
5188 MTLK_ASSERT(!mtlk_vap_is_slave_ap(core->vap_handle));
5190 if (0 == channel) {
5191 ILOG1_D("CID-%04x: Enable channel auto-selection", mtlk_vap_get_oid(core->vap_handle));
5192 } else if (0 == mtlk_core_get_country_code(core)) {
5193 WLOG_DD("CID-%04x: Set channel to %i. (AP Workaround due to invalid Driver parameters setting at BSP startup)", mtlk_vap_get_oid(core->vap_handle),
5194 channel);
5195 } else {
5196 /* Check if channel is supported in current configuration */
5197 param.reg_domain = country_code_to_domain(mtlk_core_get_country_code(core));
5198 param.is_ht = TRUE;
5199 param.ap = mtlk_vap_is_ap(core->vap_handle);
5200 param.bonding = MTLK_CORE_PDB_GET_INT(core, userCfg ? PARAM_DB_CORE_USER_BONDING_MODE : PARAM_DB_CORE_SELECTED_BONDING_MODE);
5201 param.spectrum_mode = spectrum_mode;
5202 param.frequency_band = userCfg ? mtlk_core_get_freq_band_cfg(core) : mtlk_core_get_freq_band_cur(core);
5203 param.disable_sm_channels = mtlk_eeprom_get_disable_sm_channels(mtlk_core_get_eeprom(core));
5204 param.net_mode = userCfg ? mtlk_core_get_network_mode_cfg(core) : mtlk_core_get_network_mode_cur(core);
5206 if (param.bonding == (uint8)ALTERNATE_NONE){
5207 /* Force 20MHz in case of 40 MHz, but coexistence allows only 20MHz */
5208 param.spectrum_mode = SPECTRUM_20MHZ;
5211 if (MTLK_ERR_OK == mtlk_check_channel(&param, channel)) {
5212 ILOG1_DD("CID-%04x: Set channel to %i", mtlk_vap_get_oid(core->vap_handle), channel);
5214 } else {
5215 WLOG_DD("CID-%04x: Channel (%i) is not supported in current configuration.", mtlk_vap_get_oid(core->vap_handle),
5216 channel);
5217 mtlk_core_configuration_dump(core);
5218 res = MTLK_ERR_PARAMS;
5222 if (MTLK_ERR_OK == res) {
5223 MTLK_CORE_PDB_SET_INT(core, userCfg ? PARAM_DB_CORE_CHANNEL_CFG : PARAM_DB_CORE_CHANNEL_CUR, channel);
5226 return res;
5229 static int
5230 _mtlk_general_core_range_info_get (mtlk_core_t* nic, const void* data, uint32 data_size)
5232 int res = MTLK_ERR_OK;
5233 mtlk_core_ui_range_info_t range_info;
5234 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5236 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5237 MTLK_ASSERT(!mtlk_vap_is_slave_ap(nic->vap_handle));
5239 /* Get supported bitrates */
5241 int avail = mtlk_core_get_available_bitrates(nic);
5242 uint32 short_cyclic_prefix = MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_SHORT_CYCLIC_PREFIX_TX);
5243 int num_bitrates; /* Index in table returned to userspace */
5244 int value; /* Bitrate's value */
5245 int i; /* Bitrate index */
5246 int k, l; /* Counters, used for sorting */
5248 /* Array of bitrates is sorted and consist of only unique elements */
5249 num_bitrates = 0;
5250 for (i = BITRATE_FIRST; i <= BITRATE_LAST; i++) {
5251 if ((1 << i) & avail) {
5252 if(i == BITRATE_LAST)
5254 short_cyclic_prefix |= MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_SHORT_CYCLIC_PREFIX_RATE31);
5256 value = mtlk_bitrate_get_value(i, MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE), short_cyclic_prefix);
5257 range_info.bitrates[num_bitrates] = value;
5258 k = num_bitrates;
5259 while (k && (range_info.bitrates[k-1] >= value)) k--; /* Position found */
5260 if ((k == num_bitrates) || (range_info.bitrates[k] != value)) {
5261 for (l = num_bitrates; l > k; l--)
5262 range_info.bitrates[l] = range_info.bitrates[l-1];
5263 range_info.bitrates[k] = value;
5264 num_bitrates++;
5269 range_info.num_bitrates = num_bitrates;
5272 /* Get supported channels */
5274 uint8 band;
5275 mtlk_get_channel_data_t param;
5277 if (0 == mtlk_core_get_country_code(nic)) {
5278 WLOG_D("CID-%04x: Country is not selected. Channels information is not available.",
5279 mtlk_vap_get_oid(nic->vap_handle));
5280 goto finish;
5283 if (!mtlk_vap_is_ap(nic->vap_handle) && (NET_STATE_CONNECTED == mtlk_core_get_net_state(nic)) )
5284 band = mtlk_core_get_freq_band_cur(nic);
5285 else
5286 band = mtlk_core_get_freq_band_cfg(nic);
5288 param.reg_domain = country_code_to_domain(mtlk_core_get_country_code(nic));
5289 param.is_ht = TRUE;
5290 param.ap = mtlk_vap_is_ap(nic->vap_handle);
5291 param.bonding = MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_SELECTED_BONDING_MODE);
5292 param.spectrum_mode = MTLK_CORE_PDB_GET_INT(nic, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE);
5293 param.frequency_band = band;
5294 param.disable_sm_channels = mtlk_eeprom_get_disable_sm_channels(mtlk_core_get_eeprom(nic));
5296 range_info.num_channels = mtlk_get_avail_channels(&param, range_info.channels);
5299 finish:
5300 res = mtlk_clpb_push(clpb, &range_info, sizeof(range_info));
5301 if (MTLK_ERR_OK != res) {
5302 mtlk_clpb_purge(clpb);
5305 return res;
5308 static int
5309 _mtlk_slave_core_range_info_get (mtlk_core_t* nic, const void* data, uint32 data_size)
5311 return (_mtlk_general_core_range_info_get (mtlk_core_get_master (nic), data, data_size));
5314 int __MTLK_IFUNC
5315 _mtlk_core_range_info_get (mtlk_handle_t hcore, const void* data, uint32 data_size)
5317 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
5318 if (!mtlk_vap_is_slave_ap (core->vap_handle)) {
5319 return _mtlk_general_core_range_info_get (core, data, data_size);
5321 else
5322 return _mtlk_slave_core_range_info_get (core, data, data_size);
5325 int __MTLK_IFUNC
5326 _mtlk_core_start_scanning(mtlk_handle_t hcore, const void* data, uint32 data_size)
5328 int res = MTLK_ERR_BUSY;
5329 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5330 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5331 char *essid = NULL;
5332 int net_state;
5334 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5336 net_state = mtlk_core_get_net_state(nic);
5338 /* allow scanning in net states ready and connected only */
5339 if ((net_state & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5340 WLOG1_DS("CID-%04x: Cannot start scanning in state %s", mtlk_vap_get_oid(nic->vap_handle), mtlk_net_state_to_string(net_state));
5341 goto CANNOT_SCAN;
5343 if ((net_state == NET_STATE_CONNECTED) &&
5344 !mtlk_scan_is_background_scan_enabled(&nic->slow_ctx->scan)) {
5345 WLOG1_D("CID-%04x: BG scan is off - cannot start scanning", mtlk_vap_get_oid(nic->vap_handle));
5346 goto CANNOT_SCAN;
5349 /* Although we won't start scan when the previous hasn't completed yet anyway
5350 * (scan module prohibits this) -
5351 * we need to return 0 in this case to indicate the scan
5352 * has been started successfully.
5353 * Otherwise wpa_supplicant will wait for scan completion for 3 seconds only
5354 * (which is not enough for us in the majority of cases to finish scan)
5355 * and iwlist will simply report error to the user.
5356 * If we return 0 - they start polling us for scan results, which is
5357 * an expected behavior.
5359 res = MTLK_ERR_OK;
5360 if (mtlk_scan_is_running(&nic->slow_ctx->scan)) {
5361 ILOG1_D("CID-%04x: Scan in progress - cannot start scanning", mtlk_vap_get_oid(nic->vap_handle));
5362 goto CANNOT_SCAN;
5364 if (mtlk_core_is_stopping(nic)) {
5365 WLOG1_D("CID-%04x: Core is being stopped - cannot start scanning", mtlk_vap_get_oid(nic->vap_handle));
5366 goto CANNOT_SCAN;
5369 /* iwlist wlan0 scan <ESSID> */
5370 essid = mtlk_clpb_enum_get_next(clpb, NULL);
5372 /* Perform scanning */
5373 if (net_state == NET_STATE_CONNECTED)
5374 mtlk_scan_set_background(&nic->slow_ctx->scan, TRUE);
5375 else
5376 mtlk_scan_set_background(&nic->slow_ctx->scan, FALSE);
5377 res = mtlk_scan_async(&nic->slow_ctx->scan, mtlk_core_get_freq_band_cfg(nic), essid);
5379 CANNOT_SCAN:
5380 return res;
5383 int __MTLK_IFUNC
5384 _mtlk_core_get_scanning_res(mtlk_handle_t hcore, const void* data, uint32 data_size)
5386 int res = MTLK_ERR_OK;
5387 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5388 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5389 bss_data_t bss_found;
5391 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5393 if (mtlk_scan_is_running(&nic->slow_ctx->scan)) {
5394 ILOG1_D("CID-%04x: Can't get scan results - scan in progress", mtlk_vap_get_oid(nic->vap_handle));
5395 res = MTLK_ERR_NOT_READY;
5396 goto finish;
5398 if (mtlk_core_is_stopping(nic)) {
5399 WLOG1_D("CID-%04x: Core is being stopped - cannot start scanning", mtlk_vap_get_oid(nic->vap_handle));
5400 res = MTLK_ERR_NOT_IN_USE;
5401 goto finish;
5404 mtlk_cache_rewind(&nic->slow_ctx->cache);
5405 while (mtlk_cache_get_next_bss(&nic->slow_ctx->cache, &bss_found, NULL, NULL)) {
5406 res = mtlk_clpb_push(clpb, &bss_found, sizeof(bss_found));
5407 if (MTLK_ERR_OK != res) {
5408 goto err_push;
5412 goto finish;
5414 err_push:
5415 mtlk_clpb_purge(clpb);
5416 finish:
5417 return res;
5420 static int
5421 _mtlk_core_set_wep (struct nic *nic, int wep_enabled)
5423 int res = MTLK_ERR_NOT_SUPPORTED;
5425 if ((!wep_enabled && !nic->slow_ctx->wep_enabled) ||
5426 (wep_enabled && nic->slow_ctx->wep_enabled)) { /* WEB state is not changed */
5427 res = MTLK_ERR_OK;
5428 goto end;
5431 if (wep_enabled && is_ht_net_mode(mtlk_core_get_network_mode_cfg(nic))) {
5432 if (mtlk_vap_is_ap(nic->vap_handle)) {
5433 ELOG_DS("CID-%04x: AP: Can't set WEP for HT Network Mode (%s)", mtlk_vap_get_oid(nic->vap_handle),
5434 net_mode_to_string(mtlk_core_get_network_mode_cfg(nic)));
5435 goto end;
5437 else if (!is_mixed_net_mode(mtlk_core_get_network_mode_cfg(nic))) {
5438 ELOG_DS("CID-%04x: STA: Can't set WEP for HT-only Network Mode (%s)", mtlk_vap_get_oid(nic->vap_handle),
5439 net_mode_to_string(mtlk_core_get_network_mode_cfg(nic)));
5440 goto end;
5444 res = mtlk_set_mib_value_uint8(mtlk_vap_get_txmm(nic->vap_handle),
5445 MIB_PRIVACY_INVOKED,
5446 wep_enabled);
5447 if (res != MTLK_ERR_OK) {
5448 ELOG_DD("CID-%04x: Failed to enable WEP encryption (err=%d)", mtlk_vap_get_oid(nic->vap_handle), res);
5449 goto end;
5451 nic->slow_ctx->wep_enabled = wep_enabled;
5452 if (wep_enabled) {
5453 ILOG1_V("WEP encryption enabled");
5454 }else {
5455 ILOG1_V("WEP encryption disabled");
5458 end:
5459 return res;
5462 int __MTLK_IFUNC
5463 _mtlk_core_set_wep_enc_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5465 int res = MTLK_ERR_OK;
5466 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5467 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5468 mtlk_core_ui_enc_cfg_t *enc_cfg;
5469 uint32 size;
5470 mtlk_txmm_t *txmm = mtlk_vap_get_txmm(nic->vap_handle);
5471 IEEE_ADDR addr;
5472 MIB_WEP_KEY *enc_cfg_wep_key;
5474 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5476 if ((mtlk_core_get_net_state(nic) & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5477 ILOG1_D("CID-%04x: Invalid card state - request rejected", mtlk_vap_get_oid(nic->vap_handle));
5478 res = MTLK_ERR_NOT_READY;
5479 goto finish;
5481 if (mtlk_core_scan_is_running(nic)) {
5482 ILOG1_D("CID-%04x: Can't set WEP configuration - scan in progress", mtlk_vap_get_oid(nic->vap_handle));
5483 res = MTLK_ERR_NOT_READY;
5484 goto finish;
5487 enc_cfg = mtlk_clpb_enum_get_next(clpb, &size);
5488 if ( (NULL == enc_cfg) || (sizeof(*enc_cfg) != size) ) {
5489 res = MTLK_ERR_UNKNOWN;
5490 goto finish;
5493 /* New key always passed in array's slot 0 */
5494 enc_cfg_wep_key = &enc_cfg->wep_keys.sKey[0];
5496 if (( MAX_UINT8 != enc_cfg->key_id) && (enc_cfg_wep_key->u8KeyLength == 0)) { /* MAX_UINT8 => not specified */
5497 /* new key index is specified */
5498 res = mtlk_set_mib_value_uint8(txmm, MIB_WEP_DEFAULT_KEYID, enc_cfg->key_id);
5499 if (MTLK_ERR_OK != res) {
5500 ELOG_D("CID-%04x: Unable to set WEP TX key index", mtlk_vap_get_oid(nic->vap_handle));
5501 goto finish;
5503 nic->slow_ctx->default_key = enc_cfg->key_id;
5504 ILOG1_D("Set WEP TX key index to %i", enc_cfg->key_id);
5507 if (enc_cfg_wep_key->u8KeyLength != 0) {
5508 /* Set WEP key if specified */
5510 MIB_WEP_DEF_KEYS wep_keys;
5512 if ( MAX_UINT8 == enc_cfg->key_id ) {
5513 /* if key index not specified get current index from FW */
5514 res = mtlk_get_mib_value_uint8(txmm, MIB_WEP_DEFAULT_KEYID, &enc_cfg->key_id);
5515 if (MTLK_ERR_OK != res) {
5516 ELOG_D("CID-%04x: Unable to get WEP TX key index", mtlk_vap_get_oid(nic->vap_handle));
5517 goto finish;
5521 /* make a local copy of existing keys */
5522 memcpy(&wep_keys, &nic->slow_ctx->wep_keys, sizeof(wep_keys));
5524 /* Update specified key in local copy*/
5525 wep_keys.sKey[enc_cfg->key_id].u8KeyLength = enc_cfg_wep_key->u8KeyLength;
5527 memcpy(wep_keys.sKey[enc_cfg->key_id].au8KeyData,
5528 enc_cfg_wep_key->au8KeyData,
5529 enc_cfg_wep_key->u8KeyLength);
5531 /* Send all keys to FW */
5532 res = mtlk_set_mib_value_raw(txmm, MIB_WEP_DEFAULT_KEYS, (MIB_VALUE*)&wep_keys);
5533 if (res == MTLK_ERR_OK) {
5534 /* Update local copy of modified key */
5535 nic->slow_ctx->wep_keys.sKey[enc_cfg->key_id] = wep_keys.sKey[enc_cfg->key_id];
5536 ILOG2_D("Successfully set WEP key #%i", enc_cfg->key_id);
5537 mtlk_dump(2, wep_keys.sKey[enc_cfg->key_id].au8KeyData, wep_keys.sKey[enc_cfg->key_id].u8KeyLength, "");
5538 } else {
5539 ELOG_D("CID-%04x: Failed to set WEP key", mtlk_vap_get_oid(nic->vap_handle));
5540 goto finish;
5544 if ( MAX_UINT8 != enc_cfg->authentication ) { /* MAX_UINT8 => not specified */
5545 res = mtlk_set_mib_value_uint8(txmm, MIB_AUTHENTICATION_PREFERENCE, enc_cfg->authentication);
5546 if (MTLK_ERR_OK != res) {
5547 ELOG_DD("CID-%04x: Failed to switch access policy to %i", mtlk_vap_get_oid(nic->vap_handle), enc_cfg->authentication);
5548 goto finish;
5550 nic->authentication = enc_cfg->authentication;
5551 ILOG1_D("Access policy switched to %i", enc_cfg->authentication);
5554 if ( MAX_UINT8 != enc_cfg->wep_enabled ) { /* MAX_UINT8 => not specified */
5555 res = _mtlk_core_set_wep(nic, enc_cfg->wep_enabled);
5556 if (MTLK_ERR_OK != res) {
5557 ELOG_V("Failed to set WEP to Core");
5558 goto finish;
5562 /* Update RSN group key */
5563 memset(addr.au8Addr, 0xff, sizeof(addr.au8Addr));
5564 res = _mtlk_core_set_wep_key_blocked(nic, &addr, nic->slow_ctx->default_key);
5565 if (MTLK_ERR_OK != res) {
5566 ELOG_V("Failed to update group WEP key");
5567 goto finish;
5570 finish:
5571 return res;
5574 int __MTLK_IFUNC
5575 _mtlk_core_get_wep_enc_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5577 int res = MTLK_ERR_OK;
5578 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5579 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5580 mtlk_core_ui_enc_cfg_t enc_cfg;
5581 mtlk_txmm_t *txmm = mtlk_vap_get_txmm(nic->vap_handle);
5582 uint8 tmp;
5584 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5586 if ((mtlk_core_get_net_state(nic) & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5587 ILOG1_D("CID-%04x: Invalid card state - request rejected", mtlk_vap_get_oid(nic->vap_handle));
5588 res = MTLK_ERR_NOT_READY;
5589 goto finish;
5591 if (mtlk_core_scan_is_running(nic)) {
5592 ILOG1_D("CID-%04x: Can't get WEP configuration - scan in progress", mtlk_vap_get_oid(nic->vap_handle));
5593 res = MTLK_ERR_NOT_READY;
5594 goto finish;
5597 memset(&enc_cfg, 0, sizeof(enc_cfg));
5599 enc_cfg.wep_enabled = nic->slow_ctx->wep_enabled;
5601 if (nic->slow_ctx->wep_enabled) {
5602 /* Report access policy */
5603 res = mtlk_get_mib_value_uint8(txmm, MIB_AUTHENTICATION_PREFERENCE, &tmp);
5604 if (res != MTLK_ERR_OK) {
5605 ELOG_D("CID-%04x: Failed to read WEP access policy", mtlk_vap_get_oid(nic->vap_handle));
5606 goto finish;
5608 enc_cfg.authentication = tmp;
5611 enc_cfg.key_id = nic->slow_ctx->default_key;
5612 enc_cfg.wep_keys = nic->slow_ctx->wep_keys;
5614 res = mtlk_clpb_push(clpb, &enc_cfg, sizeof(enc_cfg));
5615 if (MTLK_ERR_OK != res) {
5616 mtlk_clpb_purge(clpb);
5619 finish:
5620 return res;
5624 int __MTLK_IFUNC
5625 _mtlk_core_set_auth_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5627 int res = MTLK_ERR_OK;
5628 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5629 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5630 mtlk_core_ui_auth_cfg_t *auth_cfg;
5631 uint32 size;
5632 mtlk_txmm_t *txmm = mtlk_vap_get_txmm(nic->vap_handle);
5634 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5636 if ((mtlk_core_get_net_state(nic) & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5637 ILOG1_D("CID-%04x: Invalid card state - request rejected", mtlk_vap_get_oid(nic->vap_handle));
5638 res = MTLK_ERR_NOT_READY;
5639 goto finish;
5642 if (mtlk_core_is_stopping(nic)) {
5643 ILOG1_D("CID-%04x: Can't set AUTH configuration - core is stopping", mtlk_vap_get_oid(nic->vap_handle));
5644 res = MTLK_ERR_NOT_READY;
5645 goto finish;
5648 if (mtlk_core_scan_is_running(nic)) {
5649 ILOG1_D("CID-%04x: Can't set AUTH configuration - scan in progress", mtlk_vap_get_oid(nic->vap_handle));
5650 res = MTLK_ERR_NOT_READY;
5651 goto finish;
5654 auth_cfg = mtlk_clpb_enum_get_next(clpb, &size);
5655 if ( (NULL == auth_cfg) || (sizeof(*auth_cfg) != size) ) {
5656 ELOG_D("CID-%04x: Failed to get AUTH configuration parameters from CLPB", mtlk_vap_get_oid(nic->vap_handle));
5657 res = MTLK_ERR_UNKNOWN;
5658 goto finish;
5661 if (0 <= auth_cfg->rsn_enabled) {
5662 res = mtlk_set_mib_rsn(txmm, auth_cfg->rsn_enabled);
5663 if (MTLK_ERR_OK != res) {
5664 ELOG_DD("CID-%04x: Failed to switch RSN state to %i", mtlk_vap_get_oid(nic->vap_handle), auth_cfg->rsn_enabled);
5665 goto finish;
5667 nic->rsn_enabled = auth_cfg->rsn_enabled;
5668 ILOG1_DD("CID-%04x: RSN switched to %i", mtlk_vap_get_oid(nic->vap_handle), auth_cfg->rsn_enabled);
5671 if (0 <= auth_cfg->wep_enabled) {
5672 res = _mtlk_core_set_wep(nic, auth_cfg->wep_enabled);
5673 if (MTLK_ERR_OK != res) {
5674 goto finish;
5678 if (0 <= auth_cfg->authentication) {
5679 res = mtlk_set_mib_value_uint8(txmm, MIB_AUTHENTICATION_PREFERENCE, auth_cfg->authentication);
5680 if (MTLK_ERR_OK != res) {
5681 ELOG_DD("CID-%04x: Failed to switch access policy to %i", mtlk_vap_get_oid(nic->vap_handle), auth_cfg->authentication);
5682 goto finish;
5684 nic->authentication = auth_cfg->authentication;
5685 ILOG1_DD("CID-%04x: Access policy switched to %i", mtlk_vap_get_oid(nic->vap_handle), auth_cfg->authentication);
5688 finish:
5689 return res;
5692 int __MTLK_IFUNC
5693 _mtlk_core_get_auth_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5695 int res = MTLK_ERR_OK;
5696 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5697 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5698 mtlk_core_ui_auth_state_t auth_state;
5699 sta_entry *sta;
5701 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5703 if ((mtlk_core_get_net_state(nic) & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5704 ILOG1_D("CID-%04x: Invalid card state - request rejected", mtlk_vap_get_oid(nic->vap_handle));
5705 res = MTLK_ERR_NOT_READY;
5706 goto finish;
5709 if (mtlk_core_is_stopping(nic)) {
5710 ILOG1_D("CID-%04x: Can't set AUTH configuration - core is stopping", mtlk_vap_get_oid(nic->vap_handle));
5711 res = MTLK_ERR_NOT_READY;
5712 goto finish;
5715 if (mtlk_core_scan_is_running(nic)) {
5716 ILOG1_D("CID-%04x: Can't set AUTH configuration - scan in progress", mtlk_vap_get_oid(nic->vap_handle));
5717 res = MTLK_ERR_NOT_READY;
5718 goto finish;
5721 memset(&auth_state, 0, sizeof(auth_state));
5723 auth_state.rsnie = nic->slow_ctx->rsnie;
5724 auth_state.group_cipher = nic->group_cipher;
5725 auth_state.cipher_pairwise = -1;
5727 if (!mtlk_vap_is_ap(nic->vap_handle)) {
5728 sta = mtlk_stadb_get_ap(&nic->slow_ctx->stadb);
5729 if (!sta) {
5730 res = MTLK_ERR_PARAMS;
5731 goto finish;
5734 auth_state.cipher_pairwise = mtlk_sta_get_cipher(sta);
5735 mtlk_sta_decref(sta); /* De-reference of get_ap */
5738 res = mtlk_clpb_push(clpb, &auth_state, sizeof(auth_state));
5739 if (MTLK_ERR_OK != res) {
5740 mtlk_clpb_purge(clpb);
5743 finish:
5744 return res;
5747 static void __MTLK_IFUNC
5748 _mtlk_core_set_wps_in_progress(mtlk_core_t *core, uint8 wps_in_progress)
5750 core->slow_ctx->wps_in_progress = wps_in_progress;
5751 if (wps_in_progress)
5752 ILOG1_D("CID-%04x: WPS in progress", mtlk_vap_get_oid(core->vap_handle));
5753 else
5754 ILOG1_D("CID-%04x: WPS stopped", mtlk_vap_get_oid(core->vap_handle));
5757 static int
5758 _mtlk_core_set_rsn_enabled (mtlk_core_t *core, uint8 rsn_enabled)
5760 int res;
5762 res = mtlk_set_mib_rsn(mtlk_vap_get_txmm(core->vap_handle), rsn_enabled);
5763 if (res == MTLK_ERR_OK) {
5764 core->rsn_enabled = rsn_enabled;
5767 return res;
5770 int __MTLK_IFUNC
5771 _mtlk_core_set_genie_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5773 int res = MTLK_ERR_OK;
5774 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
5775 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5776 mtlk_core_ui_genie_cfg_t *genie_cfg;
5777 uint32 size;
5779 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5781 if ((mtlk_core_get_net_state(core) & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5782 ILOG1_D("CID-%04x:: Invalid card state - request rejected", mtlk_vap_get_oid(core->vap_handle));
5783 res = MTLK_ERR_NOT_READY;
5784 goto finish;
5787 if (mtlk_core_is_stopping(core)) {
5788 ILOG1_D("CID-%04x: Can't set GEN_IE configuration - core is stopping", mtlk_vap_get_oid(core->vap_handle));
5789 res = MTLK_ERR_NOT_READY;
5790 goto finish;
5793 if (mtlk_core_scan_is_running(core)) {
5794 ILOG1_D("CID-%04x: Can't set GEN_IE configuration - scan in progress", mtlk_vap_get_oid(core->vap_handle));
5795 res = MTLK_ERR_NOT_READY;
5796 goto finish;
5799 genie_cfg = mtlk_clpb_enum_get_next(clpb, &size);
5800 if ( (NULL == genie_cfg) || (sizeof(*genie_cfg) != size) ) {
5801 ELOG_D("CID-%04x: Failed to get GEN_IE configuration parameters from CLPB", mtlk_vap_get_oid(core->vap_handle));
5802 res = MTLK_ERR_UNKNOWN;
5803 goto finish;
5806 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
5808 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(genie_cfg, wps_in_progress,
5809 _mtlk_core_set_wps_in_progress, (core, genie_cfg->wps_in_progress));
5811 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(genie_cfg, rsnie_reset,
5812 memset, (&core->slow_ctx->rsnie, 0, sizeof(core->slow_ctx->rsnie)));
5814 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(genie_cfg, rsnie,
5815 memcpy, (&core->slow_ctx->rsnie, &genie_cfg->rsnie, sizeof(core->slow_ctx->rsnie)));
5817 MTLK_CFG_CHECK_ITEM_AND_CALL(genie_cfg, gen_ie_set, mtlk_core_set_gen_ie,
5818 (core, genie_cfg->gen_ie, genie_cfg->gen_ie_len, genie_cfg->gen_ie_type), res);
5819 MTLK_CFG_CHECK_ITEM_AND_CALL(genie_cfg, gen_ie_set, _mtlk_core_store_gen_ie,
5820 (core, genie_cfg->gen_ie, genie_cfg->gen_ie_len, genie_cfg->gen_ie_type), res);
5822 MTLK_CFG_CHECK_ITEM_AND_CALL(genie_cfg, rsn_enabled, _mtlk_core_set_rsn_enabled,
5823 (core, genie_cfg->rsn_enabled), res);
5825 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
5827 finish:
5828 return res;
5831 int __MTLK_IFUNC
5832 _mtlk_core_get_enc_ext_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5834 int res = MTLK_ERR_OK;
5835 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
5836 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5837 mtlk_txmm_t *txmm = mtlk_vap_get_txmm(nic->vap_handle);
5838 mtlk_txmm_msg_t man_msg;
5839 mtlk_txmm_data_t *man_entry = NULL;
5840 UMI_GROUP_PN *umi_gpn;
5842 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5844 if (0 != (mtlk_core_get_net_state(nic) & (NET_STATE_HALTED | NET_STATE_IDLE))) {
5845 ILOG1_D("CID-%04x: Invalid card state - request rejected", mtlk_vap_get_oid(nic->vap_handle));
5846 res = MTLK_ERR_NOT_READY;
5847 goto finish;
5850 if (mtlk_core_scan_is_running(nic)) {
5851 ILOG1_D("CID-%04x: Can't get WEP configuration - scan in progress", mtlk_vap_get_oid(nic->vap_handle));
5852 res = MTLK_ERR_NOT_READY;
5853 goto finish;
5856 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, txmm, NULL);
5857 if (NULL == man_entry) {
5858 ELOG_D("CID-%04x: No man entry available", mtlk_vap_get_oid(nic->vap_handle));
5859 res = MTLK_ERR_NO_RESOURCES;
5860 goto finish;
5863 umi_gpn = (UMI_GROUP_PN*)man_entry->payload;
5864 memset(umi_gpn, 0, sizeof(UMI_GROUP_PN));
5866 man_entry->id = UM_MAN_GET_GROUP_PN_REQ;
5867 man_entry->payload_size = sizeof(UMI_GROUP_PN);
5869 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
5870 if (MTLK_ERR_OK != res) {
5871 ELOG_D("CID-%04x: Timeout expired while waiting for CFM from MAC", mtlk_vap_get_oid(nic->vap_handle));
5872 goto finish;
5875 umi_gpn->u16Status = le16_to_cpu(umi_gpn->u16Status);
5876 if (UMI_OK != umi_gpn->u16Status) {
5877 ELOG_DD("CID-%04x: GET_GROUP_PN_REQ failed: %u", mtlk_vap_get_oid(nic->vap_handle), umi_gpn->u16Status);
5878 res = MTLK_ERR_NOT_READY;
5879 goto finish;
5882 res = mtlk_clpb_push(clpb, umi_gpn, sizeof(*umi_gpn));
5883 if (MTLK_ERR_OK != res) {
5884 mtlk_clpb_purge(clpb);
5887 finish:
5888 if (man_entry) {
5889 mtlk_txmm_msg_cleanup(&man_msg);
5891 return res;
5894 static void
5895 _mtlk_core_set_rx_seq(struct nic *nic, uint16 idx, uint8* rx_seq)
5897 nic->group_rsc[idx][0] = rx_seq[5];
5898 nic->group_rsc[idx][1] = rx_seq[4];
5899 nic->group_rsc[idx][2] = rx_seq[3];
5900 nic->group_rsc[idx][3] = rx_seq[2];
5901 nic->group_rsc[idx][4] = rx_seq[1];
5902 nic->group_rsc[idx][5] = rx_seq[0];
5906 int __MTLK_IFUNC
5907 _mtlk_core_set_enc_ext_cfg(mtlk_handle_t hcore, const void* data, uint32 data_size)
5909 int res = MTLK_ERR_OK;
5910 mtlk_core_t *core = HANDLE_T_PTR(mtlk_core_t, hcore);
5911 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
5912 mtlk_txmm_msg_t man_msg;
5913 mtlk_txmm_data_t *man_entry = NULL;
5914 mtlk_txmm_t *txmm = mtlk_vap_get_txmm(core->vap_handle);
5916 mtlk_core_ui_encext_cfg_t *encext_cfg;
5917 uint32 size;
5918 UMI_SET_KEY *umi_key;
5919 uint16 alg_type = IW_ENCODE_ALG_NONE;
5920 uint16 key_len = 0;
5921 uint16 key_idx = 0;
5922 sta_entry *sta = NULL;
5923 mtlk_pckt_filter_e sta_filter_stored = MTLK_PCKT_FLTR_ALLOW_ALL;
5925 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
5927 if ((mtlk_core_get_net_state(core) & (NET_STATE_READY | NET_STATE_CONNECTED)) == 0) {
5928 ILOG1_D("CID-%04x: Invalid card state - request rejected", mtlk_vap_get_oid(core->vap_handle));
5929 res = MTLK_ERR_NOT_READY;
5930 goto finish;
5933 if (mtlk_core_is_stopping(core)) {
5934 ILOG1_D("CID-%04x: Can't set ENC_EXT configuration - core is stopping", mtlk_vap_get_oid(core->vap_handle));
5935 res = MTLK_ERR_NOT_READY;
5936 goto finish;
5939 if (mtlk_core_scan_is_running(core)) {
5940 ILOG1_D("CID-%04x: Can't set ENC_EXT configuration - scan in progress", mtlk_vap_get_oid(core->vap_handle));
5941 res = MTLK_ERR_NOT_READY;
5942 goto finish;
5945 encext_cfg = mtlk_clpb_enum_get_next(clpb, &size);
5946 if ( (NULL == encext_cfg) || (sizeof(*encext_cfg) != size) ) {
5947 ELOG_D("CID-%04x: Failed to get ENC_EXT configuration parameters from CLPB", mtlk_vap_get_oid(core->vap_handle));
5948 res = MTLK_ERR_UNKNOWN;
5949 goto finish;
5952 /* Prepare UMI message */
5953 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, txmm, NULL);
5954 if (!man_entry) {
5955 ELOG_D("CID-%04x: No man entry available", mtlk_vap_get_oid(core->vap_handle));
5956 res = MTLK_ERR_NO_RESOURCES;
5957 goto finish;
5960 umi_key = (UMI_SET_KEY*)man_entry->payload;
5961 memset(umi_key, 0, sizeof(*umi_key));
5963 man_entry->id = UM_MAN_SET_KEY_REQ;
5964 man_entry->payload_size = sizeof(*umi_key);
5966 MTLK_CFG_START_CHEK_ITEM_AND_CALL()
5967 MTLK_CFG_GET_ITEM(encext_cfg, alg_type, alg_type);
5969 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(encext_cfg, sta_addr, memcpy,
5970 (umi_key->sStationID.au8Addr, encext_cfg->sta_addr.au8Addr, sizeof(umi_key->sStationID.au8Addr)));
5972 /* NB: key_idx now is one less than real value.
5973 * This means: 0-3,4-5 instead of 1-4,5-6 */
5974 MTLK_CFG_GET_ITEM(encext_cfg, key_idx, key_idx);
5976 /* Set default key */
5977 MTLK_CFG_CHECK_ITEM_AND_CALL(encext_cfg, default_key_idx,
5978 mtlk_set_mib_value_uint8, (txmm, MIB_WEP_DEFAULT_KEYID, encext_cfg->default_key_idx), res);
5980 MTLK_CFG_GET_ITEM(encext_cfg, default_key_idx, core->slow_ctx->default_key);
5982 MTLK_CFG_GET_ITEM(encext_cfg, key_len, key_len);
5984 /* Set WEP key if needed */
5985 if (alg_type == IW_ENCODE_ALG_WEP ||
5986 (alg_type == IW_ENCODE_ALG_NONE && core->slow_ctx->wep_enabled && key_idx < MIB_WEP_N_DEFAULT_KEYS))
5987 // IW_ENCODE_ALG_NONE - reset keys
5989 /* Set WEP key */
5990 MIB_WEP_DEF_KEYS wep_keys;
5992 memcpy(&wep_keys, &core->slow_ctx->wep_keys, sizeof(wep_keys));
5994 wep_keys.sKey[key_idx].u8KeyLength = key_len;
5996 memset(wep_keys.sKey[key_idx].au8KeyData, 0,
5997 sizeof(wep_keys.sKey[key_idx].u8KeyLength));
5999 if (0 < key_len) {
6000 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(encext_cfg, key, memcpy,
6001 (wep_keys.sKey[key_idx].au8KeyData, encext_cfg->key, key_len));
6004 res = mtlk_set_mib_value_raw(txmm, MIB_WEP_DEFAULT_KEYS, (MIB_VALUE*)&wep_keys);
6005 if (res == MTLK_ERR_OK) {
6006 core->slow_ctx->wep_keys = wep_keys;
6007 ILOG1_D("Successfully set WEP key #%i", key_idx);
6008 mtlk_dump(1, wep_keys.sKey[key_idx].au8KeyData,
6009 wep_keys.sKey[key_idx].u8KeyLength, "");
6010 } else {
6011 ELOG_D("CID-%04x: Failed to set WEP key", mtlk_vap_get_oid(core->vap_handle));
6012 goto finish;
6016 /* Reset IGTK keys */
6018 alg_type == IW_ENCODE_ALG_NONE &&
6019 key_len == 0 &&
6021 (key_idx == (UMI_RSN_IGTK_GM_KEY_INDEX - 1)) ||
6022 (key_idx == (UMI_RSN_IGTK_GN_KEY_INDEX - 1))
6026 core->igtk_cipher = alg_type;
6027 core->igtk_key_len = key_len;
6030 /* Enable disable WEP */
6031 res = _mtlk_core_set_wep(core, encext_cfg->wep_enabled);
6032 if (MTLK_ERR_OK != res) goto finish;
6034 /* Extract UNI key */
6035 /* The key has been copied into au8Tk1 array with UMI_RSN_TK1_LEN size.
6036 * But key can have UMI_RSN_TK1_LEN+UMI_RSN_TK2_LEN size - so
6037 * actually second part of key is copied into au8Tk2 array */
6038 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(encext_cfg, key, memcpy,
6039 (umi_key->au8Tk1, encext_cfg->key, key_len));
6042 if (mtlk_osal_eth_is_broadcast(umi_key->sStationID.au8Addr))
6044 umi_key->u16KeyType = cpu_to_le16(UMI_RSN_GROUP_KEY);
6046 if(alg_type == IW_ENCODE_ALG_AES_CMAC)
6048 uint8 igtk_key_array_idx = (key_idx == (UMI_RSN_IGTK_GM_KEY_INDEX - 1)) ? 0 : 1;
6050 core->igtk_cipher = alg_type;
6051 core->igtk_key_len = key_len;
6052 memcpy(core->igtk_key[igtk_key_array_idx], encext_cfg->key, key_len);
6054 else
6056 core->group_cipher = alg_type;
6058 memset(core->group_rsc[key_idx], 0, sizeof(core->group_rsc[0]));
6060 MTLK_CFG_CHECK_ITEM_AND_CALL_VOID(encext_cfg, rx_seq,
6061 _mtlk_core_set_rx_seq, (core, key_idx, encext_cfg->rx_seq));
6063 } else {
6064 umi_key->u16KeyType = cpu_to_le16(UMI_RSN_PAIRWISE_KEY);
6067 MTLK_CFG_END_CHEK_ITEM_AND_CALL()
6069 if (MTLK_ERR_OK != res) {
6070 goto finish;
6073 switch (alg_type) {
6074 case IW_ENCODE_ALG_NONE:
6075 /* IW_ENCODE_ALG_NONE - reset keys */
6076 umi_key->u16CipherSuite = cpu_to_le16(UMI_RSN_CIPHER_SUITE_NONE);
6077 break;
6078 case IW_ENCODE_ALG_WEP:
6079 umi_key->u16CipherSuite = cpu_to_le16(UMI_RSN_CIPHER_SUITE_WEP40);
6080 break;
6081 case IW_ENCODE_ALG_TKIP:
6082 umi_key->u16CipherSuite = cpu_to_le16(UMI_RSN_CIPHER_SUITE_TKIP);
6083 break;
6084 case IW_ENCODE_ALG_CCMP:
6085 umi_key->u16CipherSuite = cpu_to_le16(UMI_RSN_CIPHER_SUITE_CCMP);
6086 break;
6087 case IW_ENCODE_ALG_AES_CMAC:
6088 umi_key->u16CipherSuite = cpu_to_le16(UMI_RSN_CIPHER_SUITE_IGTK);
6089 break;
6092 /* ant, 13 Apr 07: replay detection is performed by driver,
6093 * so MAC does not need this.
6094 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
6095 memcpy(umi_key->au8RxSeqNum, ext->rx_seq, ARRAY_SIZE(umi_key->au8RxSeqNum));
6097 /* ant: DO NOT SET THIS: supplicant is doing the job for us
6098 * (the job of swapping 16 bytes of umi_key->au8Tk2 in TKIP)
6099 * (umi_key->au8Tk2 is used in TKIP only)
6100 if (mtlk_vap_is_ap(nic->vap_handle))
6101 umi_key->u16StationRole = cpu_to_le16(UMI_RSN_AUTHENTICATOR);
6102 else
6103 umi_key->u16StationRole = cpu_to_le16(UMI_RSN_SUPPLICANT);
6106 if (cpu_to_le16(UMI_RSN_PAIRWISE_KEY) == umi_key->u16KeyType) {
6107 sta = mtlk_stadb_find_sta(&core->slow_ctx->stadb, umi_key->sStationID.au8Addr);
6108 if (NULL == sta) {
6109 /* Supplicant reset keys for AP from which we just were disconnected */
6110 ILOG1_Y("There is no connection with %Y", umi_key->sStationID.au8Addr);
6111 goto finish;
6114 mtlk_sta_set_cipher(sta, alg_type);
6115 mtlk_sta_zero_rod_reply_counters(sta);
6116 mtlk_sta_zero_pmf_replay_counters(sta);
6118 if (0 == key_len) {
6119 mtlk_sta_set_packets_filter(sta, MTLK_PCKT_FLTR_ALLOW_802_1X);
6120 ILOG1_Y("%Y: turn on 802.1x filtering", mtlk_sta_get_addr(sta));
6122 } else /*key_len != 0*/ if (!mtlk_vap_is_ap(core->vap_handle)) {
6123 /* Don't set the key until msg4 is sent to MAC */
6124 while (!mtlk_sta_sq_is_empty(sta))
6125 msleep(100);
6129 umi_key->u16DefaultKeyIndex = cpu_to_le16(key_idx);
6130 if (0 < key_len) {
6131 umi_key->au8TxSeqNum[0] = 1;
6134 /* Set key/configure MAC */
6135 for (;;) {
6136 /* if WEP is configured then:
6137 * - new key should be set in MAC
6138 * - if default_key != new_key
6139 * ---- default key should be set in MAC*/
6140 uint16 status;
6141 /* Save UMI message */
6142 UMI_SET_KEY stored_umi_key = *(UMI_SET_KEY*)man_entry->payload;
6143 mtlk_txmm_data_t stored_man_entry = *man_entry;
6145 mtlk_dump(3, umi_key, sizeof(UMI_SET_KEY), "dump of UMI_SET_KEY msg:");
6147 if (NULL != sta) {
6148 sta_filter_stored = mtlk_sta_get_packets_filter(sta);
6149 mtlk_sta_set_packets_filter(sta, MTLK_PCKT_FLTR_DISCARD_ALL);
6151 /* drop all packets in sta sendqueue */
6152 mtlk_sq_peer_ctx_cancel_all_packets(core->sq, mtlk_sta_get_sq(sta));
6154 /* Close TX aggregation */
6156 mtlk_addba_peer_t *addba_peer = mtlk_sta_get_addb_peer(sta);
6157 mtlk_addba_delba_req_all(addba_peer);
6160 /* wait till all messages to MAC to be confirmed */
6161 res = mtlk_sq_wait_all_packets_confirmed(mtlk_sta_get_sq(sta));
6162 if (MTLK_ERR_OK != res) {
6163 WLOG_DY("CID-%04x: STA:%Y wait time for all MSDUs confirmation expired",
6164 mtlk_vap_get_oid(core->vap_handle),
6165 mtlk_sta_get_addr(sta));
6167 mtlk_vap_get_hw_vft(core->vap_handle)->set_prop(core->vap_handle, MTLK_HW_RESET, NULL, 0);
6168 /* restore previous state of sta packets filter */
6169 mtlk_sta_set_packets_filter(sta, sta_filter_stored);
6170 goto finish;
6174 res = mtlk_txmm_msg_send_blocked(&man_msg,
6175 MTLK_MM_BLOCKED_SEND_TIMEOUT);
6176 if (NULL != sta) {
6177 /* restore previous state of sta packets filter */
6178 mtlk_sta_set_packets_filter(sta, sta_filter_stored);
6181 if (MTLK_ERR_OK != res) {
6182 ELOG_DD("CID-%04x: mtlk_mm_send_blocked failed: %i", mtlk_vap_get_oid(core->vap_handle), res);
6183 goto finish;
6186 status = le16_to_cpu(umi_key->u16Status);
6187 if (UMI_OK != status) {
6188 res = MTLK_ERR_UNKNOWN;
6189 switch (status) {
6190 case UMI_NOT_SUPPORTED:
6191 WLOG_D("CID-%04x: SIOCSIWENCODEEXT: RSN mode is disabled or an unsupported cipher suite was selected.", mtlk_vap_get_oid(core->vap_handle));
6192 res = MTLK_ERR_NOT_SUPPORTED;
6193 break;
6194 case UMI_STATION_UNKNOWN:
6195 WLOG_D("CID-%04x: SIOCSIWENCODEEXT: Unknown station was selected.", mtlk_vap_get_oid(core->vap_handle));
6196 break;
6197 default:
6198 WLOG_DDD("CID-%04x: invalid status of last msg %04x sending to MAC - %i", mtlk_vap_get_oid(core->vap_handle),
6199 man_entry->id, status);
6201 goto finish;
6204 if ((IW_ENCODE_ALG_WEP == alg_type) &&
6205 (umi_key->u16DefaultKeyIndex != cpu_to_le16(core->slow_ctx->default_key))) {
6207 ILOG1_D("reset tx key according to default key idx %i", core->slow_ctx->default_key);
6208 /* restore UMI message*/
6209 *(UMI_SET_KEY*)man_entry->payload = stored_umi_key;
6210 *man_entry = stored_man_entry;
6212 /* update UMI message*/
6213 umi_key->u16DefaultKeyIndex = cpu_to_le16(core->slow_ctx->default_key);
6214 memcpy(umi_key->au8Tk1,
6215 core->slow_ctx->wep_keys.sKey[core->slow_ctx->default_key].au8KeyData,
6216 core->slow_ctx->wep_keys.sKey[core->slow_ctx->default_key].u8KeyLength);
6217 /*Send UMI message*/
6218 continue;
6220 break;
6223 if (NULL != sta) {
6224 /* Now we have already set the keys =>
6225 we can start ADDBA and disable filter if required */
6226 mtlk_sta_on_security_negotiated(sta);
6228 if (key_len) {
6229 mtlk_sta_set_packets_filter(sta, MTLK_PCKT_FLTR_ALLOW_ALL);
6230 ILOG1_Y("%Y: turn off 802.1x filtering", mtlk_sta_get_addr(sta));
6234 finish:
6235 if (NULL != sta) {
6236 mtlk_sta_decref(sta); /* De-reference of find */
6239 if (NULL != man_entry) {
6240 mtlk_txmm_msg_cleanup(&man_msg);
6243 return res;
6246 static int
6247 _mtlk_core_mac_get_channel_stats(mtlk_core_t *nic, mtlk_core_general_stats_t *general_stats)
6249 int res = MTLK_ERR_OK;
6250 mtlk_txmm_msg_t man_msg;
6251 mtlk_txmm_data_t *man_entry = NULL;
6252 UMI_GET_CHANNEL_STATUS *pchannel_stats= NULL;
6254 MTLK_ASSERT(nic != NULL);
6255 MTLK_ASSERT(general_stats != NULL);
6257 if (NET_STATE_HALTED == mtlk_core_get_net_state(nic)) { /* Do nothing if halted */
6258 goto finish;
6261 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(nic->vap_handle), NULL);
6262 if (NULL == man_entry) {
6263 ELOG_D("CID-%04x: No man entry available", mtlk_vap_get_oid(nic->vap_handle));
6264 res = MTLK_ERR_NO_RESOURCES;
6265 goto finish;
6268 man_entry->id = UM_MAN_GET_CHANNEL_STATUS_REQ;
6269 man_entry->payload_size = sizeof(UMI_GET_CHANNEL_STATUS);
6271 pchannel_stats = (UMI_GET_CHANNEL_STATUS *)man_entry->payload;
6272 memset(pchannel_stats, 0, sizeof(UMI_GET_CHANNEL_STATUS));
6274 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
6275 if (MTLK_ERR_OK != res) {
6276 ELOG_DD("CID-%04x: MAC Get Channel Status sending failure (%i)", mtlk_vap_get_oid(nic->vap_handle), res);
6277 goto finish;
6280 general_stats->noise = pchannel_stats->u8GlobalNoise;
6281 general_stats->channel_load = pchannel_stats->u8ChannelLoad;
6283 finish:
6284 if (NULL != man_entry) {
6285 mtlk_txmm_msg_cleanup(&man_msg);
6287 return res;
6291 static int
6292 _mtlk_core_mac_get_peers_stats(mtlk_core_t *nic, mtlk_core_general_stats_t *general_stats)
6294 int res = MTLK_ERR_OK;
6295 mtlk_txmm_msg_t man_msg;
6296 mtlk_txmm_data_t *man_entry = NULL;
6297 UMI_GET_PEERS_STATUS *ppeers_stats= NULL;
6298 uint8 device_index = 0;
6299 uint8 idx;
6301 MTLK_ASSERT(nic != NULL);
6302 MTLK_ASSERT(general_stats != NULL);
6304 if (NET_STATE_HALTED == mtlk_core_get_net_state(nic)) { /* Do nothing if halted */
6305 goto finish;
6308 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(nic->vap_handle), NULL);
6309 if (NULL == man_entry) {
6310 ELOG_D("CID-%04x: No man entry available", mtlk_vap_get_oid(nic->vap_handle));
6311 res = MTLK_ERR_NO_RESOURCES;
6312 goto finish;
6315 do {
6316 man_entry->id = UM_MAN_GET_PEERS_STATUS_REQ;
6317 man_entry->payload_size = sizeof(UMI_GET_PEERS_STATUS);
6319 ppeers_stats = (UMI_GET_PEERS_STATUS *)man_entry->payload;
6320 memset(ppeers_stats, 0, sizeof(UMI_GET_PEERS_STATUS));
6321 ppeers_stats->u8DeviceIndex = device_index;
6323 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
6324 if (MTLK_ERR_OK != res) {
6325 ELOG_DD("CID-%04x: MAC Get Peers Status sending failure (%i)", mtlk_vap_get_oid(nic->vap_handle), res);
6326 break;
6329 for (idx = 0; idx < ppeers_stats->u8NumOfDeviceStatus; idx++) {
6330 sta_entry *sta = mtlk_stadb_find_sta(
6331 &nic->slow_ctx->stadb,
6332 (unsigned char*)&ppeers_stats->sDeviceStatus[idx].sMacAdd);
6334 if (sta != NULL) {
6335 mtlk_sta_update_fw_related_info(sta, &ppeers_stats->sDeviceStatus[idx]);
6336 mtlk_sta_decref(sta); /* De-reference of find */
6340 device_index = ppeers_stats->u8DeviceIndex;
6342 } while (0 != device_index);
6344 finish:
6345 if (NULL != man_entry) {
6346 mtlk_txmm_msg_cleanup(&man_msg);
6348 return res;
6351 static int
6352 _mtlk_core_mac_get_stats(mtlk_core_t *nic, mtlk_core_general_stats_t *general_stats)
6354 int res = MTLK_ERR_OK;
6355 mtlk_txmm_msg_t man_msg;
6356 mtlk_txmm_data_t *man_entry = NULL;
6357 UMI_GET_STATISTICS *mac_stats;
6358 int idx;
6360 MTLK_ASSERT(nic != NULL);
6361 MTLK_ASSERT(general_stats != NULL);
6363 if (NET_STATE_HALTED == mtlk_core_get_net_state(nic)) { /* Do nothing if halted */
6364 goto finish;
6367 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txdm(nic->vap_handle), NULL);
6368 if (!man_entry) {
6369 ELOG_D("CID-%04x: Can't get statistics due to the lack of MAN_MSG", mtlk_vap_get_oid(nic->vap_handle));
6370 res = MTLK_ERR_NO_RESOURCES;
6371 goto finish;
6374 mac_stats = (UMI_GET_STATISTICS *)man_entry->payload;
6376 man_entry->id = UM_DBG_GET_STATISTICS_REQ;
6377 man_entry->payload_size = sizeof(*mac_stats);
6378 mac_stats->u16Status = 0;
6379 mac_stats->u16Ident = HOST_TO_MAC16(GET_ALL_STATS);
6381 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
6382 if (MTLK_ERR_OK != res) {
6383 ELOG_DD("CID-%04x: MAC Get Stat sending failure (%i)", mtlk_vap_get_oid(nic->vap_handle), res);
6384 } else if (UMI_OK != le16_to_cpu(mac_stats->u16Status)) {
6385 ELOG_DD("CID-%04x: MAC Get Stat failure (%u)", mtlk_vap_get_oid(nic->vap_handle), le16_to_cpu(mac_stats->u16Status));
6386 res = MTLK_ERR_MAC;
6387 } else {
6388 for (idx = 0; idx < STAT_TOTAL_NUMBER; idx++) {
6389 general_stats->mac_stat.stat[idx] = le32_to_cpu(mac_stats->sStats.au32Statistics[idx]);
6393 finish:
6394 if (NULL != man_entry) {
6395 mtlk_txmm_msg_cleanup(&man_msg);
6397 return res;
6402 _mtlk_core_get_status(mtlk_handle_t hcore, const void* data, uint32 data_size)
6404 int res = MTLK_ERR_OK;
6405 mtlk_core_t *nic = HANDLE_T_PTR(mtlk_core_t, hcore);
6406 mtlk_clpb_t *clpb = *(mtlk_clpb_t **) data;
6407 mtlk_core_general_stats_t *general_stats;
6408 mtlk_txmm_stats_t txm_stats;
6410 MTLK_ASSERT(sizeof(mtlk_clpb_t*) == data_size);
6412 general_stats = mtlk_osal_mem_alloc(sizeof(*general_stats), MTLK_MEM_TAG_CLPB);
6413 if(general_stats == NULL) {
6414 ELOG_V("Can't allocate clipboard data");
6415 res = MTLK_ERR_NO_MEM;
6416 goto err_finish;
6418 memset(general_stats, 0, sizeof(*general_stats));
6420 /* Fill Core private statistic fields*/
6421 general_stats->core_priv_stats = nic->pstats;
6422 general_stats->tx_packets = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_PACKETS_SENT);
6423 general_stats->tx_bytes = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_BYTES_SENT);
6424 general_stats->rx_packets = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_PACKETS_RECEIVED);
6425 general_stats->rx_bytes = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_BYTES_RECEIVED);
6427 general_stats->unicast_replayed_packets = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_UNICAST_REPLAYED_PACKETS);
6428 general_stats->multicast_replayed_packets = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_MULTICAST_REPLAYED_PACKETS);
6429 general_stats->fwd_rx_packets = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_FWD_RX_PACKETS);
6430 general_stats->fwd_rx_bytes = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_FWD_RX_BYTES);
6431 general_stats->rx_dat_frames = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_DAT_FRAMES_RECEIVED);
6432 general_stats->rx_ctl_frames = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_CTL_FRAMES_RECEIVED);
6433 general_stats->rx_man_frames = _mtlk_core_get_cnt(nic, MTLK_CORE_CNT_MAN_FRAMES_RECEIVED);
6435 /* HW status fields */
6436 mtlk_vap_get_hw_vft(nic->vap_handle)->get_prop(nic->vap_handle, MTLK_HW_FREE_TX_MSGS,
6437 &general_stats->tx_msdus_free, sizeof(general_stats->tx_msdus_free));
6438 mtlk_vap_get_hw_vft(nic->vap_handle)->get_prop(nic->vap_handle, MTLK_HW_TX_MSGS_USED_PEAK,
6439 &general_stats->tx_msdus_usage_peak, sizeof(general_stats->tx_msdus_usage_peak));
6440 mtlk_vap_get_hw_vft(nic->vap_handle)->get_prop(nic->vap_handle, MTLK_HW_BIST,
6441 &general_stats->bist_check_passed, sizeof(general_stats->bist_check_passed));
6442 mtlk_vap_get_hw_vft(nic->vap_handle)->get_prop(nic->vap_handle, MTLK_HW_FW_BUFFERS_PROCESSED,
6443 &general_stats->fw_logger_packets_processed, sizeof(general_stats->fw_logger_packets_processed));
6444 mtlk_vap_get_hw_vft(nic->vap_handle)->get_prop(nic->vap_handle, MTLK_HW_FW_BUFFERS_DROPPED,
6445 &general_stats->fw_logger_packets_dropped, sizeof(general_stats->fw_logger_packets_dropped));
6447 mtlk_txmm_get_stats(mtlk_vap_get_txmm(nic->vap_handle), &txm_stats);
6448 general_stats->txmm_sent = txm_stats.nof_sent;
6449 general_stats->txmm_cfmd = txm_stats.nof_cfmed;
6450 general_stats->txmm_peak = txm_stats.used_peak;
6452 mtlk_txmm_get_stats(mtlk_vap_get_txdm(nic->vap_handle), &txm_stats);
6453 general_stats->txdm_sent = txm_stats.nof_sent;
6454 general_stats->txdm_cfmd = txm_stats.nof_cfmed;
6455 general_stats->txdm_peak = txm_stats.used_peak;
6457 if(mtlk_vap_is_master(nic->vap_handle)) {
6458 /* Get MAC statistic */
6459 res = _mtlk_core_mac_get_stats(nic, general_stats);
6460 if (MTLK_ERR_OK != res) {
6461 goto err_finish;
6464 /* Get MAC channel information for master only*/
6465 res = _mtlk_core_mac_get_channel_stats(nic, general_stats);
6466 if (MTLK_ERR_OK != res) {
6467 goto err_finish;
6470 /* Fill core status fields */
6471 general_stats->net_state = mtlk_core_get_net_state(nic);
6473 mtlk_pdb_get_mac(
6474 mtlk_vap_get_param_db(nic->vap_handle), PARAM_DB_CORE_BSSID, general_stats->bssid);
6476 if (!mtlk_vap_is_ap(nic->vap_handle) && (mtlk_core_get_net_state(nic) == NET_STATE_CONNECTED)) {
6477 sta_entry *sta = mtlk_stadb_get_ap(&nic->slow_ctx->stadb);
6479 if (NULL != sta) {
6480 general_stats->max_rssi = mtlk_sta_get_max_rssi(sta);
6482 mtlk_sta_decref(sta); /* De-reference of get_ap */
6487 /* Get MAC peers information */
6488 res = _mtlk_core_mac_get_peers_stats(nic, general_stats);
6489 if (MTLK_ERR_OK != res) {
6490 goto err_finish;
6493 /* Return Core status & statistic data */
6494 res = mtlk_clpb_push_nocopy(clpb, general_stats, sizeof(*general_stats));
6495 if (MTLK_ERR_OK != res) {
6496 mtlk_clpb_purge(clpb);
6497 goto err_finish;
6500 return MTLK_ERR_OK;
6502 err_finish:
6503 if (general_stats) {
6504 mtlk_osal_mem_free(general_stats);
6506 return res;
6511 mtlk_core_set_cur_bonding(mtlk_core_t *core, uint8 bonding)
6513 int result = MTLK_ERR_OK;
6515 if ((bonding == ALTERNATE_UPPER) || (bonding == ALTERNATE_LOWER))
6517 ILOG3_S("Bonding changed to %s", bonding == ALTERNATE_UPPER ? "upper" : (bonding == ALTERNATE_LOWER ? "lower" : "none"));
6518 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_SELECTED_BONDING_MODE, bonding);
6519 } else {
6520 result = MTLK_ERR_PARAMS;
6523 return result;
6526 int __MTLK_IFUNC
6527 mtlk_core_set_user_bonding(mtlk_core_t *core, uint8 bonding)
6529 int result = MTLK_ERR_OK;
6531 if ((bonding == ALTERNATE_UPPER) || (bonding == ALTERNATE_LOWER))
6533 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_USER_BONDING_MODE, bonding);
6534 if (NET_STATE_READY == mtlk_core_get_net_state(core)) { /* Check if interface down */
6535 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_SELECTED_BONDING_MODE, bonding);
6537 } else {
6538 result = MTLK_ERR_PARAMS;
6541 return result;
6544 uint8 __MTLK_IFUNC
6545 mtlk_core_get_user_bonding(mtlk_core_t *core)
6547 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_USER_BONDING_MODE);
6550 uint8 __MTLK_IFUNC
6551 mtlk_core_get_cur_bonding(mtlk_core_t *core)
6553 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_SELECTED_BONDING_MODE);
6556 BOOL __MTLK_IFUNC
6557 mtlk_core_net_state_is_connected(uint16 net_state)
6559 return ((NET_STATE_CONNECTED == net_state) ? TRUE:FALSE);
6562 uint8 __MTLK_IFUNC
6563 mtlk_core_get_country_code(mtlk_core_t *core)
6565 return MTLK_CORE_PDB_GET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_COUNTRY_CODE);
6568 static void
6569 _mtlk_core_country_code_set_default(mtlk_core_t* core)
6571 uint8 country_code;
6573 if (mtlk_vap_is_master_ap(core->vap_handle)) {
6574 country_code = mtlk_eeprom_get_country_code(mtlk_core_get_eeprom(core));
6575 if (country_code) {
6576 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_COUNTRY_CODE, country_code);
6577 ILOG1_DSD("CID-%04x: Country is set to (on init): %s(0x%02x)",
6578 mtlk_vap_get_oid(core->vap_handle), country_code_to_country(country_code), country_code);
6581 /* - Do nothing for slave VAP*/
6582 /* - Do nothing for STA (default value - 0)*/
6585 static void
6586 _mtlk_core_sta_country_code_set_default_on_activate(mtlk_core_t* core)
6588 uint8 country_code = mtlk_core_get_country_code(core);
6589 if (country_code == 0) {
6590 /*TODO: GS: Hide country_code processing */
6591 /* we must set up at least something */
6592 country_code = mtlk_eeprom_get_country_code(mtlk_core_get_eeprom(core));
6593 if (0 == country_code) {
6594 MTLK_CORE_PDB_SET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_COUNTRY_CODE, country_to_country_code("US"));
6595 WLOG_DSD("CID-%04x: Country isn't set. Set it to default (on activate): %s(0x%02x)",
6596 mtlk_vap_get_oid(core->vap_handle), "US", country_to_country_code("US"));
6601 static void
6602 _mtlk_core_sta_country_code_update_on_connect(mtlk_core_t* core, uint8 country_code)
6604 if (country_code) {
6605 MTLK_CORE_PDB_SET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_COUNTRY_CODE, country_code);
6606 ILOG1_DSD("CID-%04x: Country has been adopted (on connect): %s(0x%02x)",
6607 mtlk_vap_get_oid(core->vap_handle), country_code_to_country(country_code), country_code);
6611 void __MTLK_IFUNC
6612 mtlk_core_sta_country_code_update_from_bss(mtlk_core_t* core, uint8 country_code)
6614 if ( mtlk_core_get_dot11d(core) /*802.11d mode on*/ &&
6615 (0 != country_code) /*802.11d becon with country IE recieved */ &&
6616 (0 == mtlk_core_get_country_code(core)) /*Country hasn't been set yet*/) {
6618 MTLK_CORE_PDB_SET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_COUNTRY_CODE, country_code);
6619 ILOG1_DSD("CID-%04x: Country has been adopted (from bss): %s(0x%02x)",
6620 mtlk_vap_get_oid(core->vap_handle), country_code_to_country(country_code), country_code);
6622 mtlk_scan_schedule_rescan(&mtlk_core_get_master(core)->slow_ctx->scan);
6626 static int
6627 _mtlk_core_set_country_from_ui(mtlk_core_t *core, char *val)
6629 MTLK_ASSERT(!mtlk_vap_is_slave_ap(core->vap_handle));
6631 if (mtlk_core_get_net_state(core) != NET_STATE_READY) {
6632 return MTLK_ERR_BUSY;
6635 if (mtlk_vap_is_ap(core->vap_handle) && mtlk_eeprom_get_country_code(mtlk_core_get_eeprom(core))) {
6636 ILOG1_D("CID-%04x: Can't change Country. It's read-only parameter.", mtlk_vap_get_oid(core->vap_handle));
6637 ILOG1_DSD("CID-%04x: Current Country value: %s(0x%02x)",
6638 mtlk_vap_get_oid(core->vap_handle), country_code_to_country(mtlk_core_get_country_code(core)), mtlk_core_get_country_code(core));
6639 return MTLK_ERR_NOT_SUPPORTED;
6642 if (!mtlk_vap_is_ap(core->vap_handle) && mtlk_core_get_dot11d(core)) {
6643 ILOG1_D("CID-%04x: Can't change Country until 802.11d extension is enabled.", mtlk_vap_get_oid(core->vap_handle));
6644 return MTLK_ERR_NOT_SUPPORTED;
6647 if (strncmp(val, "??", 2) && country_to_domain(val) == 0) {
6648 return MTLK_ERR_VALUE;
6651 ILOG1_DSD("CID-%04x: Country is set to (from ui): %s(0x%02x)",
6652 mtlk_vap_get_oid(core->vap_handle), val, country_to_country_code(val));
6654 MTLK_CORE_PDB_SET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_COUNTRY_CODE, country_to_country_code(val));
6655 return MTLK_ERR_OK;
6658 BOOL __MTLK_IFUNC mtlk_core_get_dot11d(mtlk_core_t *core)
6660 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_DOT11D_ENABLED);
6663 static int
6664 _mtlk_core_set_is_dot11d(mtlk_core_t *core, BOOL is_dot11d)
6666 uint8 country_code = 0;
6668 if (NET_STATE_READY != mtlk_core_get_net_state(core)) {
6669 return MTLK_ERR_NOT_READY;
6672 /* set country code */
6673 if (!mtlk_vap_is_ap(core->vap_handle)) {
6674 /* Switched on */
6675 if (is_dot11d && !mtlk_core_get_dot11d(core)) {
6676 country_code = 0;
6678 /* Switched off */
6679 else if(!is_dot11d && mtlk_core_get_dot11d(core)) {
6680 country_code = mtlk_eeprom_get_country_code(mtlk_core_get_eeprom(core));
6681 if (0 == country_code) {
6683 country_code = country_to_country_code("US");
6687 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_COUNTRY_CODE, country_code);
6690 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_DOT11D_ENABLED, !!is_dot11d);
6692 return MTLK_ERR_OK;
6695 uint8
6696 mtlk_core_get_freq_band_cur(mtlk_core_t *core)
6698 MTLK_ASSERT(NULL != core);
6700 return MTLK_CORE_PDB_GET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_FREQ_BAND_CUR);
6703 uint8
6704 mtlk_core_get_freq_band_cfg(mtlk_core_t *core)
6706 MTLK_ASSERT(NULL != core);
6708 return MTLK_CORE_PDB_GET_INT(mtlk_core_get_master(core), PARAM_DB_CORE_FREQ_BAND_CFG);
6711 BOOL __MTLK_IFUNC
6712 mtlk_core_get_interfdet_mode_cfg (mtlk_core_t *core)
6714 MTLK_ASSERT(NULL != core);
6716 return (BOOL)(MTLK_CORE_PDB_GET_INT(mtlk_core_get_master(core), PARAM_DB_INTERFDET_MODE) &&
6717 MTLK_HW_BAND_2_4_GHZ == mtlk_core_get_freq_band_cur(core));
6720 BOOL __MTLK_IFUNC
6721 mtlk_core_get_interfdet_scan_report_en (mtlk_core_t *core)
6723 MTLK_ASSERT(NULL != core);
6725 return (BOOL)MTLK_CORE_PDB_GET_INT(mtlk_core_get_master(core), PARAM_DB_INTERFDET_MODE);
6728 uint8
6729 mtlk_core_get_network_mode_cur(mtlk_core_t *core)
6731 MTLK_ASSERT(NULL != core);
6733 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_NET_MODE_CUR);
6736 uint8
6737 mtlk_core_get_network_mode_cfg(mtlk_core_t *core)
6739 MTLK_ASSERT(NULL != core);
6741 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_NET_MODE_CFG);
6744 void __MTLK_IFUNC
6745 mtlk_core_notify_scan_complete(mtlk_vap_handle_t vap_handle)
6747 mtlk_df_ui_notify_scan_complete(mtlk_vap_get_df(vap_handle));
6750 uint8
6751 mtlk_core_get_is_ht_cur(mtlk_core_t *core)
6753 MTLK_ASSERT(NULL != core);
6755 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_IS_HT_CUR);
6758 uint8
6759 mtlk_core_get_is_ht_cfg(mtlk_core_t *core)
6761 MTLK_ASSERT(NULL != core);
6763 return MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_IS_HT_CFG);
6766 static void _mtlk_core_switch_cb_mode_callback(mtlk_handle_t context, uint16 primary_channel, int secondary_channel_offset)
6768 mtlk_core_t *core;
6769 uint8 new_spectrum_mode;
6770 uint8 new_bonding, old_bonding;
6772 core = (mtlk_core_t*)context;
6774 MTLK_ASSERT(NULL != core);
6776 ILOG0_DSDS("\nCurrent Primary Channel = %d\n"
6777 "Current Spectrum Mode = %s\n"
6778 "About to switch channel with following parameters:\n"
6779 "Primary Channel = %d\n"
6780 "Channel bonding = %s\n",
6781 _mtlk_core_get_channel(core),
6782 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE)?"40MHz":"20MHz",
6783 primary_channel,
6784 secondary_channel_offset == UMI_CHANNEL_SW_MODE_SCA ? "upper" : (secondary_channel_offset == UMI_CHANNEL_SW_MODE_SCB ? "lower" : "none"));
6786 if (secondary_channel_offset == UMI_CHANNEL_SW_MODE_SCN) {
6787 new_spectrum_mode = SPECTRUM_20MHZ;
6788 new_bonding = ALTERNATE_NONE;
6790 else {
6791 new_spectrum_mode = SPECTRUM_40MHZ;
6792 if (secondary_channel_offset == UMI_CHANNEL_SW_MODE_SCA) {
6793 new_bonding = ALTERNATE_UPPER;
6795 else {
6796 new_bonding = ALTERNATE_LOWER;
6800 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE, new_spectrum_mode);
6801 mtlk_aocs_set_spectrum_mode(core->slow_ctx->aocs, new_spectrum_mode);
6802 mtlk_dot11h_set_spectrum_mode(mtlk_core_get_dfs(core), new_spectrum_mode);
6804 mtlk_dot11h_20_40_coexistence_channel_switch(mtlk_core_get_dfs(core), primary_channel, new_bonding);
6805 ILOG2_V("Channel switch message sent to FW");
6807 old_bonding = mtlk_core_get_cur_bonding(mtlk_core_get_master(core));
6808 mtlk_core_set_cur_bonding(mtlk_core_get_master(core), new_bonding);
6809 if (MTLK_ERR_OK != _mtlk_core_set_channel(mtlk_core_get_master(core), primary_channel, new_spectrum_mode, FALSE)) {
6810 mtlk_core_set_cur_bonding(mtlk_core_get_master(core), old_bonding);
6814 static int __MTLK_IFUNC _mtlk_core_send_ce_serialized_callback(mtlk_handle_t context, const void *payload, uint32 size)
6816 int res = MTLK_ERR_OK;
6817 mtlk_core_t *core;
6818 mtlk_txmm_msg_t man_msg;
6819 mtlk_txmm_data_t *man_entry;
6821 ILOG2_V("Sending Coexistence Element");
6822 core = (mtlk_core_t*)context;
6824 MTLK_ASSERT(NULL != core);
6825 MTLK_ASSERT(NULL != payload);
6826 MTLK_ASSERT(sizeof(UMI_COEX_EL) == size);
6828 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), NULL);
6829 if (man_entry != NULL) {
6830 man_entry->id = UM_MAN_SET_COEX_EL_TEMPLATE_REQ;
6831 man_entry->payload_size = size;
6832 memcpy(man_entry->payload, payload, size);
6834 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
6835 if (res != MTLK_ERR_OK) {
6836 ELOG_DD("CID-%04x: Can't send UMI_COEX_EL request to MAC (err=%d)", mtlk_vap_get_oid(core->vap_handle), res);
6838 mtlk_txmm_msg_cleanup(&man_msg);
6840 else {
6841 ELOG_D("CID-%04x: Can't send UMI_COEX_EL request to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
6842 res = MTLK_ERR_NO_RESOURCES;
6845 return res;
6848 static void _mtlk_core_send_ce_callback(mtlk_handle_t context, UMI_COEX_EL *coexistence_element)
6850 mtlk_core_t *core;
6852 ILOG2_V("Scheduling Coexistence Element sending on serializer");
6853 core = (mtlk_core_t*)context;
6855 MTLK_ASSERT(NULL != core);
6856 mtlk_core_schedule_internal_task(core, context, _mtlk_core_send_ce_serialized_callback, coexistence_element, sizeof(*coexistence_element));
6859 static int __MTLK_IFUNC _mtlk_core_send_cmf_serialized_callback(mtlk_handle_t context, const void *payload, uint32 size)
6861 int res = MTLK_ERR_OK;
6862 mtlk_core_t *core;
6863 mtlk_txmm_msg_t man_msg;
6864 mtlk_txmm_data_t *man_entry;
6866 ILOG2_V("Sending Coexistence Frame");
6867 core = (mtlk_core_t*)context;
6869 MTLK_ASSERT(NULL != core);
6870 MTLK_ASSERT(NULL != payload);
6872 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), NULL);
6873 if (man_entry != NULL) {
6874 memcpy(man_entry->payload, payload, size);
6875 man_entry->id = UM_MAN_SEND_COEX_FRAME_REQ;
6876 man_entry->payload_size = size;
6877 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
6878 if (res != MTLK_ERR_OK) {
6879 ELOG_V("Error sending coexistence management frame");
6881 mtlk_txmm_msg_cleanup(&man_msg);
6883 else{
6884 ELOG_D("CID-%04x: Can't send UM_MAN_SEND_COEX_FRAME_REQ request to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
6885 res = MTLK_ERR_NO_RESOURCES;
6888 return res;
6891 static void _mtlk_core_send_cmf_callback(mtlk_handle_t context, const UMI_COEX_FRAME *coexistence_frame)
6893 mtlk_core_t *core;
6895 ILOG2_V("Scheduling Coexistence Frame sending on serializer");
6896 core = (mtlk_core_t*)context;
6898 MTLK_ASSERT(NULL != core);
6899 mtlk_core_schedule_internal_task(core, context, _mtlk_core_send_cmf_serialized_callback, coexistence_frame, sizeof(*coexistence_frame));
6902 static int _mtlk_core_send_exemption_policy_serialized_callback(mtlk_handle_t context, const void *payload, uint32 size)
6904 int res = MTLK_ERR_OK;
6905 mtlk_core_t *core;
6906 mtlk_txmm_msg_t man_msg;
6907 mtlk_txmm_data_t *man_entry;
6909 ILOG2_V("Sending Exemption Policy To FW");
6910 core = (mtlk_core_t*)context;
6912 MTLK_ASSERT(NULL != core);
6913 MTLK_ASSERT(sizeof(BOOL) == size);
6915 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), NULL);
6916 if (man_entry != NULL) {
6917 man_entry->id = UM_MAN_SET_SCAN_EXEMPTION_POLICY_REQ;
6918 man_entry->payload_size = size;
6919 memcpy(man_entry->payload, payload, size);
6920 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
6921 if (res != MTLK_ERR_OK) {
6922 ELOG_DD("CID-%04x: Can't send UMI_SCAN_EXEMPTION_POLICY request to MAC (err=%d)", mtlk_vap_get_oid(core->vap_handle), res);
6924 mtlk_txmm_msg_cleanup(&man_msg);
6926 else {
6927 ELOG_D("CID-%04x: Can't send UMI_SCAN_EXEMPTION_POLICY request to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(core->vap_handle));
6928 res = MTLK_ERR_NO_RESOURCES;
6930 return res;
6933 static void _mtlk_core_send_exemption_policy_callback(mtlk_handle_t context, BOOL must_grant_exemption_requests)
6935 mtlk_core_t *core;
6937 ILOG1_V("Scheduling Exemption Policy sending on serializer");
6938 core = (mtlk_core_t*)context;
6940 MTLK_ASSERT(NULL != core);
6941 mtlk_core_schedule_internal_task(core, context, _mtlk_core_send_exemption_policy_serialized_callback, &must_grant_exemption_requests, sizeof(must_grant_exemption_requests));
6944 static int __MTLK_IFUNC _mtlk_core_scan_async_serialized_callback(mtlk_handle_t context, const void *payload, uint32 size)
6946 mtlk_core_t *core;
6947 const BOOL *scan_5mhz_band;
6949 core = (mtlk_core_t*)context;
6950 scan_5mhz_band = (const BOOL*)payload;
6952 mtlk_scan_async(&core->slow_ctx->scan, *scan_5mhz_band ? MTLK_HW_BAND_5_2_GHZ : MTLK_HW_BAND_2_4_GHZ, "");
6954 return MTLK_ERR_OK;
6957 static int _mtlk_core_scan_async_callback(mtlk_handle_t context, BOOL scan_5mhz_band)
6959 mtlk_core_t *core;
6961 core = (mtlk_core_t*)context;
6963 MTLK_ASSERT(NULL != core);
6964 return mtlk_core_schedule_internal_task(core, context, _mtlk_core_scan_async_serialized_callback, &scan_5mhz_band, sizeof(scan_5mhz_band));
6967 static void _mtlk_core_scan_set_obss_callback(mtlk_handle_t context, BOOL is_obss)
6969 mtlk_core_t *core;
6971 core = (mtlk_core_t*)context;
6973 MTLK_ASSERT(NULL != core);
6975 mtlk_scan_set_background(&core->slow_ctx->scan, is_obss);
6976 mtlk_scan_set_obss(&core->slow_ctx->scan, is_obss);
6979 static int _mtlk_core_register_scan_completion_notification_callback(mtlk_handle_t caller_context, mtlk_handle_t core_context,
6980 scan_completed_notification_callback_type *callback)
6982 mtlk_core_t *core;
6984 core = (mtlk_core_t*)core_context;
6986 MTLK_ASSERT(NULL != core);
6988 mtlk_scan_register_scan_completed_notification_callback(&core->slow_ctx->scan, caller_context, callback);
6989 return MTLK_ERR_OK;
6992 static int _mtlk_core_enumerate_bss_info_callback(mtlk_handle_t caller_context,
6993 mtlk_handle_t core_context, bss_enumerator_callback_type callback, uint32 expiration_time)
6995 bss_data_t bss_data;
6996 mtlk_core_t *core;
6997 uint32 original_cache_expire_time;
6998 int i = 0;
7000 core = (mtlk_core_t*)core_context;
7002 MTLK_ASSERT(NULL != core);
7004 original_cache_expire_time = mtlk_cache_get_expiration_time(&core->slow_ctx->cache);
7005 if (original_cache_expire_time < expiration_time)
7007 mtlk_cache_set_expiration_time(&core->slow_ctx->cache, expiration_time);
7009 mtlk_cache_rewind(&core->slow_ctx->cache);
7010 ILOG3_V("Accessing cache data .........");
7011 /* update channels array from cache (received bss's) */
7012 while (mtlk_cache_get_next_bss(&core->slow_ctx->cache, &bss_data, NULL, NULL))
7014 mtlk_20_40_bss_info_t bss_info;
7015 ILOG3_D("Cache data No. %d:", i);
7016 ILOG3_D("Channel = %d", bss_data.channel);
7017 ILOG3_D("Sec.channel offset = %d", bss_data.secondary_channel_offset);
7018 ILOG3_D("Spectrum = %d", bss_data.spectrum);
7019 ILOG3_D("Is HT = %d", bss_data.is_ht);
7020 ILOG3_D("40MHz Intolerant = %d",bss_data.forty_mhz_intolerant);
7022 ++i;
7023 bss_info.channel = bss_data.channel;
7024 bss_info.secondary_channel_offset = bss_data.secondary_channel_offset;
7025 bss_info.timestamp = bss_data.received_timestamp;
7026 bss_info.is_2_4 = bss_data.is_2_4;
7027 bss_info.is_ht = bss_data.is_ht;
7028 bss_info.forty_mhz_intolerant = bss_data.forty_mhz_intolerant;
7029 bss_info.max_rssi = bss_data.max_rssi;
7030 (*callback)(caller_context, &bss_info);
7032 if(i == 0)
7033 ILOG3_V("Processing cache data ended with no results - cache is empty!");
7034 /* restore cache expire time */
7035 if (original_cache_expire_time < expiration_time)
7037 mtlk_cache_set_expiration_time(&core->slow_ctx->cache, original_cache_expire_time);
7039 return MTLK_ERR_OK;
7042 #ifdef BT_ACS_DEBUG
7043 static int _mtlk_core_enumerate_bss_info_by_aocs_callback
7044 (mtlk_handle_t caller_context, mtlk_handle_t core_context,
7045 bss_enumerator_callback_type callback, uint32 expiration_time)
7047 mtlk_core_t *core;
7048 mtlk_aocs_t *aocs;
7049 mtlk_slist_entry_t *list_head;
7050 mtlk_slist_entry_t *list_entry;
7051 mtlk_aocs_channel_data_t *entry;
7053 core = (mtlk_core_t*)core_context;
7054 MTLK_ASSERT(NULL != core);
7056 aocs = core->slow_ctx->aocs;
7057 MTLK_ASSERT(NULL != aocs);
7059 mtlk_20_40_clear_intolerant_db(core->coex_20_40_sm);
7061 ILOG2_V("Accessing aocs channels data .........");
7062 /* update channels array from aocs channels */
7063 mtlk_slist_foreach(get_aocs_channel_list(aocs), list_entry, list_head) {
7064 mtlk_20_40_bss_info_t bss_info;
7065 entry = MTLK_LIST_GET_CONTAINING_RECORD(list_entry,
7066 mtlk_aocs_channel_data_t, link_entry);
7068 bss_info.channel = entry->stat.channel;
7069 bss_info.timestamp = mtlk_osal_timestamp();
7070 bss_info.is_2_4 = TRUE;
7071 bss_info.is_ht = ! entry->stat.forty_mhz_intolerant;
7072 bss_info.forty_mhz_intolerant = entry->stat.forty_mhz_intolerant;
7074 if (entry->stat.num_20mhz_bss) {
7075 bss_info.secondary_channel_offset = UMI_CHANNEL_SW_MODE_SCN;
7076 (*callback)(caller_context, &bss_info);
7078 if (entry->stat.num_40mhz_up_bss) {
7079 bss_info.secondary_channel_offset = UMI_CHANNEL_SW_MODE_SCA;
7080 (*callback)(caller_context, &bss_info);
7082 if (entry->stat.num_40mhz_lw_bss) {
7083 bss_info.secondary_channel_offset = UMI_CHANNEL_SW_MODE_SCB;
7084 (*callback)(caller_context, &bss_info);
7088 return MTLK_ERR_OK;
7090 #endif /* BT_ACS_DEBUG */
7092 static int _mtlk_core_ability_control_callback(mtlk_handle_t context,
7093 eABILITY_OPS operation, const uint32* ab_id_list, uint32 ab_id_num)
7095 mtlk_core_t *core;
7096 int ret_val = MTLK_ERR_OK;
7098 ILOG2_V("called");
7100 core = (mtlk_core_t*)context;
7102 MTLK_ASSERT(NULL != core);
7104 switch (operation)
7106 case eAO_REGISTER:
7107 ret_val = mtlk_abmgr_register_ability_set(mtlk_vap_get_abmgr(core->vap_handle), (mtlk_ability_id_t*)ab_id_list, ab_id_num);
7108 break;
7109 case eAO_UNREGISTER:
7110 mtlk_abmgr_unregister_ability_set(mtlk_vap_get_abmgr(core->vap_handle), (mtlk_ability_id_t*)ab_id_list, ab_id_num);
7111 break;
7112 case eAO_ENABLE:
7113 mtlk_abmgr_enable_ability_set(mtlk_vap_get_abmgr(core->vap_handle), (mtlk_ability_id_t*)ab_id_list, ab_id_num);
7114 break;
7115 case eAO_DISABLE:
7116 mtlk_abmgr_disable_ability_set(mtlk_vap_get_abmgr(core->vap_handle), (mtlk_ability_id_t*)ab_id_list, ab_id_num);
7117 break;
7120 return ret_val;
7124 static uint16 _mtlk_core_get_cur_channels_callback(mtlk_handle_t context, int *secondary_channel_offset)
7126 mtlk_core_t *core;
7128 ILOG2_V("called");
7130 core = (mtlk_core_t*)context;
7132 MTLK_ASSERT(NULL != core);
7134 if (mtlk_aocs_get_spectrum_mode(core->slow_ctx->aocs))
7136 if (mtlk_core_get_cur_bonding(core) == ALTERNATE_UPPER)
7138 *secondary_channel_offset = UMI_CHANNEL_SW_MODE_SCA;
7140 else
7142 *secondary_channel_offset = UMI_CHANNEL_SW_MODE_SCB;
7145 else
7147 *secondary_channel_offset = UMI_CHANNEL_SW_MODE_SCN;
7150 return _mtlk_core_get_channel(core);
7153 static unsigned long _mtlk_core_modify_cache_expire_callback (mtlk_handle_t context, unsigned long new_time, BOOL force_change)
7155 mtlk_core_t *core;
7156 unsigned long old_time = new_time;
7159 core = (mtlk_core_t*)context;
7160 MTLK_ASSERT(NULL != core);
7162 if (mtlk_cache_get_expiration_time(&core->slow_ctx->cache) < new_time)
7164 if (!force_change)/* AP forced sta its params */
7166 old_time = mtlk_cache_get_expiration_time(&core->slow_ctx->cache);
7168 mtlk_cache_set_expiration_time(&core->slow_ctx->cache, new_time);
7171 return old_time;
7174 static int _mtlk_core_update_fw_obss_scan_parameters_callback (mtlk_handle_t context)
7176 int res = MTLK_ERR_OK;
7177 mtlk_txmm_msg_t man_msg;
7178 mtlk_txmm_data_t *man_entry;
7179 UMI_OBSS_SCAN_PARAMS *umi_obss_scan_params_cfg = NULL;
7180 mtlk_core_t *core;
7181 struct _mtlk_20_40_coexistence_sm *coex_sm;
7183 core = (mtlk_core_t*)context;
7184 coex_sm= mtlk_core_get_coex_sm(core);
7186 MTLK_ASSERT(NULL != core);
7187 MTLK_ASSERT(NULL != coex_sm);
7189 ILOG2_V("Updating FW on OBSS scan parameters for associated STAs");
7191 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(core->vap_handle), NULL);
7192 if (!man_entry) {
7193 res = MTLK_ERR_NO_RESOURCES;
7194 goto END;
7197 man_entry->id = UM_MAN_SET_OBSS_SCAN_PARAMS_REQ;
7198 man_entry->payload_size = sizeof(UMI_OBSS_SCAN_PARAMS);
7200 umi_obss_scan_params_cfg = (UMI_OBSS_SCAN_PARAMS *)man_entry->payload;
7203 umi_obss_scan_params_cfg->u8_MustInclude = mtlk_20_40_get_ap_force_scan_params_on_assoc_sta(coex_sm);
7205 umi_obss_scan_params_cfg->uOBSSScanPassiveDwell = HOST_TO_MAC16(mtlk_20_40_get_scan_passive_dwell(coex_sm));
7206 umi_obss_scan_params_cfg->uOBSSScanActiveDwell = HOST_TO_MAC16(mtlk_20_40_get_scan_active_dwell(coex_sm));
7207 umi_obss_scan_params_cfg->uOBSSScanPassiveTotalPerChannel = HOST_TO_MAC16(mtlk_20_40_get_passive_total_per_channel(coex_sm));
7208 umi_obss_scan_params_cfg->uOBSSScanActiveTotalPerChannel = HOST_TO_MAC16(mtlk_20_40_get_active_total_per_channel(coex_sm));
7209 umi_obss_scan_params_cfg->uBSSWidthChannelTransitionDelayFactor = HOST_TO_MAC16(mtlk_20_40_get_transition_delay_factor(coex_sm));
7210 umi_obss_scan_params_cfg->uBSSChannelWidthTriggerScanInterval = HOST_TO_MAC16(mtlk_20_40_get_scan_interval(coex_sm));
7211 umi_obss_scan_params_cfg->uOBSSScanActivityThreshold = HOST_TO_MAC16(mtlk_20_40_get_scan_activity_threshold(coex_sm));
7213 res = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
7214 if (res != MTLK_ERR_OK)
7215 ELOG_DD("CID-%04x: mtlk_mm_send_blocked failed: %i", mtlk_vap_get_oid(core->vap_handle), res);
7217 END:
7218 mtlk_txmm_msg_cleanup(&man_msg);
7219 return res;
7222 int __MTLK_IFUNC mtlk_core_on_channel_switch_done(mtlk_vap_handle_t vap_handle,
7223 uint16 primary_channel,
7224 uint8 secondary_channel_offset,
7225 uint16 reason)
7227 mtlk_channel_switched_event_t switch_data;
7229 memset(&switch_data, 0, sizeof(mtlk_channel_switched_event_t));
7231 switch_data.primary_channel = primary_channel;
7232 switch_data.secondary_channel = mtlk_channels_get_secondary_channel_no_by_offset(primary_channel, secondary_channel_offset);
7234 switch(reason)
7236 case SWR_LOW_THROUGHPUT:
7237 case SWR_HIGH_SQ_LOAD:
7238 case SWR_CHANNEL_LOAD_CHANGED:
7239 case SWR_MAC_PRESSURE_TEST:
7240 switch_data.reason = WSSA_SWR_OPTIMIZATION;
7241 break;
7242 case SWR_RADAR_DETECTED:
7243 switch_data.reason = WSSA_SWR_RADAR;
7244 break;
7245 case SWR_INITIAL_SELECTION:
7246 switch_data.reason = WSSA_SWR_USER;
7247 break;
7248 case SWR_20_40_COEXISTENCE:
7249 switch_data.reason = WSSA_20_40_COEXISTENCE;
7250 break;
7251 case SWR_AP_SWITCHED:
7252 switch_data.reason = WSSA_SWR_AP_SWITCHED;
7253 break;
7254 case SWR_UNKNOWN:
7255 default:
7256 switch_data.reason = WSSA_SWR_UNKNOWN;
7257 break;
7260 return mtlk_wssd_send_event(mtlk_vap_get_irbd(vap_handle),
7261 MTLK_WSSA_DRV_EVENT_CH_SWITCH,
7262 &switch_data,
7263 sizeof(mtlk_channel_switched_event_t));
7267 int __MTLK_IFUNC
7268 mtlk_core_wds_on_beacon (mtlk_core_t *core, IEEE_ADDR *addr)
7270 wds_on_beacon_t *on_beacon;
7271 wds_t *master_wds;
7273 /* Note: Assuming beacon arrived on Master VAP only */
7275 /* Find addr in on_beacon list. If addr is in list, then
7276 exclude on_beacon entry from list, send it to serializer
7277 for further processing and delete. */
7279 master_wds = &core->slow_ctx->wds_mng;
7280 on_beacon = wds_on_beacon_exclude(master_wds, addr);
7281 if (on_beacon)
7283 _mtlk_process_hw_task(core, SERIALIZABLE, wds_on_beacon_proc, HANDLE_T(master_wds), on_beacon, sizeof(wds_on_beacon_t));
7284 mtlk_osal_mem_free(on_beacon);
7287 return MTLK_ERR_OK;
7290 uint32 __MTLK_IFUNC
7291 mtlk_core_wds_on_timer (mtlk_osal_timer_t *timer, mtlk_handle_t wds_peer_handle)
7293 /* Note: This function is called from timer context
7294 Do not modify WDS structure from here
7296 wds_peer_t *peer;
7297 wds_t *wds;
7298 mtlk_core_t *core;
7300 peer = (wds_peer_t *)wds_peer_handle;
7301 wds = peer->wds;
7302 core = mtlk_vap_get_core(wds->vap_handle);
7304 mtlk_core_schedule_internal_task(core, HANDLE_T(wds), wds_peer_fsm_timer, &(peer->addr), sizeof(peer->addr));
7306 return 0;
7309 uint32 __MTLK_IFUNC
7310 mtlk_core_wds_on_host_disconnect_tmr (mtlk_osal_timer_t *timer,
7311 mtlk_handle_t host_handle)
7313 mtlk_core_t *core;
7315 core = mtlk_vap_get_core(mtlk_host_get_vap_handle(host_handle));
7316 mtlk_core_schedule_internal_task(core, host_handle, mtlk_host_wds_disconnect_tmr, NULL, 0);
7318 return 0; /* timer will be rescheduled in wds host timer handler */
7321 uint32 __MTLK_IFUNC
7322 mtlk_core_ta_on_timer (mtlk_osal_timer_t *timer, mtlk_handle_t ta_handle)
7324 /* Note: This function is called from timer context
7325 Do not modify TA structure from here
7327 mtlk_core_t *core;
7329 core = mtlk_vap_get_core(mtlk_ta_get_vap_handle(ta_handle));
7331 mtlk_core_schedule_internal_task(core, ta_handle, ta_timer, NULL, 0);
7333 return mtlk_ta_get_timer_resolution_ms(ta_handle);
7336 int __MTLK_IFUNC
7337 detect_replay(mtlk_core_t *core, mtlk_nbuf_t *nbuf, u8 *last_rc, BOOL is_mgmt)
7339 return _detect_replay(core, nbuf, last_rc, is_mgmt);
7342 int __MTLK_IFUNC
7343 get_rsc_buf(mtlk_core_t* core, mtlk_nbuf_t *nbuf, int off)
7345 return _get_rsc_buf(core, nbuf, off);
7348 int __MTLK_IFUNC
7349 mtlk_core_stop_lm (struct nic *core)
7351 return (_mtlk_core_stop_lm(HANDLE_T(core), NULL, 0));
7354 int __MTLK_IFUNC
7355 mtlk_core_set_tx_antennas (mtlk_core_t *core, uint8 num_tx_antennas)
7357 int res, i;
7358 uint8 val_array[MTLK_NUM_ANTENNAS_BUFSIZE];
7360 MTLK_ASSERT(NULL != core);
7362 memset (val_array, 0, sizeof (val_array));
7364 for (i = 0; i < num_tx_antennas; i++) {
7365 val_array[i] = i + 1;
7368 res = MTLK_CORE_PDB_SET_BINARY(core,
7369 PARAM_DB_CORE_TX_ANTENNAS,
7370 val_array,
7371 MTLK_NUM_ANTENNAS_BUFSIZE);
7373 if (MTLK_ERR_OK != res) {
7374 ILOG2_V("Can not save TX antennas configuration in to the PDB");
7377 return res;
7380 int __MTLK_IFUNC
7381 mtlk_core_set_uapsd_max_sp (mtlk_core_t *core, uint8 uapsd_max_sp)
7383 int res = MTLK_ERR_OK;
7385 MTLK_ASSERT(NULL != core);
7387 if (uapsd_max_sp < UAPSD_MAX_SP_USER_MIN || uapsd_max_sp > UAPSD_MAX_SP_USER_MAX) {
7388 WLOG_DD("Value should be in interval %d..%d", UAPSD_MAX_SP_USER_MIN, UAPSD_MAX_SP_USER_MAX);
7389 res = MTLK_ERR_PARAMS;
7390 } else {
7391 core->uapsd_max_sp = uapsd_max_sp;
7392 res = mtlk_set_mib_value_uint8(mtlk_vap_get_txmm(core->vap_handle), MIB_AP_MAX_PKTS_IN_SP, uapsd_max_sp);
7395 return res;
7398 static int
7399 _core_set_umi_key (mtlk_core_t *nic, int key_idx)
7401 int result = MTLK_ERR_OK;
7402 mtlk_txmm_data_t *man_entry = NULL;
7403 mtlk_txmm_msg_t man_msg;
7404 UMI_SET_KEY *pSetKey;
7406 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(nic->vap_handle), &result);
7407 if (man_entry == NULL) {
7408 ELOG_D("CID-%04x: Can't send UMI_KEY to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(nic->vap_handle));
7409 goto FINISH;
7412 man_entry->id = UM_MAN_SET_KEY_REQ;
7413 man_entry->payload_size = sizeof(*pSetKey);
7415 memset(man_entry->payload, 0, man_entry->payload_size);
7416 pSetKey = (UMI_SET_KEY*)(man_entry->payload);
7418 pSetKey->u16KeyType = HOST_TO_MAC16(UMI_RSN_GROUP_KEY);
7419 switch (nic->group_cipher) {
7420 case IW_ENCODE_ALG_NONE:
7421 pSetKey->u16CipherSuite = HOST_TO_MAC16(UMI_RSN_CIPHER_SUITE_NONE);
7422 break;
7423 case IW_ENCODE_ALG_WEP:
7424 pSetKey->u16CipherSuite = HOST_TO_MAC16(UMI_RSN_CIPHER_SUITE_WEP40);
7425 break;
7426 case IW_ENCODE_ALG_TKIP:
7427 pSetKey->u16CipherSuite = HOST_TO_MAC16(UMI_RSN_CIPHER_SUITE_TKIP);
7428 break;
7429 case IW_ENCODE_ALG_CCMP:
7430 pSetKey->u16CipherSuite = HOST_TO_MAC16(UMI_RSN_CIPHER_SUITE_CCMP);
7431 break;
7434 memset(pSetKey->sStationID.au8Addr, 0xFF, sizeof(pSetKey->sStationID.au8Addr));
7435 pSetKey->u16DefaultKeyIndex = HOST_TO_MAC16(key_idx);
7437 memcpy(pSetKey->au8Tk1,
7438 nic->slow_ctx->wep_keys.sKey[key_idx].au8KeyData,
7439 nic->slow_ctx->wep_keys.sKey[key_idx].u8KeyLength);
7441 ILOG2_D("CID-%04x: Sending SET UMI Key", mtlk_vap_get_oid(nic->vap_handle));
7442 result = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
7443 if (result != MTLK_ERR_OK) {
7444 ELOG_DD("CID-%04x: Can't send UMI_KEY request to MAC (err=%d)", mtlk_vap_get_oid(nic->vap_handle), result);
7445 goto FINISH;
7448 if (MAC_TO_HOST16(pSetKey->u16Status) != UMI_OK) {
7449 ELOG_DD("CID-%04x: Error returned for UMI_KEY request to MAC (err=%d)", mtlk_vap_get_oid(nic->vap_handle), MAC_TO_HOST16(pSetKey->u16Status));
7450 result = MTLK_ERR_UMI;
7451 goto FINISH;
7454 FINISH:
7455 if (man_entry) {
7456 mtlk_txmm_msg_cleanup(&man_msg);
7459 return result;
7462 static int
7463 _core_set_umi_key_igtk (mtlk_core_t *nic, int key_idx)
7465 int result = MTLK_ERR_OK;
7466 mtlk_txmm_data_t *man_entry = NULL;
7467 mtlk_txmm_msg_t man_msg;
7468 UMI_SET_KEY *pSetKey;
7469 uint8 igtk_key_array_idx = (key_idx == UMI_RSN_IGTK_GM_KEY_INDEX) ? 0 : 1;
7471 if(nic->igtk_cipher != IW_ENCODE_ALG_AES_CMAC) {
7472 goto FINISH;
7474 if(key_idx != UMI_RSN_IGTK_GM_KEY_INDEX &&
7475 key_idx != UMI_RSN_IGTK_GN_KEY_INDEX)
7477 ELOG_DD("CID-%04x: Invalid IGTK key index %d", mtlk_vap_get_oid(nic->vap_handle), key_idx);
7478 goto FINISH;
7481 man_entry = mtlk_txmm_msg_init_with_empty_data(&man_msg, mtlk_vap_get_txmm(nic->vap_handle), &result);
7482 if (man_entry == NULL) {
7483 ELOG_D("CID-%04x: Can't send UMI_KEY to MAC due to the lack of MAN_MSG", mtlk_vap_get_oid(nic->vap_handle));
7484 goto FINISH;
7487 man_entry->id = UM_MAN_SET_KEY_REQ;
7488 man_entry->payload_size = sizeof(*pSetKey);
7490 memset(man_entry->payload, 0, man_entry->payload_size);
7491 pSetKey = (UMI_SET_KEY*)(man_entry->payload);
7493 pSetKey->u16KeyType = HOST_TO_MAC16(UMI_RSN_GROUP_KEY);
7494 pSetKey->u16CipherSuite = HOST_TO_MAC16(UMI_RSN_CIPHER_SUITE_IGTK);
7495 memset(pSetKey->sStationID.au8Addr, 0xFF, sizeof(pSetKey->sStationID.au8Addr));
7496 /* NB: FW accepts key indices one less than real value */
7497 pSetKey->u16DefaultKeyIndex = HOST_TO_MAC16(key_idx - 1);
7499 memcpy(pSetKey->au8Tk1,
7500 nic->igtk_key[igtk_key_array_idx],
7501 nic->igtk_key_len);
7503 ILOG2_D("CID-%04x: Sending SET UMI Key (IGTK)", mtlk_vap_get_oid(nic->vap_handle));
7504 result = mtlk_txmm_msg_send_blocked(&man_msg, MTLK_MM_BLOCKED_SEND_TIMEOUT);
7505 if (result != MTLK_ERR_OK) {
7506 ELOG_DD("CID-%04x: Can't send UMI_KEY request to MAC (err=%d)", mtlk_vap_get_oid(nic->vap_handle), result);
7507 goto FINISH;
7510 if (MAC_TO_HOST16(pSetKey->u16Status) != UMI_OK) {
7511 ELOG_DD("CID-%04x: Error returned for UMI_KEY request to MAC (err=%d)", mtlk_vap_get_oid(nic->vap_handle), MAC_TO_HOST16(pSetKey->u16Status));
7512 result = MTLK_ERR_UMI;
7513 goto FINISH;
7516 FINISH:
7517 if (man_entry) {
7518 mtlk_txmm_msg_cleanup(&man_msg);
7521 return result;
7524 static int
7525 _core_on_fast_rcvry_configure (mtlk_core_t *core)
7527 int res = MTLK_ERR_OK;
7529 res = mtlk_progmodel_load(mtlk_vap_get_txmm(core->vap_handle),
7530 core,
7531 mtlk_core_get_freq_band_cfg(core),
7532 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_PROG_MODEL_SPECTRUM_MODE));
7533 if (res != MTLK_ERR_OK) {
7534 goto FINISH;
7537 ILOG0_D("CID-%04x: Recovery pre-activation parameters:", mtlk_vap_get_oid(core->vap_handle));
7538 mtlk_core_configuration_dump(core);
7540 /* Set channel & spectrum depended MIBs */
7541 res = _core_set_preactivation_mibs(core);
7542 if (res != MTLK_ERR_OK) {
7543 goto FINISH;
7546 //TODO failing functions
7547 #if 0
7548 res = _mtlk_core_send_current_rx_high_threshold(core);
7549 if (res != MTLK_ERR_OK) {
7550 goto FINISH;
7553 res = _mtlk_core_send_current_cca_threshold(core);
7554 if (res != MTLK_ERR_OK) {
7555 goto FINISH;
7557 #endif
7559 res = _mtlk_core_set_interfdet_do_params(core);
7560 if (res != MTLK_ERR_OK) {
7561 goto FINISH;
7564 res = _mtlk_mbss_send_preactivate_req(core);
7565 if (res != MTLK_ERR_OK) {
7566 goto FINISH;
7569 res = mtlk_set_power_limit(core);
7570 if (res != MTLK_ERR_OK) {
7571 goto FINISH;
7574 FINISH:
7575 return res;
7578 static int
7579 _core_on_full_rcvry_configure (mtlk_core_t *core)
7581 int res = MTLK_ERR_OK;
7583 res = _mtlk_mbss_preactivate(core, FALSE);
7584 return res;
7587 int __MTLK_IFUNC
7588 core_on_rcvry_configure (mtlk_core_t *core,
7589 uint32 was_connected,
7590 uint32 preactivate,
7591 uint32 rcvry_type)
7593 int i;
7594 int res = MTLK_ERR_OK;
7595 mtlk_core_t *master_core = mtlk_core_get_master(core);
7597 /* Restore CORE's and its sub modules configuration.
7598 This function is intended for recovery configurable
7599 parameters only. Non configurable parameters and
7600 variables must be set in RESTORE function.
7603 res = mtlk_mbss_send_vap_add(core);
7604 if (res != MTLK_ERR_OK) {
7605 return res;
7608 res = mtlk_core_set_net_state(core, NET_STATE_READY);
7609 if (res != MTLK_ERR_OK) {
7610 return res;
7613 res = _mtlk_core_process_antennas_configuration(core);
7614 if (res != MTLK_ERR_OK) {
7615 return res;
7618 /* Set all MIBs, beside of security & preactivation MIBs */
7619 res = mtlk_set_vap_mibs(core);
7620 if (res != MTLK_ERR_OK) {
7621 return res;
7624 res = mtlk_mib_set_security(core);
7625 if (res != MTLK_ERR_OK) {
7626 return res;
7629 for (i = 0; i < MIB_WEP_N_DEFAULT_KEYS; i++) {
7630 res = _core_set_umi_key(core, i);
7631 if (res != MTLK_ERR_OK) {
7632 return res;
7636 res = _core_set_umi_key_igtk(core, UMI_RSN_IGTK_GM_KEY_INDEX);
7637 if (res != MTLK_ERR_OK) {
7638 return res;
7641 res = _core_set_umi_key_igtk(core, UMI_RSN_IGTK_GN_KEY_INDEX);
7642 if (res != MTLK_ERR_OK) {
7643 return res;
7646 for (i = 0; i < UMI_WPS_IE_NUM; i++) {
7647 res = mtlk_core_set_gen_ie(core,
7648 core->slow_ctx->gen_ie[i],
7649 core->slow_ctx->gen_ie_len[i],
7651 if (res != MTLK_ERR_OK) {
7652 return res;
7656 if (preactivate) {
7658 /* GPIO configuration */
7659 mtlk_fw_led_gpio_cfg_t fw_led_gpio_cfg;
7660 _mtlk_core_get_fw_led_gpio_cfg(master_core, &fw_led_gpio_cfg);
7661 res = _mtlk_core_set_fw_led_gpio_cfg(master_core, &fw_led_gpio_cfg);
7662 if (res != MTLK_ERR_OK) {
7663 return res;
7667 /* LED state configuration */
7668 mtlk_fw_led_state_t fw_led_state;
7669 _mtlk_core_get_fw_led_state(master_core, &fw_led_state);
7670 res = _mtlk_core_set_fw_led_state(master_core, &fw_led_state);
7671 if (res != MTLK_ERR_OK) {
7672 return res;
7676 /* Enhanced 11B thresholds configuration */
7677 mtlk_enhanced11b_th_t thresholds;
7678 thresholds.Consecutive11bTH = MTLK_CORE_PDB_GET_INT(master_core, PARAM_DB_CONSECUTIVE_11B_TH);
7679 thresholds.Consecutive11bTH = MTLK_CORE_PDB_GET_INT(master_core, PARAM_DB_CONSECUTIVE_11N_TH);
7680 res = _mtlk_core_set_enhanced11b_th(master_core, &thresholds);
7681 if (res != MTLK_ERR_OK) {
7682 return res;
7686 /* Antenna selection configuration */
7687 mtlk_11b_antsel_t antsel;
7688 antsel.rate = MTLK_CORE_PDB_GET_INT(master_core, PARAM_DB_11B_ANTSEL_RATE);
7689 antsel.rxAnt = MTLK_CORE_PDB_GET_INT(master_core, PARAM_DB_11B_ANTSEL_RXANT);
7690 antsel.txAnt = MTLK_CORE_PDB_GET_INT(master_core, PARAM_DB_11B_ANTSEL_TXANT);
7691 _mtlk_core_set_11b_antsel(master_core, &antsel);
7694 res = mtlk_core_set_mc_ps_size(core, MTLK_CORE_PDB_GET_INT(core, PARAM_DB_FW_MC_PS_MAX_FSDUS));
7695 if (res != MTLK_ERR_OK) {
7696 return res;
7699 switch (rcvry_type) {
7700 case RCVRY_TYPE_FAST:
7701 res = _core_on_fast_rcvry_configure(master_core);
7702 if (res != MTLK_ERR_OK) {
7703 ELOG_D("CID-%04x: FAST recovery configuration failed", mtlk_vap_get_oid(core->vap_handle));
7704 return res;
7706 break;
7707 case RCVRY_TYPE_FULL:
7708 res = _core_on_full_rcvry_configure(master_core);
7709 if (res != MTLK_ERR_OK) {
7710 ELOG_D("CID-%04x: FULL recovery configuration failed", mtlk_vap_get_oid(core->vap_handle));
7711 return res;
7713 break;
7714 default:
7715 break;
7718 /* CoC configuration */
7719 res = mtlk_coc_on_rcvry_configure(master_core->slow_ctx->coc_mngmt);
7720 if (res != MTLK_ERR_OK) {
7721 return res;
7724 /* PCoC configuration */
7725 #ifdef MTCFG_PMCU_SUPPORT
7726 res = mtlk_pcoc_on_rcvry_configure(master_core->slow_ctx->pcoc_mngmt);
7727 if (res != MTLK_ERR_OK) {
7728 return res;
7730 #endif /* MTCFG_PMCU_SUPPORT */
7732 /* Coexistence configuration */
7733 if (mtlk_core_is_20_40_active(master_core)) {
7734 switch (rcvry_type) {
7735 case RCVRY_TYPE_FAST:
7736 res = mtlk_20_40_ap_on_fast_rcvry_configure(master_core->coex_20_40_sm);
7737 break;
7738 case RCVRY_TYPE_FULL:
7740 eCSM_STATES mode_to_start = CSM_STATE_20;
7741 if (MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_SELECTED_SPECTRUM_MODE) == SPECTRUM_40MHZ) {
7742 mode_to_start = CSM_STATE_20_40;
7744 res = mtlk_20_40_ap_on_full_rcvry_configure(master_core->coex_20_40_sm,
7745 mode_to_start,
7746 core->wss);
7748 break;
7749 default:
7750 break;
7752 if (res != MTLK_ERR_OK) {
7753 return res;
7758 if (was_connected) {
7759 res = mtlk_mbss_send_vap_activate(core);
7760 if (res != MTLK_ERR_OK) {
7761 ELOG_D("CID-%04x: VAP activation failed", mtlk_vap_get_oid(core->vap_handle));
7762 return res;
7765 if (BR_MODE_WDS == MTLK_CORE_HOT_PATH_PDB_GET_INT(core, CORE_DB_CORE_BRIDGE_MODE)) {
7766 wds_on_if_up(&core->slow_ctx->wds_mng);
7769 /* restore STA limits */
7770 res = _mtlk_core_set_mbss_vap_limits(core,
7771 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_STA_LIMIT_MIN),
7772 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_STA_LIMIT_MAX));
7773 if (res != MTLK_ERR_OK) {
7774 return res;
7777 mtlk_stadb_start(&core->slow_ctx->stadb);
7780 /* Start TX data */
7781 mtlk_flctrl_start_data(master_core->hw_tx_flctrl, master_core->flctrl_id);
7783 return MTLK_ERR_OK;
7786 void __MTLK_IFUNC
7787 core_schedule_recovery_task (mtlk_vap_handle_t vap_handle, void *task, mtlk_handle_t rcvry_handle, int vap_num)
7789 /* Just wrapper to put recovery task to the serializer */
7790 mtlk_core_t *core = mtlk_vap_get_core(vap_handle);
7792 _mtlk_process_emergency_task(core, (mtlk_core_task_func_t)task, rcvry_handle, &vap_num, sizeof(vap_num));
7794 return;
7797 BOOL __MTLK_IFUNC
7798 core_get_is_mac_fatal_pending (mtlk_core_t *core)
7800 return (BOOL)mtlk_osal_atomic_get(&mtlk_core_get_master(core)->is_mac_fatal_pending);
7803 void __MTLK_IFUNC
7804 core_set_is_mac_fatal_pending (mtlk_core_t *core, BOOL pending)
7806 mtlk_osal_atomic_set(&mtlk_core_get_master(core)->is_mac_fatal_pending, (uint32)pending);
7809 void __MTLK_IFUNC
7810 mtlk_core_store_calibration_channel_bit_map (mtlk_core_t *core, uint32 *storedCalibrationChannelBitMap)
7812 memcpy(core->storedCalibrationChannelBitMap,
7813 storedCalibrationChannelBitMap,
7814 sizeof(core->storedCalibrationChannelBitMap));
7817 void __MTLK_IFUNC
7818 core_on_rcvry_error (mtlk_core_t *core)
7820 mtlk_core_set_net_state_halted(core);
7823 void __MTLK_IFUNC
7824 core_on_rcvry_isol_irbd_unregister (mtlk_core_t *core)
7826 #ifdef MTCFG_RF_MANAGEMENT_MTLK
7827 mtlk_rf_mgmt_stop(core->rf_mgmt);
7828 #endif
7830 mtlk_wssd_unregister_request_handler(mtlk_vap_get_irbd(core->vap_handle), core->slow_ctx->stat_irb_handle);
7831 core->slow_ctx->stat_irb_handle = NULL;
7834 void __MTLK_IFUNC
7835 core_on_rcvry_isol (mtlk_core_t *core, uint32 rcvry_type)
7837 if (mtlk_vap_is_master_ap(core->vap_handle)) {
7838 /* Stop TX data */
7839 mtlk_flctrl_stop_data(core->hw_tx_flctrl, core->flctrl_id);
7841 /* Disable MAC WatchDog */
7842 mtlk_osal_timer_cancel_sync(&core->slow_ctx->mac_watchdog_timer);
7844 /* CoC isolation */
7845 mtlk_coc_on_rcvry_isol(core->slow_ctx->coc_mngmt);
7847 /* PCoC isolation */
7848 #ifdef MTCFG_PMCU_SUPPORT
7849 mtlk_pcoc_on_rcvry_isol(core->slow_ctx->pcoc_mngmt);
7850 #endif /* MTCFG_PMCU_SUPPORT */
7852 /* AOCs isolation */
7853 /* Coexistence isolation */
7854 mtlk_aocs_on_rcvry_isol(core->slow_ctx->aocs);
7855 switch (rcvry_type) {
7856 case RCVRY_TYPE_FAST:
7857 mtlk_aocs_stop_watchdog(core->slow_ctx->aocs);
7858 mtlk_20_40_ap_on_fast_rcvry_isol(core->coex_20_40_sm);
7859 break;
7860 case RCVRY_TYPE_FULL:
7861 _mtlk_mbss_undo_preactivate(core);
7862 mtlk_20_40_ap_on_full_rcvry_isol(core->coex_20_40_sm);
7863 break;
7864 default:
7865 break;
7868 mtlk_dot11h_on_rcvry_isol(mtlk_core_get_dfs(core));
7871 clean_all_sta_on_disconnect(core);
7873 if (mtlk_vap_is_ap(core->vap_handle)) {
7874 wds_on_if_down(&core->slow_ctx->wds_mng);
7877 mtlk_stadb_stop(&core->slow_ctx->stadb);
7878 if (rcvry_type == RCVRY_TYPE_FULL) {
7879 mtlk_cache_clear(&core->slow_ctx->cache);
7880 core->cb_scanned_bands = 0;
7883 mtlk_core_set_net_state_halted(core);
7886 int __MTLK_IFUNC
7887 core_on_rcvry_restore (mtlk_core_t *core)
7889 /* Restore CORE's data & variables
7890 not related with current configuration
7892 int res = MTLK_ERR_OK;
7894 res = mtlk_core_set_net_state(core, NET_STATE_IDLE);
7895 if (res != MTLK_ERR_OK) {
7896 return res;
7899 mtlk_sq_peer_ctx_on_rcvry_restore(core->sq, &core->sq_broadcast_ctx, MTLK_SQ_TX_LIMIT_DEFAULT);
7901 /* Restore WATCHDOG timer */
7902 if (!mtlk_vap_is_slave_ap(core->vap_handle)) {
7903 mtlk_osal_timer_set(&core->slow_ctx->mac_watchdog_timer,
7904 MTLK_CORE_PDB_GET_INT(core, PARAM_DB_CORE_MAC_WATCHDOG_TIMER_PERIOD_MS));
7907 #ifdef MTCFG_RF_MANAGEMENT_MTLK
7908 mtlk_rf_mgmt_start(core->rf_mgmt);
7909 #endif
7911 /* register back irb handler */
7912 core->slow_ctx->stat_irb_handle =
7913 mtlk_wssd_register_request_handler(mtlk_vap_get_irbd(core->vap_handle),
7914 _mtlk_core_stat_handle_request,
7915 HANDLE_T(core->slow_ctx));
7916 if (core->slow_ctx->stat_irb_handle == NULL) {
7917 return res;
7920 if (mtlk_vap_is_master(core->vap_handle)) {
7921 res = mtlk_aocs_on_rcvry_restore(core->slow_ctx->aocs);
7922 if (res != MTLK_ERR_OK) {
7923 return res;
7926 mtlk_20_40_ap_on_rcvry_restore(core->coex_20_40_sm);
7928 core->slow_ctx->last_pm_spectrum = -1;
7929 core->slow_ctx->last_pm_freq = MTLK_HW_BAND_NONE;
7932 return MTLK_ERR_OK;
7935 mtlk_dot11h_t* __MTLK_IFUNC
7936 mtlk_core_get_dfs(mtlk_core_t* core)
7938 if (mtlk_vap_is_slave_ap(core->vap_handle)) {
7939 return mtlk_core_get_master(core)->slow_ctx->dot11h;
7942 return core->slow_ctx->dot11h;
7945 void __MTLK_IFUNC
7946 mtlk_core_api_cleanup (mtlk_core_api_t *core_api)
7948 mtlk_core_t* core = HANDLE_T_PTR(mtlk_core_t, core_api->core_handle);
7950 _mtlk_core_cleanup(core);
7951 mtlk_fast_mem_free(core);
7954 static int
7955 _mtlk_core_set_sm_required(mtlk_core_t *core, BOOL enable_sm_required)
7957 MTLK_ASSERT(mtlk_vap_is_master_ap(core->vap_handle));
7959 if (TRUE == enable_sm_required) {
7960 mtlk_aocs_enable_smrequired(core->slow_ctx->aocs);
7961 } else {
7962 mtlk_aocs_disable_smrequired(core->slow_ctx->aocs);
7964 return MTLK_ERR_OK;
7967 static __INLINE BOOL
7968 _mtlk_core_has_connections(mtlk_core_t *core)
7970 return !mtlk_stadb_is_empty(&core->slow_ctx->stadb);
7973 static __INLINE int
7974 _mtlk_core_save_tx_power_limit(mtlk_core_t *core, mtlk_tx_power_limit_cfg_t *cfg)
7977 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_POWER_LIMIT_11B_BOOST, cfg->field_01);
7978 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_POWER_LIMIT_BPSK_BOOST, cfg->field_02);
7979 MTLK_CORE_PDB_SET_INT(core, PARAM_DB_CORE_POWER_LIMIT_AUTO_RESPONCE, cfg->field_03);
7981 /* send UM_MAN_CHANGE_TX_POWER_LIMIT_REQ only after "MIB_TPC_ANT_"
7982 * configuration, issue WAVE300_SW-2705 */
7983 if (mtlk_vap_manager_get_active_vaps_number(mtlk_vap_get_manager(core->vap_handle))) {
7984 return mtlk_set_power_limit(core);
7987 return MTLK_ERR_OK;
7990 BOOL __MTLK_IFUNC
7991 mtlk_core_is_connected (mtlk_core_t *core)
7993 return mtlk_core_net_state_is_connected(mtlk_core_get_net_state(core));
7996 BOOL __MTLK_IFUNC
7997 mtlk_core_is_halted (mtlk_core_t *core)
7999 return (mtlk_core_get_net_state(core) & NET_STATE_HALTED);