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