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