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