• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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