1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2016 Realtek Corporation.
5 *
6 * Contact Information:
7 * wlanfae <wlanfae@realtek.com>
8 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9 * Hsinchu 300, Taiwan.
10 *
11 * Larry Finger <Larry.Finger@lwfinger.net>
12 *
13 *****************************************************************************/
14
15 #include "halmac_api.h"
16 #include "rtl_halmac.h"
17 #include <linux/module.h>
18 #include <linux/vmalloc.h>
19
20 #define DEFAULT_INDICATOR_TIMELMT msecs_to_jiffies(1000) /* ms */
21 #define FIRMWARE_MAX_SIZE HALMAC_FW_SIZE_MAX_88XX
22
23 static struct rtl_halmac_ops rtl_halmac_operation = {
24 .halmac_init_adapter = rtl_halmac_init_adapter,
25 .halmac_deinit_adapter = rtl_halmac_deinit_adapter,
26 .halmac_init_hal = rtl_halmac_init_hal,
27 .halmac_deinit_hal = rtl_halmac_deinit_hal,
28 .halmac_poweron = rtl_halmac_poweron,
29 .halmac_poweroff = rtl_halmac_poweroff,
30
31 .halmac_phy_power_switch = rtl_halmac_phy_power_switch,
32 .halmac_set_mac_address = rtl_halmac_set_mac_address,
33 .halmac_set_bssid = rtl_halmac_set_bssid,
34
35 .halmac_get_physical_efuse_size = rtl_halmac_get_physical_efuse_size,
36 .halmac_read_physical_efuse_map = rtl_halmac_read_physical_efuse_map,
37 .halmac_get_logical_efuse_size = rtl_halmac_get_logical_efuse_size,
38 .halmac_read_logical_efuse_map = rtl_halmac_read_logical_efuse_map,
39
40 .halmac_set_bandwidth = rtl_halmac_set_bandwidth,
41
42 .halmac_c2h_handle = rtl_halmac_c2h_handle,
43
44 .halmac_chk_txdesc = rtl_halmac_chk_txdesc,
45 };
46
rtl_halmac_get_ops_pointer(void)47 struct rtl_halmac_ops *rtl_halmac_get_ops_pointer(void)
48 {
49 return &rtl_halmac_operation;
50 }
51 EXPORT_SYMBOL(rtl_halmac_get_ops_pointer);
52
53 /*
54 * Driver API for HALMAC operations
55 */
56
_halmac_reg_read_8(void * p,u32 offset)57 static u8 _halmac_reg_read_8(void *p, u32 offset)
58 {
59 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
60
61 return rtl_read_byte(rtlpriv, offset);
62 }
63
_halmac_reg_read_16(void * p,u32 offset)64 static u16 _halmac_reg_read_16(void *p, u32 offset)
65 {
66 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
67
68 return rtl_read_word(rtlpriv, offset);
69 }
70
_halmac_reg_read_32(void * p,u32 offset)71 static u32 _halmac_reg_read_32(void *p, u32 offset)
72 {
73 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
74
75 return rtl_read_dword(rtlpriv, offset);
76 }
77
_halmac_reg_write_8(void * p,u32 offset,u8 val)78 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
79 {
80 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
81
82 rtl_write_byte(rtlpriv, offset, val);
83 }
84
_halmac_reg_write_16(void * p,u32 offset,u16 val)85 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
86 {
87 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
88
89 rtl_write_word(rtlpriv, offset, val);
90 }
91
_halmac_reg_write_32(void * p,u32 offset,u32 val)92 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
93 {
94 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
95
96 rtl_write_dword(rtlpriv, offset, val);
97 }
98
_halmac_write_data_rsvd_page(void * p,u8 * buf,u32 size)99 static bool _halmac_write_data_rsvd_page(void *p, u8 *buf, u32 size)
100 {
101 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
102
103 if (rtlpriv->cfg->ops->halmac_cb_write_data_rsvd_page &&
104 rtlpriv->cfg->ops->halmac_cb_write_data_rsvd_page(rtlpriv, buf,
105 size))
106 return true;
107
108 return false;
109 }
110
_halmac_write_data_h2c(void * p,u8 * buf,u32 size)111 static bool _halmac_write_data_h2c(void *p, u8 *buf, u32 size)
112 {
113 struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
114
115 if (rtlpriv->cfg->ops->halmac_cb_write_data_h2c &&
116 rtlpriv->cfg->ops->halmac_cb_write_data_h2c(rtlpriv, buf, size))
117 return true;
118
119 return false;
120 }
121
122 static const char *const RTL_HALMAC_FEATURE_NAME[] = {
123 "HALMAC_FEATURE_CFG_PARA",
124 "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
125 "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
126 "HALMAC_FEATURE_UPDATE_PACKET",
127 "HALMAC_FEATURE_UPDATE_DATAPACK",
128 "HALMAC_FEATURE_RUN_DATAPACK",
129 "HALMAC_FEATURE_CHANNEL_SWITCH",
130 "HALMAC_FEATURE_IQK",
131 "HALMAC_FEATURE_POWER_TRACKING",
132 "HALMAC_FEATURE_PSD",
133 "HALMAC_FEATURE_ALL"};
134
is_valid_id_status(struct rtl_priv * rtlpriv,enum halmac_feature_id id,enum halmac_cmd_process_status status)135 static inline bool is_valid_id_status(struct rtl_priv *rtlpriv,
136 enum halmac_feature_id id,
137 enum halmac_cmd_process_status status)
138 {
139 switch (id) {
140 case HALMAC_FEATURE_CFG_PARA:
141 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
142 RTL_HALMAC_FEATURE_NAME[id]);
143 break;
144 case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
145 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
146 RTL_HALMAC_FEATURE_NAME[id]);
147 if (status != HALMAC_CMD_PROCESS_DONE) {
148 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
149 "%s: <WARN> id(%d) unspecified status(%d)!\n",
150 __func__, id, status);
151 }
152 break;
153 case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
154 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
155 RTL_HALMAC_FEATURE_NAME[id]);
156 if (status != HALMAC_CMD_PROCESS_DONE) {
157 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
158 "%s: <WARN> id(%d) unspecified status(%d)!\n",
159 __func__, id, status);
160 }
161 break;
162 case HALMAC_FEATURE_UPDATE_PACKET:
163 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
164 RTL_HALMAC_FEATURE_NAME[id]);
165 break;
166 case HALMAC_FEATURE_UPDATE_DATAPACK:
167 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
168 RTL_HALMAC_FEATURE_NAME[id]);
169 break;
170 case HALMAC_FEATURE_RUN_DATAPACK:
171 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
172 RTL_HALMAC_FEATURE_NAME[id]);
173 break;
174 case HALMAC_FEATURE_CHANNEL_SWITCH:
175 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
176 RTL_HALMAC_FEATURE_NAME[id]);
177 break;
178 case HALMAC_FEATURE_IQK:
179 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
180 RTL_HALMAC_FEATURE_NAME[id]);
181 break;
182 case HALMAC_FEATURE_POWER_TRACKING:
183 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
184 RTL_HALMAC_FEATURE_NAME[id]);
185 break;
186 case HALMAC_FEATURE_PSD:
187 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
188 RTL_HALMAC_FEATURE_NAME[id]);
189 break;
190 case HALMAC_FEATURE_ALL:
191 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
192 RTL_HALMAC_FEATURE_NAME[id]);
193 break;
194 default:
195 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
196 "%s: unknown feature id(%d)\n", __func__, id);
197 return false;
198 }
199
200 return true;
201 }
202
init_halmac_event_with_waittime(struct rtl_priv * rtlpriv,enum halmac_feature_id id,u8 * buf,u32 size,u32 time)203 static int init_halmac_event_with_waittime(struct rtl_priv *rtlpriv,
204 enum halmac_feature_id id, u8 *buf,
205 u32 size, u32 time)
206 {
207 struct completion *comp;
208
209 if (!rtlpriv->halmac.indicator[id].comp) {
210 comp = kzalloc(sizeof(*comp), GFP_KERNEL);
211 if (!comp)
212 return -1;
213 } else {
214 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
215 "%s: <WARN> id(%d) sctx is not NULL!!\n", __func__,
216 id);
217 comp = rtlpriv->halmac.indicator[id].comp;
218 rtlpriv->halmac.indicator[id].comp = NULL;
219 }
220
221 init_completion(comp);
222 rtlpriv->halmac.indicator[id].wait_ms = time;
223
224 rtlpriv->halmac.indicator[id].buffer = buf;
225 rtlpriv->halmac.indicator[id].buf_size = size;
226 rtlpriv->halmac.indicator[id].ret_size = 0;
227 rtlpriv->halmac.indicator[id].status = 0;
228 /* fill sctx at least to sure other variables are all ready! */
229 rtlpriv->halmac.indicator[id].comp = comp;
230
231 return 0;
232 }
233
init_halmac_event(struct rtl_priv * rtlpriv,enum halmac_feature_id id,u8 * buf,u32 size)234 static inline int init_halmac_event(struct rtl_priv *rtlpriv,
235 enum halmac_feature_id id, u8 *buf,
236 u32 size)
237 {
238 return init_halmac_event_with_waittime(rtlpriv, id, buf, size,
239 DEFAULT_INDICATOR_TIMELMT);
240 }
241
free_halmac_event(struct rtl_priv * rtlpriv,enum halmac_feature_id id)242 static void free_halmac_event(struct rtl_priv *rtlpriv,
243 enum halmac_feature_id id)
244 {
245 struct completion *comp;
246
247 if (!rtlpriv->halmac.indicator[id].comp)
248 return;
249
250 comp = rtlpriv->halmac.indicator[id].comp;
251 rtlpriv->halmac.indicator[id].comp = NULL;
252 kfree(comp);
253 }
254
wait_halmac_event(struct rtl_priv * rtlpriv,enum halmac_feature_id id)255 static int wait_halmac_event(struct rtl_priv *rtlpriv,
256 enum halmac_feature_id id)
257 {
258 struct completion *comp;
259 int ret;
260
261 comp = rtlpriv->halmac.indicator[id].comp;
262 if (!comp)
263 return -1;
264
265 ret = wait_for_completion_timeout(
266 comp, rtlpriv->halmac.indicator[id].wait_ms);
267 free_halmac_event(rtlpriv, id);
268 if (ret > 0)
269 return 0;
270
271 return -1;
272 }
273
274 /*
275 * Return:
276 * Always return true, HALMAC don't care the return value.
277 */
278 static bool
_halmac_event_indication(void * p,enum halmac_feature_id feature_id,enum halmac_cmd_process_status process_status,u8 * buf,u32 size)279 _halmac_event_indication(void *p, enum halmac_feature_id feature_id,
280 enum halmac_cmd_process_status process_status, u8 *buf,
281 u32 size)
282 {
283 struct rtl_priv *rtlpriv;
284 struct rtl_halmac_indicator *tbl, *indicator;
285 struct completion *comp;
286 u32 cpsz;
287 bool ret;
288
289 rtlpriv = (struct rtl_priv *)p;
290 tbl = rtlpriv->halmac.indicator;
291
292 ret = is_valid_id_status(rtlpriv, feature_id, process_status);
293 if (!ret)
294 goto exit;
295
296 indicator = &tbl[feature_id];
297 indicator->status = process_status;
298 indicator->ret_size = size;
299 if (!indicator->comp) {
300 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
301 "%s: No feature id(%d) waiting!!\n", __func__,
302 feature_id);
303 goto exit;
304 }
305 comp = indicator->comp;
306
307 if (process_status == HALMAC_CMD_PROCESS_ERROR) {
308 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
309 "%s: Something wrong id(%d)!!\n", __func__,
310 feature_id);
311 complete(comp); /* may provide error code */
312 goto exit;
313 }
314
315 if (size > indicator->buf_size) {
316 RT_TRACE(
317 rtlpriv, COMP_HALMAC, DBG_LOUD,
318 "%s: <WARN> id(%d) buffer is not enough(%d<%d), data will be truncated!\n",
319 __func__, feature_id, indicator->buf_size, size);
320 cpsz = indicator->buf_size;
321 } else {
322 cpsz = size;
323 }
324
325 if (cpsz && indicator->buffer)
326 memcpy(indicator->buffer, buf, cpsz);
327
328 complete(comp);
329
330 exit:
331 return true;
332 }
333
334 static struct halmac_platform_api rtl_halmac_platform_api = {
335 /* R/W register */
336 .REG_READ_8 = _halmac_reg_read_8,
337 .REG_READ_16 = _halmac_reg_read_16,
338 .REG_READ_32 = _halmac_reg_read_32,
339 .REG_WRITE_8 = _halmac_reg_write_8,
340 .REG_WRITE_16 = _halmac_reg_write_16,
341 .REG_WRITE_32 = _halmac_reg_write_32,
342
343 /* Write data */
344 /* impletement in HAL-IC level */
345 .SEND_RSVD_PAGE = _halmac_write_data_rsvd_page,
346 .SEND_H2C_PKT = _halmac_write_data_h2c,
347
348 .EVENT_INDICATION = _halmac_event_indication,
349 };
350
init_priv(struct rtl_halmac * halmac)351 static int init_priv(struct rtl_halmac *halmac)
352 {
353 struct rtl_halmac_indicator *indicator;
354 u32 count, size;
355
356 halmac->send_general_info = 0;
357
358 count = HALMAC_FEATURE_ALL + 1;
359 size = sizeof(*indicator) * count;
360 indicator = kzalloc(size, GFP_KERNEL);
361 if (!indicator)
362 return -1;
363 halmac->indicator = indicator;
364
365 return 0;
366 }
367
deinit_priv(struct rtl_halmac * halmac)368 static void deinit_priv(struct rtl_halmac *halmac)
369 {
370 struct rtl_halmac_indicator *indicator;
371
372 indicator = halmac->indicator;
373 halmac->indicator = NULL;
374 kfree(indicator);
375 }
376
rtl_halmac_init_adapter(struct rtl_priv * rtlpriv)377 int rtl_halmac_init_adapter(struct rtl_priv *rtlpriv)
378 {
379 struct halmac_adapter *halmac;
380 struct halmac_api *api;
381 enum halmac_interface intf;
382 enum halmac_ret_status status;
383 int err = 0;
384 struct halmac_platform_api *pf_api = &rtl_halmac_platform_api;
385
386 halmac = rtlpriv_to_halmac(rtlpriv);
387 if (halmac) {
388 err = 0;
389 goto out;
390 }
391
392 err = init_priv(&rtlpriv->halmac);
393 if (err)
394 goto out;
395
396 intf = HALMAC_INTERFACE_PCIE;
397 status = halmac_init_adapter(rtlpriv, pf_api, intf, &halmac, &api);
398 if (status != HALMAC_RET_SUCCESS) {
399 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
400 "%s: halmac_init_adapter fail!(status=%d)\n", __func__,
401 status);
402 err = -1;
403 goto out;
404 }
405
406 rtlpriv->halmac.internal = halmac;
407
408 out:
409 if (err)
410 rtl_halmac_deinit_adapter(rtlpriv);
411
412 return err;
413 }
414
rtl_halmac_deinit_adapter(struct rtl_priv * rtlpriv)415 int rtl_halmac_deinit_adapter(struct rtl_priv *rtlpriv)
416 {
417 struct halmac_adapter *halmac;
418 enum halmac_ret_status status;
419 int err = 0;
420
421 halmac = rtlpriv_to_halmac(rtlpriv);
422 if (!halmac) {
423 err = 0;
424 goto out;
425 }
426
427 deinit_priv(&rtlpriv->halmac);
428
429 halmac_halt_api(halmac);
430
431 status = halmac_deinit_adapter(halmac);
432 rtlpriv->halmac.internal = NULL;
433 if (status != HALMAC_RET_SUCCESS) {
434 err = -1;
435 goto out;
436 }
437
438 out:
439 return err;
440 }
441
rtl_halmac_poweron(struct rtl_priv * rtlpriv)442 int rtl_halmac_poweron(struct rtl_priv *rtlpriv)
443 {
444 struct halmac_adapter *halmac;
445 struct halmac_api *api;
446 enum halmac_ret_status status;
447 int err = -1;
448
449 halmac = rtlpriv_to_halmac(rtlpriv);
450 if (!halmac)
451 goto out;
452
453 api = HALMAC_GET_API(halmac);
454
455 status = api->halmac_pre_init_system_cfg(halmac);
456 if (status != HALMAC_RET_SUCCESS)
457 goto out;
458
459 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
460 if (status != HALMAC_RET_SUCCESS)
461 goto out;
462
463 status = api->halmac_init_system_cfg(halmac);
464 if (status != HALMAC_RET_SUCCESS)
465 goto out;
466
467 err = 0;
468 out:
469 return err;
470 }
471
rtl_halmac_poweroff(struct rtl_priv * rtlpriv)472 int rtl_halmac_poweroff(struct rtl_priv *rtlpriv)
473 {
474 struct halmac_adapter *halmac;
475 struct halmac_api *api;
476 enum halmac_ret_status status;
477 int err = -1;
478
479 halmac = rtlpriv_to_halmac(rtlpriv);
480 if (!halmac)
481 goto out;
482
483 api = HALMAC_GET_API(halmac);
484
485 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
486 if (status != HALMAC_RET_SUCCESS)
487 goto out;
488
489 err = 0;
490 out:
491 return err;
492 }
493
494 /*
495 * Note:
496 * When this function return, the register REG_RCR may be changed.
497 */
rtl_halmac_config_rx_info(struct rtl_priv * rtlpriv,enum halmac_drv_info info)498 int rtl_halmac_config_rx_info(struct rtl_priv *rtlpriv,
499 enum halmac_drv_info info)
500 {
501 struct halmac_adapter *halmac;
502 struct halmac_api *api;
503 enum halmac_ret_status status;
504 int err = -1;
505
506 halmac = rtlpriv_to_halmac(rtlpriv);
507 api = HALMAC_GET_API(halmac);
508
509 status = api->halmac_cfg_drv_info(halmac, info);
510 if (status != HALMAC_RET_SUCCESS)
511 goto out;
512
513 err = 0;
514 out:
515 return err;
516 }
517
init_mac_flow(struct rtl_priv * rtlpriv)518 static enum halmac_ret_status init_mac_flow(struct rtl_priv *rtlpriv)
519 {
520 struct halmac_adapter *halmac;
521 struct halmac_api *api;
522 enum halmac_ret_status status;
523 u8 wifi_test = 0;
524 int err;
525
526 halmac = rtlpriv_to_halmac(rtlpriv);
527 api = HALMAC_GET_API(halmac);
528
529 if (wifi_test)
530 status = api->halmac_init_mac_cfg(halmac, HALMAC_TRX_MODE_WMM);
531 else
532 status = api->halmac_init_mac_cfg(halmac,
533 HALMAC_TRX_MODE_NORMAL);
534 if (status != HALMAC_RET_SUCCESS)
535 goto out;
536
537 err = rtl_halmac_rx_agg_switch(rtlpriv, true);
538 if (err)
539 goto out;
540
541 if (rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7])
542 status = api->halmac_cfg_operation_mode(
543 halmac, HALMAC_WIRELESS_MODE_AC);
544 else if (rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7])
545 status = api->halmac_cfg_operation_mode(halmac,
546 HALMAC_WIRELESS_MODE_N);
547 else if (rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M])
548 status = api->halmac_cfg_operation_mode(halmac,
549 HALMAC_WIRELESS_MODE_G);
550 else
551 status = api->halmac_cfg_operation_mode(halmac,
552 HALMAC_WIRELESS_MODE_B);
553 if (status != HALMAC_RET_SUCCESS)
554 goto out;
555
556 out:
557 return status;
558 }
559
_rf_type_drv2halmac(enum rf_type rf_drv)560 static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
561 {
562 enum halmac_rf_type rf_mac;
563
564 switch (rf_drv) {
565 case RF_1T2R:
566 rf_mac = HALMAC_RF_1T2R;
567 break;
568 case RF_2T2R:
569 rf_mac = HALMAC_RF_2T2R;
570 break;
571 case RF_1T1R:
572 rf_mac = HALMAC_RF_1T1R;
573 break;
574 case RF_2T2R_GREEN:
575 rf_mac = HALMAC_RF_2T2R_GREEN;
576 break;
577 default:
578 rf_mac = (enum halmac_rf_type)rf_drv;
579 break;
580 }
581
582 return rf_mac;
583 }
584
_send_general_info(struct rtl_priv * rtlpriv)585 static int _send_general_info(struct rtl_priv *rtlpriv)
586 {
587 struct halmac_adapter *halmac;
588 struct halmac_api *api;
589 struct halmac_general_info info;
590 enum halmac_ret_status status;
591
592 halmac = rtlpriv_to_halmac(rtlpriv);
593 if (!halmac)
594 return -1;
595 api = HALMAC_GET_API(halmac);
596
597 memset(&info, 0, sizeof(info));
598 info.rfe_type = rtlpriv->rtlhal.rfe_type;
599 info.rf_type = _rf_type_drv2halmac(rtlpriv->phy.rf_type);
600
601 status = api->halmac_send_general_info(halmac, &info);
602 switch (status) {
603 case HALMAC_RET_SUCCESS:
604 break;
605 case HALMAC_RET_NO_DLFW:
606 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_WARNING,
607 "%s: halmac_send_general_info() fail because fw not dl!\n",
608 __func__);
609 /* fall through */
610 default:
611 return -1;
612 }
613
614 return 0;
615 }
616
617 /*
618 * Notices:
619 * Make sure
620 * 1. rtl_hal_get_hwreg(HW_VAR_RF_TYPE)
621 * 2. HAL_DATA_TYPE.rfe_type
622 * already ready for use before calling this function.
623 */
_halmac_init_hal(struct rtl_priv * rtlpriv,u8 * fw,u32 fwsize)624 static int _halmac_init_hal(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize)
625 {
626 struct halmac_adapter *halmac;
627 struct halmac_api *api;
628 enum halmac_ret_status status;
629 bool ok;
630 bool fw_ok = false;
631 int err, err_ret = -1;
632
633 halmac = rtlpriv_to_halmac(rtlpriv);
634 if (!halmac)
635 goto out;
636 api = HALMAC_GET_API(halmac);
637
638 /* StatePowerOff */
639
640 /* SKIP: halmac_init_adapter (Already done before) */
641
642 /* halmac_pre_Init_system_cfg */
643 /* halmac_mac_power_switch(on) */
644 /* halmac_Init_system_cfg */
645 err = rtl_halmac_poweron(rtlpriv);
646 if (err)
647 goto out;
648
649 /* StatePowerOn */
650
651 /* DownloadFW */
652 rtlpriv->halmac.send_general_info = 0;
653 if (fw && fwsize) {
654 err = rtl_halmac_dlfw(rtlpriv, fw, fwsize);
655 if (err)
656 goto out;
657 fw_ok = true;
658 }
659
660 /* InitMACFlow */
661 status = init_mac_flow(rtlpriv);
662 if (status != HALMAC_RET_SUCCESS)
663 goto out;
664
665 /* halmac_send_general_info */
666 if (fw_ok) {
667 rtlpriv->halmac.send_general_info = 0;
668 err = _send_general_info(rtlpriv);
669 if (err)
670 goto out;
671 } else {
672 rtlpriv->halmac.send_general_info = 1;
673 }
674
675 /* Init Phy parameter-MAC */
676 if (rtlpriv->cfg->ops->halmac_cb_init_mac_register)
677 ok = rtlpriv->cfg->ops->halmac_cb_init_mac_register(rtlpriv);
678 else
679 ok = false;
680
681 if (!ok)
682 goto out;
683
684 /* StateMacInitialized */
685
686 /* halmac_cfg_drv_info */
687 err = rtl_halmac_config_rx_info(rtlpriv, HALMAC_DRV_INFO_PHY_STATUS);
688 if (err)
689 goto out;
690
691 /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
692 /* Init BB, RF */
693 if (rtlpriv->cfg->ops->halmac_cb_init_bb_rf_register)
694 ok = rtlpriv->cfg->ops->halmac_cb_init_bb_rf_register(rtlpriv);
695 else
696 ok = false;
697
698 if (!ok)
699 goto out;
700
701 status = api->halmac_init_interface_cfg(halmac);
702 if (status != HALMAC_RET_SUCCESS)
703 goto out;
704
705 /* SKIP: halmac_verify_platform_api */
706 /* SKIP: halmac_h2c_lb */
707
708 /* StateRxIdle */
709
710 err_ret = 0;
711 out:
712 return err_ret;
713 }
714
rtl_halmac_init_hal(struct rtl_priv * rtlpriv)715 int rtl_halmac_init_hal(struct rtl_priv *rtlpriv)
716 {
717 if (!rtlpriv->rtlhal.pfirmware || rtlpriv->rtlhal.fwsize == 0)
718 return -1;
719
720 return _halmac_init_hal(rtlpriv, rtlpriv->rtlhal.pfirmware,
721 rtlpriv->rtlhal.fwsize);
722 }
723
rtl_halmac_deinit_hal(struct rtl_priv * rtlpriv)724 int rtl_halmac_deinit_hal(struct rtl_priv *rtlpriv)
725 {
726 struct halmac_adapter *halmac;
727 struct halmac_api *api;
728 enum halmac_ret_status status;
729 int err = -1;
730
731 halmac = rtlpriv_to_halmac(rtlpriv);
732 if (!halmac)
733 goto out;
734 api = HALMAC_GET_API(halmac);
735
736 status = api->halmac_deinit_interface_cfg(halmac);
737 if (status != HALMAC_RET_SUCCESS)
738 goto out;
739
740 /* rtw_hal_power_off(adapter); */
741 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
742 if (status != HALMAC_RET_SUCCESS)
743 goto out;
744
745 err = 0;
746 out:
747 return err;
748 }
749
rtl_halmac_self_verify(struct rtl_priv * rtlpriv)750 int rtl_halmac_self_verify(struct rtl_priv *rtlpriv)
751 {
752 struct halmac_adapter *mac;
753 struct halmac_api *api;
754 enum halmac_ret_status status;
755 int err = -1;
756
757 mac = rtlpriv_to_halmac(rtlpriv);
758 api = HALMAC_GET_API(mac);
759
760 status = api->halmac_verify_platform_api(mac);
761 if (status != HALMAC_RET_SUCCESS)
762 goto out;
763
764 status = api->halmac_h2c_lb(mac);
765 if (status != HALMAC_RET_SUCCESS)
766 goto out;
767
768 err = 0;
769 out:
770 return err;
771 }
772
rtl_halmac_dlfw(struct rtl_priv * rtlpriv,u8 * fw,u32 fwsize)773 int rtl_halmac_dlfw(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize)
774 {
775 struct halmac_adapter *mac;
776 struct halmac_api *api;
777 enum halmac_ret_status status;
778 struct halmac_fw_version fw_version;
779 int err = 0;
780
781 mac = rtlpriv_to_halmac(rtlpriv);
782 api = HALMAC_GET_API(mac);
783
784 if ((!fw) || (!fwsize))
785 return -1;
786
787 /* 1. Driver Stop Tx */
788 /* ToDo */
789
790 /* 2. Driver Check Tx FIFO is empty */
791 /* ToDo */
792
793 /* 3. Config MAX download size */
794 api->halmac_cfg_max_dl_size(mac, 0x1000);
795
796 /* 4. Download Firmware */
797 mac->h2c_packet_seq = 0;
798 status = api->halmac_download_firmware(mac, fw, fwsize);
799 if (status != HALMAC_RET_SUCCESS)
800 return -1;
801
802 status = api->halmac_get_fw_version(mac, &fw_version);
803 if (status == HALMAC_RET_SUCCESS) {
804 rtlpriv->rtlhal.fw_version = fw_version.version;
805 rtlpriv->rtlhal.fw_subversion =
806 (fw_version.sub_version << 8) | (fw_version.sub_index);
807
808 RT_TRACE(
809 rtlpriv, COMP_HALMAC, DBG_DMESG,
810 "halmac report firmware version %04X.%04X\n",
811 rtlpriv->rtlhal.fw_version,
812 rtlpriv->rtlhal.fw_subversion);
813 }
814
815 if (rtlpriv->halmac.send_general_info) {
816 rtlpriv->halmac.send_general_info = 0;
817 err = _send_general_info(rtlpriv);
818 }
819
820 /* 5. Driver resume TX if needed */
821 /* ToDo */
822
823 /* 6. Reset driver variables if needed */
824 /*hal->LastHMEBoxNum = 0;*/
825
826 return err;
827 }
828
829 /*
830 * Description:
831 * Power on/off BB/RF domain.
832 *
833 * Parameters:
834 * enable true/false for power on/off
835 *
836 * Return:
837 * 0 Success
838 * others Fail
839 */
rtl_halmac_phy_power_switch(struct rtl_priv * rtlpriv,u8 enable)840 int rtl_halmac_phy_power_switch(struct rtl_priv *rtlpriv, u8 enable)
841 {
842 struct halmac_adapter *halmac;
843 struct halmac_api *api;
844 enum halmac_ret_status status;
845
846 halmac = rtlpriv_to_halmac(rtlpriv);
847 if (!halmac)
848 return -1;
849 api = HALMAC_GET_API(halmac);
850
851 status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &enable);
852 if (status != HALMAC_RET_SUCCESS)
853 return -1;
854
855 return 0;
856 }
857
_is_fw_read_cmd_down(struct rtl_priv * rtlpriv,u8 msgbox_num)858 static bool _is_fw_read_cmd_down(struct rtl_priv *rtlpriv, u8 msgbox_num)
859 {
860 bool read_down = false;
861 int retry_cnts = 100;
862 u8 valid;
863
864 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
865 "%s, reg_1cc(%x), msg_box(%d)...\n", __func__,
866 rtl_read_byte(rtlpriv, REG_HMETFR), msgbox_num);
867
868 do {
869 valid = rtl_read_byte(rtlpriv, REG_HMETFR) & BIT(msgbox_num);
870 if (valid == 0)
871 read_down = true;
872 else
873 mdelay(1);
874 } while ((!read_down) && (retry_cnts--));
875
876 return read_down;
877 }
878
rtl_halmac_send_h2c(struct rtl_priv * rtlpriv,u8 * h2c)879 int rtl_halmac_send_h2c(struct rtl_priv *rtlpriv, u8 *h2c)
880 {
881 u8 h2c_box_num = 0;
882 u32 msgbox_addr = 0;
883 u32 msgbox_ex_addr = 0;
884 __le32 h2c_cmd = 0;
885 __le32 h2c_cmd_ex = 0;
886 s32 ret = -1;
887 unsigned long flag = 0;
888 struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
889
890 if (!h2c) {
891 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: pbuf is NULL\n",
892 __func__);
893 return ret;
894 }
895
896 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
897
898 /* pay attention to if race condition happened in H2C cmd setting */
899 h2c_box_num = rtlhal->last_hmeboxnum;
900
901 if (!_is_fw_read_cmd_down(rtlpriv, h2c_box_num)) {
902 RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
903 " fw read cmd failed...\n");
904 goto exit;
905 }
906
907 /* Write Ext command(byte 4 -7) */
908 msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
909 memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
910 rtl_write_dword(rtlpriv, msgbox_ex_addr, le32_to_cpu(h2c_cmd_ex));
911
912 /* Write command (byte 0 -3 ) */
913 msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
914 memcpy((u8 *)(&h2c_cmd), h2c, 4);
915 rtl_write_dword(rtlpriv, msgbox_addr, le32_to_cpu(h2c_cmd));
916
917 /* update last msg box number */
918 rtlhal->last_hmeboxnum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
919 ret = 0;
920
921 exit:
922 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
923 return ret;
924 }
925
rtl_halmac_c2h_handle(struct rtl_priv * rtlpriv,u8 * c2h,u32 size)926 int rtl_halmac_c2h_handle(struct rtl_priv *rtlpriv, u8 *c2h, u32 size)
927 {
928 struct halmac_adapter *mac;
929 struct halmac_api *api;
930 enum halmac_ret_status status;
931
932 mac = rtlpriv_to_halmac(rtlpriv);
933 api = HALMAC_GET_API(mac);
934
935 status = api->halmac_get_c2h_info(mac, c2h, size);
936 if (status != HALMAC_RET_SUCCESS)
937 return -1;
938
939 return 0;
940 }
941
rtl_halmac_get_physical_efuse_size(struct rtl_priv * rtlpriv,u32 * size)942 int rtl_halmac_get_physical_efuse_size(struct rtl_priv *rtlpriv, u32 *size)
943 {
944 struct halmac_adapter *mac;
945 struct halmac_api *api;
946 enum halmac_ret_status status;
947 u32 val;
948
949 mac = rtlpriv_to_halmac(rtlpriv);
950 api = HALMAC_GET_API(mac);
951
952 status = api->halmac_get_efuse_size(mac, &val);
953 if (status != HALMAC_RET_SUCCESS)
954 return -1;
955
956 *size = val;
957 return 0;
958 }
959
rtl_halmac_read_physical_efuse_map(struct rtl_priv * rtlpriv,u8 * map,u32 size)960 int rtl_halmac_read_physical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
961 u32 size)
962 {
963 struct halmac_adapter *mac;
964 struct halmac_api *api;
965 enum halmac_ret_status status;
966 enum halmac_feature_id id;
967 int ret;
968
969 mac = rtlpriv_to_halmac(rtlpriv);
970 api = HALMAC_GET_API(mac);
971 id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
972
973 ret = init_halmac_event(rtlpriv, id, map, size);
974 if (ret)
975 return -1;
976
977 status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
978 if (status != HALMAC_RET_SUCCESS) {
979 free_halmac_event(rtlpriv, id);
980 return -1;
981 }
982
983 ret = wait_halmac_event(rtlpriv, id);
984 if (ret)
985 return -1;
986
987 return 0;
988 }
989
rtl_halmac_read_physical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)990 int rtl_halmac_read_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
991 u32 cnt, u8 *data)
992 {
993 struct halmac_adapter *mac;
994 struct halmac_api *api;
995 enum halmac_ret_status status;
996 u8 v;
997 u32 i;
998
999 mac = rtlpriv_to_halmac(rtlpriv);
1000 api = HALMAC_GET_API(mac);
1001
1002 for (i = 0; i < cnt; i++) {
1003 status = api->halmac_read_efuse(mac, offset + i, &v);
1004 if (status != HALMAC_RET_SUCCESS)
1005 return -1;
1006 data[i] = v;
1007 }
1008
1009 return 0;
1010 }
1011
rtl_halmac_write_physical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)1012 int rtl_halmac_write_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
1013 u32 cnt, u8 *data)
1014 {
1015 struct halmac_adapter *mac;
1016 struct halmac_api *api;
1017 enum halmac_ret_status status;
1018 u32 i;
1019
1020 mac = rtlpriv_to_halmac(rtlpriv);
1021 api = HALMAC_GET_API(mac);
1022
1023 for (i = 0; i < cnt; i++) {
1024 status = api->halmac_write_efuse(mac, offset + i, data[i]);
1025 if (status != HALMAC_RET_SUCCESS)
1026 return -1;
1027 }
1028
1029 return 0;
1030 }
1031
rtl_halmac_get_logical_efuse_size(struct rtl_priv * rtlpriv,u32 * size)1032 int rtl_halmac_get_logical_efuse_size(struct rtl_priv *rtlpriv, u32 *size)
1033 {
1034 struct halmac_adapter *mac;
1035 struct halmac_api *api;
1036 enum halmac_ret_status status;
1037 u32 val;
1038
1039 mac = rtlpriv_to_halmac(rtlpriv);
1040 api = HALMAC_GET_API(mac);
1041
1042 status = api->halmac_get_logical_efuse_size(mac, &val);
1043 if (status != HALMAC_RET_SUCCESS)
1044 return -1;
1045
1046 *size = val;
1047 return 0;
1048 }
1049
rtl_halmac_read_logical_efuse_map(struct rtl_priv * rtlpriv,u8 * map,u32 size)1050 int rtl_halmac_read_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
1051 u32 size)
1052 {
1053 struct halmac_adapter *mac;
1054 struct halmac_api *api;
1055 enum halmac_ret_status status;
1056 enum halmac_feature_id id;
1057 int ret;
1058
1059 mac = rtlpriv_to_halmac(rtlpriv);
1060 api = HALMAC_GET_API(mac);
1061 id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
1062
1063 ret = init_halmac_event(rtlpriv, id, map, size);
1064 if (ret)
1065 return -1;
1066
1067 status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_AUTO);
1068 if (status != HALMAC_RET_SUCCESS) {
1069 free_halmac_event(rtlpriv, id);
1070 return -1;
1071 }
1072
1073 ret = wait_halmac_event(rtlpriv, id);
1074 if (ret)
1075 return -1;
1076
1077 return 0;
1078 }
1079
rtl_halmac_write_logical_efuse_map(struct rtl_priv * rtlpriv,u8 * map,u32 size,u8 * maskmap,u32 masksize)1080 int rtl_halmac_write_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
1081 u32 size, u8 *maskmap, u32 masksize)
1082 {
1083 struct halmac_adapter *mac;
1084 struct halmac_api *api;
1085 struct halmac_pg_efuse_info pginfo;
1086 enum halmac_ret_status status;
1087
1088 mac = rtlpriv_to_halmac(rtlpriv);
1089 api = HALMAC_GET_API(mac);
1090
1091 pginfo.efuse_map = map;
1092 pginfo.efuse_map_size = size;
1093 pginfo.efuse_mask = maskmap;
1094 pginfo.efuse_mask_size = masksize;
1095
1096 status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
1097 if (status != HALMAC_RET_SUCCESS)
1098 return -1;
1099
1100 return 0;
1101 }
1102
rtl_halmac_read_logical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)1103 int rtl_halmac_read_logical_efuse(struct rtl_priv *rtlpriv, u32 offset, u32 cnt,
1104 u8 *data)
1105 {
1106 struct halmac_adapter *mac;
1107 struct halmac_api *api;
1108 enum halmac_ret_status status;
1109 u8 v;
1110 u32 i;
1111
1112 mac = rtlpriv_to_halmac(rtlpriv);
1113 api = HALMAC_GET_API(mac);
1114
1115 for (i = 0; i < cnt; i++) {
1116 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
1117 if (status != HALMAC_RET_SUCCESS)
1118 return -1;
1119 data[i] = v;
1120 }
1121
1122 return 0;
1123 }
1124
rtl_halmac_write_logical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)1125 int rtl_halmac_write_logical_efuse(struct rtl_priv *rtlpriv, u32 offset,
1126 u32 cnt, u8 *data)
1127 {
1128 struct halmac_adapter *mac;
1129 struct halmac_api *api;
1130 enum halmac_ret_status status;
1131 u32 i;
1132
1133 mac = rtlpriv_to_halmac(rtlpriv);
1134 api = HALMAC_GET_API(mac);
1135
1136 for (i = 0; i < cnt; i++) {
1137 status = api->halmac_write_logical_efuse(mac, offset + i,
1138 data[i]);
1139 if (status != HALMAC_RET_SUCCESS)
1140 return -1;
1141 }
1142
1143 return 0;
1144 }
1145
rtl_halmac_set_mac_address(struct rtl_priv * rtlpriv,u8 hwport,u8 * addr)1146 int rtl_halmac_set_mac_address(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr)
1147 {
1148 struct halmac_adapter *halmac;
1149 struct halmac_api *api;
1150 u8 port;
1151 union halmac_wlan_addr hwa;
1152 enum halmac_ret_status status;
1153 int err = -1;
1154
1155 halmac = rtlpriv_to_halmac(rtlpriv);
1156 api = HALMAC_GET_API(halmac);
1157
1158 port = hwport;
1159 memset(&hwa, 0, sizeof(hwa));
1160 memcpy(hwa.address, addr, 6);
1161
1162 status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
1163 if (status != HALMAC_RET_SUCCESS)
1164 goto out;
1165
1166 err = 0;
1167 out:
1168 return err;
1169 }
1170
rtl_halmac_set_bssid(struct rtl_priv * rtlpriv,u8 hwport,u8 * addr)1171 int rtl_halmac_set_bssid(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr)
1172 {
1173 struct halmac_adapter *halmac;
1174 struct halmac_api *api;
1175 u8 port;
1176 union halmac_wlan_addr hwa;
1177 enum halmac_ret_status status;
1178 int err = -1;
1179
1180 halmac = rtlpriv_to_halmac(rtlpriv);
1181 api = HALMAC_GET_API(halmac);
1182 port = hwport;
1183
1184 memset(&hwa, 0, sizeof(union halmac_wlan_addr));
1185 memcpy(hwa.address, addr, 6);
1186 status = api->halmac_cfg_bssid(halmac, port, &hwa);
1187 if (status != HALMAC_RET_SUCCESS)
1188 goto out;
1189
1190 err = 0;
1191 out:
1192 return err;
1193 }
1194
rtl_halmac_set_bandwidth(struct rtl_priv * rtlpriv,u8 channel,u8 pri_ch_idx,u8 bw)1195 int rtl_halmac_set_bandwidth(struct rtl_priv *rtlpriv, u8 channel,
1196 u8 pri_ch_idx, u8 bw)
1197 {
1198 struct halmac_adapter *mac;
1199 struct halmac_api *api;
1200 enum halmac_ret_status status;
1201
1202 mac = rtlpriv_to_halmac(rtlpriv);
1203 api = HALMAC_GET_API(mac);
1204
1205 status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
1206 if (status != HALMAC_RET_SUCCESS)
1207 return -1;
1208
1209 return 0;
1210 }
1211
rtl_halmac_get_hw_value(struct rtl_priv * rtlpriv,enum halmac_hw_id hw_id,void * pvalue)1212 int rtl_halmac_get_hw_value(struct rtl_priv *rtlpriv, enum halmac_hw_id hw_id,
1213 void *pvalue)
1214 {
1215 struct halmac_adapter *mac;
1216 struct halmac_api *api;
1217 enum halmac_ret_status status;
1218
1219 mac = rtlpriv_to_halmac(rtlpriv);
1220 api = HALMAC_GET_API(mac);
1221
1222 status = api->halmac_get_hw_value(mac, hw_id, pvalue);
1223 if (status != HALMAC_RET_SUCCESS)
1224 return -1;
1225
1226 return 0;
1227 }
1228
rtl_halmac_dump_fifo(struct rtl_priv * rtlpriv,enum hal_fifo_sel halmac_fifo_sel)1229 int rtl_halmac_dump_fifo(struct rtl_priv *rtlpriv,
1230 enum hal_fifo_sel halmac_fifo_sel)
1231 {
1232 struct halmac_adapter *mac;
1233 struct halmac_api *api;
1234 enum halmac_ret_status status;
1235 u8 *pfifo_map = NULL;
1236 u32 fifo_size = 0;
1237 s8 ret = 0;
1238
1239 mac = rtlpriv_to_halmac(rtlpriv);
1240 api = HALMAC_GET_API(mac);
1241
1242 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
1243 if (fifo_size)
1244 pfifo_map = vmalloc(fifo_size);
1245 if (!pfifo_map)
1246 return -1;
1247
1248 status = api->halmac_dump_fifo(mac, halmac_fifo_sel, 0, fifo_size,
1249 pfifo_map);
1250
1251 if (status != HALMAC_RET_SUCCESS) {
1252 ret = -1;
1253 goto _exit;
1254 }
1255
1256 _exit:
1257 if (pfifo_map)
1258 vfree(pfifo_map);
1259 return ret;
1260 }
1261
rtl_halmac_rx_agg_switch(struct rtl_priv * rtlpriv,bool enable)1262 int rtl_halmac_rx_agg_switch(struct rtl_priv *rtlpriv, bool enable)
1263 {
1264 struct halmac_adapter *halmac;
1265 struct halmac_api *api;
1266 struct halmac_rxagg_cfg rxaggcfg;
1267 enum halmac_ret_status status;
1268 int err = -1;
1269
1270 halmac = rtlpriv_to_halmac(rtlpriv);
1271 api = HALMAC_GET_API(halmac);
1272 memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
1273
1274 if (enable) {
1275 /* enable RX agg. */
1276 /* PCIE do nothing */
1277 } else {
1278 /* disable RX agg. */
1279 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
1280 }
1281
1282 status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
1283 if (status != HALMAC_RET_SUCCESS)
1284 goto out;
1285
1286 err = 0;
1287 out:
1288 return err;
1289 }
1290
rtl_halmac_get_wow_reason(struct rtl_priv * rtlpriv,u8 * reason)1291 int rtl_halmac_get_wow_reason(struct rtl_priv *rtlpriv, u8 *reason)
1292 {
1293 u8 val8;
1294 int err = -1;
1295
1296 val8 = rtl_read_byte(rtlpriv, 0x1C7);
1297 if (val8 == 0xEA)
1298 goto out;
1299
1300 *reason = val8;
1301 err = 0;
1302 out:
1303 return err;
1304 }
1305
1306 /*
1307 * Description:
1308 * Get RX driver info size. RX driver info is a small memory space between
1309 * scriptor and RX payload.
1310 *
1311 * +-------------------------+
1312 * | RX descriptor |
1313 * | usually 24 bytes |
1314 * +-------------------------+
1315 * | RX driver info |
1316 * | depends on driver cfg |
1317 * +-------------------------+
1318 * | RX paylad |
1319 * | |
1320 * +-------------------------+
1321 *
1322 * Parameter:
1323 * d pointer to struct dvobj_priv of driver
1324 * sz rx driver info size in bytes.
1325 *
1326 * Rteurn:
1327 * 0 Success
1328 * other Fail
1329 */
rtl_halmac_get_drv_info_sz(struct rtl_priv * rtlpriv,u8 * sz)1330 int rtl_halmac_get_drv_info_sz(struct rtl_priv *rtlpriv, u8 *sz)
1331 {
1332 /* enum halmac_ret_status status; */
1333 u8 dw = 6; /* max number */
1334
1335 *sz = dw * 8;
1336 return 0;
1337 }
1338
rtl_halmac_get_rsvd_drv_pg_bndy(struct rtl_priv * rtlpriv,u16 * drv_pg)1339 int rtl_halmac_get_rsvd_drv_pg_bndy(struct rtl_priv *rtlpriv, u16 *drv_pg)
1340 {
1341 enum halmac_ret_status status;
1342 struct halmac_adapter *halmac = rtlpriv_to_halmac(rtlpriv);
1343 struct halmac_api *api = HALMAC_GET_API(halmac);
1344
1345 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY,
1346 drv_pg);
1347 if (status != HALMAC_RET_SUCCESS)
1348 return -1;
1349
1350 return 0;
1351 }
1352
rtl_halmac_chk_txdesc(struct rtl_priv * rtlpriv,u8 * txdesc,u32 size)1353 int rtl_halmac_chk_txdesc(struct rtl_priv *rtlpriv, u8 *txdesc, u32 size)
1354 {
1355 struct halmac_adapter *mac;
1356 struct halmac_api *api;
1357 enum halmac_ret_status status;
1358
1359 mac = rtlpriv_to_halmac(rtlpriv);
1360 api = HALMAC_GET_API(mac);
1361
1362 status = api->halmac_chk_txdesc(mac, txdesc, size);
1363
1364 if (status != HALMAC_RET_SUCCESS)
1365 return -1;
1366
1367 return 0;
1368 }
1369
1370 MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
1371 MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
1372 MODULE_LICENSE("GPL");
1373 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
1374