1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15
16 #include <drv_types.h>
17 #include <hal_data.h>
18 #ifdef CONFIG_RTW_80211K
19 #include "rtw_rm_fsm.h"
20 #include "rtw_rm_util.h"
21
22 struct fsm_state {
23 u8 *name;
24 int(*fsm_func)(struct rm_obj *prm, enum RM_EV_ID evid);
25 };
26
27 static void rm_state_initial(struct rm_obj *prm);
28 static void rm_state_goto(struct rm_obj *prm, enum RM_STATE rm_state);
29 static void rm_state_run(struct rm_obj *prm, enum RM_EV_ID evid);
30 static struct rm_event *rm_dequeue_ev(_queue *queue);
31 static struct rm_obj *rm_dequeue_rm(_queue *queue);
32
rm_timer_callback(void * data)33 void rm_timer_callback(void *data)
34 {
35 int i;
36 _adapter *padapter = (_adapter *)data;
37 struct rm_priv *prmpriv = &padapter->rmpriv;
38 struct rm_clock *pclock;
39
40
41 /* deal with clock */
42 for (i=0;i<RM_TIMER_NUM;i++) {
43 pclock = &prmpriv->clock[i];
44 if (pclock->prm == NULL
45 ||(ATOMIC_READ(&(pclock->counter)) == 0))
46 continue;
47
48 ATOMIC_DEC(&(pclock->counter));
49
50 if (ATOMIC_READ(&(pclock->counter)) == 0)
51 rm_post_event(pclock->prm->psta->padapter,
52 pclock->prm->rmid, prmpriv->clock[i].evid);
53 }
54 _set_timer(&prmpriv->rm_timer, CLOCK_UNIT);
55 }
56
rtw_init_rm(_adapter * padapter)57 int rtw_init_rm(_adapter *padapter)
58 {
59 struct rm_priv *prmpriv = &padapter->rmpriv;
60
61
62 RTW_INFO("RM: %s\n",__func__);
63 _rtw_init_queue(&(prmpriv->rm_queue));
64 _rtw_init_queue(&(prmpriv->ev_queue));
65
66 /* bit 0-7 */
67 prmpriv->rm_en_cap_def[0] = 0
68 | BIT(RM_LINK_MEAS_CAP_EN)
69 | BIT(RM_NB_REP_CAP_EN)
70 /*| BIT(RM_PARAL_MEAS_CAP_EN)*/
71 | BIT(RM_REPEAT_MEAS_CAP_EN)
72 | BIT(RM_BCN_PASSIVE_MEAS_CAP_EN)
73 | BIT(RM_BCN_ACTIVE_MEAS_CAP_EN)
74 | BIT(RM_BCN_TABLE_MEAS_CAP_EN)
75 /*| BIT(RM_BCN_MEAS_REP_COND_CAP_EN)*/;
76
77 /* bit 8-15 */
78 prmpriv->rm_en_cap_def[1] = 0
79 /*| BIT(RM_FRAME_MEAS_CAP_EN - 8)*/
80 #ifdef CONFIG_RTW_ACS
81 | BIT(RM_CH_LOAD_CAP_EN - 8)
82 | BIT(RM_NOISE_HISTO_CAP_EN - 8)
83 #endif
84 /*| BIT(RM_STATIS_MEAS_CAP_EN - 8)*/
85 /*| BIT(RM_LCI_MEAS_CAP_EN - 8)*/
86 /*| BIT(RM_LCI_AMIMUTH_CAP_EN - 8)*/
87 /*| BIT(RM_TRANS_STREAM_CAT_MEAS_CAP_EN - 8)*/
88 /*| BIT(RM_TRIG_TRANS_STREAM_CAT_MEAS_CAP_EN - 8)*/;
89
90 /* bit 16-23 */
91 prmpriv->rm_en_cap_def[2] = 0
92 /*| BIT(RM_AP_CH_REP_CAP_EN - 16)*/
93 /*| BIT(RM_RM_MIB_CAP_EN - 16)*/
94 /*| BIT(RM_OP_CH_MAX_MEAS_DUR0 - 16)*/
95 /*| BIT(RM_OP_CH_MAX_MEAS_DUR1 - 16)*/
96 /*| BIT(RM_OP_CH_MAX_MEAS_DUR2 - 16)*/
97 /*| BIT(RM_NONOP_CH_MAX_MEAS_DUR0 - 16)*/
98 /*| BIT(RM_NONOP_CH_MAX_MEAS_DUR1 - 16)*/
99 /*| BIT(RM_NONOP_CH_MAX_MEAS_DUR2 - 16)*/;
100
101 /* bit 24-31 */
102 prmpriv->rm_en_cap_def[3] = 0
103 /*| BIT(RM_MEAS_PILOT_CAP0 - 24)*/
104 /*| BIT(RM_MEAS_PILOT_CAP1 - 24)*/
105 /*| BIT(RM_MEAS_PILOT_CAP2 - 24)*/
106 /*| BIT(RM_MEAS_PILOT_TRANS_INFO_CAP_EN - 24)*/
107 /*| BIT(RM_NB_REP_TSF_OFFSET_CAP_EN - 24)*/
108 | BIT(RM_RCPI_MEAS_CAP_EN - 24)
109 | BIT(RM_RSNI_MEAS_CAP_EN - 24)
110 /*| BIT(RM_BSS_AVG_ACCESS_DELAY_CAP_EN - 24)*/;
111
112 /* bit 32-39 */
113 prmpriv->rm_en_cap_def[4] = 0
114 /*| BIT(RM_BSS_AVG_ACCESS_DELAY_CAP_EN - 32)*/
115 /*| BIT(RM_AVALB_ADMIS_CAPACITY_CAP_EN - 32)*/
116 /*| BIT(RM_ANT_CAP_EN - 32)*/;
117
118 prmpriv->enable = _TRUE;
119
120 /* clock timer */
121 rtw_init_timer(&prmpriv->rm_timer,
122 padapter, rm_timer_callback, padapter);
123 _set_timer(&prmpriv->rm_timer, CLOCK_UNIT);
124
125 prmpriv->meas_token = 1;
126 return _SUCCESS;
127 }
128
rtw_deinit_rm(_adapter * padapter)129 int rtw_deinit_rm(_adapter *padapter)
130 {
131 struct rm_priv *prmpriv = &padapter->rmpriv;
132 struct rm_obj *prm;
133 struct rm_event *pev;
134
135
136 RTW_INFO("RM: %s\n",__func__);
137 prmpriv->enable = _FALSE;
138 _cancel_timer_ex(&prmpriv->rm_timer);
139
140 /* free all events and measurements */
141 while((pev = rm_dequeue_ev(&prmpriv->ev_queue)) != NULL)
142 rtw_mfree((void *)pev, sizeof(struct rm_event));
143
144 while((prm = rm_dequeue_rm(&prmpriv->rm_queue)) != NULL)
145 rm_state_run(prm, RM_EV_cancel);
146
147 _rtw_deinit_queue(&(prmpriv->rm_queue));
148 _rtw_deinit_queue(&(prmpriv->ev_queue));
149
150 return _SUCCESS;
151 }
152
rtw_free_rm_priv(_adapter * padapter)153 int rtw_free_rm_priv(_adapter *padapter)
154 {
155 return rtw_deinit_rm(padapter);
156 }
157
rm_enqueue_ev(_queue * queue,struct rm_event * obj,bool to_head)158 static int rm_enqueue_ev(_queue *queue, struct rm_event *obj, bool to_head)
159 {
160 _irqL irqL;
161
162
163 if (obj == NULL)
164 return _FAIL;
165
166 _enter_critical(&queue->lock, &irqL);
167
168 if (to_head)
169 rtw_list_insert_head(&obj->list, &queue->queue);
170 else
171 rtw_list_insert_tail(&obj->list, &queue->queue);
172
173 _exit_critical(&queue->lock, &irqL);
174
175 return _SUCCESS;
176 }
177
rm_set_clock(struct rm_obj * prm,u32 ms,enum RM_EV_ID evid)178 static void rm_set_clock(struct rm_obj *prm, u32 ms, enum RM_EV_ID evid)
179 {
180 ATOMIC_SET(&(prm->pclock->counter), (ms/CLOCK_UNIT));
181 prm->pclock->evid = evid;
182 }
183
rm_alloc_clock(_adapter * padapter,struct rm_obj * prm)184 static struct rm_clock *rm_alloc_clock(_adapter *padapter, struct rm_obj *prm)
185 {
186 int i;
187 struct rm_priv *prmpriv = &padapter->rmpriv;
188 struct rm_clock *pclock = NULL;
189
190
191 for (i=0;i<RM_TIMER_NUM;i++) {
192 pclock = &prmpriv->clock[i];
193
194 if (pclock->prm == NULL) {
195 pclock->prm = prm;
196 ATOMIC_SET(&(pclock->counter), 0);
197 pclock->evid = RM_EV_max;
198 break;
199 }
200 }
201 return pclock;
202 }
203
rm_cancel_clock(struct rm_obj * prm)204 static void rm_cancel_clock(struct rm_obj *prm)
205 {
206 ATOMIC_SET(&(prm->pclock->counter), 0);
207 prm->pclock->evid = RM_EV_max;
208 }
209
rm_free_clock(struct rm_clock * pclock)210 static void rm_free_clock(struct rm_clock *pclock)
211 {
212 pclock->prm = NULL;
213 ATOMIC_SET(&(pclock->counter), 0);
214 pclock->evid = RM_EV_max;
215 }
216
is_list_linked(const struct list_head * head)217 static int is_list_linked(const struct list_head *head)
218 {
219 return head->prev != NULL;
220 }
221
rm_free_rmobj(struct rm_obj * prm)222 void rm_free_rmobj(struct rm_obj *prm)
223 {
224 if (is_list_linked(&prm->list))
225 rtw_list_delete(&prm->list);
226
227 if (prm->q.pssid)
228 rtw_mfree(prm->q.pssid, strlen(prm->q.pssid)+1);
229
230 if (prm->q.opt.bcn.req_start)
231 rtw_mfree(prm->q.opt.bcn.req_start,
232 prm->q.opt.bcn.req_len);
233
234 if (prm->pclock)
235 rm_free_clock(prm->pclock);
236
237 rtw_mfree((void *)prm, sizeof(struct rm_obj));
238 }
239
rm_alloc_rmobj(_adapter * padapter)240 struct rm_obj *rm_alloc_rmobj(_adapter *padapter)
241 {
242 struct rm_obj *prm;
243
244
245 prm = (struct rm_obj *)rtw_malloc(sizeof(struct rm_obj));
246 if (prm == NULL)
247 return NULL;
248
249 _rtw_memset(prm, 0, sizeof(struct rm_obj));
250
251 /* alloc timer */
252 if ((prm->pclock = rm_alloc_clock(padapter, prm)) == NULL) {
253 rm_free_rmobj(prm);
254 return NULL;
255 }
256 return prm;
257 }
258
rm_enqueue_rmobj(_adapter * padapter,struct rm_obj * prm,bool to_head)259 int rm_enqueue_rmobj(_adapter *padapter, struct rm_obj *prm, bool to_head)
260 {
261 _irqL irqL;
262 struct rm_priv *prmpriv = &padapter->rmpriv;
263 _queue *queue = &prmpriv->rm_queue;
264
265
266 if (prm == NULL)
267 return _FAIL;
268
269 _enter_critical(&queue->lock, &irqL);
270 if (to_head)
271 rtw_list_insert_head(&prm->list, &queue->queue);
272 else
273 rtw_list_insert_tail(&prm->list, &queue->queue);
274 _exit_critical(&queue->lock, &irqL);
275
276 rm_state_initial(prm);
277
278 return _SUCCESS;
279 }
280
rm_dequeue_rm(_queue * queue)281 static struct rm_obj *rm_dequeue_rm(_queue *queue)
282 {
283 _irqL irqL;
284 struct rm_obj *prm;
285
286
287 _enter_critical(&queue->lock, &irqL);
288 if (rtw_is_list_empty(&(queue->queue)))
289 prm = NULL;
290 else {
291 prm = LIST_CONTAINOR(get_next(&(queue->queue)),
292 struct rm_obj, list);
293 /* rtw_list_delete(&prm->list); */
294 }
295 _exit_critical(&queue->lock, &irqL);
296
297 return prm;
298 }
299
rm_dequeue_ev(_queue * queue)300 static struct rm_event *rm_dequeue_ev(_queue *queue)
301 {
302 _irqL irqL;
303 struct rm_event *ev;
304
305
306 _enter_critical(&queue->lock, &irqL);
307 if (rtw_is_list_empty(&(queue->queue)))
308 ev = NULL;
309 else {
310 ev = LIST_CONTAINOR(get_next(&(queue->queue)),
311 struct rm_event, list);
312 rtw_list_delete(&ev->list);
313 }
314 _exit_critical(&queue->lock, &irqL);
315
316 return ev;
317 }
318
_rm_get_rmobj(_queue * queue,u32 rmid)319 static struct rm_obj *_rm_get_rmobj(_queue *queue, u32 rmid)
320 {
321 _irqL irqL;
322 _list *phead, *plist;
323 struct rm_obj *prm = NULL;
324
325
326 if (rmid == 0)
327 return NULL;
328
329 _enter_critical(&queue->lock, &irqL);
330
331 phead = get_list_head(queue);
332 plist = get_next(phead);
333 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
334
335 prm = LIST_CONTAINOR(plist, struct rm_obj, list);
336 if (rmid == (prm->rmid)) {
337 _exit_critical(&queue->lock, &irqL);
338 return prm;
339 }
340 plist = get_next(plist);
341 }
342 _exit_critical(&queue->lock, &irqL);
343
344 return NULL;
345 }
346
rm_get_psta(_adapter * padapter,u32 rmid)347 struct sta_info *rm_get_psta(_adapter *padapter, u32 rmid)
348 {
349 struct rm_priv *prmpriv = &padapter->rmpriv;
350 struct rm_obj *prm;
351
352
353 prm = _rm_get_rmobj(&prmpriv->rm_queue, rmid);
354
355 if (prm)
356 return prm->psta;
357
358 return NULL;
359 }
360
rm_get_rmobj(_adapter * padapter,u32 rmid)361 struct rm_obj *rm_get_rmobj(_adapter *padapter, u32 rmid)
362 {
363 struct rm_priv *prmpriv = &padapter->rmpriv;
364
365 return _rm_get_rmobj(&prmpriv->rm_queue, rmid);
366 }
367
rtw_rm_post_envent_cmd(_adapter * padapter,u32 rmid,u8 evid)368 u8 rtw_rm_post_envent_cmd(_adapter *padapter, u32 rmid, u8 evid)
369 {
370 struct cmd_obj *pcmd;
371 struct rm_event *pev;
372 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
373 u8 res = _SUCCESS;
374
375
376 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
377 if (pcmd == NULL) {
378 res = _FAIL;
379 goto exit;
380 }
381 pev = (struct rm_event*)rtw_zmalloc(sizeof(struct rm_event));
382
383 if (pev == NULL) {
384 rtw_mfree((u8 *) pcmd, sizeof(struct cmd_obj));
385 res = _FAIL;
386 goto exit;
387 }
388 pev->rmid = rmid;
389 pev->evid = evid;
390
391 init_h2fwcmd_w_parm_no_rsp(pcmd, pev, CMD_RM_POST_EVENT);
392 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
393 exit:
394 return res;
395 }
396
rm_post_event(_adapter * padapter,u32 rmid,enum RM_EV_ID evid)397 int rm_post_event(_adapter *padapter, u32 rmid, enum RM_EV_ID evid)
398 {
399 if (padapter->rmpriv.enable == _FALSE)
400 return _FALSE;
401
402 RTW_INFO("RM: post asyn %s to rmid=%x\n", rm_event_name(evid), rmid);
403 rtw_rm_post_envent_cmd(padapter, rmid, evid);
404 return _SUCCESS;
405 }
406
_rm_post_event(_adapter * padapter,u32 rmid,enum RM_EV_ID evid)407 int _rm_post_event(_adapter *padapter, u32 rmid, enum RM_EV_ID evid)
408 {
409 struct rm_priv *prmpriv = &padapter->rmpriv;
410 struct rm_event *pev;
411
412 if (evid >= RM_EV_max || rmid == 0)
413 return _FALSE;
414
415 pev = (struct rm_event *)rtw_malloc(sizeof(struct rm_event));
416 if (pev == NULL)
417 return _FALSE;
418
419 pev->rmid = rmid;
420 pev->evid = evid;
421
422 RTW_INFO("RM: post sync %s to rmid=%x\n", rm_event_name(evid), rmid);
423 rm_enqueue_ev(&prmpriv->ev_queue, pev, FALSE);
424
425 return _SUCCESS;
426 }
427
rm_bcast_aid_handler(_adapter * padapter,struct rm_event * pev)428 static void rm_bcast_aid_handler(_adapter *padapter, struct rm_event *pev)
429 {
430 _irqL irqL;
431 _list *phead, *plist;
432 _queue *queue = &padapter->rmpriv.rm_queue;
433 struct rm_obj *prm;
434
435
436 _enter_critical(&queue->lock, &irqL);
437 phead = get_list_head(queue);
438 plist = get_next(phead);
439 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
440
441 prm = LIST_CONTAINOR(plist, struct rm_obj, list);
442 plist = get_next(plist);
443 if (RM_GET_AID(pev->rmid) == RM_GET_AID(prm->rmid)) {
444 _exit_critical(&queue->lock, &irqL);
445 rm_state_run(prm, pev->evid);
446 _enter_critical(&queue->lock, &irqL);
447 }
448 }
449 _exit_critical(&queue->lock, &irqL);
450 return;
451 }
452
453 /* main handler of RM (Resource Management) */
rm_handler(_adapter * padapter,struct rm_event * pe)454 void rm_handler(_adapter *padapter, struct rm_event *pe)
455 {
456 int i;
457 struct rm_priv *prmpriv = &padapter->rmpriv;
458 struct rm_obj *prm;
459 struct rm_event *pev;
460
461
462 /* dequeue event */
463 while((pev = rm_dequeue_ev(&prmpriv->ev_queue)) != NULL)
464 {
465 if (RM_IS_ID_FOR_ALL(pev->rmid)) {
466 /* apply to all aid mateched measurement */
467 rm_bcast_aid_handler(padapter, pev);
468 rtw_mfree((void *)pev, sizeof(struct rm_event));
469 continue;
470 }
471
472 /* retrieve rmobj */
473 prm = _rm_get_rmobj(&prmpriv->rm_queue, pev->rmid);
474 if (prm == NULL) {
475 RTW_ERR("RM: rmid=%x event=%s doesn't find rm obj\n",
476 pev->rmid, rm_event_name(pev->evid));
477 rtw_mfree((void *)pev, sizeof(struct rm_event));
478 return;
479 }
480 /* run state machine */
481 rm_state_run(prm, pev->evid);
482 rtw_mfree((void *)pev, sizeof(struct rm_event));
483 }
484 }
485
rm_issue_meas_req(struct rm_obj * prm)486 static int rm_issue_meas_req(struct rm_obj *prm)
487 {
488 switch (prm->q.action_code) {
489 case RM_ACT_RADIO_MEAS_REQ:
490 switch (prm->q.m_type) {
491 case bcn_req:
492 case ch_load_req:
493 case noise_histo_req:
494 issue_radio_meas_req(prm);
495 break;
496 default:
497 break;
498 } /* meas_type */
499 break;
500 case RM_ACT_NB_REP_REQ:
501 /* issue neighbor request */
502 issue_nb_req(prm);
503 break;
504 case RM_ACT_LINK_MEAS_REQ:
505 issue_link_meas_req(prm);
506 break;
507 default:
508 return _FALSE;
509 } /* action_code */
510
511 return _SUCCESS;
512 }
513
514 /*
515 * RM state machine
516 */
517
rm_state_idle(struct rm_obj * prm,enum RM_EV_ID evid)518 static int rm_state_idle(struct rm_obj *prm, enum RM_EV_ID evid)
519 {
520 _adapter *padapter = prm->psta->padapter;
521 u8 val8;
522 u32 val32;
523
524
525 prm->p.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
526
527 switch (evid) {
528 case RM_EV_state_in:
529 switch (prm->q.action_code) {
530 case RM_ACT_RADIO_MEAS_REQ:
531 /* copy attrib from meas_req to meas_rep */
532 prm->p.action_code = RM_ACT_RADIO_MEAS_REP;
533 prm->p.diag_token = prm->q.diag_token;
534 prm->p.e_id = _MEAS_RSP_IE_;
535 prm->p.m_token = prm->q.m_token;
536 prm->p.m_type = prm->q.m_type;
537 prm->p.rpt = prm->q.rpt;
538 prm->p.ch_num = prm->q.ch_num;
539 prm->p.op_class = prm->q.op_class;
540
541 if (prm->q.m_type == ch_load_req
542 || prm->q.m_type == noise_histo_req) {
543 /*
544 * phydm measure current ch periodically
545 * scan current ch is not necessary
546 */
547 val8 = padapter->mlmeextpriv.cur_channel;
548 if (prm->q.ch_num == val8)
549 prm->poll_mode = 1;
550 }
551 RTW_INFO("RM: rmid=%x %s switch in repeat=%u\n",
552 prm->rmid, rm_type_req_name(prm->q.m_type),
553 prm->q.rpt);
554 break;
555 case RM_ACT_NB_REP_REQ:
556 prm->p.action_code = RM_ACT_NB_REP_RESP;
557 RTW_INFO("RM: rmid=%x Neighbor request switch in\n",
558 prm->rmid);
559 break;
560 case RM_ACT_LINK_MEAS_REQ:
561 prm->p.diag_token = prm->q.diag_token;
562 prm->p.action_code = RM_ACT_LINK_MEAS_REP;
563 RTW_INFO("RM: rmid=%x Link meas switch in\n",
564 prm->rmid);
565 break;
566 default:
567 prm->p.action_code = prm->q.action_code;
568 rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);
569 RTW_INFO("RM: rmid=%x recv unknown action %d\n",
570 prm->rmid,prm->p.action_code);
571 break;
572 } /* switch() */
573
574 if (prm->rmid & RM_MASTER) {
575 if (rm_issue_meas_req(prm) == _SUCCESS)
576 rm_state_goto(prm, RM_ST_WAIT_MEAS);
577 else
578 rm_state_goto(prm, RM_ST_END);
579 return _SUCCESS;
580 } else {
581 rm_state_goto(prm, RM_ST_DO_MEAS);
582 return _SUCCESS;
583 }
584
585 if (prm->p.m_mode) {
586 issue_null_reply(prm);
587 rm_state_goto(prm, RM_ST_END);
588 return _SUCCESS;
589 }
590 if (prm->q.rand_intvl) {
591 /* get low tsf to generate random interval */
592 val32 = rtw_read32(padapter, REG_TSFTR);
593 val32 = val32 % prm->q.rand_intvl;
594 RTW_INFO("RM: rmid=%x rand_intval=%d, rand=%d\n",
595 prm->rmid, (int)prm->q.rand_intvl,val32);
596 rm_set_clock(prm, prm->q.rand_intvl,
597 RM_EV_delay_timer_expire);
598 return _SUCCESS;
599 }
600 break;
601 case RM_EV_delay_timer_expire:
602 rm_state_goto(prm, RM_ST_DO_MEAS);
603 break;
604 case RM_EV_cancel:
605 rm_state_goto(prm, RM_ST_END);
606 break;
607 case RM_EV_state_out:
608 rm_cancel_clock(prm);
609 break;
610 default:
611 break;
612 }
613 return _SUCCESS;
614 }
615
616 /* we do the measuring */
rm_state_do_meas(struct rm_obj * prm,enum RM_EV_ID evid)617 static int rm_state_do_meas(struct rm_obj *prm, enum RM_EV_ID evid)
618 {
619 _adapter *padapter = prm->psta->padapter;
620 u8 val8;
621 u64 val64;
622
623
624 switch (evid) {
625 case RM_EV_state_in:
626 if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
627 switch (prm->q.m_type) {
628 case bcn_req:
629 if (prm->q.m_mode == bcn_req_bcn_table) {
630 RTW_INFO("RM: rmid=%x Beacon table\n",
631 prm->rmid);
632 _rm_post_event(padapter, prm->rmid,
633 RM_EV_survey_done);
634 return _SUCCESS;
635 }
636 break;
637 case ch_load_req:
638 case noise_histo_req:
639 if (prm->poll_mode)
640 _rm_post_event(padapter, prm->rmid,
641 RM_EV_survey_done);
642 return _SUCCESS;
643 default:
644 rm_state_goto(prm, RM_ST_END);
645 return _SUCCESS;
646 }
647
648 if (!ready_for_scan(prm)) {
649 prm->wait_busy = RM_BUSY_TRAFFIC_TIMES;
650 RTW_INFO("RM: wait busy traffic - %d\n",
651 prm->wait_busy);
652 rm_set_clock(prm, RM_WAIT_BUSY_TIMEOUT,
653 RM_EV_busy_timer_expire);
654 return _SUCCESS;
655 }
656 } else if (prm->q.action_code == RM_ACT_LINK_MEAS_REQ) {
657 ; /* do nothing */
658 rm_state_goto(prm, RM_ST_SEND_REPORT);
659 return _SUCCESS;
660 }
661 _rm_post_event(padapter, prm->rmid, RM_EV_start_meas);
662 break;
663 case RM_EV_start_meas:
664 if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
665 /* resotre measurement start time */
666 prm->meas_start_time = rtw_hal_get_tsftr_by_port(padapter
667 , rtw_hal_get_port(padapter));
668
669 switch (prm->q.m_type) {
670 case bcn_req:
671 val8 = 1; /* Enable free run counter */
672 prm->free_run_counter_valid = rtw_hal_set_hwreg(
673 padapter, HW_VAR_FREECNT, &val8);
674
675 rm_sitesurvey(prm);
676 break;
677 case ch_load_req:
678 case noise_histo_req:
679 rm_sitesurvey(prm);
680 break;
681 default:
682 rm_state_goto(prm, RM_ST_END);
683 return _SUCCESS;
684 break;
685 }
686 }
687 /* handle measurement timeout */
688 rm_set_clock(prm, RM_MEAS_TIMEOUT, RM_EV_meas_timer_expire);
689 break;
690 case RM_EV_survey_done:
691 if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
692 switch (prm->q.m_type) {
693 case bcn_req:
694 rm_cancel_clock(prm);
695 rm_state_goto(prm, RM_ST_SEND_REPORT);
696 return _SUCCESS;
697 case ch_load_req:
698 case noise_histo_req:
699 retrieve_radio_meas_result(prm);
700
701 if (rm_radio_meas_report_cond(prm) == _SUCCESS)
702 rm_state_goto(prm, RM_ST_SEND_REPORT);
703 else
704 rm_set_clock(prm, RM_COND_INTVL,
705 RM_EV_retry_timer_expire);
706 break;
707 default:
708 rm_state_goto(prm, RM_ST_END);
709 return _SUCCESS;
710 }
711 }
712 break;
713 case RM_EV_meas_timer_expire:
714 RTW_INFO("RM: rmid=%x measurement timeount\n",prm->rmid);
715 rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
716 issue_null_reply(prm);
717 rm_state_goto(prm, RM_ST_END);
718 break;
719 case RM_EV_busy_timer_expire:
720 if (!ready_for_scan(prm) && prm->wait_busy--) {
721 RTW_INFO("RM: wait busy - %d\n",prm->wait_busy);
722 rm_set_clock(prm, RM_WAIT_BUSY_TIMEOUT,
723 RM_EV_busy_timer_expire);
724 break;
725 }
726 else if (prm->wait_busy <= 0) {
727 RTW_INFO("RM: wait busy timeout\n");
728 rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
729 issue_null_reply(prm);
730 rm_state_goto(prm, RM_ST_END);
731 return _SUCCESS;
732 }
733 _rm_post_event(padapter, prm->rmid, RM_EV_start_meas);
734 break;
735 case RM_EV_request_timer_expire:
736 rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
737 issue_null_reply(prm);
738 rm_state_goto(prm, RM_ST_END);
739 break;
740 case RM_EV_retry_timer_expire:
741 /* expired due to meas condition mismatch, meas again */
742 _rm_post_event(padapter, prm->rmid, RM_EV_start_meas);
743 break;
744 case RM_EV_cancel:
745 rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
746 issue_null_reply(prm);
747 rm_state_goto(prm, RM_ST_END);
748 break;
749 case RM_EV_state_out:
750 rm_cancel_clock(prm);
751 /* resotre measurement end time */
752 prm->meas_end_time = rtw_hal_get_tsftr_by_port(padapter
753 , rtw_hal_get_port(padapter));
754
755 val8 = 0; /* Disable free run counter */
756 rtw_hal_set_hwreg(padapter, HW_VAR_FREECNT, &val8);
757 break;
758 default:
759 break;
760 }
761
762 return _SUCCESS;
763 }
764
rm_state_wait_meas(struct rm_obj * prm,enum RM_EV_ID evid)765 static int rm_state_wait_meas(struct rm_obj *prm, enum RM_EV_ID evid)
766 {
767 u8 val8;
768 u64 val64;
769
770
771 switch (evid) {
772 case RM_EV_state_in:
773 /* we create meas_req, waiting for peer report */
774 rm_set_clock(prm, RM_REQ_TIMEOUT,
775 RM_EV_request_timer_expire);
776 break;
777 case RM_EV_recv_rep:
778 rm_state_goto(prm, RM_ST_RECV_REPORT);
779 break;
780 case RM_EV_request_timer_expire:
781 case RM_EV_cancel:
782 rm_state_goto(prm, RM_ST_END);
783 break;
784 case RM_EV_state_out:
785 rm_cancel_clock(prm);
786 break;
787 default:
788 break;
789 }
790 return _SUCCESS;
791 }
792
rm_state_send_report(struct rm_obj * prm,enum RM_EV_ID evid)793 static int rm_state_send_report(struct rm_obj *prm, enum RM_EV_ID evid)
794 {
795 u8 val8;
796
797
798 switch (evid) {
799 case RM_EV_state_in:
800 /* we have to issue report */
801 if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
802 switch (prm->q.m_type) {
803 case bcn_req:
804 issue_beacon_rep(prm);
805 break;
806 case ch_load_req:
807 case noise_histo_req:
808 issue_radio_meas_rep(prm);
809 break;
810 default:
811 rm_state_goto(prm, RM_ST_END);
812 return _SUCCESS;
813 }
814
815 } else if (prm->q.action_code == RM_ACT_LINK_MEAS_REQ) {
816 issue_link_meas_rep(prm);
817 rm_state_goto(prm, RM_ST_END);
818 return _SUCCESS;
819
820 } else {
821 rm_state_goto(prm, RM_ST_END);
822 return _SUCCESS;
823 }
824
825 /* check repeat */
826 if (prm->p.rpt) {
827 RTW_INFO("RM: rmid=%x repeat=%u/%u\n",
828 prm->rmid, prm->p.rpt,
829 prm->q.rpt);
830 prm->p.rpt--;
831 /*
832 * we recv meas_req,
833 * delay for a wihile and than meas again
834 */
835 if (prm->poll_mode)
836 rm_set_clock(prm, RM_REPT_POLL_INTVL,
837 RM_EV_repeat_delay_expire);
838 else
839 rm_set_clock(prm, RM_REPT_SCAN_INTVL,
840 RM_EV_repeat_delay_expire);
841 return _SUCCESS;
842 }
843 /* we are done */
844 rm_state_goto(prm, RM_ST_END);
845 break;
846 case RM_EV_repeat_delay_expire:
847 rm_state_goto(prm, RM_ST_DO_MEAS);
848 break;
849 case RM_EV_cancel:
850 rm_state_goto(prm, RM_ST_END);
851 break;
852 case RM_EV_state_out:
853 rm_cancel_clock(prm);
854 break;
855 default:
856 break;
857 }
858 return _SUCCESS;
859 }
860
rm_state_recv_report(struct rm_obj * prm,enum RM_EV_ID evid)861 static int rm_state_recv_report(struct rm_obj *prm, enum RM_EV_ID evid)
862 {
863 u8 val8;
864
865
866 switch (evid) {
867 case RM_EV_state_in:
868 /* we issue meas_req, got peer's meas report */
869 switch (prm->p.action_code) {
870 case RM_ACT_RADIO_MEAS_REP:
871 /* check refuse, incapable and repeat */
872 val8 = prm->p.m_mode;
873 if (val8) {
874 RTW_INFO("RM: rmid=%x peer reject (%s repeat=%d)\n",
875 prm->rmid,
876 val8|MEAS_REP_MOD_INCAP?"INCAP":
877 val8|MEAS_REP_MOD_REFUSE?"REFUSE":
878 val8|MEAS_REP_MOD_LATE?"LATE":"",
879 prm->p.rpt);
880 rm_state_goto(prm, RM_ST_END);
881 return _SUCCESS;
882 }
883 break;
884 case RM_ACT_NB_REP_RESP:
885 /* report to upper layer if needing */
886 rm_state_goto(prm, RM_ST_END);
887 return _SUCCESS;
888 default:
889 rm_state_goto(prm, RM_ST_END);
890 return _SUCCESS;
891 }
892 /* check repeat */
893 if (prm->p.rpt) {
894 RTW_INFO("RM: rmid=%x repeat=%u/%u\n",
895 prm->rmid, prm->p.rpt,
896 prm->q.rpt);
897 prm->p.rpt--;
898 /* waitting more report */
899 rm_state_goto(prm, RM_ST_WAIT_MEAS);
900 break;
901 }
902 /* we are done */
903 rm_state_goto(prm, RM_ST_END);
904 break;
905 case RM_EV_cancel:
906 rm_state_goto(prm, RM_ST_END);
907 break;
908 case RM_EV_state_out:
909 rm_cancel_clock(prm);
910 break;
911 default:
912 break;
913 }
914 return _SUCCESS;
915 }
916
rm_state_end(struct rm_obj * prm,enum RM_EV_ID evid)917 static int rm_state_end(struct rm_obj *prm, enum RM_EV_ID evid)
918 {
919 switch (evid) {
920 case RM_EV_state_in:
921 _rm_post_event(prm->psta->padapter, prm->rmid, RM_EV_state_out);
922 break;
923
924 case RM_EV_cancel:
925 case RM_EV_state_out:
926 default:
927 rm_free_rmobj(prm);
928 break;
929 }
930 return _SUCCESS;
931 }
932
933 struct fsm_state rm_fsm[] = {
934 {"RM_ST_IDLE", rm_state_idle},
935 {"RM_ST_DO_MEAS", rm_state_do_meas},
936 {"RM_ST_WAIT_MEAS", rm_state_wait_meas},
937 {"RM_ST_SEND_REPORT", rm_state_send_report},
938 {"RM_ST_RECV_REPORT", rm_state_recv_report},
939 {"RM_ST_END", rm_state_end}
940 };
941
rm_state_name(enum RM_STATE state)942 char *rm_state_name(enum RM_STATE state)
943 {
944 return rm_fsm[state].name;
945 }
946
rm_event_name(enum RM_EV_ID evid)947 char *rm_event_name(enum RM_EV_ID evid)
948 {
949 switch(evid) {
950 case RM_EV_state_in:
951 return "RM_EV_state_in";
952 case RM_EV_busy_timer_expire:
953 return "RM_EV_busy_timer_expire";
954 case RM_EV_delay_timer_expire:
955 return "RM_EV_delay_timer_expire";
956 case RM_EV_meas_timer_expire:
957 return "RM_EV_meas_timer_expire";
958 case RM_EV_repeat_delay_expire:
959 return "RM_EV_repeat_delay_expire";
960 case RM_EV_retry_timer_expire:
961 return "RM_EV_retry_timer_expire";
962 case RM_EV_request_timer_expire:
963 return "RM_EV_request_timer_expire";
964 case RM_EV_wait_report:
965 return "RM_EV_wait_report";
966 case RM_EV_start_meas:
967 return "RM_EV_start_meas";
968 case RM_EV_survey_done:
969 return "RM_EV_survey_done";
970 case RM_EV_recv_rep:
971 return "RM_EV_recv_report";
972 case RM_EV_cancel:
973 return "RM_EV_cancel";
974 case RM_EV_state_out:
975 return "RM_EV_state_out";
976 case RM_EV_max:
977 return "RM_EV_max";
978 default:
979 return "RM_EV_unknown";
980 }
981 return "UNKNOWN";
982 }
983
rm_state_initial(struct rm_obj * prm)984 static void rm_state_initial(struct rm_obj *prm)
985 {
986 prm->state = RM_ST_IDLE;
987
988 RTW_INFO("\n");
989 RTW_INFO("RM: rmid=%x %-18s -> %s\n",prm->rmid,
990 "new measurement", rm_fsm[prm->state].name);
991
992 rm_post_event(prm->psta->padapter, prm->rmid, RM_EV_state_in);
993 }
994
rm_state_run(struct rm_obj * prm,enum RM_EV_ID evid)995 static void rm_state_run(struct rm_obj *prm, enum RM_EV_ID evid)
996 {
997 RTW_INFO("RM: rmid=%x %-18s %s\n",prm->rmid,
998 rm_fsm[prm->state].name,rm_event_name(evid));
999
1000 rm_fsm[prm->state].fsm_func(prm, evid);
1001 }
1002
rm_state_goto(struct rm_obj * prm,enum RM_STATE rm_state)1003 static void rm_state_goto(struct rm_obj *prm, enum RM_STATE rm_state)
1004 {
1005 if (prm->state == rm_state)
1006 return;
1007
1008 rm_state_run(prm, RM_EV_state_out);
1009
1010 RTW_INFO("\n");
1011 RTW_INFO("RM: rmid=%x %-18s -> %s\n",prm->rmid,
1012 rm_fsm[prm->state].name, rm_fsm[rm_state].name);
1013
1014 prm->state = rm_state;
1015 rm_state_run(prm, RM_EV_state_in);
1016 }
1017 #endif /* CONFIG_RTW_80211K */
1018