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_CUSTOMIZE_FEATURE_C_
16 #include "../phl_headers.h"
17
18 #ifdef CONFIG_PHL_CUSTOM_FEATURE_FB
19 #include "phl_custom_fb.h"
20
21 #define LLC_HDR_LENGTH 6
22 #define SNAP_HDR_LENGTH 2
23
24 enum phl_mdl_ret_code
_is_fb_mode_valid(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg,u32 size)25 _is_fb_mode_valid(void* custom_ctx,
26 struct _custom_facebook_ctx* fb_ctx,
27 struct phl_msg* msg, u32 size)
28 {
29 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
30 enum phl_mdl_ret_code ret = MDL_RET_SUCCESS;
31 if (!fb_ctx->init.enable || cmd->len < size || fb_ctx->init.wifi_role == NULL) {
32 PHL_INFO(" %s, evt_id(%d) not accepted\n",
33 __FUNCTION__,
34 MSG_EVT_ID_FIELD(msg->msg_id));
35 ret = MDL_RET_FAIL;
36 return ret;
37 }
38 //check chanctx if wifi_role exists
39 if (fb_ctx->init.wifi_role->chanctx == NULL) {
40 PHL_INFO(" %s, wifi_role->chanctx is NULL\n", __FUNCTION__);
41 fb_ctx->init.wifi_role = NULL;
42 ret = MDL_RET_FAIL;
43 } else {
44 ret = MDL_RET_SUCCESS;
45 }
46 return ret;
47 }
48
49 enum phl_mdl_ret_code
_custom_fb_feature_enable(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)50 _custom_fb_feature_enable(void* custom_ctx,
51 struct _custom_facebook_ctx* fb_ctx,
52 struct phl_msg* msg)
53 {
54 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
55
56 if (cmd->len < sizeof(u32))
57 return MDL_RET_FAIL;
58
59 fb_ctx->init.enable = *(u32*)(cmd + 1);
60 fb_ctx->init.test_mode = 0;
61 phl_custom_prepare_evt_rpt(custom_ctx,
62 cmd->evt_id,
63 cmd->customer_id,
64 (u8*)&(fb_ctx->init.enable),
65 sizeof(u32));
66
67 return MDL_RET_SUCCESS;
68 }
69
70 enum phl_mdl_ret_code
_custom_fb_feature_query(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)71 _custom_fb_feature_query(void* custom_ctx,
72 struct _custom_facebook_ctx* fb_ctx,
73 struct phl_msg* msg)
74 {
75 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
76 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
77 if (cmd->len < sizeof(u32))
78 return ret;
79 PHL_INFO("%s, fb query feature enable(%d)\n",
80 __FUNCTION__,
81 fb_ctx->init.enable);
82 phl_custom_prepare_evt_rpt(custom_ctx,
83 cmd->evt_id,
84 cmd->customer_id,
85 (u8*)&(fb_ctx->init.enable),
86 sizeof(u32));
87 ret = MDL_RET_SUCCESS;
88 return ret;
89 }
90
91 enum phl_mdl_ret_code
_custom_fb_testmode_param(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)92 _custom_fb_testmode_param(void* custom_ctx,
93 struct _custom_facebook_ctx* fb_ctx,
94 struct phl_msg* msg)
95 {
96 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
97 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
98
99 if (cmd->len < sizeof(u32))
100 return ret;
101 fb_ctx->init.test_mode = *(u32*)(cmd + 1);
102 PHL_INFO("%s, test mode(0x%x)\n", __FUNCTION__,
103 fb_ctx->init.test_mode);
104 phl_custom_prepare_evt_rpt(custom_ctx,
105 cmd->evt_id,
106 cmd->customer_id,
107 (u8*)&ret,
108 sizeof(u8));
109
110 ret = MDL_RET_SUCCESS;
111 return ret;
112 }
113
114 enum phl_mdl_ret_code
_custom_fb_set_wifi_role(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)115 _custom_fb_set_wifi_role(void* custom_ctx,
116 struct _custom_facebook_ctx* fb_ctx,
117 struct phl_msg* msg)
118 {
119 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
120 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
121 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
122 u32 size = MAC_ADDRESS_LENGTH;
123 u8* val = (u8*)(cmd + 1);
124
125 if (cmd->len < MAC_ADDRESS_LENGTH)
126 return ret;
127 if (!(fb_ctx->init.test_mode & FB_TEST_MODE_USE_STA_MAC))
128 *val |= (BIT1 | BIT7);
129 PHL_INFO("val - MAC-Addr:%02x-%02x-%02x-%02x-%02x-%02x\n",
130 *val,*(val + 1),*(val + 2),
131 *(val + 3), *(val + 4),*(val + 5));
132 fb_ctx->init.wifi_role = phl_get_wrole_by_addr(phl, val);
133
134 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
135 phl_custom_prepare_evt_rpt(custom_ctx,
136 cmd->evt_id,
137 cmd->customer_id,
138 (u8*)&ret,
139 sizeof(u8));
140
141 return ret;
142 }
143
144 enum phl_mdl_ret_code
_custom_fb_ampdu_cfg(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)145 _custom_fb_ampdu_cfg(void* custom_ctx,
146 struct _custom_facebook_ctx* fb_ctx,
147 struct phl_msg* msg)
148 {
149 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
150 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
151 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
152 void *d = phl_to_drvpriv(phl);
153 struct rtw_phl_stainfo_t *phl_sta = NULL;
154 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
155 struct rtw_phl_custom_ampdu_cfg custom_fb_ampdu_cfg = {0};
156 u32 size = sizeof(struct rtw_phl_custom_ampdu_cfg);
157 u8* val = (u8*)(cmd + 1);
158
159 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
160 if (ret != MDL_RET_SUCCESS) {
161 goto exit;
162 }
163 phl_sta = rtw_phl_get_stainfo_self(phl, fb_ctx->init.wifi_role);
164 _os_mem_cpy(d, &custom_fb_ampdu_cfg, val, size);
165 hal_status = rtw_hal_custom_cfg_tx_ampdu(phl->hal,
166 fb_ctx->init.wifi_role,
167 &custom_fb_ampdu_cfg);
168 phl_sta->asoc_cap.num_ampdu = (u8)custom_fb_ampdu_cfg.max_agg_num;
169
170 PHL_INFO("%s, halsta(%d) ampdu dur(%d) num(%d)\n",
171 __FUNCTION__,
172 hal_status,
173 custom_fb_ampdu_cfg.max_agg_time_32us,
174 custom_fb_ampdu_cfg.max_agg_num);
175 if (hal_status != RTW_HAL_STATUS_SUCCESS)
176 ret = MDL_RET_FAIL;
177 exit:
178 phl_custom_prepare_evt_rpt(custom_ctx,
179 cmd->evt_id,
180 cmd->customer_id,
181 (u8*)&ret,
182 sizeof(u8));
183 return ret;
184 }
185
186 enum phl_mdl_ret_code
_custom_fb_ampdu_query(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)187 _custom_fb_ampdu_query(void* custom_ctx,
188 struct _custom_facebook_ctx* fb_ctx,
189 struct phl_msg* msg)
190 {
191 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
192 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
193 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
194 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
195 struct rtw_phl_custom_ampdu_cfg custom_fb_ampdu_cfg = {0};
196 u32 size = sizeof(struct rtw_phl_custom_ampdu_cfg);
197
198 /* 0xffffffff is querying failed for SDK*/
199 custom_fb_ampdu_cfg.max_agg_num = 0xffffffff;
200 custom_fb_ampdu_cfg.max_agg_time_32us = 0xffffffff;
201
202 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
203 if (ret != MDL_RET_SUCCESS) {
204 goto exit;
205 }
206 hal_status = rtw_hal_get_ampdu_cfg(phl->hal,
207 fb_ctx->init.wifi_role,
208 &custom_fb_ampdu_cfg);
209 if (hal_status != RTW_HAL_STATUS_SUCCESS)
210 ret = MDL_RET_FAIL;
211 PHL_INFO(" %s, ampdu dur(%d) time(%d)\n",
212 __FUNCTION__,
213 custom_fb_ampdu_cfg.max_agg_time_32us,
214 custom_fb_ampdu_cfg.max_agg_num);
215 exit:
216 phl_custom_prepare_evt_rpt(custom_ctx,
217 cmd->evt_id,
218 cmd->customer_id,
219 (u8*)&custom_fb_ampdu_cfg,
220 sizeof(struct rtw_phl_custom_ampdu_cfg));
221 return ret;
222 }
223
224 enum phl_mdl_ret_code
_custom_fb_pdthr_cfg(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)225 _custom_fb_pdthr_cfg(void* custom_ctx,
226 struct _custom_facebook_ctx* fb_ctx,
227 struct phl_msg* msg)
228 {
229 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
230 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
231 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
232 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
233 int pd_thr = 0xff;
234 u32 size = sizeof(int);
235
236 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
237 if (ret != MDL_RET_SUCCESS) {
238 goto exit;
239 }
240 pd_thr = *(int*)(cmd + 1);
241 PHL_INFO("%s, pd_thr(%d)\n", __FUNCTION__, pd_thr);
242 PHL_INFO("%s, bw(%d) band(%d)\n", __FUNCTION__,
243 fb_ctx->init.wifi_role->chanctx->chan_def.bw,
244 fb_ctx->init.wifi_role->hw_band);
245 hal_status = rtw_hal_set_pkt_detect_thold(phl->hal, (u32)pd_thr);
246 PHL_INFO("%s, hal_status(%d)\n", __FUNCTION__, hal_status);
247 if (hal_status != RTW_HAL_STATUS_SUCCESS)
248 ret = MDL_RET_FAIL;
249 exit:
250 phl_custom_prepare_evt_rpt(custom_ctx,
251 cmd->evt_id,
252 cmd->customer_id,
253 (u8*)&ret,
254 sizeof(u8));
255 return ret;
256 }
257
258 enum phl_mdl_ret_code
_custom_fb_pdthr_query(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)259 _custom_fb_pdthr_query(void* custom_ctx,
260 struct _custom_facebook_ctx* fb_ctx,
261 struct phl_msg* msg)
262 {
263 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
264 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
265 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
266 int pd_thr = 0xff;
267 u32 size = sizeof(int);
268
269 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
270 if (ret != MDL_RET_SUCCESS) {
271 goto exit;
272 }
273 /*confirm whether pd thr is enabling or not*/
274 pd_thr = rtw_hal_query_pkt_detect_thold(phl->hal,
275 true,
276 fb_ctx->init.wifi_role->hw_band);
277 if (pd_thr == 0) {
278 PHL_INFO("%s, disable! pd_thr(%d)\n", __FUNCTION__, pd_thr);
279 } else {
280 pd_thr = rtw_hal_query_pkt_detect_thold(phl->hal,
281 false,
282 fb_ctx->init.wifi_role->hw_band);
283 PHL_INFO("%s, pd_thr(%d)\n", __FUNCTION__, pd_thr);
284 }
285 exit:
286 phl_custom_prepare_evt_rpt(custom_ctx,
287 cmd->evt_id,
288 cmd->customer_id,
289 (u8*)&pd_thr,
290 sizeof(int));
291 return ret;
292 }
293
294 enum phl_mdl_ret_code
_custom_fb_pop_cfg(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)295 _custom_fb_pop_cfg(void* custom_ctx,
296 struct _custom_facebook_ctx* fb_ctx,
297 struct phl_msg* msg)
298 {
299 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
300 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
301 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
302 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
303 u32 size = sizeof(u32);
304 u32 pop_enable = 0xff;
305
306 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
307 if (ret != MDL_RET_SUCCESS) {
308 goto exit;
309 }
310 pop_enable = *(u32*)(cmd + 1);
311 PHL_INFO("%s, pop_enable(%d)\n", __FUNCTION__, pop_enable);
312 if (pop_enable != 0xff) {
313 hal_status = rtw_hal_set_pop_en(phl->hal,
314 (bool)pop_enable,
315 fb_ctx->init.wifi_role->hw_band);
316 if (hal_status != RTW_HAL_STATUS_SUCCESS)
317 ret = MDL_RET_FAIL;
318 }
319 exit:
320 phl_custom_prepare_evt_rpt(custom_ctx,
321 cmd->evt_id,
322 cmd->customer_id,
323 (u8*)&ret,
324 sizeof(u8));
325 return ret;
326 }
327
328 enum phl_mdl_ret_code
_custom_fb_pop_query(void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)329 _custom_fb_pop_query(void* custom_ctx,
330 struct _custom_facebook_ctx* fb_ctx,
331 struct phl_msg* msg)
332 {
333 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
334 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
335 struct rtw_custom_decrpt *cmd = (struct rtw_custom_decrpt *)(msg->inbuf);
336 u32 size = sizeof(u32);
337 u32 pop_enable = 0xff;
338
339 ret = _is_fb_mode_valid(custom_ctx, fb_ctx, msg, size);
340 if (ret != MDL_RET_SUCCESS){
341 goto exit;
342 }
343
344 pop_enable = rtw_hal_query_pop_en(phl->hal, fb_ctx->init.wifi_role->hw_band);
345 PHL_INFO("%s, pop_en(%d)\n", __FUNCTION__, pop_enable);
346 exit:
347 phl_custom_prepare_evt_rpt(custom_ctx,
348 cmd->evt_id,
349 cmd->customer_id,
350 (u8*)&pop_enable,
351 sizeof(u32));
352 return ret;
353 }
354
355 enum phl_mdl_ret_code
phl_custom_hdl_fb_evt(void * dispr,void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)356 phl_custom_hdl_fb_evt(void* dispr,
357 void* custom_ctx,
358 struct _custom_facebook_ctx* fb_ctx,
359 struct phl_msg* msg)
360 {
361 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
362 u8 prephase = (IS_MSG_IN_PRE_PHASE(msg->msg_id)) ? (true) : (false);
363
364 if (prephase == true)
365 return MDL_RET_SUCCESS;
366
367 switch (MSG_EVT_ID_FIELD(msg->msg_id)) {
368 case MSG_EVT_CUSTOME_FEATURE_ENABLE:
369 ret = _custom_fb_feature_enable(custom_ctx, fb_ctx, msg);
370 break;
371 case MSG_EVT_CUSTOME_FEATURE_QUERY:
372 ret = _custom_fb_feature_query(custom_ctx, fb_ctx, msg);
373 break;
374 case MSG_EVT_CUSTOME_TESTMODE_PARAM:
375 ret = _custom_fb_testmode_param(custom_ctx, fb_ctx, msg);
376 break;
377 case MSG_EVT_CUSTOME_SET_WIFI_ROLE:
378 ret = _custom_fb_set_wifi_role(custom_ctx, fb_ctx, msg);
379 break;
380 case MSG_EVT_AMPDU_CFG:
381 ret = _custom_fb_ampdu_cfg(custom_ctx, fb_ctx, msg);
382 break;
383 case MSG_EVT_AMPDU_QUERY:
384 ret = _custom_fb_ampdu_query(custom_ctx, fb_ctx, msg);
385 break;
386 case MSG_EVT_PDTHR_CFG:
387 ret = _custom_fb_pdthr_cfg(custom_ctx, fb_ctx, msg);
388 break;
389 case MSG_EVT_PDTHR_QUERY:
390 ret = _custom_fb_pdthr_query(custom_ctx, fb_ctx, msg);
391 break;
392 case MSG_EVT_POP_CFG:
393 ret = _custom_fb_pop_cfg(custom_ctx, fb_ctx, msg);
394 break;
395 case MSG_EVT_POP_QUERY:
396 ret = _custom_fb_pop_query(custom_ctx, fb_ctx, msg);
397 break;
398 default:
399 ret = MDL_RET_SUCCESS;
400 break;
401 }
402 PHL_INFO("%s, evt(%d), ret(%d)\n", __FUNCTION__,
403 MSG_EVT_ID_FIELD(msg->msg_id),
404 ret);
405 return ret;
406 }
407 enum phl_mdl_ret_code
phl_custom_hdl_fb_fail_evt(void * dispr,void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_msg * msg)408 phl_custom_hdl_fb_fail_evt(void* dispr,
409 void* custom_ctx,
410 struct _custom_facebook_ctx* fb_ctx,
411 struct phl_msg* msg)
412 {
413 return MDL_RET_IGNORE;
414 }
415
416 enum phl_mdl_ret_code
phl_custom_fb_update_opt_ie(void * dispr,void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_module_op_info * info)417 phl_custom_fb_update_opt_ie(void* dispr,
418 void* custom_ctx,
419 struct _custom_facebook_ctx* fb_ctx,
420 struct phl_module_op_info* info)
421 {
422 enum phl_mdl_ret_code status = MDL_RET_SUCCESS;
423 struct phl_info_t *phl = phl_custom_get_phl_info(custom_ctx);
424 void *d = phl_to_drvpriv(phl);
425
426 if (info->outlen == 0)
427 return MDL_RET_FAIL;
428 _os_mem_cpy(d, info->outbuf, &fb_ctx->bcn_param, info->outlen);
429
430 return status;
431 }
432
433 enum phl_mdl_ret_code
phl_custom_fb_set_role_cap(void * dispr,void * custom_ctx,struct _custom_facebook_ctx * fb_ctx,struct phl_module_op_info * info)434 phl_custom_fb_set_role_cap(void* dispr,
435 void* custom_ctx,
436 struct _custom_facebook_ctx* fb_ctx,
437 struct phl_module_op_info* info)
438 {
439 enum phl_mdl_ret_code status = MDL_RET_SUCCESS;
440
441 FUNCIN();
442
443 fb_ctx->bcn_param.enable = true;
444 fb_ctx->bcn_param.cus_wmode = *(u8*)info->inbuf;
445
446 FUNCOUT();
447
448 return status;
449 }
450
451 enum rtw_phl_status
phl_custom_fb_init_role_cap(struct phl_info_t * phl_info,u8 hw_band,struct role_cap_t * role_cap)452 phl_custom_fb_init_role_cap(struct phl_info_t *phl_info,
453 u8 hw_band,
454 struct role_cap_t *role_cap)
455 {
456 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
457 struct phl_module_op_info op_info = {0};
458 struct _facebook_bcn_param bcn_param = {0};
459
460 op_info.op_code = BK_MODL_OP_CUS_UPDATE_ROLE_CAP;
461 op_info.outbuf = (u8*)&bcn_param;
462 op_info.outlen = sizeof(struct _facebook_bcn_param);
463 if (phl_disp_eng_query_bk_module_info(phl_info,
464 hw_band,
465 PHL_MDL_CUSTOM,
466 &op_info) == MDL_RET_SUCCESS) {
467 if (bcn_param.enable == true) {
468 role_cap->wmode &= bcn_param.cus_wmode;
469 }
470 PHL_INFO("%s, wmode(%d) cus_wmode(%d) enable(%d)\n", __FUNCTION__,
471 role_cap->wmode,
472 bcn_param.cus_wmode,
473 bcn_param.enable);
474 } else {
475 status = RTW_PHL_STATUS_FAILURE;
476 }
477 return status;
478 }
479 #endif
480