xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/phl_msg_hub.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 - 2020 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  * Author: vincent_fann@realtek.com
15  *
16  *****************************************************************************/
17 #include "phl_headers.h"
18 #define MODL_MASK_LEN (PHL_BK_MDL_END / 8)
19 #define MAX_MSG_NUM	(16)
20 
21 enum msg_hub_status {
22 	MSG_HUB_INIT = BIT0,
23 	MSG_HUB_STARTED = BIT1,
24 };
25 
26 enum msg_recver_status {
27 	MSG_RECVER_INIT = BIT0,
28 	MSG_RECVER_CLR_CTX = BIT1,
29 };
30 
31 struct phl_msg_receiver_ex {
32 	u8 status;
33 	u8 bitmap[ MODL_MASK_LEN ];
34 	struct phl_msg_receiver ctx;
35 };
36 
37 
38 struct phl_msg_ex {
39 	_os_list list;
40 	struct phl_msg ctx;
41 	struct msg_completion_routine completion;
42 };
43 /**
44  * phl_msg_hub - responsible for phl msg forwarding,
45  * @status: contain mgnt status flags, refer to enum msg_hub_status
46  * @msg_pool: msg extension pool
47  * @msg_notify_thread: thread fot forwarding msg
48  * @recver: msg receiver, refer to enum phl_msg_recver_layer
49  */
50 struct phl_msg_hub {
51 	u32 status;
52 		struct phl_msg_ex msg_pool[MAX_MSG_NUM];
53 		struct phl_queue  idle_msg_q;
54 		struct phl_queue  wait_msg_q;
55 		_os_sema msg_q_sema;
56 		_os_thread msg_notify_thread;
57 		/* for core & phl layer respectively */
58 		struct phl_msg_receiver_ex recver[MSG_RECV_MAX];
59 };
60 
_is_bitmap_empty(void * d,u8 * bitmap)61 inline static u8 _is_bitmap_empty(void* d, u8* bitmap){
62 	u8 empty[MODL_MASK_LEN] = {0};
63 	return (!_os_mem_cmp(d, bitmap, empty, MODL_MASK_LEN))?(true):(false);
64 }
65 
pop_front_idle_msg(struct phl_info_t * phl,struct phl_msg_ex ** msg)66 static u8 pop_front_idle_msg(struct phl_info_t* phl, struct phl_msg_ex** msg)
67 {
68 	void *d = phl_to_drvpriv(phl);
69 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
70 	_os_list* new_msg = NULL;
71 
72 	(*msg) = NULL;
73 	if(pq_pop(d, &hub->idle_msg_q, &new_msg, _first, _bh)) {
74 		(*msg) = (struct phl_msg_ex*)new_msg;
75 		_os_mem_set(d, &((*msg)->ctx), 0, sizeof(struct phl_msg));
76 		(*msg)->completion.completion = NULL;
77 		(*msg)->completion.priv = NULL;
78 		return true;
79 	}
80 	else
81 		return false;
82 }
83 
push_back_idle_msg(struct phl_info_t * phl,struct phl_msg_ex * ex)84 static void push_back_idle_msg(struct phl_info_t* phl, struct phl_msg_ex* ex)
85 {
86 	void *d = phl_to_drvpriv(phl);
87 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
88 
89 	if(ex->completion.completion)
90 		ex->completion.completion(ex->completion.priv, &(ex->ctx));
91 	pq_push(d, &hub->idle_msg_q, &ex->list, _tail, _bh);
92 }
93 
pop_front_wait_msg(struct phl_info_t * phl,struct phl_msg_ex ** msg)94 static u8 pop_front_wait_msg(struct phl_info_t* phl, struct phl_msg_ex** msg)
95 {
96 	void *d = phl_to_drvpriv(phl);
97 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
98 	_os_list* new_msg = NULL;
99 
100 	(*msg) = NULL;
101 	if(pq_pop(d, &hub->wait_msg_q, &new_msg, _first, _bh)) {
102 		(*msg) = (struct phl_msg_ex*)new_msg;
103 		return true;
104 	}
105 	else
106 		return false;
107 }
108 
push_back_wait_msg(struct phl_info_t * phl,struct phl_msg_ex * ex)109 static void push_back_wait_msg(struct phl_info_t* phl, struct phl_msg_ex* ex)
110 {
111 	void *d = phl_to_drvpriv(phl);
112 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
113 	pq_push(d, &hub->wait_msg_q, &ex->list, _tail, _bh);
114 	_os_sema_up(d, &(hub->msg_q_sema));
115 }
116 
msg_forward(struct phl_info_t * phl,struct phl_msg_ex * ex)117 void msg_forward(struct phl_info_t* phl, struct phl_msg_ex* ex)
118 {
119 	void *d = phl_to_drvpriv(phl);
120 	u8 i = 0;
121 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
122 	struct phl_msg_receiver_ex* recver = NULL;
123 	u8 module_id = MSG_MDL_ID_FIELD(ex->ctx.msg_id);
124 
125 	if (!TEST_STATUS_FLAG(hub->status, MSG_HUB_STARTED)) {
126 		PHL_INFO("%s, msg hub not working\n",__FUNCTION__);
127 		return;
128 	}
129 	for(i = 0; i < MSG_RECV_MAX; i++) {
130 		recver = &(hub->recver[i]);
131 		if(!TEST_STATUS_FLAG(recver->status, MSG_RECVER_INIT)) {
132 			if(TEST_STATUS_FLAG(recver->status, MSG_RECVER_CLR_CTX))
133 				_os_mem_set(d, recver, 0, sizeof(struct phl_msg_receiver_ex));
134 			continue;
135 		}
136 		if(_chk_bitmap_bit(recver->bitmap, module_id)) {
137 			PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s notify %d layer\n",
138 				  __FUNCTION__, i);
139 			recver->ctx.incoming_evt_notify(recver->ctx.priv,
140 							&(ex->ctx));
141 			PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s notify %d layer\n",
142 				  __FUNCTION__, i);
143 		}
144 	}
145 
146 }
147 
msg_thread_hdl(void * param)148 int msg_thread_hdl(void* param)
149 {
150 	struct phl_info_t* phl = (struct phl_info_t *)param;
151 	void *d = phl_to_drvpriv(phl);
152 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
153 	struct phl_msg_ex* ex = NULL;
154 
155 	PHL_INFO("%s enter\n",__FUNCTION__);
156 	while(!_os_thread_check_stop(d, &(hub->msg_notify_thread))) {
157 
158 		_os_sema_down(d, &hub->msg_q_sema);
159 
160 		if(_os_thread_check_stop(d, &(hub->msg_notify_thread)))
161 			break;
162 
163 		while(pop_front_wait_msg(phl, &ex)){
164 			msg_forward(phl, ex);
165 			push_back_idle_msg(phl, ex);
166 		}
167 	}
168 	while (hub->idle_msg_q.cnt != MAX_MSG_NUM) {
169 		while(pop_front_wait_msg(phl, &ex))
170 			push_back_idle_msg(phl, ex);
171 	}
172 	_os_thread_wait_stop(d, &(hub->msg_notify_thread));
173 	PHL_INFO("%s down\n",__FUNCTION__);
174 	return 0;
175 }
176 
177 
phl_msg_hub_init(struct phl_info_t * phl)178 enum rtw_phl_status phl_msg_hub_init(struct phl_info_t* phl)
179 {
180 	struct phl_msg_hub* hub = NULL;
181 	void *d = phl_to_drvpriv(phl);
182 
183 
184 	if(phl->msg_hub != NULL)
185 		return RTW_PHL_STATUS_FAILURE;
186 
187 	hub = (struct phl_msg_hub *)_os_mem_alloc(d,
188 					sizeof(struct phl_msg_hub));
189 	if(hub == NULL) {
190 		PHL_ERR("%s, alloc fail\n",__FUNCTION__);
191 		return RTW_PHL_STATUS_RESOURCE;
192 	}
193 	phl->msg_hub = hub;
194 	_os_sema_init(d, &(hub->msg_q_sema), 0);
195 	pq_init(d, &(hub->idle_msg_q));
196 	pq_init(d, &(hub->wait_msg_q));
197 	SET_STATUS_FLAG(hub->status, MSG_HUB_INIT);
198 	PHL_INFO("%s\n",__FUNCTION__);
199 	return RTW_PHL_STATUS_SUCCESS;
200 }
201 
phl_msg_hub_deinit(struct phl_info_t * phl)202 enum rtw_phl_status phl_msg_hub_deinit(struct phl_info_t* phl)
203 {
204 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
205 	void *d = phl_to_drvpriv(phl);
206 
207 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_INIT))
208 		return RTW_PHL_STATUS_FAILURE;
209 	CLEAR_STATUS_FLAG(hub->status, MSG_HUB_INIT);
210 	phl_msg_hub_stop(phl);
211 	pq_deinit(d, &(hub->idle_msg_q));
212 	pq_deinit(d, &(hub->wait_msg_q));
213 	_os_sema_free(d, &(hub->msg_q_sema));
214 	_os_mem_free(d, hub, sizeof(struct phl_msg_hub));
215 	PHL_INFO("%s\n",__FUNCTION__);
216 	return RTW_PHL_STATUS_SUCCESS;
217 }
218 
phl_msg_hub_start(struct phl_info_t * phl)219 enum rtw_phl_status phl_msg_hub_start(struct phl_info_t* phl)
220 {
221 	u8 i = 0;
222 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
223 	void *d = phl_to_drvpriv(phl);
224 
225 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_INIT)||
226 		TEST_STATUS_FLAG(hub->status, MSG_HUB_STARTED))
227 		return RTW_PHL_STATUS_FAILURE;
228 
229 	_os_mem_set(d, hub->msg_pool, 0,
230 			sizeof(struct phl_msg_ex) * MAX_MSG_NUM );
231 	pq_reset(d, &(hub->idle_msg_q), _bh);
232 	pq_reset(d, &(hub->wait_msg_q), _bh);
233 	for(i = 0; i < MAX_MSG_NUM; i++) {
234 		pq_push(d, &hub->idle_msg_q, &hub->msg_pool[i].list, _tail, _bh);
235 	}
236 	_os_thread_init(d, &(hub->msg_notify_thread), msg_thread_hdl, phl,
237 						"msg_notify_thread");
238 	_os_thread_schedule(d, &(hub->msg_notify_thread));
239 	SET_STATUS_FLAG(hub->status, MSG_HUB_STARTED);
240 	PHL_INFO("%s\n",__FUNCTION__);
241 	return RTW_PHL_STATUS_SUCCESS;
242 }
243 
phl_msg_hub_stop(struct phl_info_t * phl)244 enum rtw_phl_status phl_msg_hub_stop(struct phl_info_t* phl)
245 {
246 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
247 	void *d = phl_to_drvpriv(phl);
248 
249 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_STARTED))
250 		return RTW_PHL_STATUS_FAILURE;
251 
252 	CLEAR_STATUS_FLAG(hub->status, MSG_HUB_STARTED);
253 	_os_thread_stop(d, &(hub->msg_notify_thread));
254 	_os_sema_up(d, &(hub->msg_q_sema));
255 	_os_thread_deinit(d, &(hub->msg_notify_thread));
256 	pq_reset(d, &(hub->idle_msg_q), _bh);
257 	pq_reset(d, &(hub->wait_msg_q), _bh);
258 
259 	PHL_INFO("%s\n",__FUNCTION__);
260 	return RTW_PHL_STATUS_SUCCESS;
261 }
262 
phl_msg_hub_send(struct phl_info_t * phl,struct phl_msg_attribute * attr,struct phl_msg * msg)263 enum rtw_phl_status phl_msg_hub_send(struct phl_info_t* phl,
264 						struct phl_msg_attribute* attr,	struct phl_msg* msg)
265 {
266 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl->msg_hub;
267 	void *d = phl_to_drvpriv(phl);
268 	struct phl_msg_ex* ex = NULL;
269 
270 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_STARTED) || msg == NULL)
271 		return RTW_PHL_STATUS_FAILURE;
272 
273 	if(!pop_front_idle_msg(phl, &ex)) {
274 		PHL_ERR(" %s idle msg empty\n",__FUNCTION__);
275 		return RTW_PHL_STATUS_RESOURCE;
276 	}
277 	_os_mem_cpy(d, &(ex->ctx), msg, sizeof(struct phl_msg));
278 	if(attr && attr->completion.completion) {
279 		ex->completion.completion = attr->completion.completion;
280 		ex->completion.priv = attr->completion.priv;
281 	}
282 
283 	push_back_wait_msg(phl, ex);
284 
285 	PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s, msg_id:0x%x enqueue\n",
286 		  __FUNCTION__, msg->msg_id);
287 	return RTW_PHL_STATUS_SUCCESS;
288 }
289 
290 
phl_msg_hub_register_recver(void * phl,struct phl_msg_receiver * ctx,enum phl_msg_recver_layer layer)291 enum rtw_phl_status phl_msg_hub_register_recver(void* phl,
292 		struct phl_msg_receiver* ctx, enum phl_msg_recver_layer layer)
293 {
294 	struct phl_info_t* phl_info = (struct phl_info_t*)phl;
295 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl_info->msg_hub;
296 	void *d = phl_to_drvpriv(phl_info);
297 	struct phl_msg_receiver_ex* recver = NULL;
298 
299 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_INIT) ||
300 		layer >= MSG_RECV_MAX ||
301 		ctx == NULL)
302 		return RTW_PHL_STATUS_FAILURE;
303 
304 	recver =  &(hub->recver[layer]);
305 	if(TEST_STATUS_FLAG(recver->status, MSG_RECVER_INIT)) {
306 		PHL_ERR("%s, layer registered\n",__FUNCTION__);
307 		return RTW_PHL_STATUS_FAILURE;
308 	}
309 
310 	_os_mem_cpy(d, &(recver->ctx), ctx, sizeof(struct phl_msg_receiver));
311 	_os_mem_set(d, &(recver->bitmap), 0, MODL_MASK_LEN);
312 	SET_STATUS_FLAG(recver->status, MSG_RECVER_INIT);
313 	PHL_INFO("%s\n",__FUNCTION__);
314 	return RTW_PHL_STATUS_SUCCESS;
315 }
316 
phl_msg_hub_update_recver_mask(void * phl,enum phl_msg_recver_layer layer,u8 * mdl_id,u32 len,u8 clr)317 enum rtw_phl_status phl_msg_hub_update_recver_mask(void* phl,
318 		enum phl_msg_recver_layer layer, u8* mdl_id, u32 len, u8 clr)
319 {
320 	struct phl_info_t* phl_info = (struct phl_info_t*)phl;
321 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl_info->msg_hub;
322 	struct phl_msg_receiver_ex* recver = NULL;
323 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_INIT) ||
324 		layer >= MSG_RECV_MAX)
325 		return RTW_PHL_STATUS_FAILURE;
326 
327 	recver =  &(hub->recver[layer]);
328 	if(!TEST_STATUS_FLAG(recver->status, MSG_RECVER_INIT)) {
329 		PHL_ERR("%s, layer not registered\n",__FUNCTION__);
330 		return RTW_PHL_STATUS_FAILURE;
331 	}
332 
333 	if(clr == true)
334 		_clr_bitmap_bit(recver->bitmap, mdl_id, len);
335 	else
336 		_add_bitmap_bit(recver->bitmap, mdl_id, len);
337 	PHL_INFO(" %s\n",__FUNCTION__);
338 	return RTW_PHL_STATUS_SUCCESS;
339 }
340 
phl_msg_hub_deregister_recver(void * phl,enum phl_msg_recver_layer layer)341 enum rtw_phl_status phl_msg_hub_deregister_recver(void* phl,
342 					enum phl_msg_recver_layer layer)
343 {
344 	struct phl_info_t* phl_info = (struct phl_info_t*)phl;
345 	struct phl_msg_hub* hub = (struct phl_msg_hub*)phl_info->msg_hub;
346 	struct phl_msg_receiver_ex* recver = NULL;
347 	if(!TEST_STATUS_FLAG(hub->status, MSG_HUB_INIT) ||
348 		layer >= MSG_RECV_MAX)
349 		return RTW_PHL_STATUS_FAILURE;
350 
351 	recver =  &(hub->recver[layer]);
352 	if(!TEST_STATUS_FLAG(recver->status, MSG_RECVER_INIT)) {
353 		PHL_ERR("%s, layer not registered\n",__FUNCTION__);
354 		return RTW_PHL_STATUS_FAILURE;
355 	}
356 	CLEAR_STATUS_FLAG(recver->status, MSG_RECVER_INIT);
357 	SET_STATUS_FLAG(recver->status, MSG_RECVER_CLR_CTX);
358 	PHL_INFO("%s\n",__FUNCTION__);
359 	return RTW_PHL_STATUS_SUCCESS;
360 }
361 
362 /* handling msg hub event with PHL_MDL_PHY_MGNT as module id */
phl_msg_hub_phy_mgnt_evt_hdlr(struct phl_info_t * phl,u16 evt_id)363 void phl_msg_hub_phy_mgnt_evt_hdlr(struct phl_info_t* phl, u16 evt_id)
364 {
365 	PHL_INFO("%s : evt_id %d.\n", __func__, evt_id);
366 
367 	switch (evt_id) {
368 	case MSG_EVT_FWDL_OK:
369 		break;
370 	case MSG_EVT_FWDL_FAIL:
371 		break;
372 	case MSG_EVT_DUMP_PLE_BUFFER:
373 		rtw_phl_ser_dump_ple_buffer(phl);
374 		break;
375 	default:
376 		break;
377 	}
378 }
379 
phl_msg_hub_rx_evt_hdlr(struct phl_info_t * phl,u16 evt_id,u8 * buf,u32 len)380 void phl_msg_hub_rx_evt_hdlr(struct phl_info_t* phl, u16 evt_id,
381 		u8 *buf, u32 len)
382 {
383 	PHL_DBG("%s : evt_id %d.\n", __func__, evt_id);
384 
385 	switch (evt_id) {
386 	case HAL_C2H_EV_BB_MUGRP_DOWN:
387 		break;
388 	case MSG_EVT_TSF32_TOG:
389 		PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_msg_hub_rx_evt_hdlr():toggle happen!!\n");
390 		phl_p2pps_tsf32_tog_handler(phl);
391 		break;
392 	case MSG_EVT_DBG_RX_DUMP:
393 		phl_rx_dbg_dump(phl, HW_PHY_0);
394 		break;
395 	default:
396 		break;
397 	}
398 }