xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_sta.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 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 #define _PHL_STA_C_
16 #include "phl_headers.h"
17 
18 /*********** macid ctrl section ***********/
19 enum rtw_phl_status
phl_macid_ctrl_init(struct phl_info_t * phl)20 phl_macid_ctrl_init(struct phl_info_t *phl)
21 {
22 	struct rtw_phl_com_t *phl_com = phl->phl_com;
23 	struct hal_spec_t *hal_spec = phl_get_ic_spec(phl_com);
24 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl);
25 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
26 	u8 i = 0;
27 
28 	/* check invalid value or not */
29 	if (hal_spec->macid_num == 0) {
30 		PHL_ERR("Cannot get macid_num of hal\n");
31 		goto exit;
32 	}
33 
34 	_os_spinlock_init(phl_to_drvpriv(phl), &macid_ctl->lock);
35 
36 	macid_ctl->max_num = MIN(hal_spec->macid_num, PHL_MACID_MAX_NUM);
37 
38 	PHL_INFO("%s macid max_num:%d\n", __func__, macid_ctl->max_num);
39 
40 	for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++)
41 		macid_ctl->wrole_bmc[i] = macid_ctl->max_num;
42 
43 	phl_status = RTW_PHL_STATUS_SUCCESS;
44 
45 exit:
46 	return phl_status;
47 }
48 
49 enum rtw_phl_status
phl_macid_ctrl_deinit(struct phl_info_t * phl)50 phl_macid_ctrl_deinit(struct phl_info_t *phl)
51 {
52 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl);
53 
54 	_os_spinlock_free(phl_to_drvpriv(phl), &macid_ctl->lock);
55 	macid_ctl->max_num = 0;
56 
57 	return RTW_PHL_STATUS_SUCCESS;
58 }
59 
60 
61 static u8
_phl_macid_is_used(u32 * map,const u16 id)62 _phl_macid_is_used(u32 *map, const u16 id)
63 {
64 	int map_idx = (int)id / 32;
65 
66 	if (map[map_idx] & BIT(id % 32))
67 		return true;
68 	else
69 		return false;
70 }
71 
72 static void
_phl_macid_map_set(u32 * map,const u16 id)73 _phl_macid_map_set(u32 *map, const u16 id)
74 {
75 	int map_idx = (int)id / 32;
76 	map[map_idx] |=  BIT(id % 32);
77 }
78 
79 static void
_phl_macid_map_clr(u32 * map,const u16 id)80 _phl_macid_map_clr(u32 *map, const u16 id)
81 {
82 	int map_idx = (int)id / 32;
83 	map[map_idx] &= ~BIT(id % 32);
84 }
85 
_phl_wrole_bcmc_id_set(struct macid_ctl_t * macid_ctl,struct rtw_wifi_role_t * wrole,const u16 id)86 static void _phl_wrole_bcmc_id_set(struct macid_ctl_t *macid_ctl,
87 				struct rtw_wifi_role_t *wrole, const u16 id)
88 {
89 	macid_ctl->wrole_bmc[wrole->id] = id;
90 }
91 
92 static enum rtw_phl_status
_phl_alloc_macid(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * phl_sta)93 _phl_alloc_macid(struct phl_info_t *phl_info,
94 			struct rtw_phl_stainfo_t *phl_sta)
95 {
96 	struct macid_ctl_t *mc = phl_to_mac_ctrl(phl_info);
97 	struct rtw_wifi_role_t *wrole = phl_sta->wrole;
98 	u8 bc_addr[MAC_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
99 	u16 mid = 0;
100 	u16 max_macid_num = 0;
101 	bool bmc_sta = false;
102 
103 	if (wrole == NULL) {
104 		PHL_ERR("%s wrole=NULL!\n", __func__);
105 		return RTW_PHL_STATUS_FAILURE;
106 	}
107 
108 	if (_os_mem_cmp(phl_to_drvpriv(phl_info),
109 			bc_addr, phl_sta->mac_addr, MAC_ALEN) == 0)
110 		bmc_sta = true;
111 
112 	/* TODO
113 	if (wrole->type == PHL_RTYPE_STATION)
114 	else if (wrole->type == PHL_RTYPE_AP)*/
115 
116 	/*TODO - struct mac_ax_hw_info-> u16 macid_num; need to check */
117 	max_macid_num = mc->max_num;
118 	_os_spinlock(phl_to_drvpriv(phl_info), &mc->lock, _bh, NULL);
119 	for(mid = 0; mid < max_macid_num; mid++) {
120 		if (!_phl_macid_is_used(mc->used_map, mid)) {
121 			_phl_macid_map_set(mc->used_map, mid);
122 			_phl_macid_map_set(&mc->wifi_role_usedmap[wrole->id][0], mid);
123 			mc->sta[mid] = phl_sta;
124 
125 			if (bmc_sta) {
126 				_phl_macid_map_set(mc->bmc_map, mid);
127 				_phl_wrole_bcmc_id_set(mc, wrole, mid);
128 			}
129 
130 			break;
131 		}
132 	}
133 	_os_spinunlock(phl_to_drvpriv(phl_info), &mc->lock, _bh, NULL);
134 
135 	if (mid == max_macid_num) {
136 		phl_sta->macid = max_macid_num;
137 		PHL_ERR("%s cannot get macid\n", __func__);
138 		return RTW_PHL_STATUS_FAILURE;
139 	}
140 
141 	phl_sta->macid = mid;
142 
143 	PHL_INFO("%s allocate %02x:%02x:%02x:%02x:%02x:%02x for macid:%u\n", __func__,
144 	         phl_sta->mac_addr[0], phl_sta->mac_addr[1], phl_sta->mac_addr[2],
145 	         phl_sta->mac_addr[3], phl_sta->mac_addr[4], phl_sta->mac_addr[5],
146 	         phl_sta->macid);
147 	return RTW_PHL_STATUS_SUCCESS;
148 }
149 
150 static enum rtw_phl_status
_phl_release_macid(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * phl_sta)151 _phl_release_macid(struct phl_info_t *phl_info,
152 			struct rtw_phl_stainfo_t *phl_sta)
153 {
154 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
155 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
156 	struct rtw_wifi_role_t *wrole = phl_sta->wrole;
157 	u8 bc_addr[MAC_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
158 	u16 invalid_macid = macid_ctl->max_num;
159 
160 	if (phl_sta->macid >= invalid_macid) {
161 		PHL_ERR("_phl_release_macid macid error (%d\n)", phl_sta->macid);
162 		phl_status = RTW_PHL_STATUS_FAILURE;
163 		goto exit;
164 	}
165 
166 
167 	_os_spinlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
168 
169 	if (!_phl_macid_is_used(macid_ctl->used_map, phl_sta->macid)) {
170 		PHL_WARN("_phl_release_macid macid unused (%d\n)", phl_sta->macid);
171 		_os_spinunlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
172 		phl_status = RTW_PHL_STATUS_FAILURE;
173 		goto exit;
174 	}
175 
176 
177 	_phl_macid_map_clr(macid_ctl->used_map, phl_sta->macid);
178 	_phl_macid_map_clr(&macid_ctl->wifi_role_usedmap[wrole->id][0], phl_sta->macid);
179 	macid_ctl->sta[phl_sta->macid] = NULL;
180 
181 	if (_os_mem_cmp(phl_to_drvpriv(phl_info),
182 			bc_addr, phl_sta->mac_addr, MAC_ALEN) == 0)
183 		_phl_macid_map_clr(macid_ctl->bmc_map, phl_sta->macid);
184 
185 	phl_status = RTW_PHL_STATUS_SUCCESS;
186 	_os_spinunlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
187 
188 exit:
189 	PHL_INFO("%s release macid:%d - %02x:%02x:%02x:%02x:%02x:%02x \n",
190 		 __func__,
191 		 phl_sta->macid,
192 	         phl_sta->mac_addr[0], phl_sta->mac_addr[1], phl_sta->mac_addr[2],
193 	         phl_sta->mac_addr[3], phl_sta->mac_addr[4], phl_sta->mac_addr[5]);
194 
195 	phl_sta->macid = invalid_macid;
196 	return phl_status;
197 }
198 
_phl_get_macid(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * phl_sta)199 u16 _phl_get_macid(struct phl_info_t *phl_info,
200 		struct rtw_phl_stainfo_t *phl_sta)
201 {
202 	/* TODO: macid management */
203 	return phl_sta->macid;
204 }
205 
206 /**
207  * This function export to core layer use
208  * to get phl role bmc macid
209  * @phl: see phl_info_t
210  * @wrole: wifi role
211  */
212 u16
rtw_phl_wrole_bcmc_id_get(void * phl,struct rtw_wifi_role_t * wrole)213 rtw_phl_wrole_bcmc_id_get(void *phl, struct rtw_wifi_role_t *wrole)
214 {
215 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
216 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
217 
218 	return macid_ctl->wrole_bmc[wrole->id];
219 }
220 
221 /**
222  * This function export to core layer use
223  * to get maximum macid number
224  * @phl: see phl_info_t
225  */
226 u16
rtw_phl_get_macid_max_num(void * phl)227 rtw_phl_get_macid_max_num(void *phl)
228 {
229 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
230 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
231 
232 	return macid_ctl->max_num;
233 }
234 
235 /**
236  * This function export to core layer use
237  * to check macid is bmc or not
238  * @phl: see phl_info_t
239  * @macid: macid
240  */
241 u8
rtw_phl_macid_is_bmc(void * phl,u16 macid)242 rtw_phl_macid_is_bmc(void *phl, u16 macid)
243 {
244 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
245 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
246 
247 	if (macid >= macid_ctl->max_num) {
248 		PHL_ERR("%s macid(%d) is invalid\n", __func__, macid);
249 		return true;
250 	}
251 
252 	return _phl_macid_is_used(macid_ctl->bmc_map, macid);
253 }
254 
255 
256 /**
257  * This function export to core layer use
258  * to check macid is used or not
259  * @phl: see phl_info_t
260  * @macid: macid
261  */
262 u8
rtw_phl_macid_is_used(void * phl,u16 macid)263 rtw_phl_macid_is_used(void *phl, u16 macid)
264 {
265 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
266 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
267 
268 	if (macid >= macid_ctl->max_num) {
269 		PHL_ERR("%s macid(%d) is invalid\n", __func__, macid);
270 		return true;
271 	}
272 
273 
274 	return _phl_macid_is_used(macid_ctl->used_map, macid);
275 }
276 
277 /**
278  * This function is used to
279  * check macid shared by all wifi role
280  * @phl: see phl_info_t
281  * @macid: macid
282  */
283 
284 u8
rtw_phl_macid_is_wrole_shared(void * phl,u16 macid)285 rtw_phl_macid_is_wrole_shared(void *phl, u16 macid)
286 {
287 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
288 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
289 	int i = 0;
290 	u8 iface_bmp = 0;
291 
292 	if (macid >= macid_ctl->max_num) {
293 		PHL_ERR("%s macid(%d) is invalid\n", __func__, macid);
294 		return false;
295 	}
296 
297 	for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
298 		if (_phl_macid_is_used(&macid_ctl->wifi_role_usedmap[i][0], macid)) {
299 			if (iface_bmp)
300 				return true;
301 			iface_bmp |= BIT(i);
302 		}
303 	}
304 	return false;
305 }
306 
307 /**
308  * This function is used to
309  * check macid not shared by all wifi role
310  * and belong to wifi role
311  * @phl: see phl_info_t
312  * @macid: macid
313  * @wrole: check id belong to this wifi role
314  */
315 u8
rtw_phl_macid_is_wrole_specific(void * phl,u16 macid,struct rtw_wifi_role_t * wrole)316 rtw_phl_macid_is_wrole_specific(void *phl,
317 					u16 macid, struct rtw_wifi_role_t *wrole)
318 {
319 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
320 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
321 	int i = 0;
322 	u8 iface_bmp = 0;
323 
324 	if (macid >= macid_ctl->max_num) {
325 		PHL_ERR("%s macid(%d) invalid\n", __func__, macid);
326 		return false;
327 	}
328 
329 	for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
330 		if (_phl_macid_is_used(&macid_ctl->wifi_role_usedmap[i][0], macid)) {
331 			if (iface_bmp || i != wrole->id)
332 				return false;
333 			iface_bmp |= BIT(i);
334 		}
335 	}
336 
337 	return iface_bmp ? true : false;
338 }
339 
340 
341 /*********** stainfo_ctrl section ***********/
342 static enum rtw_phl_status
_phl_stainfo_init(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * phl_sta)343 _phl_stainfo_init(struct phl_info_t *phl_info,
344                   struct rtw_phl_stainfo_t *phl_sta)
345 {
346 	void *drv = phl_to_drvpriv(phl_info);
347 
348 	INIT_LIST_HEAD(&phl_sta->list);
349 	_os_spinlock_init(drv, &phl_sta->tid_rx_lock);
350 	_os_mem_set(drv, phl_sta->tid_rx, 0, sizeof(phl_sta->tid_rx));
351 	_os_event_init(drv, &phl_sta->comp_sync);
352 	_os_init_timer(drv, &phl_sta->reorder_timer,
353 	               phl_sta_rx_reorder_timer_expired, phl_sta, "reorder_timer");
354 
355 	_os_atomic_set(drv, &phl_sta->ps_sta, 0);
356 
357 	if (rtw_hal_stainfo_init(phl_info->hal, phl_sta) !=
358 	    RTW_HAL_STATUS_SUCCESS) {
359 		PHL_ERR("hal_stainfo_init failed\n");
360 		FUNCOUT();
361 		return RTW_PHL_STATUS_FAILURE;
362 	}
363 	phl_sta->active = false;
364 #ifdef RTW_WKARD_CHECK_STAINFO_DOUBLE_DEL
365 	phl_sta->allocated = false;
366 #endif
367 	return RTW_PHL_STATUS_SUCCESS;
368 }
369 
370 enum rtw_phl_status
_phl_stainfo_deinit(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * phl_sta)371 _phl_stainfo_deinit(struct phl_info_t *phl_info,
372 				struct rtw_phl_stainfo_t *phl_sta)
373 {
374 	void *drv = phl_to_drvpriv(phl_info);
375 
376 	_os_release_timer(drv, &phl_sta->reorder_timer);
377 	_os_spinlock_free(phl_to_drvpriv(phl_info), &phl_sta->tid_rx_lock);
378 	_os_event_free(drv, &phl_sta->comp_sync);
379 
380 	if (rtw_hal_stainfo_deinit(phl_info->hal, phl_sta)!=
381 					RTW_HAL_STATUS_SUCCESS) {
382 		PHL_ERR("hal_stainfo_deinit failed\n");
383 		FUNCOUT();
384 		return RTW_PHL_STATUS_FAILURE;
385 	}
386 	return RTW_PHL_STATUS_SUCCESS;
387 }
388 
389 enum rtw_phl_status
phl_stainfo_enqueue(struct phl_info_t * phl_info,struct phl_queue * sta_queue,struct rtw_phl_stainfo_t * psta)390 phl_stainfo_enqueue(struct phl_info_t *phl_info,
391 			 struct phl_queue *sta_queue,
392 			 struct rtw_phl_stainfo_t *psta)
393 {
394 	void *drv = phl_to_drvpriv(phl_info);
395 
396 	if (!psta)
397 		return RTW_PHL_STATUS_FAILURE;
398 
399 	_os_spinlock(drv, &sta_queue->lock, _bh, NULL);
400 	list_add_tail(&psta->list, &sta_queue->queue);
401 	sta_queue->cnt++;
402 	_os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
403 	return RTW_PHL_STATUS_SUCCESS;
404 }
405 
406 struct rtw_phl_stainfo_t *
phl_stainfo_dequeue(struct phl_info_t * phl_info,struct phl_queue * sta_queue)407 phl_stainfo_dequeue(struct phl_info_t *phl_info,
408 			struct phl_queue *sta_queue)
409 {
410 	struct rtw_phl_stainfo_t *psta = NULL;
411 	void *drv = phl_to_drvpriv(phl_info);
412 
413 	_os_spinlock(drv, &sta_queue->lock, _bh, NULL);
414 	if (list_empty(&sta_queue->queue)) {
415 		psta = NULL;
416 	} else {
417 		psta = list_first_entry(&sta_queue->queue,
418 					struct rtw_phl_stainfo_t, list);
419 
420 		list_del(&psta->list);
421 		sta_queue->cnt--;
422 	}
423 	_os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
424 
425 	return psta;
426 }
427 
428 enum rtw_phl_status
phl_stainfo_queue_del(struct phl_info_t * phl_info,struct phl_queue * sta_queue,struct rtw_phl_stainfo_t * psta)429 phl_stainfo_queue_del(struct phl_info_t *phl_info,
430 			 struct phl_queue *sta_queue,
431 			 struct rtw_phl_stainfo_t *psta)
432 {
433 	void *drv = phl_to_drvpriv(phl_info);
434 
435 	if (!psta)
436 		return RTW_PHL_STATUS_FAILURE;
437 
438 	_os_spinlock(drv, &sta_queue->lock, _bh, NULL);
439 	if (sta_queue->cnt) {
440 		list_del(&psta->list);
441 		sta_queue->cnt--;
442 	}
443 	_os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
444 	return RTW_PHL_STATUS_SUCCESS;
445 }
446 
447 struct rtw_phl_stainfo_t *
phl_stainfo_queue_search(struct phl_info_t * phl_info,struct phl_queue * sta_queue,u8 * addr)448 phl_stainfo_queue_search(struct phl_info_t *phl_info,
449 			 struct phl_queue *sta_queue,
450 			 u8 *addr)
451 {
452 	struct rtw_phl_stainfo_t *sta = NULL;
453 	_os_list *sta_list = &sta_queue->queue;
454 	void *drv = phl_to_drvpriv(phl_info);
455 	bool sta_found = false;
456 
457 	_os_spinlock(drv, &sta_queue->lock, _bh, NULL);
458 	if (list_empty(sta_list) == true)
459 		goto _exit;
460 
461 	phl_list_for_loop(sta, struct rtw_phl_stainfo_t, sta_list, list) {
462 		if (_os_mem_cmp(phl_to_drvpriv(phl_info),
463 			sta->mac_addr, addr, MAC_ALEN) == 0) {
464 			sta_found = true;
465 			break;
466 		}
467 	}
468 _exit:
469 	_os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
470 
471 	if (sta_found == false)
472 		sta = NULL;
473 
474 	return sta;
475 }
476 
477 struct rtw_phl_stainfo_t *
phl_stainfo_queue_get_first(struct phl_info_t * phl_info,struct phl_queue * sta_queue)478 phl_stainfo_queue_get_first(struct phl_info_t *phl_info,
479 			 struct phl_queue *sta_queue)
480 {
481 
482 	_os_list *sta_list = &sta_queue->queue;
483 	void *drv = phl_to_drvpriv(phl_info);
484 	struct rtw_phl_stainfo_t *sta = NULL;
485 
486 	/* first sta info in assoc_sta_queu is self sta info */
487 	_os_spinlock(drv, &sta_queue->lock, _bh, NULL);
488 	if (list_empty(sta_list) == true)
489 		goto _exit;
490 
491 	sta = list_first_entry(sta_list, struct rtw_phl_stainfo_t, list);
492 _exit :
493 	_os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
494 
495 	return sta;
496 }
497 
498 enum rtw_phl_status
phl_stainfo_ctrl_deinie(struct phl_info_t * phl_info)499 phl_stainfo_ctrl_deinie(struct phl_info_t *phl_info)
500 {
501 	struct stainfo_ctl_t *sta_ctrl = phl_to_sta_ctrl(phl_info);
502 	void *drv = phl_to_drvpriv(phl_info);
503 	struct rtw_phl_stainfo_t *psta = NULL;
504 	struct phl_queue *fsta_queue = &sta_ctrl->free_sta_queue;
505 
506 	FUNCIN();
507 	do {
508 		psta = phl_stainfo_dequeue(phl_info, fsta_queue);
509 		if (psta)
510 			_phl_stainfo_deinit(phl_info, psta);
511 
512 	}while (psta != NULL);
513 
514 	pq_deinit(drv, fsta_queue);
515 
516 	if (sta_ctrl->allocated_stainfo_buf)
517 		_os_mem_free(drv, sta_ctrl->allocated_stainfo_buf,
518 					sta_ctrl->allocated_stainfo_sz);
519 	FUNCOUT();
520 	return RTW_PHL_STATUS_SUCCESS;
521 }
522 
523 enum rtw_phl_status
phl_stainfo_ctrl_init(struct phl_info_t * phl_info)524 phl_stainfo_ctrl_init(struct phl_info_t *phl_info)
525 {
526 	struct stainfo_ctl_t *sta_ctrl = phl_to_sta_ctrl(phl_info);
527 	void *drv = phl_to_drvpriv(phl_info);
528 	struct rtw_phl_stainfo_t *psta = NULL;
529 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
530 	struct phl_queue *fsta_queue = NULL;
531 
532 	u16 i;
533 	bool sta_init_fail = false;
534 
535 	FUNCIN();
536 	sta_ctrl->phl_info = phl_info;
537 
538 	sta_ctrl->allocated_stainfo_sz = sizeof(struct rtw_phl_stainfo_t) * PHL_MAX_STA_NUM;
539 
540 	#ifdef MEM_ALIGNMENT
541 	sta_ctrl->allocated_stainfo_sz += MEM_ALIGNMENT_OFFSET;
542 	#endif
543 
544 	sta_ctrl->allocated_stainfo_buf =
545 			_os_mem_alloc(drv, sta_ctrl->allocated_stainfo_sz);
546 
547 	if (!sta_ctrl->allocated_stainfo_buf) {
548 		PHL_ERR("allocate stainfo buf failed\n");
549 		goto _exit;
550 	}
551 	sta_ctrl->stainfo_buf = sta_ctrl->allocated_stainfo_buf;
552 
553 	#ifdef MEM_ALIGNMENT
554 	if (sta_ctrl->stainfo_buf & MEM_ALIGNMENT_PADDING)
555 		sta_ctrl->stainfo_buf += MEM_ALIGNMENT_OFFSET -
556 			(sta_ctrl->stainfo_buf & MEM_ALIGNMENT_PADDING);
557 	#endif
558 
559 	fsta_queue = &sta_ctrl->free_sta_queue;
560 
561 	pq_init(drv, fsta_queue);
562 	psta = (struct rtw_phl_stainfo_t *)(sta_ctrl->stainfo_buf);
563 
564 	for (i = 0; i < PHL_MAX_STA_NUM; i++) {
565 		if (_phl_stainfo_init(phl_info, psta) != RTW_PHL_STATUS_SUCCESS) {
566 			sta_init_fail = true;
567 			break;
568 		}
569 		phl_stainfo_enqueue(phl_info, fsta_queue, psta);
570 		psta++;
571 	}
572 
573 	if (sta_init_fail == true) {
574 		PHL_ERR("sta_init failed\n");
575 		phl_stainfo_ctrl_deinie(phl_info);
576 		goto _exit;
577 	}
578 	PHL_DUMP_STACTRL_EX(phl_info);
579 
580 	pstatus = RTW_PHL_STATUS_SUCCESS;
581 _exit:
582 	FUNCOUT();
583 	return pstatus;
584 }
585 
586 /*********** phl stainfo section ***********/
587 #ifdef DBG_PHL_STAINFO
588 void
phl_dump_stactrl(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info)589 phl_dump_stactrl(const char *caller, const int line, bool show_caller,
590 						struct phl_info_t *phl_info)
591 {
592 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
593 	u8 ridx = MAX_WIFI_ROLE_NUMBER;
594 	struct rtw_wifi_role_t *role;
595 	struct stainfo_ctl_t *sta_ctrl = NULL;
596 
597 	sta_ctrl = phl_to_sta_ctrl(phl_info);
598 
599 	if (show_caller)
600 		PHL_INFO("[PSTA] ###### FUN - %s LINE - %d #######\n", caller, line);
601 	PHL_INFO("[PSTA] PHL_MAX_STA_NUM:%d\n", PHL_MAX_STA_NUM);
602 	PHL_INFO("[PSTA] sta_ctrl - q_cnt :%d\n", sta_ctrl->free_sta_queue.cnt);
603 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
604 		role = &(phl_com->wifi_roles[ridx]);
605 		PHL_INFO("[PSTA] wrole_%d asoc_q cnt :%d\n",
606 				ridx, role->assoc_sta_queue.cnt);
607 	}
608 	if (show_caller)
609 		PHL_INFO("#################################\n");
610 }
611 
_phl_dump_stainfo(struct rtw_phl_stainfo_t * phl_sta)612 static void _phl_dump_stainfo(struct rtw_phl_stainfo_t *phl_sta)
613 {
614 	PHL_INFO("\t[STA] MAC-ID:%d, AID:%d, MAC-ADDR:%02x-%02x-%02x-%02x-%02x-%02x, Active:%s\n",
615 			phl_sta->macid, phl_sta->aid,
616 			phl_sta->mac_addr[0],phl_sta->mac_addr[1],phl_sta->mac_addr[2],
617 			phl_sta->mac_addr[3],phl_sta->mac_addr[4],phl_sta->mac_addr[5],
618 			(phl_sta->active) ? "Y" : "N");
619 	PHL_INFO("\t[STA] WROLE-IDX:%d wlan_mode:0x%02x\n", phl_sta->wrole->id, phl_sta->wmode);
620 	PHL_DUMP_CHAN_DEF(&phl_sta->chandef);
621 
622 	/****** statistic ******/
623 	PHL_INFO("\t[STA] TP -[Tx:%d Rx :%d BI:N/A] (KBits)\n",
624 		phl_sta->stats.tx_tp_kbits, phl_sta->stats.rx_tp_kbits);
625 	PHL_INFO("\t[STA] Total -[Tx:%llu Rx :%llu BI:N/A] (Bytes)\n",
626 		phl_sta->stats.tx_byte_total, phl_sta->stats.rx_byte_total);
627 	/****** asoc_cap ******/
628 	/****** protect ******/
629 	/****** sec_mode ******/
630 	/****** rssi_stat ******/
631 	PHL_INFO("\t\t[HAL STA] rssi:%d assoc_rssi:%d, ofdm:%d, cck:%d, rssi_ma:%d, ma_rssi:%d\n",
632 			(phl_sta->hal_sta->rssi_stat.rssi >> 1), phl_sta->hal_sta->rssi_stat.assoc_rssi,
633 			(phl_sta->hal_sta->rssi_stat.rssi_ofdm >> 1), (phl_sta->hal_sta->rssi_stat.rssi_cck >> 1),
634 			(phl_sta->hal_sta->rssi_stat.rssi_ma >> 5), phl_sta->hal_sta->rssi_stat.ma_rssi);
635 
636 	/****** ra_info ******/
637 	PHL_INFO("\t\t[HAL STA] - RA info\n");
638 
639 	PHL_INFO("\t\t[HAL STA] Tx rate:0x%04x ra_bw_mode:%d, curr_tx_bw:%d\n",
640 				phl_sta->hal_sta->ra_info.curr_tx_rate,
641 				phl_sta->hal_sta->ra_info.ra_bw_mode,
642 				phl_sta->hal_sta->ra_info.curr_tx_bw);
643 
644 	PHL_INFO("\t\t[HAL STA] dis_ra:%s ra_registered:%s\n",
645 				(phl_sta->hal_sta->ra_info.dis_ra) ? "Y" : "N",
646 				(phl_sta->hal_sta->ra_info.ra_registered) ? "Y" : "N");
647 
648 	PHL_INFO("\t\t[HAL STA] ra_mask:0x%08llx cur_ra_mask:0x%08llx, retry_ratio:%d\n",
649 				phl_sta->hal_sta->ra_info.ra_mask,
650 				phl_sta->hal_sta->ra_info.cur_ra_mask,
651 				phl_sta->hal_sta->ra_info.curr_retry_ratio);
652 	/****** ra_info - Report ******/
653 	PHL_INFO("\t\t[HAL STA] RA Report: gi_ltf:%d rate_mode:%d, bw:%d, mcs_ss_idx:%d\n",
654 				phl_sta->hal_sta->ra_info.rpt_rt_i.gi_ltf,
655 				phl_sta->hal_sta->ra_info.rpt_rt_i.mode,
656 				phl_sta->hal_sta->ra_info.rpt_rt_i.bw,
657 				phl_sta->hal_sta->ra_info.rpt_rt_i.mcs_ss_idx);
658 
659 	PHL_INFO("\t\t[HAL STA] HAL rx_ok_cnt:%d rx_err_cnt:%d, rx_rate_plurality:%d\n\n",
660 				phl_sta->hal_sta->trx_stat.rx_ok_cnt,
661 				phl_sta->hal_sta->trx_stat.rx_err_cnt,
662 				phl_sta->hal_sta->trx_stat.rx_rate_plurality);
663 
664 }
phl_dump_stainfo_all(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info)665 void phl_dump_stainfo_all(const char *caller, const int line, bool show_caller,
666 				struct phl_info_t *phl_info)
667 {
668 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
669 	struct rtw_phl_stainfo_t *phl_sta = NULL;
670 	u16 max_macid_num = 0;
671 	u16 mid = 0;
672 
673 	if (show_caller)
674 		PHL_INFO("###### FUN - %s LINE - %d #######\n", caller, line);
675 
676 	max_macid_num = macid_ctl->max_num;
677 	PHL_INFO("max_macid_num:%d\n", max_macid_num);
678 	_os_spinlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
679 	for(mid = 0; mid < max_macid_num; mid++) {
680 		if (_phl_macid_is_used(macid_ctl->used_map, mid)) {
681 			phl_sta = macid_ctl->sta[mid];
682 			if (phl_sta)
683 				_phl_dump_stainfo(phl_sta);
684 		}
685 	}
686 	_os_spinunlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
687 
688 	if (show_caller)
689 		PHL_INFO("#################################\n");
690 }
691 
692 const char *const _rtype_str[] = {
693 	"NONE",
694 	"STA",
695 	"AP",
696 	"VAP",
697 	"ADHOC",
698 	"MASTER",
699 	"MESH",
700 	"MONITOR",
701 	"PD",
702 	"GC",
703 	"GO",
704 	"TDLS",
705 	"NAN",
706 	"NONE"
707 };
708 
phl_dump_stainfo_per_role(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)709 void phl_dump_stainfo_per_role(const char *caller, const int line, bool show_caller,
710 				struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
711 {
712 	void *drv = phl_to_drvpriv(phl_info);
713 	struct rtw_phl_stainfo_t *sta = NULL;
714 	int sta_cnt = 0;
715 
716 	if (show_caller)
717 		PHL_INFO("[STA] ###### FUN - %s LINE - %d #######\n", caller, line);
718 
719 	PHL_INFO("WR_IDX:%d RTYPE:%s, mac-addr:%02x-%02x-%02x-%02x-%02x-%02x\n",
720 			wrole->id,
721 			_rtype_str[wrole->type],
722 			wrole->mac_addr[0], wrole->mac_addr[1], wrole->mac_addr[2],
723 			wrole->mac_addr[3], wrole->mac_addr[4], wrole->mac_addr[5]);
724 
725 	_os_spinlock(drv, &wrole->assoc_sta_queue.lock, _bh, NULL);
726 
727 	if (wrole->type == PHL_RTYPE_STATION && wrole->mstate == MLME_LINKED)
728 		sta_cnt = 1;
729 	else if (wrole->type == PHL_RTYPE_TDLS)
730 		sta_cnt = wrole->assoc_sta_queue.cnt;
731 	else
732 		sta_cnt = wrole->assoc_sta_queue.cnt - 1;
733 
734 	PHL_INFO("assoced STA num: %d\n", sta_cnt);
735 	phl_list_for_loop(sta, struct rtw_phl_stainfo_t, &wrole->assoc_sta_queue.queue, list) {
736 		if (sta)
737 			_phl_dump_stainfo(sta);
738 	}
739 	_os_spinunlock(drv, &wrole->assoc_sta_queue.lock, _bh, NULL);
740 
741 	if (show_caller)
742 		PHL_INFO("#################################\n");
743 }
744 
rtw_phl_sta_dump_info(void * phl,bool show_caller,struct rtw_wifi_role_t * wr,u8 mode)745 void rtw_phl_sta_dump_info(void *phl, bool show_caller, struct rtw_wifi_role_t *wr, u8 mode)
746 {
747 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
748 
749 	if (mode == 1) {
750 		if (show_caller) {
751 			PHL_DUMP_STACTRL_EX(phl_info);
752 		} else {
753 			PHL_DUMP_STACTRL(phl_info);
754 		}
755 	} else if (mode == 2) {
756 		if (show_caller) {
757 			PHL_DUMP_STAINFO_EX(phl_info);
758 		} else {
759 			PHL_DUMP_STAINFO(phl_info);
760 		}
761 	} else if (mode == 3) {
762 		if (show_caller) {
763 			PHL_DUMP_ROLE_STAINFO_EX(phl_info, wr);
764 		} else {
765 			PHL_DUMP_ROLE_STAINFO(phl_info, wr);
766 		}
767 	} else {
768 		if (show_caller) {
769 			PHL_DUMP_STACTRL_EX(phl_info);
770 			PHL_DUMP_STAINFO_EX(phl_info);
771 			PHL_DUMP_ROLE_STAINFO_EX(phl_info, wr);
772 		}
773 		else {
774 			PHL_DUMP_STACTRL(phl_info);
775 			PHL_DUMP_STAINFO(phl_info);
776 			PHL_DUMP_ROLE_STAINFO(phl_info, wr);
777 		}
778 	}
779 }
780 #endif /*DBG_PHL_STAINFO*/
781 
_phl_self_stainfo_chk(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta)782 static bool _phl_self_stainfo_chk(struct phl_info_t *phl_info,
783 	struct rtw_wifi_role_t *wrole, struct rtw_phl_stainfo_t *sta)
784 {
785 	void *drv = phl_to_drvpriv(phl_info);
786 	bool is_self = false;
787 
788 	switch (wrole->type) {
789 	case PHL_RTYPE_STATION:
790 	case PHL_RTYPE_P2P_GC:
791 		_os_mem_cpy(drv, sta->mac_addr, wrole->mac_addr, MAC_ALEN);
792 		is_self = true;
793 	break;
794 
795 	case PHL_RTYPE_AP:
796 	case PHL_RTYPE_MESH:
797 	case PHL_RTYPE_P2P_GO:
798 	case PHL_RTYPE_TDLS:
799 		if (_os_mem_cmp(drv, wrole->mac_addr, sta->mac_addr, MAC_ALEN) == 0)
800 			is_self = true;
801 	break;
802 
803 	case PHL_RTYPE_NONE:
804 	case PHL_RTYPE_VAP:
805 	case PHL_RTYPE_ADHOC:
806 	case PHL_RTYPE_ADHOC_MASTER:
807 	case PHL_RTYPE_MONITOR:
808 	case PHL_RTYPE_P2P_DEVICE:
809 	case PHL_RTYPE_NAN:
810 	case PHL_MLME_MAX:
811 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "_phl_self_stainfo_chk(): Unsupported case:%d, please check it\n",
812 				wrole->type);
813 		break;
814 	default:
815 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "_phl_self_stainfo_chk(): role-type(%d) not recognize\n",
816 				wrole->type);
817 		break;
818 	}
819 	return is_self;
820 }
821 
822 enum rtw_phl_status
phl_free_stainfo_sw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)823 phl_free_stainfo_sw(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta)
824 {
825 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
826 
827 	if(sta == NULL) {
828 		PHL_ERR("%s sta is NULL\n", __func__);
829 		return RTW_PHL_STATUS_FAILURE;
830 	}
831 
832 	phl_free_rx_reorder(phl_info, sta);
833 
834 	pstatus = phl_deregister_tx_ring((void *)phl_info, sta->macid);
835 	if (pstatus != RTW_PHL_STATUS_SUCCESS) {
836 		PHL_ERR("macid(%d) phl_deregister_tx_ring failed\n", sta->macid);
837 	}
838 
839 	/* release macid for used_map */
840 	pstatus = _phl_release_macid(phl_info, sta);
841 	if (pstatus != RTW_PHL_STATUS_SUCCESS)
842 		PHL_ERR("_phl_release_macid failed\n");
843 
844 	return pstatus;
845 }
846 
847 enum rtw_phl_status
__phl_free_stainfo_sw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)848 __phl_free_stainfo_sw(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta)
849 {
850 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
851 	struct stainfo_ctl_t *sta_ctrl = phl_to_sta_ctrl(phl_info);
852 	struct rtw_wifi_role_t *wrole = NULL;
853 
854 	FUNCIN();
855 	if(sta == NULL) {
856 		PHL_ERR("%s sta is NULL\n", __func__);
857 		goto _exit;
858 	}
859 
860 #ifdef RTW_WKARD_CHECK_STAINFO_DOUBLE_DEL
861 	if (!sta->allocated) {
862 		PHL_INFO("%s sta has not been allocated\n", __func__);
863 		goto _exit;
864 	}
865 #endif
866 
867 	wrole = sta->wrole;
868 
869 	if (!is_broadcast_mac_addr(sta->mac_addr)) {
870 		if (_phl_self_stainfo_chk(phl_info, wrole, sta) == true) {
871 			pstatus = RTW_PHL_STATUS_SUCCESS;
872 			goto _exit;
873 		}
874 	}
875 
876 	pstatus = phl_stainfo_queue_del(phl_info, &wrole->assoc_sta_queue, sta);
877 	if (pstatus != RTW_PHL_STATUS_SUCCESS) {
878 		PHL_ERR("phl_stainfo_queue_del failed\n");
879 	}
880 
881 #ifdef RTW_WKARD_CHECK_STAINFO_DOUBLE_DEL
882 	sta->allocated = false;
883 #endif
884 
885 	pstatus = phl_free_stainfo_sw(phl_info, sta);
886 	if (pstatus != RTW_PHL_STATUS_SUCCESS) {
887 		PHL_ERR("macid(%d) _phl_free_stainfo_sw failed\n", sta->macid);
888 	}
889 
890 	pstatus = phl_stainfo_enqueue(phl_info, &sta_ctrl->free_sta_queue, sta);
891 	if (pstatus != RTW_PHL_STATUS_SUCCESS)
892 		PHL_ERR("phl_stainfo_enqueue to free queue failed\n");
893 
894 #ifdef RTW_WKARD_AP_CLIENT_ADD_DEL_NTY
895 	if ((wrole->type == PHL_RTYPE_AP) ||
896 	    (wrole->type == PHL_RTYPE_VAP) ||
897 	    (wrole->type == PHL_RTYPE_MESH) ||
898 	    (wrole->type == PHL_RTYPE_P2P_GO))
899 		phl_role_ap_client_notify(phl_info, wrole, MLME_NO_LINK);
900 #endif
901 
902 _exit:
903 	PHL_DUMP_STACTRL_EX(phl_info);
904 	FUNCOUT();
905 	return pstatus;
906 }
907 
908 enum rtw_phl_status
rtw_phl_free_stainfo_sw(void * phl,struct rtw_phl_stainfo_t * sta)909 rtw_phl_free_stainfo_sw(void *phl, struct rtw_phl_stainfo_t *sta)
910 {
911 	return __phl_free_stainfo_sw((struct phl_info_t *)phl, sta);
912 }
913 
914 enum rtw_phl_status
phl_free_stainfo_hw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)915 phl_free_stainfo_hw(struct phl_info_t *phl_info,
916 					struct rtw_phl_stainfo_t *sta)
917 {
918 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
919 
920 	if (sta == NULL) {
921 		PHL_ERR("%s sta == NULL\n", __func__);
922 		goto _exit;
923 	}
924 
925 	phl_pkt_ofld_del_entry(phl_info, sta->macid);
926 
927 	sta->active = false;
928 	if (rtw_hal_del_sta_entry(phl_info->hal, sta) == RTW_HAL_STATUS_SUCCESS)
929 		pstatus = RTW_PHL_STATUS_SUCCESS;
930 	else
931 		PHL_ERR("rtw_hal_del_sta_entry failed\n");
932 _exit:
933 	return pstatus;
934 }
935 
936 enum rtw_phl_status
__phl_free_stainfo_hw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)937 __phl_free_stainfo_hw(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta)
938 {
939 	struct rtw_wifi_role_t *wrole = sta->wrole;
940 
941 	if (!is_broadcast_mac_addr(sta->mac_addr)) {
942 		if (_phl_self_stainfo_chk(phl_info, wrole, sta) == true)
943 			return RTW_PHL_STATUS_SUCCESS;
944 	}
945 	return phl_free_stainfo_hw(phl_info, sta);
946 }
947 
948 static enum rtw_phl_status
__phl_free_stainfo(struct phl_info_t * phl,struct rtw_phl_stainfo_t * sta)949 __phl_free_stainfo(struct phl_info_t *phl, struct rtw_phl_stainfo_t *sta)
950 {
951 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
952 
953 	pstatus = __phl_free_stainfo_hw(phl, sta);
954 	if (pstatus != RTW_PHL_STATUS_SUCCESS)
955 		PHL_ERR("__phl_free_stainfo_hw failed\n");
956 
957 	pstatus = __phl_free_stainfo_sw(phl, sta);
958 	if (pstatus != RTW_PHL_STATUS_SUCCESS)
959 		PHL_ERR("__phl_free_stainfo_sw failed\n");
960 	return pstatus;
961 }
962 
963 
964 static enum rtw_phl_status
_phl_alloc_stainfo_sw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)965 _phl_alloc_stainfo_sw(struct phl_info_t *phl_info,struct rtw_phl_stainfo_t *sta)
966 {
967 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
968 
969 	pstatus = _phl_alloc_macid(phl_info, sta);
970 	if (pstatus != RTW_PHL_STATUS_SUCCESS) {
971 		PHL_ERR("%s allocate macid failure!\n", __func__);
972 		goto error_alloc_macid;
973 	}
974 
975 	if (phl_register_tx_ring(phl_info, sta->macid,
976 		sta->wrole->hw_band, sta->wrole->hw_wmm, sta->wrole->hw_port) !=
977 					RTW_PHL_STATUS_SUCCESS) {
978 		PHL_ERR("%s register_tx_ring failure!\n", __func__);
979 		goto error_register_tx_ring;
980 	}
981 	pstatus = RTW_PHL_STATUS_SUCCESS;
982 	return pstatus;
983 
984 error_register_tx_ring:
985 	_phl_release_macid(phl_info, sta);
986 error_alloc_macid:
987 	return pstatus;
988 }
989 
_phl_sta_set_default_value(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * phl_sta)990 static void _phl_sta_set_default_value(struct phl_info_t *phl_info,
991 		struct rtw_phl_stainfo_t *phl_sta)
992 {
993 	phl_sta->bcn_hit_cond = 0; /* beacon:A3 probersp: A1 & A3 */
994 
995 	/* fit rule
996 	 * 0: A1 & A2
997 	 * 1: A1 & A3
998 	 *
999 	 * Rule 0 should be used for both AP and STA modes.
1000 	 *
1001 	 * For STA, A3 is source address(SA) which can be any peer on the LAN.
1002 	 *
1003 	 * For AP, A3 is destination address(DA) which can also be any node
1004 	 * on the LAN. A1 & A2 match find the address CAM entry that contains the
1005 	 * correct security CAM ID and MAC ID.
1006 	 */
1007 	phl_sta->hit_rule = 0;
1008 }
1009 
1010 struct rtw_phl_stainfo_t *
phl_alloc_stainfo_sw(struct phl_info_t * phl_info,u8 * sta_addr,struct rtw_wifi_role_t * wrole)1011 phl_alloc_stainfo_sw(struct phl_info_t *phl_info,
1012                      u8 *sta_addr,
1013                      struct rtw_wifi_role_t *wrole)
1014 {
1015 	struct stainfo_ctl_t *sta_ctrl = phl_to_sta_ctrl(phl_info);
1016 	struct rtw_phl_stainfo_t *phl_sta = NULL;
1017 	void *drv = phl_to_drvpriv(phl_info);
1018 	bool bmc_sta = false;
1019 
1020 	FUNCIN();
1021 	if (is_broadcast_mac_addr(sta_addr))
1022 		bmc_sta = true;
1023 
1024 	/* if sta_addr is bmc addr, allocate new sta_info */
1025 	if (wrole->type == PHL_RTYPE_STATION && !bmc_sta) {
1026 		phl_sta = rtw_phl_get_stainfo_self(phl_info, wrole);
1027 		if (phl_sta) {
1028 			_os_mem_cpy(drv, phl_sta->mac_addr, sta_addr, MAC_ALEN);
1029 			goto _exit;
1030 		}
1031 	}
1032 
1033 	/* check station info exist */
1034 	phl_sta = rtw_phl_get_stainfo_by_addr(phl_info, wrole, sta_addr);
1035 	if (phl_sta) {
1036 		PHL_INFO("%s phl_sta(%02x:%02x:%02x:%02x:%02x:%02x) exist\n",
1037 		         __func__, sta_addr[0], sta_addr[1], sta_addr[2],
1038 		         sta_addr[3], sta_addr[4], sta_addr[5]);
1039 		goto _exit;
1040 	}
1041 
1042 	phl_sta = phl_stainfo_dequeue(phl_info, &sta_ctrl->free_sta_queue);
1043 	if (phl_sta == NULL) {
1044 		PHL_ERR("allocate phl_sta failure!\n");
1045 		goto _exit;
1046 	}
1047 
1048 	_os_mem_cpy(drv, phl_sta->mac_addr, sta_addr, MAC_ALEN);
1049 	phl_sta->wrole = wrole;
1050 
1051 	if (_phl_alloc_stainfo_sw(phl_info, phl_sta) != RTW_PHL_STATUS_SUCCESS) {
1052 		PHL_ERR("_phl_alloc_stainfo_sw failed\n");
1053 		goto error_alloc_sta;
1054 	}
1055 	_phl_sta_set_default_value(phl_info, phl_sta);
1056 
1057 	phl_stainfo_enqueue(phl_info, &wrole->assoc_sta_queue, phl_sta);
1058 #ifdef RTW_WKARD_CHECK_STAINFO_DOUBLE_DEL
1059 	phl_sta->allocated = true;
1060 #endif
1061 
1062 	#ifdef RTW_WKARD_AP_CLIENT_ADD_DEL_NTY
1063 	if (_phl_self_stainfo_chk(phl_info, wrole, phl_sta) == false) {
1064 		if ((wrole->type == PHL_RTYPE_AP) ||
1065 		     (wrole->type == PHL_RTYPE_VAP) ||
1066 		     (wrole->type == PHL_RTYPE_MESH) ||
1067 		     (wrole->type == PHL_RTYPE_P2P_GO)) {
1068 			phl_role_ap_client_notify(phl_info, wrole, MLME_LINKING);
1069 		}
1070 	}
1071 	#endif
1072 _exit:
1073 	PHL_DUMP_STACTRL_EX(phl_info);
1074 	FUNCOUT();
1075 
1076 	return phl_sta;
1077 
1078 error_alloc_sta:
1079 	phl_stainfo_enqueue(phl_info, &sta_ctrl->free_sta_queue, phl_sta);
1080 	phl_sta = NULL;
1081 	PHL_DUMP_STACTRL_EX(phl_info);
1082 	FUNCOUT();
1083 	return phl_sta;
1084 }
1085 
1086 struct rtw_phl_stainfo_t *
rtw_phl_alloc_stainfo_sw(void * phl,u8 * sta_addr,struct rtw_wifi_role_t * wrole)1087 rtw_phl_alloc_stainfo_sw(void *phl, u8 *sta_addr,
1088 				struct rtw_wifi_role_t *wrole)
1089 {
1090 	return phl_alloc_stainfo_sw((struct phl_info_t *)phl, sta_addr, wrole);
1091 }
1092 
1093 enum rtw_phl_status
phl_alloc_stainfo_hw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)1094 phl_alloc_stainfo_hw(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta)
1095 {
1096 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1097 
1098 	if (sta == NULL) {
1099 		PHL_ERR("%s sta == NULL\n", __func__);
1100 		goto _exit;
1101 	}
1102 
1103 	if (rtw_hal_add_sta_entry(phl_info->hal, sta) != RTW_HAL_STATUS_SUCCESS) {
1104 		PHL_ERR("%s rtw_hal_add_sta_entry failure!\n", __func__);
1105 		goto _exit;
1106 	}
1107 
1108 	sta->active = true;
1109 
1110 	pstatus = phl_pkt_ofld_add_entry(phl_info, sta->macid);
1111 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1112 		PHL_ERR("%s phl_pkt_ofld_add_entry failure!\n", __func__);
1113 
1114 _exit:
1115 	return pstatus;
1116 }
1117 
1118 enum rtw_phl_status
__phl_alloc_stainfo_hw(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)1119 __phl_alloc_stainfo_hw(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta)
1120 {
1121 	return phl_alloc_stainfo_hw(phl_info, sta);
1122 }
1123 
1124 static enum rtw_phl_status
__phl_alloc_stainfo(struct phl_info_t * phl,struct rtw_phl_stainfo_t ** sta,u8 * sta_addr,struct rtw_wifi_role_t * wrole)1125 __phl_alloc_stainfo(struct phl_info_t *phl,
1126                     struct rtw_phl_stainfo_t **sta,
1127                     u8 *sta_addr,
1128                     struct rtw_wifi_role_t *wrole)
1129 {
1130 	struct rtw_phl_stainfo_t *alloc_sta = NULL;
1131 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1132 
1133 	alloc_sta = phl_alloc_stainfo_sw(phl, sta_addr, wrole);
1134 	if (alloc_sta == NULL) {
1135 		PHL_ERR("%s can't alloc stainfo\n", __func__);
1136 		*sta = alloc_sta;
1137 		goto _exit;
1138 	}
1139 
1140 	if (alloc_sta->active == false) {
1141 		pstatus = __phl_alloc_stainfo_hw(phl, alloc_sta);
1142 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1143 			PHL_ERR("__phl_alloc_stainfo_hw failed\n");
1144 			goto _err_alloc_sta_hw;
1145 		}
1146 	}
1147 
1148 	PHL_INFO("%s success - macid:%u %02x:%02x:%02x:%02x:%02x:%02x\n",
1149 	         __func__, alloc_sta->macid,
1150 	         alloc_sta->mac_addr[0], alloc_sta->mac_addr[1], alloc_sta->mac_addr[2],
1151 	         alloc_sta->mac_addr[3], alloc_sta->mac_addr[4], alloc_sta->mac_addr[5]);
1152 
1153 	*sta = alloc_sta;
1154 	return RTW_PHL_STATUS_SUCCESS;
1155 
1156 _err_alloc_sta_hw:
1157 	__phl_free_stainfo_sw(phl, alloc_sta);
1158 	*sta = alloc_sta = NULL;
1159 _exit:
1160 	return RTW_PHL_STATUS_FAILURE;
1161 }
1162 
1163 static enum rtw_phl_status
_phl_alloc_stainfo(struct phl_info_t * phl,struct rtw_phl_stainfo_t ** sta,u8 * sta_addr,struct rtw_wifi_role_t * wrole,bool alloc,bool only_hw)1164 _phl_alloc_stainfo(struct phl_info_t *phl,
1165                    struct rtw_phl_stainfo_t **sta,
1166                    u8 *sta_addr,
1167                    struct rtw_wifi_role_t *wrole,
1168                    bool alloc,
1169                    bool only_hw)
1170 {
1171 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1172 
1173 	if (alloc) {
1174 		if (only_hw)
1175 			pstatus = __phl_alloc_stainfo_hw(phl, *sta);
1176 		else
1177 			pstatus = __phl_alloc_stainfo(phl, sta, sta_addr, wrole);
1178 	} else {
1179 		if (only_hw)
1180 			pstatus = __phl_free_stainfo_hw(phl, *sta);
1181 		else
1182 			pstatus = __phl_free_stainfo(phl, *sta);
1183 	}
1184 	return pstatus;
1185 }
1186 
1187 #ifdef CONFIG_CMD_DISP
1188 struct cmd_stainfo_param {
1189 	struct rtw_phl_stainfo_t **sta;
1190 	u8 sta_addr[MAC_ALEN];
1191 	struct rtw_wifi_role_t *wrole;
1192 	bool alloc;
1193 	bool only_hw;
1194 };
1195 
1196 static void
_phl_cmd_alloc_stainfo_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)1197 _phl_cmd_alloc_stainfo_done(void *drv_priv,
1198 						u8 *cmd,
1199 						u32 cmd_len,
1200 						enum rtw_phl_status status)
1201 {
1202 	if (cmd)
1203 		_os_kmem_free(drv_priv, cmd, cmd_len);
1204 }
1205 
1206 static enum rtw_phl_status
_phl_cmd_alloc_stainfo(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t ** sta,u8 * sta_addr,struct rtw_wifi_role_t * wrole,bool alloc,bool only_hw,enum phl_cmd_type cmd_type,u32 cmd_timeout)1207 _phl_cmd_alloc_stainfo(struct phl_info_t *phl_info,
1208 			struct rtw_phl_stainfo_t **sta,
1209 			u8 *sta_addr,
1210 			struct rtw_wifi_role_t *wrole,
1211 			bool alloc, bool only_hw,
1212 			enum phl_cmd_type cmd_type,
1213 			u32 cmd_timeout)
1214 {
1215 	void *drv = phl_to_drvpriv(phl_info);
1216 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
1217 	struct cmd_stainfo_param *param = NULL;
1218 	u32 param_len = 0;
1219 
1220 	if (cmd_type == PHL_CMD_DIRECTLY) {
1221 		psts = _phl_alloc_stainfo(phl_info, sta, sta_addr, wrole, alloc, only_hw);
1222 		goto _exit;
1223 	}
1224 
1225 	param_len = sizeof(struct cmd_stainfo_param);
1226 	param = _os_kmem_alloc(drv, param_len);
1227 	if (param == NULL) {
1228 		PHL_ERR("%s: alloc param failed!\n", __func__);
1229 		psts = RTW_PHL_STATUS_RESOURCE;
1230 		goto _exit;
1231 	}
1232 
1233 	_os_mem_set(drv, param, 0, param_len);
1234 	param->sta = sta;
1235 	_os_mem_cpy(drv, param->sta_addr, sta_addr, MAC_ALEN);
1236 	param->wrole = wrole;
1237 	param->alloc = alloc;
1238 	param->only_hw = only_hw;
1239 
1240 	psts = phl_cmd_enqueue(phl_info,
1241 	                       wrole->hw_band,
1242 	                       MSG_EVT_STA_INFO_CTRL,
1243 	                       (u8 *)param,
1244 	                       param_len,
1245 	                       _phl_cmd_alloc_stainfo_done,
1246 	                       cmd_type,
1247 	                       cmd_timeout);
1248 
1249 	if (is_cmd_failure(psts)) {
1250 		/* Send cmd success, but wait cmd fail*/
1251 		psts = RTW_PHL_STATUS_FAILURE;
1252 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
1253 		/* Send cmd fail */
1254 		psts = RTW_PHL_STATUS_FAILURE;
1255 		_os_kmem_free(drv, param, param_len);
1256 	}
1257 _exit:
1258 	return psts;
1259 }
1260 
1261 enum rtw_phl_status
phl_cmd_alloc_stainfo_hdl(struct phl_info_t * phl_info,u8 * param)1262 phl_cmd_alloc_stainfo_hdl(struct phl_info_t *phl_info, u8 *param)
1263 {
1264 	struct cmd_stainfo_param *cmd_sta_param = (struct cmd_stainfo_param *)param;
1265 
1266 	return _phl_alloc_stainfo(phl_info,
1267 					cmd_sta_param->sta,
1268 					cmd_sta_param->sta_addr,
1269 					cmd_sta_param->wrole,
1270 					cmd_sta_param->alloc,
1271 					cmd_sta_param->only_hw);
1272 }
1273 
1274 #endif /* CONFIG_CMD_DISP */
1275 
1276 enum rtw_phl_status
rtw_phl_cmd_alloc_stainfo(void * phl,struct rtw_phl_stainfo_t ** sta,u8 * sta_addr,struct rtw_wifi_role_t * wrole,bool alloc,bool only_hw,enum phl_cmd_type cmd_type,u32 cmd_timeout)1277 rtw_phl_cmd_alloc_stainfo(void *phl,
1278                           struct rtw_phl_stainfo_t **sta,
1279                           u8 *sta_addr,
1280                           struct rtw_wifi_role_t *wrole,
1281                           bool alloc, bool only_hw,
1282                           enum phl_cmd_type cmd_type,
1283                           u32 cmd_timeout)
1284 {
1285 #ifdef CONFIG_CMD_DISP
1286 	return _phl_cmd_alloc_stainfo(phl, sta, sta_addr, wrole, alloc, only_hw, cmd_type, cmd_timeout);
1287 #else
1288 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: not support alloc stainfo cmd\n",
1289 				__func__);
1290 
1291 	return _phl_alloc_stainfo((struct phl_info_t *)phl, sta, sta_addr, wrole, alloc, only_hw);
1292 #endif /* CONFIG_CMD_DISP */
1293 }
1294 
1295 enum rtw_phl_status
phl_wifi_role_free_stainfo_hw(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)1296 phl_wifi_role_free_stainfo_hw(struct phl_info_t *phl_info,
1297                               struct rtw_wifi_role_t *wrole)
1298 {
1299 	struct macid_ctl_t *mc = phl_to_mac_ctrl(phl_info);
1300 	u16 max_macid_num = mc->max_num;
1301 	struct rtw_phl_stainfo_t *sta = NULL;
1302 	u32 *used_map;
1303 	u16 mid;
1304 
1305 	used_map = &mc->wifi_role_usedmap[wrole->id][0];
1306 
1307 	for(mid = 0; mid < max_macid_num; mid++) {
1308 		if (_phl_macid_is_used(used_map, mid)) {
1309 			sta = mc->sta[mid];
1310 			if (sta) {
1311 				PHL_INFO("%s [WR-%d] free sta_info(MID:%d)\n",
1312 					__func__, wrole->id, sta->macid);
1313 				phl_free_stainfo_hw(phl_info, sta);
1314 			}
1315 		}
1316 	}
1317 	return RTW_PHL_STATUS_SUCCESS;
1318 }
1319 
1320 enum rtw_phl_status
phl_wifi_role_free_stainfo_sw(struct phl_info_t * phl_info,struct rtw_wifi_role_t * role)1321 phl_wifi_role_free_stainfo_sw(struct phl_info_t *phl_info,
1322 				struct rtw_wifi_role_t *role)
1323 {
1324 	struct rtw_phl_stainfo_t *phl_sta = NULL;
1325 	struct stainfo_ctl_t *sta_ctrl = phl_to_sta_ctrl(phl_info);
1326 
1327 	PHL_DUMP_STACTRL_EX(phl_info);
1328 	do {
1329 		phl_sta = phl_stainfo_dequeue(phl_info, &role->assoc_sta_queue);
1330 
1331 		if (phl_sta) {
1332 #ifdef RTW_WKARD_CHECK_STAINFO_DOUBLE_DEL
1333 			phl_sta->allocated = false;
1334 #endif
1335 			phl_free_stainfo_sw(phl_info, phl_sta);
1336 			phl_stainfo_enqueue(phl_info,
1337 						&sta_ctrl->free_sta_queue, phl_sta);
1338 		}
1339 	} while(phl_sta != NULL);
1340 
1341 	return RTW_PHL_STATUS_SUCCESS;
1342 }
1343 
1344 enum rtw_phl_status
phl_wifi_role_free_stainfo(struct phl_info_t * phl_info,struct rtw_wifi_role_t * role)1345 phl_wifi_role_free_stainfo(struct phl_info_t *phl_info,
1346                            struct rtw_wifi_role_t *role)
1347 {
1348 	struct rtw_phl_stainfo_t *phl_sta = NULL;
1349 	struct stainfo_ctl_t *sta_ctrl = phl_to_sta_ctrl(phl_info);
1350 
1351 	PHL_DUMP_STACTRL_EX(phl_info);
1352 	do {
1353 		phl_sta = phl_stainfo_dequeue(phl_info, &role->assoc_sta_queue);
1354 
1355 		if (phl_sta) {
1356 #ifdef RTW_WKARD_CHECK_STAINFO_DOUBLE_DEL
1357 			phl_sta->allocated = false;
1358 #endif
1359 			phl_free_stainfo_hw(phl_info, phl_sta);
1360 			phl_free_stainfo_sw(phl_info, phl_sta);
1361 			phl_stainfo_enqueue(phl_info,
1362 			                    &sta_ctrl->free_sta_queue,
1363 			                    phl_sta);
1364 		}
1365 	} while(phl_sta != NULL);
1366 
1367 	return RTW_PHL_STATUS_SUCCESS;
1368 }
1369 
1370 /**
1371  * According to 802.11 spec 26.5.2.3.2
1372  * We shall not transmit HE TB PPDU with RU-26 on DFS channel
1373  */
1374 static void
_phl_set_dfs_tb_ctrl(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)1375 _phl_set_dfs_tb_ctrl(struct phl_info_t *phl_info,
1376 		     struct rtw_wifi_role_t *wrole)
1377 {
1378 	struct rtw_regulation_channel reg_ch = {0};
1379 	enum band_type band = wrole->chandef.band;
1380 	u8 channel = wrole->chandef.chan;
1381 	bool is_dfs = false;
1382 
1383 
1384 	if (rtw_phl_regulation_query_ch(phl_info, band, channel, &reg_ch)) {
1385 		if (reg_ch.property & CH_DFS)
1386 			is_dfs = true;
1387 
1388 		rtw_hal_set_dfs_tb_ctrl(phl_info->hal, is_dfs);
1389 	}
1390 }
1391 
1392 static void
_phl_no_link_reset_sta_info(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta)1393 _phl_no_link_reset_sta_info(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta)
1394 {
1395 	void *drv = phl_to_drvpriv(phl_info);
1396 
1397 	/* asoc cap */
1398 	_os_mem_set(drv, &sta->asoc_cap, 0, sizeof(struct protocol_cap_t));
1399 
1400 	/* other capabilities under stainfo need to reset with default value */
1401 	sta->tf_trs = 0;
1402 
1403 	/* protection mode */
1404 	sta->protect = RTW_PROTECT_DISABLE;
1405 }
1406 
1407 /**
1408  * This function is called once station associated with AP
1409  * or incoming station got associated under AP mode.
1410  * Before calling this function, update address / net_type / ...
1411  * information of stainfo
1412  * It will configure some hw register, ex
1413  * address cam
1414  * @phl: see phl_info_t
1415  * @stainfo: information is updated through phl_station_info
1416  */
1417 static enum rtw_phl_status
phl_update_media_status(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta,u8 * sta_addr,bool is_connect)1418 phl_update_media_status(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta,
1419 			u8 *sta_addr, bool is_connect)
1420 {
1421 	struct rtw_wifi_role_t *wrole = sta->wrole;
1422 	void *drv = phl_to_drvpriv(phl_info);
1423 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1424 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1425 	bool is_sta_linked = false;
1426 
1427 	is_sta_linked = rtw_hal_is_sta_linked(phl_info->hal, sta);
1428 	if (is_connect == true && is_sta_linked == true) {
1429 		PHL_ERR("%s STA (MAC_ID:%d) had connected\n", __func__, sta->macid);
1430 		goto _exit;
1431 	}
1432 	if (is_connect == false && is_sta_linked == false) {
1433 		/* handle connect abort case */
1434 		if (wrole->mstate == MLME_LINKING) {
1435 			PHL_INFO("%s MAC_ID(%d) connect abort\n", __func__, sta->macid);
1436 			pstatus = RTW_PHL_STATUS_SUCCESS;
1437 		} else {
1438 			PHL_ERR("%s MAC_ID(%d) had disconnected\n", __func__, sta->macid);
1439 		}
1440 
1441 		if (wrole->type == PHL_RTYPE_STATION || wrole->type == PHL_RTYPE_P2P_GC)
1442 			wrole->mstate = MLME_NO_LINK;
1443 		goto _exit;
1444 	}
1445 
1446 	/* reset trx statistics */
1447 	if (is_connect == false) {
1448 		phl_reset_tx_stats(&sta->stats);
1449 		phl_reset_rx_stats(&sta->stats);
1450 		_phl_no_link_reset_sta_info(phl_info, sta);
1451 		CLEAR_STATUS_FLAG(wrole->status, WR_STATUS_TSF_SYNC);
1452 	} else {
1453 		phl_clean_sta_bcn_info(phl_info, sta);
1454 	}
1455 
1456 	/* Configure address cam, including net_type and sync_tsf */
1457 	if ((wrole->type == PHL_RTYPE_STATION) || (wrole->type == PHL_RTYPE_P2P_GC)
1458 	#ifdef CONFIG_PHL_TDLS
1459 		/* STA disconnects with the associated AP before tearing down with TDLS peers */
1460 		|| ((wrole->type == PHL_RTYPE_TDLS) && (!sta_addr))
1461 	#endif
1462 	) {
1463 		if (is_connect) {
1464 			wrole->mstate = MLME_LINKED;
1465 			_os_mem_cpy(drv, sta->mac_addr, sta_addr, MAC_ALEN);
1466 			_phl_set_dfs_tb_ctrl(phl_info, wrole);
1467 		} else {
1468 			wrole->mstate = MLME_NO_LINK;
1469 		}
1470 	}
1471 	#ifdef RTW_WKARD_AP_CLIENT_ADD_DEL_NTY
1472 	else if ((wrole->type == PHL_RTYPE_AP) ||
1473 		  (wrole->type == PHL_RTYPE_VAP) ||
1474 		  (wrole->type == PHL_RTYPE_MESH) ||
1475 		  (wrole->type == PHL_RTYPE_P2P_GO)) {
1476 			if (is_connect)
1477 				phl_role_ap_client_notify(phl_info, wrole, MLME_LINKED);
1478 	}
1479 	#endif
1480 	hstatus = rtw_hal_update_sta_entry(phl_info->hal, sta, is_connect);
1481 	if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1482 		PHL_ERR("rtw_hal_update_sta_entry failure!\n");
1483 		goto _exit;
1484 	}
1485 
1486 	if (wrole->type == PHL_RTYPE_STATION
1487 	#ifdef CONFIG_PHL_TDLS
1488 		/* STA disconnects with the associated AP before tearing down with TDLS peers */
1489 		|| ((wrole->type == PHL_RTYPE_TDLS) && (!sta_addr))
1490 	#endif
1491 	) {
1492 		hstatus = rtw_hal_role_cfg(phl_info->hal, wrole);
1493 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1494 			PHL_ERR("rtw_hal_role_cfg failure!\n");
1495 			goto _exit;
1496 		}
1497 	}
1498 
1499 	pstatus = RTW_PHL_STATUS_SUCCESS;
1500 
1501 	/* TODO: Configure RCR */
1502 _exit:
1503 	return pstatus;
1504 }
1505 
1506 #ifdef CONFIG_CMD_DISP
1507 struct sta_media_param {
1508 	struct rtw_phl_stainfo_t *sta;
1509 	u8 sta_addr[MAC_ALEN];
1510 	bool is_connect;
1511 };
1512 
1513 enum rtw_phl_status
phl_update_media_status_hdl(struct phl_info_t * phl_info,u8 * param)1514 phl_update_media_status_hdl(struct phl_info_t *phl_info, u8 *param)
1515 {
1516 	struct sta_media_param *media_sts = (struct sta_media_param *)param;
1517 
1518 	return phl_update_media_status(phl_info,
1519 			media_sts->sta, media_sts->sta_addr, media_sts->is_connect);
1520 }
1521 
phl_update_media_status_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)1522 void phl_update_media_status_done(void *drv_priv, u8 *cmd, u32 cmd_len,
1523 						enum rtw_phl_status status)
1524 {
1525 	if (cmd) {
1526 		_os_kmem_free(drv_priv, cmd, cmd_len);
1527 		cmd = NULL;
1528 	}
1529 }
1530 #endif
1531 
1532 enum rtw_phl_status
rtw_phl_cmd_update_media_status(void * phl,struct rtw_phl_stainfo_t * sta,u8 * sta_addr,bool is_connect,enum phl_cmd_type cmd_type,u32 cmd_timeout)1533 rtw_phl_cmd_update_media_status(void *phl,
1534                                 struct rtw_phl_stainfo_t *sta,
1535                                 u8 *sta_addr,
1536                                 bool is_connect,
1537                                 enum phl_cmd_type cmd_type,
1538                                 u32 cmd_timeout)
1539 {
1540 #ifdef CONFIG_CMD_DISP
1541 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
1542 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1543 	void *drv = phl_to_drvpriv(phl_info);
1544 	struct rtw_wifi_role_t *wrole = NULL;
1545 	struct sta_media_param *sta_ms = NULL;
1546 	u32 sta_ms_len = 0;
1547 
1548 	if (cmd_type == PHL_CMD_DIRECTLY) {
1549 		psts = phl_update_media_status(phl_info, sta, sta_addr, is_connect);
1550 		goto _exit;
1551 	}
1552 
1553 	sta_ms_len = sizeof(struct sta_media_param);
1554 	sta_ms = _os_kmem_alloc(drv, sta_ms_len);
1555 	if (sta_ms == NULL) {
1556 		PHL_ERR("%s: alloc sta media status param failed!\n", __func__);
1557 		psts = RTW_PHL_STATUS_RESOURCE;
1558 		goto _exit;
1559 	}
1560 	_os_mem_set(drv, sta_ms, 0, sta_ms_len);
1561 	sta_ms->sta = sta;
1562 	sta_ms->is_connect = is_connect;
1563 	if (is_connect && sta_addr)
1564 		_os_mem_cpy(drv, sta_ms->sta_addr, sta_addr, MAC_ALEN);
1565 
1566 	wrole = sta->wrole;
1567 
1568 	psts = phl_cmd_enqueue(phl_info,
1569 	                       wrole->hw_band,
1570 	                       MSG_EVT_STA_MEDIA_STATUS_UPT,
1571 	                       (u8*)sta_ms,
1572 	                       sta_ms_len,
1573 	                       phl_update_media_status_done,
1574 	                       cmd_type,
1575 	                       cmd_timeout);
1576 
1577 	if (is_cmd_failure(psts)) {
1578 		/* Send cmd success, but wait cmd fail*/
1579 		psts = RTW_PHL_STATUS_FAILURE;
1580 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
1581 		/* Send cmd fail */
1582 		psts = RTW_PHL_STATUS_FAILURE;
1583 		_os_kmem_free(drv, sta_ms, sta_ms_len);
1584 	}
1585 _exit:
1586 	return psts;
1587 #else
1588 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: not support cmd to update media status\n",
1589 	          __func__);
1590 
1591 	return phl_update_media_status((struct phl_info_t *)phl, sta, sta_addr, is_connect);
1592 #endif
1593 }
1594 
1595 /**
1596  * This function is called once station info changed
1597  * (BW/NSS/RAMASK/SEC/ROLE/MACADDR........)
1598  * @phl: see phl_info_t
1599  * @stainfo: information is updated through phl_station_info
1600  * @mode: see phl_upd_mode
1601  */
1602 enum rtw_phl_status
phl_change_stainfo(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta,enum phl_upd_mode mode)1603 phl_change_stainfo(struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta,
1604 			enum phl_upd_mode mode)
1605 {
1606 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1607 
1608 	hstatus = rtw_hal_change_sta_entry(phl_info->hal, sta, mode);
1609 	if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1610 		PHL_ERR("rtw_hal_change_sta_entry failure!\n");
1611 		return RTW_PHL_STATUS_FAILURE;
1612 	}
1613 	return RTW_PHL_STATUS_SUCCESS;
1614 }
1615 
1616 static enum rtw_phl_status
_change_stainfo(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta,enum sta_chg_id chg_id,u8 * chg_info,u8 chg_info_len)1617 _change_stainfo(struct phl_info_t *phl_info,
1618 	struct rtw_phl_stainfo_t *sta, enum sta_chg_id chg_id, u8 *chg_info, u8 chg_info_len)
1619 {
1620 	enum phl_upd_mode mode = PHL_UPD_STA_INFO_CHANGE;
1621 
1622 	switch (chg_id) {
1623 	case STA_CHG_BW:
1624 	case STA_CHG_NSS:
1625 	case STA_CHG_RAMASK:
1626 	{
1627 		PHL_INFO("%s MACID:%d %02x:%02x:%02x:%02x:%02x:%02x update bw\n",
1628 		         __func__, sta->macid,
1629 		         sta->mac_addr[0], sta->mac_addr[1], sta->mac_addr[2],
1630 		         sta->mac_addr[3], sta->mac_addr[4], sta->mac_addr[5]);
1631 	}
1632 		break;
1633 	case STA_CHG_SEC_MODE:
1634 		sta->sec_mode = *((u8*)chg_info);
1635 		break;
1636 	case STA_CHG_MBSSID:
1637 		sta->addr_sel = 1;
1638 		sta->addr_msk = *((u8*)chg_info);
1639 		break;
1640 	case STA_CHG_RA_GILTF:
1641 		sta->hal_sta->ra_info.cal_giltf = *((u8*)chg_info);
1642 		sta->hal_sta->ra_info.fix_giltf_en = true;
1643 		PHL_INFO("%s: Config RA GI LTF = %d\n", __FUNCTION__, *((u8*)chg_info));
1644 		break;
1645 	case STA_CHG_MAX:
1646 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "rtw_phl_change_stainfo(): Unsupported case:%d, please check it\n",
1647 				chg_id);
1648 		break;
1649 	default:
1650 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "rtw_phl_change_stainfo(): Unrecognize case:%d, please check it\n",
1651 				chg_id);
1652 		break;
1653 	}
1654 
1655 	return phl_change_stainfo(phl_info, sta, mode);
1656 }
1657 
1658 #ifdef CONFIG_CMD_DISP
1659 struct sta_chg_param {
1660 	struct rtw_phl_stainfo_t *sta;
1661 	enum sta_chg_id id;
1662 	u8 *info;
1663 	u8 info_len;
1664 };
1665 
1666 enum rtw_phl_status
phl_cmd_change_stainfo_hdl(struct phl_info_t * phl_info,u8 * param)1667 phl_cmd_change_stainfo_hdl(struct phl_info_t *phl_info, u8 *param)
1668 {
1669 	struct sta_chg_param *sta_param = (struct sta_chg_param *)param;
1670 
1671 	return _change_stainfo(phl_info,
1672 			sta_param->sta, sta_param->id,
1673 			sta_param->info, sta_param->info_len);
1674 }
1675 
1676 static void
_phl_cmd_change_stainfo_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)1677 _phl_cmd_change_stainfo_done(void *drv_priv, u8 *cmd, u32 cmd_len,
1678 						enum rtw_phl_status status)
1679 {
1680 	struct sta_chg_param *sta_chg_info = NULL;
1681 
1682 	if (cmd == NULL || cmd_len == 0) {
1683 		PHL_ERR("%s buf == NULL || buf_len == 0\n", __func__);
1684 		_os_warn_on(1);
1685 		return;
1686 	}
1687 
1688 	sta_chg_info = (struct sta_chg_param *)cmd;
1689 	PHL_INFO("%s - id:%d .....\n", __func__, sta_chg_info->id);
1690 
1691 	if (sta_chg_info->info && sta_chg_info->info_len > 0)
1692 		_os_kmem_free(drv_priv, sta_chg_info->info, sta_chg_info->info_len);
1693 
1694 	_os_kmem_free(drv_priv, cmd, cmd_len);
1695 	cmd = NULL;
1696 }
1697 
1698 static enum rtw_phl_status
_phl_cmd_change_stainfo(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta,enum sta_chg_id chg_id,u8 * chg_info,u8 chg_info_len,enum phl_cmd_type cmd_type,u32 cmd_timeout)1699 _phl_cmd_change_stainfo(struct phl_info_t *phl_info,
1700 	struct rtw_phl_stainfo_t *sta, enum sta_chg_id chg_id,
1701 	u8 *chg_info, u8 chg_info_len,
1702 	enum phl_cmd_type cmd_type, u32 cmd_timeout)
1703 {
1704 	void *drv = phl_to_drvpriv(phl_info);
1705 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
1706 	struct rtw_wifi_role_t *wrole = sta->wrole;
1707 	struct sta_chg_param *param = NULL;
1708 	u8 param_len = 0;
1709 
1710 	if (cmd_type == PHL_CMD_DIRECTLY) {
1711 		psts = _change_stainfo(phl_info, sta, chg_id, chg_info, chg_info_len);
1712 		goto _exit;
1713 	}
1714 
1715 	param_len = sizeof(struct sta_chg_param);
1716 	param = _os_kmem_alloc(drv, param_len);
1717 	if (param == NULL) {
1718 		PHL_ERR("%s: alloc param failed!\n", __func__);
1719 		psts = RTW_PHL_STATUS_RESOURCE;
1720 		goto _exit;
1721 	}
1722 
1723 	_os_mem_set(drv, param, 0, param_len);
1724 	param->sta = sta;
1725 	param->id = chg_id;
1726 	param->info_len = chg_info_len;
1727 
1728 	if (chg_info_len > 0) {
1729 		param->info = _os_kmem_alloc(drv, chg_info_len);
1730 		if (param->info == NULL) {
1731 			PHL_ERR("%s: alloc param->info failed!\n", __func__);
1732 			psts = RTW_PHL_STATUS_RESOURCE;
1733 			goto _err_info;
1734 		}
1735 
1736 		_os_mem_set(drv, param->info, 0, chg_info_len);
1737 		_os_mem_cpy(drv, param->info, chg_info, chg_info_len);
1738 	} else {
1739 		param->info = NULL;
1740 	}
1741 
1742 	psts = phl_cmd_enqueue(phl_info,
1743 	                       wrole->hw_band,
1744 	                       MSG_EVT_STA_CHG_STAINFO,
1745 	                       (u8 *)param,
1746 	                       param_len,
1747 	                       _phl_cmd_change_stainfo_done,
1748 	                       cmd_type,
1749 	                       cmd_timeout);
1750 
1751 	if (is_cmd_failure(psts)) {
1752 		/* Send cmd success, but wait cmd fail*/
1753 		psts = RTW_PHL_STATUS_FAILURE;
1754 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
1755 		/* Send cmd fail */
1756 		psts = RTW_PHL_STATUS_FAILURE;
1757 		goto _err_cmd;
1758 	}
1759 
1760 	return psts;
1761 
1762 _err_cmd:
1763 	if (param->info)
1764 		_os_kmem_free(drv, param->info, param->info_len);
1765 _err_info:
1766 	if (param)
1767 		_os_kmem_free(drv, param, param_len);
1768 _exit:
1769 	return psts;
1770 }
1771 #endif
1772 
1773 enum rtw_phl_status
rtw_phl_cmd_change_stainfo(void * phl,struct rtw_phl_stainfo_t * sta,enum sta_chg_id chg_id,u8 * chg_info,u8 chg_info_len,enum phl_cmd_type cmd_type,u32 cmd_timeout)1774 rtw_phl_cmd_change_stainfo(void *phl,
1775 	struct rtw_phl_stainfo_t *sta, enum sta_chg_id chg_id,
1776 	u8 *chg_info, u8 chg_info_len,
1777 	enum phl_cmd_type cmd_type, u32 cmd_timeout)
1778 {
1779 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1780 
1781 #ifdef CONFIG_CMD_DISP
1782 	return _phl_cmd_change_stainfo(phl_info, sta, chg_id, chg_info, chg_info_len,
1783 		cmd_type, cmd_timeout);
1784 #else
1785 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: not support alloc stainfo cmd\n",
1786 				__func__);
1787 
1788 	return _change_stainfo(phl_info, sta, chg_id, chg_info, chg_info_len);
1789 #endif /* CONFIG_CMD_DISP */
1790 }
1791 /**
1792  * This function updates tx/rx traffic status of each active station info
1793  */
1794 void
phl_sta_trx_tfc_upd(struct phl_info_t * phl_info)1795 phl_sta_trx_tfc_upd(struct phl_info_t *phl_info)
1796 {
1797 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
1798 	struct rtw_phl_stainfo_t *phl_sta = NULL;
1799 	struct rtw_stats *sta_stats = NULL;
1800 	u16 max_macid_num = 0;
1801 	u16 mid = 0;
1802 
1803 	max_macid_num = macid_ctl->max_num;
1804 
1805 	_os_spinlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
1806 	for(mid = 0; mid < max_macid_num; mid++) {
1807 		if (_phl_macid_is_used(macid_ctl->used_map, mid)) {
1808 			phl_sta = macid_ctl->sta[mid];
1809 			if (phl_sta) {
1810 				#ifdef CONFIG_PHL_RA_TXSTS_DBG
1811 				/* issue H2C to get ra txsts report */
1812 				rtw_phl_txsts_rpt_config(phl_info, phl_sta);
1813 				#endif
1814 				sta_stats = &phl_sta->stats;
1815 				phl_tx_traffic_upd(sta_stats);
1816 				phl_rx_traffic_upd(sta_stats);
1817 			}
1818 		}
1819 	}
1820 	_os_spinunlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
1821 }
1822 
1823 
1824 /**
1825  * This function is used to get phl sta info
1826  * by macid
1827  * @phl: see phl_info_t
1828  * @macid: macid
1829  */
1830 struct rtw_phl_stainfo_t *
rtw_phl_get_stainfo_by_macid(void * phl,u16 macid)1831 rtw_phl_get_stainfo_by_macid(void *phl, u16 macid)
1832 {
1833 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1834 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
1835 	struct rtw_phl_stainfo_t *phl_sta = NULL;
1836 
1837 	if (macid >= macid_ctl->max_num) {
1838 		PHL_ERR("%s macid(%d) is invalid\n", __func__, macid);
1839 		return NULL;
1840 	}
1841 	_os_spinlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
1842 	if (_phl_macid_is_used(macid_ctl->used_map, macid))
1843 		phl_sta = macid_ctl->sta[macid];
1844 
1845 	if (phl_sta == NULL) {
1846 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_,"%s sta info (macid:%d) is NULL\n", __func__, macid);
1847 		#ifdef CONFIG_PHL_RELEASE_RPT_ENABLE
1848 		/* comment temporarily since release report may report unused macid */
1849 		/* and trigger call tracing */
1850 		/* _os_warn_on(1); */
1851 		#else
1852 		_os_warn_on(1);
1853 		#endif /* CONFIG_PHL_RELEASE_RPT_ENABLE */
1854 	}
1855 	_os_spinunlock(phl_to_drvpriv(phl_info), &macid_ctl->lock, _bh, NULL);
1856 
1857 	return phl_sta;
1858 }
1859 
1860 struct rtw_phl_stainfo_t *
rtw_phl_get_stainfo_by_addr_ex(void * phl,u8 * addr)1861 rtw_phl_get_stainfo_by_addr_ex(void *phl, u8 *addr)
1862 {
1863 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1864 	struct macid_ctl_t *mc = phl_to_mac_ctrl(phl_info);
1865 	struct rtw_phl_stainfo_t *sta = NULL;
1866 	u16 mid = 0;
1867 	u16 max_macid_num = mc->max_num;
1868 	bool sta_found = false;
1869 
1870 	_os_spinlock(phl_to_drvpriv(phl_info), &mc->lock, _bh, NULL);
1871 	for(mid = 0; mid < max_macid_num; mid++) {
1872 		if (_phl_macid_is_used(mc->used_map, mid)) {
1873 			sta = mc->sta[mid];
1874 			if (_os_mem_cmp(phl_to_drvpriv(phl_info),
1875 				sta->mac_addr, addr, MAC_ALEN) == 0) {
1876 				sta_found = true;
1877 				break;
1878 			}
1879 		}
1880 	}
1881 	_os_spinunlock(phl_to_drvpriv(phl_info), &mc->lock, _bh, NULL);
1882 
1883 	if (sta_found == false)
1884 		sta = NULL;
1885 	return sta;
1886 }
1887 
rtw_phl_get_macid_by_addr(void * phl,u8 * addr)1888 u16 rtw_phl_get_macid_by_addr(void *phl, u8 *addr)
1889 {
1890 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1891 	struct macid_ctl_t *mc = phl_to_mac_ctrl(phl_info);
1892 	struct rtw_phl_stainfo_t *sta = NULL;
1893 
1894 	sta = rtw_phl_get_stainfo_by_addr_ex(phl, addr);
1895 	if (sta)
1896 		return sta->macid;
1897 	return mc->max_num;
1898 }
1899 
1900 /**
1901  * This function is called to create phl_station_info
1902  * return pointer to rtw_phl_stainfo_t
1903  * @phl: see phl_info_t
1904  * @roleidx: index of wifi role(linux) port nubmer(windows)
1905  * @addr: current address of this station
1906  */
1907 struct rtw_phl_stainfo_t *
rtw_phl_get_stainfo_by_addr(void * phl,struct rtw_wifi_role_t * wrole,u8 * addr)1908 rtw_phl_get_stainfo_by_addr(void *phl, struct rtw_wifi_role_t *wrole, u8 *addr)
1909 {
1910 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1911 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
1912 	struct rtw_phl_stainfo_t *sta = NULL;
1913 
1914 	if (is_broadcast_mac_addr(addr)) {
1915 		u16 macid = macid_ctl->wrole_bmc[wrole->id];
1916 
1917 		if (macid >= macid_ctl->max_num)
1918 			sta = NULL;
1919 		else
1920 			sta = macid_ctl->sta[macid];
1921 		goto _exit;
1922 	}
1923 
1924 	sta = phl_stainfo_queue_search(phl_info,
1925 			 &wrole->assoc_sta_queue, addr);
1926 _exit:
1927 	return sta;
1928 }
1929 
1930 struct rtw_phl_stainfo_t *
rtw_phl_get_stainfo_self(void * phl,struct rtw_wifi_role_t * wrole)1931 rtw_phl_get_stainfo_self(void *phl, struct rtw_wifi_role_t *wrole)
1932 {
1933 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1934 	struct rtw_phl_stainfo_t *sta = NULL;
1935 
1936 	#if 0
1937 	if ((wrole->type == PHL_RTYPE_STATION) &&
1938 		(wrole->mstate == MLME_LINKED))
1939 			//????
1940 		else
1941 			sta = phl_stainfo_queue_search(phl_info,
1942 				&wrole->assoc_sta_queue, wrole->mac_addr);
1943 	}
1944 	#else
1945 	sta = phl_stainfo_queue_get_first(phl_info, &wrole->assoc_sta_queue);
1946 	if (sta == NULL)
1947 		PHL_ERR("%s sta == NULL\n", __func__);
1948 	#endif
1949 	return sta;
1950 }
1951 
1952 u8
rtw_phl_get_sta_rssi(struct rtw_phl_stainfo_t * sta)1953 rtw_phl_get_sta_rssi(struct rtw_phl_stainfo_t *sta)
1954 {
1955 	u8 rssi = rtw_hal_get_sta_rssi(sta);
1956 
1957 	return rssi;
1958 }
1959 
phl_get_min_rssi_bcn(struct phl_info_t * phl_info)1960 u8 phl_get_min_rssi_bcn(struct phl_info_t *phl_info)
1961 {
1962 	struct macid_ctl_t *macid_ctl = phl_to_mac_ctrl(phl_info);
1963 	struct rtw_phl_stainfo_t *sta = NULL;
1964 	u8 rssi_bcn_min = 0xFF;
1965 	u16 i = 0;
1966 	u8 rssi = 0;
1967 
1968 	for (i = 0; i < macid_ctl->max_num; i++) {
1969 		if (!_phl_macid_is_used(macid_ctl->used_map, i))
1970 			continue;
1971 
1972 		sta = rtw_phl_get_stainfo_by_macid(phl_info, i);
1973 
1974 		if (NULL == sta)
1975 			continue;
1976 
1977 		rssi = rtw_hal_get_sta_rssi_bcn(sta);
1978 
1979 		PHL_DBG("%s macid(%d) with rssi_bcn = %d\n",
1980 			__func__, i, rssi);
1981 
1982 		if (rssi == 0)
1983 			continue;
1984 
1985 		rssi_bcn_min = MIN(rssi, rssi_bcn_min);
1986 	}
1987 
1988 	return rssi_bcn_min;
1989 }
1990 
1991 
1992 enum rtw_phl_status
rtw_phl_query_rainfo(void * phl,struct rtw_phl_stainfo_t * phl_sta,struct rtw_phl_rainfo * ra_info)1993 rtw_phl_query_rainfo(void *phl, struct rtw_phl_stainfo_t *phl_sta,
1994 		     struct rtw_phl_rainfo *ra_info)
1995 {
1996 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1997 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_FAILURE;
1998 
1999 	do {
2000 		if (NULL == phl_sta) {
2001 			PHL_TRACE(COMP_PHL_XMIT, _PHL_ERR_,
2002 				  "%s : phl_sta is NULL\n",
2003 				  __func__);
2004 			break;
2005 		}
2006 
2007 		if (NULL == ra_info) {
2008 			PHL_TRACE(COMP_PHL_XMIT, _PHL_ERR_,
2009 				  "%s : Input parameter is NULL\n",
2010 				  __func__);
2011 			break;
2012 		}
2013 
2014 		if (RTW_HAL_STATUS_SUCCESS ==
2015 		    rtw_hal_query_rainfo(phl_info->hal, phl_sta->hal_sta,
2016 					 ra_info)) {
2017 			phl_sts = RTW_PHL_STATUS_SUCCESS;
2018 			break;
2019 		} else {
2020 			break;
2021 		}
2022 	} while (false);
2023 
2024 	return phl_sts;
2025 }
2026 
2027 enum rtw_phl_status
rtw_phl_get_rx_stat(void * phl,struct rtw_phl_stainfo_t * phl_sta,u16 * rx_rate,u8 * bw,u8 * gi_ltf)2028 rtw_phl_get_rx_stat(void *phl, struct rtw_phl_stainfo_t *phl_sta,
2029 		     u16 *rx_rate, u8 *bw, u8 *gi_ltf)
2030 {
2031 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_FAILURE;
2032 	struct rtw_hal_stainfo_t *hal_sta;
2033 
2034 	if(phl_sta) {
2035 		hal_sta = phl_sta->hal_sta;
2036 		*rx_rate = hal_sta->trx_stat.rx_rate;
2037 		*gi_ltf = hal_sta->trx_stat.rx_gi_ltf;
2038 		*bw = hal_sta->trx_stat.rx_bw;
2039 		phl_sts = RTW_PHL_STATUS_SUCCESS;
2040 	}
2041 
2042 	return phl_sts;
2043 }
2044 
2045 /**
2046  * rtw_phl_txsts_rpt_config() - issue h2c for txok and tx retry info
2047  * @phl:		struct phl_info_t *
2048  * @phl_sta:		indicate the first macid that you want to query.
2049  * Return rtw_phl_txsts_rpt_config's return value in enum rtw_phl_status type.
2050  */
2051 enum rtw_phl_status
rtw_phl_txsts_rpt_config(void * phl,struct rtw_phl_stainfo_t * phl_sta)2052 rtw_phl_txsts_rpt_config(void *phl, struct rtw_phl_stainfo_t *phl_sta)
2053 {
2054 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
2055 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_FAILURE;
2056 
2057 	if (phl_sta) {
2058 		if (RTW_HAL_STATUS_SUCCESS == rtw_hal_query_txsts_rpt(phl_info->hal, phl_sta->macid))
2059 			phl_sts = RTW_PHL_STATUS_SUCCESS;
2060 	}
2061 	return phl_sts;
2062 }
2063 
2064 #if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
2065 /**
2066  * rtw_phl_get_tx_ok_rpt() - get txok info.
2067  * @phl:		struct phl_info_t *
2068  * @phl_sta:		information is updated through phl_station_info.
2069  * @tx_ok_cnt:		buffer address that we used to store tx ok statistics.
2070  * @qsel			indicate which AC queue, or fetch all by PHL_AC_QUEUE_TOTAL
2071  *
2072  * Return rtw_phl_get_tx_ok_rpt's return value in enum rtw_phl_status type.
2073  */
2074 enum rtw_phl_status
rtw_phl_get_tx_ok_rpt(void * phl,struct rtw_phl_stainfo_t * phl_sta,u32 * tx_ok_cnt,enum phl_ac_queue qsel)2075 rtw_phl_get_tx_ok_rpt(void *phl, struct rtw_phl_stainfo_t *phl_sta, u32 *tx_ok_cnt,
2076  enum phl_ac_queue qsel)
2077 {
2078 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
2079 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_SUCCESS;
2080 	struct rtw_hal_stainfo_t *hal_sta;
2081 
2082 	if(phl_sta) {
2083 		hal_sta = phl_sta->hal_sta;
2084 
2085 		if (tx_ok_cnt && qsel <= PHL_AC_QUEUE_TOTAL) {
2086 			if (qsel == PHL_AC_QUEUE_TOTAL) {
2087 				/* copy all AC counter */
2088 				tx_ok_cnt[PHL_BE_QUEUE_SEL] = hal_sta->trx_stat.wp_rpt_stats[PHL_BE_QUEUE_SEL].tx_ok_cnt;
2089 				tx_ok_cnt[PHL_BK_QUEUE_SEL] = hal_sta->trx_stat.wp_rpt_stats[PHL_BK_QUEUE_SEL].tx_ok_cnt;
2090 				tx_ok_cnt[PHL_VI_QUEUE_SEL] = hal_sta->trx_stat.wp_rpt_stats[PHL_VI_QUEUE_SEL].tx_ok_cnt;
2091 				tx_ok_cnt[PHL_VO_QUEUE_SEL] = hal_sta->trx_stat.wp_rpt_stats[PHL_VO_QUEUE_SEL].tx_ok_cnt;
2092 
2093 				/* reset all counter */
2094 				_os_spinlock(phl_to_drvpriv(phl_info), &hal_sta->trx_stat.tx_sts_lock, _bh, NULL);
2095 				hal_sta->trx_stat.wp_rpt_stats[PHL_BE_QUEUE_SEL].tx_ok_cnt = 0;
2096 				hal_sta->trx_stat.wp_rpt_stats[PHL_BK_QUEUE_SEL].tx_ok_cnt = 0;
2097 				hal_sta->trx_stat.wp_rpt_stats[PHL_VI_QUEUE_SEL].tx_ok_cnt = 0;
2098 				hal_sta->trx_stat.wp_rpt_stats[PHL_VO_QUEUE_SEL].tx_ok_cnt = 0;
2099 				_os_spinunlock(phl_to_drvpriv(phl_info), &hal_sta->trx_stat.tx_sts_lock, _bh, NULL);
2100 			} else {
2101 				/*copy target AC queue counter*/
2102 				*tx_ok_cnt = hal_sta->trx_stat.wp_rpt_stats[qsel].tx_ok_cnt;
2103 				/* reset target AC queue counter */
2104 				_os_spinlock(phl_to_drvpriv(phl_info), &hal_sta->trx_stat.tx_sts_lock, _bh, NULL);
2105 				hal_sta->trx_stat.wp_rpt_stats[qsel].tx_ok_cnt = 0;
2106 				_os_spinunlock(phl_to_drvpriv(phl_info), &hal_sta->trx_stat.tx_sts_lock, _bh, NULL);
2107 			}
2108 		} else {
2109 			phl_sts = RTW_PHL_STATUS_FAILURE;
2110 			PHL_ERR("tx_ok_cnt = %p, qsel = %d\n", tx_ok_cnt, qsel);
2111 		}
2112 
2113 	} else {
2114 		phl_sts = RTW_PHL_STATUS_FAILURE;
2115 		PHL_ERR("PHL STA NULL.\n");
2116 	}
2117 	return phl_sts;
2118 }
2119 
rtw_phl_get_hw_tx_fail_cnt(struct rtw_hal_stainfo_t * hal_sta,enum phl_ac_queue qsel)2120 static u32 rtw_phl_get_hw_tx_fail_cnt(struct rtw_hal_stainfo_t *hal_sta,
2121 	enum phl_ac_queue qsel) {
2122 	u32 total = 0;
2123 
2124 	if (hal_sta) {
2125 		total = hal_sta->trx_stat.wp_rpt_stats[qsel].rty_fail_cnt\
2126 				+ hal_sta->trx_stat.wp_rpt_stats[qsel].lifetime_drop_cnt \
2127 				+ hal_sta->trx_stat.wp_rpt_stats[qsel].macid_drop_cnt;
2128 	}
2129 
2130 	return total;
2131 }
2132 
rtw_phl_reset_tx_fail_cnt(struct phl_info_t * phl_info,struct rtw_hal_stainfo_t * hal_sta,enum phl_ac_queue qsel)2133 static void rtw_phl_reset_tx_fail_cnt(struct phl_info_t *phl_info,
2134 	struct rtw_hal_stainfo_t *hal_sta, enum phl_ac_queue qsel) {
2135 
2136 	if (hal_sta) {
2137 		_os_spinlock(phl_to_drvpriv(phl_info), &hal_sta->trx_stat.tx_sts_lock, _bh, NULL);
2138 		hal_sta->trx_stat.wp_rpt_stats[qsel].rty_fail_cnt = 0;
2139 		hal_sta->trx_stat.wp_rpt_stats[qsel].lifetime_drop_cnt = 0;
2140 		hal_sta->trx_stat.wp_rpt_stats[qsel].macid_drop_cnt = 0;
2141 		_os_spinunlock(phl_to_drvpriv(phl_info), &hal_sta->trx_stat.tx_sts_lock, _bh, NULL);
2142 	}
2143 }
2144 
2145 /**
2146  * rtw_phl_get_tx_fail_rpt() - get tx fail info.
2147  * @phl:		struct phl_info_t *
2148  * @phl_sta:		information is updated through phl_station_info.
2149  * @tx_fail_cnt:	buffer address that we used to store tx fail statistics.
2150  * @qsel			indicate which AC queue, or fetch all by PHL_AC_QUEUE_TOTAL
2151  *
2152  * Return rtw_phl_get_tx_fail_rpt's return value in enum rtw_phl_status type.
2153  */
2154 enum rtw_phl_status
rtw_phl_get_tx_fail_rpt(void * phl,struct rtw_phl_stainfo_t * phl_sta,u32 * tx_fail_cnt,enum phl_ac_queue qsel)2155 rtw_phl_get_tx_fail_rpt(void *phl, struct rtw_phl_stainfo_t *phl_sta, u32 *tx_fail_cnt,
2156  enum phl_ac_queue qsel)
2157 {
2158 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
2159 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_SUCCESS;
2160 	struct rtw_hal_stainfo_t *hal_sta;
2161 
2162 	if(phl_sta) {
2163 		hal_sta = phl_sta->hal_sta;
2164 
2165 		if (tx_fail_cnt && qsel <= PHL_AC_QUEUE_TOTAL) {
2166 			if (qsel == PHL_AC_QUEUE_TOTAL) {
2167 				/* copy all AC counter */
2168 				tx_fail_cnt[PHL_BE_QUEUE_SEL] = rtw_phl_get_hw_tx_fail_cnt(hal_sta, PHL_BE_QUEUE_SEL);
2169 				tx_fail_cnt[PHL_BK_QUEUE_SEL] = rtw_phl_get_hw_tx_fail_cnt(hal_sta, PHL_BK_QUEUE_SEL);
2170 				tx_fail_cnt[PHL_VI_QUEUE_SEL] = rtw_phl_get_hw_tx_fail_cnt(hal_sta, PHL_VI_QUEUE_SEL);
2171 				tx_fail_cnt[PHL_VO_QUEUE_SEL] = rtw_phl_get_hw_tx_fail_cnt(hal_sta, PHL_VO_QUEUE_SEL);
2172 				/* reset all counter */
2173 				rtw_phl_reset_tx_fail_cnt(phl_info, hal_sta, PHL_BE_QUEUE_SEL);
2174 				rtw_phl_reset_tx_fail_cnt(phl_info, hal_sta, PHL_BK_QUEUE_SEL);
2175 				rtw_phl_reset_tx_fail_cnt(phl_info, hal_sta, PHL_VI_QUEUE_SEL);
2176 				rtw_phl_reset_tx_fail_cnt(phl_info, hal_sta, PHL_VO_QUEUE_SEL);
2177 			} else {
2178 				/*copy target AC queue counter*/
2179 				tx_fail_cnt[qsel] = rtw_phl_get_hw_tx_fail_cnt(hal_sta, qsel);
2180 				/* reset target AC queue counter */
2181 				rtw_phl_reset_tx_fail_cnt(phl_info, hal_sta, qsel);
2182 			}
2183 		} else {
2184 			phl_sts = RTW_PHL_STATUS_FAILURE;
2185 			PHL_ERR("tx_fail_cnt = %p, qsel = %d\n", tx_fail_cnt, qsel);
2186 		}
2187 	} else {
2188 		phl_sts = RTW_PHL_STATUS_FAILURE;
2189 		PHL_ERR("PHL STA NULL.\n");
2190 	}
2191 	return phl_sts;
2192 }
2193 
2194 /**
2195  * rtw_phl_get_tx_retry_rpt() - get tx retry info.
2196  * @phl:		struct phl_info_t *
2197  * @phl_sta:		information is updated through phl_station_info.
2198  * @tx_retry_cnt:	buffer address that we used to store tx fail statistics.
2199  * @qsel			indicate which AC queue, or fetch all by PHL_AC_QUEUE_TOTAL
2200  *
2201  * Return rtw_phl_get_tx_retry_rpt's return value in enum rtw_phl_status type.
2202  */
2203 enum rtw_phl_status
rtw_phl_get_tx_retry_rpt(void * phl,struct rtw_phl_stainfo_t * phl_sta,u32 * tx_retry_cnt,enum phl_ac_queue qsel)2204 rtw_phl_get_tx_retry_rpt(void *phl, struct rtw_phl_stainfo_t *phl_sta, u32 *tx_retry_cnt,
2205  enum phl_ac_queue qsel)
2206 {
2207 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
2208 	void *drv = phl_to_drvpriv(phl_info);
2209 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_SUCCESS;
2210 	struct rtw_hal_stainfo_t *hal_sta;
2211 
2212 	if(phl_sta) {
2213 		hal_sta = phl_sta->hal_sta;
2214 
2215 		if (tx_retry_cnt && qsel <= PHL_AC_QUEUE_TOTAL) {
2216 			if (qsel == PHL_AC_QUEUE_TOTAL) {
2217 				/* copy all AC counter */
2218 				_os_mem_cpy(drv, tx_retry_cnt, hal_sta->ra_info.tx_retry_cnt,
2219 					sizeof(u32)*PHL_AC_QUEUE_TOTAL);
2220 				/* reset all counter */
2221 				/* TODO: Here needs lock, and so does halbb_get_txsts_rpt */
2222 				_os_mem_set(drv, hal_sta->ra_info.tx_retry_cnt, 0, sizeof(u32)*PHL_AC_QUEUE_TOTAL);
2223 			} else {
2224 				/*copy target AC queue counter*/
2225 				*tx_retry_cnt = hal_sta->ra_info.tx_retry_cnt[qsel];
2226 				/* reset target AC queue counter */
2227 				/* TODO: Here needs lock, and so does halbb_get_txsts_rpt */
2228 				hal_sta->ra_info.tx_retry_cnt[qsel] = 0;
2229 			}
2230 		} else {
2231 			phl_sts = RTW_PHL_STATUS_FAILURE;
2232 			PHL_ERR("tx_retry_cnt = %p, qsel = %d\n", tx_retry_cnt, qsel);
2233 		}
2234 	} else {
2235 		phl_sts = RTW_PHL_STATUS_FAILURE;
2236 		PHL_ERR("PHL STA NULL.\n");
2237 	}
2238 	return phl_sts;
2239 }
2240 #endif /* defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI) */
2241 
2242 /*
2243  * Get next idx
2244  */
_get_fidx(u8 num,u8 cur_idx)2245 u8 _get_fidx(u8 num, u8 cur_idx)
2246 {
2247 	u8 idx = 0;
2248 
2249 	if (num == 0)
2250 		idx = cur_idx;
2251 	else {
2252 		idx = cur_idx + 1;
2253 		if (idx >= MAX_STORE_BCN_NUM)
2254 			idx = 0;
2255 	}
2256 	return idx;
2257 }
2258 
2259 /*
2260  * Get previous idx
2261  */
_get_bidx(u8 num,u8 cur_idx)2262 u8 _get_bidx(u8 num, u8 cur_idx)
2263 {
2264 	u8 idx = 0;
2265 
2266 	if (cur_idx == 0) {
2267 		idx = num - 1;
2268 	} else {
2269 		idx = cur_idx - 1;
2270 	}
2271 	return idx;
2272 }
2273 
_phl_sta_up_bcn_offset_info(struct phl_info_t * phl,struct rtw_rx_bcn_info * bcn_i,u16 bcn_intvl)2274 void _phl_sta_up_bcn_offset_info(struct phl_info_t *phl,
2275 			struct rtw_rx_bcn_info *bcn_i, u16 bcn_intvl)
2276 {
2277 	struct rtw_bcn_offset *offset_i = &bcn_i->offset_i;
2278 	u16 offset = bcn_intvl;
2279 	u16 similar_th = 2;/*Unit: TU*/
2280 	u64 diff = 0;
2281 	u8 idx = 0, jdx = 0, cur_idx = 0, bidx = 0, start_idx = 0;
2282 
2283 	if (bcn_i->num == 1) {
2284 		offset_i->offset = (u16)bcn_i->info[1][bcn_i->idx];
2285 		offset_i->conf_lvl = CONF_LVL_LOW;
2286 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "_phl_sta_up_bcn_offset_info(): bcn_i->num ==1, conf_lvl = CONF_LVL_LOW, offset(%d)\n",
2287 			offset_i->offset);
2288 		goto exit;
2289 	}
2290 	cur_idx = bcn_i->idx;
2291 	start_idx = cur_idx;
2292 	for (idx = 0; idx < bcn_i->num; idx++) {
2293 		bidx = cur_idx;
2294 		for (jdx = 1; jdx < bcn_i->num; jdx++) {
2295 			bidx = _get_bidx(bcn_i->num, bidx);
2296 			if (start_idx == bidx)
2297 				break;
2298 			diff = bcn_i->info[0][cur_idx] - bcn_i->info[0][bidx];
2299 			diff = _os_division64(
2300 					_os_modular64(diff, bcn_intvl * TU), TU);
2301 			/*ex: diff = 99, BcnIntvl = 100, It's similar case
2302 			 * diff = 2, BcnIntvl = 100, It's similar case
2303 			 */
2304 			if (!((diff < similar_th) ||
2305 				((bcn_intvl - diff) < similar_th))) {
2306 					continue;
2307 			}
2308 			if (offset > bcn_i->info[1][cur_idx])
2309 				offset = (u16)bcn_i->info[1][cur_idx];
2310 			if (offset > bcn_i->info[1][bidx])
2311 				offset = (u16)bcn_i->info[1][bidx];
2312 		}
2313 		cur_idx = _get_bidx(bcn_i->num, cur_idx);
2314 	}
2315 	if (offset != bcn_intvl) {
2316 		offset_i->conf_lvl = CONF_LVL_HIGH;
2317 		if (offset < offset_i->offset) {
2318 			offset_i->offset = offset;
2319 		}
2320 		goto exit;
2321 	}
2322 	for (idx = 0; idx < bcn_i->num; idx++) {
2323 		if (bcn_i->info[1][idx] < offset_i->offset) {
2324 			offset_i->offset = (u16)bcn_i->info[1][idx];
2325 			offset_i->conf_lvl = CONF_LVL_MID;
2326 		}
2327 	}
2328 exit:
2329 	/*
2330 	   if offset is small, maybe impact by environment, offset < 5% bcn_intvl, we consider offset is 0
2331 	*/
2332 	if ((offset_i->offset != 0) &&
2333 		(offset_i->offset < ((bcn_intvl * 5) / 100))) {
2334 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_phl_sta_up_bcn_offset_info(): offset(%d) < (%d), set offset = 0\n",
2335 			offset_i->offset, (bcn_intvl * 5) / 100);
2336 		offset_i->offset = 0;
2337 	}
2338 	PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "_phl_sta_up_bcn_offset_info(): bcn num(%d), offset(%d), conf_lvl(%d), current CR(%d)\n",
2339 		bcn_i->num, offset_i->offset, offset_i->conf_lvl, offset_i->cr_tbtt_shift);
2340 	return;
2341 }
2342 
rtw_phl_sta_up_rx_bcn(void * phl,struct rtw_bcn_pkt_info * info)2343 void rtw_phl_sta_up_rx_bcn(void *phl, struct rtw_bcn_pkt_info *info)
2344 {
2345 	struct rtw_rx_bcn_info *bcn_i = &info->sta->bcn_i;
2346 	u16 bcn_intvl = info->sta->asoc_cap.bcn_interval;
2347 
2348 	if (bcn_intvl == 0) {
2349 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "bcn_intvl == 0");
2350 		return;
2351 	}
2352 
2353 	bcn_i->idx = _get_fidx(bcn_i->num, bcn_i->idx);
2354 	if (bcn_i->num < MAX_STORE_BCN_NUM)
2355 		bcn_i->num++;
2356 	bcn_i->info[0][bcn_i->idx] = info->tsf;
2357 	bcn_i->info[1][bcn_i->idx] = _os_division64(
2358 				_os_modular64(info->tsf, bcn_intvl * TU), TU);
2359 	bcn_i->info[2][bcn_i->idx] = info->hw_tsf;
2360 	_phl_sta_up_bcn_offset_info(phl, bcn_i, bcn_intvl);
2361 }
2362 
phl_clean_sta_bcn_info(struct phl_info_t * phl,struct rtw_phl_stainfo_t * sta)2363 void phl_clean_sta_bcn_info(struct phl_info_t *phl, struct rtw_phl_stainfo_t *sta)
2364 {
2365 	void *priv = phl_to_drvpriv(phl);
2366 	struct rtw_rx_bcn_info *bcn_i = &sta->bcn_i;
2367 
2368 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "phl_clean_sta_bcn_info(): sta->wrole->id(%d)\n",
2369 		sta->wrole->id);
2370 	_os_mem_set(priv, bcn_i, 0, sizeof(struct rtw_rx_bcn_info));
2371 }
2372 
phl_get_sta_bcn_offset_info(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole)2373 struct rtw_bcn_offset * phl_get_sta_bcn_offset_info(struct phl_info_t *phl,
2374 					struct rtw_wifi_role_t *wrole)
2375 {
2376 	struct rtw_phl_stainfo_t *sta = rtw_phl_get_stainfo_self(phl, wrole);
2377 	struct rtw_bcn_offset *offset_i = &sta->bcn_i.offset_i;
2378 
2379 	return offset_i;
2380 }
2381 
phl_bcn_watchdog(struct phl_info_t * phl)2382 void phl_bcn_watchdog(struct phl_info_t *phl)
2383 {
2384 	u8 ridx = MAX_WIFI_ROLE_NUMBER;
2385 	struct rtw_wifi_role_t *wrole = NULL;
2386 	struct rtw_bcn_offset *b_ofst_i = NULL;
2387 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
2388 
2389 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2390 		wrole = rtw_phl_get_wrole_by_ridx(phl->phl_com, ridx);
2391 		if (wrole->active == false)
2392 			continue;
2393 
2394 		if (rtw_phl_role_is_client_category(wrole) && wrole->mstate == MLME_LINKED) {
2395 			b_ofst_i = phl_get_sta_bcn_offset_info(phl, wrole);
2396 
2397 			if (b_ofst_i->conf_lvl >= CONF_LVL_MID &&
2398 				b_ofst_i->offset != b_ofst_i->cr_tbtt_shift) {
2399 				PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s(): update bcn offset to %d TU\n",
2400 							__func__, b_ofst_i->offset);
2401 				hstatus = rtw_hal_role_cfg_ex(phl->hal, wrole, PCFG_TBTT_SHIFT, &(b_ofst_i->offset));
2402 				if (hstatus == RTW_HAL_STATUS_SUCCESS)
2403 					b_ofst_i->cr_tbtt_shift = b_ofst_i->offset;
2404 				else
2405 					PHL_ERR("%s(): role cfg fail, status: %d\n", __func__, hstatus);
2406 			}
2407 		}
2408 	}
2409 }
2410 
2411 /*
2412  * calculate the value between current TSF and TBTT
2413  * TSF   0       50    180    150              250
2414  * TBTT          ^                ^                ^
2415  * Curr T                 |
2416  *                   | 30 |
2417  *
2418  * TSF   0       80     120     180              280
2419  * TBTT           ^                 ^                 ^
2420  * Curr T                  |
2421  *                   | 40  |
2422  * @wrole: specific role, we get bcn offset info from the role.
2423  * @cur_t: current TSF
2424  * @ofst: output value, unit: TU
2425  */
phl_calc_offset_from_tbtt(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,u64 cur_t,u16 * ofst)2426 bool phl_calc_offset_from_tbtt(struct phl_info_t *phl,
2427 			struct rtw_wifi_role_t *wrole, u64 cur_t, u16 *ofst)
2428 {
2429 	struct rtw_bcn_offset *b_ofst_i = phl_get_sta_bcn_offset_info(phl, wrole);
2430 	struct rtw_phl_stainfo_t *sta = rtw_phl_get_stainfo_self(phl, wrole);
2431 	u64 b_ofst = b_ofst_i->offset;
2432 	u64 b_intvl = 0;
2433 	u32 mod = 0; /*TU*/
2434 
2435 #ifdef RTW_PHL_BCN
2436 	if (phl_role_is_ap_category(wrole))
2437 		b_intvl = (u16)wrole->bcn_cmn.bcn_interval;
2438 	else
2439 #endif
2440 		b_intvl = sta->asoc_cap.bcn_interval;
2441 	if (0 == b_intvl) {
2442 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "phl_calc_offset_from_tbtt(): Fail, b_intvl ==0, wrole->id(%d), type(%d)\n",
2443 			wrole->id, wrole->type);
2444 		return false;
2445 	}
2446 	mod = (u32)_os_division64(_os_modular64(cur_t, b_intvl * TU), TU);
2447 	if (mod < b_ofst) {
2448 		*ofst = (u16)(mod + (b_intvl - b_ofst));
2449 	} else {
2450 		*ofst = (u16)(mod - b_ofst);
2451 	}
2452 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "phl_calc_offset_from_tbtt(): wrole->id(%d), ofst(%d), cur_t: 0x%08x %08x modular(%d, TU), Bcn offset: conf_lvl(%d), offset(%d)\n",
2453 		wrole->id, *ofst, (u32)(cur_t >> 32), (u32)cur_t, mod,
2454 		b_ofst_i->conf_lvl, (u32)b_ofst);
2455 	return true;
2456 }
2457 
2458 /*
2459  * Synchronize TBTT of target role with TBTT of sourec role
2460  * Assume TBTT of target role is locate in Mod(Tgt Tsf) = 0
2461  * @sync_ofst: Offset between TBTT of target role and TBTT of sourec role. Unit: TU
2462  * @sync_now_once: Sync once time right now.
2463  * @*diff_t : output diff_tsf. Unit: TU
2464  */
rtw_phl_tbtt_sync(struct phl_info_t * phl,struct rtw_wifi_role_t * src_role,struct rtw_wifi_role_t * tgt_role,u16 sync_ofst,bool sync_now_once,u16 * diff_t)2465 enum rtw_phl_status rtw_phl_tbtt_sync(struct phl_info_t *phl,
2466 		struct rtw_wifi_role_t *src_role,
2467 		struct rtw_wifi_role_t *tgt_role,
2468 		u16 sync_ofst, bool sync_now_once, u16 *diff_t)
2469 {
2470 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2471 	u32 tsf_h = 0, tsf_l = 0;
2472 	u64 tsf = 0, tgt_tsf = 0, bcn_intvl = 0;
2473 	u16 ofst = 0;
2474 	u64 diff_tsf = 0;
2475 	enum hal_tsf_sync_act act = sync_now_once ? HAL_TSF_SYNC_NOW_ONCE :
2476 							HAL_TSF_EN_SYNC_AUTO;
2477 
2478 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_get_tsf(phl->hal,
2479 					src_role->hw_port, &tsf_h, &tsf_l)) {
2480 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "rtw_phl_tbtt_sync(): Get tsf fail, src_role->id(%d)\n",
2481 			src_role->id);
2482 		goto exit;
2483 	}
2484 	bcn_intvl = phl_role_get_bcn_intvl(phl, tgt_role);
2485 	if (bcn_intvl == 0) {
2486 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "rtw_phl_tbtt_sync(): bcn_intvl == 0, tgt_role->id(%d)\n",
2487 			tgt_role->id);
2488 		goto exit;
2489 	}
2490 	tsf = tsf_h;
2491 	tsf = tsf << 32;
2492 	tsf |= tsf_l;
2493 	/*calculate the value between current TSF and TBTT*/
2494 	phl_calc_offset_from_tbtt(phl, src_role, tsf, &ofst);
2495 	tgt_tsf = (tsf + sync_ofst * TU) - ofst * TU;
2496 	/*Find diff_tsf, let Mod((tgt_tsf + diff_tsf), bcn_intvl) = 0*/
2497 	diff_tsf = bcn_intvl * TU - _os_modular64(tgt_tsf, bcn_intvl * TU);
2498 	diff_tsf = _os_division64(diff_tsf, TU);
2499 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "rtw_phl_tbtt_sync(): diff_tsf(%d), sync_ofst(%d), ofst(%d)\n",
2500 		(u32)diff_tsf, sync_ofst, (u32)ofst);
2501 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_tsf_sync(phl->hal,
2502 					src_role->hw_port, tgt_role->hw_port,
2503 					src_role->hw_band, (s32)diff_tsf,
2504 					act)) {
2505 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "rtw_phl_tbtt_sync(): Sync tsf fail\n");
2506 		goto exit;
2507 	}
2508 	if (RTW_HAL_STATUS_SUCCESS == rtw_hal_get_tsf(phl->hal,
2509 					src_role->hw_port, &tsf_h, &tsf_l)) {
2510 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "rtw_phl_tbtt_sync(): tsf_src(0x%08x %08x)\n",
2511 			tsf_h, tsf_l);
2512 	}
2513 	if (RTW_HAL_STATUS_SUCCESS == rtw_hal_get_tsf(phl->hal,
2514 					tgt_role->hw_port, &tsf_h, &tsf_l)) {
2515 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "rtw_phl_tbtt_sync(): tsf_tgt(0x%08x %08x)\n",
2516 			tsf_h, tsf_l);
2517 	}
2518 	*diff_t = (u16)diff_tsf;
2519 	status = RTW_PHL_STATUS_SUCCESS;
2520 exit:
2521 	return status;
2522 
2523 }
2524 
phl_self_stainfo_chk(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta)2525 bool phl_self_stainfo_chk(struct phl_info_t *phl_info,
2526                           struct rtw_wifi_role_t *wrole,
2527                           struct rtw_phl_stainfo_t *sta)
2528 {
2529 	return _phl_self_stainfo_chk(phl_info, wrole, sta);
2530 }
2531